QUIC multi-stream#1533
Conversation
There was a problem hiding this comment.
Pull request overview
Updates XEP-0467 (“XMPP over QUIC”) to expand and clarify the proposed QUIC multi-stream behavior, including stream ordering constraints and how stream management/connection migration should work.
Changes:
- Refines requirements for QUIC connection migration and stream usage timing (post-auth/bind).
- Adds new “Use Cases” subsections: Connection Migration, Multiple Streams, and Stream Management.
- Introduces detailed rules for mapping stanza traffic to QUIC streams to preserve RFC 6120 ordering semantics.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <li>The ALPN protocol MUST be '<strong>xmpp-server</strong>' when negotiating an s2s connection.</li> | ||
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link> which allows for a single QUIC session and therefore multiple XMPP connections to migrate between IPs without reconnecting. Use of &xep0198; is therefore optional but encouraged if reconnection might occur over another transport like TLS or WebSocket.</li> | ||
| <li>QUIC supports uni-directional and bi-directional streams, but XMPP MUST only use bi-directional streams. Multiple bi-directional MAY be opened in one session and MUST be treated as a seperate connections with the same security and authentication as negotiated in the initial TLS handshake. This means clients can log into multiple accounts, or the same account multiple times over one QUIC session, or servers can open multiple s2s connections over one QUIC session where one of the servers can prove control over multiple domains, for example if the certificate covered multiple domain names.</li> | ||
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link> which allows for a single QUIC session and therefore multiple XMPP connections to migrate between IPs without reconnecting. The timeout SHOULD be set to the maximum 600 seconds.</li> |
There was a problem hiding this comment.
"The timeout SHOULD be set to the maximum 600 seconds" is ambiguous (which QUIC timeout/transport parameter?) and appears to state a universal maximum that QUIC does not define. Please specify the exact QUIC mechanism/parameter (and units) and avoid asserting a fixed protocol maximum unless it is referenced/normatively defined.
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link> which allows for a single QUIC session and therefore multiple XMPP connections to migrate between IPs without reconnecting. The timeout SHOULD be set to the maximum 600 seconds.</li> | |
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link> which allows for a single QUIC session and therefore multiple XMPP connections to migrate between IPs without reconnecting. To support migration scenarios, the QUIC idle timeout (that is, the <code>max_idle_timeout</code> transport parameter, expressed in milliseconds) SHOULD be configured appropriately; deployments MAY use 600000 milliseconds (600 seconds), but this specification does not define that value as a protocol maximum.</li> |
| <section1 topic='Use Cases' anchor='usecases'> | ||
| <p>Perhaps the most compelling benefit of QUIC over TCP+TLS is connection migration especially for mobile devices which swap between mobile and WiFi often. Multiple connections per QUIC session is also helpful for clients with multiple accounts or servers with multiple streams to each other. The handshake and especially 0-rtt mode will be faster than STARTTLS, and in theory, QUIC in general should be faster than TLS, though perhaps not enough to matter for XMPP.</p> | ||
| <section2 topic="Connection Migration"> | ||
| <p>The entire QUIC connection can be migrated to a different source IP address. This allows mobile devices to seamlessly switch between mobile data and WiFi, without renegotiation. This takes the place of the session resumption in &xep0198;, which MUST NOT be used.</p> |
There was a problem hiding this comment.
Connection migration keeps the same QUIC connection alive across address changes; it does not provide XEP-0198-style stream resumption after a disconnect/reconnect. Consider rephrasing to avoid implying that connection migration is a form of (or complete replacement for) session resumption.
| <p>The entire QUIC connection can be migrated to a different source IP address. This allows mobile devices to seamlessly switch between mobile data and WiFi, without renegotiation. This takes the place of the session resumption in &xep0198;, which MUST NOT be used.</p> | ||
| </section2> | ||
| <section2 topic="Multiple Streams"> | ||
| <p>QUIC allows the use of multiple streams. A QUIC connection still maps to a single XMLStream, and the initial bidirection stream (id=0) SHALL be used to setup and make ready this XMLStream. Until the XMLStream is ready for general stanza exchange, further bidirectional QUIC streams MUST NOT be opened. For S2S XMLStreams, this will be after SASL authentication, whereas for C2S XMLStreams this will be after resource binding. It is advised to support &xep0388; and &xep0387; to streamline these, though there is no interoperability issue if the older forms are used.</p> |
There was a problem hiding this comment.
Typo: "bidirection" should be "bidirectional".
| <p>QUIC allows the use of multiple streams. A QUIC connection still maps to a single XMLStream, and the initial bidirection stream (id=0) SHALL be used to setup and make ready this XMLStream. Until the XMLStream is ready for general stanza exchange, further bidirectional QUIC streams MUST NOT be opened. For S2S XMLStreams, this will be after SASL authentication, whereas for C2S XMLStreams this will be after resource binding. It is advised to support &xep0388; and &xep0387; to streamline these, though there is no interoperability issue if the older forms are used.</p> | |
| <p>QUIC allows the use of multiple streams. A QUIC connection still maps to a single XMLStream, and the initial bidirectional stream (id=0) SHALL be used to setup and make ready this XMLStream. Until the XMLStream is ready for general stanza exchange, further bidirectional QUIC streams MUST NOT be opened. For S2S XMLStreams, this will be after SASL authentication, whereas for C2S XMLStreams this will be after resource binding. It is advised to support &xep0388; and &xep0387; to streamline these, though there is no interoperability issue if the older forms are used.</p> |
| <p>The entire QUIC connection can be migrated to a different source IP address. This allows mobile devices to seamlessly switch between mobile data and WiFi, without renegotiation. This takes the place of the session resumption in &xep0198;, which MUST NOT be used.</p> | ||
| </section2> | ||
| <section2 topic="Multiple Streams"> | ||
| <p>QUIC allows the use of multiple streams. A QUIC connection still maps to a single XMLStream, and the initial bidirection stream (id=0) SHALL be used to setup and make ready this XMLStream. Until the XMLStream is ready for general stanza exchange, further bidirectional QUIC streams MUST NOT be opened. For S2S XMLStreams, this will be after SASL authentication, whereas for C2S XMLStreams this will be after resource binding. It is advised to support &xep0388; and &xep0387; to streamline these, though there is no interoperability issue if the older forms are used.</p> |
There was a problem hiding this comment.
Grammar: "to setup" should be "to set up" when used as a verb phrase.
| <p>QUIC allows the use of multiple streams. A QUIC connection still maps to a single XMLStream, and the initial bidirection stream (id=0) SHALL be used to setup and make ready this XMLStream. Until the XMLStream is ready for general stanza exchange, further bidirectional QUIC streams MUST NOT be opened. For S2S XMLStreams, this will be after SASL authentication, whereas for C2S XMLStreams this will be after resource binding. It is advised to support &xep0388; and &xep0387; to streamline these, though there is no interoperability issue if the older forms are used.</p> | |
| <p>QUIC allows the use of multiple streams. A QUIC connection still maps to a single XMLStream, and the initial bidirection stream (id=0) SHALL be used to set up and make ready this XMLStream. Until the XMLStream is ready for general stanza exchange, further bidirectional QUIC streams MUST NOT be opened. For S2S XMLStreams, this will be after SASL authentication, whereas for C2S XMLStreams this will be after resource binding. It is advised to support &xep0388; and &xep0387; to streamline these, though there is no interoperability issue if the older forms are used.</p> |
| </section2> | ||
| <section2 topic="Multiple Streams"> | ||
| <p>QUIC allows the use of multiple streams. A QUIC connection still maps to a single XMLStream, and the initial bidirection stream (id=0) SHALL be used to setup and make ready this XMLStream. Until the XMLStream is ready for general stanza exchange, further bidirectional QUIC streams MUST NOT be opened. For S2S XMLStreams, this will be after SASL authentication, whereas for C2S XMLStreams this will be after resource binding. It is advised to support &xep0388; and &xep0387; to streamline these, though there is no interoperability issue if the older forms are used.</p> | ||
| <p>Once multiple streams are opened, it is MANDATORY that both peers continue to follow the ordering rules defined in Section 10.1 of &rfc6120;, however stanzas sent in different QUIC streams have no fixed order relative to those sent in other QUIC streams. The sending peer MUST therefore use a single QUIC stream for all stanzas sent between a pair of two bare jids. For example, when sending a stanza from sender@example.net/resource to receiver@example.com, and another from sender@example.net/other to receiver@sender.com/xyzzy, both stanzas MUST be sent within the same QUIC stream. Multiple "pairs" of Jids MAY share the same QUIC stream, with the degenerate case - all pairs sharing the same QUIC stream - being the case where no additional QUIC streams are opened. This mapping of bare jid pairs to QUIC streams MUST NOT be enforced by the receiver; the receiver MUST simply process all stanzas received over a QUIC stream in the order they were sent in the same way they would if a single QUIC stream (or TCP) were used.</p> |
There was a problem hiding this comment.
The example JIDs appear to contradict the stated rule. It says both stanzas MUST use the same QUIC stream because they are between the same bare JID pair, but the second stanza is addressed to "receiver@sender.com/xyzzy" (a different bare JID/domain than "receiver@example.com"). Please correct the example addresses so they demonstrate the intended same bare-JID-pair case.
| <p>Once multiple streams are opened, it is MANDATORY that both peers continue to follow the ordering rules defined in Section 10.1 of &rfc6120;, however stanzas sent in different QUIC streams have no fixed order relative to those sent in other QUIC streams. The sending peer MUST therefore use a single QUIC stream for all stanzas sent between a pair of two bare jids. For example, when sending a stanza from sender@example.net/resource to receiver@example.com, and another from sender@example.net/other to receiver@sender.com/xyzzy, both stanzas MUST be sent within the same QUIC stream. Multiple "pairs" of Jids MAY share the same QUIC stream, with the degenerate case - all pairs sharing the same QUIC stream - being the case where no additional QUIC streams are opened. This mapping of bare jid pairs to QUIC streams MUST NOT be enforced by the receiver; the receiver MUST simply process all stanzas received over a QUIC stream in the order they were sent in the same way they would if a single QUIC stream (or TCP) were used.</p> | |
| <p>Once multiple streams are opened, it is MANDATORY that both peers continue to follow the ordering rules defined in Section 10.1 of &rfc6120;, however stanzas sent in different QUIC streams have no fixed order relative to those sent in other QUIC streams. The sending peer MUST therefore use a single QUIC stream for all stanzas sent between a pair of two bare jids. For example, when sending a stanza from sender@example.net/resource to receiver@example.com, and another from sender@example.net/other to receiver@example.com/xyzzy, both stanzas MUST be sent within the same QUIC stream. Multiple "pairs" of Jids MAY share the same QUIC stream, with the degenerate case - all pairs sharing the same QUIC stream - being the case where no additional QUIC streams are opened. This mapping of bare jid pairs to QUIC streams MUST NOT be enforced by the receiver; the receiver MUST simply process all stanzas received over a QUIC stream in the order they were sent in the same way they would if a single QUIC stream (or TCP) were used.</p> |
| <p>There is no "stream open" or "stream close" sent on streams other than the initial stream (id=0).</p> | ||
| <p>There is no requirement that the peer use the same QUIC streams for the same bare jid pairs, though again in C2S the initial stream (id=0) SHOULD be used for all stanzas sent from the user's own bare jid and also from the server's jid itself. In the general case, though, this means that (for example) an <iq type='result'/> MAY come back on a different QUIC stream than the <iq type='get'/> that elicited it.</p> | ||
| <p>Conceptually, there remains a single XMLStream for an entire QUIC connection, and the XMLStream state therefore applies to all QUIC streams within the QUIC connection. Stanzas received on a QUIC stream are processed by taking each complete stanza and injecting it into the XMLStream at that point. An incomplete stanza received on any QUIC stream (including the initial stream) is buffered until such time as the data arrives to complete it.</p> | ||
| <p>The benefits of doing this are that individual streams do not block each other on low bandwidth or packet loss. Eliminating this blocking effect, called Head Of Line Blocking, means that higher-volume chatrooms (for example) do not slow down the transmission of perhaps more urgent low volume messages. Because of this effect, peers MAY use QUIC's ability to proritise specific QUIC streams for finer control, though this is out of scope for this document.</p> |
There was a problem hiding this comment.
Typo: "proritise" should be "prioritize" (or "prioritise", but currently it's misspelled).
| <p>The benefits of doing this are that individual streams do not block each other on low bandwidth or packet loss. Eliminating this blocking effect, called Head Of Line Blocking, means that higher-volume chatrooms (for example) do not slow down the transmission of perhaps more urgent low volume messages. Because of this effect, peers MAY use QUIC's ability to proritise specific QUIC streams for finer control, though this is out of scope for this document.</p> | |
| <p>The benefits of doing this are that individual streams do not block each other on low bandwidth or packet loss. Eliminating this blocking effect, called Head Of Line Blocking, means that higher-volume chatrooms (for example) do not slow down the transmission of perhaps more urgent low volume messages. Because of this effect, peers MAY use QUIC's ability to prioritise specific QUIC streams for finer control, though this is out of scope for this document.</p> |
| <li>The ALPN protocol MUST be '<strong>xmpp-server</strong>' when negotiating an s2s connection.</li> | ||
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link> which allows for a single QUIC session and therefore multiple XMPP connections to migrate between IPs without reconnecting. Use of &xep0198; is therefore optional but encouraged if reconnection might occur over another transport like TLS or WebSocket.</li> | ||
| <li>QUIC supports uni-directional and bi-directional streams, but XMPP MUST only use bi-directional streams. Multiple bi-directional MAY be opened in one session and MUST be treated as a seperate connections with the same security and authentication as negotiated in the initial TLS handshake. This means clients can log into multiple accounts, or the same account multiple times over one QUIC session, or servers can open multiple s2s connections over one QUIC session where one of the servers can prove control over multiple domains, for example if the certificate covered multiple domain names.</li> | ||
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link> which allows for a single QUIC session and therefore multiple XMPP connections to migrate between IPs without reconnecting. The timeout SHOULD be set to the maximum 600 seconds.</li> |
There was a problem hiding this comment.
This requirement mentions "multiple XMPP connections" migrating with a single QUIC session, but later text states that a QUIC connection maps to a single XMLStream. Please clarify whether this is about multiple QUIC streams within one XMPP connection (single XMLStream) vs multiple independent XMLStreams, and adjust the wording to avoid a contradiction.
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link> which allows for a single QUIC session and therefore multiple XMPP connections to migrate between IPs without reconnecting. The timeout SHOULD be set to the maximum 600 seconds.</li> | |
| <li>The client or server MUST use <link url='https://datatracker.ietf.org/doc/html/rfc9000#section-9'>QUIC Connection Migration</link>, which allows a single QUIC session, and therefore the XMPP connection/XMLStream established over it, to migrate between IPs without reconnecting. The timeout SHOULD be set to the maximum 600 seconds.</li> |
A proposal for QUIC multi-stream.
Implemented to PoC level in dwd/Wimsy#3 (client) and igniterealtime/Openfire#3251 (server). Seems to work.
There are almost certainly more open questions than I've mentioned in the doc, including questions of what a sensible idle timeout really is, and whether/how to use PING frames, and how many bidirectional streams to allow, and ...
Anyway, I would expect considerable discussion on-list prior to merging, and it needs @moparisthebest as author anyway.