Start routing table
This commit is contained in:
parent
10c447c78d
commit
1a83e4d543
5 changed files with 98 additions and 9 deletions
|
@ -79,6 +79,14 @@ func Unmarshal(data []byte) (*Packet, error) {
|
||||||
NBPID: data[1],
|
NBPID: data[1],
|
||||||
}
|
}
|
||||||
tupleCount := data[0] & 0x0F
|
tupleCount := data[0] & 0x0F
|
||||||
|
if tupleCount == 0 {
|
||||||
|
return nil, fmt.Errorf("no tuples")
|
||||||
|
}
|
||||||
|
// Only LkUp-Reply can have more than 1 tuple
|
||||||
|
if tupleCount > 1 && p.Function != FunctionLkUpReply {
|
||||||
|
return nil, fmt.Errorf("wrong number of tuples %d for function %s", tupleCount, p.Function)
|
||||||
|
}
|
||||||
|
|
||||||
data = data[2:]
|
data = data[2:]
|
||||||
for range tupleCount {
|
for range tupleCount {
|
||||||
if len(data) < 8 {
|
if len(data) < 8 {
|
||||||
|
@ -144,7 +152,7 @@ func (t *Tuple) writeTo(b *bytes.Buffer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tuple) String() string {
|
func (t Tuple) String() string {
|
||||||
return fmt.Sprintf("%d.%d.%d (enum %d) <-> %s:%s@%s",
|
return fmt.Sprintf("%d.%d.%d (enum %d) <-> %s:%s@%s",
|
||||||
t.Network, t.Node, t.Socket, t.Enumerator, t.Object, t.Type, t.Zone,
|
t.Network, t.Node, t.Socket, t.Enumerator, t.Object, t.Type, t.Zone,
|
||||||
)
|
)
|
||||||
|
|
|
@ -102,6 +102,14 @@ func (tr *Transport) sequenced(connID, seq uint16) TrHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAppleTalkPacket returns a new AppleTalkPacket.
|
||||||
|
func (tr *Transport) NewAppleTalkPacket(data []byte) *AppleTalkPacket {
|
||||||
|
return &AppleTalkPacket{
|
||||||
|
DomainHeader: tr.domainHeader(PacketTypeAppleTalk),
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewOpenReqPacket returns a new Open-Req packet structure. By default it sets
|
// NewOpenReqPacket returns a new Open-Req packet structure. By default it sets
|
||||||
// all SUI flags and uses version 1.
|
// all SUI flags and uses version 1.
|
||||||
func (tr *Transport) NewOpenReqPacket(opts Options) *OpenReqPacket {
|
func (tr *Transport) NewOpenReqPacket(opts Options) *OpenReqPacket {
|
||||||
|
|
30
main.go
30
main.go
|
@ -128,7 +128,7 @@ func main() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------- Configured peer setup ---------------
|
// ------------------------- Configured peer setup ------------------------
|
||||||
for _, peerStr := range cfg.Peers {
|
for _, peerStr := range cfg.Peers {
|
||||||
if !hasPortRE.MatchString(peerStr) {
|
if !hasPortRE.MatchString(peerStr) {
|
||||||
peerStr += ":387"
|
peerStr += ":387"
|
||||||
|
@ -156,12 +156,12 @@ func main() {
|
||||||
goPeerHandler(peer)
|
goPeerHandler(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- AARP --------------------
|
// --------------------------------- AARP ---------------------------------
|
||||||
aarpMachine := NewAARPMachine(cfg, pcapHandle, myHWAddr)
|
aarpMachine := NewAARPMachine(cfg, pcapHandle, myHWAddr)
|
||||||
aarpCh := make(chan *ethertalk.Packet, 1024)
|
aarpCh := make(chan *ethertalk.Packet, 1024)
|
||||||
go aarpMachine.Run(ctx, aarpCh)
|
go aarpMachine.Run(ctx, aarpCh)
|
||||||
|
|
||||||
// -------------------- RTMP --------------------
|
// --------------------------------- RTMP ---------------------------------
|
||||||
rtmpMachine := &RTMPMachine{
|
rtmpMachine := &RTMPMachine{
|
||||||
aarp: aarpMachine,
|
aarp: aarpMachine,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
@ -170,7 +170,7 @@ func main() {
|
||||||
rtmpCh := make(chan *ddp.ExtPacket, 1024)
|
rtmpCh := make(chan *ddp.ExtPacket, 1024)
|
||||||
go rtmpMachine.Run(ctx, rtmpCh)
|
go rtmpMachine.Run(ctx, rtmpCh)
|
||||||
|
|
||||||
// --------------------- NBP --------------------
|
// ---------------------------------- NBP ---------------------------------
|
||||||
nbpMachine := &NBPMachine{
|
nbpMachine := &NBPMachine{
|
||||||
aarp: aarpMachine,
|
aarp: aarpMachine,
|
||||||
pcapHandle: pcapHandle,
|
pcapHandle: pcapHandle,
|
||||||
|
@ -178,7 +178,7 @@ func main() {
|
||||||
nbpCh := make(chan *ddp.ExtPacket, 1024)
|
nbpCh := make(chan *ddp.ExtPacket, 1024)
|
||||||
go nbpMachine.Run(ctx, nbpCh)
|
go nbpMachine.Run(ctx, nbpCh)
|
||||||
|
|
||||||
// ---------- Raw AppleTalk/AARP inbound ----------
|
// ---------------------- Raw AppleTalk/AARP inbound ----------------------
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
|
@ -235,12 +235,28 @@ func main() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: If the packet is NBP BrRq and for a zone we have in
|
||||||
|
// our zone info table, convert it to a FwdReq and send that
|
||||||
|
// out to the peer
|
||||||
|
// TODO: implement the zone information table
|
||||||
|
|
||||||
// Our network?
|
// Our network?
|
||||||
// "The network number 0 is reserved to mean unknown; by default
|
// "The network number 0 is reserved to mean unknown; by default
|
||||||
// it specifies the local network to which the node is
|
// it specifies the local network to which the node is
|
||||||
// connected. Packets whose destination network number is 0 are
|
// connected. Packets whose destination network number is 0 are
|
||||||
// addressed to a node on the local network."
|
// addressed to a node on the local network."
|
||||||
if ddpkt.DstNet != 0 && ddpkt.DstNet != myAddr.Proto.Network {
|
if ddpkt.DstNet != 0 && (ddpkt.DstNet < cfg.EtherTalk.NetStart || ddpkt.DstNet > cfg.EtherTalk.NetEnd) {
|
||||||
|
// Is it for a network in the routing table?
|
||||||
|
rt := lookupRoute(ddpkt.DstNet)
|
||||||
|
if rt == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encap ethPacket.Payload into an AURP packet
|
||||||
|
if _, err := rt.peer.send(rt.peer.tr.NewAppleTalkPacket(ethFrame.Payload)); err != nil {
|
||||||
|
log.Printf("DDP: Couldn't forward packet to AURP peer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +291,7 @@ func main() {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// ---------- AURP inbound ----------
|
// ----------------------------- AURP inbound -----------------------------
|
||||||
for {
|
for {
|
||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
return
|
return
|
||||||
|
|
5
peer.go
5
peer.go
|
@ -24,6 +24,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.drjosh.dev/josh/jrouter/aurp"
|
"gitea.drjosh.dev/josh/jrouter/aurp"
|
||||||
|
"github.com/sfiera/multitalk/pkg/ddp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -275,7 +276,9 @@ func (p *peer) handle(ctx context.Context) error {
|
||||||
|
|
||||||
log.Printf("Learned about these networks: %v", pkt.Networks)
|
log.Printf("Learned about these networks: %v", pkt.Networks)
|
||||||
|
|
||||||
// TODO: Integrate info into route table
|
for _, nt := range pkt.Networks {
|
||||||
|
upsertRoutes(ddp.Network(nt.RangeStart), ddp.Network(nt.RangeEnd), p, nt.Distance)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: track which networks we don't have zone info for, and
|
// TODO: track which networks we don't have zone info for, and
|
||||||
// only set SZI for those ?
|
// only set SZI for those ?
|
||||||
|
|
54
route.go
Normal file
54
route.go
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmp"
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sfiera/multitalk/pkg/ddp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type route struct {
|
||||||
|
peer *peer
|
||||||
|
metric uint8
|
||||||
|
last time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
routingTableMu sync.Mutex
|
||||||
|
routingTable = make(map[ddp.Network][]*route)
|
||||||
|
)
|
||||||
|
|
||||||
|
func lookupRoute(network ddp.Network) *route {
|
||||||
|
routingTableMu.Lock()
|
||||||
|
defer routingTableMu.Unlock()
|
||||||
|
|
||||||
|
rs := routingTable[network]
|
||||||
|
if len(rs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return rs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func upsertRoutes(netStart, netEnd ddp.Network, peer *peer, metric uint8) error {
|
||||||
|
if netStart > netEnd {
|
||||||
|
return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd)
|
||||||
|
}
|
||||||
|
r := &route{
|
||||||
|
peer: peer,
|
||||||
|
metric: metric,
|
||||||
|
last: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
routingTableMu.Lock()
|
||||||
|
defer routingTableMu.Unlock()
|
||||||
|
for n := netStart; n <= netEnd; n++ {
|
||||||
|
routingTable[n] = append(routingTable[n], r)
|
||||||
|
slices.SortFunc(routingTable[n], func(r, s *route) int {
|
||||||
|
return cmp.Compare(r.metric, s.metric)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue