This commit is contained in:
55
internal/beacon/client.go
Normal file
55
internal/beacon/client.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.send.nrw/sendnrw/decent-websrv/internal/mesh"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
URL, Token string
|
||||
HTTP *http.Client
|
||||
}
|
||||
|
||||
func (c *Client) LoopRegister(n mesh.NodeInfo) {
|
||||
go func() {
|
||||
for {
|
||||
c.register(n)
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *Client) register(n mesh.NodeInfo) {
|
||||
b, _ := json.Marshal(RegisterReq{BaseURL: n.PublicURL, MeshURL: n.MeshURL, NodeID: n.NodeID, TTL: 45})
|
||||
req, _ := http.NewRequest(http.MethodPost, c.URL+"/_beacon/register", bytes.NewReader(b))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if c.Token != "" {
|
||||
req.Header.Set("X-Beacon-Token", c.Token)
|
||||
}
|
||||
resp, err := c.HTTP.Do(req)
|
||||
if err != nil {
|
||||
log.Println("beacon register:", err)
|
||||
return
|
||||
}
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
func (c *Client) PollPeers() []mesh.NodeInfo {
|
||||
req, _ := http.NewRequest(http.MethodGet, c.URL+"/_beacon/peers", nil)
|
||||
if c.Token != "" {
|
||||
req.Header.Set("X-Beacon-Token", c.Token)
|
||||
}
|
||||
resp, err := c.HTTP.Do(req)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var out PeersResp
|
||||
_ = json.NewDecoder(resp.Body).Decode(&out)
|
||||
return out.Peers
|
||||
}
|
||||
73
internal/beacon/server.go
Normal file
73
internal/beacon/server.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.send.nrw/sendnrw/decent-websrv/internal/mesh"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
addr string
|
||||
token string
|
||||
reg *registry
|
||||
http *http.Server
|
||||
}
|
||||
|
||||
type registry struct {
|
||||
mu sync.Mutex
|
||||
m map[string]mesh.NodeInfo
|
||||
exp map[string]int64 // id->expires
|
||||
}
|
||||
|
||||
func NewServer(addr, token string) *Server {
|
||||
s := &Server{addr: addr, token: token, reg: ®istry{m: map[string]mesh.NodeInfo{}, exp: map[string]int64{}}}
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/_beacon/register", s.handleRegister)
|
||||
mux.HandleFunc("/_beacon/peers", s.handlePeers)
|
||||
s.http = &http.Server{Addr: addr, Handler: mux, ReadHeaderTimeout: 5 * time.Second}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Server) ListenAndServe() error { return s.http.ListenAndServe() }
|
||||
func (s *Server) ListenAndServeTLS(cert, key string) error {
|
||||
return s.http.ListenAndServeTLS(cert, key)
|
||||
}
|
||||
|
||||
func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||
if s.token != "" && r.Header.Get("X-Beacon-Token") != s.token {
|
||||
http.Error(w, "forbidden", 403)
|
||||
return
|
||||
}
|
||||
var in RegisterReq
|
||||
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
|
||||
http.Error(w, "bad", 400)
|
||||
return
|
||||
}
|
||||
n := mesh.NodeInfo{NodeID: in.NodeID, PublicURL: in.BaseURL, MeshURL: in.MeshURL}
|
||||
exp := time.Now().Add(time.Duration(in.TTL) * time.Second).Unix()
|
||||
s.reg.mu.Lock()
|
||||
s.reg.m[n.NodeID] = n
|
||||
s.reg.exp[n.NodeID] = exp
|
||||
s.reg.mu.Unlock()
|
||||
w.WriteHeader(200)
|
||||
}
|
||||
|
||||
func (s *Server) handlePeers(w http.ResponseWriter, r *http.Request) {
|
||||
if s.token != "" && r.Header.Get("X-Beacon-Token") != s.token {
|
||||
http.Error(w, "forbidden", 403)
|
||||
return
|
||||
}
|
||||
now := time.Now().Unix()
|
||||
s.reg.mu.Lock()
|
||||
out := make([]mesh.NodeInfo, 0, len(s.reg.m))
|
||||
for id, n := range s.reg.m {
|
||||
if s.reg.exp[id] > now {
|
||||
out = append(out, n)
|
||||
}
|
||||
}
|
||||
s.reg.mu.Unlock()
|
||||
_ = json.NewEncoder(w).Encode(PeersResp{Peers: out})
|
||||
}
|
||||
14
internal/beacon/types.go
Normal file
14
internal/beacon/types.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package beacon
|
||||
|
||||
import "git.send.nrw/sendnrw/decent-websrv/internal/mesh"
|
||||
|
||||
type RegisterReq struct {
|
||||
BaseURL string `json:"public_url"`
|
||||
MeshURL string `json:"mesh_url"`
|
||||
NodeID string `json:"node_id"`
|
||||
TTL int `json:"ttl"`
|
||||
}
|
||||
|
||||
type PeersResp struct {
|
||||
Peers []mesh.NodeInfo `json:"peers"`
|
||||
}
|
||||
Reference in New Issue
Block a user