vppn/peer/connhandler.go
2024-12-14 07:38:06 +01:00

100 lines
1.8 KiB
Go

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:
}
}