package peer import ( "net/netip" "time" ) type stateClientInit2 struct { *peerData startedAt time.Time traceID uint64 } func enterStateClientInit2(data *peerData) peerState { ip, ipValid := netip.AddrFromSlice(data.peer.PublicIP) data.staged.Up = false data.staged.Relay = false data.staged.Direct = ipValid data.staged.DirectAddr = netip.AddrPortFrom(ip, data.peer.Port) data.staged.PubSignKey = data.peer.PubSignKey data.staged.ControlCipher = newControlCipher(data.privKey, data.peer.PubKey) data.staged.DataCipher = newDataCipher() data.publish(data.staged) state := &stateClientInit2{ peerData: data, startedAt: time.Now(), traceID: newTraceID(), } state.sendInit() data.pingTimer.Reset(pingInterval) state.logf("==> ClientInit") return state } func (s *stateClientInit2) logf(str string, args ...any) { s.peerData.logf("INIT | "+str, args...) } func (s *stateClientInit2) OnMsg(raw any) peerState { switch msg := raw.(type) { case peerUpdateMsg: return initPeerState(s.peerData, msg.Peer) case controlMsg[packetInit]: return s.onInit(msg) case pingTimerMsg: return s.onPing() default: s.logf("Ignoring message: %v", raw) return s } } func (s *stateClientInit2) onInit(msg controlMsg[packetInit]) peerState { if msg.Packet.TraceID != s.traceID { s.logf("Invalid trace ID on INIT.") return s } s.logf("Got INIT version %d.", msg.Packet.Version) return s.nextState() } func (s *stateClientInit2) onPing() peerState { if time.Since(s.startedAt) > timeoutInterval { s.logf("Init timeout. Assuming version 1.") return s.nextState() } s.sendInit() return s } func (s *stateClientInit2) sendInit() { s.traceID = newTraceID() init := packetInit{ TraceID: s.traceID, Direct: s.staged.Direct, Version: version, } s.Send(s.staged, init) } func (s *stateClientInit2) nextState() peerState { if s.staged.Direct { return enterStateClientDirect2(s.peerData, s.staged.DirectAddr) } return enterStateClientRelayed2(s.peerData) }