ccm,ocm: allow URL-based credentials to accept reverse connections

Previously, findReceiverCredential required baseURL == reverseProxyBaseURL,
so only credentials with no URL could accept incoming reverse connections.
Now credentials with a normal URL also accept reverse connections, preferring
the reverse session when active and falling back to the direct URL when not.
This commit is contained in:
世界
2026-03-14 18:06:40 +08:00
parent 2c907bef2c
commit 4d907bc49d
4 changed files with 90 additions and 14 deletions
+36 -5
View File
@@ -47,8 +47,9 @@ type externalCredential struct {
requestAccess sync.Mutex
// Reverse proxy fields
reverse bool
reverseSession *yamux.Session
reverse bool
reverseHttpClient *http.Client
reverseSession *yamux.Session
reverseAccess sync.RWMutex
closed bool
reverseContext context.Context
@@ -194,6 +195,14 @@ func newExternalCredential(ctx context.Context, tag string, options option.CCMEx
} else {
// Normal mode: standard HTTP client for proxying
cred.httpClient = &http.Client{Transport: transport}
cred.reverseHttpClient = &http.Client{
Transport: &http.Transport{
ForceAttemptHTTP2: false,
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
return cred.openReverseConnection(ctx)
},
},
}
}
}
@@ -341,7 +350,14 @@ func (c *externalCredential) getAccessToken() (string, error) {
}
func (c *externalCredential) buildProxyRequest(ctx context.Context, original *http.Request, bodyBytes []byte, _ http.Header) (*http.Request, error) {
proxyURL := c.baseURL + original.URL.RequestURI()
baseURL := c.baseURL
if c.reverseHttpClient != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
baseURL = reverseProxyBaseURL
}
}
proxyURL := baseURL + original.URL.RequestURI()
var body io.Reader
if bodyBytes != nil {
body = bytes.NewReader(bodyBytes)
@@ -489,9 +505,18 @@ func (c *externalCredential) pollUsage(ctx context.Context) {
defer c.pollAccess.Unlock()
defer c.markUsagePollAttempted()
statusURL := c.baseURL + "/ccm/v1/status"
activeBaseURL := c.baseURL
activeTransport := c.httpClient.Transport
if c.reverseHttpClient != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
activeBaseURL = reverseProxyBaseURL
activeTransport = c.reverseHttpClient.Transport
}
}
statusURL := activeBaseURL + "/ccm/v1/status"
httpClient := &http.Client{
Transport: c.httpClient.Transport,
Transport: activeTransport,
Timeout: 5 * time.Second,
}
@@ -602,6 +627,12 @@ func (c *externalCredential) usageTrackerOrNil() *AggregatedUsage {
}
func (c *externalCredential) httpTransport() *http.Client {
if c.reverseHttpClient != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
return c.reverseHttpClient
}
}
return c.httpClient
}
+2 -2
View File
@@ -126,10 +126,10 @@ func (s *Service) handleReverseConnect(ctx context.Context, w http.ResponseWrite
func (s *Service) findReceiverCredential(token string) *externalCredential {
for _, cred := range s.allCredentials {
extCred, ok := cred.(*externalCredential)
if !ok {
if !ok || extCred.connectorURL != nil {
continue
}
if extCred.baseURL == reverseProxyBaseURL && extCred.token == token {
if extCred.token == token {
return extCred
}
}
+50 -5
View File
@@ -49,8 +49,10 @@ type externalCredential struct {
requestAccess sync.Mutex
// Reverse proxy fields
reverse bool
reverseSession *yamux.Session
reverse bool
reverseHttpClient *http.Client
reverseCredDialer N.Dialer
reverseSession *yamux.Session
reverseAccess sync.RWMutex
closed bool
reverseContext context.Context
@@ -213,6 +215,15 @@ func newExternalCredential(ctx context.Context, tag string, options option.OCMEx
// Normal mode: standard HTTP client for proxying
cred.credDialer = credentialDialer
cred.httpClient = &http.Client{Transport: transport}
cred.reverseCredDialer = reverseSessionDialer{credential: cred}
cred.reverseHttpClient = &http.Client{
Transport: &http.Transport{
ForceAttemptHTTP2: false,
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
return cred.openReverseConnection(ctx)
},
},
}
}
}
@@ -363,7 +374,14 @@ func (c *externalCredential) getAccessToken() (string, error) {
}
func (c *externalCredential) buildProxyRequest(ctx context.Context, original *http.Request, bodyBytes []byte, _ http.Header) (*http.Request, error) {
proxyURL := c.baseURL + original.URL.RequestURI()
baseURL := c.baseURL
if c.reverseHttpClient != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
baseURL = reverseProxyBaseURL
}
}
proxyURL := baseURL + original.URL.RequestURI()
var body io.Reader
if bodyBytes != nil {
body = bytes.NewReader(bodyBytes)
@@ -526,9 +544,18 @@ func (c *externalCredential) pollUsage(ctx context.Context) {
defer c.pollAccess.Unlock()
defer c.markUsagePollAttempted()
statusURL := c.baseURL + "/ocm/v1/status"
activeBaseURL := c.baseURL
activeTransport := c.httpClient.Transport
if c.reverseHttpClient != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
activeBaseURL = reverseProxyBaseURL
activeTransport = c.reverseHttpClient.Transport
}
}
statusURL := activeBaseURL + "/ocm/v1/status"
httpClient := &http.Client{
Transport: c.httpClient.Transport,
Transport: activeTransport,
Timeout: 5 * time.Second,
}
@@ -639,10 +666,22 @@ func (c *externalCredential) usageTrackerOrNil() *AggregatedUsage {
}
func (c *externalCredential) httpTransport() *http.Client {
if c.reverseHttpClient != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
return c.reverseHttpClient
}
}
return c.httpClient
}
func (c *externalCredential) ocmDialer() N.Dialer {
if c.reverseCredDialer != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
return c.reverseCredDialer
}
}
return c.credDialer
}
@@ -655,6 +694,12 @@ func (c *externalCredential) ocmGetAccountID() string {
}
func (c *externalCredential) ocmGetBaseURL() string {
if c.reverseHttpClient != nil {
session := c.getReverseSession()
if session != nil && !session.IsClosed() {
return reverseProxyBaseURL
}
}
return c.baseURL
}
+2 -2
View File
@@ -126,10 +126,10 @@ func (s *Service) handleReverseConnect(ctx context.Context, w http.ResponseWrite
func (s *Service) findReceiverCredential(token string) *externalCredential {
for _, cred := range s.allCredentials {
extCred, ok := cred.(*externalCredential)
if !ok {
if !ok || extCred.connectorURL != nil {
continue
}
if extCred.baseURL == reverseProxyBaseURL && extCred.token == token {
if extCred.token == token {
return extCred
}
}