jrouter/route.go

89 lines
1.6 KiB
Go
Raw Normal View History

2024-04-12 16:14:27 +10:00
package main
import (
"cmp"
"fmt"
"slices"
"sync"
"time"
"github.com/sfiera/multitalk/pkg/ddp"
)
2024-04-14 13:44:35 +10:00
const maxRouteAge = 10 * time.Minute // TODO: confirm
2024-04-12 16:14:27 +10:00
type route struct {
2024-04-13 15:47:58 +10:00
extended bool
netStart ddp.Network
netEnd ddp.Network
peer *peer
metric uint8
last time.Time
2024-04-12 16:14:27 +10:00
}
2024-04-14 13:44:35 +10:00
type routingTable struct {
tableMu sync.Mutex
table map[ddp.Network][]*route
2024-04-13 15:47:58 +10:00
allRoutesMu sync.Mutex
2024-04-14 13:44:35 +10:00
allRoutes map[*route]struct{}
}
2024-04-12 16:14:27 +10:00
2024-04-14 13:44:35 +10:00
func (rt *routingTable) lookupRoute(network ddp.Network) *route {
rt.tableMu.Lock()
defer rt.tableMu.Unlock()
2024-04-12 16:14:27 +10:00
2024-04-14 13:44:35 +10:00
for _, rs := range rt.table[network] {
if time.Since(rs.last) > maxRouteAge {
continue
}
return rs
2024-04-12 16:14:27 +10:00
}
2024-04-14 13:44:35 +10:00
return nil
2024-04-12 16:14:27 +10:00
}
2024-04-14 13:44:35 +10:00
func (rt *routingTable) upsertRoutes(extended bool, netStart, netEnd ddp.Network, peer *peer, metric uint8) error {
2024-04-12 16:14:27 +10:00
if netStart > netEnd {
return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd)
}
2024-04-14 13:44:35 +10:00
2024-04-12 16:14:27 +10:00
r := &route{
2024-04-13 15:47:58 +10:00
extended: extended,
netStart: netStart,
netEnd: netEnd,
peer: peer,
metric: metric,
last: time.Now(),
2024-04-12 16:14:27 +10:00
}
2024-04-14 13:44:35 +10:00
rt.allRoutesMu.Lock()
rt.allRoutes[r] = struct{}{}
rt.allRoutesMu.Unlock()
2024-04-13 15:47:58 +10:00
2024-04-14 13:44:35 +10:00
rt.tableMu.Lock()
defer rt.tableMu.Unlock()
2024-04-12 16:14:27 +10:00
for n := netStart; n <= netEnd; n++ {
2024-04-14 13:44:35 +10:00
rt.table[n] = append(rt.table[n], r)
slices.SortFunc(rt.table[n], func(r, s *route) int {
2024-04-12 16:14:27 +10:00
return cmp.Compare(r.metric, s.metric)
})
}
return nil
}
2024-04-14 13:44:35 +10:00
func (rt *routingTable) validRoutes() []*route {
rt.allRoutesMu.Lock()
defer rt.allRoutesMu.Unlock()
valid := make([]*route, 0, len(rt.allRoutes))
for r := range rt.allRoutes {
if r.peer == nil {
continue
}
if time.Since(r.last) > maxRouteAge {
continue
}
valid = append(valid, r)
}
2024-04-14 13:45:05 +10:00
return valid
2024-04-14 13:44:35 +10:00
}