Files
go-playit/core/agent.go

130 lines
3.5 KiB
Go

package core
import (
"fmt"
"net"
"net/netip"
"time"
"sirherobrine23.com.br/go-bds/go-playit/api"
"sirherobrine23.com.br/go-bds/go-playit/proto"
"sirherobrine23.com.br/go-bds/go-playit/xcode"
)
type AgentSettings struct {
Api *api.ApiClient
}
type PlayitAgent struct {
Config *AgentSettings // Agent config
keepRunning bool // Keep running new connections from Controller
clientAcceptTcp chan *proto.NewClient // TCP Clients
UdpRxPacket chan *proto.UdpChannelDetails // UDP Packets
AgentInfo *api.AgentRunData // Agent run data
ForceUpdateAgentInfo bool // Force agent get new data from API
// Connected
ControlAddr netip.AddrPort // Current Controller address
PacketIo *net.UDPConn // Local listen UDP
PongLatest proto.Pong // Last Pong return from controller
// Estabilished
PongAtAuth proto.Pong // Pong on authenticate
Registered *proto.AgentRegistered // Agent register from controller
CurrentPing xcode.Option[uint32] // Current ping
ClockOffset int64 // Clock offset
ForceExpired bool // Force expire auth
// Maintened
LastControlTargets []netip.AddrPort // Last controller addresses
LastKeepAlive time.Time // Last keep alive from agent
LastPing time.Time // Last ping to controller
LastPong time.Time // Last pong return from controller
LastUdpAuth time.Time // Last send auth to controller
}
func NewPlayitAgent(config *AgentSettings) (*PlayitAgent, error) {
agent := &PlayitAgent{
keepRunning: true,
clientAcceptTcp: make(chan *proto.NewClient),
UdpRxPacket: make(chan *proto.UdpChannelDetails),
Config: config,
}
if err := connectToFirst(agent); err != nil {
close(agent.clientAcceptTcp)
close(agent.UdpRxPacket)
return nil, fmt.Errorf("cannot connect to first address: %w", err)
}
if err := agent.setupConnection(); err != nil {
close(agent.clientAcceptTcp)
close(agent.UdpRxPacket)
return nil, fmt.Errorf("cannot setup connection: %w", err)
}
// Start agent packet process
go agent.run()
return agent, nil
}
func (agent *PlayitAgent) Close() (err error) {
defer func() { recover() }()
if err = agent.PacketIo.Close(); err != nil {
return
}
if agent.clientAcceptTcp != nil {
close(agent.clientAcceptTcp)
agent.clientAcceptTcp = nil
}
if agent.UdpRxPacket != nil {
close(agent.UdpRxPacket)
agent.UdpRxPacket = nil
}
return nil
}
// Process controller packets
func (agent *PlayitAgent) run() {
lastRunData := time.Now()
lastControlAddr := lastRunData
for agent.keepRunning {
if agent.AgentInfo == nil || len(agent.AgentInfo.Tunnels) == 0 || agent.ForceUpdateAgentInfo || lastRunData.Add(time.Minute).Compare(time.Now()) < 0 {
agent.AgentInfo, _ = agent.Config.Api.AgentInfo()
lastRunData = time.Now()
agent.ForceUpdateAgentInfo = false
}
if lastControlAddr.Add(time.Millisecond*30_000).Compare(time.Now()) < 0 {
lastControlAddr = time.Now()
agent.reloadControlAddrs()
// if err := ; err != nil {
// fmt.Fprintf(os.Stderr, "cannot reload control addresses: %s\n", err)
// }
}
// Update PacketIo
event, err := agent.update()
if err != nil {
// fmt.Fprintf(os.Stderr, "cannot update agent: %s\n", err)
continue
} else if event == nil {
continue
}
switch {
case event.NewClientTcp != nil:
agent.clientAcceptTcp <- event.NewClientTcp
case event.UdpRxPacket != nil:
agent.UdpRxPacket <- event.UdpRxPacket
}
}
}