package peer import ( "fmt" "log" "runtime/debug" "sync/atomic" "time" ) type connHandler struct { // Communication. mediatorUpdates chan byte peerUpdates chan peerUpdate packets chan wrapper data *connData } func newConnHandler( server bool, peerIP byte, routes [MAX_IP]*atomic.Pointer[route], encPrivKey []byte, sender *safeConnSender, ) *connHandler { d := &connData{ server: server, pingTimer: time.NewTimer(pingInterval), timeoutTimer: time.NewTimer(timeoutInterval), routes: routes, route: routes[peerIP], peerIP: peerIP, encPrivKey: encPrivKey, buf: make([]byte, BUFFER_SIZE), sender: sender, } h := &connHandler{ mediatorUpdates: make(chan byte, 1), peerUpdates: make(chan peerUpdate, 1), packets: make(chan wrapper, 1), data: d, } go h.mainLoop() return h } func (h *connHandler) mainLoop() { defer func() { if r := recover(); r != nil { fmt.Println("stacktrace from panic: \n" + string(debug.Stack())) } }() var ( data = h.data state = newConnNull(data) name = state.Name() ) for { select { case update := <-h.peerUpdates: state = data.HandlePeerUpdate(state, update) case <-data.pingTimer.C: data.HandleSendPing() case w := <-h.packets: state = state.HandlePacket(w) case <-data.timeoutTimer.C: log.Printf("[%s] Connection timeout.", state.Name()) state = state.HandleTimeout() } if state.Name() != name { log.Printf("[%03d] STATE: %s", data.peerIP, state.Name()) name = state.Name() } } } func (c *connHandler) HandlePacket(w wrapper) { select { case c.packets <- w: default: } } func (c *connHandler) UpdatePeer(update peerUpdate) { select { case c.peerUpdates <- update: default: } }