From 64f491fcba9276b382932a2efe602f4d48038f43 Mon Sep 17 00:00:00 2001 From: Josh Deprez Date: Sat, 30 Mar 2024 14:24:16 +1100 Subject: [PATCH] Handle SIGINT, send RD --- aurp/transport.go | 11 +++++++++++ main.go | 13 ++++++++----- peer.go | 6 ++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/aurp/transport.go b/aurp/transport.go index 70a57e2..221d6d4 100644 --- a/aurp/transport.go +++ b/aurp/transport.go @@ -111,6 +111,17 @@ func (tr *Transport) NewOpenRspPacket(envFlags RoutingFlag, rateOrErr int16, opt } } +func (tr *Transport) NewRDPacket(errCode ErrorCode) *RDPacket { + return &RDPacket{ + Header: Header{ + TrHeader: tr.transaction(tr.LocalConnID), + CommandCode: CmdCodeRD, + Flags: 0, + }, + ErrorCode: errCode, + } +} + func (tr *Transport) NewTicklePacket() *TicklePacket { return &TicklePacket{ Header: Header{ diff --git a/main.go b/main.go index 6e7f3fe..89db23c 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,8 @@ import ( "flag" "log" "net" + "os" + "os/signal" "regexp" "gitea.drjosh.dev/josh/jrouter/aurp" @@ -18,8 +20,6 @@ func main() { flag.Parse() log.Println("jrouter") - ctx := context.Background() - cfg, err := loadConfig(*configFilePath) if err != nil { log.Fatalf("Couldn't load configuration file: %v", err) @@ -62,6 +62,9 @@ func main() { defer ln.Close() log.Printf("Listening on %v", ln.LocalAddr()) + log.Println("Press ^C or send SIGINT to stop the router gracefully") + ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt) + for _, peerStr := range cfg.Peers { if !hasPortRE.MatchString(peerStr) { peerStr += ":387" @@ -92,15 +95,15 @@ func main() { } // Incoming packet loop - pb := make([]byte, 65536) for { - pktlen, raddr, readErr := ln.ReadFromUDP(pb) + pktbuf := make([]byte, 65536) + pktlen, raddr, readErr := ln.ReadFromUDP(pktbuf) // net.PacketConn.ReadFrom: "Callers should always process // the n > 0 bytes returned before considering the error err." log.Printf("Received packet of length %d from %v", pktlen, raddr) - dh, pkt, parseErr := aurp.ParsePacket(pb[:pktlen]) + dh, pkt, parseErr := aurp.ParsePacket(pktbuf[:pktlen]) if parseErr != nil { log.Printf("Failed to parse packet: %v", parseErr) continue diff --git a/peer.go b/peer.go index 51aafe5..538cba9 100644 --- a/peer.go +++ b/peer.go @@ -32,6 +32,8 @@ func (p *peer) handle(ctx context.Context) error { ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() + p.lastHeardFrom = time.Now() + // Write an Open-Req packet n, err := p.send(p.tr.NewOpenReqPacket(nil)) if err != nil { @@ -43,6 +45,10 @@ func (p *peer) handle(ctx context.Context) error { for { select { case <-ctx.Done(): + // Send a best-effort Router Down before returning + if _, err := p.send(p.tr.NewRDPacket(aurp.ErrCodeNormalClose)); err != nil { + log.Printf("Couldn't send RD packet: %v", err) + } return ctx.Err() case <-ticker.C: