package api import ( "encoding/json" "log" "crypto-miner-server/internal/atlas" ) func (h *WSHub) handleAgentAtlasGossip(senderID string, payload json.RawMessage) { if !h.serverPolicySnapshot().AtlasLanGossipEnabled { return } var body struct { Hints []atlas.GossipHint `json:"hints"` } if err := json.Unmarshal(payload, &body); err != nil || len(body.Hints) == 0 { return } hints := atlas.NormalizeGossipHints(body.Hints) if len(hints) == 0 { return } h.relayAtlasGossip(senderID, hints) } func (h *WSHub) relayAtlasGossip(senderID string, hints []atlas.GossipHint) { senderSubnet := h.agentSubnetFor(senderID) if senderSubnet == "" { return } skips := atlas.SkipsFromHints(hints) if len(skips) == 0 { return } out := Message{ Type: "atlas_gossip", Payload: mustMarshal(map[string]interface{}{ "hints": skips, "source_agent_id": senderID, }), } h.mu.RLock() defer h.mu.RUnlock() for id, ac := range h.agents { if id == senderID || h.agentSubnet[id] != senderSubnet { continue } if err := ac.SendJSON(out); err != nil { log.Printf("[atlas-gossip] relay to %s: %v", id, err) } } } func (h *WSHub) agentSubnetFor(agentID string) string { h.mu.RLock() subnet := h.agentSubnet[agentID] h.mu.RUnlock() if subnet != "" { return subnet } if h.db == nil { return "" } ag, err := h.db.GetAgent(agentID) if err != nil || ag == nil { return "" } return atlas.SubnetPrefix(ag.IP) }