jrouter/router/peer_aurp.go

822 lines
23 KiB
Go
Raw Permalink Normal View History

2024-03-31 09:31:50 +11:00
/*
Copyright 2024 Josh Deprez
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
2024-04-19 14:57:25 +10:00
package router
2024-03-25 19:30:06 +11:00
import (
"bytes"
2024-03-30 14:13:34 +11:00
"context"
2024-03-25 19:30:06 +11:00
"log"
"net"
"sync"
2024-03-30 14:13:34 +11:00
"time"
2024-03-25 19:30:06 +11:00
2024-10-18 13:20:34 +11:00
"drjosh.dev/jrouter/aurp"
2024-04-12 16:14:27 +10:00
"github.com/sfiera/multitalk/pkg/ddp"
2024-03-25 19:30:06 +11:00
)
2024-03-30 16:43:14 +11:00
const (
// TODO: check these parameters
2024-04-01 15:42:35 +11:00
lastHeardFromTimer = 90 * time.Second
2024-03-30 16:48:47 +11:00
tickleRetryLimit = 10
sendRetryTimer = 10 * time.Second
sendRetryLimit = 5
2024-04-21 15:26:07 +10:00
reconnectTimer = 10 * time.Minute
2024-04-20 12:01:03 +10:00
updateTimer = 10 * time.Second
2024-03-30 16:43:14 +11:00
)
type ReceiverState int
2024-03-30 16:14:18 +11:00
const (
ReceiverUnconnected ReceiverState = iota
ReceiverConnected
ReceiverWaitForOpenRsp
ReceiverWaitForRIRsp
ReceiverWaitForTickleAck
2024-03-30 16:14:18 +11:00
)
func (rs ReceiverState) String() string {
2024-04-26 14:37:38 +10:00
switch rs {
case ReceiverUnconnected:
2024-04-26 14:37:38 +10:00
return "unconnected"
case ReceiverConnected:
2024-04-26 14:37:38 +10:00
return "connected"
case ReceiverWaitForOpenRsp:
2024-04-26 14:37:38 +10:00
return "waiting for Open-Rsp"
case ReceiverWaitForRIRsp:
2024-04-26 14:37:38 +10:00
return "waiting for RI-Rsp"
case ReceiverWaitForTickleAck:
2024-04-26 14:37:38 +10:00
return "waiting for Tickle-Ack"
default:
return "unknown"
}
2024-03-30 18:01:28 +11:00
}
type SenderState int
2024-03-30 16:14:18 +11:00
const (
SenderUnconnected SenderState = iota
SenderConnected
SenderWaitForRIRspAck
SenderWaitForRIUpdAck
SenderWaitForRDAck
2024-03-30 16:14:18 +11:00
)
func (ss SenderState) String() string {
2024-04-26 14:37:38 +10:00
switch ss {
case SenderUnconnected:
2024-04-26 14:37:38 +10:00
return "unconnected"
case SenderConnected:
2024-04-26 14:37:38 +10:00
return "connected"
case SenderWaitForRIRspAck:
2024-04-26 14:37:38 +10:00
return "waiting for RI-Ack for RI-Rsp"
case SenderWaitForRIUpdAck:
2024-04-26 14:37:38 +10:00
return "waiting for RI-Ack for RI-Upd"
case SenderWaitForRDAck:
2024-04-26 14:37:38 +10:00
return "waiting for RI-Ack for RD"
default:
return "unknown"
}
2024-03-30 18:01:28 +11:00
}
2024-04-29 09:32:57 +10:00
// AURPPeer handles the peering with a peer AURP router.
type AURPPeer struct {
// AURP-Tr state for producing packets.
Transport *aurp.Transport
// Connection to reply to packets on.
UDPConn *net.UDPConn
// The string that appeared in the config file / peer list file (with a
// ":387" appended as necessary).
// May be empty if this peer was not configured (it connected to us).
ConfiguredAddr string
// The resolved address of the peer.
RemoteAddr *net.UDPAddr
// Incoming packet channel.
ReceiveCh chan aurp.Packet
2024-05-05 17:01:23 +10:00
// Route table (the peer will add/remove/update routes and zones)
RouteTable *RouteTable
2024-05-24 15:55:34 +10:00
// Event tuples yet to be sent to this peer in an RI-Upd.
2024-06-07 16:00:43 +10:00
pendingEventsMu sync.Mutex
pendingEvents aurp.EventTuples
2024-05-24 15:55:34 +10:00
2024-05-12 18:07:27 +10:00
// The internal states below are only set within the Handle loop, but can
// be read concurrently from outside.
mu sync.RWMutex
rstate ReceiverState
sstate SenderState
lastReconnect time.Time
lastHeardFrom time.Time
lastSend time.Time // TODO: clarify use of lastSend / sendRetries
lastUpdate time.Time
sendRetries int
}
2024-05-24 16:52:59 +10:00
func NewAURPPeer(routes *RouteTable, udpConn *net.UDPConn, peerAddr string, raddr *net.UDPAddr, localDI, remoteDI aurp.DomainIdentifier, connID uint16) *AURPPeer {
if remoteDI == nil {
remoteDI = aurp.IPDomainIdentifier(raddr.IP)
}
return &AURPPeer{
Transport: &aurp.Transport{
LocalDI: localDI,
RemoteDI: remoteDI,
LocalConnID: connID,
},
UDPConn: udpConn,
ConfiguredAddr: peerAddr,
RemoteAddr: raddr,
ReceiveCh: make(chan aurp.Packet, 1024),
RouteTable: routes,
}
}
2024-05-24 15:55:34 +10:00
func (p *AURPPeer) addPendingEvent(ec aurp.EventCode, route *Route) {
// Don't advertise routes to AURP peers to other AURP peers
if route.AURPPeer != nil {
return
}
et := aurp.EventTuple{
EventCode: ec,
Extended: route.Extended,
RangeStart: route.NetStart,
Distance: route.Distance,
RangeEnd: route.NetEnd,
}
switch ec {
case aurp.EventCodeND, aurp.EventCodeNRC:
et.Distance = 0 // "The distance field does not apply to ND or NRC event tuples and should be set to 0."
}
2024-06-07 16:00:43 +10:00
p.pendingEventsMu.Lock()
defer p.pendingEventsMu.Unlock()
p.pendingEvents = append(p.pendingEvents, et)
2024-05-24 15:55:34 +10:00
}
func (p *AURPPeer) RouteAdded(route *Route) {
p.addPendingEvent(aurp.EventCodeNA, route)
}
func (p *AURPPeer) RouteDeleted(route *Route) {
p.addPendingEvent(aurp.EventCodeND, route)
}
func (p *AURPPeer) RouteDistanceChanged(route *Route) {
p.addPendingEvent(aurp.EventCodeNDC, route)
}
func (p *AURPPeer) RouteForwarderChanged(route *Route) {
p.addPendingEvent(aurp.EventCodeNRC, route)
}
2024-05-03 16:13:59 +10:00
func (p *AURPPeer) Forward(ddpkt *ddp.ExtPacket) error {
outPkt, err := ddp.ExtMarshal(*ddpkt)
if err != nil {
return err
}
2024-05-12 18:31:01 +10:00
_, err = p.send(p.Transport.NewAppleTalkPacket(outPkt))
2024-05-03 16:13:59 +10:00
return err
}
2024-04-29 09:32:57 +10:00
func (p *AURPPeer) ReceiverState() ReceiverState {
p.mu.RLock()
defer p.mu.RUnlock()
return p.rstate
}
2024-04-29 09:32:57 +10:00
func (p *AURPPeer) SenderState() SenderState {
p.mu.RLock()
defer p.mu.RUnlock()
return p.sstate
}
2024-05-12 18:07:27 +10:00
func (p *AURPPeer) LastReconnectAgo() string {
p.mu.RLock()
defer p.mu.RUnlock()
2024-05-12 18:12:27 +10:00
return ago(p.lastReconnect)
2024-05-12 18:07:27 +10:00
}
func (p *AURPPeer) LastHeardFromAgo() string {
p.mu.RLock()
defer p.mu.RUnlock()
2024-05-12 18:12:27 +10:00
return ago(p.lastHeardFrom)
2024-05-12 18:07:27 +10:00
}
func (p *AURPPeer) LastSendAgo() string {
p.mu.RLock()
defer p.mu.RUnlock()
2024-05-12 18:12:27 +10:00
return ago(p.lastSend)
2024-05-12 18:07:27 +10:00
}
func (p *AURPPeer) LastUpdateAgo() string {
p.mu.RLock()
defer p.mu.RUnlock()
2024-05-12 18:12:27 +10:00
return ago(p.lastUpdate)
2024-05-12 18:07:27 +10:00
}
func (p *AURPPeer) SendRetries() int {
p.mu.RLock()
defer p.mu.RUnlock()
return p.sendRetries
}
2024-04-29 09:32:57 +10:00
func (p *AURPPeer) setRState(rstate ReceiverState) {
p.mu.Lock()
defer p.mu.Unlock()
p.rstate = rstate
}
2024-04-29 09:32:57 +10:00
func (p *AURPPeer) setSState(sstate SenderState) {
p.mu.Lock()
defer p.mu.Unlock()
p.sstate = sstate
}
2024-05-12 18:07:27 +10:00
func (p *AURPPeer) incSendRetries() {
p.mu.Lock()
defer p.mu.Unlock()
p.sendRetries++
}
func (p *AURPPeer) resetSendRetries() {
p.mu.Lock()
defer p.mu.Unlock()
p.sendRetries = 0
}
func (p *AURPPeer) bumpLastHeardFrom() {
p.mu.Lock()
defer p.mu.Unlock()
p.lastHeardFrom = time.Now()
}
func (p *AURPPeer) bumpLastReconnect() {
p.mu.Lock()
defer p.mu.Unlock()
p.lastReconnect = time.Now()
}
func (p *AURPPeer) bumpLastSend() {
p.mu.Lock()
defer p.mu.Unlock()
p.lastSend = time.Now()
}
func (p *AURPPeer) bumpLastUpdate() {
p.mu.Lock()
defer p.mu.Unlock()
p.lastUpdate = time.Now()
}
2024-04-29 09:32:57 +10:00
func (p *AURPPeer) disconnect() {
p.mu.Lock()
defer p.mu.Unlock()
p.rstate = ReceiverUnconnected
p.sstate = SenderUnconnected
2024-03-25 19:30:06 +11:00
}
2024-05-12 18:31:01 +10:00
// send encodes and sends pkt to the remote host.
func (p *AURPPeer) send(pkt aurp.Packet) (int, error) {
2024-03-25 19:30:06 +11:00
var b bytes.Buffer
if _, err := pkt.WriteTo(&b); err != nil {
return 0, err
}
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Sending %T (len %d) to %v", pkt, b.Len(), p.RemoteAddr)
2024-04-19 14:57:25 +10:00
return p.UDPConn.WriteToUDP(b.Bytes(), p.RemoteAddr)
2024-03-25 19:30:06 +11:00
}
2024-04-29 09:32:57 +10:00
func (p *AURPPeer) Handle(ctx context.Context) error {
2024-06-07 16:00:43 +10:00
// Stop listening to events if the goroutine exits
defer p.RouteTable.RemoveObserver(p)
2024-04-20 12:01:03 +10:00
rticker := time.NewTicker(1 * time.Second)
defer rticker.Stop()
sticker := time.NewTicker(1 * time.Second)
defer sticker.Stop()
2024-03-30 14:13:34 +11:00
2024-05-12 18:07:27 +10:00
p.mu.Lock()
p.lastReconnect = time.Now()
p.lastHeardFrom = time.Now()
p.lastSend = time.Now() // TODO: clarify use of lastSend / sendRetries
p.lastUpdate = time.Now()
p.sendRetries = 0
p.mu.Unlock()
2024-03-30 14:24:16 +11:00
2024-04-21 14:18:58 +10:00
var lastRISent aurp.Packet
p.disconnect()
2024-03-30 16:14:18 +11:00
2024-03-25 19:30:06 +11:00
// Write an Open-Req packet
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewOpenReqPacket(nil)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send Open-Req packet: %v", err)
2024-03-30 14:13:34 +11:00
return err
2024-03-25 19:30:06 +11:00
}
p.setRState(ReceiverWaitForOpenRsp)
2024-03-30 16:14:18 +11:00
2024-03-30 14:13:34 +11:00
for {
select {
case <-ctx.Done():
if p.sstate == SenderUnconnected {
2024-03-30 16:48:47 +11:00
// Return immediately
2024-03-30 16:14:18 +11:00
return ctx.Err()
}
2024-03-30 14:24:16 +11:00
// Send a best-effort Router Down before returning
2024-04-21 14:18:58 +10:00
lastRISent = p.Transport.NewRDPacket(aurp.ErrCodeNormalClose)
2024-05-12 18:31:01 +10:00
if _, err := p.send(lastRISent); err != nil {
2024-03-30 14:24:16 +11:00
log.Printf("Couldn't send RD packet: %v", err)
}
2024-03-30 14:13:34 +11:00
return ctx.Err()
2024-04-20 12:01:03 +10:00
case <-rticker.C:
switch p.rstate {
case ReceiverWaitForOpenRsp:
2024-05-12 18:07:27 +10:00
if time.Since(p.lastSend) <= sendRetryTimer {
2024-03-30 16:43:14 +11:00
break
}
2024-05-12 18:07:27 +10:00
if p.sendRetries >= sendRetryLimit {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Send retry limit reached while waiting for Open-Rsp, closing connection")
p.setRState(ReceiverUnconnected)
2024-03-30 16:43:14 +11:00
break
}
// Send another Open-Req
2024-05-12 18:07:27 +10:00
p.incSendRetries()
p.bumpLastSend()
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewOpenReqPacket(nil)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send Open-Req packet: %v", err)
2024-03-30 16:43:14 +11:00
return err
}
case ReceiverConnected:
2024-03-30 16:14:18 +11:00
// Check LHFT, send tickle?
2024-05-12 18:07:27 +10:00
if time.Since(p.lastHeardFrom) <= lastHeardFromTimer {
2024-03-30 16:48:47 +11:00
break
}
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewTicklePacket()); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send Tickle: %v", err)
2024-03-30 16:48:47 +11:00
return err
}
p.setRState(ReceiverWaitForTickleAck)
2024-05-12 18:07:27 +10:00
p.resetSendRetries()
p.bumpLastSend()
2024-03-30 16:48:47 +11:00
case ReceiverWaitForTickleAck:
2024-05-12 18:07:27 +10:00
if time.Since(p.lastSend) <= sendRetryTimer {
2024-03-30 16:48:47 +11:00
break
}
2024-05-12 18:07:27 +10:00
if p.sendRetries >= tickleRetryLimit {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Send retry limit reached while waiting for Tickle-Ack, closing connection")
p.setRState(ReceiverUnconnected)
2024-05-05 17:01:23 +10:00
p.RouteTable.DeleteAURPPeer(p)
2024-03-30 16:48:47 +11:00
break
}
2024-05-12 18:07:27 +10:00
p.incSendRetries()
p.bumpLastSend()
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewTicklePacket()); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send Tickle: %v", err)
2024-03-30 16:48:47 +11:00
return err
2024-03-30 14:13:34 +11:00
}
2024-04-19 16:32:27 +10:00
// still in Wait For Tickle-Ack
2024-04-01 15:43:53 +11:00
case ReceiverWaitForRIRsp:
2024-05-12 18:07:27 +10:00
if time.Since(p.lastSend) <= sendRetryTimer {
2024-04-19 16:32:27 +10:00
break
}
2024-05-12 18:07:27 +10:00
if p.sendRetries >= sendRetryLimit {
2024-04-19 16:32:27 +10:00
log.Printf("AURP Peer: Send retry limit reached while waiting for RI-Rsp, closing connection")
p.setRState(ReceiverUnconnected)
2024-05-05 17:01:23 +10:00
p.RouteTable.DeleteAURPPeer(p)
2024-04-19 16:32:27 +10:00
break
}
// RI-Req is stateless, so we don't need to cache the one we
// sent earlier just to send it again
2024-05-12 18:07:27 +10:00
p.incSendRetries()
p.bumpLastSend()
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewRIReqPacket()); err != nil {
2024-04-19 16:32:27 +10:00
log.Printf("AURP Peer: Couldn't send RI-Req packet: %v", err)
return err
}
// still in Wait For RI-Rsp
2024-04-01 15:43:53 +11:00
case ReceiverUnconnected:
2024-04-21 14:18:58 +10:00
// Data receiver is unconnected. If data sender is connected,
// send a null RI-Upd to check if the sender is also unconnected
2024-05-12 18:07:27 +10:00
if p.sstate == SenderConnected && time.Since(p.lastSend) > sendRetryTimer {
if p.sendRetries >= sendRetryLimit {
2024-04-20 12:01:03 +10:00
log.Printf("AURP Peer: Send retry limit reached while probing sender connect, closing connection")
}
2024-05-12 18:07:27 +10:00
p.incSendRetries()
p.bumpLastSend()
2024-04-20 12:01:03 +10:00
aurp.Inc(&p.Transport.LocalSeq)
events := aurp.EventTuples{{
EventCode: aurp.EventCodeNull,
}}
2024-04-21 14:18:58 +10:00
lastRISent = p.Transport.NewRIUpdPacket(events)
2024-05-12 18:31:01 +10:00
if _, err := p.send(lastRISent); err != nil {
2024-04-20 12:01:03 +10:00
log.Printf("AURP Peer: Couldn't send RI-Upd packet: %v", err)
return err
}
p.setSState(SenderWaitForRIUpdAck)
2024-04-20 12:01:03 +10:00
}
if p.ConfiguredAddr != "" {
2024-04-20 12:01:03 +10:00
// Periodically try to reconnect, if this peer is in the config file
2024-05-12 18:07:27 +10:00
if time.Since(p.lastReconnect) <= reconnectTimer {
2024-04-20 12:01:03 +10:00
break
}
// In case it's a DNS name, re-resolve it before reconnecting
raddr, err := net.ResolveUDPAddr("udp4", p.ConfiguredAddr)
if err != nil {
log.Printf("couldn't resolve UDP address, skipping: %v", err)
break
}
log.Printf("AURP Peer: resolved %q to %v", p.ConfiguredAddr, raddr)
p.RemoteAddr = raddr
2024-05-12 18:07:27 +10:00
p.bumpLastReconnect()
p.resetSendRetries()
p.bumpLastSend()
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewOpenReqPacket(nil)); err != nil {
2024-04-20 12:01:03 +10:00
log.Printf("AURP Peer: Couldn't send Open-Req packet: %v", err)
return err
}
p.setRState(ReceiverWaitForOpenRsp)
2024-04-20 12:01:03 +10:00
}
}
case <-sticker.C:
switch p.sstate {
case SenderUnconnected:
2024-04-20 12:01:03 +10:00
// Do nothing
case SenderConnected:
2024-05-12 18:07:27 +10:00
if time.Since(p.lastUpdate) <= updateTimer {
2024-04-20 12:01:03 +10:00
break
}
2024-06-07 16:00:43 +10:00
// Are there routing updates to send?
p.pendingEventsMu.Lock()
if len(p.pendingEvents) == 0 {
p.pendingEventsMu.Unlock()
break
}
// Yes - swap the slices, release the mutex, then send them
pending := p.pendingEvents
p.pendingEvents = make(aurp.EventTuples, 0, cap(pending))
p.pendingEventsMu.Unlock()
// TODO: eliminate events that cancel out (e.g. NA then ND)
// TODO: split pending events to fit within a packet
2024-05-12 18:07:27 +10:00
p.bumpLastUpdate()
2024-06-07 16:00:43 +10:00
aurp.Inc(&p.Transport.LocalSeq)
lastRISent = p.Transport.NewRIUpdPacket(pending)
if _, err := p.send(lastRISent); err != nil {
log.Printf("AURP Peer: Couldn't send RI-Upd packet: %v", err)
return err
}
p.setSState(SenderWaitForRIUpdAck)
2024-04-20 12:01:03 +10:00
case SenderWaitForRIRspAck, SenderWaitForRIUpdAck:
2024-05-12 18:07:27 +10:00
if time.Since(p.lastSend) <= sendRetryTimer {
2024-04-20 12:01:03 +10:00
break
}
2024-04-21 14:18:58 +10:00
if lastRISent == nil {
log.Print("AURP Peer: sender retry: lastRISent = nil?")
continue
}
2024-05-12 18:07:27 +10:00
if p.sendRetries >= sendRetryLimit {
2024-04-21 14:18:58 +10:00
log.Printf("AURP Peer: Send retry limit reached, closing connection")
p.setSState(SenderUnconnected)
2024-06-07 16:00:43 +10:00
p.RouteTable.RemoveObserver(p)
2024-04-21 14:18:58 +10:00
continue
}
2024-05-12 18:07:27 +10:00
p.incSendRetries()
p.bumpLastSend()
2024-05-12 18:31:01 +10:00
if _, err := p.send(lastRISent); err != nil {
2024-04-21 14:18:58 +10:00
log.Printf("AURP Peer: Couldn't re-send %T: %v", lastRISent, err)
return err
2024-04-20 12:01:03 +10:00
}
case SenderWaitForRDAck:
2024-05-12 18:07:27 +10:00
if time.Since(p.lastSend) <= sendRetryTimer {
2024-04-20 12:01:03 +10:00
break
}
p.setSState(SenderUnconnected)
2024-06-07 16:00:43 +10:00
p.RouteTable.RemoveObserver(p)
2024-03-25 19:30:06 +11:00
}
case pkt := <-p.ReceiveCh:
2024-05-12 18:07:27 +10:00
p.bumpLastHeardFrom()
2024-03-30 15:26:23 +11:00
2024-03-30 14:13:34 +11:00
switch pkt := pkt.(type) {
case *aurp.OpenReqPacket:
if p.sstate != SenderUnconnected {
log.Printf("AURP Peer: Open-Req received but sender state is not unconnected (was %v)", p.sstate)
2024-03-30 16:14:18 +11:00
}
2024-03-30 14:13:34 +11:00
// The peer tells us their connection ID in Open-Req.
2024-04-19 14:57:25 +10:00
p.Transport.RemoteConnID = pkt.ConnectionID
2024-03-30 14:13:34 +11:00
// Formulate a response.
var orsp *aurp.OpenRspPacket
switch {
case pkt.Version != 1:
// Respond with Open-Rsp with unknown version error.
2024-04-19 14:57:25 +10:00
orsp = p.Transport.NewOpenRspPacket(0, int16(aurp.ErrCodeInvalidVersion), nil)
2024-03-30 14:13:34 +11:00
case len(pkt.Options) > 0:
// Options? OPTIONS? We don't accept no stinkin' _options_
2024-04-19 14:57:25 +10:00
orsp = p.Transport.NewOpenRspPacket(0, int16(aurp.ErrCodeOptionNegotiation), nil)
2024-03-30 14:13:34 +11:00
default:
// Accept it I guess.
2024-04-19 14:57:25 +10:00
orsp = p.Transport.NewOpenRspPacket(0, 1, nil)
2024-03-30 14:13:34 +11:00
}
2024-05-12 18:31:01 +10:00
if _, err := p.send(orsp); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send Open-Rsp: %v", err)
2024-03-30 16:48:47 +11:00
return err
2024-03-30 14:13:34 +11:00
}
2024-03-30 16:14:18 +11:00
if orsp.RateOrErrCode >= 0 {
2024-06-07 16:00:43 +10:00
// Data sender is successfully in connected state
p.setSState(SenderConnected)
2024-06-07 16:00:43 +10:00
p.RouteTable.AddObserver(p)
2024-03-30 16:14:18 +11:00
}
2024-03-30 14:13:34 +11:00
2024-03-30 18:53:31 +11:00
// If receiver is unconnected, commence connecting
if p.rstate == ReceiverUnconnected {
2024-05-12 18:07:27 +10:00
p.resetSendRetries()
p.bumpLastSend()
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewOpenReqPacket(nil)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send Open-Req packet: %v", err)
2024-03-30 18:53:31 +11:00
return err
}
p.setRState(ReceiverWaitForOpenRsp)
2024-03-30 18:53:31 +11:00
}
2024-03-30 14:13:34 +11:00
case *aurp.OpenRspPacket:
if p.rstate != ReceiverWaitForOpenRsp {
log.Printf("AURP Peer: Received Open-Rsp but was not waiting for one (receiver state was %v)", p.rstate)
2024-03-30 16:14:18 +11:00
}
2024-03-30 14:13:34 +11:00
if pkt.RateOrErrCode < 0 {
// It's an error code.
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Open-Rsp error code from peer %v: %d", p.RemoteAddr.IP, pkt.RateOrErrCode)
p.setRState(ReceiverUnconnected)
2024-03-30 18:01:28 +11:00
break
2024-03-30 14:13:34 +11:00
}
2024-04-19 16:25:39 +10:00
//log.Printf("AURP Peer: Data receiver is connected!")
p.setRState(ReceiverConnected)
2024-03-30 14:13:34 +11:00
2024-04-01 14:44:51 +11:00
// Send an RI-Req
2024-05-12 18:07:27 +10:00
p.resetSendRetries()
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewRIReqPacket()); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send RI-Req packet: %v", err)
2024-04-01 14:44:51 +11:00
return err
}
p.setRState(ReceiverWaitForRIRsp)
2024-03-30 14:13:34 +11:00
case *aurp.RIReqPacket:
if p.sstate != SenderConnected {
log.Printf("AURP Peer: Received RI-Req but was not expecting one (sender state was %v)", p.sstate)
2024-03-30 18:01:28 +11:00
}
2024-03-30 18:53:31 +11:00
2024-05-05 17:25:11 +10:00
var nets aurp.NetworkTuples
for _, r := range p.RouteTable.ValidNonAURPRoutes() {
nets = append(nets, aurp.NetworkTuple{
Extended: r.Extended,
RangeStart: r.NetStart,
RangeEnd: r.NetEnd,
Distance: r.Distance,
})
2024-03-30 20:27:24 +11:00
}
2024-04-19 14:57:25 +10:00
p.Transport.LocalSeq = 1
2024-05-05 17:25:11 +10:00
// TODO: Split tuples across multiple packets as required
2024-04-21 14:18:58 +10:00
lastRISent = p.Transport.NewRIRspPacket(aurp.RoutingFlagLast, nets)
2024-05-12 18:31:01 +10:00
if _, err := p.send(lastRISent); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send RI-Rsp packet: %v", err)
2024-04-01 14:56:49 +11:00
return err
2024-03-30 20:27:24 +11:00
}
p.setSState(SenderWaitForRIRspAck)
2024-03-30 14:13:34 +11:00
case *aurp.RIRspPacket:
if p.rstate != ReceiverWaitForRIRsp {
log.Printf("Received RI-Rsp but was not waiting for one (receiver state was %v)", p.rstate)
2024-03-30 18:01:28 +11:00
}
2024-04-01 14:56:49 +11:00
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Learned about these networks: %v", pkt.Networks)
2024-04-01 14:56:49 +11:00
2024-04-12 16:14:27 +10:00
for _, nt := range pkt.Networks {
2024-05-05 17:01:23 +10:00
p.RouteTable.InsertAURPRoute(
p,
2024-04-13 15:47:58 +10:00
nt.Extended,
ddp.Network(nt.RangeStart),
ddp.Network(nt.RangeEnd),
2024-04-26 13:22:48 +10:00
nt.Distance+1,
2024-04-13 15:47:58 +10:00
)
2024-04-12 16:14:27 +10:00
}
2024-03-30 14:13:34 +11:00
2024-04-01 14:56:49 +11:00
// TODO: track which networks we don't have zone info for, and
// only set SZI for those ?
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, aurp.RoutingFlagSendZoneInfo)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send RI-Ack packet: %v", err)
2024-04-01 14:56:49 +11:00
return err
}
2024-04-01 15:09:26 +11:00
if pkt.Flags&aurp.RoutingFlagLast != 0 {
// No longer waiting for an RI-Rsp
p.setRState(ReceiverConnected)
2024-04-01 15:09:26 +11:00
}
2024-04-01 14:56:49 +11:00
2024-03-30 14:13:34 +11:00
case *aurp.RIAckPacket:
switch p.sstate {
case SenderWaitForRIRspAck:
2024-03-30 20:27:24 +11:00
// We sent an RI-Rsp, this is the RI-Ack we expected.
case SenderWaitForRIUpdAck:
2024-03-30 20:27:24 +11:00
// We sent an RI-Upd, this is the RI-Ack we expected.
case SenderWaitForRDAck:
2024-03-30 20:27:24 +11:00
// We sent an RD... Why are we here?
continue
default:
log.Printf("AURP Peer: Received RI-Ack but was not waiting for one (sender state was %v)", p.sstate)
2024-03-30 20:27:24 +11:00
}
p.setSState(SenderConnected)
2024-05-12 18:07:27 +10:00
p.resetSendRetries()
2024-06-07 16:00:43 +10:00
p.RouteTable.AddObserver(p)
2024-03-30 20:27:24 +11:00
// If SZI flag is set, send ZI-Rsp (transaction)
if pkt.Flags&aurp.RoutingFlagSendZoneInfo != 0 {
2024-05-05 17:25:11 +10:00
// Inspect last routing info packet sent to determine
// networks to gather names for
var nets []ddp.Network
switch last := lastRISent.(type) {
case *aurp.RIRspPacket:
for _, nt := range last.Networks {
nets = append(nets, nt.RangeStart)
}
case *aurp.RIUpdPacket:
for _, et := range last.Events {
// Only networks that were added
if et.EventCode != aurp.EventCodeNA {
continue
}
nets = append(nets, et.RangeStart)
}
2024-03-30 20:27:24 +11:00
}
2024-05-05 17:25:11 +10:00
zones := p.RouteTable.ZonesForNetworks(nets)
// TODO: split ZI-Rsp packets similarly to ZIP Replies
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewZIRspPacket(zones)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send ZI-Rsp packet: %v", err)
2024-03-30 20:27:24 +11:00
}
}
// TODO: Continue sending next RI-Rsp (streamed)?
2024-03-30 14:13:34 +11:00
if p.rstate == ReceiverUnconnected {
2024-04-23 17:05:06 +10:00
// Receiver is unconnected, but their receiver sent us an
// RI-Ack for something
// Try to reconnect?
2024-05-12 18:07:27 +10:00
p.resetSendRetries()
p.bumpLastSend()
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewOpenReqPacket(nil)); err != nil {
2024-04-23 17:05:06 +10:00
log.Printf("AURP Peer: Couldn't send Open-Req packet: %v", err)
return err
}
p.setRState(ReceiverWaitForOpenRsp)
2024-04-23 17:05:06 +10:00
}
2024-03-30 14:13:34 +11:00
case *aurp.RIUpdPacket:
var ackFlag aurp.RoutingFlag
2024-04-19 16:48:59 +10:00
for _, et := range pkt.Events {
log.Printf("AURP Peer: RI-Upd event %v", et)
switch et.EventCode {
case aurp.EventCodeNull:
// Do nothing except respond with RI-Ack
case aurp.EventCodeNA:
2024-05-05 17:01:23 +10:00
if err := p.RouteTable.InsertAURPRoute(
p,
et.Extended,
et.RangeStart,
et.RangeEnd,
et.Distance+1,
); err != nil {
log.Printf("AURP Peer: couldn't insert route: %v", err)
}
ackFlag = aurp.RoutingFlagSendZoneInfo
case aurp.EventCodeND:
2024-05-05 17:01:23 +10:00
p.RouteTable.DeleteAURPPeerNetwork(p, et.RangeStart)
case aurp.EventCodeNDC:
2024-05-05 17:01:23 +10:00
p.RouteTable.UpdateAURPRouteDistance(p, et.RangeStart, et.Distance+1)
case aurp.EventCodeNRC:
// "An exterior router sends a Network Route Change
// (NRC) event if the path to an exported network
// through its local internet changes to a path through
// a tunneling port, causing split-horizoned processing
// to eliminate that networks routing information."
2024-05-05 17:01:23 +10:00
p.RouteTable.DeleteAURPPeerNetwork(p, et.RangeStart)
case aurp.EventCodeZC:
// "This event is reserved for future use."
}
2024-04-19 16:48:59 +10:00
}
2024-03-30 14:13:34 +11:00
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, ackFlag)); err != nil {
2024-04-19 17:10:00 +10:00
log.Printf("AURP Peer: Couldn't send RI-Ack: %v", err)
return err
}
2024-03-30 14:13:34 +11:00
case *aurp.RDPacket:
if p.rstate == ReceiverUnconnected || p.rstate == ReceiverWaitForOpenRsp {
log.Printf("AURP Peer: Received RD but was not expecting one (receiver state was %v)", p.rstate)
2024-03-30 18:01:28 +11:00
}
2024-03-30 16:16:46 +11:00
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Router Down: error code %d %s", pkt.ErrorCode, pkt.ErrorCode)
2024-05-05 17:01:23 +10:00
p.RouteTable.DeleteAURPPeer(p)
2024-04-19 16:25:39 +10:00
2024-03-30 16:14:18 +11:00
// Respond with RI-Ack
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewRIAckPacket(pkt.ConnectionID, pkt.Sequence, 0)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send RI-Ack: %v", err)
2024-03-30 16:48:47 +11:00
return err
2024-03-30 16:14:18 +11:00
}
2024-04-20 12:01:03 +10:00
// Connections closed
p.disconnect()
2024-03-30 14:13:34 +11:00
case *aurp.ZIReqPacket:
2024-04-19 16:48:59 +10:00
// TODO: split ZI-Rsp packets similarly to ZIP Replies
2024-05-05 17:01:23 +10:00
zones := p.RouteTable.ZonesForNetworks(pkt.Networks)
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewZIRspPacket(zones)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send ZI-Rsp packet: %v", err)
2024-04-01 15:33:57 +11:00
return err
2024-04-01 14:56:49 +11:00
}
2024-03-30 14:13:34 +11:00
case *aurp.ZIRspPacket:
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Learned about these zones: %v", pkt.Zones)
2024-04-14 18:29:29 +10:00
for _, zt := range pkt.Zones {
2024-05-05 17:59:49 +10:00
p.RouteTable.AddZonesToNetwork(zt.Network, zt.Name)
2024-04-14 18:29:29 +10:00
}
2024-03-30 14:13:34 +11:00
2024-04-01 15:33:57 +11:00
case *aurp.GDZLReqPacket:
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewGDZLRspPacket(-1, nil)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send GDZL-Rsp packet: %v", err)
2024-04-01 15:33:57 +11:00
return err
}
case *aurp.GDZLRspPacket:
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Received a GDZL-Rsp, but I wouldn't have sent a GDZL-Req - that's weird")
2024-04-01 15:33:57 +11:00
case *aurp.GZNReqPacket:
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewGZNRspPacket(pkt.ZoneName, false, nil)); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send GZN-Rsp packet: %v", err)
2024-04-01 15:33:57 +11:00
return err
}
case *aurp.GZNRspPacket:
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Received a GZN-Rsp, but I wouldn't have sent a GZN-Req - that's weird")
2024-04-01 15:33:57 +11:00
2024-03-30 14:13:34 +11:00
case *aurp.TicklePacket:
2024-03-30 15:26:23 +11:00
// Immediately respond with Tickle-Ack
2024-05-12 18:31:01 +10:00
if _, err := p.send(p.Transport.NewTickleAckPacket()); err != nil {
2024-04-19 16:25:39 +10:00
log.Printf("AURP Peer: Couldn't send Tickle-Ack: %v", err)
2024-03-30 16:48:47 +11:00
return err
2024-03-30 14:13:34 +11:00
}
case *aurp.TickleAckPacket:
if p.rstate != ReceiverWaitForTickleAck {
log.Printf("AURP Peer: Received Tickle-Ack but was not waiting for one (receiver state was %v)", p.rstate)
2024-03-30 16:14:18 +11:00
}
p.setRState(ReceiverConnected)
2024-03-25 19:30:06 +11:00
}
}
}
}