datagrams: Add initial datagram draft - #680
Conversation
marten-seemann
left a comment
There was a problem hiding this comment.
Have you considered tying a datagram flow to a stream, similar to what HTTP DATAGRAMS (RFC 9297) does?
This would have the following benefits:
- Shorter datagram header (especially important given MTU restrictions).
- Both peers get the opportunity to cancel a datagram flow (by closing / resetting the associated stream).
- A reliable control channel, e.g. for application protocols that need to send an occasional control message next to a datagram flow.
|
Thanks @marten-seemann! That's a nice idea. We can include the versioning information in the stream as well so we don't pay that overhead on every datagram. The datagram itself then only has a single varint of overhead. |
8dac785 to
1b5c110
Compare
|
@jxs - I've reached out to zig, nim, py and dotnet for feedback to get this moving. |
| libp2p datagrams on WebTransport behave the same as libp2p datagrams on QUIC. | ||
| However, the application data may be further limited by the overhead of HTTP | ||
| Datagram's Quarter Stream ID field. | ||
|
|
||
| In the future, a separate spec may be able to remove this overhead. |
There was a problem hiding this comment.
the quic encoding uses a stream id as the control stream identifier, but browser webtransport doesn't expose quic stream ids. If browser implementations are expected to support this, how is the control stream identified? would some specific webtransport flow identifier be needed?
| start sending datagrams at once. There is currently no other use for the control | ||
| stream besides negotiating the application protocol ID. Receipt of a QUIC | ||
| DATAGRAM frame whose payload is too short to allow parsing the Control Stream ID | ||
| field MUST be treated as a connection error of type PROTOCOL_VIOLATION (0x1003). |
There was a problem hiding this comment.
Perhaps something like this so the name does not clash with QUIC's own PROTOCOL_VIOLATION (0x0a) error? (also on line 71:72)
| field MUST be treated as a connection error of type PROTOCOL_VIOLATION (0x1003). | |
| field MUST be treated as a connection error of type DG_PROTOCOL_VIOLATION (0x1003). |
| If a libp2p datagram is received and its Control Stream ID field maps to a | ||
| stream that cannot be created due to client-initiated bidirectional stream | ||
| limits, it MUST be treated as a connection error of type PROTOCOL_VIOLATION | ||
| (0x1003). |
There was a problem hiding this comment.
i'm a bit confused by the reference to "client-initiated bidirectional stream limits". Can control streams be opened by either peer?
| protocol. A control stream is a QUIC bidirectional stream that has negotiated | ||
| the libp2p datagram control stream protocol ID `/dg/1`. The initiator MUST send | ||
| the related application protocol ID with a [uvarint] length prefix after | ||
| negotiating the control stream. The control stream MUST stay open for the |
There was a problem hiding this comment.
i think it would help to clarify the receiver behavior if the application protocol id is unsupported or malformed. (i.e. close stream / reset?). Is this going to use multistream-select?
| the related application protocol ID with a [uvarint] length prefix after | ||
| negotiating the control stream. The control stream MUST stay open for the | ||
| duration of the datagram flow. Implementation MAY create the control stream and | ||
| start sending datagrams at once. There is currently no other use for the control |
There was a problem hiding this comment.
What should happen to datagrams that arrive before control stream has finished /dg1 processing and application protocol negotiation? should they be dropped or buffered?
There was a problem hiding this comment.
I suggest discarding them, buffering them introduces a possible attack vector
| This specification defines libp2p datagrams, which enable the transmission of | ||
| MTU-sized, unreliable, and low latency messages between peers. |
There was a problem hiding this comment.
the transmission of ... unreliable ... messages between peers
It's not very clear to me what these are. If the definition is the same of QUIC's unreliable datagrams, maybe it's worth it to be explicit here?
Come to think of it... are not all datagrams unreliable? This is a different discussion but the name seems confusing.
| Some libp2p transports natively support datagrams, such as QUIC and | ||
| WebTransport. libp2p implementations MUST use the native datagram support to |
There was a problem hiding this comment.
such as QUIC and WebTransport
But then what follows is a detailed description of how datagrams in QUIC are supposed to be handled. At least to me this seems to telegraph that this document will hold an extensive list of the supported underlying protocols, and how to handle each of them.
In other words, reading this makes me think that following there will be a list of all supported protocols and how to handle them, otherwise they're not supported at all.
So I guess if we'll have particular cases such as QUIC, we must also have a non-particular (i.e. default) case that hopefully most of the underlying protocols will follow
In other words, sth like this:
such as quic and webtransport
Datagrams
for most protocols this is the case...
Excepctions
QUIC Datagrams
blabla
another exception
The alternative would be to have an extensive list of supported underlying protos, but to me that would make it harder to extend and the spec would need constant maintenance
| closed, the received datagrams MUST be silently dropped. | ||
|
|
||
| If a libp2p datagram is received and its Control Stream ID field maps to a | ||
| stream that has not yet been created, the receiver SHALL either drop that |
There was a problem hiding this comment.
| stream that has not yet been created, the receiver SHALL either drop that | |
| stream that has not yet been created, the receiver MUST either drop that |
|
|
||
| ### Encoding | ||
|
|
||
| Each libp2p datagram SHALL be encoded with the following structure. |
There was a problem hiding this comment.
| Each libp2p datagram SHALL be encoded with the following structure. | |
| Each libp2p datagram MUST be encoded with the following structure. |
| Each datagram flow MUST be associated with a control stream. A datagram flow is | ||
| defined as a logical flow of datagrams related to a specific application | ||
| protocol. A control stream is a QUIC bidirectional stream that has negotiated |
There was a problem hiding this comment.
A datagram flow is defined as a logical flow of datagrams related to a specific application protocol. A control stream is a QUIC bidirectional stream that has negotiated...
These could be in a Terminology section to make it easier to understand when only reading parts of the document.
| stream besides negotiating the application protocol ID. Receipt of a QUIC | ||
| DATAGRAM frame whose payload is too short to allow parsing the Control Stream ID | ||
| field MUST be treated as a connection error of type PROTOCOL_VIOLATION (0x1003). |
There was a problem hiding this comment.
nit: wording
| stream besides negotiating the application protocol ID. Receipt of a QUIC | |
| DATAGRAM frame whose payload is too short to allow parsing the Control Stream ID | |
| field MUST be treated as a connection error of type PROTOCOL_VIOLATION (0x1003). | |
| stream besides negotiating the application protocol ID. If a DATAGRAM frame's payload cannot be parsed as a Control Stream ID followed by application data, the endpoint MUST close the connection with a PROTOCOL_VIOLATION (0x1003) error. |
| libp2p datagrams MUST NOT be sent unless the control stream's send side is open. | ||
| If a datagram is received after the corresponding stream's receive side is | ||
| closed, the received datagrams MUST be silently dropped. |
There was a problem hiding this comment.
nit: wording
| libp2p datagrams MUST NOT be sent unless the control stream's send side is open. | |
| If a datagram is received after the corresponding stream's receive side is | |
| closed, the received datagrams MUST be silently dropped. | |
| An endpoint MUST NOT send libp2p datagrams unless the send side of the associated control stream is open. An endpoint that receives a datagram after the receive side of the corresponding control stream is closed MUST silently drop it. |
Initial text for specifying how datagrams will work on libp2p.
cc @raulk @sukunrt @jxs