112 lines
2.0 KiB
Go
112 lines
2.0 KiB
Go
package peer
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"runtime/debug"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
type connHandler struct {
|
|
// Communication.
|
|
mediatorUpdates chan byte
|
|
peerUpdates chan peerUpdate
|
|
pings chan wrapper[Ping]
|
|
pongs chan wrapper[Pong]
|
|
|
|
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),
|
|
pings: make(chan wrapper[Ping], 1),
|
|
pongs: make(chan wrapper[Pong], 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 w := <-h.pings:
|
|
state = state.HandlePing(w)
|
|
|
|
case w := <-h.pongs:
|
|
state = state.HandlePong(w)
|
|
|
|
case <-data.pingTimer.C:
|
|
data.HandleSendPing()
|
|
|
|
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) HandlePing(w wrapper[Ping]) {
|
|
select {
|
|
case c.pings <- w:
|
|
default:
|
|
}
|
|
}
|
|
|
|
func (c *connHandler) HandlePong(w wrapper[Pong]) {
|
|
select {
|
|
case c.pongs <- w:
|
|
default:
|
|
}
|
|
}
|
|
|
|
func (c *connHandler) UpdatePeer(update peerUpdate) {
|
|
select {
|
|
case c.peerUpdates <- update:
|
|
default:
|
|
}
|
|
}
|