|
| 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