SCP - Session Control Protocol V 1.1

Simon E. Spero (
University Of North Carolina At Chapel Hill


This document describes version 1.1 of the Session Control Protocol, or SCP. The SCP provides a simple mechanism for creating multiple lightweight connections over a single TCP connection. Several such lightweight connections can be active simultaneously. SCP provides a byte oriented service, but allows message boundaries to be marked.


There are several protocols in widespread use on the Internet which create a single TCP connection for each transaction. Doing so offers two advantages to the protocol designer; the end of file marker can be used to mark the end of a transaction, and several transactions can take place concurrently. Unfortunately, because these transactions are so short lived, the cost of setting up and tearing down these connections becomes significant, both in terms of resources used and in the delays associated with TCP's congestion control mechanisms.

The Session Control Protocol (SCP) is a simple protocol running on top of TCP than can be used to create multiple lightweight connections over a single transport connection. Data from several different channels can be interleaved, and both message boundaries and end of stream markers can be provided.

Because SCP runs on top of a reliable ordered transport service it can avoid most of the extra work TCP must go through in order to ensure reliability. For example, SCP sessions do not need to be confirmed, so there is no need to wait for handshaking to complete.

Changes From Previous Versions

There are two main changes between this version of the specification and previous approaches. The biggest change is the addition of a compressed header format to reduce the size overhead for low bandwidth connections.

Protocol Model

The basic protocol model is that of multiple lightweight sessions operating over a reliable stream of bytes. The party which initiated the connection is referred to as the client, and the party which accepted the connection is referred to as the server. Sessions may be unidirectional or bi-directional; each end of a bi-directional session may be closed separately. Sessions may be closed normally, or reset to indicate an abortive release. Aborting a session closes both channels.

One a session has been opened, the application can send messages over it, and signal the end of these application level messages. These messages are encapsulated in SCP packets and transferred over the byte stream. Messages can be split up into several different packets.

Packet Format

SCP headers come in to varieties, compressed and uncompressed. The canonical version of the header is the uncompressed format- the compressed format is conceptually expanded before being processed.

The uncompressed form of an SCP packet consists of a 64 bit header followed by zero or more octets of data. If the COMPRESSION flag in the first byte is set, the header should be interpreted as described in the section on compression.

The header contains three fields; a flag byte, the session identifier, and the packet length.

+SFRP0000| Session ID               |
|            LENGTH                 |
This field is one octet long. If the least significant bit in the octet is set, then the header should be interpreted as a compressed header. If this bit is not set, then the four high order bits contain flags used to open and close sessions, and to mark application level messages.
Name Mask Description
Compressed Header XXXX|XXX1 Mark a Compressed Header
SYN 1XXX|0000 Open A New Connection
FIN X1XX|0000 Close An Existing Connection
PUSH XX1X|0000 Mark an application level message boundary
RESET XXX1|0000 Abort the Connection

The RESET flag may not be sent in conjunction with any other flags.

Session Identifiers
Each session is identified by a 24 bit integer.
Sessions created by the client must have even identifiers; those created by the server must have odd identifiers.
Session Identifiers below 1024 not otherwise allocated by this document are reserved to the IANA for allocating to standard sub protocols..
If a party receives a message for a reserved sessions which it does not implement it must return a RESET message on that channel the first time it receives a message on any such channel. At the receiver's option a RESET may be sent for subsequent messages on that channel
Session Identifiers are compared modulo 2^24, using the same algorithm as that for comparing TCP sequence numbers.
Reserved Session Identifiers
1 Presentation Control Protocol (PCP)
2 Multiplexed Data Algorithm (MDA)
    XXXX - Define PCP - select higher-level protocol to talk to. Is this
	   necessary? Why in http MUX
	   Define MDA - Wrapped SCP packets with options. Is this 
	   necessary? It's all optional anyway. 
Packet Lengths
The packet length is represented by a 32 bit unsigned integer value. Application level messages may be longer than 2^32-1 octets long; however in this case the messages must be split up into two or more SCP layer packets.
An SCP implementation is free to regenerate SCP packets when so desired; for example, if the underlying transport can make part of an SCP packet available before the entire packet has been received, the implementation is free to deliver the data as and when it becomes available as long as any message boundary marker is only send for the final packet. An implementation may also combine two SCP packets for the same session as long as no packet but the last has a message boundary marker.

Session States

Sessions can exist in several different states; closed, opened for read, opened for write, and opened for read and write. A Session can change its state in response to receiving a packet with the SYN, FIN, or RESET bits set, or in response to an API by the application. The available API calls are open, close, abort.

The following table describes the actions and state transitions that occur in response to a given event. The events are given in order of priority - if multiple flags are present, then the first matched action should be followed, and any remaining flags processed in the resultant successor state.

For example, if a session is in the CLOSED state, and it receives a packet containing a SYN, a FIN, and data, the implementation should check the table for Closed, and look for the first even that matches. In this case, the first match is for SYN; the implementation should Accept the Session, remove the SYN from the set of pending events, and move to Open-Receive.

State Event Action New State

RESET Discard Closed
SYN (1) Accept Session Open-Receive
FIN Discard Closed
Other Discard Closed

FIN Close Session, Discard Closed
RESET Abort Session, Discard Closed
SYN Send RESET, Abort Session Closed

CLOSE Send RESET, Close Session Closed
ABORT Send RESET, Close Session Closed
DATA-IN Read Data Open-Receive
OPEN Send SYN, Open for Writing Open-ReadWrite
Open-ReadWrite SYN Send Reset, Close Connection Closed
DATA-IN Read Data Open-ReadWrite
DATA-OUT Write Data Open-ReadWrite
Shutdown Send FIN, Close for Writing Open-Receive
FIN Close for Reading Open-Write
RESET Abort Connection Closed
CLOSE Send FIN + RESET, Close Connection Closed
Open-Write RESET Abort Connection Closed
SYN Open for Reading Open-ReadWrite
Data-In Send RESET, Abort Connection Closed
Data-Out Write Data Open-Write
FIN Send RESET, Abort Connection Open-Write
CLOSE Send FIN, Close Connection Closed
Abort Send Reset, Close Connection Closed

Header Compression

If the SCP is used to send small messages over low bandwidth links, the costs of the eight byte header may become noticeable, outweighing the savings gained from having a fixed format header.

Observed SCP traffic typically follows a predictable pattern; this predictability can be used to implement a system of header compression similar to that developed for TCP by Van Jacobsen.

The first Observation is that there are normally only a small number of session simultaneously active, and these active sessions are strongly localised in time. A small cache of recently used session Ids can be used instead of full session ids with good success.

The second observation is that message lengths are often the same for packets on a given channel, and where packets sizes do vary, they are typically small. The same cache used for session Ids can be used to store the length of the most recent message sent on a given channel. An abbreviated length field with an escape value for the previous length can be used to encode lengths for typical messages. Longer messages may need larger length fields; however the size of headers is not significant with longer messages.

Header Cache

Each end of an SCP connection that supports compression maintains two LRU caches, one for sending and one for receiving. Each cache contains six entries; each entry contains a session identifier and a packet length. In addition to the caches, the protocol manager also keeps a record of the last session identifier used in each direction.


Each cache is initialised to contain the following values:

Entry SessionID Length
0 0 0
1 1 7
2 1,024 128
3 1,025 128
4 1,026 128
5 1,027 128

The first use of one of these predefined sessions shall be considered to have an implicit SYN.

The cache for a particular direction is not be updated until the first packet with a compressed header is sent or received.

Compressed Format.

The compressed format is either one, two, or three bytes long The first byte of a compressed format header contains various flags, together with the session id and lengths for most segments.

This octet is sometimes followed by a one byte extended session id , an extended length, or both.

Flag byte

The flag byte is sent in place of the standard SCP flag byte- the semantics of the rest of the bits is determined by the least significant bit. If this bit is 0, then the standard interpretation is used; otherwise, it is treated as a compressed header as follows.

P - Push Bit
This bit indicates whether the PUSH flag is set. This is the most commonly used flag, and the only flag that supported by the compressed header format.
Len - Length field
This three bit field encodes the segment length.
0-5 Actual Length
6 Use Extended Length Format.
7 Use Length From Cache
Ses - Session Id field
This three bit field encodes the session identifier.
0-5 Position of Session Identifier in LRU Cache
6 Use Extended SessionId Format
7 Use next session identifier. The next identifier is determined as follows:
	let p = the last allocated identifier, n = the next session identifier
	n = p + 2;
	if (n >= 2^24) {
  	   n = n % 2^24 + 1024;
If session 'n' is currently active, this option cannot be used; the implementation must use either the extended SessionId or the uncompressed format.
The receiver should treat packets that use the next session identifier feature as if SYN bit is implicitly set.

Extended Formats.

If both an extended session id and an extended length are present, the session id octet should precede the length octet.

The extended formats must not be used if the value could be represented using the compact format.

Extended SessionId Format

| Delta  |
This is a single octet containing an 8-bit signed two's complement integer. This integer is added to the most recently used session identifier (which is stored in cache entry zero), and the result is used as the SessionId.

Extended Length Format

|Length  |

This is a single octet containing a length from 0-255.

Compression Examples

To help make the compressed format a little clearer, here are a few simple examples.

To start with, the clients sending side cache is intialised to the default values.

Entry SessionID Length
0 0 0
1 1 7
2 1,024 128
3 1,025 128
4 1,026 128
5 1,027 128
LastId = 1026

The first packet is a 4 byte message on session 1024. The corresponding compressed header is

|0| 4 | 2 |1|
 P Len Ses 1

If we were using the uncompressed format, the corresponding header would be:

| 10000000|         1024           |   Flags (SYN),8 bits, Session(1024), 24 bits
|                                4 |	 Length (4), 32 bits

After sending this packet, the clients cache looks like this:

Entry SessionID Length
0 1,024 4
1 0 0
2 1 7
3 1,025 128
4 1,026 128
5 1,027 128
LastId = 1026

The next message is a 10 byte packet, also for session 1024.

+-+---+---+-+ +--------+
|0| 6 | 0 |1| |     10 |
+-+---+---+-+ +--------+
 P Len Ses 1    length  

If we were using the uncompressed format, the corresponding header would be:

| 00000000|         1024           |   Flags (none),8 bits, Session(1024), 24 bits
|                               10 |	 Length (10), 32 bits

After sending this packet, the clients cache looks like this:

Entry SessionID Length
0 1,024 10
1 0 0
2 1 7
3 1,025 128
4 1,026 128
5 1,027 128
LastId = 1026

After this, we want to open a new channel and send a 4 byte message. The next session id is 1028, which is unallocated- thus we can use the next session id feature of the compressed header.

|0| 4 | 7 |1| 
 P Len Ses 1

If we were using the uncompressed format, the corresponding header would be:

| 10000000|         1028           |   Flags (SYN),8 bits, Session(1028), 24 bits
|                               4  |	 Length (4), 32 bits

After sending this packet, the clients cache looks like this:

Entry SessionID Length
0 1,028 4
1 1,024 10
2 0 0
3 1 7
4 1,025 128
5 1,026 128
LastId = 1028