diff --git a/main.go b/main.go index a7af0d9..55f274d 100644 --- a/main.go +++ b/main.go @@ -164,7 +164,8 @@ func main() { cfg: cfg, pcapHandle: pcapHandle, } - go rtmpMachine.Run(ctx) + rtmpCh := make(chan *ddp.ExtPacket, 1024) + go rtmpMachine.Run(ctx, rtmpCh) // ---------- Raw AppleTalk/AARP inbound ---------- go func() { @@ -217,6 +218,36 @@ func main() { aarpMachine.Learn(srcAddr, ethFrame.Src) log.Printf("DDP: Gleaned that %v -> %v", srcAddr, ethFrame.Src) + // Packet for us? First, who am I? + myAddr, ok := aarpMachine.Address() + if !ok { + continue + } + + // Our network? + // "The network number 0 is reserved to mean unknown; by default + // it specifies the local network to which the node is + // connected. Packets whose destination network number is 0 are + // addressed to a node on the local network." + if ddpkt.DstNet != 0 && ddpkt.DstNet != myAddr.Proto.Network { + continue + } + + // To me? + // "Node ID 0 indicates any router on the network"- I'm a router + // "node ID $FF indicates either a network-wide or zone-specific + // broadcast"- that's relevant + if ddpkt.DstNode != 0 && ddpkt.DstNode != 0xff && ddpkt.DstNode != myAddr.Proto.Node { + continue + } + + switch ddpkt.DstSocket { + case 1: // The RTMP socket + rtmpCh <- &ddpkt + default: + log.Printf("DDP: No handler for socket %d", ddpkt.DstSocket) + } + default: log.Printf("Read unknown packet %s -> %s with payload %x", ethFrame.Src, ethFrame.Dst, ethFrame.Payload) diff --git a/rtmp.go b/rtmp.go index 044a412..c38a0e8 100644 --- a/rtmp.go +++ b/rtmp.go @@ -18,7 +18,7 @@ type RTMPMachine struct { pcapHandle *pcap.Handle } -func (m *RTMPMachine) Run(ctx context.Context) error { +func (m *RTMPMachine) Run(ctx context.Context, incomingCh <-chan *ddp.ExtPacket) error { bcastTicker := time.NewTicker(10 * time.Second) defer bcastTicker.Stop() @@ -86,6 +86,37 @@ func (m *RTMPMachine) Run(ctx context.Context) error { if err := m.pcapHandle.WritePacketData(ethFrameRaw); err != nil { log.Printf("RTMP: Couldn't write frame: %v", err) } + + case pkt := <-incomingCh: + switch pkt.Proto { + case ddp.ProtoRTMPReq: + // I can answer RTMP requests! + req, err := rtmp.UnmarshalRequestPacket(pkt.Data) + if err != nil { + log.Printf("RTMP: Couldn't unmarshal Request packet: %v", err) + } + switch req.Function { + case 1: // RTMP Request + // TODO + log.Print("RTMP: Got Request") + + case 2: // RTMP RDR with split-horizon processing + // TODO + log.Print("RTMP: Got RDR with split-horizon") + + case 3: // RTMP RDR for whole table + // TODO + log.Print("RTMP: Got RDR without split-horizon") + + } + + case ddp.ProtoRTMPResp: + // It's a peer router on the AppleTalk network! + // TODO + log.Print("RTMP: Got Response or ") + + } + } } }