init
Some checks failed
release-tag / release-image (push) Failing after 1m28s

This commit is contained in:
2025-09-24 10:32:22 +02:00
parent b851b57e28
commit dc3abf661f
17 changed files with 1008 additions and 0 deletions

55
internal/beacon/client.go Normal file
View 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
View 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: &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})
}

14
internal/beacon/types.go Normal file
View 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"`
}