package server import ( "log" "net/netip" "github.com/openp2p-cn/inp2p/pkg/protocol" ) func (s *Server) GetSDWAN() protocol.SDWANConfig { return s.sdwan.get() } func (s *Server) GetSDWANTenant(tenantID int64) protocol.SDWANConfig { return s.sdwan.getTenant(tenantID) } func (s *Server) SetSDWAN(cfg protocol.SDWANConfig) error { if err := s.sdwan.save(cfg); err != nil { return err } s.broadcastSDWAN(s.sdwan.get()) return nil } func (s *Server) SetSDWANTenant(tenantID int64, cfg protocol.SDWANConfig) error { if err := s.sdwan.saveTenant(tenantID, cfg); err != nil { return err } s.broadcastSDWANTenant(tenantID, s.sdwan.getTenant(tenantID)) return nil } func (s *Server) broadcastSDWAN(cfg protocol.SDWANConfig) { if !cfg.Enabled || cfg.GatewayCIDR == "" { return } s.mu.RLock() defer s.mu.RUnlock() for _, n := range s.nodes { if !n.IsOnline() { continue } _ = n.Conn.Write(protocol.MsgPush, protocol.SubPushSDWANConfig, cfg) } } func (s *Server) broadcastSDWANTenant(tenantID int64, cfg protocol.SDWANConfig) { if !cfg.Enabled || cfg.GatewayCIDR == "" { return } s.mu.RLock() defer s.mu.RUnlock() for _, n := range s.nodes { if !n.IsOnline() || n.TenantID != tenantID { continue } _ = n.Conn.Write(protocol.MsgPush, protocol.SubPushSDWANConfig, cfg) } } func (s *Server) pushSDWANPeer(to *NodeInfo, peer protocol.SDWANPeer) { if to == nil || !to.IsOnline() { return } _ = to.Conn.Write(protocol.MsgPush, protocol.SubPushSDWANPeer, peer) } func (s *Server) pushSDWANDel(to *NodeInfo, peer protocol.SDWANPeer) { if to == nil || !to.IsOnline() { return } _ = to.Conn.Write(protocol.MsgPush, protocol.SubPushSDWANDel, peer) } func (s *Server) announceSDWANNodeOnline(nodeName string) { // pick tenant config by node s.mu.RLock() newNode := s.nodes[nodeName] s.mu.RUnlock() if newNode == nil { return } cfg := s.sdwan.getTenant(newNode.TenantID) if cfg.GatewayCIDR == "" { return } selfIP := "" for _, n := range cfg.Nodes { if n.Node == nodeName { selfIP = n.IP break } } if selfIP == "" { return } s.mu.RLock() newNode = s.nodes[nodeName] if newNode == nil || !newNode.IsOnline() { s.mu.RUnlock() return } for _, n := range cfg.Nodes { if n.Node == nodeName { continue } other := s.nodes[n.Node] if other == nil || !other.IsOnline() || other.TenantID != newNode.TenantID { continue } // existing -> new s.pushSDWANPeer(newNode, protocol.SDWANPeer{Node: n.Node, IP: n.IP, Online: true}) // new -> existing s.pushSDWANPeer(other, protocol.SDWANPeer{Node: nodeName, IP: selfIP, Online: true}) } s.mu.RUnlock() } func (s *Server) announceSDWANNodeOffline(nodeName string) { s.mu.RLock() old := s.nodes[nodeName] s.mu.RUnlock() if old == nil { return } cfg := s.sdwan.getTenant(old.TenantID) if cfg.GatewayCIDR == "" { return } selfIP := "" for _, n := range cfg.Nodes { if n.Node == nodeName { selfIP = n.IP break } } s.mu.RLock() defer s.mu.RUnlock() for _, n := range s.nodes { if n.Name == nodeName || !n.IsOnline() || n.TenantID != old.TenantID { continue } s.pushSDWANDel(n, protocol.SDWANPeer{Node: nodeName, IP: selfIP, Online: false}) } } func (s *Server) RouteSDWANPacket(from *NodeInfo, pkt protocol.SDWANPacket) { log.Printf("[sdwan] route: %s -> %s len=%d", from.Name, pkt.DstIP, len(pkt.Payload)) if from == nil { return } // Use global config for untrusted nodes (TenantID=0), otherwise use tenant config var cfg protocol.SDWANConfig if from.TenantID == 0 { cfg = s.sdwan.get() } else { cfg = s.sdwan.getTenant(from.TenantID) } if cfg.GatewayCIDR == "" || pkt.DstIP == "" || len(pkt.Payload) == 0 { return } dst, err := netip.ParseAddr(pkt.DstIP) if err != nil { return } toNode := "" for _, n := range cfg.Nodes { if n.IP == pkt.DstIP { candidate := s.GetNodeForUser(n.Node, from.Token) if candidate != nil && candidate.TenantID == from.TenantID { toNode = n.Node break } } if p, err := netip.ParseAddr(n.IP); err == nil && p == dst { candidate := s.GetNodeForUser(n.Node, from.Token) if candidate != nil && candidate.TenantID == from.TenantID { toNode = n.Node break } } } if toNode == "" || toNode == from.Name { return } s.mu.RLock() to := s.nodes[toNode] if to != nil && to.TenantID != from.TenantID { to = nil } s.mu.RUnlock() if to == nil || !to.IsOnline() { return } pkt.FromNode = from.Name pkt.ToNode = toNode frame := protocol.EncodeRaw(protocol.MsgTunnel, protocol.SubTunnelSDWANRaw, pkt.Payload) _ = to.Conn.WriteRaw(frame) }