RFC 908
Reliable Data Protocol
Reliable Data Protocol ๐
Okay bestie, welcome to RFC-908 ๐. This is the Reliable Data Protocol (RDP), and the title block has the tea:
- RFC: RFC-908
- Title: Reliable Data Protocol
- Authors: David Velten, Robert Hinden, Jack Sax
- Organization: BBN Communications Corporation
- Date: July 1984
- Status: a proposed protocol (more on that in the Status section ๐)
- Obsoletes / updates: the title block doesn't list anything it obsoletes or updates โจ
Status of This Memo ๐
So this RFC specifies a proposed protocol for the ARPA Internet community ๐, and it's literally asking people to discuss it and send suggestions for improvements ๐ฌ. Distribution of this memo is unlimited ๐ฆ.
Table of Contents ๐ง
1 Introduction.......................................... 1
2 General Description................................... 3
2.1 Motivation.......................................... 3
2.2 Relation to Other Protocols......................... 5
3 Protocol Operation.................................... 7
3.1 Protocol Service Objectives......................... 7
3.2 RDP Connection Management........................... 7
3.2.1 Opening a Connection.............................. 8
3.2.2 Ports............................................. 8
3.2.3 Connection States................................. 8
3.2.4 Connection Record................................ 11
3.2.5 Closing a Connection............................. 13
3.2.6 Detecting an Half-Open Connection................ 14
3.3 Data Communication................................. 14
3.4 Reliable Communication............................. 15
3.4.1 Segment Sequence Numbers......................... 15
3.4.2 Checksums........................................ 16
3.4.3 Positive Acknowledgement of Segments............. 16
3.4.4 Retransmission Timeout........................... 17
3.5 Flow Control and Window Management................. 17
3.6 User Interface..................................... 19
3.7 Event Processing................................... 20
3.7.1 User Request Events.............................. 21
3.7.2 Segment Arrival Events........................... 24
3.7.3 Timeout Events................................... 29
4 RDP Segments and Formats............................. 31
4.1 IP Header Format................................... 31
4.2 RDP Header Format.................................. 32
4.2.1 RDP Header Fields................................ 33
4.3 SYN Segment........................................ 36
4.3.1 SYN Segment Format............................... 36
4.3.2 SYN Segment Fields............................... 37
4.4 ACK Segment........................................ 38
4.4.1 ACK Segment Format............................... 38
4.4.2 ACK Segment Fields............................... 39
4.5 Extended ACK Segment............................... 40
4.5.1 EACK Segment Format.............................. 40
4.5.2 EACK Segment Fields.............................. 40
4.6 RST Segment........................................ 42
4.6.1 RST Segment Format............................... 42
4.7 NUL Segment........................................ 43
4.7.1 NUL segment format............................... 43
5 Examples of Operation................................ 45
5.1 Connection Establishment........................... 45
5.2 Simultaneous Connection Establishment.............. 46
5.3 Lost Segments...................................... 47
5.4 Segments Received Out of Order..................... 48
5.5 Communication Over Long Delay Path................. 49
5.6 Communication Over Long Delay Path With Lost
Segments
.................................................... 50
5.7 Detecting a Half-Open Connection on Crash
Recovery
.................................................... 51
5.8 Detecting a Half-Open Connection from the
Active Side
.................................................... 52
A Implementing a Minimal RDP........................... 53
FIGURES
1 Relation to Other Protocols............................ 5
2 Form of Data Exchange Between Layers................... 6
3 RDP Connection State Diagram.......................... 10
4 Segment Format........................................ 31
5 RDP Header Format..................................... 32
6 SYN Segment Format.................................... 37
7 ACK Segment Format.................................... 38
8 EACK Segment Format................................... 41
9 RST Segment Format.................................... 42
10 NUL Segment Format................................... 43
1. Introduction โจ
The Reliable Data Protocol (RDP) is designed to give packet-based applications, like remote loading and debugging ๐ ๏ธ, a reliable data transport service. It's meant to be simple to implement but still efficient in environments with long transmission delays and with loss or non-sequential delivery of message segments ๐ข.
Okay so, RDP was designed with stuff like remote loading and debugging in mind, but it may also be suitable for other apps that need reliable message services ๐ฌ. Think computer mail, file transfer, transaction processing, etc. It's giving versatile ๐ .
The concepts came from a bunch of places ๐. The authors wanted to give credit to Eric Rosen, Rob Gurwitz, and Jack Haverty ๐ซถ. They also acknowledge material adapted from "RFC-793, The Transmission Control Protocol", edited by Jon Postel ๐. Thanks to John Linn for the checksum algorithm ๐.
2. General Description ๐
2.1. Motivation ๐
RDP is a transport protocol built to efficiently support bulk transfer of data for host monitoring and control apps, like loading/dumping and remote debugging ๐ฅ๏ธ. It only provides the services it really needs, so it stays efficient in operation and small in size ๐. Before designing it, the authors had to figure out the minimum set of transport functions that would satisfy what these apps need ๐ง .
Here's the list of requirements for a transport protocol like this ๐:
- Reliable delivery is required. When you load or dump a memory image, every memory segment has to get delivered. A 'hole' left in the memory image is not acceptable ๐ โโ๏ธ. But the internet is a lossy place where packets can get damaged or lost ๐ญ. So a positive acknowledgement and retransmission mechanism is a necessary part of the protocol ๐.
- Bulk transfers need to be efficient. Loading and dumping memory images means moving big amounts of data over a lossy network with potentially long delays ๐. So the protocol has to move data efficiently. In particular, unnecessary retransmission of segments should be avoided ๐ซ. If one segment gets lost but the ones after it arrive fine, the protocol should not require retransmitting all of the segments ๐.
- Sequenced delivery isn't always needed. Loading and dumping don't necessarily need segments delivered in sequence, as long as they all eventually arrive ๐ธ. So the protocol doesn't need to force sequenced delivery. For these kinds of apps, segments can be delivered in the order they arrive โจ.
- Some apps do need sequenced delivery. Sometimes an app needs to know that a piece of data was delivered before it sends the next thing ๐. For example, a debugger wants to know that a command inserting a breakpoint into a host memory image was delivered before it sends a "proceed" command ๐. If those segments arrived out of sequence, the intended results wouldn't happen ๐. So the protocol should let a user optionally specify that a connection must deliver segments in sequence-number order ๐ข.
- These apps are simple to packetize. Loading/dumping and debugging are well-defined, and they lend themselves to easy packetization of the transferred data ๐ฆ. They don't need a complex byte-stream transfer mechanism ๐ โโ๏ธ.
To combine bulk data transfer with reliable delivery, you need a connection-oriented protocol that uses a three-way handshake to synchronize sequence numbers ๐ค. Now, this protocol ends up looking kinda like TCP in complexity, so why didn't they just pick TCP? ๐ค Good question! The answer is that TCP has some disadvantages for these apps ๐ซ . Specifically:
- TCP is built for a more general environment. It supports transferring a stream of bytes between two communicating parties ๐. TCP is best suited to situations where there's no obvious demarcation of data in an exchange ๐งฉ. A lot of the difficulty in building a TCP implementation comes from supporting that general byte-stream transfer, so a big chunk of complexity can be avoided by using another protocol ๐งน. And that's not just an implementation thing. It's an efficiency thing too โก.
- TCP forces unnecessary retransmission. TCP doesn't let a byte be acknowledged until all prior bytes have been acknowledged ๐. That often forces unnecessary retransmission of data ๐. So it doesn't meet another one of the requirements above ๐.
- TCP forces sequenced delivery. TCP gives the application sequenced delivery of data ๐. If the app doesn't need that, a lot of resources get wasted providing it ๐๏ธ. For example, buffers can get tied up holding data until a segment with an earlier sequence number shows up ๐ฉ. The protocol should not force its segment-sequencing desires on the application ๐ โโ๏ธ๐ .
RDP supports a much simpler set of functions than TCP ๐ง. Its flow control, buffering, and connection management schemes are considerably simpler and less complex ๐ซง. The goal is a protocol that can be implemented easily and efficiently and that will serve a whole range of applications ๐.
Okay so RDP can also be trimmed down to make an implementation smaller ๐ For example, a target processor that needs to be downloaded to from another host might only run an RDP module that supports the passive Open function and one single connection. The module might also choose not to implement out-of-sequence acknowledgements ๐ง
2.2. Relation to Other Protocols ๐ฆ
RDP is a transport protocol that fits into the layered internet protocol environment. Figure 1 shows where RDP sits in the protocol hierarchy ๐
+------+ +-----+ +-----+ +------+
|TELNET| | FTP | |Debug| ... |Loader| Application Layer
+------+ +-----+ +-----+ +------+
| | | |
+-----+----+ +------+------+
| |
+------+ +-------+
| TCP | | RDP | Transport Layer
+------+ +-------+
| |
+--------------------------------+
| Internet Protocol & ICMP | Internetwork Layer
+--------------------------------+
|
+-------------------------+
| Network Access Protocol | Network Layer
+-------------------------+
Relation to Other Protocols, Figure 1
RDP gives the application layer a reliable message transport service ๐ธ The interface between users and RDP moves data in units of messages. When it's implemented in the internet environment, RDP is layered on the Internet Protocol (IP), which gives RDP an unreliable datagram service. Data crosses the RDP/IP interface in the form of segments. RDP uses the standard IP interface primitives to send and receive RDP segments as IP datagrams. At the internet level, IP exchanges datagrams with the network layer. An internet packet MAY contain an entire datagram or a fragment of a datagram โจ
# %
? * !
@ )
+------+ +-----+ +----+ $ = ^ +
| |Messages | |Segments | | Datagrams *
| User |<------->| RDP |<------->| IP |<-------> Internet
| | | | | | , ?
+------+ +-----+ +----+ ! )
* % $
@ ^ !
Form of Data Exchange Between Layers, Figure 2
If internetwork services aren't required, it SHOULD be possible to use RDP without the IP layer ๐ As long as the encapsulating protocol gives RDP the necessary information, like addressing and protocol demultiplexing, it SHOULD be possible to run RDP layered on a variety of different protocols ๐
3. Protocol Operation ๐
3.1. Protocol Service Objectives
The RDP protocol has the following goals ๐
- RDP will provide a full-duplex communications channel between the two ports of each transport connection.
- RDP will attempt to reliably deliver all user messages and will report a failure to the user if it cannot deliver a message. RDP extends the datagram service of IP to include reliable delivery.
- RDP will attempt to detect and discard all damaged and duplicate segments. It will use a checksum and sequence number in each segment header to achieve this goal.
- RDP will optionally provide sequenced delivery of segments. Sequenced delivery of segments MUST be specified when the connection is established.
- RDP will acknowledge segments received out of sequence, as they arrive. This will free up resources on the sending side.
3.2. RDP Connection Management
RDP is a connection-oriented protocol in which each connection acts as a full-duplex communication channel between two processes ๐ Segments from a sender are directed to a port on the destination host. The two 8-bit source and destination port identifiers in the RDP header are used in conjunction with the network source and destination addresses to uniquely identify each connection ๐ฅ
3.2.1. Opening a Connection
Connections are opened by issuing the Open request, which can be either active or passive. A passive Open request puts RDP into the Listen state, during which it passively listens for a request to open a connection from a remote site. The active Open request attempts to establish a connection with a specified port at a remote site.
The active Open request requires that a specific remote port and host address be specified with the request. The passive Open MAY optionally specify a specific remote port and network address, or it MAY specify that an open be accepted from anyone. If a specific remote port and host address were specified, an arriving request to open a connection MUST exactly match the specified remote port and address ๐ซถ
3.2.2. Ports
Valid port numbers range from 1 to 255 (decimal). There are two types of ports: "well known" ports and "allocable" ports. Well-known ports have numbers in the range 1 to 63 (decimal) and allocable ports are given numbers in the range 64 to 255 ๐ฆ
The user, when issuing an active Open request, MUST specify both the remote host and port and MAY optionally specify the local port. If the local port was not specified, RDP will select an unused port from the range of allocable ports. When issuing a passive Open request, the user MUST specify the local port number. Generally, in this case the local port will be a well-known port ๐
3.2.3. Connection States
An RDP connection will progress through a series of states during its lifetime. The states are shown in Figure 3 and are individually described below. In Figure 3, the boxes represent the states of the RDP FSM and the arcs represent changes in state. Each arc is annotated with the event causing the state change and the resulting output ๐
CLOSED
The CLOSED state exists when no connection exists and there is no connection record allocated ๐ง
LISTEN
The LISTEN state is entered after a passive Open request is processed. A connection record is allocated and RDP waits for an active request to establish a connection from a remote site ๐
SYN-SENT
The SYN-SENT state is entered after processing an active Open request. A connection record is allocated, an initial sequence number is generated, and a SYN segment is sent to the remote site. RDP then waits in the SYN-SENT state for acknowledgement of its Open request ๐
SYN-RCVD
The SYN-RCVD state MAY be reached from either the LISTEN state or from the SYN-SENT state. SYN-RCVD is reached from the LISTEN state when a SYN segment requesting a connection is received from a remote host. In reply, the local RDP generates an initial sequence number for its side of the connection, and then sends the sequence number and an acknowledgement of the SYN segment to the remote site. It then waits for an acknowledgement ๐ซ
The SYN-RCVD state is reached from the SYN-SENT state when a SYN segment is received from the remote host without an accompanying acknowledgement of the SYN segment sent to that remote host by the local RDP. This situation is caused by simultaneous attempts to open a connection, with the SYN segments passing each other in transit. The action is to repeat the SYN segment with the same sequence number, but now including an ACK of the remote host's SYN segment to indicate acceptance of the Open request ๐คฏ
+------------+
Passive Open | |<-------------------------+
+----------------| CLOSED | |
| Request | |---------------+ |
V +------------+ | |
+------------+ | |
| | | |
| LISTEN | | |
| | | |
+------------+ | |
| Active | |
| rcv SYN Open Request | |
| ----------- ------------ | |
| snd SYN,ACK snd SYN | |
V rcv SYN V |
+------------+ ----------- +------------+ |
| | snd SYN,ACK | | |
| SYN-RCVD |<-------------------------------| SYN-SENT | |
| | | | |
+------------+ +------------+ |
| rcv ACK rcv SYN,ACK | |
| ---------- ------------- | |
| xxx +------------+ snd ACK | |
| | | | |
+--------------->| OPEN |<--------------+ |
| | |
+------------+ |
rcv RST | Close request |
----------- | --------------- |
xxx | snd RST |
V |
+------------+ |
| | |
| CLOSE-WAIT |--------------------------+
| | After a Delay
+------------+
RDP Connection State Diagram, Figure 3
OPEN
The OPEN state is when a connection is fully set up ๐คโจ, after both sides have swapped their state info. Each side has exchanged and received things like the initial sequence number, the maximum segment size, and the maximum number of unacknowledged segments that can be outstanding. Once you're in the OPEN state, data can flow between the two parties ๐.
CLOSE-WAIT
The CLOSE-WAIT state gets entered from either a Close request or from receiving an RST segment from the remote site ๐ฅน. RDP has sent an RST segment and is waiting a delay period for activity on the connection to finish up โณ.
3.2.4 Connection Record
Okay bestie, every connection keeps its state in a connection record ๐. This section names some of the variables you'd usually find in a typical RDP connection record. It is not an implementation spec, and it isn't a complete list either. We're naming these fields just to make it easier to talk about how RDP works, especially event processing ๐ง .
The connection record fields and what they mean:
STATE
- The current state of the connection. Legal values are
OPEN,LISTEN,CLOSED,SYN-SENT,SYN-RCVD, andCLOSE-WAIT๐ฅ.
Send Sequence Number Variables:
SND.NXT: The sequence number of the next segment that is to be sent ๐ค.SND.UNA: The sequence number of the oldest unacknowledged segment.SND.MAX: The maximum number of outstanding (unacknowledged) segments that can be sent. The sender should not send more than this number of segments without getting an acknowledgement ๐ฆ.SND.ISS: The initial send sequence number. This is the sequence number that was sent in theSYNsegment ๐ฑ.
Receive Sequence Number Variables:
RCV.CUR: The sequence number of the last segment received correctly and in sequence โ .RCV.MAX: The maximum number of segments that can be buffered for this connection ๐งบ.RCV.IRS: The initial receive sequence number. This is the sequence number of theSYNsegment that established this connection ๐ท.RCVDSEQNO[n]: The array of sequence numbers of segments that have been received and acknowledged out of sequence ๐งฉ.
Other Variables:
CLOSEWAIT: A timer used to time out theCLOSE-WAITstate โฐ.SBUF.MAX: The largest possible segment (in octets) that can legally be sent. This variable is specified by the foreign host in theSYNsegment during connection establishment ๐ค.RBUF.MAX: The largest possible segment (in octets) that can be received. This variable is specified by the user when the connection is opened. The variable is sent to the foreign host in theSYNsegment ๐.
Variables from Current Segment:
SEG.SEQ: The sequence number of the segment currently being processed ๐.SEG.ACK: The acknowledgement sequence number in the segment currently being processed ๐.SEG.MAX: The maximum number of outstanding segments the receiver is willing to hold, as specified in theSYNsegment that established the connection ๐ซง.SEG.BMAX: The maximum segment size (in octets) accepted by the foreign host on a connection, as specified in theSYNsegment that established the connection ๐ฆ.
3.2.5 Closing a Connection
So, closing a connection can start from a Close request from the user process, or when an RST segment shows up from the other end ๐ช. For a Close request, RDP sends an RST segment to the other side and then enters the CLOSE-WAIT state for a period of time ๐
. While it's in CLOSE-WAIT, RDP throws away any segments that come in from the other side ๐๏ธ. When the timeout runs out, the connection record gets deallocated and the connection ceases to exist ๐.
This closing feature is pretty simple, and that's the catch: users have to make sure all their data has been reliably delivered before they ask to close the connection ๐.
3.2.6 Detecting an Half-Open Connection
If one side of a connection crashes, the other side might still be active and holding on to the connection. That's called a half-open connection ๐ซ . In lots of cases, the active RDP will eventually notice and reset ๐. Usually, recovery happens through user activity, or when the crashed host tries to re-establish the connection ๐ค.
But sometimes recovery can't happen without RDP doing something on its own. For example, if all connection blocks are in use, attempts to re-establish a broken connection will be rejected ๐ซ. In that situation, RDP may try to free up resources by checking that connections are still fully open. It does this by sending a NUL segment to each of the other RDPs ๐จ. An acknowledgement means the connection is still open and valid โ
.
To keep network overhead low, connections should only be verified when it's really needed to prevent a deadlock situation ๐. Only inactive connections should be verified ๐ค. An inactive connection is one that has no outstanding unacknowledged segments, has no segments in the user input or output queues, and hasn't had any traffic for some period of time ๐ด.
3.3 Data Communication
Data flows through an RDP connection as segments ๐. Each user message submitted with a Send request gets packaged for transport as a single RDP segment ๐. Each RDP segment is made of an RDP header plus one or more octets of data. RDP will not attempt to fragment a large user message into smaller segments and reassemble it on the receiving end ๐ โโ๏ธ. That's different from a byte-stream protocol like TCP, which supports transferring an indeterminate-length stream of data between ports and buffers data until the receiver asks for it ๐.
At the RDP level, outgoing segments are queued as input to the IP layer as they're created ๐ฆ. Each segment is held by the sending RDP until the foreign host acknowledges it ๐คฒ. Incoming segments are queued as input to the user process through the user interface ๐ฅ. Segments get acknowledged once the receiving RDP has accepted them ๐.
The receiving end of each connection specifies the maximum segment size it will accept. Any attempt by the sender to transmit a larger segment is an error ๐จ. If RDP determines that a buffer submitted with a Send request is bigger than the maximum segment size allowed on the connection, RDP will return an error to the user ๐
. On top of that, RDP will abort a connection with an RST segment if an incoming segment has more data than the maximum acceptable segment size. No attempt will be made to recover from or otherwise overcome this error condition ๐.
If sequenced delivery of segments is necessary for a connection, that requirement has to be stated when the connection is established ๐. Sequenced delivery is specified when the Open request is made. After that, sequenced delivery is the mode of delivery for the entire life of the connection ๐.
3.4 Reliable Communication
RDP gives you a reliable message service through a bunch of mechanisms ๐ก๏ธโจ. These include adding sequence numbers and checksums to segments, positively acknowledging receipt of segments, and timing out and retransmitting missing segments ๐๐.
3.4.1 Segment Sequence Numbers
Every segment carrying data has a sequence number that uniquely identifies it among all the other segments in the same connection ๐ชช. The initial sequence number is chosen when the connection is opened, and it's picked by reading a value from a monotonically increasing clock โฑ๏ธ. Each time a segment containing data is transmitted, the sequence number goes up ๐. Segments with no data don't increment the sequence number. The exceptions are the SYN and NUL segments, which can't contain data ๐. The SYN segment is always sent with a unique sequence number, which is the initial sequence number ๐. The NUL segment is sent with the next valid sequence number ๐ฏ.
3.4.2 Checksums
Each RDP segment has a checksum so the receiver can detect damaged segments ๐. RDP uses a non-linear checksum algorithm to compute a 32-bit-wide checksum that works on data in units of four octets (32 bits) ๐งฎ. The checksum covers both the RDP header and the RDP data area ๐งพ.
If a segment's header and data octets don't add up to an integral multiple of 4 octets, the last octet gets padded on the right with zeros to make a 32-bit quantity for the computation ๐ช. Those padding zeros are not transmitted as part of the segment ๐ซฅ. While computing the checksum, the checksum field itself is replaced with zeros 0๏ธโฃ. The actual algorithm is described in Section 4.2.1 ๐.
3.4.3 Positive Acknowledgement of Segments
RDP assumes it only has an unreliable datagram service to deliver segments ๐ฌ. To guarantee delivery in that environment, RDP uses positive acknowledgement and retransmission of segments ๐. Each segment containing data, plus the SYN and NUL segments, gets acknowledged once it's correctly received and accepted by the destination host ๐ค. Segments that only contain an acknowledgement aren't acknowledged themselves ๐
. Damaged segments are discarded and not acknowledged ๐๏ธ. Segments are retransmitted when the destination host doesn't acknowledge them in a timely way โฐ.
RDP allows two types of acknowledgement ๐. A cumulative acknowledgement is used to acknowledge all segments up to a specified sequence number ๐. This type can be sent using fixed-length fields within the RDP header ๐งฑ. Specifically, the ACK control flag is set and the last acknowledged sequence number goes into the Acknowledgement Number field ๐.
The extended or non-cumulative acknowledgement lets the receiver acknowledge segments out of sequence ๐งฉ. This type gets sent using the EACK control flag and the
Okay so picking up right where the variable length header fields ๐ are carrying the sequence numbers of the out-of-sequence segments that got acked. The type of ack is basically decided by the order segments show up in โจ. Whenever it can, the receiver uses the cumulative acknowledgement segment. Only out-of-sequence segments get the extended acknowledgement option ๐ฆ
The user process can't pick the ack type when it opens the connection, bestie ๐ A receiver can skip out-of-sequence acks completely if it wants, and on the flip side the sender can just ignore them ๐
3.4.4. Retransmission Timeout
Segments can go missing for two reasons ๐ญ Either the lossy media mangles or drops them, or the receiving RDP throws them away on purpose. The positive acknowledgement policy means the receiver only acks a segment once it's been correctly received and accepted โจ
So how does the sender notice something's missing? ๐ Every segment it transmits gets its own retransmission timer. That timer is set to roughly the time the segment takes to travel through the network. When an ack comes in for a segment, its timer gets cancelled ๐ If the timer runs out before that ack shows up, the segment gets retransmitted and the timer restarts ๐
3.5. Flow Control and Window Management
RDP uses a simple flow control mechanism ๐ง It's based on how many segments are sent but not yet acknowledged, compared with the maximum number of outstanding (unacknowledged) segments allowed. Every RDP connection has its own set of flow control parameters, including the maximum number of outstanding segments for each side of the connection ๐ Each side sets its own parameters when the connection is opened with the Open request. These get passed from one host to the other in the initial connection segments ๐ซถ
The values should be based on how much buffer space the RDP is willing to allocate to a connection, both in amount and in size ๐ธ Each implementation can pick values that suit its own buffering scheme. Once they're set, they stay the same for the entire life of the connection ๐
RDP uses a sequence number window to decide which segment sequence numbers are acceptable ๐ช The left edge is the last in-sequence acknowledged sequence number plus one. The right edge is the left edge plus twice the allowed maximum number of outstanding segments. That allowed maximum is how many segments the transmitting RDP software is allowed to send without getting any acknowledgement back ๐ง
Here's how it all plays out. The transmitting RDP module keeps sending segments until it hits the connection's segment limit set by the receiving process ๐ Once it's hit that limit, the transmitting RDP module can only send one new segment for each segment that's been acknowledged ๐
When a received segment's sequence number lands inside the acceptance window, it gets acknowledged ๐ If the sequence number equals the left-hand edge (so it's exactly the next sequence number expected), it gets a cumulative acknowledgement (ACK). The acceptance window then moves forward by adding one to the value of the edges โจ If the sequence number is inside the acceptance window but out of sequence, it gets a non-cumulative acknowledgement (EACK). In that case the window doesn't move, but the receipt of the out-of-sequence segment is recorded ๐
๐จ Watch out for this one: when segments get acked out of order, the transmitting RDP module must not transmit beyond the acceptance window. This can happen when one segment is never acknowledged but all the later segments are received and acked. That situation pins the left edge of the window at the sequence number of the unacknowledged segment. As more segments get transmitted, the next segment to send creeps closer and eventually runs into the right window edge. At that point, all transmission of new segments stops until the unacknowledged segment gets acknowledged ๐
3.6. User Interface
The user interface to RDP is up to each implementation ๐ It can use system calls, function calls, or some other mechanism entirely. The list of requests below isn't meant to suggest any particular implementation ๐ง
OPEN Request
Opens a connection ๐ช Parameters include type (active or passive), local port, remote port, remote host address, maximum segment size, maximum number of unacknowledged segments, and delivery mode (sequenced or non-sequenced). The connection id, including any allocated port number, is returned to the user ๐
SEND Request
Sends a user message ๐จ Parameters include connection identifier, buffer address and data count.
RECEIVE Request
Receives a user message ๐ฌ Parameters include connection identifier, buffer address and data count.
CLOSE Request
Closes a specified connection ๐ The single parameter is the connection identifier.
STATUS Request
Returns the status of a connection ๐ The parameters include the connection identifier and the address of the status buffer.
3.7. Event Processing
This section describes one possible sequence for processing events ๐ง It isn't meant to suggest a particular implementation. Any actual implementation should only differ from this description in detail, not in substance ๐ These are the kinds of events that may occur:
USER REQUESTS
Open
Send
Receive
Close
Status
ARRIVING SEGMENT
Segment Arrives
TIMEOUTS
Retransmission Timeout
Close-Wait Timeout
User request processing always ends with a return to the caller, with a possible error indication ๐ โโ๏ธ Error responses come back as a character string. Sometimes a delayed response happens too, and it gets returned to the user through whatever event or pseudo interrupt mechanism is available. The term "signal" is used to refer to delayed responses ๐
Arriving segments usually get processed like this: the sequence number is checked for validity and, if it's valid, the segment is queued and processed in sequence-number order ๐ For all events, unless a state change is specified, RDP stays in the same state ๐ซง
3.7.1. User Request Events
These scenarios show how events caused by user requests get processed ๐
Open Request
CLOSED STATE
Create a connection record
If none available
Return "Error - insufficient resources"
Endif
If passive Open
If local port not specified
Return "Error - local port not specified"
Endif
Generate SND.ISS
Set SND.NXT = SND.ISS + 1
SND.UNA = SND.ISS
Fill in SND.MAX, RMAX.BUF from Open parameters
Set State = LISTEN
Return
Endif
If active Open
If remote port not specified
Return "Error - remote port not specified"
Endif
Generate SND.ISS
Set SND.NXT = SND.ISS + 1
SND.UNA = SND.ISS
Fill in SND.MAX, RMAX.BUF from Open parameters
If local port not specified
Allocate a local port
Endif
Send <SEQ=SND.ISS><MAX=SND.MAX><MAXBUF=RMAX.BUF><SYN>
Set State = SYN-SENT
Return (local port, connection identifier)
Endif
LISTEN STATE
SYN-SENT STATE
SYN-RCVD STATE
OPEN STATE
CLOSE-WAIT STATE
Return "Error - connection already open"
Close Request
OPEN STATE
Send <SEQ=SND.NXT><RST>
Set State = CLOSE-WAIT
Start TIMWAIT Timer
Return
LISTEN STATE
Set State = CLOSED
Deallocate connection record
Return
SYN-RCVD STATE
SYN-SENT STATE
Send <SEQ=SND.NXT><RST>
Set State = CLOSED
Return
CLOSE-WAIT STATE
Return "Error - connection closing"
CLOSE STATE
Return "Error - connection not open"
Receive Request
OPEN STATE
If Data is pending
Return with data
else
Return with "no data" indication
Endif
LISTEN STATE
SYN-RCVD STATE
SYN-SENT STATE
Return with "no data" indication
CLOSE STATE
CLOSE-WAIT STATE
Return "Error - connection not open"
Send Request
OPEN STATE
If SND.NXT < SND.UNA + SND.MAX
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><Data>
Set SND.NXT = SND.NXT + 1
Return
else
Return "Error - insufficient resources to send data"
Endif
LISTEN STATE
SYN-RCVD STATE
SYN-SENT STATE
CLOSE STATE
CLOSE-WAIT STATE
Return "Error - connection not open"
Status Request
Returns with:
State of connection (OPEN, LISTEN, etc.)
Number of segments unacknowledged
Number of segments received not given to user
Maximum segment size for the send side of the connection
Maximum segment size for the receive side of the connection
3.7.2. Segment Arrival Events
These scenarios describe how the event of an RDP segment arriving from a remote host gets processed ๐ฌ They assume the segment was addressed to the local port associated with the connection record ๐ฎ
If State = CLOSED
If RST set
Discard segment
Return
Endif
If ACK or NUL set
Send <SEQ=SEG.ACK + 1><RST>
Discard segment
Return
else
Send <SEQ=0><RST><ACK=RCV.CUR><ACK>
Discard segment
Return
Endif
Endif
If State = CLOSE-WAIT, the RDP does a little housekeeping before anything else happens ๐งน
If State = CLOSE-WAIT
If RST set
Set State = CLOSED
Discard segment
Cancel TIMWAIT timer
Deallocate connection record
else
Discard segment
Endif
Return
Endif
Next up is the LISTEN state. The vibe here is "wait for someone to knock" ๐ชโจ
If State = LISTEN
If RST set
Discard the segment
Return
Endif
If ACK or NUL set
Send <SEQ=SEG.ACK + 1><RST>
Return
Endif
If SYN set
Set RCV.CUR = SEG.SEQ
RCV.IRS = SEG.SEQ
SND.MAX = SEG.MAX
SBUF.MAX = SEG.BMAX
Send <SEQ=SND.ISS><ACK=RCV.CUR><MAX=RCV.MAX><BUFMAX=RBUF.MAX>
<ACK><SYN>
Set State = SYN-RCVD
Return
Endif
If anything else (should never get here)
Discard segment
Return
Endif
Endif
Now SYN-SENT, the "I knocked, is anyone home?" state ๐ซฃ
If State = SYN-SENT
If ACK set
If RST clear and SEG.ACK != SND.ISS
Send <SEQ=SEG.ACK + 1><RST>
Endif
Discard segment; Return
Endif
If RST set
If ACK set
Signal "Connection Refused"
Set State = CLOSED
Deallocate connection record
Endif
Discard segment
Return
Endif
If SYN set
Set RCV.CUR = SEG.SEQ
RCV.IRS = SEG.SEQ
SND.MAX = SEG.MAX
RBUF.MAX = SEG.BMAX
If ACK set
Set SND.UNA = SEG.ACK
State = OPEN
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
else
Set State = SYN-RCVD
Send <SEQ=SND.ISS><ACK=RCV.CUR><MAX=RCV.MAX><BUFMAX=RBUF.MAX>
<SYN><ACK>
Endif
Return
Endif
If anything else
Discard segment
Return
Endif
Endif
Okay, SYN-RCVD is where things get spicy ๐ถ๏ธ There's a sequence number window check, then RST, SYN, EACK and ACK all get their own rules.
If State = SYN-RCVD
If RCV.IRS < SEG.SEQ =< RCV.CUR + (RCV.MAX * 2)
Segment sequence number acceptable
else
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
Discard segment
Return
Endif
If RST set
If passive Open
Set State = LISTEN
else
Set State = CLOSED
Signal "Connection Refused"
Discard segment
Deallocate connection record
Endif
Return
Endif
If SYN set
Send <SEQ=SEG.ACK + 1><RST>
Set State = CLOSED
Signal "Connection Reset"
Discard segment
Deallocate connection record
Return
Endif
If EACK set
Send <SEQ=SEG.ACK + 1><RST>
Discard segment
Return
Endif
If ACK set
If SEG.ACK = SND.ISS
Set State = OPEN
else
Send <SEQ=SEG.ACK + 1><RST>
Discard segment
Return
Endif
else
Discard segment
Return
Endif
If Data in segment or NUL set
If the received segment is in sequence
Copy the data (if any) to user buffers
Set RCV.CUR=SEG.SEQ
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
else
If out-of-sequence delivery permitted
Copy the data (if any) to user buffers
Endif
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><EACK><RCVDSEQNO1>
...<RCVDSEQNOn>
Endif
Endif
Endif
Last state up is OPEN ๐ This is the main stage where the data actually flows.
If State = OPEN
If RCV.CUR < SEG.SEQ =< RCV.CUR + (RCV.MAX * 2)
Segment sequence number acceptable
else
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
Discard segment and return
Endif
If RST set
Set State = CLOSE-WAIT
Signal "Connection Reset"
Return
Endif
If NUL set
Set RCV.CUR=SEG.SEQ
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
Discard segment
Return
Endif
If SYN set
Send <SEQ=SEG.ACK + 1><RST>
Set State = CLOSED
Signal "Connection Reset"
Discard segment
Deallocate connection record
Return
Endif
If ACK set
If SND.UNA =< SEG.ACK < SND.NXT
Set SND.UNA = SEG.ACK
Flush acknowledged segments
Endif
Endif
If EACK set
Flush acknowledged segments
Endif
If Data in segment
If the received segment is in sequence
Copy the data to user buffers
Set RCV.CUR=SEG.SEQ
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
else
If out-of-sequence delivery permitted
Copy the data to user buffers
Endif
Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><EACK><RCVDSEQNO1>
...<RCVDSEQNOn>
Endif
Endif
Endif
3.7.3. Timeout Events โฐ
Timeout events occur when a timer expires and signals the RDP. Two types of timeout events can occur, as described below:
RETRANSMISSION TIMEOUTS
If timeout on segment at head of retransmission queue
Resend the segment at head of queue
Restart the retransmission timer for the segment
Requeue the segment on retransmission queue
Return
Endif
CLOSE-WAIT TIMEOUTS
Set State = CLOSED
Deallocate connection record
Return
Chapter 4 is where we get to see what the segments actually look like! ๐
4. RDP Segments and Formats โจ
The segments sent by the application layer are encapsulated in headers by the transport, internet and network layers, as follows:
+----------------+
| Network Access |
| Header |
+----------------+
| IP Header |
+----------------+
| RDP Header |
+----------------+
| D |
| A |
| T |
| A |
+----------------+
Segment Format
Figure 4
4.1. IP Header Format ๐
When used in the internet environment, RDP segments are sent using the version 4 IP header as described in RFC791, "Internet Protocol." The RDP protocol number is ??? (decimal). The time-to-live field should be set to a reasonable value for the network.
All other fields should be set as specified in RFC-791.
4.2. RDP Header Format ๐ฆ
Every RDP segment is prefaced with an RDP header. The format of the header is shown in Figure 5 below. The RDP header is variable in length and its size is indicated by a field in a fixed location within the header.
0 0 0 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+---+---------------+
|S|A|E|R|N| |Ver| Header |
0 |Y|C|A|S|U|0|No.| Length |
|N|K|K|T|L| | | |
+-+-+-+-+-+-+---+---------------+
1 | Source Port | Dest. Port |
+---------------+---------------+
2 | Data Length |
+---------------+---------------+
3 | |
+--- Sequence Number ---+
4 | |
+---------------+---------------+
5 | |
+--- Acknowledgement Number ---+
6 | |
+---------------+---------------+
7 | |
+--- Checksum ---+
8 | |
+---------------+---------------+
9 | Variable Header Area |
. .
. .
| |
+---------------+---------------+
RDP Header Format
Figure 5
4.2.1. RDP Header Fields ๐
Control Flags
This 8-bit field occupies the first octet of word one in the header. It is bit encoded with the following bits currently defined:
Bit # Bit Name Description
0 SYN Establish connection and
synchronize sequence numbers.
1 ACK Acknowledge field significant.
2 EACK Non-cumulative (Extended) acknowledgement.
3 RST Reset the connection.
4 NUL This is a null (zero data length) segment.
5 Unused.
Note that the SYN and RST are sent as separate segments and may not contain any data. The ACK may accompany any message. The NUL segment must have a zero data length, but may be accompanied by ACK and EACK information. The other control bit is currently unused and is defined to be zero.
Version Number
This field occupies bits 6-7 of the first octet. It contains the version number of the protocol described by this document. Current value is one (1).
Header Length
The length of the RDP header in units of two (2) octets, including this field. This field allows RDP to find the start of the Data field, given a pointer to the head of the segment. This field is 8 bits in length. For a segment with no variable header section, the header length field will have the value 9.
Source and Destination Ports
The Source and Destination Ports are used to identify the processes in the two hosts that are communicating with each other. The combination of the port identifiers with the source and destination addresses in the network access protocol header serves to fully qualify the connection and constitutes the connection identifier. This permits RDP to distinguish multiple connections between two hosts. Each field is 8 bits in length, allowing port numbers from 0 to 255 (decimal).
Data Length
The length in octets of the data in this segment. The data length does not include the RDP header. This field is 16 bits in length.
Sequence Number
The sequence number of this segment. This field is 32 bits in length.
Acknowledgement Number
Okay bestie, the Acknowledgement Number is literally the header field that tells the other side what they've gotten right so far ๐ซถ If the ACK bit is set, this is the sequence number of the last segment the sender got correctly and in sequence, and once a connection is established it should always be sent. It's 32 bits long ๐ฆ
Checksum
Okay the Checksum is giving precision ๐ It's a 32-bit checksum over the segment header and data. The algorithm uses two imaginary helpers: the checksum accumulator (an actual 32-bit register where the checksum gets built) and the checksum pointer (just for explaining the process, since it's walking through the data four octets, or 32 bits, at a time. An implementation doesn't have to keep it in a register) ๐ง
- The checksum pointer is set to zero, so it lines up with the start of the area being checksummed. The checksum accumulator is also set to zero before the computation begins โจ
- The 32-bit memory word at the address the checksum pointer points to gets added arithmetically to the checksum accumulator. Any carry that comes out of the accumulator is ignored. While being added, the checksum field itself is treated as all zeros ๐ฅ
Page 34
- The checksum accumulator gets rotated left one bit position, and the checksum pointer moves forward to the next 32-bit word in the segment ๐
- Steps 2 and 3 repeat until the whole segment has been summed. If the header and data octets don't add up to a multiple of 4 octets, the last octet gets padded on the right with zeros so it becomes a full 32-bit quantity for the math ๐
Variable Header Area
This area is where the parameters for SYN and EACK segments get sent ๐
Page 35
4.3. SYN Segment
The SYN is the segment that establishes a connection and syncs sequence numbers between two hosts ๐ธ It also tells the remote host the maximum number of segments the local RDP is willing to accept and the maximum segment size it can take. A SYN can be combined with an ACK in one segment, but it is never combined with user data ๐
4.3.1. SYN Segment Format
0 0 0 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+---+---------------+
0 |1|0|0|0|0|0|0 1| Header Length |
+-+-+-+-+-+-+---+---------------+
1 | Source Port | Dest. Port |
+---------------+---------------+
2 | Data Length = 0 |
+---------------+---------------+
3 | |
+--- Sequence Number ---+
4 | |
+---------------+---------------+
5 | |
+--- Acknowledgement Number ---+
6 | |
+---------------+---------------+
7 | |
+--- Checksum ---+
8 | |
+---------------+---------------+
9 | Max. # of Outstanding Segments|
+---------------+---------------+
10 | Max. Segment Size |
+-------------------------------+
11 | Options Flag Field |
+---------------+---------------+
SYN Segment Format
Figure 6
Page 36
4.3.2. SYN Segment Fields
Sequence Number
This is the initial sequence number picked for this connection ๐ฆ
Acknowledgement Number
This field only counts if the ACK flag is set ๐ In that case it holds the sequence number of the SYN segment that came in from the other RDP.
Maximum Number of Outstanding Segments
This is how many segments can be sent without getting an acknowledgement. The receiver uses it for flow control ๐ It gets picked during connection setup and can't be changed later in the life of the connection.
Maximum Segment Size
This is the biggest segment in octets the sender should send. It basically tells the sender how big the receiver's buffers are ๐ง The size includes the IP header, the RDP header, and the data. It does not include the network access layer's header length.
Options Flag Field
This two-octet field holds a set of options flags for the optional functions wanted on this connection. The flags go like this:
Bit # Bit Name Description
0 SDM Sequenced delivery mode.
The sequenced delivery mode flag says whether segments get delivered to the user in sequence-number order (sequenced) or in arrival order no matter what the sequence number is (non-sequenced). A value of 0 means non-sequenced delivery, and a value of 1 means sequenced delivery ๐
Page 37
4.4. ACK Segment
The ACK segment acknowledges in-sequence segments, and it carries both the next send sequence number and the acknowledgement sequence number in the RDP header ๐ซถ It can be sent as its own segment, but it should be combined with data whenever possible. Data segments must always include the ACK bit and the Acknowledgement Number field โจ
4.4.1. ACK Segment Format
0 0 0 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+---+---------------+
0 |0|1|0|0|0|0|0 1| Header Length |
+-+-+-+-+-+-+---+---------------+
1 | Source Port | Dest. Port |
+---------------+---------------+
2 | Data Length |
+---------------+---------------+
3 | |
+--- Sequence Number ---+
4 | |
+---------------+---------------+
5 | |
+--- Acknowledgement Number ---+
6 | |
+---------------+---------------+
7 | |
+--- Checksum ---+
8 | |
+---------------+---------------+
| |
| Data |
. .
. .
+---------------+---------------+
ACK Segment Format
Figure 7
Page 38
4.4.2. ACK Segment Fields
Data Length
A non-zero Data Length means there's data in the segment ๐
Sequence Number
The Sequence Number only moves forward to the next sequence number if there's data in the segment. An ACK segment without data doesn't use any sequence number space ๐
Acknowledgement Number
This field holds the sequence number of the last segment received in sequential order ๐ธ
4.5. Extended ACK Segment
The EACK segment is how we acknowledge segments that showed up out of sequence ๐ญ It carries the sequence numbers of one or more segments that were received with a correct checksum but out of sequence. The EACK is always combined with an ACK in the segment, which gives the sequence number of the last segment received in sequence. An EACK segment may also include user data ๐
4.5.1. EACK Segment Format
The EACK segment has the format shown in Figure 8. ๐ง
4.5.2. EACK Segment Fields
Data Length
A non-zero Data Length means there's data in the segment โจ
Sequence Number
The Sequence Number only moves forward to the next sequence number if there's data in the segment. An EACK segment without data doesn't use any sequence number space ๐ฆ
Acknowledgement Number
This field holds the sequence number of the last segment received in sequential order ๐
Sequence # Received OK
Each entry here is the sequence number of a segment that was received with a correct checksum, but out of sequence ๐ฅ
Page 40
0 0 0 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+---+---------------+
0 |0|1|1|0|0|0|0 1| Header Length |
+-+-+-+-+-+-+---+---------------+
1 | Source Port | Dest. Port |
+---------------+---------------+
2 | Data Length |
+---------------+---------------+
3 | |
+--- Sequence Number ---|
4 | |
+---------------+---------------+
5 | |
+--- Acknowledgement Number ---+
6 | |
+---------------+---------------+
7 | |
+--- Checksum ---+
8 | |
+---------------+---------------+
9 | |
+--- Sequence # Received OK ---+
10 | |
+---------------+---------------+
11 | |
+--- Sequence # Received OK ---+
12 | |
+---------------+---------------+
: . :
: . :
: . :
+---------------+---------------+
| |
| Data |
| |
+---------------+---------------+
EACK Segment Format
Figure 8
Page 41
4.6. RST Segment ๐ฅ
okay so the RST segment is the "we are so done here" button ๐ It's how a connection gets closed or reset. When an RST shows up, the sender must stop sending and must abort any unserviced requests. Main character move: the RST goes out as its own separate segment and carries no data at all ๐ซถ
4.6.1. RST Segment Format
0 0 0 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+---+---------------+
0 |0|0|0|1|0|0|0 1| Header Length |
+-+-+-+-+-+-+---+---------------+
1 | Source Port | Dest. Port |
+---------------+---------------+
2 | Data Length = 0 |
+---------------+---------------+
3 | |
+--- Sequence Number ---+
4 | |
+---------------+---------------+
5 | |
+--- Acknowledgement Number ---+
6 | |
+---------------+---------------+
7 | |
+--- Checksum ---+
8 | |
+-------------------------------+
RST Segment Format
Figure 9
Page 42
4.7. NUL Segment ๐
the NUL segment is the vibe check ๐ It's how you figure out whether the other side of a connection is still around. When a NUL segment is received, an RDP implementation must acknowledge the segment if a valid connection exists and the segment sequence number falls within the acceptance window. After that, the segment gets discarded ๐๏ธ The NUL may be combined with an ACK in a segment, but it is never combined with user data, periodt ๐
4.7.1. NUL segment format
0 0 0 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+---+---------------+
0 |0|0|0|0|1|0|0 1| Header Length |
+-+-+-+-+-+-+---+---------------+
1 | Source Port | Dest. Port |
+---------------+---------------+
2 | Data Length = 0 |
+---------------+---------------+
3 | |
+--- Sequence Number ---+
4 | |
+---------------+---------------+
5 | |
+--- Acknowledgement Number ---+
6 | |
+---------------+---------------+
7 | |
+--- Checksum ---+
8 | |
+-------------------------------+
NUL Segment Format
Figure 10
Page 43
Page 44
5. Examples of Operation ๐
5.1. Connection Establishment ๐ฆ
this is an example of a connection getting established between Host A and Host B. Host B has done a passive Open and is sitting in LISTEN state. Host A does an active Open to set up the connection.
Host A Host B
Time State State
1. CLOSED LISTEN
2. SYN-SENT <SEQ=100><SYN> --->
3. <--- <SEQ=200><ACK=100><SYN,ACK>
SYN-RCVD
4. OPEN <SEQ=101><ACK=200> ---> OPEN
5. <SEQ=101><ACK=200><Data> --->
6. <--- <SEQ=201><ACK=101>
Page 45
5.2. Simultaneous Connection Establishment ๐
this is an example of two hosts trying to set up connections to each other at the exact same time ๐ญ Host A sends a SYN request to Host B at the same moment Host B sends a SYN request to Host A.
Host A Host B
Time State State
1. CLOSED CLOSED
2. SYN-SENT <SEQ=100><SYN> --->
<--- <SEQ=200><SYN> SYN-SENT
3. SYN-RCVD SYN-RCVD
<SEQ=100><ACK=200><SYN,ACK> --->
<--- <SEQ=200><ACK=100><SYN,ACK>
4. OPEN OPEN
Page 46
5.3. Lost Segments ๐ง
this is what happens when a segment gets lost. It shows how segments can be acknowledged out of sequence, and that only the missing segment needs to be retransmitted. Heads up: in this example and the ones after it, "EA" stands for "Out of Sequence Acknowledgement." ๐
Time Host A Host B
1. <SEQ=100><ACK=200><Data> --->
2. <--- <SEQ=201><ACK=100>
3. <SEQ=101><ACK=200><Data> (segment lost)
4.
5. <SEQ=102><ACK=200><Data> --->
6. <-- <SEQ=201><ACK=100><EA=102>
7. <SEQ=103><ACK=200><Data> --->
8. <--- <SEQ=201><ACK=100>
<EA=102,103>
9. <SEQ=101><ACK=200><Data> --->
10. <--- <SEQ=201><ACK=103>
11. <SEQ=104><ACK=200><Data> --->
12. <--- <SEQ=201><ACK=104>
Page 47
5.4. Segments Received Out of Order ๐
this is an example of segments showing up out of order. It shows even more clearly how acknowledging segments out of order helps avoid needless retransmissions ๐
Time Host A Host B
1. <SEQ=100><ACK=200><Data> --->
2. <--- <SEQ=201><ACK=100>
3. <SEQ=101><ACK=200><Data> (delayed)
4.
5. <SEQ=102><ACK=200><Data> --->
6. <--- <SEQ=201><ACK=100><EA=102>
7. <SEQ=103><ACK=200><Data> --->
---> (delayed segment 101 arrives)
8. <--- <SEQ=201><ACK=103>
9. <SEQ=104><ACK=200><Data> --->
10. <--- <SEQ=201><ACK=104>
Page 48
5.5. Communication Over Long Delay Path ๐ธ
this is an example of data being transferred over a long delay path โ๏ธ In this one, Host A is allowed to have as many as five unacknowledged segments. It shows that Host A doesn't have to sit around waiting for an acknowledgement before it sends more data. Slay efficiency ๐
Time Host A Host B
1. <SEQ=100><ACK=200><Data> -1->
2. <SEQ=101><ACK=200><Data> -2->
3. <SEQ=102><ACK=200><Data> -3->
-1-> (received)
4. <-4- <SEQ=201><ACK=100>
5. <SEQ=103><ACK=200><Data> -5->
-2-> (received)
6. <-6- <SEQ=201><ACK=101>
7. <SEQ=104><ACK=200><Data> -7->
-3-> (received)
8. <-8- <SEQ=201><ACK=102>
(received) <-4-
9. <SEQ=105><ACK=200><Data> -9->
-5-> (received)
10. <-10- <SEQ=201><ACK=103>
(received) <-6-
11. <SEQ=106><ACK=200><Data> -11->
-7-> (received)
12. <-12- <SEQ=201><ACK=104>
(received) <-8-
13. -9-> (received)
14. <-13- <SEQ=201><ACK=105>
(received) <-10-
15. -11-> (received)
16. <-14- <SEQ=201><ACK=106>
(received) <-12-
17. (received) <-13-
18. (received) <-14-
Page 49
5.6. Communication Over Long Delay Path With Lost Segments ๐ฆ
this is an example of communication over a long delay path where one segment gets lost โจ It shows that by acknowledging segments out of sequence, only the lost segment needs to be retransmitted, so nothing else has to be sent again ๐ซถ
Time Host A Host B
1. <SEQ=100><ACK=200><Data> -1->
2. <SEQ=101><ACK=200><Data> -2->
3. <SEQ=102><ACK=200><Data> -3->
-1-> (received)
4. <-4- <SEQ=201><ACK=100>
5. <SEQ=103><ACK=200><Data> (segment lost)
-2-> (received)
6. <-5- <SEQ=201><ACK=101>
7. <SEQ=104><ACK=200><Data> -6->
-3-> (received)
8. <-7- <SEQ=201><ACK=102>
(received) <-4-
9. <SEQ=105><ACK=200><Data> -8->
10.
(received) <-5-
11. <SEQ=106><ACK=200><Data> -10->
-6-> (received)
12. <-11- <SEQ=201><ACK=102><EA=104>
(received) <-7-
-8-> (received)
13. <-12- <SEQ=201><ACK=102><EA=104,105>
-10-> (received)
14. <-13- <SEQ=201><ACK=102><EA=104-106>
(received) <-11-
15. <SEQ=103><ACK=200><Data> -14->
(received) <-12-
16. (received) <-13-
-14-> (received)
17. <-15- <SEQ=201><ACK=106>
18.
19. (received) <-15-
Page 50
5.7. Detecting a Half-Open Connection on Crash Recovery โจ
Okay so this is an example of a host spotting a half-open connection ๐ซฃ after it crashed and restarted. Host A crashes in the middle of a session, then recovers and tries to reopen the connection. During that reopen attempt, it finds out a half-open connection is still hanging around, so it resets the other side. Both sides were in the OPEN state before the crash, so it's giving full drama ๐
Host A Host B
Time
1. OPEN OPEN
(crash!) <--- <SEQ=200><ACK=100><ACK>
2. CLOSED OPEN
(recover)
3. SYN-SENT OPEN
<SEQ=400><SYN> ---> (?)
4. SYN-SENT OPEN
(!) <--- <SEQ=200><ACK=100><ACK>
5. SYN-SENT OPEN
<SEQ=101><RST> ---> (abort)
6. SYN-SENT CLOSED
7. SYN-SENT <SEQ=400><SYN> --->
Page 51
5.8. Detecting a Half-Open Connection from the Active Side ๐ฆ
This is another one of those half-open connection moments ๐ญ caused by a crash and restart of a host in the connection. Host A crashes and restarts again, but this time Host B is still active and keeps trying to send data to host A. Host A has zero memory of the connection, so it rejects the data with an RST segment ๐ โโ๏ธ, and that makes host B reset the connection. Iconic behaviour, honestly ๐
Host A Host B
Time
1. (crash!) OPEN
2. CLOSED <--- <SEQ=200><ACK=100><Data> OPEN
3. CLOSED <SEQ=101><RST> ---> (abort)
4. CLOSED CLOSED
Page 52
Appendix A. Implementing a Minimal RDP ๐ง
Bestie, you do NOT need the whole RDP spec to use RDP ๐ For simple stuff like a loader, where the size of the protocol module really matters, you can go with a subset. For example, an implementation of RDP for loading might use these restrictions:
- Only one connection and connection record is supported. This is the connection used to load the device. ๐
- A single, well-known port is used as the loader port. Allocable ports are not implemented.
- Only the passive Open request is implemented. Active Opens are not supported.
- The sequenced delivery option is not supported. Messages arriving out of order are delivered in the order they arrive.
- If efficiency is less important than protocol size, the extended acknowledgement feature need not be supported.
Page 53
Index ๐
ACK.......................................... 16, 33, 34, 38
ACK segment format....................................... 38
acknowledgement number field......... 16, 34, 37, 38, 39, 40
byte-stream protocols................................. 4, 14
checksum................................................. 16
checksum field........................................... 34
Close request............................................ 13
Closed state.......................................... 9, 10
CLOSEWAIT................................................ 12
Close-Wait state................................. 10, 11, 13
CLOSE-WAIT timeouts...................................... 29
connection, closing of............................... 13, 42
connection, establishment of...................... 8, 11, 45
connection identifier................................. 7, 33
connection management..................................... 7
connection record..................................... 9, 11
connection state diagram................................. 10
connection states......................................... 8
control flags field...................................... 33
cumulative acknowledgement............................... 16
data communication....................................... 14
data length field................................ 34, 39, 40
datagrams................................................. 6
debugging.............................................. 1, 3
dumping................................................... 3
EACK......................................... 16, 33, 35, 40
EACK segment format...................................... 40
event processing......................................... 20
extended acknowledgement................................. 16
flow control............................................. 17
half-open connection, detection of............... 14, 51, 52
initial sequence number....................... 9, 11, 12, 15
internet protocols........................................ 5
IP................................................ 6, 15, 31
IP header............................................ 31, 37
Listen state................................... 8, 9, 10, 45
loading................................................ 1, 3
maximum segment size..................... 11, 12, 13, 15, 37
maximum unacknowledged segments.............. 11, 12, 17, 37
message fragmentation.................................... 14
non-cumulative acknowledgement........................... 16
Page 54
NUL.................................................. 33, 43
NUL segment format....................................... 43
Open request.......................................... 8, 17
Open request, active................................... 8, 9
Open request, passive.................................. 8, 9
Open state....................................... 10, 11, 45
options flag field....................................... 37
out-of-sequence acknowledgement.................. 12, 16, 18
ports................................................. 7, 33
ports, well-known......................................... 8
positive acknowledgement............................. 15, 16
RBUF.MAX................................................. 13
RCV.CUR.................................................. 12
RCVDSEQNO................................................ 12
RCV.IRS.................................................. 12
RCV.MAX.................................................. 12
RDP connection........................................... 14
RDP header................................... 14, 16, 32, 37
RDP header length........................................ 33
RDP segment format....................................... 31
reliable communication................................... 15
retransmission of segments....................... 15, 16, 17
retransmission timeout............................... 17, 29
RST.................................................. 33, 42
RST segment.......................................... 13, 52
RST segment format....................................... 42
SBUF.MAX................................................. 12
SDM...................................................... 37
SEG.ACK.................................................. 13
SEG.BMAX................................................. 13
SEG.MAX.................................................. 13
segment arrival events............................... 20, 24
segments................................................. 14
SEG.SEQ.................................................. 13
Send request......................................... 14, 15
sequence number...................................... 12, 15
sequence number acceptance window........................ 18
sequence number field........................ 34, 37, 39, 40
sequenced delivery................................. 3, 4, 37
sequential acknowledgement................................ 4
SND.ISS.................................................. 12
SND.MAX.................................................. 12
SND.NXT.................................................. 11
SND.UNA.................................................. 12
STATE.................................................... 11
SYN.................................. 12, 13, 15, 33, 35, 36
SYN segment........................................... 9, 36
Page 55
Syn-Rcvd state........................................ 9, 10
Syn-Sent state........................................ 9, 10
TCP................................................... 4, 14
three-way handshake....................................... 4
user request events.................................. 20, 21
version number field..................................... 33
Page 56
Page 57
๐ฆ where this page comes from
- ietf: rfc908 1984-07
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms