diff --git a/main.go b/main.go index 97650af..45904ac 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "flag" "log" "net" @@ -136,114 +135,6 @@ func main() { } } -type peer struct { - tr *aurp.Transport - conn *net.UDPConn - raddr *net.UDPAddr - recv chan aurp.Packet -} - -// 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 - } - return p.conn.WriteToUDP(b.Bytes(), p.raddr) -} - -func (p *peer) handle() { - // Write an Open-Req packet - n, err := p.send(p.tr.NewOpenReqPacket(nil)) - if err != nil { - log.Printf("Couldn't send Open-Req packet: %v", err) - return - } - log.Printf("Sent Open-Req (len %d) to peer %v", n, p.raddr) - - for pkt := range p.recv { - switch pkt := pkt.(type) { - case *aurp.AppleTalkPacket: - // Probably something like: - // - // * parse the DDP header - // * check that this is headed for our local network - // * write the packet out in an EtherTalk frame - // - // or maybe if we were implementing a "central hub" - // - // * parse the DDP header - // * see if we know the network - // * forward to the peer with that network and lowest metric - - case *aurp.OpenReqPacket: - // The peer tells us their connection ID in Open-Req. - p.tr.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, aurp.ErrCodeInvalidVersion, nil) - - case len(pkt.Options) > 0: - // Options? OPTIONS? We don't accept no stinkin' _options_ - orsp = p.tr.NewOpenRspPacket(0, aurp.ErrCodeOptionNegotiation, nil) - - default: - // Accept it I guess. - orsp = p.tr.NewOpenRspPacket(0, 1, nil) - } - - log.Printf("Responding with %T", orsp) - - if _, err := p.send(orsp); err != nil { - log.Printf("Couldn't send Open-Rsp: %v", err) - } - - case *aurp.OpenRspPacket: - if pkt.RateOrErrCode < 0 { - // It's an error code. - log.Printf("Open-Rsp error code from peer %v: %d", p.raddr.IP, pkt.RateOrErrCode) - // Close the connection - } - - // TODO: Make other requests - - case *aurp.RIReqPacket: - // TODO: Respond with RI-Rsp - - case *aurp.RIRspPacket: - // TODO: Repsond with RI-Ack - // TODO: Integrate info into route table - - case *aurp.RIAckPacket: - // TODO: Continue sending next RI-Rsp (streamed) - // TODO: If SZI flag is set, send ZI-Rsp (transaction) - - case *aurp.RIUpdPacket: - // TODO: Integrate info into route table - - case *aurp.RDPacket: - // TODO: Remove router from tables - // TODO: Close connection - - case *aurp.ZIReqPacket: - // TODO: Respond with ZI-Rsp - - case *aurp.ZIRspPacket: - // TODO: Integrate info into zone table - - case *aurp.TicklePacket: - // TODO: Respond with TickleAck - - case *aurp.TickleAckPacket: - // TODO: Reset LHFT - } - } -} - // Hashable net.UDPAddr type udpAddr struct { ipv4 [4]byte diff --git a/peer.go b/peer.go new file mode 100644 index 0000000..4b9bd4a --- /dev/null +++ b/peer.go @@ -0,0 +1,117 @@ +package main + +import ( + "bytes" + "log" + "net" + + "gitea.drjosh.dev/josh/jrouter/aurp" +) + +type peer struct { + tr *aurp.Transport + conn *net.UDPConn + raddr *net.UDPAddr + recv chan aurp.Packet +} + +// 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 + } + return p.conn.WriteToUDP(b.Bytes(), p.raddr) +} + +func (p *peer) handle() { + // Write an Open-Req packet + n, err := p.send(p.tr.NewOpenReqPacket(nil)) + if err != nil { + log.Printf("Couldn't send Open-Req packet: %v", err) + return + } + log.Printf("Sent Open-Req (len %d) to peer %v", n, p.raddr) + + for pkt := range p.recv { + switch pkt := pkt.(type) { + case *aurp.AppleTalkPacket: + // Probably something like: + // + // * parse the DDP header + // * check that this is headed for our local network + // * write the packet out in an EtherTalk frame + // + // or maybe if we were implementing a "central hub" + // + // * parse the DDP header + // * see if we know the network + // * forward to the peer with that network and lowest metric + + case *aurp.OpenReqPacket: + // The peer tells us their connection ID in Open-Req. + p.tr.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, aurp.ErrCodeInvalidVersion, nil) + + case len(pkt.Options) > 0: + // Options? OPTIONS? We don't accept no stinkin' _options_ + orsp = p.tr.NewOpenRspPacket(0, aurp.ErrCodeOptionNegotiation, nil) + + default: + // Accept it I guess. + orsp = p.tr.NewOpenRspPacket(0, 1, nil) + } + + log.Printf("Responding with %T", orsp) + + if _, err := p.send(orsp); err != nil { + log.Printf("Couldn't send Open-Rsp: %v", err) + } + + case *aurp.OpenRspPacket: + if pkt.RateOrErrCode < 0 { + // It's an error code. + log.Printf("Open-Rsp error code from peer %v: %d", p.raddr.IP, pkt.RateOrErrCode) + // Close the connection + } + + // TODO: Make other requests + + case *aurp.RIReqPacket: + // TODO: Respond with RI-Rsp + + case *aurp.RIRspPacket: + // TODO: Repsond with RI-Ack + // TODO: Integrate info into route table + + case *aurp.RIAckPacket: + // TODO: Continue sending next RI-Rsp (streamed) + // TODO: If SZI flag is set, send ZI-Rsp (transaction) + + case *aurp.RIUpdPacket: + // TODO: Integrate info into route table + + case *aurp.RDPacket: + // TODO: Remove router from tables + // TODO: Close connection + + case *aurp.ZIReqPacket: + // TODO: Respond with ZI-Rsp + + case *aurp.ZIRspPacket: + // TODO: Integrate info into zone table + + case *aurp.TicklePacket: + // TODO: Respond with TickleAck + + case *aurp.TickleAckPacket: + // TODO: Reset LHFT + } + } +}