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 } type Transport struct { // LocalDI and RemoteDI are used for producing packets. // When sending a packet, we use LocalDI as SourceDI and RemoteDI as // DestinationDI. // (When receiving a packet, we expect to see LocalDI as DestinationDI // - but it might not be - and we expect to see RemoteDI as SourceDI.) LocalDI, RemoteDI DomainIdentifier // LocalConnID is used for packets sent in the role of data receiver. // RemoteConnID is used for packets sent in the role of data sender. LocalConnID, RemoteConnID uint16 // LocalSeq is used for packets sent (as data sender) // RemoteSeq is used to check packets received (remote is the data sender). LocalSeq, RemoteSeq uint16 } // domainHeader returns a new domain header suitable for sending a packet. func (tr *Transport) domainHeader(pt PacketType) DomainHeader { return DomainHeader{ DestinationDI: tr.RemoteDI, SourceDI: tr.LocalDI, Version: 1, Reserved: 0, PacketType: pt, } } // transaction returns a new TrHeader, usable for transaction requests or // responses. Both data senders and data receivers can send transactions. // It should be given one of tr.LocalConnID (as data receiver) or // tr.RemoteConnID (as data sender). func (tr *Transport) transaction(connID uint16) TrHeader { return TrHeader{ DomainHeader: tr.domainHeader(PacketTypeRouting), ConnectionID: connID, Sequence: 0, // Transaction packets all use sequence number 0. } } // sequenced returns a new TrHeader usable for sending a sequenced data packet. // Only data senders send sequenced data. func (tr *Transport) sequenced(connID, seq uint16) TrHeader { return TrHeader{ DomainHeader: tr.domainHeader(PacketTypeRouting), ConnectionID: connID, Sequence: seq, } } // NewOpenReqPacket returns a new Open-Req packet structure. By default it sets // all SUI flags and uses version 1. func (tr *Transport) NewOpenReqPacket(opts Options) *OpenReqPacket { return &OpenReqPacket{ Header: Header{ TrHeader: tr.transaction(tr.LocalConnID), CommandCode: CmdCodeOpenReq, Flags: RoutingFlagAllSUI, }, Version: 1, Options: opts, } } // NewOpenRspPacket returns a new Open-Rsp packet structure. func (tr *Transport) NewOpenRspPacket(envFlags RoutingFlag, rateOrErr int16, opts Options) *OpenRspPacket { return &OpenRspPacket{ Header: Header{ TrHeader: tr.transaction(tr.RemoteConnID), CommandCode: CmdCodeOpenRsp, Flags: envFlags, }, RateOrErrCode: rateOrErr, Options: opts, } }