§3.2.

Fetch

A FETCH requests pre-existing Objects from a Track between a Start Location and an End Location, inclusive. This range is specified by a Location Filter (see Section 3.3.1) when present, or defaults to {0, 0} and Largest Object (Section 3.1.4) respectively.

Objects with Locations larger than the Largest Object at the time the request is processed will not be retrieved by a FETCH. The actual end of the FETCH response is indicated in the FETCH_OK End Location (see Section 9.12). Because Largest Object can identify an Object that is still arriving (Section 3.1.4), a FETCH whose range includes Largest Object includes that Object in full; the publisher delivers the remainder as it becomes available.

The publisher MUST send exactly one FETCH_OK or FETCH_ERROR in response to a FETCH. The FETCH_OK or FETCH_ERROR can come at any time relative to object delivery. The 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 End Location is known.

If no Objects have been published for the track or Start Location is greater than the Largest Object (Section 3.1.4) the publisher MUST return FETCH_ERROR with error code INVALID_RANGE.

3.2.1. Fetch Object Delivery

The publisher creates a single unidirectional stream (see Section 11.4) that is used to send the Objects. If no Objects exist in the requested range, the publisher opens the unidirectional stream, sends the FETCH_HEADER (see Section 11.4.1) and closes the stream with a FIN.

A publisher MUST send fetched groups in the requested group order (see Section 9.20.8). Within each group, objects are sent in Object ID order; subgroup ID is not used for ordering. The Object Delivery Mode does not apply.

3.2.2. Gaps in a Fetch Stream

A gap in a fetch stream occurs when the publisher has no object for the next ordered Location. A gap can occur because the object does not exist, the object was filtered out by the subscriber, or the object state cannot be determined (e.g. a Relay has temporarily lost contact with the Original Publisher and does not have the Object in cache).

Unless the request included Range Filters (see Section 3.3.2), any gaps in the Group and Object IDs in the response stream that are not otherwise marked indicate objects that do not exist (see Section 2.1.2). When one or more Range Filters are present, unmarked gaps indicate objects in the unknown state.

For Ascending Group Order, and Descending Group Order where Start and End Location are in the same group, gaps include ranges between the Start Location and the first object in the stream; between objects in the stream; and between the last object in the stream and the End Location indicated in FETCH_OK.

For Descending Group Order where Start and End Location are in different groups, the first expected Object in the stream is {End Location.Group, 0} and the last expected Object in the stream is {Start Location.Group, 2^64-1}. When two consecutive objects A and B are in different groups, a gap represents multiple logical gaps: the tail of A.Group; all skipped groups; and {B.Group, 0} through B, exclusive.

Gaps at the end of a stream are only detectable when the stream is terminated by a FIN.

When the cause of the gap differs from the default, the publisher marks the range of Objects it will not serialize with an End of Range indicator (see Section 11.4.1.2), identifying those Objects as non-existent, unknown, or timed out. A publisher SHOULD NOT use End of Non-Existent Range in a FETCH response except to split a range of Objects that will not be serialized into those that are known not to exist and those with unknown or timed out status.

If a Publisher receives a FETCH with a range that includes one or more Objects with unknown state, it can choose to reset the FETCH data stream with UNKNOWN_OBJECT_STATUS (Section 12.5), or indicate the range of unknown Objects (End of Unknown Range, see Section 11.4.1.2) and continue serving other known Objects. When resetting the stream, the publisher can do so immediately or after previously sent objects are delivered. If it has not yet sent FETCH_OK, it can send FETCH_ERROR in addition to resetting the stream.

3.2.3. Relay Fetch Handling

A relay that has cached objects from the beginning of the range MAY start sending objects immediately in response to a FETCH. When a relay encounters Objects within the requested range that are not immediately available and have unknown status, it issues one or more upstream FETCHes to retrieve them.

If an upstream FETCH fails, the relay indicates the range of unknown Objects or resets the FETCH data stream, as described above.

The Fill Timeout (see Section 9.20.5) represents a total budget for all upstream FETCHes generated by a single request. If the budget is exhausted, the relay reports any remaining unavailable Objects as Timed-Out gaps (End of Timed-Out Range, see Section 11.4.1.2) and continues delivering available Objects in the range.

3.2.4. Fetch State Management

A subscriber keeps FETCH state until it cancels the request (see Section 6.4.2.3), receives FETCH_ERROR, or the FETCH data stream receives a FIN or is reset. If the data stream is already open, the subscriber wishing to cancel the FETCH MAY send STOP_SENDING for the data stream as well as the bidi request stream. It MUST send STOP_SENDING for the bidi request stream.

The Publisher can remove fetch state as soon as it has received a STOP_SENDING. It MUST reset the bidi request stream and unidirectional data stream associated with the FETCH. It can also remove state after closing the FETCH data stream.

It can remove all FETCH state after closing the data stream with a FIN.

A FETCH_ERROR indicates that both endpoints can immediately remove state. Since a relay can start delivering FETCH Objects from cache before determining the result of the request, some Objects could be received even if the FETCH results in error.

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