From 112012bf5b8e0bd931c7bcdb60f8f1254e691461 Mon Sep 17 00:00:00 2001 From: Josh Deprez Date: Sun, 7 Apr 2024 15:14:54 +1000 Subject: [PATCH] WIP RTMP machine --- main.go | 14 +++++++-- rtmp.go | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 rtmp.go diff --git a/main.go b/main.go index 84fdeb4..e96f5e6 100644 --- a/main.go +++ b/main.go @@ -125,6 +125,7 @@ func main() { }() } + // --------------- Configured peer setup --------------- for _, peerStr := range cfg.Peers { if !hasPortRE.MatchString(peerStr) { peerStr += ":387" @@ -152,11 +153,20 @@ func main() { goPeerHandler(peer) } - // AppleTalk packet loops + // -------------------- AARP -------------------- aarpMachine := NewAARPMachine(cfg, pcapHandle, myHWAddr) aarpCh := make(chan *ethertalk.Packet, 1024) go aarpMachine.Run(ctx, aarpCh) + // -------------------- RTMP -------------------- + rtmpMachine := &RTMPMachine{ + aarp: aarpMachine, + cfg: cfg, + pcapHandle: pcapHandle, + } + go rtmpMachine.Run(ctx) + + // ---------- Raw AppleTalk/AARP inbound ---------- go func() { for { if ctx.Err() != nil { @@ -212,7 +222,7 @@ func main() { } }() - // AURP packet loop + // ---------- AURP inbound ---------- for { if ctx.Err() != nil { return diff --git a/rtmp.go b/rtmp.go new file mode 100644 index 0000000..bfaf1dd --- /dev/null +++ b/rtmp.go @@ -0,0 +1,89 @@ +package main + +import ( + "context" + "log" + "time" + + "gitea.drjosh.dev/josh/jrouter/atalk/rtmp" + "github.com/google/gopacket/pcap" + "github.com/sfiera/multitalk/pkg/ddp" + "github.com/sfiera/multitalk/pkg/ethertalk" +) + +// RTMPMachine implements RTMP on an AppleTalk network attached to the router. +type RTMPMachine struct { + aarp *AARPMachine + cfg *config + pcapHandle *pcap.Handle +} + +func (m *RTMPMachine) Run(ctx context.Context) error { + bcastTicker := time.NewTicker(10 * time.Second) + defer bcastTicker.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + + case <-bcastTicker.C: + // Broadcast an RTMP Data + myAddr, ok := m.aarp.Address() + if !ok { + continue + } + + dataPkt := &rtmp.DataPacket{ + RouterAddr: myAddr.Proto, + Extended: true, + NetworkTuples: []rtmp.NetworkTuple{ + // "The first tuple in RTMP Data packets sent on extended + // networks ... indicates the network number range assigned + // to that network." + { + Extended: true, + RangeStart: m.cfg.EtherTalk.NetStart, + RangeEnd: m.cfg.EtherTalk.NetEnd, + Distance: 0, + }, + }, + } + // TODO: append more networks! + + dataPktRaw, err := dataPkt.Marshal() + if err != nil { + log.Printf("RTMP: Couldn't marshal Data packet: %v", err) + continue + } + + ddpPkt := ddp.ExtPacket{ + ExtHeader: ddp.ExtHeader{ + Size: uint16(len(dataPktRaw)), + DstNet: 0, + DstNode: 0xff, // broadcast packet + DstSocket: 1, // the special RTMP socket + SrcNet: myAddr.Proto.Network, + SrcNode: myAddr.Proto.Node, + SrcSocket: 1, // the special RTMP socket + Proto: ddp.ProtoRTMPResp, + }, + Data: dataPktRaw, + } + + ethFrame, err := ethertalk.AppleTalk(ethertalk.AppleTalkBroadcast, ddpPkt) + if err != nil { + log.Printf("RTMP: Couldn't create EtherTalk frame: %v", err) + } + + ethFrameRaw, err := ethertalk.Marshal(*ethFrame) + if err != nil { + log.Printf("RTMP: Couldn't marshal EtherTalk frame: %v", err) + } + + if err := m.pcapHandle.WritePacketData(ethFrameRaw); err != nil { + log.Printf("RTMP: Couldn't write frame: %v", err) + } + } + } +}