TUN-5616: Never fallback transport if user chooses it on purpose

This commit is contained in:
Nuno Diegues 2022-01-05 17:58:49 +00:00
parent 628545d229
commit c314d58b69
3 changed files with 47 additions and 36 deletions

View File

@ -19,9 +19,7 @@ const (
edgeH2TLSServerName = "h2.cftunnel.com" edgeH2TLSServerName = "h2.cftunnel.com"
// edgeQUICServerName is the server name to establish quic connection with edge. // edgeQUICServerName is the server name to establish quic connection with edge.
edgeQUICServerName = "quic.cftunnel.com" edgeQUICServerName = "quic.cftunnel.com"
// threshold to switch back to h2mux when the user intentionally pick --protocol http2 autoSelectFlag = "auto"
explicitHTTP2FallbackThreshold = -1
autoSelectFlag = "auto"
) )
var ( var (
@ -237,25 +235,23 @@ func selectNamedTunnelProtocols(
threshold int32, threshold int32,
protocol Protocol, protocol Protocol,
) (ProtocolSelector, error) { ) (ProtocolSelector, error) {
if protocolFlag == H2mux.String() { // If the user picks a protocol, then we stick to it no matter what.
return &staticProtocolSelector{ switch protocolFlag {
current: H2mux, case H2mux.String():
}, nil return &staticProtocolSelector{current: H2mux}, nil
case QUIC.String():
return &staticProtocolSelector{current: QUIC}, nil
case HTTP2.String():
return &staticProtocolSelector{current: HTTP2}, nil
} }
if protocolFlag == QUIC.String() { // If the user does not pick (hopefully the majority) then we use the one derived from the TXT DNS record and
return newAutoProtocolSelector(QUIC, []Protocol{QUIC, HTTP2, H2mux}, explicitHTTP2FallbackThreshold, fetchFunc, ttl, log), nil // fallback on failures.
if protocolFlag == autoSelectFlag {
return newAutoProtocolSelector(protocol, []Protocol{QUIC, HTTP2, H2mux}, threshold, fetchFunc, ttl, log), nil
} }
if protocolFlag == HTTP2.String() { return nil, fmt.Errorf("Unknown protocol %s, %s", protocolFlag, AvailableProtocolFlagMessage)
return newAutoProtocolSelector(HTTP2, []Protocol{HTTP2, H2mux}, explicitHTTP2FallbackThreshold, fetchFunc, ttl, log), nil
}
if protocolFlag != autoSelectFlag {
return nil, fmt.Errorf("Unknown protocol %s, %s", protocolFlag, AvailableProtocolFlagMessage)
}
return newAutoProtocolSelector(protocol, []Protocol{QUIC, HTTP2, H2mux}, threshold, fetchFunc, ttl, log), nil
} }
func selectWarpRoutingProtocols( func selectWarpRoutingProtocols(
@ -266,19 +262,21 @@ func selectWarpRoutingProtocols(
threshold int32, threshold int32,
protocol Protocol, protocol Protocol,
) (ProtocolSelector, error) { ) (ProtocolSelector, error) {
if protocolFlag == QUIC.String() { // If the user picks a protocol, then we stick to it no matter what.
return newAutoProtocolSelector(QUICWarp, []Protocol{QUICWarp, HTTP2Warp}, explicitHTTP2FallbackThreshold, fetchFunc, ttl, log), nil switch protocolFlag {
case QUIC.String():
return &staticProtocolSelector{current: QUICWarp}, nil
case HTTP2.String():
return &staticProtocolSelector{current: HTTP2Warp}, nil
} }
if protocolFlag == HTTP2.String() { // If the user does not pick (hopefully the majority) then we use the one derived from the TXT DNS record and
return newAutoProtocolSelector(HTTP2Warp, []Protocol{HTTP2Warp}, explicitHTTP2FallbackThreshold, fetchFunc, ttl, log), nil // fallback on failures.
if protocolFlag == autoSelectFlag {
return newAutoProtocolSelector(protocol, []Protocol{QUICWarp, HTTP2Warp}, threshold, fetchFunc, ttl, log), nil
} }
if protocolFlag != autoSelectFlag { return nil, fmt.Errorf("Unknown protocol %s, %s", protocolFlag, AvailableProtocolFlagMessage)
return nil, fmt.Errorf("Unknown protocol %s, %s", protocolFlag, AvailableProtocolFlagMessage)
}
return newAutoProtocolSelector(protocol, []Protocol{QUICWarp, HTTP2Warp}, threshold, fetchFunc, ttl, log), nil
} }
func switchThreshold(accountTag string) int32 { func switchThreshold(accountTag string) int32 {

View File

@ -72,21 +72,33 @@ func TestNewProtocolSelector(t *testing.T) {
name: "named tunnel over http2", name: "named tunnel over http2",
protocol: "http2", protocol: "http2",
expectedProtocol: HTTP2, expectedProtocol: HTTP2,
hasFallback: true,
expectedFallback: H2mux,
fetchFunc: mockFetcher(false, edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: 0}), fetchFunc: mockFetcher(false, edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: 0}),
namedTunnelConfig: testNamedTunnelConfig, namedTunnelConfig: testNamedTunnelConfig,
}, },
{ {
name: "named tunnel http2 disabled", name: "named tunnel http2 disabled still gets http2 because it is manually picked",
protocol: "http2", protocol: "http2",
expectedProtocol: H2mux, expectedProtocol: HTTP2,
fetchFunc: mockFetcher(false, edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: -1}), fetchFunc: mockFetcher(false, edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: -1}),
namedTunnelConfig: testNamedTunnelConfig, namedTunnelConfig: testNamedTunnelConfig,
}, },
{
name: "named tunnel quic disabled still gets quic because it is manually picked",
protocol: "quic",
expectedProtocol: QUIC,
fetchFunc: mockFetcher(false, edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: 100}, edgediscovery.ProtocolPercent{Protocol: "quic", Percentage: -1}),
namedTunnelConfig: testNamedTunnelConfig,
},
{
name: "named tunnel quic and http2 disabled",
protocol: "auto",
expectedProtocol: H2mux,
fetchFunc: mockFetcher(false, edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: -1}, edgediscovery.ProtocolPercent{Protocol: "quic", Percentage: -1}),
namedTunnelConfig: testNamedTunnelConfig,
},
{ {
name: "named tunnel quic disabled", name: "named tunnel quic disabled",
protocol: "quic", protocol: "auto",
expectedProtocol: HTTP2, expectedProtocol: HTTP2,
// Hasfallback true is because if http2 fails, then we further fallback to h2mux. // Hasfallback true is because if http2 fails, then we further fallback to h2mux.
hasFallback: true, hasFallback: true,
@ -155,7 +167,7 @@ func TestNewProtocolSelector(t *testing.T) {
}, },
{ {
name: "warp routing quic", name: "warp routing quic",
protocol: "quic", protocol: "auto",
expectedProtocol: QUICWarp, expectedProtocol: QUICWarp,
hasFallback: true, hasFallback: true,
expectedFallback: HTTP2Warp, expectedFallback: HTTP2Warp,
@ -254,6 +266,7 @@ func TestAutoProtocolSelectorRefresh(t *testing.T) {
func TestHTTP2ProtocolSelectorRefresh(t *testing.T) { func TestHTTP2ProtocolSelectorRefresh(t *testing.T) {
fetcher := dynamicMockFetcher{} fetcher := dynamicMockFetcher{}
// Since the user chooses http2 on purpose, we always stick to it.
selector, err := NewProtocolSelector("http2", noWarpRoutingEnabled, testNamedTunnelConfig, fetcher.fetch(), testNoTTL, &log) selector, err := NewProtocolSelector("http2", noWarpRoutingEnabled, testNamedTunnelConfig, fetcher.fetch(), testNoTTL, &log)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, HTTP2, selector.Current()) assert.Equal(t, HTTP2, selector.Current())
@ -269,7 +282,7 @@ func TestHTTP2ProtocolSelectorRefresh(t *testing.T) {
fetcher.protocolPercents = edgediscovery.ProtocolPercents{edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: -1}} fetcher.protocolPercents = edgediscovery.ProtocolPercents{edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: -1}}
fetcher.err = nil fetcher.err = nil
assert.Equal(t, H2mux, selector.Current()) assert.Equal(t, HTTP2, selector.Current())
fetcher.protocolPercents = edgediscovery.ProtocolPercents{edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: 0}} fetcher.protocolPercents = edgediscovery.ProtocolPercents{edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: 0}}
assert.Equal(t, HTTP2, selector.Current()) assert.Equal(t, HTTP2, selector.Current())
@ -278,7 +291,7 @@ func TestHTTP2ProtocolSelectorRefresh(t *testing.T) {
assert.Equal(t, HTTP2, selector.Current()) assert.Equal(t, HTTP2, selector.Current())
fetcher.protocolPercents = edgediscovery.ProtocolPercents{edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: -1}} fetcher.protocolPercents = edgediscovery.ProtocolPercents{edgediscovery.ProtocolPercent{Protocol: "http2", Percentage: -1}}
assert.Equal(t, H2mux, selector.Current()) assert.Equal(t, HTTP2, selector.Current())
} }
func TestProtocolSelectorRefreshTTL(t *testing.T) { func TestProtocolSelectorRefreshTTL(t *testing.T) {

View File

@ -41,7 +41,7 @@ func TestWaitForBackoffFallback(t *testing.T) {
} }
warpRoutingEnabled := false warpRoutingEnabled := false
protocolSelector, err := connection.NewProtocolSelector( protocolSelector, err := connection.NewProtocolSelector(
connection.HTTP2.String(), "auto",
warpRoutingEnabled, warpRoutingEnabled,
namedTunnel, namedTunnel,
mockFetcher.fetch(), mockFetcher.fetch(),