package peer import ( "encoding/json" "io" "log" "net/http" "net/url" "time" "vppn/m" ) type HubPoller struct { Globals client *http.Client req *http.Request versions [256]int64 netName string } func NewHubPoller( g Globals, netName, hubURL, apiKey string, ) (*HubPoller, error) { u, err := url.Parse(hubURL) if err != nil { return nil, err } u.Path = "/peer/fetch-state/" client := &http.Client{Timeout: 8 * time.Second} req := &http.Request{ Method: http.MethodGet, URL: u, Header: http.Header{}, } req.SetBasicAuth("", apiKey) return &HubPoller{ Globals: g, client: client, req: req, netName: netName, }, nil } func (hp *HubPoller) logf(s string, args ...any) { log.Printf("[HubPoller] "+s, args...) } func (hp *HubPoller) Run() { state, err := loadNetworkState(hp.netName) if err != nil { hp.logf("Failed to load network state: %v", err) hp.logf("Polling hub...") hp.pollHub() } else { hp.applyNetworkState(state) } for range time.Tick(64 * time.Second) { hp.pollHub() } } func (hp *HubPoller) pollHub() { var state m.NetworkState resp, err := hp.client.Do(hp.req) if err != nil { hp.logf("Failed to fetch peer state: %v", err) return } body, err := io.ReadAll(resp.Body) _ = resp.Body.Close() if err != nil { hp.logf("Failed to read body from hub: %v", err) return } if err := json.Unmarshal(body, &state); err != nil { hp.logf("Failed to unmarshal response from hub: %v\n%s", err, body) return } if err := storeNetworkState(hp.netName, state); err != nil { hp.logf("Failed to store network state: %v", err) } hp.applyNetworkState(state) } func (hp *HubPoller) applyNetworkState(state m.NetworkState) { for i, peer := range state.Peers { if i == int(hp.LocalPeerIP) { continue } if peer != nil && peer.Version == hp.versions[i] { continue } hp.RemotePeers[i].Load().HandlePeerUpdate(peerUpdateMsg{Peer: state.Peers[i]}) if peer != nil { hp.versions[i] = peer.Version } } }