diff --git a/main.go b/main.go
index e55337a..4643ba2 100644
--- a/main.go
+++ b/main.go
@@ -45,6 +45,27 @@ import (
"github.com/sfiera/multitalk/pkg/ethertalk"
)
+const routingTableTemplate = `
+
+
+ Network range |
+ Extended? |
+ Distance |
+ Last seen |
+ |
+
+{{range $route := . }}
+
+ {{$route.NetStart}}{{if not (eq $route.NetStart $route.NetEnd)}} - {{$route.NetEnd}}{{end}} |
+ {{if $route.Extended}}✅{{else}}❌{{end}} |
+ {{$route.Distance}} |
+ {{$route.LastSeenAgo}} |
+
+{{end}}
+
+
+`
+
var hasPortRE = regexp.MustCompile(`:\d+$`)
var configFilePath = flag.String("config", "jrouter.yaml", "Path to configuration file to use")
@@ -143,6 +164,11 @@ func main() {
// -------------------------------- Tables --------------------------------
routes := router.NewRoutingTable()
+ _, done := status.AddItem(ctx, "Routing table", routingTableTemplate, func(context.Context) (any, error) {
+ return routes.Dump(), nil
+ })
+ defer done()
+
zones := router.NewZoneTable()
zones.Upsert(cfg.EtherTalk.NetStart, cfg.EtherTalk.ZoneName, true)
diff --git a/router/route.go b/router/route.go
index 7ef9c72..17207b6 100644
--- a/router/route.go
+++ b/router/route.go
@@ -35,6 +35,13 @@ type Route struct {
LastSeen time.Time
}
+func (r Route) LastSeenAgo() string {
+ if r.LastSeen.IsZero() {
+ return "never"
+ }
+ return fmt.Sprintf("%v ago", time.Since(r.LastSeen).Truncate(time.Millisecond))
+}
+
type RoutingTable struct {
mu sync.Mutex
routes map[*Route]struct{}
@@ -46,6 +53,17 @@ func NewRoutingTable() *RoutingTable {
}
}
+func (rt *RoutingTable) Dump() []Route {
+ rt.mu.Lock()
+ defer rt.mu.Unlock()
+
+ table := make([]Route, 0, len(rt.routes))
+ for r := range rt.routes {
+ table = append(table, *r)
+ }
+ return table
+}
+
func (rt *RoutingTable) LookupRoute(network ddp.Network) *Route {
rt.mu.Lock()
defer rt.mu.Unlock()
diff --git a/status/status.go b/status/status.go
index 1246581..1c66193 100644
--- a/status/status.go
+++ b/status/status.go
@@ -229,7 +229,7 @@ func Handle(w http.ResponseWriter, r *http.Request) {
// AddItem adds an item to be displayed on the status page. On each page load,
// the item's callback is called, and the data returned used to fill the
// HTML template in tmpl. The title should be unique (among items under this
-// parent.
+// parent).
func AddItem(parent context.Context, title, tmpl string, cb func(context.Context) (any, error)) (context.Context, func()) {
if cb == nil {
cb = func(context.Context) (any, error) { return nil, nil }