Skip to content
Merged
Show file tree
Hide file tree
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
30 changes: 30 additions & 0 deletions draft-lcurley-moq-lite.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ normative:
moqt: I-D.ietf-moq-transport
qmux: I-D.ietf-quic-qmux
RFC1951:
RFC7692:
RFC3986:
RFC6455:
RFC9002:
Expand Down Expand Up @@ -296,6 +297,9 @@ When the stream is closed, the subscriber MUST assume that all broadcasts are no

Path prefix matching and equality is done on a byte-by-byte basis.
There MAY be multiple Announce Streams, potentially containing overlapping prefixes, that get their own ANNOUNCE_OK + ANNOUNCE_BROADCAST messages.
The compression context for ANNOUNCE_BROADCAST payloads is retained across messages on the same Announce Stream, so separate messages still benefit from repeated path components and Hop ID lists.
The publisher flushes the compressor after each ANNOUNCE_BROADCAST, allowing the subscriber to decode each announcement as soon as its message bytes arrive.
For this reason, batching multiple path changes into one ANNOUNCE_BROADCAST is not needed for compression; `Active Count` provides application-level batching for the initial set while preserving one state change per ANNOUNCE_BROADCAST message.

### Subscribe
A subscriber opens Subscribe Streams to request a Track.
Expand Down Expand Up @@ -680,13 +684,23 @@ An ANNOUNCE_BROADCAST before ANNOUNCE_OK is a protocol violation.
~~~
ANNOUNCE_BROADCAST Message {
Message Length (i)
Compressed Payload (..)
}

ANNOUNCE_BROADCAST Payload {
Announce Status (i),
Broadcast Path Suffix (s),
Hop Count (i),
Hop ID (i) ...,
}
~~~

**Message Length**:
The number of bytes in `Compressed Payload`.

**Compressed Payload**:
The compressed form of `ANNOUNCE_BROADCAST Payload`, as described in [Compressed ANNOUNCE_BROADCAST Payloads](#compressed-announce-broadcast-payloads).

**Announce Status**:
A flag indicating the announce status.

Expand All @@ -708,6 +722,21 @@ When forwarding an announcement received from an upstream peer, a relay MUST app
The total path length is `Hop Count + 1` (including the implicit ANNOUNCE_OK `Hop ID`).
A Hop ID value of 0 means the hop is unknown: either it was never assigned (e.g. when bridging from an older protocol version) or a relay deliberately withholds it to obscure the underlying routing; the Hop Count still reflects the total number of entries including unknown hops.

### Compressed ANNOUNCE_BROADCAST Payloads {#compressed-announce-broadcast-payloads}
ANNOUNCE_BROADCAST compresses the entire message payload, excluding only the `Message Length` field.
The uncompressed input is exactly the `ANNOUNCE_BROADCAST Payload` encoding defined above.

Compression uses the DEFLATE format [RFC1951] with a single compression context per Announce Stream.
The context is initialized immediately after ANNOUNCE_OK and is retained until the Announce Stream closes.
For each ANNOUNCE_BROADCAST, the publisher feeds the uncompressed payload bytes into that context and then performs the equivalent of `Z_SYNC_FLUSH`.
A sync flush produces output ending with the fixed four-byte marker `00 00 ff ff`; the publisher MUST remove this marker before writing the compressed bytes into `Compressed Payload`, matching WebSocket compression [RFC7692].

The subscriber uses a single decompression context per Announce Stream.
Before inflating each `Compressed Payload`, the subscriber appends the four bytes `00 00 ff ff` to reconstruct the sync-flushed DEFLATE stream.
After reading `Compressed Payload`, the subscriber inflates it using the retained context and parses the resulting bytes as `ANNOUNCE_BROADCAST Payload`.
The decompressed payload MUST be a valid `ANNOUNCE_BROADCAST Payload`; otherwise, the subscriber MUST reset the Announce Stream with a PROTOCOL_VIOLATION.
If decompression fails, the subscriber MUST reset the Announce Stream with a PROTOCOL_VIOLATION.


## SUBSCRIBE
SUBSCRIBE is sent by a subscriber to start a subscription.
Expand Down Expand Up @@ -1035,6 +1064,7 @@ The `Message Length` describes the payload size on the wire.
- Added QUIC datagram delivery for groups.
- Dropped the `Subscriber` prefix from fields that exist on only one side.
- Added Qmux [qmux] transport bindings for TCP/TLS and WebSocket.
- Added mandatory DEFLATE compression for ANNOUNCE_BROADCAST payloads.

## moq-lite-04
- Renamed ANNOUNCE_PLEASE to ANNOUNCE_REQUEST.
Expand Down
146 changes: 146 additions & 0 deletions draft-lcurley-moq-namespace-compression.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
title: "MoQ Namespace Compression Extension"
abbrev: "moq-namespace-compression"
category: info

docname: draft-lcurley-moq-namespace-compression-latest
submissiontype: IETF # also: "independent", "editorial", "IAB", or "IRTF"
number:
date:
v: 3
area: wit
workgroup: moq

author:
-
fullname: Luke Curley
email: kixelated@gmail.com

normative:
moqt: I-D.ietf-moq-transport
RFC1951:
RFC7692:

informative:

--- abstract

This document defines an extension for MoQ Transport {{moqt}} that compresses namespace advertisements sent in response to SUBSCRIBE_NAMESPACE.
The extension defines a namespace suffix compression negotiation and a DEFLATE compression algorithm for the Track Namespace Suffix carried by NAMESPACE and NAMESPACE_DONE messages, retaining compression context across messages on the same namespace subscription response stream and flushing after each message.

--- middle

# Conventions and Definitions
{::boilerplate bcp14-tagged}


# Introduction

MoQ Transport {{moqt}} lets a subscriber discover published namespaces by sending SUBSCRIBE_NAMESPACE.
The publisher responds with NAMESPACE messages for matching namespaces and NAMESPACE_DONE messages when a matching namespace is no longer available.

In applications with many live publishers, these namespace suffixes often share repeated structure, such as room identifiers, participant identifiers, or media role names.
This extension compresses only the Track Namespace Suffix field of NAMESPACE and NAMESPACE_DONE messages.
The rest of the control message framing remains unchanged, allowing each namespace change to remain an independent protocol event.

The compression model intentionally mirrors WebSocket per-message compression {{RFC7692}}: compressed data is flushed at each message boundary so the receiver can process each message immediately, and the fixed sync-flush marker is removed from the bytes carried on the wire.


# Setup Negotiation

The Namespace Compression extension is negotiated during the SETUP exchange as defined in {{moqt}} Section 10.3.
An endpoint indicates support by including the following Setup Option:

~~~
NAMESPACE_COMPRESSION Setup Option {
Option Key (vi64) = 0x40B59
Option Value Length (vi64)
Namespace Compression Algorithm (vi64)
}
~~~

**Namespace Compression Algorithm**:
The namespace suffix compression algorithm supported by the endpoint.

- `deflate` (0): DEFLATE compression as defined in [Compressed Suffix Encoding](#compressed-suffix-encoding).

The Option Value MUST contain exactly one Namespace Compression Algorithm.
An endpoint that receives an unknown Namespace Compression Algorithm MUST close the session with PROTOCOL_VIOLATION.

If both endpoints include NAMESPACE_COMPRESSION with the same Namespace Compression Algorithm, then namespace suffix compression is negotiated for the session.
When namespace suffix compression is negotiated, every NAMESPACE and NAMESPACE_DONE message sent in response to SUBSCRIBE_NAMESPACE on the session MUST encode its Track Namespace Suffix using the negotiated algorithm.
If either endpoint omits NAMESPACE_COMPRESSION, namespace suffix compression is not negotiated and NAMESPACE and NAMESPACE_DONE use the encoding defined by {{moqt}}.

The extension applies to a single hop and is negotiated independently for each session.
A relay MUST NOT assume support on one session implies support on another.


# Compressed Namespace Suffixes

This extension does not define new message types and does not otherwise replace the NAMESPACE or NAMESPACE_DONE message definitions in {{moqt}}.
Instead, when namespace suffix compression is negotiated, only the Track Namespace Suffix field in each NAMESPACE and NAMESPACE_DONE message is compressed.
All other fields and any future fields in those messages retain the encoding defined by {{moqt}} or by the extension that defines them.

**Track Namespace Suffix**:
When namespace suffix compression is negotiated, this field carries the compressed form of the Track Namespace Suffix value.
The uncompressed bytes are exactly the Track Namespace Suffix encoding defined by {{moqt}}, excluding the field's own length prefix if the base encoding supplies one.

After decompression, the receiver parses the resulting bytes as a Track Namespace Suffix.
If decompression fails, or if the decompressed bytes are not a valid Track Namespace Suffix, the receiver MUST close the session with PROTOCOL_VIOLATION.


# Compressed Suffix Encoding
{: #compressed-suffix-encoding}

The `deflate` Namespace Compression Algorithm uses the DEFLATE format {{RFC1951}} with one compression context per SUBSCRIBE_NAMESPACE response stream.
The context is initialized when the publisher accepts the SUBSCRIBE_NAMESPACE request and is retained until the response stream is closed.

For each NAMESPACE or NAMESPACE_DONE message, the publisher feeds the uncompressed Track Namespace Suffix bytes into that stream's compression context and then performs the equivalent of `Z_SYNC_FLUSH`.
A sync flush produces output ending with the fixed four-byte marker `00 00 ff ff`; the publisher MUST remove this marker before writing the compressed bytes into the Track Namespace Suffix field.

The subscriber uses one decompression context for the same response stream.
Before inflating each compressed Track Namespace Suffix, the subscriber appends the four bytes `00 00 ff ff` to reconstruct the sync-flushed DEFLATE stream.
Because the publisher flushes after every NAMESPACE or NAMESPACE_DONE message, the subscriber can decompress and process each namespace update as soon as that message is received.
The flush does not reset the compression context, so repeated namespace components in later messages can reference bytes from earlier messages on the same response stream.


# Security Considerations

This extension adds stateful decompression to namespace discovery.
Implementations SHOULD bound the amount of memory and CPU used for each compression context and SHOULD apply the same limits to decompressed namespace suffixes that they apply to uncompressed suffixes.

Compression can reveal information through compressed sizes when an attacker can influence namespace names and observe response sizes.
Applications that consider namespace names sensitive SHOULD avoid enabling this extension across trust boundaries, or partition namespace subscriptions so attacker-controlled and secret namespace components do not share a compression context.

Malformed compressed data is a protocol violation.
Repeated decompression failures can be used as a denial-of-service signal and MAY be rate limited or logged by implementations.


# IANA Considerations

This document requests the following registrations.
High, distinctive values are requested to avoid the low ranges reserved by {{moqt}} and to minimize collisions with provisional registrations by other extensions; they also avoid the greasing pattern (`0x7f * N + 0x9D`).

## MOQT Setup Options

This document requests a registration in the "MOQT Setup Options" registry ({{moqt}} Section 15.4), whose policy is Specification Required.

| Value | Name | Reference |
|:--------|:------------------|:--------------|
| 0x40B59 | NAMESPACE_COMPRESSION | This Document |

## MOQT Namespace Compression Algorithms

This document requests a new "MOQT Namespace Compression Algorithms" registry, whose policy is Specification Required.

| Value | Name | Reference |
|:------|:--------|:--------------|
| 0 | DEFLATE | This Document |


--- back

# Acknowledgments
{:numbered="false"}

This document was drafted with the assistance of AI tools.
Loading