Start massive refactor

This commit is contained in:
Josh Deprez 2024-04-19 14:57:25 +10:00
parent c81c6002f8
commit 52b08a83f1
No known key found for this signature in database
12 changed files with 213 additions and 160 deletions

83
main.go
View File

@ -32,6 +32,8 @@ import (
"time"
"gitea.drjosh.dev/josh/jrouter/aurp"
"gitea.drjosh.dev/josh/jrouter/router"
"github.com/google/gopacket/pcap"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
@ -46,7 +48,7 @@ func main() {
flag.Parse()
log.Println("jrouter")
cfg, err := loadConfig(*configFilePath)
cfg, err := router.LoadConfig(*configFilePath)
if err != nil {
log.Fatalf("Couldn't load configuration file: %v", err)
}
@ -80,7 +82,7 @@ func main() {
log.Printf("EtherTalk configuration: %+v", cfg.EtherTalk)
peers := make(map[udpAddr]*peer)
peers := make(map[udpAddr]*router.Peer)
var nextConnID uint16
for nextConnID == 0 {
nextConnID = uint16(rand.IntN(0x10000))
@ -131,17 +133,17 @@ func main() {
handlersWG.Wait()
ln.Close()
}()
goPeerHandler := func(p *peer) {
goPeerHandler := func(p *router.Peer) {
handlersWG.Add(1)
go func() {
defer handlersWG.Done()
p.handle(ctx)
p.Handle(ctx)
}()
}
// -------------------------------- Tables --------------------------------
routing := NewRoutingTable()
zones := NewZoneTable()
routing := router.NewRoutingTable()
zones := router.NewZoneTable()
zones.Upsert(cfg.EtherTalk.NetStart, cfg.EtherTalk.ZoneName, true)
// ------------------------- Configured peer setup ------------------------
@ -156,18 +158,18 @@ func main() {
}
log.Printf("resolved %q to %v", peerStr, raddr)
peer := &peer{
cfg: cfg,
tr: &aurp.Transport{
peer := &router.Peer{
Config: cfg,
Transport: &aurp.Transport{
LocalDI: localDI,
RemoteDI: aurp.IPDomainIdentifier(raddr.IP),
LocalConnID: nextConnID,
},
conn: ln,
raddr: raddr,
recv: make(chan aurp.Packet, 1024),
routingTable: routing,
zoneTable: zones,
UDPConn: ln,
RemoteAddr: raddr,
RecieveCh: make(chan aurp.Packet, 1024),
RoutingTable: routing,
ZoneTable: zones,
}
aurp.Inc(&nextConnID)
peers[udpAddrFromNet(raddr)] = peer
@ -175,20 +177,30 @@ func main() {
}
// --------------------------------- AARP ---------------------------------
aarpMachine := NewAARPMachine(cfg, pcapHandle, myHWAddr)
aarpMachine := router.NewAARPMachine(cfg, pcapHandle, myHWAddr)
aarpCh := make(chan *ethertalk.Packet, 1024)
go aarpMachine.Run(ctx, aarpCh)
// --------------------------------- RTMP ---------------------------------
rtmpMachine := &RTMPMachine{
aarp: aarpMachine,
cfg: cfg,
pcapHandle: pcapHandle,
routingTable: routing,
rtmpMachine := &router.RTMPMachine{
AARP: aarpMachine,
Config: cfg,
PcapHandle: pcapHandle,
RoutingTable: routing,
}
rtmpCh := make(chan *ddp.ExtPacket, 1024)
go rtmpMachine.Run(ctx, rtmpCh)
// -------------------------------- Router --------------------------------
rooter := &router.Router{
Config: cfg,
PcapHandle: pcapHandle,
MyHWAddr: myHWAddr,
// MyDDPAddr: ...,
RouteTable: routing,
ZoneTable: zones,
}
// ---------------------- Raw AppleTalk/AARP inbound ----------------------
go func() {
for {
@ -249,6 +261,7 @@ func main() {
if !ok {
continue
}
rooter.MyDDPAddr = myAddr.Proto
// Our network?
// "The network number 0 is reserved to mean unknown; by default
@ -264,8 +277,8 @@ func main() {
}
// Encap ethPacket.Payload into an AURP packet
log.Printf("DDP: forwarding to AURP peer %v", rt.Peer.tr.RemoteDI)
if _, err := rt.Peer.send(rt.Peer.tr.NewAppleTalkPacket(ethFrame.Payload)); err != nil {
log.Printf("DDP: forwarding to AURP peer %v", rt.Peer.Transport.RemoteDI)
if _, err := rt.Peer.Send(rt.Peer.Transport.NewAppleTalkPacket(ethFrame.Payload)); err != nil {
log.Printf("DDP: Couldn't forward packet to AURP peer: %v", err)
}
@ -285,17 +298,17 @@ func main() {
rtmpCh <- ddpkt
case 2: // The NIS (name information socket / NBP socket)
if err := handleNBP(pcapHandle, myHWAddr, ethFrame.Src, myAddr, zones, routing, cfg, ddpkt); err != nil {
if err := rooter.HandleNBP(ethFrame.Src, ddpkt); err != nil {
log.Printf("NBP: Couldn't handle: %v", err)
}
case 4: // The AEP socket
if err := handleAEP(pcapHandle, myHWAddr, ethFrame.Src, ddpkt); err != nil {
if err := rooter.HandleAEP(ethFrame.Src, ddpkt); err != nil {
log.Printf("AEP: Couldn't handle: %v", err)
}
case 6: // The ZIS (zone information socket / ZIP socket)
if err := handleZIP(pcapHandle, ethFrame.Src, myHWAddr, myAddr, cfg, zones, ddpkt); err != nil {
if err := rooter.HandleZIP(ethFrame.Src, ddpkt); err != nil {
log.Printf("ZIP: couldn't handle: %v", err)
}
@ -375,7 +388,7 @@ func main() {
continue
}
// It's NBP
if err := handleNBPInAURP(pcapHandle, myHWAddr, ddpkt); err != nil {
if err := rooter.HandleNBPInAURP(ddpkt); err != nil {
log.Printf("NBP/DDP/AURP: %v", err)
}
continue
@ -413,18 +426,18 @@ func main() {
pr := peers[ra]
if pr == nil {
// New peer!
pr = &peer{
cfg: cfg,
tr: &aurp.Transport{
pr = &router.Peer{
Config: cfg,
Transport: &aurp.Transport{
LocalDI: localDI,
RemoteDI: dh.SourceDI, // platinum rule
LocalConnID: nextConnID,
},
conn: ln,
raddr: raddr,
recv: make(chan aurp.Packet, 1024),
routingTable: routing,
zoneTable: zones,
UDPConn: ln,
RemoteAddr: raddr,
RecieveCh: make(chan aurp.Packet, 1024),
RoutingTable: routing,
ZoneTable: zones,
}
aurp.Inc(&nextConnID)
peers[ra] = pr
@ -433,7 +446,7 @@ func main() {
// Pass the packet to the goroutine in charge of this peer.
select {
case pr.recv <- pkt:
case pr.RecieveCh <- pkt:
// That's it for us.
case <-ctx.Done():

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"context"
@ -44,7 +44,7 @@ const (
type AARPMachine struct {
*addressMappingTable
cfg *config
cfg *Config
pcapHandle *pcap.Handle
// The Run goroutine is responsible for all writes to myAddr.Proto and
@ -58,7 +58,7 @@ type AARPMachine struct {
}
// NewAARPMachine creates a new AARPMachine.
func NewAARPMachine(cfg *config, pcapHandle *pcap.Handle, myHWAddr ethernet.Addr) *AARPMachine {
func NewAARPMachine(cfg *Config, pcapHandle *pcap.Handle, myHWAddr ethernet.Addr) *AARPMachine {
return &AARPMachine{
addressMappingTable: new(addressMappingTable),
cfg: cfg,

View File

@ -14,19 +14,18 @@
limitations under the License.
*/
package main
package router
import (
"fmt"
"gitea.drjosh.dev/josh/jrouter/atalk/aep"
"github.com/google/gopacket/pcap"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
"github.com/sfiera/multitalk/pkg/ethertalk"
)
func handleAEP(pcapHandle *pcap.Handle, src, dst ethernet.Addr, ddpkt *ddp.ExtPacket) error {
func (rtr *Router) HandleAEP(src ethernet.Addr, ddpkt *ddp.ExtPacket) error {
if ddpkt.Proto != ddp.ProtoAEP {
return fmt.Errorf("invalid DDP type %d on socket 4", ddpkt.Proto)
}
@ -49,16 +48,16 @@ func handleAEP(pcapHandle *pcap.Handle, src, dst ethernet.Addr, ddpkt *ddp.ExtPa
ddpkt.DstSocket, ddpkt.SrcSocket = ddpkt.SrcSocket, ddpkt.DstSocket
ddpkt.Data[0] = byte(aep.EchoReply)
ethFrame, err := ethertalk.AppleTalk(src, *ddpkt)
ethFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, *ddpkt)
if err != nil {
return err
}
ethFrame.Dst = dst
ethFrame.Dst = src
ethFrameRaw, err := ethertalk.Marshal(*ethFrame)
if err != nil {
return err
}
return pcapHandle.WritePacketData(ethFrameRaw)
return rtr.PcapHandle.WritePacketData(ethFrameRaw)
default:
return fmt.Errorf("invalid AEP function %d", ep.Function)

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"os"
@ -23,7 +23,7 @@ import (
"gopkg.in/yaml.v3"
)
type config struct {
type Config struct {
// Optional: default is 387.
ListenPort uint16 `yaml:"listen_port"`
@ -55,14 +55,14 @@ type config struct {
Peers []string `yaml:"peers"`
}
func loadConfig(cfgPath string) (*config, error) {
func LoadConfig(cfgPath string) (*Config, error) {
f, err := os.Open(cfgPath)
if err != nil {
return nil, err
}
defer f.Close()
c := new(config)
c := new(Config)
if err := yaml.NewDecoder(f).Decode(c); err != nil {
return nil, err
}

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"fmt"
@ -22,14 +22,12 @@ import (
"gitea.drjosh.dev/josh/jrouter/atalk"
"gitea.drjosh.dev/josh/jrouter/atalk/nbp"
"github.com/google/gopacket/pcap"
"github.com/sfiera/multitalk/pkg/aarp"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
"github.com/sfiera/multitalk/pkg/ethertalk"
)
func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAddr aarp.AddrPair, zoneTable *ZoneTable, routeTable *RoutingTable, cfg *config, ddpkt *ddp.ExtPacket) error {
func (rtr *Router) HandleNBP(srcHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) error {
if ddpkt.Proto != ddp.ProtoNBP {
return fmt.Errorf("invalid DDP type %d on socket 2", ddpkt.Proto)
}
@ -51,7 +49,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
if tuple.Type != "AppleRouter" && tuple.Type != "=" {
return nil
}
if tuple.Zone != cfg.EtherTalk.ZoneName && tuple.Zone != "*" && tuple.Zone != "" {
if tuple.Zone != rtr.Config.EtherTalk.ZoneName && tuple.Zone != "*" && tuple.Zone != "" {
return nil
}
respPkt := &nbp.Packet{
@ -59,13 +57,13 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
NBPID: nbpkt.NBPID,
Tuples: []nbp.Tuple{
{
Network: myAddr.Proto.Network,
Node: myAddr.Proto.Node,
Network: rtr.MyDDPAddr.Network,
Node: rtr.MyDDPAddr.Node,
Socket: 253,
Enumerator: 0,
Object: "jrouter",
Type: "AppleRouter",
Zone: cfg.EtherTalk.ZoneName,
Zone: rtr.Config.EtherTalk.ZoneName,
},
},
}
@ -80,13 +78,13 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
DstNet: ddpkt.SrcNet,
DstNode: ddpkt.SrcNode,
DstSocket: ddpkt.SrcSocket,
SrcNet: myAddr.Proto.Network,
SrcNode: myAddr.Proto.Node,
SrcNet: rtr.MyDDPAddr.Network,
SrcNode: rtr.MyDDPAddr.Node,
SrcSocket: 2,
},
Data: respRaw,
}
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
if err != nil {
return err
}
@ -95,7 +93,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
if err != nil {
return err
}
return pcapHandle.WritePacketData(outFrameRaw)
return rtr.PcapHandle.WritePacketData(outFrameRaw)
case nbp.FunctionBrRq:
// There must be 1!
@ -105,7 +103,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
ethDst = atalk.MulticastAddr(tuple.Zone)
}
zones := zoneTable.LookupName(tuple.Zone)
zones := rtr.ZoneTable.LookupName(tuple.Zone)
for _, z := range zones {
if z.Local {
// If it's for the local zone, translate it to a LkUp and broadcast it back
@ -127,7 +125,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
outDDP.DstNode = 0xFF // Broadcast node address within the dest network
outDDP.Data = nbpRaw
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
if err != nil {
return err
}
@ -136,14 +134,14 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
if err != nil {
return err
}
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
if err := rtr.PcapHandle.WritePacketData(outFrameRaw); err != nil {
return err
}
continue
}
route := routeTable.LookupRoute(z.Network)
route := rtr.RouteTable.LookupRoute(z.Network)
if route == nil {
return fmt.Errorf("no route for network %d", z.Network)
}
@ -171,7 +169,7 @@ func handleNBP(pcapHandle *pcap.Handle, myHWAddr, srcHWAddr ethernet.Addr, myAdd
return err
}
if _, err := peer.send(peer.tr.NewAppleTalkPacket(outDDPRaw)); err != nil {
if _, err := peer.Send(peer.Transport.NewAppleTalkPacket(outDDPRaw)); err != nil {
return fmt.Errorf("sending FwdReq on to peer: %w", err)
}
}

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"fmt"
@ -22,13 +22,11 @@ import (
"gitea.drjosh.dev/josh/jrouter/atalk"
"gitea.drjosh.dev/josh/jrouter/atalk/nbp"
"github.com/google/gopacket/pcap"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
"github.com/sfiera/multitalk/pkg/ethertalk"
)
func handleNBPInAURP(pcapHandle *pcap.Handle, myHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) error {
func (rtr *Router) HandleNBPInAURP(ddpkt *ddp.ExtPacket) error {
if ddpkt.Proto != ddp.ProtoNBP {
return fmt.Errorf("invalid DDP type %d on socket 2", ddpkt.Proto)
}
@ -63,7 +61,7 @@ func handleNBPInAURP(pcapHandle *pcap.Handle, myHWAddr ethernet.Addr, ddpkt *ddp
ddpkt.DstNode = 0xFF // Broadcast node address within the dest network
ddpkt.Data = nbpRaw
outFrame, err := ethertalk.AppleTalk(myHWAddr, *ddpkt)
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, *ddpkt)
if err != nil {
return err
}
@ -74,5 +72,5 @@ func handleNBPInAURP(pcapHandle *pcap.Handle, myHWAddr ethernet.Addr, ddpkt *ddp
if err != nil {
return err
}
return pcapHandle.WritePacketData(outFrameRaw)
return rtr.PcapHandle.WritePacketData(outFrameRaw)
}

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"bytes"
@ -75,28 +75,27 @@ func (ss senderState) String() string {
}[ss]
}
type peer struct {
cfg *config
tr *aurp.Transport
conn *net.UDPConn
raddr *net.UDPAddr
recv chan aurp.Packet
routingTable *RoutingTable
zoneTable *ZoneTable
type Peer struct {
Config *Config
Transport *aurp.Transport
UDPConn *net.UDPConn
RemoteAddr *net.UDPAddr
RecieveCh chan aurp.Packet
RoutingTable *RoutingTable
ZoneTable *ZoneTable
}
// send encodes and sends pkt to the remote host.
func (p *peer) send(pkt aurp.Packet) (int, error) {
// Send encodes and sends pkt to the remote host.
func (p *Peer) Send(pkt aurp.Packet) (int, error) {
var b bytes.Buffer
if _, err := pkt.WriteTo(&b); err != nil {
return 0, err
}
log.Printf("Sending %T (len %d) to %v", pkt, b.Len(), p.raddr)
return p.conn.WriteToUDP(b.Bytes(), p.raddr)
log.Printf("Sending %T (len %d) to %v", pkt, b.Len(), p.RemoteAddr)
return p.UDPConn.WriteToUDP(b.Bytes(), p.RemoteAddr)
}
func (p *peer) handle(ctx context.Context) error {
func (p *Peer) Handle(ctx context.Context) error {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
@ -108,7 +107,7 @@ func (p *peer) handle(ctx context.Context) error {
sstate := ssUnconnected
// Write an Open-Req packet
if _, err := p.send(p.tr.NewOpenReqPacket(nil)); err != nil {
if _, err := p.Send(p.Transport.NewOpenReqPacket(nil)); err != nil {
log.Printf("Couldn't send Open-Req packet: %v", err)
return err
}
@ -123,7 +122,7 @@ func (p *peer) handle(ctx context.Context) error {
return ctx.Err()
}
// Send a best-effort Router Down before returning
if _, err := p.send(p.tr.NewRDPacket(aurp.ErrCodeNormalClose)); err != nil {
if _, err := p.Send(p.Transport.NewRDPacket(aurp.ErrCodeNormalClose)); err != nil {
log.Printf("Couldn't send RD packet: %v", err)
}
return ctx.Err()
@ -143,7 +142,7 @@ func (p *peer) handle(ctx context.Context) error {
// Send another Open-Req
sendRetries++
lastSend = time.Now()
if _, err := p.send(p.tr.NewOpenReqPacket(nil)); err != nil {
if _, err := p.Send(p.Transport.NewOpenReqPacket(nil)); err != nil {
log.Printf("Couldn't send Open-Req packet: %v", err)
return err
}
@ -153,7 +152,7 @@ func (p *peer) handle(ctx context.Context) error {
if time.Since(lastHeardFrom) <= lastHeardFromTimer {
break
}
if _, err := p.send(p.tr.NewTicklePacket()); err != nil {
if _, err := p.Send(p.Transport.NewTicklePacket()); err != nil {
log.Printf("Couldn't send Tickle: %v", err)
return err
}
@ -173,7 +172,7 @@ func (p *peer) handle(ctx context.Context) error {
sendRetries++
lastSend = time.Now()
if _, err := p.send(p.tr.NewTicklePacket()); err != nil {
if _, err := p.Send(p.Transport.NewTicklePacket()); err != nil {
log.Printf("Couldn't send Tickle: %v", err)
return err
}
@ -185,7 +184,7 @@ func (p *peer) handle(ctx context.Context) error {
// TODO
}
case pkt := <-p.recv:
case pkt := <-p.RecieveCh:
lastHeardFrom = time.Now()
switch pkt := pkt.(type) {
@ -195,25 +194,25 @@ func (p *peer) handle(ctx context.Context) error {
}
// The peer tells us their connection ID in Open-Req.
p.tr.RemoteConnID = pkt.ConnectionID
p.Transport.RemoteConnID = pkt.ConnectionID
// Formulate a response.
var orsp *aurp.OpenRspPacket
switch {
case pkt.Version != 1:
// Respond with Open-Rsp with unknown version error.
orsp = p.tr.NewOpenRspPacket(0, int16(aurp.ErrCodeInvalidVersion), nil)
orsp = p.Transport.NewOpenRspPacket(0, int16(aurp.ErrCodeInvalidVersion), nil)
case len(pkt.Options) > 0:
// Options? OPTIONS? We don't accept no stinkin' _options_
orsp = p.tr.NewOpenRspPacket(0, int16(aurp.ErrCodeOptionNegotiation), nil)
orsp = p.Transport.NewOpenRspPacket(0, int16(aurp.ErrCodeOptionNegotiation), nil)
default:
// Accept it I guess.
orsp = p.tr.NewOpenRspPacket(0, 1, nil)
orsp = p.Transport.NewOpenRspPacket(0, 1, nil)
}
if _, err := p.send(orsp); err != nil {
if _, err := p.Send(orsp); err != nil {
log.Printf("Couldn't send Open-Rsp: %v", err)
return err
}
@ -225,7 +224,7 @@ func (p *peer) handle(ctx context.Context) error {
if rstate == rsUnconnected {
lastSend = time.Now()
sendRetries = 0
if _, err := p.send(p.tr.NewOpenReqPacket(nil)); err != nil {
if _, err := p.Send(p.Transport.NewOpenReqPacket(nil)); err != nil {
log.Printf("Couldn't send Open-Req packet: %v", err)
return err
}
@ -238,7 +237,7 @@ func (p *peer) handle(ctx context.Context) error {
}
if pkt.RateOrErrCode < 0 {
// It's an error code.
log.Printf("Open-Rsp error code from peer %v: %d", p.raddr.IP, pkt.RateOrErrCode)
log.Printf("Open-Rsp error code from peer %v: %d", p.RemoteAddr.IP, pkt.RateOrErrCode)
rstate = rsUnconnected
break
}
@ -246,7 +245,7 @@ func (p *peer) handle(ctx context.Context) error {
rstate = rsConnected
// Send an RI-Req
if _, err := p.send(p.tr.NewRIReqPacket()); err != nil {
if _, err := p.Send(p.Transport.NewRIReqPacket()); err != nil {
log.Printf("Couldn't send RI-Req packet: %v", err)
return err
}
@ -260,13 +259,13 @@ func (p *peer) handle(ctx context.Context) error {
nets := aurp.NetworkTuples{
{
Extended: true,
RangeStart: uint16(p.cfg.EtherTalk.NetStart),
RangeEnd: uint16(p.cfg.EtherTalk.NetEnd),
RangeStart: uint16(p.Config.EtherTalk.NetStart),
RangeEnd: uint16(p.Config.EtherTalk.NetEnd),
Distance: 0,
},
}
p.tr.LocalSeq = 1
if _, err := p.send(p.tr.NewRIRspPacket(aurp.RoutingFlagLast, nets)); err != nil {
p.Transport.LocalSeq = 1
if _, err := p.Send(p.Transport.NewRIRspPacket(aurp.RoutingFlagLast, nets)); err != nil {
log.Printf("Couldn't send RI-Rsp packet: %v", err)
return err
}
@ -280,7 +279,7 @@ func (p *peer) handle(ctx context.Context) error {
log.Printf("Learned about these networks: %v", pkt.Networks)
for _, nt := range pkt.Networks {
p.routingTable.UpsertRoute(
p.RoutingTable.UpsertRoute(
nt.Extended,
ddp.Network(nt.RangeStart),
ddp.Network(nt.RangeEnd),
@ -291,7 +290,7 @@ func (p *peer) handle(ctx context.Context) error {
// TODO: track which networks we don't have zone info for, and
// only set SZI for those ?
if _, err := p.send(p.tr.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, aurp.RoutingFlagSendZoneInfo)); err != nil {
if _, err := p.Send(p.Transport.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, aurp.RoutingFlagSendZoneInfo)); err != nil {
log.Printf("Couldn't send RI-Ack packet: %v", err)
return err
}
@ -324,11 +323,11 @@ func (p *peer) handle(ctx context.Context) error {
if pkt.Flags&aurp.RoutingFlagSendZoneInfo != 0 {
zones := aurp.ZoneTuples{
{
Network: uint16(p.cfg.EtherTalk.NetStart),
Name: p.cfg.EtherTalk.ZoneName,
Network: uint16(p.Config.EtherTalk.NetStart),
Name: p.Config.EtherTalk.ZoneName,
},
}
if _, err := p.send(p.tr.NewZIRspPacket(zones)); err != nil {
if _, err := p.Send(p.Transport.NewZIRspPacket(zones)); err != nil {
log.Printf("Couldn't send ZI-Rsp packet: %v", err)
}
}
@ -346,7 +345,7 @@ func (p *peer) handle(ctx context.Context) error {
log.Printf("Router Down: error code %d %s", pkt.ErrorCode, pkt.ErrorCode)
// Respond with RI-Ack
if _, err := p.send(p.tr.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, 0)); err != nil {
if _, err := p.Send(p.Transport.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, 0)); err != nil {
log.Printf("Couldn't send RI-Ack: %v", err)
return err
}
@ -358,11 +357,11 @@ func (p *peer) handle(ctx context.Context) error {
// ZI-Req
zones := aurp.ZoneTuples{
{
Network: uint16(p.cfg.EtherTalk.NetStart),
Name: p.cfg.EtherTalk.ZoneName,
Network: uint16(p.Config.EtherTalk.NetStart),
Name: p.Config.EtherTalk.ZoneName,
},
}
if _, err := p.send(p.tr.NewZIRspPacket(zones)); err != nil {
if _, err := p.Send(p.Transport.NewZIRspPacket(zones)); err != nil {
log.Printf("Couldn't send ZI-Rsp packet: %v", err)
return err
}
@ -370,11 +369,11 @@ func (p *peer) handle(ctx context.Context) error {
case *aurp.ZIRspPacket:
log.Printf("Learned about these zones: %v", pkt.Zones)
for _, zt := range pkt.Zones {
p.zoneTable.Upsert(ddp.Network(zt.Network), zt.Name, false)
p.ZoneTable.Upsert(ddp.Network(zt.Network), zt.Name, false)
}
case *aurp.GDZLReqPacket:
if _, err := p.send(p.tr.NewGDZLRspPacket(-1, nil)); err != nil {
if _, err := p.Send(p.Transport.NewGDZLRspPacket(-1, nil)); err != nil {
log.Printf("Couldn't send GDZL-Rsp packet: %v", err)
return err
}
@ -383,7 +382,7 @@ func (p *peer) handle(ctx context.Context) error {
log.Printf("Received a GDZL-Rsp, but I wouldn't have sent a GDZL-Req - that's weird")
case *aurp.GZNReqPacket:
if _, err := p.send(p.tr.NewGZNRspPacket(pkt.ZoneName, false, nil)); err != nil {
if _, err := p.Send(p.Transport.NewGZNRspPacket(pkt.ZoneName, false, nil)); err != nil {
log.Printf("Couldn't send GZN-Rsp packet: %v", err)
return err
}
@ -393,7 +392,7 @@ func (p *peer) handle(ctx context.Context) error {
case *aurp.TicklePacket:
// Immediately respond with Tickle-Ack
if _, err := p.send(p.tr.NewTickleAckPacket()); err != nil {
if _, err := p.Send(p.Transport.NewTickleAckPacket()); err != nil {
log.Printf("Couldn't send Tickle-Ack: %v", err)
return err
}

View File

@ -1,4 +1,20 @@
package main
/*
Copyright 2024 Josh Deprez
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package router
import (
"fmt"
@ -14,7 +30,7 @@ type Route struct {
Extended bool
NetStart ddp.Network
NetEnd ddp.Network
Peer *peer
Peer *Peer
Distance uint8
LastSeen time.Time
}
@ -56,7 +72,7 @@ func (rt *RoutingTable) LookupRoute(network ddp.Network) *Route {
return bestRoute
}
func (rt *RoutingTable) UpsertRoute(extended bool, netStart, netEnd ddp.Network, peer *peer, metric uint8) error {
func (rt *RoutingTable) UpsertRoute(extended bool, netStart, netEnd ddp.Network, peer *Peer, metric uint8) error {
if netStart > netEnd {
return fmt.Errorf("invalid network range [%d, %d]", netStart, netEnd)
}

32
router/router.go Normal file
View File

@ -0,0 +1,32 @@
/*
Copyright 2024 Josh Deprez
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package router
import (
"github.com/google/gopacket/pcap"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
)
type Router struct {
Config *Config
PcapHandle *pcap.Handle
MyHWAddr ethernet.Addr
MyDDPAddr ddp.Addr
RouteTable *RoutingTable
ZoneTable *ZoneTable
}

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"context"
@ -33,17 +33,17 @@ import (
// RTMPMachine implements RTMP on an AppleTalk network attached to the router.
type RTMPMachine struct {
aarp *AARPMachine
cfg *config
pcapHandle *pcap.Handle
routingTable *RoutingTable
AARP *AARPMachine
Config *Config
PcapHandle *pcap.Handle
RoutingTable *RoutingTable
}
// Run executes the machine.
func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket) error {
// Await local address assignment before doing anything
<-m.aarp.Assigned()
myAddr, ok := m.aarp.Address()
<-m.AARP.Assigned()
myAddr, ok := m.AARP.Address()
if !ok {
return fmt.Errorf("AARP machine closed Assigned channel but Address is not valid")
}
@ -76,7 +76,7 @@ func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket)
}
// should be in the cache...
theirHWAddr, err := m.aarp.Resolve(ctx, ddp.Addr{Network: pkt.SrcNet, Node: pkt.SrcNode})
theirHWAddr, err := m.AARP.Resolve(ctx, ddp.Addr{Network: pkt.SrcNet, Node: pkt.SrcNode})
if err != nil {
log.Printf("RTMP: Couldn't resolve %d.%d to a hardware address: %v", pkt.SrcNet, pkt.SrcNode, err)
continue
@ -88,8 +88,8 @@ func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket)
respPkt := &rtmp.ResponsePacket{
SenderAddr: myAddr.Proto,
Extended: true,
RangeStart: m.cfg.EtherTalk.NetStart,
RangeEnd: m.cfg.EtherTalk.NetEnd,
RangeStart: m.Config.EtherTalk.NetStart,
RangeEnd: m.Config.EtherTalk.NetEnd,
}
respPktRaw, err := respPkt.Marshal()
if err != nil {
@ -170,7 +170,7 @@ func (m *RTMPMachine) send(src, dst ethernet.Addr, ddpPkt *ddp.ExtPacket) error
if err != nil {
return err
}
return m.pcapHandle.WritePacketData(ethFrameRaw)
return m.PcapHandle.WritePacketData(ethFrameRaw)
}
func (m *RTMPMachine) broadcastData(myAddr aarp.AddrPair) error {
@ -209,13 +209,13 @@ func (m *RTMPMachine) dataPacket(myAddr ddp.Addr) *rtmp.DataPacket {
// to that network."
{
Extended: true,
RangeStart: m.cfg.EtherTalk.NetStart,
RangeEnd: m.cfg.EtherTalk.NetEnd,
RangeStart: m.Config.EtherTalk.NetStart,
RangeEnd: m.Config.EtherTalk.NetEnd,
Distance: 0,
},
},
}
for _, rt := range m.routingTable.ValidRoutes() {
for _, rt := range m.RoutingTable.ValidRoutes() {
p.NetworkTuples = append(p.NetworkTuples, rtmp.NetworkTuple{
Extended: rt.Extended,
RangeStart: rt.NetStart,

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"fmt"
@ -23,14 +23,12 @@ import (
"gitea.drjosh.dev/josh/jrouter/atalk"
"gitea.drjosh.dev/josh/jrouter/atalk/atp"
"gitea.drjosh.dev/josh/jrouter/atalk/zip"
"github.com/google/gopacket/pcap"
"github.com/sfiera/multitalk/pkg/aarp"
"github.com/sfiera/multitalk/pkg/ddp"
"github.com/sfiera/multitalk/pkg/ethernet"
"github.com/sfiera/multitalk/pkg/ethertalk"
)
func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAddr aarp.AddrPair, cfg *config, zones *ZoneTable, ddpkt *ddp.ExtPacket) error {
func (rtr *Router) HandleZIP(srcHWAddr ethernet.Addr, ddpkt *ddp.ExtPacket) error {
switch ddpkt.Proto {
case ddp.ProtoATP:
atpkt, err := atp.UnmarshalPacket(ddpkt.Data)
@ -54,13 +52,13 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
switch gzl.Function {
case zip.FunctionGetZoneList:
resp.Zones = zones.AllNames()
resp.Zones = rtr.ZoneTable.AllNames()
case zip.FunctionGetLocalZones:
resp.Zones = zones.LocalNames()
resp.Zones = rtr.ZoneTable.LocalNames()
case zip.FunctionGetMyZone:
resp.Zones = []string{cfg.EtherTalk.ZoneName}
resp.Zones = []string{rtr.Config.EtherTalk.ZoneName}
}
// Inside AppleTalk SE, pp 8-8
@ -101,14 +99,14 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
DstNet: ddpkt.SrcNet,
DstNode: ddpkt.SrcNode,
DstSocket: ddpkt.SrcSocket,
SrcNet: myAddr.Proto.Network,
SrcNode: myAddr.Proto.Node,
SrcNet: rtr.MyDDPAddr.Network,
SrcNode: rtr.MyDDPAddr.Node,
SrcSocket: 6,
Proto: ddp.ProtoATP,
},
Data: ddpBody,
}
outFrame, err := ethertalk.AppleTalk(myHWAddr, respDDP)
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, respDDP)
if err != nil {
return err
}
@ -117,7 +115,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
if err != nil {
return err
}
return pcapHandle.WritePacketData(outFrameRaw)
return rtr.PcapHandle.WritePacketData(outFrameRaw)
case *atp.TResp:
return fmt.Errorf("TODO: support handling ZIP ATP replies?")
@ -135,7 +133,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
switch zipkt := zipkt.(type) {
case *zip.QueryPacket:
log.Printf("ZIP: Got Query for networks %v", zipkt.Networks)
networks := zones.Query(zipkt.Networks)
networks := rtr.ZoneTable.Query(zipkt.Networks)
sendReply := func(resp *zip.ReplyPacket) error {
respRaw, err := resp.Marshal()
@ -149,15 +147,15 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
DstNet: ddpkt.SrcNet,
DstNode: ddpkt.SrcNode,
DstSocket: ddpkt.SrcSocket,
SrcNet: myAddr.Proto.Network,
SrcNode: myAddr.Proto.Node,
SrcNet: rtr.MyDDPAddr.Network,
SrcNode: rtr.MyDDPAddr.Node,
SrcSocket: 6,
Proto: ddp.ProtoZIP,
},
Data: respRaw,
}
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
if err != nil {
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
}
@ -167,7 +165,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
if err != nil {
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
}
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
if err := rtr.PcapHandle.WritePacketData(outFrameRaw); err != nil {
return fmt.Errorf("couldn't write packet data: %w", err)
}
return nil
@ -246,14 +244,14 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
// Only running a network with one zone for now.
resp := &zip.GetNetInfoReplyPacket{
ZoneInvalid: zipkt.ZoneName != cfg.EtherTalk.ZoneName,
ZoneInvalid: zipkt.ZoneName != rtr.Config.EtherTalk.ZoneName,
UseBroadcast: false,
OnlyOneZone: true,
NetStart: cfg.EtherTalk.NetStart,
NetEnd: cfg.EtherTalk.NetEnd,
NetStart: rtr.Config.EtherTalk.NetStart,
NetEnd: rtr.Config.EtherTalk.NetEnd,
ZoneName: zipkt.ZoneName, // has to match request
MulticastAddr: atalk.MulticastAddr(cfg.EtherTalk.ZoneName),
DefaultZoneName: cfg.EtherTalk.ZoneName,
MulticastAddr: atalk.MulticastAddr(rtr.Config.EtherTalk.ZoneName),
DefaultZoneName: rtr.Config.EtherTalk.ZoneName,
}
log.Printf("ZIP: Replying with GetNetInfo-Reply: %+v", resp)
@ -277,8 +275,8 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
DstNet: ddpkt.SrcNet,
DstNode: ddpkt.SrcNode,
DstSocket: ddpkt.SrcSocket,
SrcNet: myAddr.Proto.Network,
SrcNode: myAddr.Proto.Node,
SrcNet: rtr.MyDDPAddr.Network,
SrcNode: rtr.MyDDPAddr.Node,
SrcSocket: 6,
Proto: ddp.ProtoZIP,
},
@ -291,7 +289,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
outDDP.DstNode = 0xFF
}
outFrame, err := ethertalk.AppleTalk(myHWAddr, outDDP)
outFrame, err := ethertalk.AppleTalk(rtr.MyHWAddr, outDDP)
if err != nil {
return fmt.Errorf("couldn't create EtherTalk frame: %w", err)
}
@ -303,7 +301,7 @@ func handleZIP(pcapHandle *pcap.Handle, srcHWAddr, myHWAddr ethernet.Addr, myAdd
if err != nil {
return fmt.Errorf("couldn't marshal EtherTalk frame: %w", err)
}
if err := pcapHandle.WritePacketData(outFrameRaw); err != nil {
if err := rtr.PcapHandle.WritePacketData(outFrameRaw); err != nil {
return fmt.Errorf("couldn't write packet data: %w", err)
}
return nil

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package main
package router
import (
"slices"