package server import ( "encoding/json" "net/http" "strings" "github.com/openp2p-cn/inp2p/pkg/protocol" ) func (s *Server) HandleNodeMeta(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { writeJSON(w, http.StatusMethodNotAllowed, `{"error":1,"message":"method not allowed"}`) return } if s.store == nil { writeJSON(w, http.StatusInternalServerError, `{"error":1,"message":"store not ready"}`) return } ac, ok := s.ResolveTenantAccessToken(BearerToken(r)) if !ok || ac.TenantID <= 0 { writeJSON(w, http.StatusUnauthorized, `{"error":1,"message":"unauthorized"}`) return } if strings.HasSuffix(r.URL.Path, "/alias") { var req struct { NodeUUID string `json:"node_uuid"` Alias string `json:"alias"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.NodeUUID == "" { writeJSON(w, http.StatusBadRequest, `{"error":1,"message":"bad request"}`) return } if err := s.store.SetNodeAlias(ac.TenantID, req.NodeUUID, req.Alias); err != nil { writeJSON(w, http.StatusBadRequest, `{"error":1,"message":"`+err.Error()+`"}`) return } writeJSON(w, http.StatusOK, `{"error":0,"message":"ok"}`) return } if strings.HasSuffix(r.URL.Path, "/ip") { var req struct { NodeUUID string `json:"node_uuid"` VirtualIP string `json:"virtual_ip"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.NodeUUID == "" || req.VirtualIP == "" { writeJSON(w, http.StatusBadRequest, `{"error":1,"message":"bad request"}`) return } if err := s.store.SetNodeVirtualIP(ac.TenantID, req.NodeUUID, req.VirtualIP); err != nil { writeJSON(w, http.StatusBadRequest, `{"error":1,"message":"`+err.Error()+`"}`) return } nodes := s.GetOnlineNodesByTenant(ac.TenantID) affectedNode := "" reconnectTriggered := false broadcastCount := 0 for _, n := range nodes { nc, err := s.store.GetNodeCredentialByName(ac.TenantID, n.Name) if err != nil || nc == nil { continue } peer := map[string]any{"node": n.Name, "ip": nc.VirtualIP, "online": n.IsOnline()} if nc.NodeUUID == req.NodeUUID { affectedNode = n.Name _ = n.Conn.Write(protocol.MsgPush, protocol.SubPushSDWANDel, peer) n.Conn.Close() reconnectTriggered = true continue } _ = n.Conn.Write(protocol.MsgPush, protocol.SubPushSDWANPeer, peer) broadcastCount++ } resp, _ := json.Marshal(map[string]any{ "error": 0, "message": "ok", "affected_node": affectedNode, "target_node_uuid": req.NodeUUID, "new_virtual_ip": req.VirtualIP, "broadcast_count": broadcastCount, "reconnect_triggered": reconnectTriggered, }) writeJSON(w, http.StatusOK, string(resp)) return } writeJSON(w, http.StatusNotFound, `{"error":1,"message":"not found"}`) }