Files
jbergner dc3abf661f
Some checks failed
release-tag / release-image (push) Failing after 1m28s
init
2025-09-24 10:32:22 +02:00

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: &registry{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})
}