moqtap_codec/draft16/error_codes.rs
1//! Error and status code registries defined by MoQT draft-16.
2//!
3//! Each registry in Section 13.4 of the draft becomes one enum here. Variant names are
4//! the draft's ALLCAPS names in UpperCamelCase; every variant's doc comment repeats the
5//! draft spelling so the mapping stays checkable against the specification.
6//!
7//! `from_u64` returns `None` for a code this draft does not define. Peers legitimately
8//! send codes from other draft versions or from private extensions, so an unknown code
9//! is a decode result to handle, not a fault.
10
11/// Session termination error codes.
12///
13/// Sent in the session-level close. Assigned in Section 13.4.1 of draft-16; the code definitions
14/// are in Section 3.4.
15///
16/// Draft-16 assigns 0x0 through 0x9 and 0x10 through 0x1A. The gap at 0xA through 0xF is the
17/// draft's own; this registry reserves no greasing range.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19#[repr(u64)]
20pub enum SessionErrorCode {
21 /// `NO_ERROR` — The session is being terminated without an error.
22 NoError = 0x0,
23 /// `INTERNAL_ERROR` — An implementation specific error occurred.
24 InternalError = 0x1,
25 /// `UNAUTHORIZED` — The client is not authorized to establish a session.
26 Unauthorized = 0x2,
27 /// `PROTOCOL_VIOLATION` — The remote endpoint performed an action that was disallowed by the
28 /// specification.
29 ProtocolViolation = 0x3,
30 /// `INVALID_REQUEST_ID` — The session was closed because the endpoint used a Request ID that
31 /// was smaller than or equal to a previously received request ID, or the least-significant bit
32 /// of the request ID was incorrect for the endpoint.
33 InvalidRequestId = 0x4,
34 /// `DUPLICATE_TRACK_ALIAS` — The endpoint attempted to use a Track Alias that was already in
35 /// use.
36 DuplicateTrackAlias = 0x5,
37 /// `KEY_VALUE_FORMATTING_ERROR` — The key-value pair has a formatting error.
38 KeyValueFormattingError = 0x6,
39 /// `TOO_MANY_REQUESTS` — The session was closed because the endpoint used a Request ID equal to
40 /// or larger than the current Maximum Request ID.
41 TooManyRequests = 0x7,
42 /// `INVALID_PATH` — The PATH parameter was used by a server, on a WebTransport session, or the
43 /// server does not support the path.
44 InvalidPath = 0x8,
45 /// `MALFORMED_PATH` — The PATH parameter does not conform to the rules in Section 9.3.1.2.
46 MalformedPath = 0x9,
47 /// `GOAWAY_TIMEOUT` — The session was closed because the peer took too long to close the
48 /// session in response to a GOAWAY (Section 9.4) message. See session migration (Section 3.5).
49 GoawayTimeout = 0x10,
50 /// `CONTROL_MESSAGE_TIMEOUT` — The session was closed because the peer took too long to respond
51 /// to a control message.
52 ControlMessageTimeout = 0x11,
53 /// `DATA_STREAM_TIMEOUT` — The session was closed because the peer took too long to send data
54 /// expected on an open Data Stream (see Section 10). This includes fields of a stream header or
55 /// an object header within a data stream. If an endpoint times out waiting for a new object
56 /// header on an open subgroup stream, it MAY send a STOP_SENDING on that stream or terminate
57 /// the subscription.
58 DataStreamTimeout = 0x12,
59 /// `AUTH_TOKEN_CACHE_OVERFLOW` — The Session limit Section 9.3.1.4 of the size of all
60 /// registered Authorization tokens has been exceeded.
61 AuthTokenCacheOverflow = 0x13,
62 /// `DUPLICATE_AUTH_TOKEN_ALIAS` — Authorization Token attempted to register an Alias that was
63 /// in use (see Section 9.2.2.1).
64 DuplicateAuthTokenAlias = 0x14,
65 /// `VERSION_NEGOTIATION_FAILED` — The client didn't offer a version supported by the server.
66 VersionNegotiationFailed = 0x15,
67 /// `MALFORMED_AUTH_TOKEN` — Invalid Auth Token serialization during registration (see Section
68 /// 9.2.2.1).
69 MalformedAuthToken = 0x16,
70 /// `UNKNOWN_AUTH_TOKEN_ALIAS` — No registered token found for the provided Alias (see Section
71 /// 9.2.2.1).
72 UnknownAuthTokenAlias = 0x17,
73 /// `EXPIRED_AUTH_TOKEN` — Authorization token has expired (Section 9.2.2.1).
74 ExpiredAuthToken = 0x18,
75 /// `INVALID_AUTHORITY` — The specified AUTHORITY does not correspond to this server or cannot
76 /// be used in this context.
77 InvalidAuthority = 0x19,
78 /// `MALFORMED_AUTHORITY` — The AUTHORITY value is syntactically invalid.
79 MalformedAuthority = 0x1A,
80}
81
82/// Error codes carried in the REQUEST_ERROR control message.
83///
84/// REQUEST_ERROR answers any request (SUBSCRIBE, FETCH, PUBLISH, SUBSCRIBE_NAMESPACE,
85/// PUBLISH_NAMESPACE, TRACK_STATUS). Most codes mean the same thing for every request type, but a
86/// few are request-specific. Assigned in Section 13.4.2 of draft-16; the code definitions are in
87/// Section 9.8.
88///
89/// PUBLISH_NAMESPACE_CANCEL carries a code from this registry as well: Section 9.24 states it uses
90/// the same error codes as the REQUEST_ERROR that responds to PUBLISH_NAMESPACE.
91///
92/// Draft-16 assigns 0x0 through 0x5, 0x10 through 0x12, 0x19, 0x20, 0x30 and 0x32. The registry is
93/// sparse by design and reserves no greasing range.
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
95#[repr(u64)]
96pub enum RequestErrorCode {
97 /// `INTERNAL_ERROR` — An implementation specific or generic error occurred.
98 InternalError = 0x0,
99 /// `UNAUTHORIZED` — The subscriber is not authorized to perform the requested action on the
100 /// given track. This might be retryable if the authorization token is not yet valid.
101 Unauthorized = 0x1,
102 /// `TIMEOUT` — The subscription could not be completed before an implementation specific
103 /// timeout. For example, a relay could not establish an upstream subscription within the
104 /// timeout.
105 Timeout = 0x2,
106 /// `NOT_SUPPORTED` — The endpoint does not support the type of request.
107 NotSupported = 0x3,
108 /// `MALFORMED_AUTH_TOKEN` — Invalid Auth Token serialization during registration (see Section
109 /// 9.2.2.1).
110 MalformedAuthToken = 0x4,
111 /// `EXPIRED_AUTH_TOKEN` — Authorization token has expired (Section 9.2.2.1).
112 ExpiredAuthToken = 0x5,
113 /// `DOES_NOT_EXIST` — The track or namespace is not available at the publisher.
114 DoesNotExist = 0x10,
115 /// `INVALID_RANGE` — In response to SUBSCRIBE or FETCH, specified Filter or range of Locations
116 /// cannot be satisfied.
117 InvalidRange = 0x11,
118 /// `MALFORMED_TRACK` — In response to a FETCH, a relay publisher detected the track was
119 /// malformed (see Section 2.4.2).
120 MalformedTrack = 0x12,
121 /// `DUPLICATE_SUBSCRIPTION` — The PUBLISH or SUBSCRIBE request attempted to create a
122 /// subscription to a Track with the same role as an existing subscription.
123 DuplicateSubscription = 0x19,
124 /// `UNINTERESTED` — The subscriber is not interested in the track or namespace.
125 Uninterested = 0x20,
126 /// `PREFIX_OVERLAP` — In response to SUBSCRIBE_NAMESPACE, the namespace prefix overlaps with
127 /// another SUBSCRIBE_NAMESPACE in the same session.
128 PrefixOverlap = 0x30,
129 /// `INVALID_JOINING_REQUEST_ID` — In response to a Joining FETCH, the referenced Request ID is
130 /// not an Established Subscription.
131 InvalidJoiningRequestId = 0x32,
132}
133
134/// Status codes carried in the PUBLISH_DONE control message.
135///
136/// Indicates why a subscription ended, and whether ending it was an error. Assigned in Section
137/// 13.4.3 of draft-16; the code definitions are in Section 9.15.
138///
139/// Draft-16 assigns 0x0 through 0x6, 0x8 and 0x12. The hole at 0x7 is real and deliberate:
140/// draft-15 assigned 0x7 to MALFORMED_TRACK, and draft-16 moved that code to 0x12 without
141/// reassigning 0x7. Section 9.15 also lists MALFORMED_TRACK ahead of UPDATE_FAILED in its prose
142/// while the registry table lists both in numeric order; the two agree on names and values.
143#[derive(Debug, Clone, Copy, PartialEq, Eq)]
144#[repr(u64)]
145pub enum PublishDoneStatusCode {
146 /// `INTERNAL_ERROR` — An implementation specific or generic error occurred.
147 InternalError = 0x0,
148 /// `UNAUTHORIZED` — The subscriber is no longer authorized to subscribe to the given track.
149 Unauthorized = 0x1,
150 /// `TRACK_ENDED` — The track is no longer being published.
151 TrackEnded = 0x2,
152 /// `SUBSCRIPTION_ENDED` — The publisher reached the end of an associated subscription filter.
153 SubscriptionEnded = 0x3,
154 /// `GOING_AWAY` — The subscriber or publisher issued a GOAWAY message.
155 GoingAway = 0x4,
156 /// `EXPIRED` — The publisher reached the timeout specified in SUBSCRIBE_OK.
157 Expired = 0x5,
158 /// `TOO_FAR_BEHIND` — The publisher's queue of objects to be sent to the given subscriber
159 /// exceeds its implementation defined limit.
160 TooFarBehind = 0x6,
161 /// `UPDATE_FAILED` — REQUEST_UPDATE failed on this subscription (see Section 9.11).
162 UpdateFailed = 0x8,
163 /// `MALFORMED_TRACK` — A relay publisher detected that the track was malformed (see Section
164 /// 2.4.2).
165 MalformedTrack = 0x12,
166}
167
168/// Error codes carried in RESET_STREAM and RESET_STREAM_AT on a data stream.
169///
170/// Sent when a publisher closes a subgroup or fetch stream before delivering every object on it.
171/// Assigned in Section 13.4.4 of draft-16; the code definitions are in Section 10.4.3. These are
172/// application error codes carried on the stream, not session-level codes.
173///
174/// Draft-16 assigns 0x0 through 0x4 and 0x12, and reserves no greasing range.
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176#[repr(u64)]
177pub enum DataStreamResetErrorCode {
178 /// `INTERNAL_ERROR` — An implementation specific error.
179 InternalError = 0x0,
180 /// `CANCELLED` — The subscriber requested cancellation via UNSUBSCRIBE, FETCH_CANCEL or
181 /// STOP_SENDING, or the publisher ended the subscription, in which case PUBLISH_DONE (Section
182 /// 9.15) will have a more detailed status code.
183 Cancelled = 0x1,
184 /// `DELIVERY_TIMEOUT` — The DELIVERY TIMEOUT Section 9.2.2.2 was exceeded for this stream.
185 DeliveryTimeout = 0x2,
186 /// `SESSION_CLOSED` — The publisher session is being closed.
187 SessionClosed = 0x3,
188 /// `UNKNOWN_OBJECT_STATUS` — In response to a FETCH, the publisher is unable to determine the
189 /// Status of the next Object in the requested range.
190 UnknownObjectStatus = 0x4,
191 /// `MALFORMED_TRACK` — A relay publisher detected that the track was malformed (see Section
192 /// 2.4.2).
193 MalformedTrack = 0x12,
194}
195
196impl SessionErrorCode {
197 /// Every session termination code draft-16 assigns, in ascending wire order.
198 ///
199 /// This is the set [`Self::from_u64`] accepts, written out so that it can
200 /// be enumerated: nothing can iterate an enum's variants, so a caller that
201 /// wants the registry has to be handed it. Writing it down is also what
202 /// lets a test state its claims about the registry itself rather than about
203 /// the range some sweep happens to reach.
204 pub const ALL: &[SessionErrorCode] = &[
205 SessionErrorCode::NoError,
206 SessionErrorCode::InternalError,
207 SessionErrorCode::Unauthorized,
208 SessionErrorCode::ProtocolViolation,
209 SessionErrorCode::InvalidRequestId,
210 SessionErrorCode::DuplicateTrackAlias,
211 SessionErrorCode::KeyValueFormattingError,
212 SessionErrorCode::TooManyRequests,
213 SessionErrorCode::InvalidPath,
214 SessionErrorCode::MalformedPath,
215 SessionErrorCode::GoawayTimeout,
216 SessionErrorCode::ControlMessageTimeout,
217 SessionErrorCode::DataStreamTimeout,
218 SessionErrorCode::AuthTokenCacheOverflow,
219 SessionErrorCode::DuplicateAuthTokenAlias,
220 SessionErrorCode::VersionNegotiationFailed,
221 SessionErrorCode::MalformedAuthToken,
222 SessionErrorCode::UnknownAuthTokenAlias,
223 SessionErrorCode::ExpiredAuthToken,
224 SessionErrorCode::InvalidAuthority,
225 SessionErrorCode::MalformedAuthority,
226 ];
227
228 /// Convert a raw u64 to a `SessionErrorCode`, if this draft defines that code.
229 pub fn from_u64(v: u64) -> Option<Self> {
230 match v {
231 0x0 => Some(SessionErrorCode::NoError),
232 0x1 => Some(SessionErrorCode::InternalError),
233 0x2 => Some(SessionErrorCode::Unauthorized),
234 0x3 => Some(SessionErrorCode::ProtocolViolation),
235 0x4 => Some(SessionErrorCode::InvalidRequestId),
236 0x5 => Some(SessionErrorCode::DuplicateTrackAlias),
237 0x6 => Some(SessionErrorCode::KeyValueFormattingError),
238 0x7 => Some(SessionErrorCode::TooManyRequests),
239 0x8 => Some(SessionErrorCode::InvalidPath),
240 0x9 => Some(SessionErrorCode::MalformedPath),
241 0x10 => Some(SessionErrorCode::GoawayTimeout),
242 0x11 => Some(SessionErrorCode::ControlMessageTimeout),
243 0x12 => Some(SessionErrorCode::DataStreamTimeout),
244 0x13 => Some(SessionErrorCode::AuthTokenCacheOverflow),
245 0x14 => Some(SessionErrorCode::DuplicateAuthTokenAlias),
246 0x15 => Some(SessionErrorCode::VersionNegotiationFailed),
247 0x16 => Some(SessionErrorCode::MalformedAuthToken),
248 0x17 => Some(SessionErrorCode::UnknownAuthTokenAlias),
249 0x18 => Some(SessionErrorCode::ExpiredAuthToken),
250 0x19 => Some(SessionErrorCode::InvalidAuthority),
251 0x1A => Some(SessionErrorCode::MalformedAuthority),
252 _ => None,
253 }
254 }
255
256 /// Return the raw u64 value of this error code.
257 pub fn as_u64(self) -> u64 {
258 self as u64
259 }
260}
261
262impl RequestErrorCode {
263 /// Every REQUEST_ERROR code draft-16 assigns, in ascending wire order.
264 ///
265 /// This is the set [`Self::from_u64`] accepts, written out so that it can
266 /// be enumerated: nothing can iterate an enum's variants, so a caller that
267 /// wants the registry has to be handed it. Writing it down is also what
268 /// lets a test state its claims about the registry itself rather than about
269 /// the range some sweep happens to reach.
270 pub const ALL: &[RequestErrorCode] = &[
271 RequestErrorCode::InternalError,
272 RequestErrorCode::Unauthorized,
273 RequestErrorCode::Timeout,
274 RequestErrorCode::NotSupported,
275 RequestErrorCode::MalformedAuthToken,
276 RequestErrorCode::ExpiredAuthToken,
277 RequestErrorCode::DoesNotExist,
278 RequestErrorCode::InvalidRange,
279 RequestErrorCode::MalformedTrack,
280 RequestErrorCode::DuplicateSubscription,
281 RequestErrorCode::Uninterested,
282 RequestErrorCode::PrefixOverlap,
283 RequestErrorCode::InvalidJoiningRequestId,
284 ];
285
286 /// Convert a raw u64 to a `RequestErrorCode`, if this draft defines that code.
287 pub fn from_u64(v: u64) -> Option<Self> {
288 match v {
289 0x0 => Some(RequestErrorCode::InternalError),
290 0x1 => Some(RequestErrorCode::Unauthorized),
291 0x2 => Some(RequestErrorCode::Timeout),
292 0x3 => Some(RequestErrorCode::NotSupported),
293 0x4 => Some(RequestErrorCode::MalformedAuthToken),
294 0x5 => Some(RequestErrorCode::ExpiredAuthToken),
295 0x10 => Some(RequestErrorCode::DoesNotExist),
296 0x11 => Some(RequestErrorCode::InvalidRange),
297 0x12 => Some(RequestErrorCode::MalformedTrack),
298 0x19 => Some(RequestErrorCode::DuplicateSubscription),
299 0x20 => Some(RequestErrorCode::Uninterested),
300 0x30 => Some(RequestErrorCode::PrefixOverlap),
301 0x32 => Some(RequestErrorCode::InvalidJoiningRequestId),
302 _ => None,
303 }
304 }
305
306 /// Return the raw u64 value of this error code.
307 pub fn as_u64(self) -> u64 {
308 self as u64
309 }
310}
311
312impl PublishDoneStatusCode {
313 /// Every PUBLISH_DONE status code draft-16 assigns, in ascending wire order.
314 ///
315 /// This is the set [`Self::from_u64`] accepts, written out so that it can
316 /// be enumerated: nothing can iterate an enum's variants, so a caller that
317 /// wants the registry has to be handed it. Writing it down is also what
318 /// lets a test state its claims about the registry itself rather than about
319 /// the range some sweep happens to reach.
320 pub const ALL: &[PublishDoneStatusCode] = &[
321 PublishDoneStatusCode::InternalError,
322 PublishDoneStatusCode::Unauthorized,
323 PublishDoneStatusCode::TrackEnded,
324 PublishDoneStatusCode::SubscriptionEnded,
325 PublishDoneStatusCode::GoingAway,
326 PublishDoneStatusCode::Expired,
327 PublishDoneStatusCode::TooFarBehind,
328 PublishDoneStatusCode::UpdateFailed,
329 PublishDoneStatusCode::MalformedTrack,
330 ];
331
332 /// Convert a raw u64 to a `PublishDoneStatusCode`, if this draft defines that code.
333 pub fn from_u64(v: u64) -> Option<Self> {
334 match v {
335 0x0 => Some(PublishDoneStatusCode::InternalError),
336 0x1 => Some(PublishDoneStatusCode::Unauthorized),
337 0x2 => Some(PublishDoneStatusCode::TrackEnded),
338 0x3 => Some(PublishDoneStatusCode::SubscriptionEnded),
339 0x4 => Some(PublishDoneStatusCode::GoingAway),
340 0x5 => Some(PublishDoneStatusCode::Expired),
341 0x6 => Some(PublishDoneStatusCode::TooFarBehind),
342 0x8 => Some(PublishDoneStatusCode::UpdateFailed),
343 0x12 => Some(PublishDoneStatusCode::MalformedTrack),
344 _ => None,
345 }
346 }
347
348 /// Return the raw u64 value of this status code.
349 pub fn as_u64(self) -> u64 {
350 self as u64
351 }
352}
353
354impl DataStreamResetErrorCode {
355 /// Every data stream reset code draft-16 assigns, in ascending wire order.
356 ///
357 /// This is the set [`Self::from_u64`] accepts, written out so that it can
358 /// be enumerated: nothing can iterate an enum's variants, so a caller that
359 /// wants the registry has to be handed it. Writing it down is also what
360 /// lets a test state its claims about the registry itself rather than about
361 /// the range some sweep happens to reach.
362 pub const ALL: &[DataStreamResetErrorCode] = &[
363 DataStreamResetErrorCode::InternalError,
364 DataStreamResetErrorCode::Cancelled,
365 DataStreamResetErrorCode::DeliveryTimeout,
366 DataStreamResetErrorCode::SessionClosed,
367 DataStreamResetErrorCode::UnknownObjectStatus,
368 DataStreamResetErrorCode::MalformedTrack,
369 ];
370
371 /// Convert a raw u64 to a `DataStreamResetErrorCode`, if this draft defines that code.
372 pub fn from_u64(v: u64) -> Option<Self> {
373 match v {
374 0x0 => Some(DataStreamResetErrorCode::InternalError),
375 0x1 => Some(DataStreamResetErrorCode::Cancelled),
376 0x2 => Some(DataStreamResetErrorCode::DeliveryTimeout),
377 0x3 => Some(DataStreamResetErrorCode::SessionClosed),
378 0x4 => Some(DataStreamResetErrorCode::UnknownObjectStatus),
379 0x12 => Some(DataStreamResetErrorCode::MalformedTrack),
380 _ => None,
381 }
382 }
383
384 /// Return the raw u64 value of this error code.
385 pub fn as_u64(self) -> u64 {
386 self as u64
387 }
388}