roo_transport
API Documentation for roo_transport
Loading...
Searching...
No Matches
protocol.h
Go to the documentation of this file.
1#pragma once
2
4
5namespace roo_transport {
6namespace internal {
7
8// Protocol description:
9//
10// This protocol implements reliable point-to-point bidirectional streaming over
11// a lossy packet-based transport. It implements packet deduplication,
12// reordering, retransmission, and flow control.
13//
14// The peers establish the connection by means of a handshake protocol, vaguely
15// similar to the TCP handshake protocol. Each side generates a random 32-bit
16// stream ID to identify itself. (The ID helps the peer to detect and ignore
17// stale packets from previous connections, e.g. after the microcontroller has
18// been reset). Each peer sends a handshake 'CONN' packet, including its stream
19// ID and a randomly generated initial sequence number. Upon receiving a 'CONN'
20// packet, the peer responds by sending a handshake 'CONN/ACK' packet,
21// confirming reception of the peer's stream ID and initial sequence number, and
22// sending its own stream ID and initial sequence number. The initiator of the
23// connection responds by sending a final handshake 'ACK' packet.
24//
25// Once the handshake is concluded, each side may send and receive data.
26// Increasing sequence numbers are used to label the outgoing data packets, and
27// to acknowledge reception of incoming data packets. Each side maintains a
28// window of incoming and outgoing data packets, to implement flow control and
29// to allow for retransmission of lost packets.
30//
31// The protocol allows the following type of packets:
32// * 'handshake', used for the handshake protocol described above;
33// * 'data', carrying application data;
34// * 'final data', indicating end-of-stream;
35// * 'data ack', acknowledging reception of data packets;
36// * 'flow control', indicating the maximum sequence number that the recipient
37// has space to receive.
38//
39// Each packet consists of a 16-bit header, and an optional payload. The format
40// of the header is the following:
41// * bit 15 (the most significant bit): the 'control' bit;
42// * bits 14-12: the packet type (one of the values defined in the PacketType
43// enum below);
44// * bits 11-0: the packet's sequence number.
45//
46// The 'control' bit is used to detect and ignore cross-talk packets (the
47// packets originating from our own transmitter, rather than from the peer).
48// Cross-talk can happen e.g. when a remote peer gets physically disconnected.
49// The two long parallel TX and RX wires, now unconnected at the far end, act as
50// a capacitor, and, at high baud rates, can cause electrical coupling between
51// the local TX and RX pins.
52//
53// An easy way to work around cross-talk would be to include the stream ID in
54// each packet (similarly to how it is done in IP). However, that would add 4
55// bytes of overhead to each packet, which is significant when the packets are
56// small. Instead, we use the single 'control' bit to differentiate between the
57// two sides of the connection. The rule is that whichever side has the larger
58// stream ID sets the control bit in all its outgoing packets; the other side
59// clears the control bit in all its outgoing packets. This way, both sides can
60// easily identify and ignore cross-talk packets.
61//
62// Control bit is always zero for handshake packets, since the stream IDs are
63// not known yet at that point. During handshake, reception of a CONN packet
64// with stream ID and sequence ID identical to our own is interpreted as
65// cross-talk. (Probability of that happening by chance is less than 6e-14).
66//
67// Packet payload formats and semantics:
68//
69// * 'handshake' packet:
70// Used in the handshake protocol. The payload consists of 9 bytes. The bytes
71// 1-4 contain the sender's 32-bit stream ID (in the network order). The bytes
72// 5-8 contain the acknowledgement of the previously received peer's 32-bit
73// stream ID (in the network order), or zero if we don't know it yet. In the
74// last byte, the most significant bit indicates whether the sender expects an
75// acknowledgement of the handshake (1 indicates that the ack is requested),
76// and the 4 least significant bits communicate the peer's receive buffer
77// size, as a power of 2 (valid values are 0-12, indicating buffer sizes of
78// 1-4096 packets). Remaining bits are reserved and must be zero.
79//
80// * 'data' packet:
81// the payload is all application data. Must not be empty.
82//
83// * 'final data' packet:
84// like 'data' packet, but indicates that the sender has no more data to
85// transmit. The recipient's input stream transitions to 'end of stream' after
86// reading this packet. The sender should not send any more packets after this
87// one. The payload may be empty.
88//
89// * 'data ack' packet:
90// Sent by the recipient, to confirm reception of all packets with sequence
91// numbers preceding the sequence number carried in the header (which we call
92// 'unack_seq_number'). The (optional) payload consists of an arbitrary number
93// of bytes, which constitute the the lookahead 'ack' bitmap. That is,
94// successive bits, with most-significant bit first, indicate the 'ack' status
95// of packets with subsequent sequence numbers, starting with unack_seq_number
96// + 1. (Knowing that some packets have been received allows the sender to
97// avoid needless retransmissions).
98//
99// * 'flow control' packet:
100// Sent by the recipient, to indicate maximum sequence number that the
101// recipient has space to receive.
102
110
111inline bool GetPacketControlBit(uint16_t header) {
112 return (header & 0x8000) != 0;
113}
114
115inline PacketType GetPacketType(uint16_t header) {
116 return (PacketType)((header & 0x7FFF) >> 12);
117}
118
119// Control bit differentiates between the two sides of the connection. It is
120// determined by whichever side happens to use the larger stream ID.
121inline uint16_t FormatPacketHeader(SeqNum seq, PacketType type,
122 bool control_bit) {
123 return (seq.raw() & 0x0FFF) | (type << 12) | (control_bit ? 0x8000 : 0);
124}
125
126inline void SetPacketHeaderTypeFin(uint16_t& header) {
127 DCHECK_LE(header & 0x7000, 1) << "Must be 'data' or 'final data' packet";
128 header |= 0x1000; // Set the 'final' type.
129}
130
131} // namespace internal
132} // namespace roo_transport
void SetPacketHeaderTypeFin(uint16_t &header)
Definition protocol.h:126
PacketType GetPacketType(uint16_t header)
Definition protocol.h:115
uint16_t FormatPacketHeader(SeqNum seq, PacketType type, bool control_bit)
Definition protocol.h:121
bool GetPacketControlBit(uint16_t header)
Definition protocol.h:111