package peer import ( "net/netip" "time" ) type stateClientDirect2 struct { *peerData lastSeen time.Time syn packetSyn } func enterStateClientDirect2(data *peerData, directAddr netip.AddrPort) peerState { data.staged.Relay = data.peer.Relay data.staged.Direct = true data.staged.DirectAddr = directAddr data.publish(data.staged) state := &stateClientDirect2{ peerData: data, lastSeen: time.Now(), syn: packetSyn{ TraceID: newTraceID(), SharedKey: data.staged.DataCipher.Key(), Direct: true, }, } state.Send(state.staged, state.syn) data.pingTimer.Reset(pingInterval) state.logf("==> ClientDirect") return state } func (s *stateClientDirect2) logf(str string, args ...any) { s.peerData.logf("CLNT | "+str, args...) } func (s *stateClientDirect2) OnMsg(raw any) peerState { switch msg := raw.(type) { case peerUpdateMsg: return initPeerState(s.peerData, msg.Peer) case controlMsg[packetAck]: return s.onAck(msg) case pingTimerMsg: return s.onPingTimer() case controlMsg[packetLocalDiscovery]: return s default: s.logf("Ignoring message: %v", raw) return s } } func (s *stateClientDirect2) onAck(msg controlMsg[packetAck]) peerState { if msg.Packet.TraceID != s.syn.TraceID { return s } s.lastSeen = time.Now() if !s.staged.Up { s.staged.Up = true s.publish(s.staged) s.logf("Got ACK.") } s.pubAddrs.Store(msg.Packet.ToAddr) return s } func (s *stateClientDirect2) onPingTimer() peerState { if time.Since(s.lastSeen) > timeoutInterval { if s.staged.Up { s.logf("Timeout.") } return initPeerState(s.peerData, s.peer) } s.Send(s.staged, s.syn) return s }