diff --git a/ianswett-move-connection-url/draft-ietf-moq-transport.html b/ianswett-move-connection-url/draft-ietf-moq-transport.html new file mode 100644 index 00000000..0259b137 --- /dev/null +++ b/ianswett-move-connection-url/draft-ietf-moq-transport.html @@ -0,0 +1,5151 @@ + + +
+ + + +Internet-Draft | +moq-transport | +March 2025 | +
Curley, et al. | +Expires 3 September 2025 | +[Page] | +
This document defines the core behavior for Media over QUIC Transport +(MOQT), a media transport protocol designed to operate over QUIC and +WebTransport, which have similar functionality. MOQT allows a producer of +media to publish data and have it consumed via subscription by a +multiplicity of endpoints. It supports intermediate content distribution +networks and is designed for high scale and low latency distribution.¶
+This note is to be removed before publishing as an RFC.¶
++ The latest revision of this draft can be found at https://moq-wg.github.io/moq-transport/draft-ietf-moq-transport.html. + Status information for this document may be found at https://datatracker.ietf.org/doc/draft-ietf-moq-transport/.¶
++ Discussion of this document takes place on the + Media Over QUIC Working Group mailing list (mailto:moq@ietf.org), + which is archived at https://mailarchive.ietf.org/arch/browse/moq/. + Subscribe at https://www.ietf.org/mailman/listinfo/moq/.¶
+Source for this draft and an issue tracker can be found at + https://github.com/moq-wg/moq-transport.¶
++ This Internet-Draft is submitted in full conformance with the + provisions of BCP 78 and BCP 79.¶
++ Internet-Drafts are working documents of the Internet Engineering Task + Force (IETF). Note that other groups may also distribute working + documents as Internet-Drafts. The list of current Internet-Drafts is + at https://datatracker.ietf.org/drafts/current/.¶
++ Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress."¶
++ This Internet-Draft will expire on 3 September 2025.¶
++ Copyright (c) 2025 IETF Trust and the persons identified as the + document authors. All rights reserved.¶
++ This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with + respect to this document. Code Components extracted from this + document must include Revised BSD License text as described in + Section 4.e of the Trust Legal Provisions and are provided without + warranty as described in the Revised BSD License.¶
+Media Over QUIC Transport (MOQT) is a protocol that is optimized +for the QUIC protocol [QUIC], either directly or via WebTransport +[WebTransport], for the dissemination of media. MOQT utilizes a +publish/subscribe workflow in which producers of media publish data in +response to subscription requests from a multiplicity of endpoints. MOQT +supports wide range of use-cases with different resiliency and latency +(live, interactive) needs without compromising the scalability and cost +effectiveness associated with content delivery networks.¶
+MOQT is a generic protocol designed to work in concert with multiple +MoQ Streaming Formats. These MoQ Streaming Formats define how content is +encoded, packaged, and mapped to MOQT objects, along with policies for +discovery and subscription.¶
+Section 5 covers mechanisms for prioritizing subscriptions.¶
+Section 7 covers how control messages are encoded on the wire.¶
+Section 8 covers how data messages are encoded on the wire.¶
+The development of MOQT is driven by goals in a number of areas - +specifically latency, the robust feature set of QUIC and relay +support.¶
+Latency is necessary to correct for variable network throughput. Ideally live +content is consumed at the same bitrate it is produced. End-to-end latency would +be fixed and only subject to encoding and transmission delays. Unfortunately, +networks have variable throughput, primarily due to congestion. Attempting to +deliver content encoded at a higher bitrate than the network can support causes +queuing along the path from producer to consumer. The speed at which a protocol +can detect and respond to congestion determines the overall latency. TCP-based +protocols are simple but are slow to detect congestion and suffer from +head-of-line blocking. Protocols utilizing UDP directly can avoid queuing, but +the application is then responsible for the complexity of fragmentation, +congestion control, retransmissions, receiver feedback, reassembly, and +more. One goal of MOQT is to achieve the best of both these worlds: leverage the +features of QUIC to create a simple yet flexible low latency protocol that can +rapidly detect and respond to congestion.¶
+The parallel nature of QUIC streams can provide improvements in the face +of loss. A goal of MOQT is to design a streaming protocol to leverage +the transmission benefits afforded by parallel QUIC streams as well +exercising options for flexible loss recovery.¶
+Some live media architectures today have separate protocols for ingest and +distribution, for example RTMP and HTTP based HLS or DASH. Switching protocols +necessitates intermediary origins which re-package the +media content. While specialization can have its benefits, there are efficiency +gains to be had in not having to re-package content. A goal of MOQT is to +develop a single protocol which can be used for transmission from contribution +to distribution. A related goal is the ability to support existing encoding and +packaging schemas, both for backwards compatibility and for interoperability +with the established content preparation ecosystem.¶
+An integral feature of a protocol being successful is its ability to +deliver media at scale. Greatest scale is achieved when third-party +networks, independent of both the publisher and subscriber, can be +leveraged to relay the content. These relays must cache content for +distribution efficiency while simultaneously routing content and +deterministically responding to congestion in a multi-tenant network. A +goal of MOQT is to treat relays as first-class citizens of the protocol +and ensure that objects are structured such that information necessary +for distribution is available to relays while the media content itself +remains opaque and private.¶
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", +"MAY", and "OPTIONAL" in this document are to be interpreted as +described in BCP 14 [RFC2119] [RFC8174] when, and only when, they +appear in all capitals, as shown here.¶
+The following terms are used with the first letter capitalized.¶
+The party initiating a Transport Session.¶
+The party accepting an incoming Transport Session.¶
+A Client or Server.¶
+The other endpoint than the one being described¶
+An endpoint that handles subscriptions by sending requested Objects from the requested track.¶
+An endpoint that subscribes to and receives tracks.¶
+The initial publisher of a given track.¶
+A subscriber that initiates a subscription and does not send the data on to other subscribers.¶
+An entity that is both a Publisher and a Subscriber, but not the Original +Publisher or End Subscriber.¶
+In the direction of the Original Publisher¶
+In the direction of the End Subscriber(s)¶
+A raw QUIC connection or a WebTransport session.¶
+Packet loss and queuing caused by degraded or overloaded networks.¶
+A temporal sequence of objects. A group represents a join point in a +track. See (Section 2.3).¶
+An object is an addressable unit whose payload is a sequence of +bytes. Objects form the base element in the MOQT data model. See +(Section 2.1).¶
+A track is a collection of groups. See (Section 2.4).¶
+This document uses the conventions detailed in ([RFC9000], Section 1.3) +when describing the binary encoding.¶
+As a quick reference, the following list provides a non normative summary +of the parts of RFC9000 field syntax that are used in this specification.¶
+Indicates that x is L bits long¶
+Indicates that x holds an integer value using the variable-length +encoding as described in ([RFC9000], Section 16)¶
+Indicates that x can be any length including zero bits long. Values + in this format always end on a byte boundary.¶
+Indicates that x is optional and has a length of L¶
+Indicates that x is repeated zero or more times and that each instance +has a length of L¶
+This document extends the RFC9000 syntax and with the additional field types:¶
+Indicates that x consists of a variable length integer encoding as +described in ([RFC9000], Section 16), followed by that many bytes +of binary data¶
+Indicates that x is a tuple, consisting of a variable length integer encoded +as described in ([RFC9000], Section 16), followed by that many variable +length tuple fields, each of which are encoded as (b) above.¶
+To reduce unnecessary use of bandwidth, variable length integers SHOULD +be encoded using the least number of bytes possible to represent the +required value.¶
+MOQT has a hierarchical data model, comprised of tracks which contain +groups, and groups that contain objects. Inside of a group, the objects +can be organized into subgroups.¶
+To give an example of how an application might use this data model, +consider an application sending high and low resolution video using a +codec with temporal scalability. Each resolution is sent as a separate +track to allow the subscriber to pick the appropriate resolution given +the display environment and available bandwidth. Each "group of pictures" +in a video is sent as a group because the first frame is needed to +decode later frames. This allows the client to join at the logical points +where they can get the information to start decoding the stream. +The temporal layers are sent as separate sub groups to allow the +priority mechanism to favour the base layer when there is not enough +bandwidth to send both the base and enhancement layers. Each frame of +video on a given layer is sent as a single object.¶
+The basic data element of MOQT is an object. An object is an +addressable unit whose payload is a sequence of bytes. All objects +belong to a group, indicating ordering and potential +dependencies. Section 2.3 An object is uniquely identified by +its track namespace, track name, group ID, and object ID, and must be an +identical sequence of bytes regardless of how or where it is retrieved. +An Object can become unavailable, but its contents MUST NOT change over +time.¶
+Objects are comprised of two parts: metadata and a payload. The metadata is +never encrypted and is always visible to relays (see Section 6). The +payload portion may be encrypted, in which case it is only visible to the +Original Publisher and End Subscribers. The Original Publisher is solely +responsible for the content of the object payload. This includes the +underlying encoding, compression, any end-to-end encryption, or +authentication. A relay MUST NOT combine, split, or otherwise modify object +payloads.¶
+Objects within a group are ordered numerically by their Object ID.¶
+A subgroup is a sequence of one or more objects from the same group +(Section 2.3) in ascending order by Object ID. Objects in a subgroup +have a dependency and priority relationship consistent with sharing a +stream and are sent on a single stream whenever possible. A Group is delivered +using at least as many streams as there are Subgroups, +typically with a one-to-one mapping between Subgroups and streams.¶
+When a Track's forwarding preference (see Section 8.1.1) is +"Datagram", Objects are not sent in Subgroups and the +description in the remainder of this section does not apply.¶
+Streams offer in-order reliable delivery and the ability to cancel sending +and retransmission of data. Furthermore, many implementations offer the ability +to control the relative priority of streams, which allows control over the +scheduling of sending data on active streams.¶
+Every object within a Group belongs to exactly one Subgroup.¶
+Objects from two subgroups cannot be sent on the same stream. Objects from the +same Subgroup MUST NOT be sent on different streams, unless one of the streams +was reset prematurely, or upstream conditions have forced objects from a Subgroup +to be sent out of Object ID order.¶
+Original publishers assign each Subgroup a Subgroup ID, and do so as they see fit. The +scope of a Subgroup ID is a Group, so Subgroups from different Groups MAY share a Subgroup +ID without implying any relationship between them. In general, publishers assign +objects to subgroups in order to leverage the features of streams as described +above.¶
+An example strategy for using stream properties follows. If object B is +dependent on object A, then delivery of B can follow A, i.e. A and B can be +usefully delivered over a single stream. Furthermore, in this example:¶
+If an object is dependent on all previous objects in a Subgroup, it is added to +that Subgroup.¶
+If an object is not dependent on all of the objects in a Subgroup, it goes in +a different Subgroup.¶
+There are often many ways to compose Subgroups that meet these criteria. Where +possible, choose the composition that results in the fewest Subgroups in a group +to minimize the number of streams used.¶
+A group is a collection of objects and is a sub-unit of a track (Section 2.4). +Groups SHOULD be indendepently useful, so objects within a group SHOULD NOT depend +on objects in other groups. A group provides a join point for subscriptions, so a +subscriber that does not want to receive the entire track can opt to receive only +the latest group(s). The publisher then selectively transmits objects based on +their group membership. Groups can contain any number of objects.¶
+Within a track, the original publisher SHOULD produce Group IDs which increase +with time. Subscribers to tracks which do not follow this requirement SHOULD NOT +use range filters which span multiple groups in FETCH or SUBSCRIBE. SUBSCRIBE and +FETCH delivery use Group Order, so a FETCH cannot deliver Groups out of order +and a subscription could have unexpected delivery order if Group IDs do not increase +with time.¶
+A track is a sequence of groups (Section 2.3). It is the entity +against which a subscriber issues a subscription request. A subscriber +can request to receive individual tracks starting at a group boundary, +including any new objects pushed by the publisher while the track is +active.¶
+In MOQT, every track is identified by a Full Track Name, consisting of a Track +Namespace and a Track Name.¶
+Track Namespace is an ordered N-tuple of bytes where N can be between 1 and 32. +The structured nature of Track Namespace allows relays and applications to +manipulate prefixes of a namespace. If an endpoint receives a Track Namespace +tuple with an N of 0 or more than 32, it MUST close the session with a Protocol +Violation.¶
+Track Name is a sequence of bytes that identifies an individual track within the +namespace.¶
+In this specification, both the Track Namespace tuple fields and the Track Name +are not constrained to a specific encoding. They carry a sequence of bytes and +comparison between two Track Namespace tuple fields or Track Names is done by +exact comparison of the bytes. Specifications that use MoQ Transport may +constrain the information in these fields, for example by restricting them to +UTF-8. Any specification that does needs to specify the canonicalization into +the bytes in the Track Namespace or Track Name such that exact comparison works.¶
+A MOQT scope is a set of servers (as identified by their connection +URIs) for which the tuple of Track Name and Track Namespace are +guaranteed to be unique and identify a specific track. It is up to +the application using MOQT to define how broad or narrow the scope is. +An application that deals with connections between devices +on a local network may limit the scope to a single connection; by +contrast, an application that uses multiple CDNs to serve media may +require the scope to include all of those CDNs.¶
+Because the tuple of Track Namespace and Track Name are unique within an +MOQT scope, they can be used as a cache key. +MOQT does not provide any in-band content negotiation methods similar to +the ones defined by HTTP ([RFC9110], Section 10); if, at a given +moment in time, two tracks within the same scope contain different data, +they have to have different names and/or namespaces.¶
+This document defines a protocol that can be used interchangeably both +over a QUIC connection directly [QUIC], and over WebTransport +[WebTransport]. Both provide streams and datagrams with similar +semantics (see [I-D.ietf-webtrans-overview], Section 4); thus, the +main difference lies in how the servers are identified and how the +connection is established. When using QUIC, datagrams MUST be +supported via the [QUIC-DATAGRAM] extension, which is already a +requirement for WebTransport over HTTP/3.¶
+There is no definition of the protocol over other transports, +such as TCP, and applications using MoQ might need to fallback to +another protocol when QUIC or WebTransport aren't available.¶
+A MOQT server that is accessible via WebTransport can be identified +using an HTTPS URI ([RFC9110], Section 4.2.2). A MOQT session can be +established by sending an extended CONNECT request to the host and the +path indicated by the URI, as described in +([WebTransport], Section 3).¶
+A MOQT server that is accessible via native QUIC can be identified by a +URI with a "moqt" scheme. The "moqt" URI scheme is defined as follows, +using definitions from [RFC3986]:¶
++moqt-URI = "moqt" "://" authority path-abempty [ "?" query ] +¶ +
The authority
portion MUST NOT contain an empty host
portion.
+The moqt
URI scheme supports the /.well-known/
path prefix defined in
+[RFC8615].¶
This protocol does not specify any semantics on the path-abempty
and
+query
portions of the URI. The contents of those are left up to the
+application.¶
The client can establish a connection to a MoQ server identified by a
+given URI by setting up a QUIC connection to the host and port
+identified by the authority
section of the URI. The path-abempty
+and query
portions of the URI are communicated to the server using the
+PATH parameter (Section 7.2.2.1) which is sent in the CLIENT_SETUP message at the
+start of the session. The ALPN value [RFC7301] used by the protocol
+is moq-00
.¶
Each track MAY have one or more associated connection URLs specifying +network hosts through which a track may be accessed. The syntax of the +Connection URL and the associated connection setup procedures are +specific to the underlying transport protocol usage Section 3.¶
+Endpoints use the exchange of Setup messages to negotiate the MOQT version and +any extensions to use.¶
+The client indicates the MOQT versions it supports in the CLIENT_SETUP message +(see Section 7.2). It also includes the union of all Setup Parameters +Section 7.2.2 required for a handshake by any of those versions.¶
+Within any MOQT version, clients request the use of extensions by adding Setup +parameters corresponding to that extension. No extensions are defined in this +document.¶
+The server replies with a SERVER_SETUP message that indicates the chosen +version, includes all parameters required for a handshake in that version, and +parameters for every extension requested by the client that it supports.¶
+New versions of MOQT MUST specify which existing extensions can be used with +that version. New extensions MUST specify the existing versions with which they +can be used.¶
+If a given parameter carries the same information in multiple versions, +but might have different optimal values in those versions, there SHOULD be +separate Setup parameters for that information in each version.¶
+The first stream opened is a client-initiated bidirectional control stream where +the endpoints exchange Setup messages (Section 7.2). All messages defined +in this draft except OBJECT and OBJECT_WITH_LENGTH are sent on the control +stream after the Setup message. Control messages MUST NOT be sent on any other +stream, and a peer receiving a control message on a different stream closes the +session as a 'Protocol Violation'. Objects MUST NOT be sent on the control +stream, and a peer receiving an Object on the control stream closes the session +as a 'Protocol Violation'.¶
+This draft only specifies a single use of bidirectional streams. Objects are +sent on unidirectional streams. Because there are no other uses of +bidirectional streams, a peer MAY currently close the session as a +'Protocol Violation' if it receives a second bidirectional stream.¶
+The control stream MUST NOT be closed at the underlying transport layer while the +session is active. Doing so results in the session being closed as a +'Protocol Violation'.¶
+Streams aside from the control stream MAY be canceled due to congestion +or other reasons by either the publisher or subscriber. Early termination of a +stream does not affect the MoQ application state, and therefore has no +effect on outstanding subscriptions.¶
+The Transport Session can be terminated at any point. When native QUIC +is used, the session is closed using the CONNECTION_CLOSE frame +([QUIC], Section 19.19). When WebTransport is used, the session is +closed using the CLOSE_WEBTRANSPORT_SESSION capsule ([WebTransport], Section 5).¶
+The application MAY use any error message and SHOULD use a relevant +code, as defined below:¶
+Code | +Reason | +
---|---|
0x0 | +No Error | +
0x1 | +Internal Error | +
0x2 | +Unauthorized | +
0x3 | +Protocol Violation | +
0x4 | +Duplicate Track Alias | +
0x5 | +Parameter Length Mismatch | +
0x6 | +Too Many Subscribes | +
0x10 | +GOAWAY Timeout | +
0x11 | +Control Message Timeout | +
0x12 | +Data Stream Timeout | +
No Error: The session is being terminated without an error.¶
+Internal Error: An implementation specific error occurred.¶
+Unauthorized: The endpoint breached an agreement, which MAY have been + pre-negotiated by the application.¶
+Protocol Violation: The remote endpoint performed an action that was +disallowed by the specification.¶
+Duplicate Track Alias: The endpoint attempted to use a Track Alias +that was already in use.¶
+Too Many Subscribes: The session was closed because the subscriber used +a Subscribe ID equal or larger than the current Maximum Subscribe ID.¶
+GOAWAY Timeout: The session was closed because the peer took too long to +close the session in response to a GOAWAY (Section 7.3) message. +See session migration (Section 3.6).¶
+Control Message Timeout: The session was closed because the peer took too +long to respond to a control message.¶
+Data Stream Timeout: The session was closed because the peer took too +long to send data expected on an open Data Stream Section 8. This +includes fields of a stream header or an object header within a data +stream. If an endpoint times out waiting for a new object header on an +open subgroup stream, it MAY send a STOP_SENDING on that stream, terminate +the subscription, or close the session with an error.¶
+MOQT requires a long-lived and stateful session. However, a service +provider needs the ability to shutdown/restart a server without waiting for all +sessions to drain naturally, as that can take days for long-form media. +MOQT enables proactively draining sessions via the GOAWAY message (Section 7.3).¶
+The server sends a GOAWAY message, signaling the client to establish a new +session and migrate any active subscriptions. The GOAWAY message optionally +contains a new URI for the new session, otherwise the current URI is +reused. The server SHOULD terminate the session with 'GOAWAY Timeout' after a +sufficient timeout if there are still open subscriptions or fetches on a +connection.¶
+When the server is a subscriber, it SHOULD send a GOAWAY message to downstream +subscribers prior to any UNSUBSCRIBE messages to upstream publishers.¶
+After the client receives a GOAWAY, it's RECOMMENDED that the client waits until +there are no more active subscriptions before closing the session with NO_ERROR. +Ideally this is transparent to the application using MOQT, which involves +establishing a new session in the background and migrating active subscriptions +and announcements. The client can choose to delay closing the session if it +expects more OBJECTs to be delivered. The server closes the session with a +'GOAWAY Timeout' if the client doesn't close the session quickly enough.¶
+Discovery of MoQT servers is always done out-of-band. Namespace discovery can be +done in the context of an established MoQT session.¶
+Given sufficient out of band information, it is valid for a subscriber +to send a SUBSCRIBE or FETCH message to a publisher (including a relay) without +any previous MoQT messages besides SETUP. However, SUBSCRIBE_ANNOUNCES and +ANNOUNCE messages provide an in-band means of discovery of subscribers and +publishers for a namespace.¶
+The syntax of these messages is described in Section 7.¶
+If the subscriber is aware of a namespace of interest, it can send +SUBSCRIBE_ANNOUNCES to publishers/relays it has established a session with. The +recipient of this message will send any relevant ANNOUNCE or UNANNOUNCE messages +for that namespace, or subset of that namespace.¶
+A publisher MUST send exactly one SUBSCRIBE_ANNOUNCES_OK or +SUBSCRIBE_ANNOUNCES_ERROR in response to a SUBSCRIBE_ANNOUNCES. The subscriber +SHOULD close the session with a protocol error if it detects receiving more than +one.¶
+The receiver of a SUBSCRIBE_ANNOUNCES_OK or SUBSCRIBE_ANNOUNCES_ERROR ought to +forward the result to the application, so that it can make decisions about +further publishers to contact.¶
+An UNSUBSCRIBE_ANNOUNCES withdraws a previous SUBSCRIBE_ANNOUNCES. It does +not prohibit the receiver (publisher) from sending further ANNOUNCE messages.¶
+A publisher MAY send ANNOUNCE messages to any subscriber. An ANNOUNCE indicates +to the subscriber where to route a SUBSCRIBE or FETCH for that namespace. A +subscriber MAY send SUBSCRIBE or FETCH for a namespace without having received +an ANNOUNCE for it.¶
+If a publisher is authoritative for a given namespace, or is a relay that has +received an authorized ANNOUNCE for that namespace from an upstream publisher, +it MUST send an ANNOUNCE to any subscriber that has subscribed to ANNOUNCE for +that namespace, or a subset of that namespace. A publisher MAY send the ANNOUNCE +to any other subscriber.¶
+An endpoint SHOULD NOT, however, send an ANNOUNCE advertising a namespace that +exactly matches a namespace for which the peer sent an earlier ANNOUNCE +(i.e. an ANNOUNCE ought not to be echoed back to its sender).¶
+The receiver of an ANNOUNCE_OK or ANNOUNCE_ERROR SHOULD report this to the +application to inform the search for additional subscribers for a namespace, +or abandoning the attempt to publish under this namespace. This might be +especially useful in upload or chat applications. A subscriber MUST send exactly +one ANNOUNCE_OK or ANNOUNCE_ERROR in response to an ANNOUNCE. The publisher +SHOULD close the session with a protocol error if it receives more than one.¶
+An UNANNOUNCE message withdraws a previous ANNOUNCE, although it is not a +protocol error for the subscriber to send a SUBSCRIBE or FETCH message after +receiving an UNANNOUNCE.¶
+A subscriber can send ANNOUNCE_CANCEL to revoke acceptance of an ANNOUNCE, for +example due to expiration of authorization credentials. The message enables the +publisher to ANNOUNCE again with refreshed authorization, or discard associated +state. After receiving an ANNOUNCE_CANCEL, the publisher does not send UNANNOUNCE.¶
+While ANNOUNCE does provide hints on where to route a SUBSCRIBE or FETCH, it is +not a full-fledged routing protocol and does not protect against loops and other +phenomena. In particular, ANNOUNCE SHOULD NOT be used to find paths through +richly connected networks of relays.¶
+The central interaction with a publisher is to send SUBSCRIBE and/or FETCH for +a particular track. The subscriber expects to receive a +SUBSCRIBE_OK/FETCH_OK and objects from the track.¶
+A subscriber MAY send a SUBSCRIBE or FETCH for a track to any publisher. If it +has accepted an ANNOUNCE with a namespace that exactly matches the namespace for +that track, it SHOULD only request it from the senders of those ANNOUNCE +messages.¶
+A publisher MUST send exactly one SUBSCRIBE_OK or SUBSCRIBE_ERROR in response to +a SUBSCRIBE. It MUST send exactly one FETCH_OK or FETCH_ERROR in response to a +FETCH. The subscriber SHOULD close the session with a protocol error if it +receives more than one.¶
+A subscriber keeps SUBSCRIBE state until it sends UNSUBSCRIBE, or after receipt +of a SUBSCRIBE_DONE or SUBSCRIBE_ERROR. Note that SUBSCRIBE_DONE does not +usually indicate that state can immediately be destroyed, see +Section 7.19.¶
+A subscriber keeps FETCH state until it sends FETCH_CANCEL, receives +FETCH_ERROR, or receives a FIN or RESET_STREAM for the FETCH data stream. If the +data stream is already open, it MAY send STOP_SENDING for the data stream along +with FETCH_CANCEL, but MUST send FETCH_CANCEL.¶
+The Publisher can destroy subscription or fetch state as soon as it has received +UNSUBSCRIBE or FETCH_CANCEL, respectively. It MUST reset any open streams +associated with the SUBSCRIBE or FETCH. It can also destroy state after closing +the FETCH data stream.¶
+The publisher can immediately delete SUBSCRIBE state after sending +SUBSCRIBE_DONE, but MUST NOT send it until it has closed all related streams. It +can destroy all FETCH state after closing the data stream.¶
+A SUBSCRIBE_ERROR or FETCH_ERROR indicates no objects will be delivered, and +both endpoints can immediately destroy relevant state. Objects MUST NOT be sent +for requests that end with an error.¶
+MoQ priorities allow a subscriber and original publisher to influence +the transmission order of Objects within a session in the presence of +congestion.¶
+MoQT maintains priorities between different schedulable objects. +A schedulable object in MoQT is either:¶
+An object that belongs to a subgroup where that object would be the next +object to be sent in that subgroup.¶
+An object that belongs to a track with delivery preference Datagram.¶
+Since a single subgroup or datagram has a single publisher priority, it can be +useful to conceptualize this process as scheduling subgroups or datagrams +instead of individual objects on them.¶
+A priority number is an unsigned integer with a value between 0 and 255. +A lower priority number indicates higher priority; the highest priority is 0.¶
+Subscriber Priority is a priority number associated with an individual +subscription. It is specified in the SUBSCRIBE message, and can be updated via +SUBSCRIBE_UPDATE message. The subscriber priority of an individual schedulable +object is the subscriber priority of the subscription that caused that object +to be sent. When subscriber priority is changed, a best effort SHOULD be made +to apply the change to all objects that have not been sent, but it is +implementation dependent what happens to objects that have already been +received and possibly scheduled.¶
+Publisher Priority is a priority number associated with an individual +schedulable object. It is specified in the header of the respective subgroup or +datagram, and is the same for all objects in a single subgroup.¶
+Group Order is a property of an invidual subscription. It can be either +'Ascending' (groups with lower group ID are sent first), or 'Descending' +(groups with higher group ID are sent first). The publisher communicates its +group order in the SUBSCRIBE_OK message; the subscriber can override it in its +SUBSCRIBE message. The group order of an existing subscription cannot be +changed.¶
+When an MoQT publisher has multiple schedulable objects it can choose between, +the objects SHOULD be selected as follows:¶
+If two objects have a different subscriber priority associated with them, +the one with the highest subscriber priority is sent first.¶
+If two objects have the same subscriber priority, but a different publisher +priority, the one with the highest publisher priority is sent first.¶
+If two objects have the same subscriber and publisher priority, but belong +to two different groups of the same track, +the group order of the associated subscription is used to +decide the one that is sent first.¶
+If two objects belong to the same group of the same track, +the one with the lowest Subgroup ID (for tracks +with delivery preference Subgroup), or the lowest Object ID (for tracks +with delivery preference Datagram) is sent first.¶
+This algorithm does not provide a well-defined ordering for objects that belong +to different subscriptions, but have the same subscriber and publisher +priority. The ordering in those cases is implementation-defined, though the +expectation is that all subscriptions will be able to send some data.¶
+Given the critical nature of control messages and their relatively +small size, the control stream SHOULD be prioritized higher than all +subscribed Objects.¶
+Relays SHOULD respect the subscriber and original publisher's priorities. +Relays SHOULD NOT directly use Subscriber Priority or Group Order +from incoming subscriptions for upstream subscriptions. Relays use of +Subscriber Priority for upstream subscriptions can be based on +factors specific to it, such as the popularity of the +content or policy, or relays can specify the same value for all +upstream subscriptions.¶
+MoQ Sessions can span multiple namespaces, and priorities might not +be coordinated across namespaces. The subscriber's priority is +considered first, so there is a mechanism for a subscriber to fix +incompatibilities between different namespaces prioritization schemes. +Additionally, it is anticipated that when multiple namespaces +are present within a session, the namespaces could be coordinating, +possibly part of the same application. In cases when pooling among +namespaces is expected to cause issues, multiple MoQ sessions, either +within a single connection or on multiple connections can be used.¶
+Implementations that have a default priority SHOULD set it to a value in +the middle of the range (eg: 128) to allow non-default priorities to be +set either higher or lower.¶
+Relays are leveraged to enable distribution scale in the MoQ +architecture. Relays can be used to form an overlay delivery network, +similar in functionality to Content Delivery Networks +(CDNs). Additionally, relays serve as policy enforcement points by +validating subscribe and publish requests at the edge of a network.¶
+Relays are endpoints, which means they terminate Transport Sessions in order to +have visibility of MoQ Object metadata.¶
+Relays MAY cache Objects, but are not required to.¶
+Subscribers subscribe to tracks by sending a SUBSCRIBE +(Section 7.4) control message for each track of +interest. Relays MUST ensure subscribers are authorized to access the +content associated with the track. The authorization +information can be part of subscription request itself or part of the +encompassing session. The specifics of how a relay authorizes a user are outside +the scope of this specification.¶
+The relay will have to send an upstream SUBSCRIBE and/or FETCH if it does not +have all the objects in the FETCH, or is not currently subscribed to the full +requested range. In this case, it SHOULD withhold sending its own SUBSCRIBE_OK +until receiving one from upstream. It MUST withhold FETCH_OK until receiving +one from upstream.¶
+For successful subscriptions, the publisher maintains a list of +subscribers for each track. Each new OBJECT belonging to the +track within the subscription range is forwarded to each active +subscriber, dependent on the congestion response.¶
+A caching relay saves Objects to its cache identified by the Object's +Full Track Name, Group ID and Object ID. Relays MUST be able to +process objects for the same Full Track Name from multiple +publishers and forward objects to active matching subscriptions. +If multiple objects are received with the same Full Track Name, +Group ID and Object ID, Relays MAY ignore subsequently received Objects +or MAY use them to update the cache. Implementations that update the +cache need to protect against cache poisoning.¶
+A relay MUST NOT reorder or drop objects received on a multi-object stream when +forwarding to subscribers, unless it has application specific information.¶
+Relays MAY aggregate authorized subscriptions for a given track when +multiple subscribers request the same track. Subscription aggregation +allows relays to make only a single upstream subscription for the +track. The published content received from the upstream subscription +request is cached and shared among the pending subscribers.¶
+This section describes behavior a subscriber MAY implement +to allow for a better user experience when a relay sends a GOAWAY.¶
+When a subscriber receives the GOAWAY message, it starts the process +of connecting to a new relay and sending the SUBSCRIBE requests for +all active subscriptions to the new relay. The new relay will send a +response to the subscribes and if they are successful, the subscriptions +to the old relay can be stopped with an UNSUBSCRIBE.¶
+Publishing through the relay starts with publisher sending ANNOUNCE
+control message with a Track Namespace
(Section 2.4).
+The ANNOUNCE enables the relay to know which publisher to forward a
+SUBSCRIBE to.¶
Relays MUST verify that publishers are authorized to publish +the content associated with the set of +tracks whose Track Namespace matches the announced namespace. Where the +authorization and identification of the publisher occurs depends on the way the +relay is managed and is application specific.¶
+A Relay can receive announcements from multiple publishers for the same +Track Namespace and it SHOULD respond with the same response to each of the +publishers, as though it was responding to an ANNOUNCE +from a single publisher for a given track namespace.¶
+When a publisher wants to stop +new subscriptions for an announced namespace it sends an UNANNOUNCE. +A subscriber indicates it will no longer route subscriptions for a +namespace it previously responded ANNOUNCE_OK to by sending an +ANNOUNCE_CANCEL.¶
+A relay manages sessions from multiple publishers and subscribers, +connecting them based on the track namespace. This MUST use an exact +match on track namespace unless otherwise negotiated by the application. +For example, a SUBSCRIBE namespace=foobar message will be forwarded to +the session that sent ANNOUNCE namespace=foobar.¶
+When a relay receives an incoming SUBSCRIBE request that triggers an +upstream subscription, it SHOULD send a SUBSCRIBE request to each +publisher that has announced the subscription's namespace, unless it +already has an active subscription for the Objects requested by the +incoming SUBSCRIBE request from all available publishers.¶
+When a relay receives an incoming ANNOUNCE for a given namespace, for +each active upstream subscription that matches that namespace, it SHOULD send a +SUBSCRIBE to the publisher that sent the ANNOUNCE.¶
+OBJECT message headers carry a short hop-by-hop Track Alias
that maps to
+the Full Track Name (see Section 7.15). Relays use the
+Track Alias
of an incoming OBJECT message to identify its track and find
+the active subscribers for that track. Relays MUST forward OBJECT messages to
+matching subscribers in accordance to each subscription's priority, group order,
+and delivery timeout.¶
This section describes behavior that a publisher MAY +choose to implement to allow for a better users experience when +switching between networks, such as WiFi to Cellular or vice versa.¶
+If the original publisher detects it is likely to need to switch networks, +for example because the WiFi signal is getting weaker, and it does not +have QUIC connection migration available, it establishes a new session +over the new interface and sends an ANNOUCE. The relay will forward +matching subscribes and the publisher publishes objects on both sessions. +Once the subscriptions have migrated over to session on the new network, +the publisher can stop publishing objects on the old network. The relay +will drop duplicate objects received on both subscriptions. +Ideally, the subscriptions downstream from the relay do no observe this +change, and keep receiving the objects on the same subscription.¶
+This section describes behavior that a publisher MAY choose to implement +to allow for a better user experience when a relay sends them a GOAWAY.¶
+When a publisher receives a GOAWAY, it starts the process of +connecting to a new relay and sends announces, but it does not immediately +stop publishing objects to the old relay. The new relay will send +subscribes and the publisher can start sending new objects to the new relay +instead of the old relay. Once objects are going to the new relay, +the announcement and subscription to the old relay can be stopped.¶
+MOQT encodes the delivery information for a stream via OBJECT headers +(Section 8.1). A relay MUST NOT modify Object properties when +forwarding.¶
+A relay MUST treat the object payload as opaque. A relay MUST NOT +combine, split, or otherwise modify object payloads. A relay SHOULD +prioritize sending Objects based on Section 5.¶
+A publisher SHOULD begin sending incomplete objects when available to +avoid incurring additional latency.¶
+A relay that reads from one stream and writes to another in order can +introduce head-of-line blocking. Packet loss will cause stream data to +be buffered in the library, awaiting in-order delivery, which could +increase latency over additional hops. To mitigate this, a relay MAY +read and write stream data out of order subject to flow control +limits. See section 2.2 in [QUIC].¶
+MOQT uses a single bidirectional stream to exchange control messages, as +defined in Section 3.3. Every single message on the control stream is +formatted as follows:¶
++MOQT Control Message { + Message Type (i), + Message Length (i), + Message Payload (..), +} ++
ID | +Messages | +
---|---|
0x2 | +SUBSCRIBE_UPDATE (Section 7.5) | +
0x3 | +SUBSCRIBE (Section 7.4) | +
0x4 | +SUBSCRIBE_OK (Section 7.15) | +
0x5 | +SUBSCRIBE_ERROR (Section 7.16) | +
0x6 | +ANNOUNCE (Section 7.22) | +
0x7 | +ANNOUNCE_OK (Section 7.9) | +
0x8 | +ANNOUNCE_ERROR (Section 7.10) | +
0x9 | +UNANNOUNCE (Section 7.23) | +
0xA | +UNSUBSCRIBE (Section 7.6) | +
0xB | +SUBSCRIBE_DONE (Section 7.19) | +
0xC | +ANNOUNCE_CANCEL (Section 7.11) | +
0xD | +TRACK_STATUS_REQUEST (Section 7.12) | +
0xE | +TRACK_STATUS (Section 7.24) | +
0x10 | +GOAWAY (Section 7.3) | +
0x11 | +SUBSCRIBE_ANNOUNCES (Section 7.13) | +
0x12 | +SUBSCRIBE_ANNOUNCES_OK (Section 7.25) | +
0x13 | +SUBSCRIBE_ANNOUNCES_ERROR (Section 7.26 + | +
0x14 | +UNSUBSCRIBE_ANNOUNCES (Section 7.14) | +
0x15 | +MAX_SUBSCRIBE_ID (Section 7.20) | +
0x1A | +SUBSCRIBES_BLOCKED (Section 7.21) | +
0x16 | +FETCH (Section 7.7) | +
0x17 | +FETCH_CANCEL (Section 7.8) | +
0x18 | +FETCH_OK (Section 7.17) | +
0x19 | +FETCH_ERROR (Section 7.18) | +
0x40 | +CLIENT_SETUP (Section 7.2) | +
0x41 | +SERVER_SETUP (Section 7.2) | +
An endpoint that receives an unknown message type MUST close the session. +Control messages have a length to make parsing easier, but no control +messages are intended to be ignored. If the length does not match the +length of the message content, the receiver MUST close the session.¶
+Some messages include a Parameters field that encode optional message +elements. They contain a type, length, and value.¶
+Senders MUST NOT repeat the same parameter type in a message. Receivers +SHOULD check that there are no duplicate parameters and close the session +as a 'Protocol Violation' if found.¶
+Receivers ignore unrecognized parameters.¶
+The format of Parameters is as follows:¶
++Parameter { + Parameter Type (i), + Parameter Length (i), + Parameter Value (..), +} ++
Parameter Type is an integer that indicates the semantic meaning of the +parameter. Setup message parameters use a namespace that is constant across all +MoQ Transport versions. All other messages use a version-specific namespace. For +example, the integer '1' can refer to different parameters for Setup messages +and for all other message types.¶
+SETUP message parameter types are defined in Section 7.2.2. Version- +specific parameter types are defined in Section 7.1.1.¶
+The Parameter Length field of the String Parameter encodes the length +of the Parameter Value field in bytes.¶
+Each parameter description will indicate the data type in the Parameter Value +field. If a receiver understands a parameter type, and the parameter length +implied by that type does not match the Parameter Length field, the receiver +MUST terminate the session with error code 'Parameter Length Mismatch'.¶
+Each version-specific parameter definition indicates the message types in which +it can appear. If it appears in some other type of message, it MUST be ignored. +Note that since Setup parameters use a separate namespace, it is impossible for +these parameters to appear in Setup messages.¶
+ +The DELIVERY TIMEOUT parameter (Parameter Type 0x03) MAY appear in a +SUBSCRIBE, SUBSCRIBE_OK, or a SUBSCRIBE_UDPATE message. It is the duration in +milliseconds the relay SHOULD continue to attempt forwarding Objects after +they have been received. The start time for the timeout is based on when the +beginning of the Object is received, and does not depend upon the forwarding +preference. There is no explicit signal that an Object was not sent because +the delivery timeout was exceeded.¶
+If both the subscriber and publisher specify the parameter, they use the min of the +two values for the subscription. The publisher SHOULD always specify the value +received from an upstream subscription when there is one, and nothing otherwise. +If an earlier Object arrives later than subsequent Objects, relays can consider +the receipt time as that of the next later Object, with the assumption that the +Object's data was reordered.¶
+If neither the subscriber or publisher specify DELIVERY TIMEOUT, all Objects +in the track matching the subscription filter are delivered as indicated by +their Group Order and Priority. If a subscriber exceeds the publisher's +resource limits by failing to consume objects at a sufficient rate, the +publisher MAY terminate the subscription with error 'Too Far Behind'.¶
+If an object in a subgroup exceeds the delivery timeout, the publisher MUST +reset the underlying transport stream (see Section 8.4.2).¶
+When sent by a subscriber, this parameter is intended to be specific to a +subscription, so it SHOULD NOT be forwarded upstream by a relay that intends +to serve multiple subscriptions for the same track.¶
+Publishers SHOULD consider whether the entire Object is likely to be delivered +before sending any data for that Object, taking into account priorities, +congestion control, and any other relevant information.¶
+MAX_CACHE_DURATION (Parameter Type 0x04): An integer expressing a number of +milliseconds. If present, the relay MUST NOT start forwarding any individual +Object received through this subscription after the specified number of +milliseconds has elapsed since the beginning of the Object was received. This +means Objects earlier in a multi-object stream will expire earlier than Objects +later in the stream. Once Objects have expired, their state becomes unknown, and +a relay that handles a subscription that includes those Objects re-requests them.¶
+The CLIENT_SETUP
and SERVER_SETUP
messages are the first messages exchanged
+by the client and the server; they allow the endpoints to establish the mutually
+supported version and agree on the initial configuration before any objects are
+exchanged. It is a sequence of key-value pairs called Setup parameters; the
+semantics and format of which can vary based on whether the client or server is
+sending. To ensure future extensibility of MOQT, endpoints MUST ignore unknown
+setup parameters. TODO: describe GREASE for those.¶
The wire format of the Setup messages are as follows:¶
++CLIENT_SETUP Message { + Type (i) = 0x40, + Length (i), + Number of Supported Versions (i), + Supported Version (i) ..., + Number of Parameters (i) ..., + Setup Parameters (..) ..., +} + +SERVER_SETUP Message { + Type (i) = 0x41, + Length (i), + Selected Version (i), + Number of Parameters (i) ..., + Setup Parameters (..) ..., +} ++
The available versions and Setup parameters are detailed in the next sections.¶
+MoQ Transport versions are a 32-bit unsigned integer, encoded as a varint. +This version of the specification is identified by the number 0x00000001. +Versions with the most significant 16 bits of the version number cleared are +reserved for use in future IETF consensus documents.¶
+The client offers the list of the protocol versions it supports; the +server MUST reply with one of the versions offered by the client. If the +server does not support any of the versions offered by the client, or +the client receives a server version that it did not offer, the +corresponding peer MUST close the session.¶
+[[RFC editor: please remove the remainder of this section before +publication.]]¶
+The version number for the final version of this specification (0x00000001), is +reserved for the version of the protocol that is published as an RFC. +Version numbers used to identify IETF drafts are created by adding the draft +number to 0xff000000. For example, draft-ietf-moq-transport-13 would be +identified as 0xff00000D.¶
+The PATH parameter (Parameter Type 0x01) allows the client to specify the path +of the MoQ URI when using native QUIC ([QUIC]). It MUST NOT be used by +the server, or when WebTransport is used. If the peer receives a PATH +parameter from the server, or when WebTransport is used, it MUST close +the connection. It follows the URI formatting rules [RFC3986].¶
+When connecting to a server using a URI with the "moqt" scheme, the
+client MUST set the PATH parameter to the path-abempty
portion of the
+URI; if query
is present, the client MUST concatenate ?
, followed by
+the query
portion of the URI to the parameter.¶
The MAX_SUBSCRIBE_ID parameter (Parameter Type 0x02) communicates an initial +value for the Maximum Subscribe ID to the receiving subscriber. The default +value is 0, so if not specified, the peer MUST NOT create subscriptions.¶
+An endpoint sends a GOAWAY
message to inform the peer it intends to close
+the session soon. Servers can use GOAWAY to initiate session migration
+(Section 3.6) with an optional URI.¶
The GOAWAY message does not impact subscription state. A subscriber +SHOULD individually UNSUBSCRIBE for each existing subscription, while a +publisher MAY reject new requests while in the draining state.¶
+Upon receiving a GOAWAY, an endpoint SHOULD NOT initiate new requests to +the peer including SUBSCRIBE, FETCH, ANNOUNCE and SUBSCRIBE_ANNOUNCE.¶
+The endpoint MUST terminate the session with a Protocol Violation +(Section 3.5) if it receives multiple GOAWAY messages.¶
++GOAWAY Message { + Type (i) = 0x10, + Length (i), + New Session URI Length (i), + New Session URI (..), +} ++
New Session URI: When received by a client, indicates where the client can +connect to continue this session. The client MUST use this URI for the new +session if provided. If the URI is zero bytes long, the client can reuse the +current URI is reused instead. The new session URI SHOULD use the same scheme +as the current URL to ensure compatibility.¶
++If a server receives a GOAWAY with a non-zero New Session URI Length it MUST +terminate the session with a Protocol Violation.¶
+A subscription causes the publisher to send newly published objects for a track. +A subscriber MUST NOT make multiple active subscriptions for a track within a +single session and publishers SHOULD treat this as a protocol violation.¶
+Filter Types¶
+The subscriber specifies a filter on the subscription to allow +the publisher to identify which objects need to be delivered.¶
+There are 3 types of filters:¶
+Latest Object (0x2): Specifies an open-ended subscription beginning from +the current object of the current group. If no content has been delivered yet, +the subscription starts with the first published or received group.¶
+AbsoluteStart (0x3): Specifies an open-ended subscription beginning +from the object identified in the StartGroup and StartObject fields. If the +StartGroup is prior to the current group, the subscription starts at the +beginning of the current object like the 'Latest Object' filter.¶
+AbsoluteRange (0x4): Specifies a closed subscription starting at StartObject +in StartGroup and ending at the largest object in EndGroup. The start and +end of the range are inclusive. EndGroup MUST specify the same or a later +group than StartGroup. If the StartGroup is prior to the current group, the +subscription starts at the beginning of the current object like the 'Latest +Object' filter.¶
+A filter type other than the above MUST be treated as error.¶
+If a subscriber wants to subscribe to Objects both before and after +the Latest Object, it can send a SUBSCRIBE for the Latest Object +followed by a FETCH. Depending upon the application, one might want to send +both messages at the same time or wait for the first to return before sending +the second.¶
+The format of SUBSCRIBE is as follows:¶
++SUBSCRIBE Message { + Type (i) = 0x3, + Length (i), + Subscribe ID (i), + Track Alias (i), + Track Namespace (tuple), + Track Name Length (i), + Track Name (..), + Subscriber Priority (8), + Group Order (8), + Filter Type (i), + [StartGroup (i), + StartObject (i)], + [EndGroup (i)], + Number of Parameters (i), + Subscribe Parameters (..) ... +} ++
Subscribe ID: The subscriber specified identifier used to manage a
+subscription. Subscribe ID
is a variable length integer that MUST be
+unique and monotonically increasing within a session and MUST be less
+than the session's Maximum Subscribe ID.¶
Track Alias: A session specific identifier for the track. +Messages that reference a track, such as OBJECT (Section 8.1), +reference this Track Alias instead of the Track Name and Track Namespace to +reduce overhead. If the Track Alias is already being used for a different +track, the publisher MUST close the session with a Duplicate Track Alias +error (Section 3.5).¶
+Track Namespace: Identifies the namespace of the track as defined in +(Section 2.4.1).¶
+Track Name: Identifies the track name as defined in (Section 2.4.1).¶
+Subscriber Priority: Specifies the priority of a subscription relative to +other subscriptions in the same session. Lower numbers get higher priority. +See Section 5.¶
+Group Order: Allows the subscriber to request Objects be delivered in +Ascending (0x1) or Descending (0x2) order by group. See Section 5. +A value of 0x0 indicates the original publisher's Group Order SHOULD be +used. Values larger than 0x2 are a protocol error.¶
+Filter Type: Identifies the type of filter, which also indicates whether +the StartGroup/StartObject and EndGroup/EndObject fields will be present.¶
+StartGroup: The start Group ID. Only present for "AbsoluteStart" and +"AbsoluteRange" filter types.¶
+StartObject: The start Object ID. Only present for "AbsoluteStart" and +"AbsoluteRange" filter types.¶
+EndGroup: The end Group ID, inclusive. Only present for the "AbsoluteRange" +filter type.¶
+Subscribe Parameters: The parameters are defined in Section 7.1.1.¶
+On successful subscription, the publisher MUST reply with a SUBSCRIBE_OK, +allowing the subscriber to determine the start group/object when not explicitly +specified and the publisher SHOULD start delivering objects.¶
+If a publisher cannot satisfy the requested start or end or if the end has +already been published it SHOULD send a SUBSCRIBE_ERROR with code 'Invalid Range'. +A publisher MUST NOT send objects from outside the requested start and end.¶
+A subscriber issues a SUBSCRIBE_UPDATE to a publisher to request a change to +an existing subscription. Subscriptions can only become more narrow, not wider, +because an attempt to widen a subscription could fail. If Objects before the +start or after the end of the current subscription are needed, a fetch might +be able to retrieve objects before the start. The start Object MUST NOT +decrease and when it increases, there is no guarantee that a publisher will +not have already sent Objects before the new start Object. The end Group +MUST NOT increase and when it decreases, there is no guarantee that a publisher +will not have already sent Objects after the new end Object. A publisher SHOULD +close the Session as a 'Protocol Violation' if the SUBSCRIBE_UPDATE violates +either rule or if the subscriber specifies a Subscribe ID that has not existed +within the Session.¶
+There is no control message in response to a SUBSCRIBE_UPDATE, because it is +expected that it will always succeed and the worst outcome is that it is not +processed promptly and some extra objects from the existing subscription are +delivered.¶
+Unlike a new subscription, SUBSCRIBE_UPDATE can not cause an Object to be +delivered multiple times. Like SUBSCRIBE, EndGroup MUST specify the +same or a later object than StartGroup and StartObject.¶
+The format of SUBSCRIBE_UPDATE is as follows:¶
++SUBSCRIBE_UPDATE Message { + Type (i) = 0x2, + Length (i), + Subscribe ID (i), + StartGroup (i), + StartObject (i), + EndGroup (i), + Subscriber Priority (8), + Number of Parameters (i), + Subscribe Parameters (..) ... +} ++
Subscribe ID: The subscription identifier that is unique within the session. +This MUST match an existing Subscribe ID.¶
+StartGroup: The start Group ID.¶
+StartObject: The start Object ID.¶
+EndGroup: The end Group ID, plus 1. A value of 0 means the subscription is +open-ended.¶
+Subscriber Priority: Specifies the priority of a subscription relative to +other subscriptions in the same session. Lower numbers get higher priority. +See Section 5.¶
+Subscribe Parameters: The parameters are defined in Section 7.1.1.¶
+A subscriber issues a UNSUBSCRIBE
message to a publisher indicating it is no
+longer interested in receiving media for the specified track and requesting that
+the publisher stop sending Objects as soon as possible.¶
The format of UNSUBSCRIBE
is as follows:¶
+UNSUBSCRIBE Message { + Type (i) = 0xA, + Length (i), + Subscribe ID (i) +} ++
Subscribe ID: Subscription Identifier as defined in Section 7.4.¶
+A subscriber issues a FETCH to a publisher to request a range of already published +objects within a track. The publisher responding to a FETCH is responsible for retrieving +all available Objects. If there are gaps between Objects, the publisher omits them from the +fetch response. All omitted objects have status Object Does Not Exist.¶
+Fetch Types¶
+There are two types of Fetch messages:¶
+Standalone Fetch (0x1) : A Fetch of Objects performed independently of any Subscribe.¶
+Joining Fetch (0x2) : A Fetch joined together with a Subscribe by specifying +the Subscribe ID of an active subscription. A publisher receiving a +Joining Fetch uses properties of the associated Subscribe to determine the +Track Namespace, Track, StartGroup, StartObject, EndGroup, and EndObject such that +it is contiguous with the associated Subscribe. The Joining Fetch begins the +Preceding Group Offset prior to the associated subscription.¶
+A Subscriber can use a Joining Fetch to, for example, fill a playback buffer with a +certain number of groups prior to the live edge of a track.¶
+A Joining Fetch is only permitted when the associated Subscribe has the Filter +Type Latest Object.¶
+A Fetch Type other than 0x1 or 0x2 MUST be treated as an error.¶
+A publisher responds to a FETCH request with either a FETCH_OK or a FETCH_ERROR +message. If it responds with FETCH_OK, the publisher creates a new unidirectional +stream that is used to send the Objects. A relay MAY start sending objects immediately +in response to a FETCH, even if sending the FETCH_OK takes longer because it requires +going upstream to populate the latest object.¶
+The Object Forwarding Preference does not apply to fetches.¶
+Fetch specifies an inclusive range of Objects starting at StartObject +in StartGroup and ending at EndObject in EndGroup. EndGroup and EndObject MUST +specify the same or a later object than StartGroup and StartObject.¶
+The format of FETCH is as follows:¶
++FETCH Message { + Type (i) = 0x16, + Length (i), + Subscribe ID (i), + Subscriber Priority (8), + Group Order (8), + Fetch Type (i), + [Track Namespace (tuple), + Track Name Length (i), + Track Name (..), + StartGroup (i), + StartObject (i), + EndGroup (i), + EndObject (i),] + [Joining Subscribe ID (i), + Preceding Group Offset (i),] + Number of Parameters (i), + Parameters (..) ... +} ++
Fields common to all Fetch Types:¶
+Subscribe ID: The Subscribe ID identifies a given fetch request. Subscribe ID +is a variable length integer that MUST be unique and monotonically increasing +within a session.¶
+Subscriber Priority: Specifies the priority of a fetch request relative to +other subscriptions or fetches in the same session. Lower numbers get higher +priority. See Section 5.¶
+Group Order: Allows the subscriber to request Objects be delivered in +Ascending (0x1) or Descending (0x2) order by group. See Section 5. +A value of 0x0 indicates the original publisher's Group Order SHOULD be +used. Values larger than 0x2 are a protocol error.¶
+Fetch Type: Identifies the type of Fetch, whether joining or standalone.¶
+Parameters: The parameters are defined in Section 7.1.1.¶
+Fields present only for Standalone Fetch (0x1):¶
+Track Namespace: Identifies the namespace of the track as defined in +(Section 2.4.1).¶
+Track Name: Identifies the track name as defined in (Section 2.4.1).¶
+StartGroup: The start Group ID.¶
+StartObject: The start Object ID.¶
+EndGroup: The end Group ID.¶
+EndObject: The end Object ID, plus 1. A value of 0 means the entire group is +requested.¶
+Fields present only for Joining Fetch (0x2):¶
+Joining Subscribe ID: The Subscribe ID of the existing subscription to be +joined. If a publisher receives a Joining Fetch with a Subscribe ID that does +not correspond to an existing Subscribe, it MUST respond with a Fetch Error.¶
+Preceding Group Offset: The group offset for the Fetch prior and relative +to the Current Group of the corresponding Subscribe. A value of 0 indicates +the Fetch starts at the beginning of the Current Group.¶
+Objects that are not yet published will not be retrieved by a FETCH. +The latest available Object is indicated in the FETCH_OK, and is the last +Object a fetch will return if the EndGroup and EndObject have not yet been +published.¶
+A publisher MUST send fetched groups in the determined group order, either +ascending or descending. Within each group, objects are sent in Object ID order; +subgroup ID is not used for ordering.¶
+If StartGroup/StartObject is greater than the latest published Object group, +the publisher MUST return FETCH_ERROR with error code 'No Objects'.¶
+A publisher that receives a Fetch of type Type 0x2 treats it +as a Fetch with a range dynamically determined by the Preceding Group Offset +and field values derived from the corresponding subscription.¶
+The Largest Group ID and Largest Object ID values from the corresponding +subscription are used to calculate the end of a Joining Fetch so the Objects +retrieved by the FETCH and SUBSCRIBE are contiguous and non-overlapping. +If no Objects have been published for the track, and the SUBSCRIBE_OK has a +ContentExists value of 0, the publisher responds with a FETCH_ERROR with +error code 'No Objects'.¶
+The publisher receiving a Joining Fetch computes the range as follows:¶
+Fetch StartGroup: Subscribe Largest Group - Preceding Group Offset¶
+Fetch StartObject: 0¶
+Fetch EndGroup: Subscribe Largest Group¶
+Fetch EndObject: Subscribe Largest Object¶
+A Fetch EndObject of 0 requests the entire group, but Fetch will not +retrieve Objects that have not yet been published, so 1 is subtracted from +the Fetch EndGroup if Fetch EndObject is 0.¶
+A subscriber issues a FETCH_CANCEL
message to a publisher indicating it is no
+longer interested in receiving Objects for the fetch specified by 'Subscribe ID'.
+The publisher SHOULD close the unidirectional stream as soon as possible.¶
The format of FETCH_CANCEL
is as follows:¶
+FETCH_CANCEL Message { + Type (i) = 0x17, + Length (i), + Subscribe ID (i) +} ++
Subscribe ID: Subscription Identifier as defined in Section 7.7.¶
+The subscriber sends an ANNOUNCE_OK control message to acknowledge the +successful authorization and acceptance of an ANNOUNCE message.¶
++ANNOUNCE_OK Message +{ + Type (i) = 0x7, + Length (i), + Track Namespace (tuple), +} ++
Track Namespace: Identifies the track namespace in the ANNOUNCE +message for which this response is provided.¶
+The subscriber sends an ANNOUNCE_ERROR control message for tracks that +failed authorization.¶
++ANNOUNCE_ERROR Message +{ + Type (i) = 0x8, + Length (i), + Track Namespace (tuple), + Error Code (i), + Reason Phrase Length (i), + Reason Phrase (..), +} ++
Track Namespace: Identifies the track namespace in the ANNOUNCE +message for which this response is provided.¶
+Error Code: Identifies an integer error code for announcement failure.¶
+Reason Phrase: Provides the reason for announcement error.¶
+The application SHOULD use a relevant error code in ANNOUNCE_ERROR, as defined +below:¶
+Code | +Reason | +
---|---|
0x0 | +Internal Error | +
0x1 | +Unauthorized | +
0x2 | +Timeout | +
0x3 | +Not Supported | +
0x4 | +Uninterested | +
The subscriber sends an ANNOUNCE_CANCEL
control message to
+indicate it will stop sending new subscriptions for tracks
+within the provided Track Namespace.¶
+ANNOUNCE_CANCEL Message { + Type (i) = 0xC, + Length (i), + Track Namespace (tuple), + Error Code (i), + Reason Phrase Length (i), + Reason Phrase Length (..), +} ++
Track Namespace: Identifies a track's namespace as defined in +(Section 2.4.1).¶
+Error Code: Identifies an integer error code for canceling the announcement. +ANNOUNCE_CANCEL uses the same error codes as ANNOUNCE_ERROR +(Section 7.10).¶
+Reason Phrase: Provides the reason for announcement cancelation.¶
+A potential subscriber sends a 'TRACK_STATUS_REQUEST' message on the control +stream to obtain information about the current status of a given track.¶
+A TRACK_STATUS message MUST be sent in response to each TRACK_STATUS_REQUEST.¶
++TRACK_STATUS_REQUEST Message { + Type (i) = 0xD, + Length (i), + Track Namespace (tuple), + Track Name Length (i), + Track Name (..), +} ++
The subscriber sends the SUBSCRIBE_ANNOUNCES control message to a publisher +to request the current set of matching announcements, as well as future updates +to the set.¶
++SUBSCRIBE_ANNOUNCES Message { + Type (i) = 0x11, + Length (i), + Track Namespace Prefix (tuple), + Number of Parameters (i), + Parameters (..) ..., +} ++
Track Namespace Prefix: An ordered N-Tuple of byte fields which are matched +against track namespaces known to the publisher. For example, if the publisher +is a relay that has received ANNOUNCE messages for namespaces ("example.com", +"meeting=123", "participant=100") and ("example.com", "meeting=123", +"participant=200"), a SUBSCRIBE_ANNOUNCES for ("example.com", "meeting=123") +would match both. If an endpoint receives a Track Namespace Prefix tuple with +an N of 0 or more than 32, it MUST close the session with a Protocol +Violation.¶
+Parameters: The parameters are defined in Section 7.1.1.¶
+The publisher will respond with SUBSCRIBE_ANNOUNCES_OK or +SUBSCRIBE_ANNOUNCES_ERROR. If the SUBSCRIBE_ANNOUNCES is successful, +the publisher will forward any matching ANNOUNCE messages to the subscriber +that it has not yet sent. If the set of matching ANNOUNCE messages changes, the +publisher sends the corresponding ANNOUNCE or UNANNOUNCE message.¶
+A subscriber cannot make overlapping namespace subscriptions on a single +session. Within a session, if a publisher receives a SUBSCRIBE_ANNOUNCES +with a Track Namespace Prefix that is a prefix of an earlier +SUBSCRIBE_ANNOUNCES or vice versa, it MUST respond with +SUBSCRIBE_ANNOUNCES_ERROR, with error code SUBSCRIBE_ANNOUNCES_OVERLAP.¶
+The publisher MUST ensure the subscriber is authorized to perform this +namespace subscription.¶
+SUBSCRIBE_ANNOUNCES is not required for a publisher to send ANNOUNCE and +UNANNOUNCE messages to a subscriber. It is useful in applications or relays +where subscribers are only interested in or authorized to access a subset of +available announcements.¶
+A subscriber issues a UNSUBSCRIBE_ANNOUNCES
message to a publisher
+indicating it is no longer interested in ANNOUNCE and UNANNOUNCE messages for
+the specified track namespace prefix.¶
The format of UNSUBSCRIBE_ANNOUNCES
is as follows:¶
+UNSUBSCRIBE_ANNOUNCES Message { + Type (i) = 0x14, + Length (i), + Track Namespace Prefix (tuple) +} ++
Track Namespace Prefix: As defined in Section 7.13.¶
+A publisher sends a SUBSCRIBE_OK control message for successful +subscriptions.¶
++SUBSCRIBE_OK +{ + Type (i) = 0x4, + Length (i), + Subscribe ID (i), + Expires (i), + Group Order (8), + ContentExists (8), + [Largest Group ID (i)], + [Largest Object ID (i)], + Number of Parameters (i), + Subscribe Parameters (..) ... +} ++
Subscribe ID: Subscription Identifier as defined in Section 7.4.¶
+Expires: Time in milliseconds after which the subscription is no +longer valid. A value of 0 indicates that the subscription does not expire +or expires at an unknown time. Expires is advisory and a subscription can +end prior to the expiry time or last longer.¶
+Group Order: Indicates the subscription will be delivered in +Ascending (0x1) or Descending (0x2) order by group. See Section 5. +Values of 0x0 and those larger than 0x2 are a protocol error.¶
+ContentExists: 1 if an object has been published on this track, 0 if not. +If 0, then the Largest Group ID and Largest Object ID fields will not be +present. Any other value is a protocol error and MUST terminate the +session with a Protocol Violation (Section 3.5).¶
+Largest Group ID: The largest Group ID available for this track. This field +is only present if ContentExists has a value of 1.¶
+Largest Object ID: The largest Object ID available within the largest Group ID +for this track. This field is only present if ContentExists has a value of 1.¶
+Subscribe Parameters: The parameters are defined in Section 7.1.1.¶
+A publisher sends a SUBSCRIBE_ERROR control message in response to a +failed SUBSCRIBE.¶
++SUBSCRIBE_ERROR +{ + Type (i) = 0x5, + Length (i), + Subscribe ID (i), + Error Code (i), + Reason Phrase Length (i), + Reason Phrase (..), + Track Alias (i), +} ++
Subscribe ID: Subscription Identifier as defined in Section 7.4.¶
+Error Code: Identifies an integer error code for subscription failure.¶
+Reason Phrase: Provides the reason for subscription error.¶
+Track Alias: When Error Code is 'Retry Track Alias', the subscriber SHOULD re-issue the +SUBSCRIBE with this Track Alias instead. If this Track Alias is already in use, +the subscriber MUST close the connection with a Duplicate Track Alias error +(Section 3.5).¶
+The application SHOULD use a relevant error code in SUBSCRIBE_ERROR, +as defined below:¶
+Code | +Reason | +
---|---|
0x0 | +Internal Error | +
0x1 | +Unauthorized | +
0x2 | +Timeout | +
0x3 | +Not Supported | +
0x4 | +Track Does Not Exist | +
0x5 | +Invalid Range | +
0x6 | +Retry Track Alias | +
A publisher sends a FETCH_OK control message in response to successful fetches. +A publisher MAY send Objects in response to a FETCH before the FETCH_OK message is sent, +but the FETCH_OK MUST NOT be sent until the latest group and object are known.¶
++FETCH_OK +{ + Type (i) = 0x18, + Length (i), + Subscribe ID (i), + Group Order (8), + End Of Track (8), + Largest Group ID (i), + Largest Object ID (i), + Number of Parameters (i), + Subscribe Parameters (..) ... +} ++
Subscribe ID: Fetch Identifier as defined in Section 7.7.¶
+Group Order: Indicates the fetch will be delivered in +Ascending (0x1) or Descending (0x2) order by group. See Section 5. +Values of 0x0 and those larger than 0x2 are a protocol error.¶
+End Of Track: 1 if all objects have been published on this track, so +the Largest Group ID and Object Id indicate the last Object in the track, +0 if not.¶
+Largest Group ID: The largest Group ID available for this track.¶
+Largest Object ID: The largest Object ID available within the largest Group ID +for this track.¶
+Subscribe Parameters: The parameters are defined in Section 7.1.1.¶
+A publisher sends a FETCH_ERROR control message in response to a +failed FETCH.¶
++FETCH_ERROR +{ + Type (i) = 0x19, + Length (i), + Subscribe ID (i), + Error Code (i), + Reason Phrase Length (i), + Reason Phrase (..), +} ++
Subscribe ID: Subscription Identifier as defined in Section 7.4.¶
+Error Code: Identifies an integer error code for fetch failure.¶
+Reason Phrase: Provides the reason for fetch error.¶
+The application SHOULD use a relevant error code in FETCH_ERROR, +as defined below:¶
+Code | +Reason | +
---|---|
0x0 | +Internal Error | +
0x1 | +Unauthorized | +
0x2 | +Timeout | +
0x3 | +Not Supported | +
0x4 | +Track Does Not Exist | +
0x5 | +Invalid Range | +
A publisher sends a SUBSCRIBE_DONE
message to indicate it is done publishing
+Objects for that subscription. The Status Code indicates why the subscription
+ended, and whether it was an error. Because SUBSCRIBE_DONE is sent on the
+control stream, it is likely to arrive at the receiver before late-arriving
+objects, and often even late-opening streams. However, the receiver uses it
+as an indication that it should receive any late-opening streams in a relatively
+short time.¶
Note that some objects in the subscribed track might never be delivered, +because a stream was reset, or never opened in the first place, due to the +delivery timeout.¶
+A sender MUST NOT send SUBSCRIBE_DONE until it has closed all streams it will +ever open, and has no further datagrams to send, for a subscription. After +sending SUBSCRIBE_DONE, the sender can immediately destroy subscription state, +although stream state can persist until delivery completes. The sender might +persist subscription state to enforce the delivery timeout by resetting streams +on which it has already sent FIN, only deleting it when all such streams have +received ACK of the FIN.¶
+A sender MUST NOT destroy subscription state until it sends SUBSCRIBE_DONE, +though it can choose to stop sending objects (and thus send SUBSCRIBE_DONE) for +any reason.¶
+A subscriber that receives SUBSCRIBE_DONE SHOULD set a timer of at least its +delivery timeout in case some objects are still inbound due to prioritization +or packet loss. The subscriber MAY dispense with a timer if it sent UNSUBSCRIBE +or is otherwise no longer interested in objects from the track. Once the timer +has expired, the receiver destroys subscription state once all open streams for +the subscription have closed. A subscriber MAY discard subscription state +earlier, at the cost of potentially not delivering some late objects to the +application. The subscriber SHOULD send STOP_SENDING on all streams related to +the subscription when it deletes subscription state.¶
+The format of SUBSCRIBE_DONE
is as follows:¶
+SUBSCRIBE_DONE Message { + Type (i) = 0xB, + Length (i), + Subscribe ID (i), + Status Code (i), + Stream Count (i), + Reason Phrase Length (i), + Reason Phrase (..), +} ++
Subscribe ID: Subscription identifier as defined in Section 7.4.¶
+Status Code: An integer status code indicating why the subscription ended.¶
+Stream Count: An integer indicating the number of data streams the publisher +opened for this subscription. This helps the subscriber know if it has received +all of the data published in this subscription by comparing the number of +streams received. The subscriber can immediately remove all subscription state +once the same number of streams have been processed. If the track had +Forwarding Preference = Datagram, the publisher MUST set Stream Count to 0. If +the publisher is unable to set Stream Count to the exact number of streams +opened for the subscription, it MUST set Stream Count to 2^62 - 1. Subscribers +SHOULD use a timeout or other mechanism to remove subscription state in case +the publisher set an incorrect value, reset a stream before the SUBGROUP_HEADER, +or set the maximum value. If a subscriber receives more streams for a +subscription than specified in Stream Count, it MAY close the session with a +Protocol Violation.¶
+Reason Phrase: Provides the reason for subscription error.¶
+The application SHOULD use a relevant status code in +SUBSCRIBE_DONE, as defined below:¶
+Code | +Reason | +
---|---|
0x0 | +Internal Error | +
0x1 | +Unauthorized | +
0x2 | +Track Ended | +
0x3 | +Subscription Ended | +
0x4 | +Going Away | +
0x5 | +Expired | +
0x6 | +Too Far Behind | +
A publisher sends a MAX_SUBSCRIBE_ID message to increase the number of +subscriptions a subscriber can create within a session.¶
+The Maximum Subscribe Id MUST only increase within a session, and +receipt of a MAX_SUBSCRIBE_ID message with an equal or smaller Subscribe ID +value is a 'Protocol Violation'.¶
++MAX_SUBSCRIBE_ID +{ + Type (i) = 0x15, + Length (i), + Subscribe ID (i), +} ++
Subscribe ID: The new Maximum Subscribe ID for the session. If a Subscribe ID +Section 7.4 equal or larger than this is received by the publisher +that sent the MAX_SUBSCRIBE_ID, the publisher MUST close the session with an +error of 'Too Many Subscribes'.¶
+MAX_SUBSCRIBE_ID is similar to MAX_STREAMS in ([RFC9000], Section 4.6), +and similar considerations apply when deciding how often to send MAX_SUBSCRIBE_ID. +For example, implementations might choose to increase MAX_SUBSCRIBE_ID as +subscriptions close to keep the number of subscriptions available to subscribers +roughly consistent.¶
+The SUBSCRIBES_BLOCKED message is sent when a subscriber would like to begin +a new subscription, but cannot because the Subscribe ID would exceed the +Maximum Subscribe ID value sent by the peer. The subscriber SHOULD send only +one SUBSCRIBES_BLOCKED for a given Maximum Subscribe ID.¶
+A publisher MAY send a MAX_SUBSCRIBE_ID upon receipt of SUBSCRIBES_BLOCKED, +but it MUST NOT rely on SUBSCRIBES_BLOCKED to trigger sending a +MAX_SUBSCRIBE_ID, because sending SUBSCRIBES_BLOCKED is not required.¶
++SUBSCRIBES_BLOCKED +{ + Type (i) = 0x1A, + Length (i), + Maximum Subscribe ID (i), +} ++
Maximum Subscribe ID: The Maximum Subscribe ID for the session on which the subscriber +is blocked. More on Subscribe ID in Section 7.4.¶
+The publisher sends the ANNOUNCE control message to advertise where the +receiver can route SUBSCRIBEs for tracks within the announced +Track Namespace. The receiver verifies the publisher is authorized to +publish tracks under this namespace.¶
++ANNOUNCE Message { + Type (i) = 0x6, + Length (i), + Track Namespace (tuple), + Number of Parameters (i), + Parameters (..) ..., +} ++
Track Namespace: Identifies a track's namespace as defined in +(Section 2.4.1)¶
+Parameters: The parameters are defined in Section 7.1.1.¶
+The publisher sends the UNANNOUNCE
control message to indicate
+its intent to stop serving new subscriptions for tracks
+within the provided Track Namespace.¶
+UNANNOUNCE Message { + Type (i) = 0x9, + Length (i), + Track Namespace (tuple), +} ++
Track Namespace: Identifies a track's namespace as defined in +(Section 2.4.1).¶
+A publisher sends a 'TRACK_STATUS' message on the control stream in response +to a TRACK_STATUS_REQUEST message.¶
++TRACK_STATUS Message { + Type (i) = 0xE, + Length (i), + Track Namespace (tuple), + Track Name Length(i), + Track Name (..), + Status Code (i), + Last Group ID (i), + Last Object ID (i), +} ++
The 'Status Code' field provides additional information about the status of the +track. It MUST hold one of the following values. Any other value is a malformed +message.¶
+0x00: The track is in progress, and subsequent fields contain the highest group +and object ID for that track.¶
+0x01: The track does not exist. Subsequent fields MUST be zero, and any other +value is a malformed message.¶
+0x02: The track has not yet begun. Subsequent fields MUST be zero. Any other +value is a malformed message.¶
+0x03: The track has finished, so there is no "live edge." Subsequent fields +contain the highest Group and object ID known.¶
+0x04: The publisher is a relay that cannot obtain the current track status from +upstream. Subsequent fields contain the largest group and object ID known.¶
+Any other value in the Status Code field is a malformed message.¶
+When a relay is subscribed to a track, it can simply return the highest group +and object ID it has observed, whether or not that object was cached or +completely delivered. If not subscribed, a relay SHOULD send a +TRACK_STATUS_REQUEST upstream to obtain updated information.¶
+Alternatively, the relay MAY subscribe to the track to obtain the same +information.¶
+If a relay cannot or will not do either, it should return its best available +information with status code 0x04.¶
+The receiver of multiple TRACK_STATUS messages for a track uses the information +from the latest arriving message, as they are delivered in order on a single +stream.¶
+A publisher sends a SUBSCRIBE_ANNOUNCES_OK control message for successful +namespace subscriptions.¶
++SUBSCRIBE_ANNOUNCES_OK +{ + Type (i) = 0x12, + Length (i), + Track Namespace Prefix (tuple), +} ++
Track Namespace Prefix: As defined in Section 7.13.¶
+A publisher sends a SUBSCRIBE_ANNOUNCES_ERROR control message in response to +a failed SUBSCRIBE_ANNOUNCES.¶
++SUBSCRIBE_ANNOUNCES_ERROR +{ + Type (i) = 0x13, + Length (i), + Track Namespace Prefix (tuple), + Error Code (i), + Reason Phrase Length (i), + Reason Phrase (..), +} ++
Track Namespace Prefix: As defined in Section 7.13.¶
+Error Code: Identifies an integer error code for the namespace subscription +failure.¶
+Reason Phrase: Provides the reason for the namespace subscription error.¶
+The application SHOULD use a relevant error code in SUBSCRIBE_ANNOUNCES_ERROR, +as defined below:¶
+Code | +Reason | +
---|---|
0x0 | +Internal Error | +
0x1 | +Unauthorized | +
0x2 | +Timeout | +
0x3 | +Not Supported | +
0x4 | +Namespace Prefix Unknown | +
A publisher sends Objects matching a subscription on Data Streams.¶
+All unidirectional MOQT streams start with a variable-length integer indicating +the type of the stream in question.¶
+ID | +Type | +
---|---|
0x4 | +SUBGROUP_HEADER (Section 8.4.1) | +
0x5 | +FETCH_HEADER (Section 8.4.3) | +
All MOQT datagrams start with a variable-length integer indicating the type of +the datagram.¶
+ID | +Type | +
---|---|
0x1 | +OBJECT_DATAGRAM (Section 8.2) | +
0x2 | +OBJECT_DATAGRAM_STATUS (Section 8.2) | +
An endpoint that receives an unknown stream or datagram type MUST close the +session.¶
+The publisher only sends Objects after receiving a SUBSCRIBE or FETCH. The +publisher MUST NOT send Objects that are not requested. If an endpoint receives +an Object it never requested, it SHOULD terminate the session with a protocol +violation. Objects can arrive after a subscription or fetch has been cancelled, +so the session MUST NOT be teriminated in that case.¶
+Every Track has a single 'Object Forwarding Preference' and the Original +Publisher MUST NOT mix different forwarding preferences within a single track. +If a subscriber receives different forwarding preferences for a track, it +SHOULD close the session with an error of 'Protocol Violation'.¶
+An OBJECT message contains a range of contiguous bytes from from the +specified track, as well as associated metadata required to deliver, +cache, and forward it. Objects are sent by publishers.¶
+A canonical MoQ Object has the following information:¶
+Track Namespace and Track Name: The track this object belongs to.¶
+Group ID: The object is a member of the indicated group ID +Section 2.3 within the track.¶
+Object ID: The order of the object within the group. The +IDs starts at 0, increasing sequentially for each object within the +group.¶
+Publisher Priority: An 8 bit integer indicating the publisher's priority for +the Object Section 5.¶
+Object Forwarding Preference: An enumeration indicating how a publisher sends
+an object. The preferences are Subgroup and Datagram. An Object
+MUST be sent according to its Object Forwarding Preference
, described below.¶
Subgroup ID: The object is a member of the indicated subgroup ID (Section 2.2) +within the group. This field is omitted if the Object Forwarding Preference is +Track or Datagram.¶
+Object Status: As enumeration used to indicate missing +objects or mark the end of a group or track. See Section 8.1.1.1 below.¶
+Object Extension Length: The total length of the Object Extension Headers +block, in bytes.¶
+Object Extensions : A sequence of Object Extension Headers. See +Section 8.1.1.2 below.¶
+Object Payload: An opaque payload intended for an End Subscriber and SHOULD NOT be processed by a relay. Only present when 'Object Status' is Normal (0x0).¶
+The Object Status informs subscribers what objects will not be received +because they were never produced, are no longer available, or because they +are beyond the end of a group or track.¶
+Status
can have following values:¶
0x0 := Normal object. This status is implicit for any non-zero length object. + Zero-length objects explicitly encode the Normal status.¶
+0x1 := Indicates Object does not exist. Indicates that this object + does not exist at any publisher and it will not be published in + the future. This SHOULD be cached.¶
+0x3 := Indicates end of Group. ObjectId is one greater that the + largest object produced in the group identified by the + GroupID. This is sent right after the last object in the + group. If the ObjectID is 0, it indicates there are no Objects + in this Group. This SHOULD be cached. A publisher MAY use an end of + Group object to signal the end of all open Subgroups in a Group.¶
+0x4 := Indicates end of Track and Group. GroupID is the largest group produced + in this track and the ObjectId is one greater than the largest object + produced in that group. An object with this status that has a Group ID + less than any other Group ID, or an Object ID less than or equal to the + largest in the group, is a protocol error, and the receiver MUST + terminate the session. This SHOULD be cached.¶
+0x5 := Indicates end of Track. GroupID is one greater than the largest group + produced in this track and the ObjectId is zero. An object with this + status that has a Group ID less than or equal to any other Group ID, or + an Object ID other than zero, is a protocol error, and the receiver + MUST terminate the session. This SHOULD be cached.¶
+Any other value SHOULD be treated as a protocol error and terminate the +session with a Protocol Violation (Section 3.5). +Any object with a status code other than zero MUST have an empty payload.¶
+Though some status information could be inferred from QUIC stream state, +that information is not reliable and cacheable.¶
+Object Extension Headers are visible to relays and allow the transmission of +future metadata relevant to MOQT Object distribution. Any Object metadata never +accessed by the transport or relays SHOULD be serialized as part of the Object +payload and not as an extension header.¶
+Extension Headers are defined in external specifications and registered in an +IANA table Section 10. These specifications define the type and value of the +header, along with any rules concerning processing, modification, caching and +forwarding. A relay which is coded to implement these rules is said to +"support" the extension.¶
+If unsupported by the relay, Extension Headers MUST NOT be modified, MUST be +cached as part of the Object and MUST be forwarded by relays.¶
+If supported by the relay and subject to the processing rules specified in the +definition of the extension, Extension Headers MAY be modified, added, removed, +and/or cached by relays.¶
+Object Extension Headers are serialized as defined below:¶
++Extension Header { + Header Type (i), + [Header Value (i)] + [Header Length (i), + Header Value (..)] +} ++
Header type: an unsigned integer, encoded as a varint, identifying the type +of the extension and also the subsequent serialization.¶
+Header values: even types are followed by a single varint encoded value. Odd +types are followed by a varint encoded length and then the header value. +Header types are registered in the IANA table 'MOQ Extension Headers'. +See Section 10.¶
+An OBJECT_DATAGRAM
carries a single object in a datagram.¶
An Object received in an OBJECT_DATAGRAM
message has an Object
+Forwarding Preference
= Datagram
. To send an Object with Object
+Forwarding Preference
= Datagram
, determine the length of the header and
+payload and send the Object as datagram. In certain scenarios where the object
+size can be larger than maximum datagram size for the session, the Object
+will be dropped.¶
+OBJECT_DATAGRAM { + Track Alias (i), + Group ID (i), + Object ID (i), + Publisher Priority (8), + Extension Headers Length (i), + [Extension headers (...)], + Object Payload (..), +} ++
There is no explicit length field. The entirety of the transport datagram +following Publisher Priority contains the Object Payload.¶
+An OBJECT_DATAGRAM_STATUS
is similar to OBEJCT_DATAGRAM except it
+conveys an Object Status and has no payload.¶
+OBJECT_DATAGRAM_STATUS { + Track Alias (i), + Group ID (i), + Object ID (i), + Publisher Priority (8), + Extension Headers Length (i), + [Extension headers (...)], + Object Status (i), +} ++
When objects are sent on streams, the stream begins with a Subgroup Header +and is followed by one or more sets of serialized object fields. +If a stream ends gracefully in the middle of a serialized Object, the session +SHOULD be terminated with a Protocol Violation.¶
+A publisher SHOULD NOT open more than one stream at a time with the same Subgroup +Header field values.¶
+When a stream begins with SUBGROUP_HEADER
, all Objects on the stream
+belong to the track requested in the Subscribe message identified by Track Alias
+and the subgroup indicated by 'Group ID' and Subgroup ID
.¶
+SUBGROUP_HEADER { + Track Alias (i), + Group ID (i), + Subgroup ID (i), + Publisher Priority (8), +} ++
All Objects received on a stream opened with SUBGROUP_HEADER
have an
+Object Forwarding Preference
= Subgroup
.¶
To send an Object with Object Forwarding Preference
= Subgroup
, find the open
+stream that is associated with the subscription, Group ID
and Subgroup ID
,
+or open a new one and send the SUBGROUP_HEADER
. Then serialize the
+following fields.¶
The Object Status field is only sent if the Object Payload Length is zero.¶
++{ + Object ID (i), + Extension Headers Length (i), + [Extension headers (...)], + Object Payload Length (i), + [Object Status (i)], + Object Payload (..), +} ++
A publisher MUST NOT send an Object on a stream if its Object ID is less than a +previously sent Object ID within a given group in that stream.¶
+Subscribers will often need to know if they have received all objects in a +Subgroup, particularly if they serve as a relay or cache. QUIC and Webtransport +streams provide signals that can be used for this purpose. Closing Subgroups +promptly frees system resources and often unlocks flow control credit to open +more streams.¶
+If a sender has delivered all objects in a Subgroup to the QUIC stream, except +any objects before the beginning of a subscription, it MUST close the +stream with a FIN.¶
+If a sender closes the stream before delivering all such objects to the QUIC +stream, it MUST use a RESET_STREAM or RESET_STREAM_AT +[I-D.draft-ietf-quic-reliable-stream-reset] frame. This includes an open +Subgroup exceeding its Delivery Timeout, early termination of subscription due to +an UNSUBSCRIBE message, a publisher's decision to end the subscription early, or a +SUBSCRIBE_UPDATE moving the end of the subscription to before the current Group +or the start after the current Group. When RESET_STREAM_AT is used, the +reliable_size SHOULD include the stream header so the receiver can identify the +corresponding subscription and accurately account for reset data streams when +handling SUBSCRIBE_DONE (see Section 7.19). Publishers that reset +data streams without using RESET_STREAM_AT with an appropriate reliable_size can +cause subscribers to hold on to subscription state until a timeout expires.¶
+A sender might send all objects in a Subgroup and the FIN on a QUIC stream, +and then reset the stream. In this case, the receiving application would receive +the FIN if and only if all objects were received. If the application receives +all data on the stream and the FIN, it can ignore any RESET_STREAM it receives.¶
+If a sender will not deliver any objects from a Subgroup, it MAY send +a SUBGROUP_HEADER on a new stream, with no objects, and then send RESET_STREAM_AT +with a reliable_size equal to the length of the stream header. This explicitly +tells the receiver there is an unsent Subgroup.¶
+Since SUBSCRIBEs always end on a group boundary, an ending subscription can +always cleanly close all its subgroups. A sender that terminates a stream +early for any other reason (e.g., to handoff to a different sender) MUST +use RESET_STREAM or RESET_STREAM_AT. Senders SHOULD terminate a stream on +Group boundaries to avoid doing so.¶
+An MoQT implementation that processes a stream FIN is assured it has received +all objects in a subgroup from the start of the subscription. If a relay, it +can forward stream FINs to its own subscribers once those objects have been +sent. A relay MAY treat receipt of EndOfGroup, GroupDoesNotExist, or +EndOfTrack objects as a signal to close corresponding streams even if the FIN +has not arrived, as further objects on the stream would be a protocol violation.¶
+Similarly, an EndOfGroup message indicates the maximum Object ID in the +Group, so if all Objects in the Group have been received, a FIN can be sent on +any stream where the entire subgroup has been sent. This might be complex to +implement.¶
+Processing a RESET_STREAM or RESET_STREAM_AT means that there might be other +objects in the Subgroup beyond the last one received. A relay might immediately +reset the corresponding downstream stream, or it might attempt to recover the +missing Objects in an effort send all the objects in the subgroups and the FIN. It also +might send RESET_STREAM_AT with reliable_size set to the last object it has, so +as to reliably deliver the objects it has while signaling that other objects +might exist.¶
+A subscriber MAY send a QUIC STOP_SENDING frame for a subgroup stream if the Group +or Subgroup is no longer of interest to it. The publisher SHOULD respond with +RESET_STREAM or RESET_STREAM_AT. If RESET_STREAM_AT is sent, note that the receiver +has indicated no interest in the objects, so setting a reliable_size beyond the +stream header is of questionable utility.¶
+RESET_STREAM and STOP_SENDING on SUBSCRIBE data streams have no impact on other +Subgroups in the Group or the subscription, although applications might cancel all +Subgroups in a Group at once.¶
+When a stream begins with FETCH_HEADER
, all objects on the stream belong to the
+track requested in the Fetch message identified by Subscribe ID
.¶
+FETCH_HEADER { + Subscribe ID (i), +} ++
Each object sent on a fetch stream after the FETCH_HEADER has the following format:¶
++{ + Group ID (i), + Subgroup ID (i), + Object ID (i), + Publisher Priority (8), + Extension Headers Length (i), + [Extension headers (...)], + Object Payload Length (i), + [Object Status (i)], + Object Payload (..), +} ++
The Object Status field is only sent if the Object Payload Length is zero.¶
+The Subgroup ID field of an object with a Forwarding Preference of "Datagram" +(see Section 8.1.1) is set to the Object ID.¶
+Sending a subgroup on one stream:¶
++Stream = 2 + +SUBGROUP_HEADER { + Track Alias = 2 + Group ID = 0 + Subgroup ID = 0 + Publisher Priority = 0 +} +{ + Object ID = 0 + Extension Headers Length = 0 + Object Payload Length = 4 + Payload = "abcd" +} +{ + Object ID = 1 + Extension Headers Length = 0 + Object Payload Length = 4 + Payload = "efgh" +} +¶ +
Sending a group on one stream, with the first object containing two +Extension Headers.¶
++Stream = 2 + +STREAM_HEADER_GROUP { + Subscribe ID = 2 + Track Alias = 2 + Group ID = 0 + Publisher Priority = 0 +} +{ + Object ID = 0 + Extension Headers Length = 33 + { Type = 4 + Value = 2186796243 + }, + { Type = 77 + Length = 21 + Value = "traceID:123456" + } + Object Payload Length = 4 + Payload = "abcd" +} +{ + Object ID = 1 + Extension Headers Length = 0 + Object Payload Length = 4 + Payload = "efgh" +} + +¶ +
TODO: Expand this section, including subscriptions.¶
+Live content requires significant bandwidth and resources. Failure to +set limits will quickly cause resource exhaustion.¶
+MOQT uses stream limits and flow control to impose resource limits at +the network layer. Endpoints SHOULD set flow control limits based on the +anticipated bitrate.¶
+Endpoints MAY impose a MAX STREAM count limit which would restrict the +number of concurrent streams which a MOQT Streaming Format could have in +flight.¶
+The publisher prioritizes and transmits streams out of order. Streams +might be starved indefinitely during congestion. The publisher and +subscriber MUST cancel a stream, preferably the lowest priority, after +reaching a resource limit.¶
+TODO: fill out currently missing registries:¶
+MOQT version numbers¶
+Setup parameters¶
+Subscribe parameters¶
+Subscribe Error codes¶
+Subscribe Namespace Error codes¶
+Announce Error codes¶
+Announce Cancel Reason codes¶
+Message types¶
+MOQ Extension headers - we wish to reserve extension types 0-63 for +standards utilization where space is a premium, 64 - 16383 for +standards utilization where space is less of a concern, and 16384 and +above for first-come-first-served non-standardization usage.¶
+TODO: register the URI scheme and the ALPN and grease the Extension types¶
+moq-transport | +plain text | +same as main | +
moq-transport | +plain text | +diff with main | +