package localapi import ( "net/http" "time" ) // LineTestReader is the R-1247 weekly upload line test (internal/linetest.Tester) as the local API reads it. type LineTestReader interface { Value() (mbps float64, at time.Time, ok bool) } // LineTestResponse is GET /host/line-test. Present=false: never measured, or the job is not wired (no tunnel, disabled, // or an agent before the route answers 404 — the controller reads all three as „unknown"). type LineTestResponse struct { Present bool `json:"present"` Mbps float64 `json:"mbps,omitempty"` MeasuredAt string `json:"measured_at,omitempty"` // RFC3339 UTC Method string `json:"method,omitempty"` // "iperf3-tunnel": a 10-second upload to ep0 inside the tunnel } // SetLineTest wires the weekly line test (main.go builds it after the local API server). func (s *Server) SetLineTest(r LineTestReader) { s.lineTest = r } func (s *Server) handleLineTest(w http.ResponseWriter, r *http.Request, vmid int) { if s.lineTest == nil { writeOK(w, LineTestResponse{Present: false}) return } mbps, at, ok := s.lineTest.Value() if !ok { writeOK(w, LineTestResponse{Present: false}) return } s.logger.Debug("local-api: /host/line-test served", "vmid", vmid, "mbps", mbps, "measured_at", at.UTC().Format(time.RFC3339)) writeOK(w, LineTestResponse{Present: true, Mbps: mbps, MeasuredAt: at.UTC().Format(time.RFC3339), Method: "iperf3-tunnel"}) }