§3.1.

Subscriptions

All subscriptions begin in the Idle state. A subscription can be initiated and moved to the Pending state by either a publisher or a subscriber. A publisher initiates a subscription to a track by sending the PUBLISH message. The subscriber either accepts or rejects the subscription using PUBLISH_OK (Section 9.3) or REQUEST_ERROR. A subscriber initiates a subscription to a track by sending the SUBSCRIBE message. The publisher either accepts or rejects the subscription using SUBSCRIBE_OK or REQUEST_ERROR. Once either of these sequences is successful, the subscription moves to the Established state and can be updated by the subscriber using REQUEST_UPDATE. Either endpoint can terminate an Established subscription, moving it to the Terminated state. The subscriber terminates a subscription in the Pending (Subscriber) or Established states by sending STOP_SENDING. The publisher terminates a subscription in the Pending (Publisher) or Established states by sending PUBLISH_DONE and closing the stream.

This diagram shows the subscription state machine:

                              +--------+
                              |  Idle  |
                              +--------+
                                |    |
                      SUBSCRIBE |    | PUBLISH
                    (subscriber)|    | (publisher)
                                V    V
                   +--------------+ +--------------+
                   | Pending      | | Pending      |
              +----| (Subscriber) | | (Publisher)  |----+
              |    +--------------+ +--------------+    |
              |                 |    |                  |
REQUEST_ERROR |    SUBSCRIBE_OK |    | PUBLISH_OK       | REQUEST_ERROR
(publisher)   |      (publisher)|    | (subscriber)     | (subscriber)
              |                 V    V                  |
              |            +-------------+              |
              |            | Established | ------+
              |            |             |       | REQUEST_UPDATE
              |            +-------------+ <-----+
              |                 |    |                  |
              +--- STOP_SENDING |    | PUBLISH_DONE ----+
              |     (subscriber)|    | (publisher)      |
              |                 V    V                  |
              |            +-------------+              |
              +----------->| Terminated  | <------------+
                           +-------------+

A publisher MUST send exactly one SUBSCRIBE_OK or REQUEST_ERROR in response to a SUBSCRIBE. A subscriber MUST send exactly one PUBLISH_OK (Section 9.3) or REQUEST_ERROR in response to a PUBLISH. The peer SHOULD close the session with a protocol error if it receives more than one.

All Established subscriptions have a Forward State which is either 0 or 1. The publisher does not send Objects if the Forward State is 0, and does send them if the Forward State is 1. The initiator of the subscription sets the initial Forward State in either PUBLISH or SUBSCRIBE. The subscriber can send REQUEST_UPDATE to update the Forward State. Control messages, such as PUBLISH_DONE (Section 9.9) are sent regardless of the forward state.

Either endpoint can initiate a subscription to a track without exchanging any prior messages other than SETUP. Relays MUST NOT send any PUBLISH messages without knowing the client is interested in and authorized to receive the content. The communication of intent and authorization can be accomplished by the client sending SUBSCRIBE_NAMESPACE, or conveyed in other mechanisms out of band.

An endpoint MAY SUBSCRIBE to a Track it is publishing, though only Relays are required to handle such a SUBSCRIBE. Such self-subscriptions are identical to subscriptions initiated by other endpoints, and all published Objects will be forwarded back to the endpoint, subject to priority and congestion response rules.

An endpoint MAY have multiple concurrent subscriptions to the same Track, each identified by a unique Request ID. A publisher MAY assign the same or different Track Aliases to these subscriptions.

When an Object matches the filters of multiple subscriptions to the same Track, the publisher MUST send the Object once for each matching subscription, even when those subscriptions share the same Track Alias. Because subscriptions can share a Track Alias, the subscriber re-applies each subscription's filter to determine which subscription a received Object belongs to. Subscribers SHOULD avoid overlapping filters across subscriptions to the same Track, as they are responsible for deduplicating any resulting duplicate Objects.

A publisher SHOULD begin sending incomplete objects when available to avoid incurring additional latency.

Publishers MAY start sending Objects on PUBLISH-initiated subscriptions before receiving a PUBLISH_OK response to reduce latency. Doing so can consume unnecessary resources in cases where the Subscriber rejects the subscription with REQUEST_ERROR or sets Forward=0 in REQUEST_UPDATE. It can also result in the Subscriber dropping Objects if its buffering limits are exceeded (see Section 11.2 and Section 11.3.1).

An object published or received in a subgroup or datagram is subscription-delivered.

3.1.1. Subscription State Management

A subscriber keeps subscription state until it cancels the request (see Section 6.4.2.3), or until receipt of a PUBLISH_DONE or REQUEST_ERROR. Note that PUBLISH_DONE does not usually indicate that state can immediately be removed, see Section 9.9.

The Publisher can remove subscription state as soon as it has received STOP_SENDING. It MUST reset any open streams associated with the SUBSCRIBE.

The Publisher can also immediately delete subscription state after sending PUBLISH_DONE, but MUST NOT send it until it has closed all related streams.

A REQUEST_ERROR indicates no objects will be delivered, and both endpoints can immediately remove relevant state. Objects MUST NOT be sent for requests that end with an error.

3.1.2. Track Alias

To optimize wire efficiency, Subgroups and Datagrams refer to a track by a numeric identifier, rather than the Full Track Name. Track Alias is chosen by the publisher and included in SUBSCRIBE_OK (Section 9.7) or PUBLISH (Section 9.8).

The same Track Alias MUST NOT be used by a publisher to refer to two different Tracks simultaneously in the same session. If a subscriber receives a PUBLISH or SUBSCRIBE_OK that uses the same Track Alias as a different Track with an Established subscription, it MUST close the session with error DUPLICATE_TRACK_ALIAS.

Objects can be sent before the Subscriber knows the Track Alias, requiring buffering Objects with an unknown Track Alias. If a Track Alias is used for two concurrent subscriptions to the same Track, an Object that arrives with the Track Alias could be for either Subscription. Reusing the same Track Alias for concurrent subscriptions to the same Track can lead to missed delivery if objects for the new subscription arrive before the control message establishing the shared Alias. The Subscriber can assume the Track Alias is reused until told otherwise, in order to avoid missing Objects.

To avoid a protocol violation and to ensure the Subscriber knows which Track Objects are from, Publishers SHOULD NOT reuse a Track Alias for different Tracks within a session, unless it is certain the prior Subscription has been completely closed and no Objects are scheduled to be sent or in flight.

Objects can arrive after a subscription has been cancelled. Subscribers SHOULD retain sufficient state to quickly discard these unwanted Objects, rather than treating them as belonging to an unknown Track Alias.

3.1.3. Largest Object

The Largest Object is the Object with the largest Location (Section 8.2) in the Track from the perspective of the publisher processing the message. Largest Object updates when the first byte of an Object with a Location larger than the previous value is published or received through a subscription.

The Next Object is the Location immediately following Largest Object, which is {Largest Object.Group, Largest Object.Object + 1}, or {0, 0} if no content has been delivered yet.

This is one section of the MoQT specification, rendered per-section for quick reference and citation. The authoritative text is draft-ietf-moq-transport-21 at the IETF.