Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions datagrams/datagrams.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Datagrams in libp2p

| Lifecycle Stage | Maturity | Status | Latest Revision |
| --------------- | ------------- | ------ | --------------- |
| 1A | Working Draft | Active | r0, 2025-05-23 |

Authors: [@marcopolo]

Interest Group: [@sukunrt], [@jxs], [@raulk]

[@marcopolo]: https://github.com/marcopolo
[@sukunrt]: https://github.com/sukunrt
[@jxs]: https://github.com/jxs
[@raulk]: https://github.com/raulk

See the [lifecycle document][lifecycle-spec] for context about the maturity level
and spec status.

[lifecycle-spec]: https://github.com/libp2p/specs/blob/master/00-framework-01-spec-lifecycle.md

## Table of Contents

- [Introduction](#introduction)
- [Native support at the transport level](#native-support-at-the-transport-level)
- [Datagrams on QUIC](#datagrams-on-quic)
- [Encoding](#encoding)
- [Datagrams on WebTransport](#datagrams-on-webtransport)
- [Datagrams on top of a multiplexed stream on top of TCP](#datagrams-on-top-of-a-multiplexed-stream-on-top-of-tcp)
- [Datagrams with WebRTC](#datagrams-with-webrtc)

## Introduction

This specification defines libp2p datagrams, which enable the transmission of
MTU-sized, unreliable, and low latency messages between peers.
Comment on lines +33 to +34

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.


TODO write more about the tradeoffs here as well as the kinds of applications that would benefit from using datagrams.

## Native support at the transport level

Some libp2p transports natively support datagrams, such as QUIC and
WebTransport. libp2p implementations MUST use the native datagram support to
Comment on lines +40 to +41

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

send datagrams.

- QUIC has an Unreliable Datagram Extension [RFC 9221].
- WebTransport supports Datagrams though HTTP Datagrams [WebTransport draft RFC](https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-12.html#name-datagrams)

## Datagrams on QUIC

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
Comment on lines +49 to +51

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

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
Comment on lines +51 to +54

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say probably be closed

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should happen to datagrams that arrive before control stream has finished /dg1 processing and application protocol negotiation? should they be dropped or buffered?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest discarding them, buffering them introduces a possible attack vector

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps something like this so the name does not clash with QUIC's own PROTOCOL_VIOLATION (0x0a) error? (also on line 71:72)

Suggested change
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).

Comment on lines +57 to +59

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: wording

Suggested change
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.
Comment on lines +60 to +62

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: wording

Suggested change
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.


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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

datagram silently or buffer it temporarily (on the order of a round trip) while
awaiting the creation of the corresponding stream.

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).
Comment on lines +69 to +72

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm a bit confused by the reference to "client-initiated bidirectional stream limits". Can control streams be opened by either peer?


### Encoding

Each libp2p datagram SHALL be encoded with the following structure.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Each libp2p datagram SHALL be encoded with the following structure.
Each libp2p datagram MUST be encoded with the following structure.


| Field Name | Data Type | Length (bits) | Description |
| ---------------- | ------------- | ------------- | --------------------------------------------------------------------- |
| Control StreamID | [QUIC varint] | 8..64 | The stream ID of the associated control stream for this datagram flow |
| Application Data | byte sequence | variable | Application payload |

## Datagrams on WebTransport

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.
Comment on lines +85 to +89

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?


## Datagrams on top of a multiplexed stream on top of TCP

This is currently not specified.

## Datagrams with WebRTC

This is currently not specified.

[RFC 9221]: https://www.rfc-editor.org/rfc/rfc9221
[QUIC varint]: https://www.rfc-editor.org/rfc/rfc9000.html#name-variable-length-integer-enc
[uvarint]: https://github.com/multiformats/unsigned-varint