mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
[FIXED] Gateway: connect could fail due to PING sent before CONNECT
When a gateway connection was created (either accepted or initiated)
the timer to fire the first PING was started at that time, which
means that for an outbound connection, if the INFO coming from
the other side was delayed, it was possible for the outbound to
send the PING protocol before the CONNECT, which would cause
the accepting side to close the connection due to a "parse" error
(since the CONNECT for an inbound is supposed to be the very
first protocol).
Also noticed that we were not setting the auth timer like we do
for the other type of connections. If authorization{timeout:<n>}
is not set, the default is 2 seconds.
Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
This commit is contained in:
@@ -733,3 +733,76 @@ func TestGatewayAdvertiseInCluster(t *testing.T) {
|
||||
sb2.Shutdown()
|
||||
expectNothing(t, gA)
|
||||
}
|
||||
|
||||
func TestGatewayAuthTimeout(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
setAuth bool //
|
||||
wait time.Duration
|
||||
}{
|
||||
{"auth not explicitly set", false, 2500 * time.Millisecond},
|
||||
{"auth set", true, 500 * time.Millisecond},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ob := testDefaultOptionsForGateway("B")
|
||||
if test.setAuth {
|
||||
ob.Gateway.AuthTimeout = 0.25
|
||||
}
|
||||
sb := RunServer(ob)
|
||||
defer sb.Shutdown()
|
||||
|
||||
sa := createGatewayConn(t, ob.Gateway.Host, ob.Gateway.Port)
|
||||
defer sa.Close()
|
||||
|
||||
gAExpect := expectCommand(t, sa)
|
||||
|
||||
dstInfo := checkInfoMsg(t, sa)
|
||||
if dstInfo.Gateway != "B" {
|
||||
t.Fatalf("Expected to connect to %q, got %q", "B", dstInfo.Gateway)
|
||||
}
|
||||
|
||||
// Don't send our CONNECT and we should be disconnected due to auth timeout.
|
||||
time.Sleep(test.wait)
|
||||
gAExpect(errRe)
|
||||
expectDisconnect(t, sa)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGatewayFirstPingGoesAfterConnect(t *testing.T) {
|
||||
ob := testDefaultOptionsForGateway("B")
|
||||
// For this test, we want the first ping to NOT be disabled.
|
||||
ob.DisableShortFirstPing = false
|
||||
// Also, for this test increase auth_timeout so that it does not disconnect
|
||||
// while checking...
|
||||
ob.Gateway.AuthTimeout = 10.0
|
||||
sb := RunServer(ob)
|
||||
defer sb.Shutdown()
|
||||
|
||||
sa := createGatewayConn(t, ob.Gateway.Host, ob.Gateway.Port)
|
||||
defer sa.Close()
|
||||
|
||||
gASend, gAExpect := sendCommand(t, sa), expectCommand(t, sa)
|
||||
dstInfo := checkInfoMsg(t, sa)
|
||||
if dstInfo.Gateway != "B" {
|
||||
t.Fatalf("Expected to connect to %q, got %q", "B", dstInfo.Gateway)
|
||||
}
|
||||
|
||||
// Wait and we should not be receiving a PING from server B until we send
|
||||
// a CONNECT. We need to wait for more than the initial PING, so cannot
|
||||
// use expectNothing() helper here.
|
||||
buf := make([]byte, 256)
|
||||
sa.SetReadDeadline(time.Now().Add(2 * time.Second))
|
||||
if n, err := sa.Read(buf); err == nil {
|
||||
t.Fatalf("Expected nothing, got %s", buf[:n])
|
||||
}
|
||||
|
||||
// Now send connect and INFO
|
||||
cs := fmt.Sprintf("CONNECT {\"verbose\":%v,\"pedantic\":%v,\"tls_required\":%v,\"gateway\":%q}\r\n",
|
||||
false, false, false, "A")
|
||||
gASend(cs)
|
||||
gASend(fmt.Sprintf("INFO {\"gateway\":%q}\r\n", "A"))
|
||||
|
||||
// We should get the first PING
|
||||
gAExpect(pingRe)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user