Skip to content

Commit 693b487

Browse files
committed
error codes: add initial spec
1 parent f25d0c2 commit 693b487

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

error-codes/README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Error Codes
2+
3+
## Introduction
4+
In the event that a node detects violation of a protocol or is unable to
5+
complete the necessary steps required for the protocol, it's useful to provide a
6+
reason for disconnection to the other end. This error code can be sent on both
7+
Connection Close and Stream Reset. Its purpose is similar to http response
8+
status. A server, on receiving an invalid request can reset the stream providing
9+
a `BAD_REQUEST` error code, when it's busy handling too many requests can
10+
provide a `RATE_LIMITED` error code, etc. An error code doesn't always indicate
11+
an error condition. For example, a connection may be closed prematurely because
12+
a connection to the same peer on a better transport is available.
13+
14+
## Semantics
15+
Error codes are unsigned 32bit integers. The range 0 to 10000 is reserved for
16+
libp2p errors. Application specific errors can be defined by protocols from
17+
integers outside of this range. Implementations supporting error codes MUST
18+
provide the error code provided by the other end to the application.
19+
20+
Error codes provide a best effort guarantee that the error will be propogated to
21+
the applciation layer. This provides backwards compatibility with older nodes,
22+
allows smaller implementations and using transports that don't provide a
23+
mechanism to provide an error code. For example, Yamux has no equivalent of
24+
QUIC's [STOP_SENDING](https://www.rfc-editor.org/rfc/rfc9000.html#section-3.5-4)
25+
frame that would tell the peer that the node has stopped reading. So there's no
26+
way of signaling an error while closing the read end of the stream on a yamux
27+
connection.
28+
29+
### Connection Close and Stream Reset Error Codes
30+
Error codes are defined separately for Connection Close and Stream Reset. Stream
31+
Reset errors are from the range 0 to 5000 and Connection Close errors are from
32+
the range 5001 to 10000. Having separate errors for Connection Close and stream
33+
reset requires some overlap between the error code definitions but provides more
34+
information to the receiver. Receiving a `Bad Request: Connection Closed` error
35+
on reading from a stream also tells the receiver that no more streams can be
36+
started on the same connection. Implementations MUST provide the Connection
37+
Close error code on streams that are reset as a result of remote closing the
38+
connection.
39+
40+
For stream resets, when the underlying transport supports it, implementations
41+
SHOULD allow sending an error code on both closing the read side of the stream
42+
and resetting the write side of the stream.
43+
44+
## Libp2p Error Codes
45+
TODO!
46+
47+
## Wire Encoding
48+
Different transports will encode the 32bit error code differently.
49+
50+
### QUIC
51+
QUIC provides the ability to send an error on closing the read end of the
52+
stream, reseting the write end of the stream and on closing the connection.
53+
54+
For stream resets, the error code MUST be sent on the `RESET_STREAM` or the
55+
`STOP_SENDING` frame using the `Application Protocol Error Code` field as per
56+
the frame definitions in the
57+
[RFC](https://www.rfc-editor.org/rfc/rfc9000.html#name-reset_stream-frames).
58+
59+
For Connection Close, the error code MUST be sent on the CONNECTION_CLOSE frame
60+
using the Error Code field as defined in the
61+
[RFC](https://www.rfc-editor.org/rfc/rfc9000.html#section-19.19-6.2.1).
62+
63+
### Yamux
64+
Yamux has no `STOP_SENDING` frame, so there's no way to signal an error on
65+
closing the read side of the stream.
66+
67+
For Connection Close, the 32bit Length field is to be interpreted as the error
68+
code. The error code MUST be sent as an Big Endian unsigned 32 bit integer.
69+
70+
For Stream Resets, the error code is sent as the first 4 bytes of the Data Frame
71+
following the header with RST flag set as defined in the [yamux spec
72+
extension](https://github.com/libp2p/specs/pull/622).
73+
74+
Note: On TCP connections with `SO_LINGER` set to 0, the error code on connection
75+
close may not be delivered.
76+
77+
### WebRTC
78+
Since WebRTC doesn't provide reliable delivery for frames that are followed by
79+
closing of the underlying data channel, there's no simple way to introduce error
80+
codes in the current implementation. Consider the most common use case of
81+
resetting both read and write sides of the stream and closing the data channel.
82+
The chrome implementation will not deliver the final `RESET_STREAM` msg and
83+
while the go implementation will delivery the `RESET_STREAM` frame and then
84+
close the data channel, there's no guarantee that the chrome implementation will
85+
provide the `RESET_STREAM` msg to the application layer after it receives the
86+
data channel close message.
87+
88+
### WebTransport
89+
Error codes for webtransport will be introduced when browsers upgrade to draft-9
90+
of the spec. The current webtransport spec implemented by chrome and firefox is
91+
[draft-2 of webtransport over
92+
http3](https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-02.html#section-4.3-2).
93+
This version allows for only a 1 byte error code. 1 byte is too restrictive and
94+
as the latest webtransport draft,
95+
(draft-9)[https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-02.html#section-4.3-2]
96+
allows for a 4 byte error code to be sent on stream resets, we will introduce
97+
error codes over webtransport later.

0 commit comments

Comments
 (0)