RFC 908

Reliable Data Protocol

๐Ÿ“… published July 1984, from ietf

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, and CLOSE-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 the SYN segment ๐ŸŒฑ.

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 the SYN segment 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 the CLOSE-WAIT state โฐ.
  • SBUF.MAX: The largest possible segment (in octets) that can legally be sent. This variable is specified by the foreign host in the SYN segment 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 the SYN segment ๐ŸŽ€.

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 the SYN segment that established the connection ๐Ÿซง.
  • SEG.BMAX: The maximum segment size (in octets) accepted by the foreign host on a connection, as specified in the SYN segment 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) ๐Ÿงš

  1. 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 โœจ
  2. 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

  1. The checksum accumulator gets rotated left one bit position, and the checksum pointer moves forward to the next 32-bit word in the segment ๐ŸŒˆ
  2. 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