]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | # Specification |
2 | ||
3 | We use this document to detail the internal specification of Yamux. | |
4 | This is used both as a guide for implementing Yamux, but also for | |
5 | alternative interoperable libraries to be built. | |
6 | ||
7 | # Framing | |
8 | ||
9 | Yamux uses a streaming connection underneath, but imposes a message | |
10 | framing so that it can be shared between many logical streams. Each | |
11 | frame contains a header like: | |
12 | ||
13 | * Version (8 bits) | |
14 | * Type (8 bits) | |
15 | * Flags (16 bits) | |
16 | * StreamID (32 bits) | |
17 | * Length (32 bits) | |
18 | ||
19 | This means that each header has a 12 byte overhead. | |
20 | All fields are encoded in network order (big endian). | |
21 | Each field is described below: | |
22 | ||
23 | ## Version Field | |
24 | ||
25 | The version field is used for future backward compatibility. At the | |
26 | current time, the field is always set to 0, to indicate the initial | |
27 | version. | |
28 | ||
29 | ## Type Field | |
30 | ||
31 | The type field is used to switch the frame message type. The following | |
32 | message types are supported: | |
33 | ||
34 | * 0x0 Data - Used to transmit data. May transmit zero length payloads | |
35 | depending on the flags. | |
36 | ||
37 | * 0x1 Window Update - Used to updated the senders receive window size. | |
38 | This is used to implement per-session flow control. | |
39 | ||
40 | * 0x2 Ping - Used to measure RTT. It can also be used to heart-beat | |
41 | and do keep-alives over TCP. | |
42 | ||
43 | * 0x3 Go Away - Used to close a session. | |
44 | ||
45 | ## Flag Field | |
46 | ||
47 | The flags field is used to provide additional information related | |
48 | to the message type. The following flags are supported: | |
49 | ||
50 | * 0x1 SYN - Signals the start of a new stream. May be sent with a data or | |
51 | window update message. Also sent with a ping to indicate outbound. | |
52 | ||
53 | * 0x2 ACK - Acknowledges the start of a new stream. May be sent with a data | |
54 | or window update message. Also sent with a ping to indicate response. | |
55 | ||
56 | * 0x4 FIN - Performs a half-close of a stream. May be sent with a data | |
57 | message or window update. | |
58 | ||
59 | * 0x8 RST - Reset a stream immediately. May be sent with a data or | |
60 | window update message. | |
61 | ||
62 | ## StreamID Field | |
63 | ||
64 | The StreamID field is used to identify the logical stream the frame | |
65 | is addressing. The client side should use odd ID's, and the server even. | |
66 | This prevents any collisions. Additionally, the 0 ID is reserved to represent | |
67 | the session. | |
68 | ||
69 | Both Ping and Go Away messages should always use the 0 StreamID. | |
70 | ||
71 | ## Length Field | |
72 | ||
73 | The meaning of the length field depends on the message type: | |
74 | ||
75 | * Data - provides the length of bytes following the header | |
76 | * Window update - provides a delta update to the window size | |
77 | * Ping - Contains an opaque value, echoed back | |
78 | * Go Away - Contains an error code | |
79 | ||
80 | # Message Flow | |
81 | ||
82 | There is no explicit connection setup, as Yamux relies on an underlying | |
83 | transport to be provided. However, there is a distinction between client | |
84 | and server side of the connection. | |
85 | ||
86 | ## Opening a stream | |
87 | ||
88 | To open a stream, an initial data or window update frame is sent | |
89 | with a new StreamID. The SYN flag should be set to signal a new stream. | |
90 | ||
91 | The receiver must then reply with either a data or window update frame | |
92 | with the StreamID along with the ACK flag to accept the stream or with | |
93 | the RST flag to reject the stream. | |
94 | ||
95 | Because we are relying on the reliable stream underneath, a connection | |
96 | can begin sending data once the SYN flag is sent. The corresponding | |
97 | ACK does not need to be received. This is particularly well suited | |
98 | for an RPC system where a client wants to open a stream and immediately | |
99 | fire a request without waiting for the RTT of the ACK. | |
100 | ||
101 | This does introduce the possibility of a connection being rejected | |
102 | after data has been sent already. This is a slight semantic difference | |
103 | from TCP, where the conection cannot be refused after it is opened. | |
104 | Clients should be prepared to handle this by checking for an error | |
105 | that indicates a RST was received. | |
106 | ||
107 | ## Closing a stream | |
108 | ||
109 | To close a stream, either side sends a data or window update frame | |
110 | along with the FIN flag. This does a half-close indicating the sender | |
111 | will send no further data. | |
112 | ||
113 | Once both sides have closed the connection, the stream is closed. | |
114 | ||
115 | Alternatively, if an error occurs, the RST flag can be used to | |
116 | hard close a stream immediately. | |
117 | ||
118 | ## Flow Control | |
119 | ||
120 | When Yamux is initially starts each stream with a 256KB window size. | |
121 | There is no window size for the session. | |
122 | ||
123 | To prevent the streams from stalling, window update frames should be | |
124 | sent regularly. Yamux can be configured to provide a larger limit for | |
125 | windows sizes. Both sides assume the initial 256KB window, but can | |
126 | immediately send a window update as part of the SYN/ACK indicating a | |
127 | larger window. | |
128 | ||
129 | Both sides should track the number of bytes sent in Data frames | |
130 | only, as only they are tracked as part of the window size. | |
131 | ||
132 | ## Session termination | |
133 | ||
134 | When a session is being terminated, the Go Away message should | |
135 | be sent. The Length should be set to one of the following to | |
136 | provide an error code: | |
137 | ||
138 | * 0x0 Normal termination | |
139 | * 0x1 Protocol error | |
140 | * 0x2 Internal error |