74 lines
1.8 KiB
Go
74 lines
1.8 KiB
Go
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})
|
|
}
|