package node import ( "lux/crypto" "lux/host" "lux/net" "lux/proto" "sync" ) type LuxNode struct { router net.LuxRouter running bool state LuxNodeState stateLock sync.RWMutex } func NewLuxNode(nodeKey crypto.LuxKey, ks crypto.LuxKeyStore) LuxNode { return LuxNode{ router: net.NewLuxRouter(nodeKey, ks), running: false, state: NewNodeState(), } } func (node *LuxNode) GetRouter() *net.LuxRouter { return &node.router } func (node *LuxNode) GetNodeID() proto.LuxID { return node.GetRouter().GetThisKey().Id } func (node *LuxNode) AddInterior(udpAddr string) error { return node.router.CreateInboundChannel(net.LuxChannelInterior, udpAddr) } func (node *LuxNode) AddExterior(udpAddr string) error { return node.router.CreateInboundChannel(net.LuxChannelExterior, udpAddr) } func (node *LuxNode) GetState() *LuxNodeState { return &node.state } func (node *LuxNode) GetStateLock() *sync.RWMutex { return &node.stateLock } func (node *LuxNode) handleHeartbeat(packet *net.LuxPacket) { if packet.ChannelType != net.LuxChannelExterior { log.Error("heartbeat not on exterior!") return } // parse heartbeat state := host.NewLuxState("") if err := state.Read(&packet.Buffer); err != nil { log.Error("failed to parse heartbeat: %v", err) return } // register heartbeat node.stateLock.Lock() node.state.RegisterHeartbeat(packet.Target, state) node.stateLock.Unlock() log.Debugf("heartbeat from %s", packet.Target.String()) } func nodeLoop(node *LuxNode) { router := &node.router for node.running { packet, err := router.Recv() if err != nil { log.Infof("node recv err %v", err) } switch packet.Type { case net.LuxPacketTypeHeartbeat: node.handleHeartbeat(&packet) default: log.Warningf("unknown packet type %d on chType %d", packet.Type, packet.ChannelType) } } } func (node *LuxNode) Start() { node.router.Start() node.running = true go nodeLoop(node) } func (node *LuxNode) Stop() { node.running = false node.router.Stop() }