107 lines
2.1 KiB
Go
107 lines
2.1 KiB
Go
package peer
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
"vppn/m"
|
|
)
|
|
|
|
type hubPoller struct {
|
|
client *http.Client
|
|
req *http.Request
|
|
versions [256]int64
|
|
localIP byte
|
|
netName string
|
|
handleControlMsg func(fromIP byte, msg any)
|
|
}
|
|
|
|
func newHubPoller(
|
|
localIP byte,
|
|
netName,
|
|
hubURL,
|
|
apiKey string,
|
|
handleControlMsg func(byte, any),
|
|
) (*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{
|
|
client: client,
|
|
req: req,
|
|
localIP: localIP,
|
|
netName: netName,
|
|
handleControlMsg: handleControlMsg,
|
|
}, nil
|
|
}
|
|
|
|
func (hp *hubPoller) Run() {
|
|
state, err := loadNetworkState(hp.netName)
|
|
if err != nil {
|
|
log.Printf("Failed to load network state: %v", err)
|
|
log.Printf("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 {
|
|
log.Printf("Failed to fetch peer state: %v", err)
|
|
return
|
|
}
|
|
body, err := io.ReadAll(resp.Body)
|
|
_ = resp.Body.Close()
|
|
if err != nil {
|
|
log.Printf("Failed to read body from hub: %v", err)
|
|
return
|
|
}
|
|
|
|
if err := json.Unmarshal(body, &state); err != nil {
|
|
log.Printf("Failed to unmarshal response from hub: %v\n%s", err, body)
|
|
return
|
|
}
|
|
|
|
hp.applyNetworkState(state)
|
|
|
|
if err := storeNetworkState(hp.netName, state); err != nil {
|
|
log.Printf("Failed to store network state: %v", err)
|
|
}
|
|
}
|
|
|
|
func (hp *hubPoller) applyNetworkState(state m.NetworkState) {
|
|
for i, peer := range state.Peers {
|
|
if i != int(hp.localIP) {
|
|
if peer == nil || peer.Version != hp.versions[i] {
|
|
hp.handleControlMsg(byte(i), peerUpdateMsg{PeerIP: byte(i), Peer: state.Peers[i]})
|
|
if peer != nil {
|
|
hp.versions[i] = peer.Version
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|