diff --git a/peer/state-clientinit.go b/peer/state-clientinit.go index 8d963bc..8ced222 100644 --- a/peer/state-clientinit.go +++ b/peer/state-clientinit.go @@ -75,13 +75,22 @@ func (s *stateClientInit) onInit(msg controlMsg[packetInit]) peerState { } func (s *stateClientInit) onPing() peerState { - if time.Since(s.startedAt) > timeoutInterval { - s.logf("Init timeout. Assuming version 1.") - return enterStateClient(s.peerData) + if time.Since(s.startedAt) < timeoutInterval { + s.sendInit() + return s } - s.sendInit() - return s + if s.staged.Direct { + s.staged.Direct = false + s.publish(s.staged) + s.startedAt = time.Now() + s.sendInit() + s.logf("Direct connection failed. Attempting indirect connection.") + return s + } + + s.logf("Timeout.") + return initPeerState(s.peerData, s.peer) } func (s *stateClientInit) sendInit() { diff --git a/peer/state-clientinit_test.go b/peer/state-clientinit_test.go index 87cdc8b..fc910a5 100644 --- a/peer/state-clientinit_test.go +++ b/peer/state-clientinit_test.go @@ -56,11 +56,20 @@ func TestPeerState_ClientInit_onPingTimeout(t *testing.T) { state := assertType[*stateClientInit](t, h.State) state.startedAt = time.Now().Add(-2 * timeoutInterval) + assertEqual(t, state.staged.Direct, true) h.OnPingTimer() - // Should have moved into the client state due to timeout. - assertType[*stateClient](t, h.State) + // Should now try indirect connection. + state = assertType[*stateClientInit](t, h.State) + assertEqual(t, state.staged.Direct, false) + + // Should re-initialize the peer after another timeout, so should be direct + // again. + state.startedAt = time.Now().Add(-2 * timeoutInterval) + h.OnPingTimer() + + assertEqual(t, state.staged.Direct, true) } func TestPeerState_ClientInit_onPeerUpdate(t *testing.T) {