jrouter/aurp/transport.go
2024-03-22 14:20:31 +11:00

99 lines
2.5 KiB
Go

package aurp
import (
"encoding/binary"
"fmt"
"io"
)
// TrHeader represent an AURP-Tr packet header. It includes the domain header.
type TrHeader struct {
DomainHeader
ConnectionID uint16
Sequence uint16
}
// WriteTo writes the encoded form of the header to w, including the domain
// header.
func (h *TrHeader) WriteTo(w io.Writer) (int64, error) {
a := acc(w)
a.writeTo(&h.DomainHeader)
a.write16(h.ConnectionID)
a.write16(h.Sequence)
return a.ret()
}
func parseTrHeader(p []byte) (TrHeader, []byte, error) {
if len(p) < 4 {
return TrHeader{}, p, fmt.Errorf("insufficient input length %d for tr header", len(p))
}
return TrHeader{
ConnectionID: binary.BigEndian.Uint16(p[:2]),
Sequence: binary.BigEndian.Uint16(p[2:4]),
}, p[4:], nil
}
// incSequence increments the sequence number.
// Note that 0 is special and 65535+1 = 1, according to AURP.
func (tr *TrHeader) incSequence() {
tr.Sequence++
if tr.Sequence == 0 {
tr.Sequence = 1
}
}
// transaction returns a new TrHeader based on this one, usable for transaction
// requests or responses.
func (tr *TrHeader) transaction() TrHeader {
return TrHeader{
DomainHeader: DomainHeader{
DestinationDI: tr.DestinationDI,
SourceDI: tr.SourceDI,
Version: 1,
Reserved: 0,
PacketType: PacketTypeRouting,
},
ConnectionID: tr.ConnectionID,
Sequence: 0, // Transaction packets all use sequence number 0.
}
}
// DataSender is used to track sender state in a one-way AURP connection.
// Note that both data senders and data recievers can send packets.
type DataSender struct {
TrHeader
}
// NewOpenRspPacket returns a new Open-Rsp packet structure.
func (ds *DataSender) NewOpenRspPacket(envFlags RoutingFlag, rateOrErr int16, opts Options) *OpenRspPacket {
return &OpenRspPacket{
Header: Header{
TrHeader: ds.transaction(),
CommandCode: CmdCodeOpenRsp,
Flags: envFlags,
},
RateOrErrCode: rateOrErr,
Options: opts,
}
}
// DataReceiver is used to track reciever state in a one-way AURP connection.
// Note that both data senders and data recievers can send packets.
type DataReceiver struct {
TrHeader
}
// NewOpenReqPacket returns a new Open-Req packet structure. By default it sets
// all SUI flags and uses version 1.
func (dr *DataReceiver) NewOpenReqPacket(opts Options) *OpenReqPacket {
return &OpenReqPacket{
Header: Header{
TrHeader: dr.transaction(),
CommandCode: CmdCodeOpenReq,
Flags: RoutingFlagAllSUI,
},
Version: 1,
Options: opts,
}
}