diff --git a/aurp/routing_info.go b/aurp/routing_info.go index 74baaeb..c716e8d 100644 --- a/aurp/routing_info.go +++ b/aurp/routing_info.go @@ -20,6 +20,7 @@ import ( "encoding/binary" "fmt" "io" + "strings" ) type RIReqPacket struct { @@ -78,6 +79,17 @@ func parseRIUpd(p []byte) (*RIUpdPacket, error) { type NetworkTuples []NetworkTuple +func (n NetworkTuples) String() string { + var sb strings.Builder + for i, nt := range n { + if i > 0 { + sb.WriteString(", ") + } + fmt.Fprintf(&sb, "%d-%d dist %d", nt.RangeStart, nt.RangeEnd, nt.Distance) + } + return sb.String() +} + func (n NetworkTuples) WriteTo(w io.Writer) (int64, error) { a := acc(w) for _, nt := range n { diff --git a/aurp/zone_info.go b/aurp/zone_info.go index 4718e2c..76017b8 100644 --- a/aurp/zone_info.go +++ b/aurp/zone_info.go @@ -20,6 +20,7 @@ import ( "encoding/binary" "fmt" "io" + "strings" ) // Subcode is used to distinguish types of zone request/response. @@ -285,6 +286,17 @@ func parseGZNRspPacket(p []byte) (*GZNRspPacket, error) { type ZoneTuples []ZoneTuple +func (zs ZoneTuples) String() string { + var sb strings.Builder + for i, zt := range zs { + if i > 0 { + sb.WriteString(", ") + } + fmt.Fprintf(&sb, "%d %q", zt.Network, zt.Name) + } + return sb.String() +} + type ZoneTuple struct { Network uint16 Name string diff --git a/peer.go b/peer.go index 37d9009..8aab82b 100644 --- a/peer.go +++ b/peer.go @@ -240,6 +240,7 @@ func (p *peer) handle(ctx context.Context) error { log.Printf("Couldn't send RI-Req packet: %v", err) return err } + rstate = rsWaitForRIRsp case *aurp.RIReqPacket: if sstate != ssConnected { @@ -256,6 +257,7 @@ func (p *peer) handle(ctx context.Context) error { p.tr.LocalSeq = 1 if _, err := p.send(p.tr.NewRIRspPacket(aurp.RoutingFlagLast, nets)); err != nil { log.Printf("Couldn't send RI-Rsp packet: %v", err) + return err } sstate = ssWaitForRIAck1 @@ -263,9 +265,18 @@ func (p *peer) handle(ctx context.Context) error { if rstate != rsWaitForRIRsp { log.Printf("Received RI-Rsp but was not waiting for one (receiver state was %v)", rstate) } - // TODO: Repsond with RI-Ack + + log.Printf("Learned about these networks: %v", pkt.Networks) + // TODO: Integrate info into route table + // 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 { + log.Printf("Couldn't send RI-Ack packet: %v", err) + return err + } + case *aurp.RIAckPacket: switch sstate { case ssWaitForRIAck1: @@ -285,6 +296,8 @@ func (p *peer) handle(ctx context.Context) error { sstate = ssConnected // If SZI flag is set, send ZI-Rsp (transaction) + // TODO: only respond with zones for networks that were in the + // RI-Rsp that corresponded to this RI-Ack if pkt.Flags&aurp.RoutingFlagSendZoneInfo != 0 { zones := aurp.ZoneTuples{ { @@ -318,10 +331,21 @@ func (p *peer) handle(ctx context.Context) error { rstate = rsUnconnected case *aurp.ZIReqPacket: - // TODO: Respond with ZI-Rsp + // TODO: only respond with zones for networks specified by the + // ZI-Req + zones := aurp.ZoneTuples{ + { + Network: p.cfg.EtherTalk.NetStart, + Name: p.cfg.EtherTalk.ZoneName, + }, + } + if _, err := p.send(p.tr.NewZIRspPacket(zones)); err != nil { + log.Printf("Couldn't send ZI-Rsp packet: %v", err) + } case *aurp.ZIRspPacket: // TODO: Integrate info into zone table + log.Printf("Learned about these zones: %v", pkt.Zones) case *aurp.TicklePacket: // Immediately respond with Tickle-Ack