Skip to main content

moqtap_codec/draft13/
message.rs

1//! Draft-13 control message encoding and decoding.
2//!
3//! Key changes from draft-12:
4//! - `subscribe_announces` → `subscribe_namespace` (same IDs 0x11–0x14)
5//! - TrackStatusRequest (0x0D) → TrackStatus: subscribe-like request with
6//!   subscriber_priority, group_order, forward, filter_type
7//! - TrackStatus (0x0E) → TrackStatusOk: subscribe_ok-like response with
8//!   track_alias, expires, group_order, content_exists, largest_location
9//! - New TrackStatusError (0x0F): request_id + error_code + reason_phrase
10//! - Publish/PublishOk/PublishError (0x1D-0x1F) added
11
12use crate::auth_token::{AuthorizationToken, AUTH_TOKEN_PARAMETER};
13use crate::error::{
14    CodecError, MAX_FULL_TRACK_NAME_LENGTH, MAX_GOAWAY_URI_LENGTH, MAX_MESSAGE_LENGTH,
15    MAX_REASON_PHRASE_LENGTH,
16};
17use crate::kvp::{KeyValuePair, KvpValue};
18use crate::types::*;
19pub use crate::types::{check_group_range, check_location_range, check_open_ended_group_range};
20use crate::varint::VarInt;
21use bytes::{Buf, BufMut};
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24#[repr(u64)]
25pub enum MessageType {
26    SubscribeUpdate = 0x02,
27    Subscribe = 0x03,
28    SubscribeOk = 0x04,
29    SubscribeError = 0x05,
30    Announce = 0x06,
31    AnnounceOk = 0x07,
32    AnnounceError = 0x08,
33    Unannounce = 0x09,
34    Unsubscribe = 0x0A,
35    SubscribeDone = 0x0B,
36    AnnounceCancel = 0x0C,
37    TrackStatus = 0x0D,
38    TrackStatusOk = 0x0E,
39    TrackStatusError = 0x0F,
40    GoAway = 0x10,
41    SubscribeNamespace = 0x11,
42    SubscribeNamespaceOk = 0x12,
43    SubscribeNamespaceError = 0x13,
44    UnsubscribeNamespace = 0x14,
45    MaxRequestId = 0x15,
46    Fetch = 0x16,
47    FetchCancel = 0x17,
48    FetchOk = 0x18,
49    FetchError = 0x19,
50    RequestsBlocked = 0x1A,
51    Publish = 0x1D,
52    PublishOk = 0x1E,
53    PublishError = 0x1F,
54    ClientSetup = 0x20,
55    ServerSetup = 0x21,
56}
57
58impl MessageType {
59    pub fn from_id(id: u64) -> Option<Self> {
60        match id {
61            0x02 => Some(MessageType::SubscribeUpdate),
62            0x03 => Some(MessageType::Subscribe),
63            0x04 => Some(MessageType::SubscribeOk),
64            0x05 => Some(MessageType::SubscribeError),
65            0x06 => Some(MessageType::Announce),
66            0x07 => Some(MessageType::AnnounceOk),
67            0x08 => Some(MessageType::AnnounceError),
68            0x09 => Some(MessageType::Unannounce),
69            0x0A => Some(MessageType::Unsubscribe),
70            0x0B => Some(MessageType::SubscribeDone),
71            0x0C => Some(MessageType::AnnounceCancel),
72            0x0D => Some(MessageType::TrackStatus),
73            0x0E => Some(MessageType::TrackStatusOk),
74            0x0F => Some(MessageType::TrackStatusError),
75            0x10 => Some(MessageType::GoAway),
76            0x11 => Some(MessageType::SubscribeNamespace),
77            0x12 => Some(MessageType::SubscribeNamespaceOk),
78            0x13 => Some(MessageType::SubscribeNamespaceError),
79            0x14 => Some(MessageType::UnsubscribeNamespace),
80            0x15 => Some(MessageType::MaxRequestId),
81            0x16 => Some(MessageType::Fetch),
82            0x17 => Some(MessageType::FetchCancel),
83            0x18 => Some(MessageType::FetchOk),
84            0x19 => Some(MessageType::FetchError),
85            0x1A => Some(MessageType::RequestsBlocked),
86            0x1D => Some(MessageType::Publish),
87            0x1E => Some(MessageType::PublishOk),
88            0x1F => Some(MessageType::PublishError),
89            0x20 => Some(MessageType::ClientSetup),
90            0x21 => Some(MessageType::ServerSetup),
91            _ => None,
92        }
93    }
94
95    pub fn id(&self) -> u64 {
96        *self as u64
97    }
98}
99
100// ============================================================
101// Session Lifecycle Messages
102// ============================================================
103
104#[derive(Debug, Clone, PartialEq, Eq)]
105pub struct ClientSetup {
106    pub supported_versions: Vec<VarInt>,
107    pub parameters: Vec<KeyValuePair>,
108}
109
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct ServerSetup {
112    pub selected_version: VarInt,
113    pub parameters: Vec<KeyValuePair>,
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub struct GoAway {
118    pub new_session_uri: Vec<u8>,
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct MaxRequestId {
123    pub request_id: VarInt,
124}
125
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct RequestsBlocked {
128    pub maximum_request_id: VarInt,
129}
130
131// ============================================================
132// Subscribe Messages
133// ============================================================
134
135#[derive(Debug, Clone, PartialEq, Eq)]
136pub struct Subscribe {
137    pub request_id: VarInt,
138    pub track_namespace: TrackNamespace,
139    pub track_name: Vec<u8>,
140    pub subscriber_priority: u8,
141    pub group_order: GroupOrder,
142    pub forward: Forward,
143    pub filter_type: FilterType,
144    pub start_group: Option<VarInt>,
145    pub start_object: Option<VarInt>,
146    pub end_group: Option<VarInt>,
147    pub parameters: Vec<KeyValuePair>,
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub struct SubscribeOk {
152    pub request_id: VarInt,
153    pub track_alias: VarInt,
154    pub expires: VarInt,
155    pub group_order: GroupOrder,
156    pub content_exists: ContentExists,
157    pub largest_location: Option<Location>,
158    pub parameters: Vec<KeyValuePair>,
159}
160
161#[derive(Debug, Clone, PartialEq, Eq)]
162pub struct SubscribeError {
163    pub request_id: VarInt,
164    pub error_code: VarInt,
165    pub reason_phrase: Vec<u8>,
166}
167
168#[derive(Debug, Clone, PartialEq, Eq)]
169pub struct SubscribeUpdate {
170    pub request_id: VarInt,
171    pub start_group: VarInt,
172    pub start_object: VarInt,
173    pub end_group: VarInt,
174    pub subscriber_priority: u8,
175    pub forward: Forward,
176    pub parameters: Vec<KeyValuePair>,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq)]
180pub struct SubscribeDone {
181    pub request_id: VarInt,
182    pub status_code: VarInt,
183    pub stream_count: VarInt,
184    pub reason_phrase: Vec<u8>,
185}
186
187#[derive(Debug, Clone, PartialEq, Eq)]
188pub struct Unsubscribe {
189    pub request_id: VarInt,
190}
191
192// ============================================================
193// Announce Messages
194// ============================================================
195
196#[derive(Debug, Clone, PartialEq, Eq)]
197pub struct Announce {
198    pub request_id: VarInt,
199    pub track_namespace: TrackNamespace,
200    pub parameters: Vec<KeyValuePair>,
201}
202
203#[derive(Debug, Clone, PartialEq, Eq)]
204pub struct AnnounceOk {
205    pub request_id: VarInt,
206}
207
208#[derive(Debug, Clone, PartialEq, Eq)]
209pub struct AnnounceError {
210    pub request_id: VarInt,
211    pub error_code: VarInt,
212    pub reason_phrase: Vec<u8>,
213}
214
215#[derive(Debug, Clone, PartialEq, Eq)]
216pub struct AnnounceCancel {
217    pub track_namespace: TrackNamespace,
218    pub error_code: VarInt,
219    pub reason_phrase: Vec<u8>,
220}
221
222#[derive(Debug, Clone, PartialEq, Eq)]
223pub struct Unannounce {
224    pub track_namespace: TrackNamespace,
225}
226
227// ============================================================
228// Subscribe Namespace Messages (renamed from Subscribe Announces)
229// ============================================================
230
231#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct SubscribeNamespace {
233    pub request_id: VarInt,
234    pub track_namespace_prefix: TrackNamespace,
235    pub parameters: Vec<KeyValuePair>,
236}
237
238#[derive(Debug, Clone, PartialEq, Eq)]
239pub struct SubscribeNamespaceOk {
240    pub request_id: VarInt,
241}
242
243#[derive(Debug, Clone, PartialEq, Eq)]
244pub struct SubscribeNamespaceError {
245    pub request_id: VarInt,
246    pub error_code: VarInt,
247    pub reason_phrase: Vec<u8>,
248}
249
250#[derive(Debug, Clone, PartialEq, Eq)]
251pub struct UnsubscribeNamespace {
252    pub track_namespace_prefix: TrackNamespace,
253}
254
255// ============================================================
256// Track Status Messages (restructured from draft-12)
257// ============================================================
258
259/// TRACK_STATUS message (type 0x0D). Draft-13: subscribe-like request.
260///
261/// "The TRACK_STATUS message format is identical to the SUBSCRIBE message", so
262/// the fields below are the SUBSCRIBE fields and nothing else — including the
263/// two that only some filters put on the wire. Draft-12 had no such message and
264/// draft-13's changelog records the change, which is why this shape does not
265/// look like the draft-12 TRACK_STATUS_REQUEST it replaced.
266#[derive(Debug, Clone, PartialEq, Eq)]
267pub struct TrackStatus {
268    pub request_id: VarInt,
269    pub track_namespace: TrackNamespace,
270    pub track_name: Vec<u8>,
271    pub subscriber_priority: u8,
272    pub group_order: GroupOrder,
273    pub forward: Forward,
274    pub filter_type: FilterType,
275    /// Present only for the AbsoluteStart and AbsoluteRange filter types.
276    pub start_group: Option<VarInt>,
277    /// Present only for the AbsoluteStart and AbsoluteRange filter types.
278    pub start_object: Option<VarInt>,
279    /// Present only for the AbsoluteRange filter type.
280    pub end_group: Option<VarInt>,
281    pub parameters: Vec<KeyValuePair>,
282}
283
284/// TRACK_STATUS_OK message (type 0x0E). Draft-13: subscribe_ok-like response.
285#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct TrackStatusOk {
287    pub request_id: VarInt,
288    pub track_alias: VarInt,
289    pub expires: VarInt,
290    pub group_order: GroupOrder,
291    pub content_exists: ContentExists,
292    pub largest_location: Option<Location>,
293    pub parameters: Vec<KeyValuePair>,
294}
295
296/// TRACK_STATUS_ERROR message (type 0x0F). New in draft-13.
297#[derive(Debug, Clone, PartialEq, Eq)]
298pub struct TrackStatusError {
299    pub request_id: VarInt,
300    pub error_code: VarInt,
301    pub reason_phrase: Vec<u8>,
302}
303
304// ============================================================
305// Fetch Messages
306// ============================================================
307
308#[derive(Debug, Clone, Copy, PartialEq, Eq)]
309#[repr(u64)]
310pub enum FetchType {
311    Standalone = 1,
312    RelativeJoining = 2,
313    AbsoluteJoining = 3,
314}
315
316impl FetchType {
317    pub fn from_u64(v: u64) -> Option<Self> {
318        match v {
319            1 => Some(FetchType::Standalone),
320            2 => Some(FetchType::RelativeJoining),
321            3 => Some(FetchType::AbsoluteJoining),
322            _ => None,
323        }
324    }
325}
326
327#[derive(Debug, Clone, PartialEq, Eq)]
328pub struct Fetch {
329    pub request_id: VarInt,
330    pub subscriber_priority: u8,
331    pub group_order: GroupOrder,
332    pub fetch_type: FetchType,
333    pub fetch_payload: FetchPayload,
334    pub parameters: Vec<KeyValuePair>,
335}
336
337#[derive(Debug, Clone, PartialEq, Eq)]
338pub enum FetchPayload {
339    Standalone {
340        track_namespace: TrackNamespace,
341        track_name: Vec<u8>,
342        start_group: VarInt,
343        start_object: VarInt,
344        end_group: VarInt,
345        end_object: VarInt,
346    },
347    Joining {
348        /// The Request ID of the subscription this fetch joins.
349        ///
350        /// Section 8.16 names the field Joining Request ID. Draft-11 spelled
351        /// the same field Joining Subscribe ID, and the two words are not
352        /// interchangeable here: a Request ID is drawn from the one space
353        /// every request shares, so the value identifies a request that
354        /// happens to be a subscription rather than a subscription in a
355        /// space of its own.
356        joining_request_id: VarInt,
357        /// The joining start: an offset for a relative fetch, a group for an
358        /// absolute one.
359        joining_start: VarInt,
360    },
361}
362
363#[derive(Debug, Clone, PartialEq, Eq)]
364pub struct FetchOk {
365    pub request_id: VarInt,
366    pub group_order: GroupOrder,
367    /// End-of-track flag, a single byte.
368    ///
369    /// Held as a raw byte rather than an enum: the draft describes 1 and 0 and
370    /// says nothing about any other value, where it does call an out-of-range
371    /// Group Order, Forward or Content Exists a protocol error. Refusing a 2
372    /// here would be this codec's rule and not the draft's.
373    pub end_of_track: u8,
374    pub end_location: Location,
375    pub parameters: Vec<KeyValuePair>,
376}
377
378#[derive(Debug, Clone, PartialEq, Eq)]
379pub struct FetchError {
380    pub request_id: VarInt,
381    pub error_code: VarInt,
382    pub reason_phrase: Vec<u8>,
383}
384
385#[derive(Debug, Clone, PartialEq, Eq)]
386pub struct FetchCancel {
387    pub request_id: VarInt,
388}
389
390// ============================================================
391// Publish Messages
392// ============================================================
393
394#[derive(Debug, Clone, PartialEq, Eq)]
395pub struct Publish {
396    pub request_id: VarInt,
397    pub track_namespace: TrackNamespace,
398    pub track_name: Vec<u8>,
399    pub track_alias: VarInt,
400    pub group_order: GroupOrder,
401    pub content_exists: ContentExists,
402    pub largest_location: Option<Location>,
403    pub forward: Forward,
404    pub parameters: Vec<KeyValuePair>,
405}
406
407#[derive(Debug, Clone, PartialEq, Eq)]
408pub struct PublishOk {
409    pub request_id: VarInt,
410    pub forward: Forward,
411    pub subscriber_priority: u8,
412    pub group_order: GroupOrder,
413    pub filter_type: FilterType,
414    pub start_group: Option<VarInt>,
415    pub start_object: Option<VarInt>,
416    pub end_group: Option<VarInt>,
417    pub parameters: Vec<KeyValuePair>,
418}
419
420#[derive(Debug, Clone, PartialEq, Eq)]
421pub struct PublishError {
422    pub request_id: VarInt,
423    pub error_code: VarInt,
424    pub reason_phrase: Vec<u8>,
425}
426
427// ============================================================
428// Unified Message Enum
429// ============================================================
430
431#[derive(Debug, Clone, PartialEq, Eq)]
432pub enum ControlMessage {
433    ClientSetup(ClientSetup),
434    ServerSetup(ServerSetup),
435    GoAway(GoAway),
436    MaxRequestId(MaxRequestId),
437    RequestsBlocked(RequestsBlocked),
438    Subscribe(Subscribe),
439    SubscribeOk(SubscribeOk),
440    SubscribeError(SubscribeError),
441    SubscribeUpdate(SubscribeUpdate),
442    SubscribeDone(SubscribeDone),
443    Unsubscribe(Unsubscribe),
444    Announce(Announce),
445    AnnounceOk(AnnounceOk),
446    AnnounceError(AnnounceError),
447    AnnounceCancel(AnnounceCancel),
448    Unannounce(Unannounce),
449    SubscribeNamespace(SubscribeNamespace),
450    SubscribeNamespaceOk(SubscribeNamespaceOk),
451    SubscribeNamespaceError(SubscribeNamespaceError),
452    UnsubscribeNamespace(UnsubscribeNamespace),
453    TrackStatus(TrackStatus),
454    TrackStatusOk(TrackStatusOk),
455    TrackStatusError(TrackStatusError),
456    Fetch(Fetch),
457    FetchOk(FetchOk),
458    FetchError(FetchError),
459    FetchCancel(FetchCancel),
460    Publish(Publish),
461    PublishOk(PublishOk),
462    PublishError(PublishError),
463}
464
465fn check_full_track_name(namespace: &TrackNamespace, track_name: &[u8]) -> Result<(), CodecError> {
466    let total = namespace.field_bytes_len().saturating_add(track_name.len());
467    if total > MAX_FULL_TRACK_NAME_LENGTH {
468        return Err(CodecError::TrackNameTooLong);
469    }
470    Ok(())
471}
472
473/// Read a Reason Phrase, holding it to the cap this draft states for a receiver.
474///
475/// "The reason phrase length has a maximum length of 1024 bytes. If an endpoint
476/// receives a length exceeding the maximum, it MUST close the session with a
477/// Protocol Violation". The sentence is about what an endpoint receives, and
478/// receiving was the direction the cap was not applied to: the encoders refused
479/// an over-long phrase and the decoders accepted one.
480fn read_reason_phrase(buf: &mut impl Buf) -> Result<Vec<u8>, CodecError> {
481    let len = VarInt::decode(buf)?.into_inner() as usize;
482    if len > MAX_REASON_PHRASE_LENGTH {
483        return Err(CodecError::ReasonPhraseTooLong);
484    }
485    read_bytes(buf, len)
486}
487
488/// Take one byte, or report the end of the buffer instead of panicking.
489fn read_u8(buf: &mut impl Buf) -> Result<u8, CodecError> {
490    if !buf.has_remaining() {
491        return Err(CodecError::UnexpectedEnd);
492    }
493    Ok(buf.get_u8())
494}
495
496/// Read a Group Order from a message that lets the publisher choose.
497///
498/// Every figure draws this field as a single byte, and the values are 0x1
499/// Ascending, 0x2 Descending, and 0x0 for "the original publisher's Group Order
500/// SHOULD be used". "Values larger than 0x2 are a protocol error."
501///
502/// Reading it as a varint instead is invisible for all three legal values —
503/// each is a single byte below 64, where the two encodings coincide — and
504/// diverges on everything a peer may send that is not legal. A two-byte varint
505/// holding 1 passes as Ascending and shifts every field after it, while the
506/// declared message length still adds up.
507fn read_group_order(buf: &mut impl Buf) -> Result<GroupOrder, CodecError> {
508    GroupOrder::from_u8(read_u8(buf)?).ok_or(CodecError::InvalidField)
509}
510
511/// Read a Group Order from a message that must name a real order.
512///
513/// SUBSCRIBE_OK, PUBLISH, PUBLISH_OK and FETCH_OK, and TRACK_STATUS_OK,
514/// whose format "is identical to the SUBSCRIBE_OK message" each say
515/// "Values of 0x0 and those larger than 0x2 are a protocol error": a responder
516/// reports the order it settled on, so deferring to the publisher is not an
517/// answer it can give. SUBSCRIBE, TRACK_STATUS and FETCH are the requests, and there
518/// 0x0 is exactly how a subscriber says it has no preference — "the original
519/// publisher's Group Order SHOULD be used". The two readers cannot be merged
520/// without either refusing traffic the requests permit or accepting a reply
521/// that tells the subscriber nothing.
522fn read_group_order_response(buf: &mut impl Buf) -> Result<GroupOrder, CodecError> {
523    match read_group_order(buf)? {
524        GroupOrder::Publisher => Err(CodecError::InvalidField),
525        order => Ok(order),
526    }
527}
528
529/// Read a Forward flag: "Any other value is a protocol error and MUST terminate
530/// the session with a Protocol Violation"
531fn read_forward(buf: &mut impl Buf) -> Result<Forward, CodecError> {
532    match read_u8(buf)? {
533        0 => Ok(Forward::DontForward),
534        1 => Ok(Forward::Forward),
535        other => Err(CodecError::InvalidForward(other)),
536    }
537}
538
539/// Read a Content Exists flag, which carries the same sentence as Forward and
540/// also decides whether a Largest Location follows.
541fn read_content_exists(buf: &mut impl Buf) -> Result<ContentExists, CodecError> {
542    match read_u8(buf)? {
543        0 => Ok(ContentExists::NoLargestLocation),
544        1 => Ok(ContentExists::HasLargestLocation),
545        other => Err(CodecError::InvalidContentExists(other)),
546    }
547}
548
549/// Read a Filter Type.
550///
551/// Unlike the fields above this one really is `(i)`, so the varint reader is
552/// right here. "A filter type other than the above MUST be treated as error."
553///
554/// An error and not a close: this draft names no code and no session
555/// consequence, where draft-14 Section 9.7 answers the same value with "MUST be
556/// close the session with PROTOCOL_VIOLATION". The message is refused either
557/// way; only draft-14's refusal reaches the session.
558fn read_filter_type(buf: &mut impl Buf) -> Result<FilterType, CodecError> {
559    let value = VarInt::decode(buf)?.into_inner();
560    FilterType::from_u64(value).ok_or(CodecError::InvalidFilterType(value))
561}
562
563/// Read the Start Location the filter says is there, as its two halves.
564///
565/// "Only present for 'AbsoluteStart' and 'AbsoluteRange' filter types."
566type StartLocation = (Option<VarInt>, Option<VarInt>);
567fn read_start_location(
568    filter_type: FilterType,
569    buf: &mut impl Buf,
570) -> Result<StartLocation, CodecError> {
571    match filter_type {
572        FilterType::AbsoluteStart | FilterType::AbsoluteRange => {
573            Ok((Some(VarInt::decode(buf)?), Some(VarInt::decode(buf)?)))
574        }
575        _ => Ok((None, None)),
576    }
577}
578
579/// Read the End Group the filter says is there.
580///
581/// "Only present for the 'AbsoluteRange' filter type."
582fn read_end_group(
583    filter_type: FilterType,
584    buf: &mut impl Buf,
585) -> Result<Option<VarInt>, CodecError> {
586    match filter_type {
587        FilterType::AbsoluteRange => Ok(Some(VarInt::decode(buf)?)),
588        _ => Ok(None),
589    }
590}
591
592/// Read the Largest Location that Content Exists says is there.
593///
594/// "This field is only present if Content Exists has a value of 1."
595fn read_largest_location(
596    content_exists: ContentExists,
597    buf: &mut impl Buf,
598) -> Result<Option<Location>, CodecError> {
599    match content_exists {
600        ContentExists::HasLargestLocation => Ok(Some(Location::decode(buf)?)),
601        ContentExists::NoLargestLocation => Ok(None),
602    }
603}
604
605/// Refuse a Group Order of 0x0 on the messages that forbid it.
606///
607/// The decoders refuse it on the way in; without this the codec would still
608/// write a frame its own reader rejects.
609fn check_group_order(message: &ControlMessage) -> Result<(), CodecError> {
610    let order = match message {
611        ControlMessage::SubscribeOk(m) => m.group_order,
612        ControlMessage::TrackStatusOk(m) => m.group_order,
613        ControlMessage::FetchOk(m) => m.group_order,
614        ControlMessage::Publish(m) => m.group_order,
615        ControlMessage::PublishOk(m) => m.group_order,
616        _ => return Ok(()),
617    };
618    if order == GroupOrder::Publisher {
619        return Err(CodecError::InvalidField);
620    }
621    Ok(())
622}
623
624/// Refuse a message whose discriminator disagrees with the fields beside it.
625///
626/// Several draft-13 messages carry a field that says which of the fields after
627/// it are on the wire — SUBSCRIBE's and PUBLISH_OK's Filter Type, SUBSCRIBE_OK's
628/// and PUBLISH's Content Exists, FETCH's Fetch Type. This codec holds the
629/// optional halves in `Option`s and an enum, so a value can say one thing in its
630/// discriminator and another in its body, and the two sides resolve that
631/// differently: the encoder writes whatever the body holds, the decoder reads
632/// whatever the discriminator announces.
633///
634/// The result is a message that does not survive its own round trip. A
635/// SUBSCRIBE_OK saying content exists with no location encodes to a frame whose
636/// own reader takes the parameter count for a Group ID. Refusing at the encoder
637/// keeps the two readings from diverging on the wire.
638///
639/// TRACK_STATUS is here because its format is the SUBSCRIBE format, so its
640/// Filter Type governs the same two optional fields.
641fn check_discriminators(message: &ControlMessage) -> Result<(), CodecError> {
642    /// Both halves of a Start Location are present together or not at all, and
643    /// only the two absolute filters put one on the wire.
644    fn check_filter(
645        filter_type: FilterType,
646        start_group: &Option<VarInt>,
647        start_object: &Option<VarInt>,
648        end_group: &Option<VarInt>,
649    ) -> Result<(), CodecError> {
650        let wants_start =
651            matches!(filter_type, FilterType::AbsoluteStart | FilterType::AbsoluteRange);
652        if wants_start != start_group.is_some() || wants_start != start_object.is_some() {
653            return Err(CodecError::InvalidField);
654        }
655        if (filter_type == FilterType::AbsoluteRange) != end_group.is_some() {
656            return Err(CodecError::InvalidField);
657        }
658        Ok(())
659    }
660
661    fn check_content(
662        content_exists: ContentExists,
663        largest_location: &Option<Location>,
664    ) -> Result<(), CodecError> {
665        if (content_exists == ContentExists::HasLargestLocation) != largest_location.is_some() {
666            return Err(CodecError::InvalidField);
667        }
668        Ok(())
669    }
670
671    match message {
672        ControlMessage::Subscribe(m) => {
673            check_filter(m.filter_type, &m.start_group, &m.start_object, &m.end_group)
674        }
675        ControlMessage::TrackStatus(m) => {
676            check_filter(m.filter_type, &m.start_group, &m.start_object, &m.end_group)
677        }
678        ControlMessage::PublishOk(m) => {
679            check_filter(m.filter_type, &m.start_group, &m.start_object, &m.end_group)
680        }
681        ControlMessage::SubscribeOk(m) => check_content(m.content_exists, &m.largest_location),
682        ControlMessage::TrackStatusOk(m) => check_content(m.content_exists, &m.largest_location),
683        ControlMessage::Publish(m) => check_content(m.content_exists, &m.largest_location),
684        ControlMessage::Fetch(m) => {
685            let body_is_standalone = matches!(m.fetch_payload, FetchPayload::Standalone { .. });
686            if body_is_standalone != (m.fetch_type == FetchType::Standalone) {
687                return Err(CodecError::InvalidField);
688            }
689            Ok(())
690        }
691        _ => Ok(()),
692    }
693}
694
695/// Refuse a request whose range ends before it starts.
696///
697/// SUBSCRIBE's AbsoluteRange filter (Section 8.7), SUBSCRIBE_UPDATE
698/// (Section 8.10) and FETCH (Section 8.16) each state it, and the fields
699/// are not spelled the same way in the three places: an End Group is inclusive
700/// on SUBSCRIBE and FETCH and is the last group plus one on SUBSCRIBE_UPDATE,
701/// where zero means open ended, and an End Object is the last object plus one
702/// with zero meaning the whole group. The helpers this calls carry those
703/// conventions, one per shape.
704///
705/// Applied on both sides. A range that ends before it starts selects nothing,
706/// and the peer's only recourse is an error response or a session close, so
707/// writing one is not a way to ask for anything.
708fn check_ranges(message: &ControlMessage) -> Result<(), CodecError> {
709    match message {
710        ControlMessage::Subscribe(m) => match (&m.start_group, &m.end_group) {
711            (Some(start_group), Some(end_group)) => {
712                check_group_range(start_group.into_inner(), end_group.into_inner())
713            }
714            _ => Ok(()),
715        },
716        ControlMessage::SubscribeUpdate(m) => {
717            check_open_ended_group_range(m.start_group.into_inner(), m.end_group.into_inner())
718        }
719        ControlMessage::Fetch(m) => match &m.fetch_payload {
720            FetchPayload::Standalone {
721                start_group, start_object, end_group, end_object, ..
722            } => check_location_range(
723                start_group.into_inner(),
724                start_object.into_inner(),
725                end_group.into_inner(),
726                end_object.into_inner(),
727            ),
728            FetchPayload::Joining { .. } => Ok(()),
729        },
730        _ => Ok(()),
731    }
732}
733
734/// AUTHORIZATION TOKEN, the Version Specific Parameter of Section 8.2.1.1.
735///
736/// The number is this draft's own. Draft-13 assigns AUTHORIZATION TOKEN
737/// "Parameter Type 0x03"; draft-11 put it at 0x01, where this draft has the
738/// setup-side PATH parameter instead. Reading either draft's number into the
739/// other would exempt the wrong type from the repeat rule below.
740const AUTHORIZATION_TOKEN: u64 = 0x03;
741
742/// DELIVERY TIMEOUT, the Version Specific Parameter of Section 8.2.1.2.
743const DELIVERY_TIMEOUT: u64 = 0x02;
744
745/// MAX_CACHE_DURATION, the Version Specific Parameter of Section 8.2.1.3.
746const MAX_CACHE_DURATION: u64 = 0x04;
747
748/// PATH, the Setup Parameter of Section 8.3.2.1.
749const SETUP_PATH: u64 = 0x01;
750
751/// MAX_REQUEST_ID, the Setup Parameter of Section 8.3.2.2.
752const SETUP_MAX_REQUEST_ID: u64 = 0x02;
753
754/// MAX_AUTH_TOKEN_CACHE_SIZE, the Setup Parameter of Section 8.3.2.3.
755const SETUP_MAX_AUTH_TOKEN_CACHE_SIZE: u64 = 0x04;
756
757/// AUTHORIZATION TOKEN, the Setup Parameter of Section 8.3.2.4.
758///
759/// That section defines the setup-side parameter by reference - "See
760/// Section 8.2.1.1" - so it carries the same type number and the same
761/// permission to repeat: "The endpoint can specify one or more tokens in
762/// CLIENT_SETUP or SERVER_SETUP that the peer can use to authorize MOQT session
763/// establishment."
764const SETUP_AUTHORIZATION_TOKEN: u64 = AUTHORIZATION_TOKEN;
765
766/// Every Version Specific Parameter Type Section 8.2.1 names.
767///
768/// This list is what "unknown" means to the receiver's half of the Section 8.2
769/// rule. A type absent from it is one some extension defined, and Section 8.2
770/// requires a receiver to carry a repeat of such a type rather than refuse it.
771const KNOWN_PARAMETERS: &[u64] = &[AUTHORIZATION_TOKEN, DELIVERY_TIMEOUT, MAX_CACHE_DURATION];
772
773/// The Version Specific Parameter Types whose own definition allows a repeat.
774///
775/// Section 8.2.1.1: "The AUTHORIZATION TOKEN parameter MAY be repeated within a
776/// message." It is the only parameter on this draft that says so, and the
777/// exemption it earns holds on both sides.
778const REPEATABLE_PARAMETERS: &[u64] = &[AUTHORIZATION_TOKEN];
779
780/// Every Setup Parameter Type Section 8.3.2 names.
781const KNOWN_SETUP_PARAMETERS: &[u64] =
782    &[SETUP_PATH, SETUP_MAX_REQUEST_ID, SETUP_AUTHORIZATION_TOKEN, SETUP_MAX_AUTH_TOKEN_CACHE_SIZE];
783
784/// The Setup Parameter Types whose own definition allows a repeat.
785///
786/// The two namespaces are kept apart because they do not name the same set: a
787/// PATH lives at 0x01 among Setup Parameters and nothing lives there among
788/// Version Specific Parameters, so one shared list of known types would make a
789/// repeated 0x01 refusable in a message where the draft requires it to be
790/// tolerated.
791const REPEATABLE_SETUP_PARAMETERS: &[u64] = &[SETUP_AUTHORIZATION_TOKEN];
792
793/// Refuse a parameter list a sender is not allowed to put on the wire.
794///
795/// Section 8.2: "Senders MUST NOT repeat the same parameter type in a message
796/// unless the parameter definition explicitly allows multiple instances of that
797/// type to be sent in a single message."
798///
799/// This is the wider half of the rule. It names no exception for types the
800/// sender does not recognise, so every repeat is refused here except the ones
801/// `repeatable` lists. A caller holding a parameter this codec has never heard
802/// of still may not send it twice: code that scans a parameter list for a key
803/// takes whichever copy it meets first, so one frame carrying two values for one
804/// type is read differently by two conforming implementations, and that is true
805/// whoever defined the type.
806fn check_sender_parameters(
807    parameters: &[KeyValuePair],
808    repeatable: &[u64],
809) -> Result<(), CodecError> {
810    for (i, parameter) in parameters.iter().enumerate() {
811        let key = parameter.key.into_inner();
812        if repeatable.contains(&key) {
813            continue;
814        }
815        if parameters[..i].iter().any(|earlier| earlier.key == parameter.key) {
816            return Err(CodecError::DuplicateParameter(key));
817        }
818    }
819    Ok(())
820}
821
822/// Refuse a received parameter list only where Section 8.2 lets a receiver
823/// refuse it.
824///
825/// Section 8.2: "Receivers SHOULD check that there are no unauthorized
826/// duplicate parameters and close the session as a 'Protocol Violation' if
827/// found. Receivers MUST allow duplicates of unknown parameters."
828///
829/// The second sentence is why this is not the mirror of
830/// [`check_sender_parameters`]: a repeat of a type this draft names is refused,
831/// and a repeat of any other type is carried. Making the two sides symmetric
832/// would close sessions over parameters defined by an extension this codec does
833/// not implement - traffic the draft requires an endpoint to tolerate - and the
834/// first sentence is a SHOULD, which does not reach that far.
835fn check_receiver_parameters(
836    parameters: &[KeyValuePair],
837    known: &[u64],
838    repeatable: &[u64],
839) -> Result<(), CodecError> {
840    for (i, parameter) in parameters.iter().enumerate() {
841        let key = parameter.key.into_inner();
842        if repeatable.contains(&key) || !known.contains(&key) {
843            continue;
844        }
845        if parameters[..i].iter().any(|earlier| earlier.key == parameter.key) {
846            return Err(CodecError::DuplicateParameter(key));
847        }
848    }
849    Ok(())
850}
851
852/// Hold every AUTHORIZATION TOKEN parameter to the Token structure it names.
853///
854/// Section 8.2.1.1: "If the Token structure cannot be decoded, the receiver
855/// MUST close the Session with Key-Value Formatting error." That is the answer
856/// Section 1.3.2 gives for any Type whose value does not match the
857/// serialization that Type defines; the Token is the one structure this draft
858/// spells out, and the only parameter value in it that is more than opaque
859/// bytes.
860///
861/// Both namespaces carry the type on this draft, and both reach here.
862///
863/// A type this draft cannot name is left alone. The rule is conditional on the
864/// receiver understanding the Type, and an extension's parameter carries bytes
865/// no rule here describes.
866fn check_authorization_tokens(parameters: &[KeyValuePair]) -> Result<(), CodecError> {
867    for parameter in parameters {
868        let key = parameter.key.into_inner();
869        if key != AUTH_TOKEN_PARAMETER {
870            continue;
871        }
872        match &parameter.value {
873            KvpValue::Bytes(value) => {
874                AuthorizationToken::decode(key, value)?;
875            }
876            // Unreachable from the decoder, which picks the shape from the
877            // type and finds this one length-prefixed. A caller that built the
878            // pair in memory can still get here, and it is the same rule: the
879            // value is not the serialization the type defines.
880            KvpValue::Varint(_) => {
881                return Err(CodecError::KeyValueFormatting {
882                    key,
883                    detail: "its value is a bare varint where the type defines a Token structure",
884                });
885            }
886        }
887    }
888    Ok(())
889}
890
891/// Decode a Version Specific Parameter list.
892fn decode_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
893    let parameters = KeyValuePair::decode_list(buf)?;
894    check_receiver_parameters(&parameters, KNOWN_PARAMETERS, REPEATABLE_PARAMETERS)?;
895    check_authorization_tokens(&parameters)?;
896    Ok(parameters)
897}
898
899/// Encode a Version Specific Parameter list.
900fn encode_parameters(parameters: &[KeyValuePair], buf: &mut impl BufMut) -> Result<(), CodecError> {
901    check_sender_parameters(parameters, REPEATABLE_PARAMETERS)?;
902    check_authorization_tokens(parameters)?;
903    KeyValuePair::encode_list_checked(parameters, buf)?;
904    Ok(())
905}
906
907/// Decode the Setup Parameters of a CLIENT_SETUP or SERVER_SETUP message.
908fn decode_setup_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
909    let parameters = KeyValuePair::decode_list(buf)?;
910    check_receiver_parameters(&parameters, KNOWN_SETUP_PARAMETERS, REPEATABLE_SETUP_PARAMETERS)?;
911    check_authorization_tokens(&parameters)?;
912    Ok(parameters)
913}
914
915/// Encode the Setup Parameters of a CLIENT_SETUP or SERVER_SETUP message.
916///
917/// The token is in both namespaces from this draft on, so it is held to its
918/// structure in both. See [`encode_parameters`] for why writing one the reader
919/// would refuse is not a way to send it.
920fn encode_setup_parameters(
921    parameters: &[KeyValuePair],
922    buf: &mut impl BufMut,
923) -> Result<(), CodecError> {
924    check_sender_parameters(parameters, REPEATABLE_SETUP_PARAMETERS)?;
925    check_authorization_tokens(parameters)?;
926    KeyValuePair::encode_list_checked(parameters, buf)?;
927    Ok(())
928}
929
930impl ControlMessage {
931    /// Encode this control message to bytes.
932    ///
933    /// Draft-13 framing: type_id(vi) + payload_length(16) + payload.
934    pub fn encode(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
935        check_discriminators(self)?;
936        check_group_order(self)?;
937        check_ranges(self)?;
938        let mut payload = Vec::with_capacity(256);
939        self.encode_payload(&mut payload)?;
940
941        if payload.len() > MAX_MESSAGE_LENGTH {
942            return Err(CodecError::MessageTooLong(payload.len()));
943        }
944
945        VarInt::from_usize(self.message_type().id() as usize).encode(buf);
946        // Draft-13: 16-bit length (big-endian)
947        buf.put_u16(payload.len() as u16);
948        buf.put_slice(&payload);
949        Ok(())
950    }
951
952    /// Decode a control message from bytes.
953    ///
954    /// Draft-13 framing: type_id(vi) + payload_length(16) + payload.
955    pub fn decode(buf: &mut impl Buf) -> Result<Self, CodecError> {
956        let type_id = VarInt::decode(buf)?.into_inner();
957        let msg_type =
958            MessageType::from_id(type_id).ok_or(CodecError::UnknownMessageType(type_id))?;
959        // Draft-13: 16-bit length (big-endian)
960        if buf.remaining() < 2 {
961            return Err(CodecError::UnexpectedEnd);
962        }
963        let payload_len = buf.get_u16() as usize;
964        if buf.remaining() < payload_len {
965            return Err(CodecError::UnexpectedEnd);
966        }
967        let payload_bytes = buf.copy_to_bytes(payload_len);
968        let mut payload = &payload_bytes[..];
969        let msg = match Self::decode_payload(msg_type, &mut payload) {
970            Ok(msg) => msg,
971            // The fields wanted more bytes than the Length allowed. This buffer
972            // is already bounded by that Length, so running out inside it cannot
973            // mean the message is still arriving - which is what the same error
974            // means everywhere else, and why a reader loops on it rather than
975            // closing. Here there is nothing left to arrive.
976            Err(
977                CodecError::UnexpectedEnd
978                | CodecError::Kvp(crate::kvp::KvpError::UnexpectedEnd)
979                | CodecError::Kvp(crate::kvp::KvpError::VarInt(
980                    crate::varint::VarIntError::UnexpectedEnd,
981                ))
982                | CodecError::VarInt(crate::varint::VarIntError::UnexpectedEnd),
983            ) => {
984                return Err(CodecError::ControlMessageLengthMismatch {
985                    declared: payload_len,
986                    detail: "its fields ran past the end",
987                });
988            }
989            Err(e) => return Err(e),
990        };
991        check_ranges(&msg)?;
992        // The declared length is part of the message, not a hint. Bytes left over
993        // after the fields have been read mean the sender and this reader disagree
994        // about the shape of the message, and guessing which of the two is right
995        // is how a trailing field gets silently dropped.
996        if payload.has_remaining() {
997            return Err(CodecError::ControlMessageLengthMismatch {
998                declared: payload_len,
999                detail: "its fields left bytes unread",
1000            });
1001        }
1002        Ok(msg)
1003    }
1004
1005    fn encode_payload(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
1006        match self {
1007            ControlMessage::ClientSetup(m) => {
1008                VarInt::from_usize(m.supported_versions.len()).encode(buf);
1009                for v in &m.supported_versions {
1010                    v.encode(buf);
1011                }
1012                encode_setup_parameters(&m.parameters, buf)?;
1013            }
1014            ControlMessage::ServerSetup(m) => {
1015                m.selected_version.encode(buf);
1016                encode_setup_parameters(&m.parameters, buf)?;
1017            }
1018            ControlMessage::GoAway(m) => {
1019                if m.new_session_uri.len() > MAX_GOAWAY_URI_LENGTH {
1020                    return Err(CodecError::GoAwayUriTooLong);
1021                }
1022                VarInt::from_usize(m.new_session_uri.len()).encode(buf);
1023                buf.put_slice(&m.new_session_uri);
1024            }
1025            ControlMessage::MaxRequestId(m) => {
1026                m.request_id.encode(buf);
1027            }
1028            ControlMessage::RequestsBlocked(m) => {
1029                m.maximum_request_id.encode(buf);
1030            }
1031            ControlMessage::Subscribe(m) => {
1032                m.request_id.encode(buf);
1033                m.track_namespace.validate(TrackNamespaceRules::for_draft(13))?;
1034                m.track_namespace.encode(buf);
1035                check_full_track_name(&m.track_namespace, &m.track_name)?;
1036                VarInt::from_usize(m.track_name.len()).encode(buf);
1037                buf.put_slice(&m.track_name);
1038                buf.put_u8(m.subscriber_priority);
1039                buf.put_u8(m.group_order as u8);
1040                buf.put_u8(m.forward as u8);
1041                VarInt::from_usize(m.filter_type as usize).encode(buf);
1042                if let Some(sg) = &m.start_group {
1043                    sg.encode(buf);
1044                }
1045                if let Some(so) = &m.start_object {
1046                    so.encode(buf);
1047                }
1048                if let Some(eg) = &m.end_group {
1049                    eg.encode(buf);
1050                }
1051                encode_parameters(&m.parameters, buf)?;
1052            }
1053            ControlMessage::SubscribeOk(m) => {
1054                m.request_id.encode(buf);
1055                m.track_alias.encode(buf);
1056                m.expires.encode(buf);
1057                buf.put_u8(m.group_order as u8);
1058                buf.put_u8(m.content_exists as u8);
1059                if let Some(loc) = &m.largest_location {
1060                    loc.encode(buf);
1061                }
1062                encode_parameters(&m.parameters, buf)?;
1063            }
1064            ControlMessage::SubscribeError(m) => {
1065                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1066                    return Err(CodecError::ReasonPhraseTooLong);
1067                }
1068                m.request_id.encode(buf);
1069                m.error_code.encode(buf);
1070                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1071                buf.put_slice(&m.reason_phrase);
1072            }
1073            ControlMessage::SubscribeUpdate(m) => {
1074                m.request_id.encode(buf);
1075                m.start_group.encode(buf);
1076                m.start_object.encode(buf);
1077                m.end_group.encode(buf);
1078                buf.put_u8(m.subscriber_priority);
1079                buf.put_u8(m.forward as u8);
1080                encode_parameters(&m.parameters, buf)?;
1081            }
1082            ControlMessage::SubscribeDone(m) => {
1083                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1084                    return Err(CodecError::ReasonPhraseTooLong);
1085                }
1086                m.request_id.encode(buf);
1087                m.status_code.encode(buf);
1088                m.stream_count.encode(buf);
1089                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1090                buf.put_slice(&m.reason_phrase);
1091            }
1092            ControlMessage::Unsubscribe(m) => {
1093                m.request_id.encode(buf);
1094            }
1095            ControlMessage::Announce(m) => {
1096                m.request_id.encode(buf);
1097                m.track_namespace.validate(TrackNamespaceRules::for_draft(13))?;
1098                m.track_namespace.encode(buf);
1099                encode_parameters(&m.parameters, buf)?;
1100            }
1101            ControlMessage::AnnounceOk(m) => {
1102                m.request_id.encode(buf);
1103            }
1104            ControlMessage::AnnounceError(m) => {
1105                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1106                    return Err(CodecError::ReasonPhraseTooLong);
1107                }
1108                m.request_id.encode(buf);
1109                m.error_code.encode(buf);
1110                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1111                buf.put_slice(&m.reason_phrase);
1112            }
1113            ControlMessage::AnnounceCancel(m) => {
1114                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1115                    return Err(CodecError::ReasonPhraseTooLong);
1116                }
1117                m.track_namespace.validate(TrackNamespaceRules::for_draft(13))?;
1118                m.track_namespace.encode(buf);
1119                m.error_code.encode(buf);
1120                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1121                buf.put_slice(&m.reason_phrase);
1122            }
1123            ControlMessage::Unannounce(m) => {
1124                m.track_namespace.validate(TrackNamespaceRules::for_draft(13))?;
1125                m.track_namespace.encode(buf);
1126            }
1127            ControlMessage::SubscribeNamespace(m) => {
1128                m.request_id.encode(buf);
1129                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(13))?;
1130                m.track_namespace_prefix.encode(buf);
1131                encode_parameters(&m.parameters, buf)?;
1132            }
1133            ControlMessage::SubscribeNamespaceOk(m) => {
1134                m.request_id.encode(buf);
1135            }
1136            ControlMessage::SubscribeNamespaceError(m) => {
1137                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1138                    return Err(CodecError::ReasonPhraseTooLong);
1139                }
1140                m.request_id.encode(buf);
1141                m.error_code.encode(buf);
1142                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1143                buf.put_slice(&m.reason_phrase);
1144            }
1145            ControlMessage::UnsubscribeNamespace(m) => {
1146                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(13))?;
1147                m.track_namespace_prefix.encode(buf);
1148            }
1149            ControlMessage::TrackStatus(m) => {
1150                m.request_id.encode(buf);
1151                m.track_namespace.validate(TrackNamespaceRules::for_draft(13))?;
1152                m.track_namespace.encode(buf);
1153                check_full_track_name(&m.track_namespace, &m.track_name)?;
1154                VarInt::from_usize(m.track_name.len()).encode(buf);
1155                buf.put_slice(&m.track_name);
1156                buf.put_u8(m.subscriber_priority);
1157                buf.put_u8(m.group_order as u8);
1158                buf.put_u8(m.forward as u8);
1159                VarInt::from_usize(m.filter_type as usize).encode(buf);
1160                if let Some(sg) = &m.start_group {
1161                    sg.encode(buf);
1162                }
1163                if let Some(so) = &m.start_object {
1164                    so.encode(buf);
1165                }
1166                if let Some(eg) = &m.end_group {
1167                    eg.encode(buf);
1168                }
1169                encode_parameters(&m.parameters, buf)?;
1170            }
1171            ControlMessage::TrackStatusOk(m) => {
1172                m.request_id.encode(buf);
1173                m.track_alias.encode(buf);
1174                m.expires.encode(buf);
1175                buf.put_u8(m.group_order as u8);
1176                buf.put_u8(m.content_exists as u8);
1177                if let Some(loc) = &m.largest_location {
1178                    loc.encode(buf);
1179                }
1180                encode_parameters(&m.parameters, buf)?;
1181            }
1182            ControlMessage::TrackStatusError(m) => {
1183                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1184                    return Err(CodecError::ReasonPhraseTooLong);
1185                }
1186                m.request_id.encode(buf);
1187                m.error_code.encode(buf);
1188                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1189                buf.put_slice(&m.reason_phrase);
1190            }
1191            ControlMessage::Fetch(m) => {
1192                m.request_id.encode(buf);
1193                buf.put_u8(m.subscriber_priority);
1194                buf.put_u8(m.group_order as u8);
1195                VarInt::from_usize(m.fetch_type as usize).encode(buf);
1196                match &m.fetch_payload {
1197                    FetchPayload::Standalone {
1198                        track_namespace,
1199                        track_name,
1200                        start_group,
1201                        start_object,
1202                        end_group,
1203                        end_object,
1204                    } => {
1205                        track_namespace.validate(TrackNamespaceRules::for_draft(13))?;
1206                        track_namespace.encode(buf);
1207                        check_full_track_name(track_namespace, track_name)?;
1208                        VarInt::from_usize(track_name.len()).encode(buf);
1209                        buf.put_slice(track_name);
1210                        start_group.encode(buf);
1211                        start_object.encode(buf);
1212                        end_group.encode(buf);
1213                        end_object.encode(buf);
1214                    }
1215                    FetchPayload::Joining { joining_request_id, joining_start } => {
1216                        joining_request_id.encode(buf);
1217                        joining_start.encode(buf);
1218                    }
1219                }
1220                encode_parameters(&m.parameters, buf)?;
1221            }
1222            ControlMessage::FetchOk(m) => {
1223                m.request_id.encode(buf);
1224                buf.put_u8(m.group_order as u8);
1225                buf.put_u8(m.end_of_track);
1226                m.end_location.encode(buf);
1227                encode_parameters(&m.parameters, buf)?;
1228            }
1229            ControlMessage::FetchError(m) => {
1230                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1231                    return Err(CodecError::ReasonPhraseTooLong);
1232                }
1233                m.request_id.encode(buf);
1234                m.error_code.encode(buf);
1235                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1236                buf.put_slice(&m.reason_phrase);
1237            }
1238            ControlMessage::FetchCancel(m) => {
1239                m.request_id.encode(buf);
1240            }
1241            ControlMessage::Publish(m) => {
1242                m.request_id.encode(buf);
1243                m.track_namespace.validate(TrackNamespaceRules::for_draft(13))?;
1244                m.track_namespace.encode(buf);
1245                check_full_track_name(&m.track_namespace, &m.track_name)?;
1246                VarInt::from_usize(m.track_name.len()).encode(buf);
1247                buf.put_slice(&m.track_name);
1248                m.track_alias.encode(buf);
1249                buf.put_u8(m.group_order as u8);
1250                buf.put_u8(m.content_exists as u8);
1251                if let Some(loc) = &m.largest_location {
1252                    loc.encode(buf);
1253                }
1254                buf.put_u8(m.forward as u8);
1255                encode_parameters(&m.parameters, buf)?;
1256            }
1257            ControlMessage::PublishOk(m) => {
1258                m.request_id.encode(buf);
1259                buf.put_u8(m.forward as u8);
1260                buf.put_u8(m.subscriber_priority);
1261                buf.put_u8(m.group_order as u8);
1262                VarInt::from_usize(m.filter_type as usize).encode(buf);
1263                if let Some(sg) = &m.start_group {
1264                    sg.encode(buf);
1265                }
1266                if let Some(so) = &m.start_object {
1267                    so.encode(buf);
1268                }
1269                if let Some(eg) = &m.end_group {
1270                    eg.encode(buf);
1271                }
1272                encode_parameters(&m.parameters, buf)?;
1273            }
1274            ControlMessage::PublishError(m) => {
1275                if m.reason_phrase.len() > MAX_REASON_PHRASE_LENGTH {
1276                    return Err(CodecError::ReasonPhraseTooLong);
1277                }
1278                m.request_id.encode(buf);
1279                m.error_code.encode(buf);
1280                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1281                buf.put_slice(&m.reason_phrase);
1282            }
1283        }
1284        Ok(())
1285    }
1286
1287    fn decode_payload(msg_type: MessageType, buf: &mut impl Buf) -> Result<Self, CodecError> {
1288        match msg_type {
1289            MessageType::ClientSetup => {
1290                let num_versions = VarInt::decode(buf)?.into_inner() as usize;
1291                // Not a rule this draft states. It says only that the server
1292                // "MUST reply with one of the versions offered by the client"
1293                // and that a peer with no version in common "MUST close the
1294                // session" - outcomes of negotiation rather than parse errors,
1295                // and a CLIENT_SETUP offering nothing decodes cleanly under the
1296                // figure. It is refused here because there is no version a
1297                // reply could name, so the session is already over and the
1298                // early close is the more useful answer than a well-formed
1299                // message no caller can act on.
1300                if num_versions == 0 {
1301                    return Err(CodecError::InvalidField);
1302                }
1303                let mut supported_versions = crate::types::reserve_bounded(num_versions, buf);
1304                for _ in 0..num_versions {
1305                    supported_versions.push(VarInt::decode(buf)?);
1306                }
1307                let parameters = decode_setup_parameters(buf)?;
1308                Ok(ControlMessage::ClientSetup(ClientSetup { supported_versions, parameters }))
1309            }
1310            MessageType::ServerSetup => {
1311                let selected_version = VarInt::decode(buf)?;
1312                let parameters = decode_setup_parameters(buf)?;
1313                Ok(ControlMessage::ServerSetup(ServerSetup { selected_version, parameters }))
1314            }
1315            MessageType::GoAway => {
1316                let uri_len = VarInt::decode(buf)?.into_inner() as usize;
1317                if uri_len > MAX_GOAWAY_URI_LENGTH {
1318                    return Err(CodecError::GoAwayUriTooLong);
1319                }
1320                let uri = read_bytes(buf, uri_len)?;
1321                Ok(ControlMessage::GoAway(GoAway { new_session_uri: uri }))
1322            }
1323            MessageType::MaxRequestId => {
1324                let request_id = VarInt::decode(buf)?;
1325                Ok(ControlMessage::MaxRequestId(MaxRequestId { request_id }))
1326            }
1327            MessageType::RequestsBlocked => {
1328                let maximum_request_id = VarInt::decode(buf)?;
1329                Ok(ControlMessage::RequestsBlocked(RequestsBlocked { maximum_request_id }))
1330            }
1331            MessageType::Subscribe => {
1332                let request_id = VarInt::decode(buf)?;
1333                let track_namespace = TrackNamespace::decode(buf)?;
1334                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1335                let track_name = read_bytes(buf, track_name_len)?;
1336                check_full_track_name(&track_namespace, &track_name)?;
1337                let subscriber_priority = read_u8(buf)?;
1338                let group_order = read_group_order(buf)?;
1339                let forward = read_forward(buf)?;
1340                let filter_type = read_filter_type(buf)?;
1341                let (start_group, start_object) = read_start_location(filter_type, buf)?;
1342                let end_group = read_end_group(filter_type, buf)?;
1343                let parameters = decode_parameters(buf)?;
1344                Ok(ControlMessage::Subscribe(Subscribe {
1345                    request_id,
1346                    track_namespace,
1347                    track_name,
1348                    subscriber_priority,
1349                    group_order,
1350                    forward,
1351                    filter_type,
1352                    start_group,
1353                    start_object,
1354                    end_group,
1355                    parameters,
1356                }))
1357            }
1358            MessageType::SubscribeOk => {
1359                let request_id = VarInt::decode(buf)?;
1360                let track_alias = VarInt::decode(buf)?;
1361                let expires = VarInt::decode(buf)?;
1362                let group_order = read_group_order_response(buf)?;
1363                let content_exists = read_content_exists(buf)?;
1364                let largest_location = read_largest_location(content_exists, buf)?;
1365                let parameters = decode_parameters(buf)?;
1366                Ok(ControlMessage::SubscribeOk(SubscribeOk {
1367                    request_id,
1368                    track_alias,
1369                    expires,
1370                    group_order,
1371                    content_exists,
1372                    largest_location,
1373                    parameters,
1374                }))
1375            }
1376            MessageType::SubscribeError => {
1377                let request_id = VarInt::decode(buf)?;
1378                let error_code = VarInt::decode(buf)?;
1379                let reason_phrase = read_reason_phrase(buf)?;
1380                Ok(ControlMessage::SubscribeError(SubscribeError {
1381                    request_id,
1382                    error_code,
1383                    reason_phrase,
1384                }))
1385            }
1386            MessageType::SubscribeUpdate => {
1387                let request_id = VarInt::decode(buf)?;
1388                let start_group = VarInt::decode(buf)?;
1389                let start_object = VarInt::decode(buf)?;
1390                let end_group = VarInt::decode(buf)?;
1391                let subscriber_priority = read_u8(buf)?;
1392                let forward = read_forward(buf)?;
1393                let parameters = decode_parameters(buf)?;
1394                Ok(ControlMessage::SubscribeUpdate(SubscribeUpdate {
1395                    request_id,
1396                    start_group,
1397                    start_object,
1398                    end_group,
1399                    subscriber_priority,
1400                    forward,
1401                    parameters,
1402                }))
1403            }
1404            MessageType::SubscribeDone => {
1405                let request_id = VarInt::decode(buf)?;
1406                let status_code = VarInt::decode(buf)?;
1407                let stream_count = VarInt::decode(buf)?;
1408                let reason_phrase = read_reason_phrase(buf)?;
1409                Ok(ControlMessage::SubscribeDone(SubscribeDone {
1410                    request_id,
1411                    status_code,
1412                    stream_count,
1413                    reason_phrase,
1414                }))
1415            }
1416            MessageType::Unsubscribe => {
1417                let request_id = VarInt::decode(buf)?;
1418                Ok(ControlMessage::Unsubscribe(Unsubscribe { request_id }))
1419            }
1420            MessageType::Announce => {
1421                let request_id = VarInt::decode(buf)?;
1422                let track_namespace = TrackNamespace::decode(buf)?;
1423                let parameters = decode_parameters(buf)?;
1424                Ok(ControlMessage::Announce(Announce { request_id, track_namespace, parameters }))
1425            }
1426            MessageType::AnnounceOk => {
1427                let request_id = VarInt::decode(buf)?;
1428                Ok(ControlMessage::AnnounceOk(AnnounceOk { request_id }))
1429            }
1430            MessageType::AnnounceError => {
1431                let request_id = VarInt::decode(buf)?;
1432                let error_code = VarInt::decode(buf)?;
1433                let reason_phrase = read_reason_phrase(buf)?;
1434                Ok(ControlMessage::AnnounceError(AnnounceError {
1435                    request_id,
1436                    error_code,
1437                    reason_phrase,
1438                }))
1439            }
1440            MessageType::AnnounceCancel => {
1441                let track_namespace = TrackNamespace::decode(buf)?;
1442                let error_code = VarInt::decode(buf)?;
1443                let reason_phrase = read_reason_phrase(buf)?;
1444                Ok(ControlMessage::AnnounceCancel(AnnounceCancel {
1445                    track_namespace,
1446                    error_code,
1447                    reason_phrase,
1448                }))
1449            }
1450            MessageType::Unannounce => {
1451                let track_namespace = TrackNamespace::decode(buf)?;
1452                Ok(ControlMessage::Unannounce(Unannounce { track_namespace }))
1453            }
1454            MessageType::SubscribeNamespace => {
1455                let request_id = VarInt::decode(buf)?;
1456                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1457                let parameters = decode_parameters(buf)?;
1458                Ok(ControlMessage::SubscribeNamespace(SubscribeNamespace {
1459                    request_id,
1460                    track_namespace_prefix,
1461                    parameters,
1462                }))
1463            }
1464            MessageType::SubscribeNamespaceOk => {
1465                let request_id = VarInt::decode(buf)?;
1466                Ok(ControlMessage::SubscribeNamespaceOk(SubscribeNamespaceOk { request_id }))
1467            }
1468            MessageType::SubscribeNamespaceError => {
1469                let request_id = VarInt::decode(buf)?;
1470                let error_code = VarInt::decode(buf)?;
1471                let reason_phrase = read_reason_phrase(buf)?;
1472                Ok(ControlMessage::SubscribeNamespaceError(SubscribeNamespaceError {
1473                    request_id,
1474                    error_code,
1475                    reason_phrase,
1476                }))
1477            }
1478            MessageType::UnsubscribeNamespace => {
1479                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1480                Ok(ControlMessage::UnsubscribeNamespace(UnsubscribeNamespace {
1481                    track_namespace_prefix,
1482                }))
1483            }
1484            MessageType::TrackStatus => {
1485                let request_id = VarInt::decode(buf)?;
1486                let track_namespace = TrackNamespace::decode(buf)?;
1487                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1488                let track_name = read_bytes(buf, track_name_len)?;
1489                check_full_track_name(&track_namespace, &track_name)?;
1490                let subscriber_priority = read_u8(buf)?;
1491                let group_order = read_group_order(buf)?;
1492                let forward = read_forward(buf)?;
1493                let filter_type = read_filter_type(buf)?;
1494                let (start_group, start_object) = read_start_location(filter_type, buf)?;
1495                let end_group = read_end_group(filter_type, buf)?;
1496                let parameters = decode_parameters(buf)?;
1497                Ok(ControlMessage::TrackStatus(TrackStatus {
1498                    request_id,
1499                    track_namespace,
1500                    track_name,
1501                    subscriber_priority,
1502                    group_order,
1503                    forward,
1504                    filter_type,
1505                    start_group,
1506                    start_object,
1507                    end_group,
1508                    parameters,
1509                }))
1510            }
1511            MessageType::TrackStatusOk => {
1512                let request_id = VarInt::decode(buf)?;
1513                let track_alias = VarInt::decode(buf)?;
1514                let expires = VarInt::decode(buf)?;
1515                let group_order = read_group_order_response(buf)?;
1516                let content_exists = read_content_exists(buf)?;
1517                let largest_location = read_largest_location(content_exists, buf)?;
1518                let parameters = decode_parameters(buf)?;
1519                Ok(ControlMessage::TrackStatusOk(TrackStatusOk {
1520                    request_id,
1521                    track_alias,
1522                    expires,
1523                    group_order,
1524                    content_exists,
1525                    largest_location,
1526                    parameters,
1527                }))
1528            }
1529            MessageType::TrackStatusError => {
1530                let request_id = VarInt::decode(buf)?;
1531                let error_code = VarInt::decode(buf)?;
1532                let reason_phrase = read_reason_phrase(buf)?;
1533                Ok(ControlMessage::TrackStatusError(TrackStatusError {
1534                    request_id,
1535                    error_code,
1536                    reason_phrase,
1537                }))
1538            }
1539            MessageType::Fetch => {
1540                let request_id = VarInt::decode(buf)?;
1541                let subscriber_priority = read_u8(buf)?;
1542                let group_order = read_group_order(buf)?;
1543                let fetch_type_val = VarInt::decode(buf)?.into_inner();
1544                let fetch_type = FetchType::from_u64(fetch_type_val)
1545                    .ok_or(CodecError::InvalidFetchType(fetch_type_val))?;
1546                let fetch_payload = match fetch_type {
1547                    FetchType::Standalone => {
1548                        let track_namespace = TrackNamespace::decode(buf)?;
1549                        let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1550                        let track_name = read_bytes(buf, track_name_len)?;
1551                        check_full_track_name(&track_namespace, &track_name)?;
1552                        let start_group = VarInt::decode(buf)?;
1553                        let start_object = VarInt::decode(buf)?;
1554                        let end_group = VarInt::decode(buf)?;
1555                        let end_object = VarInt::decode(buf)?;
1556                        FetchPayload::Standalone {
1557                            track_namespace,
1558                            track_name,
1559                            start_group,
1560                            start_object,
1561                            end_group,
1562                            end_object,
1563                        }
1564                    }
1565                    FetchType::RelativeJoining | FetchType::AbsoluteJoining => {
1566                        let joining_request_id = VarInt::decode(buf)?;
1567                        let joining_start = VarInt::decode(buf)?;
1568                        FetchPayload::Joining { joining_request_id, joining_start }
1569                    }
1570                };
1571                let parameters = decode_parameters(buf)?;
1572                Ok(ControlMessage::Fetch(Fetch {
1573                    request_id,
1574                    subscriber_priority,
1575                    group_order,
1576                    fetch_type,
1577                    fetch_payload,
1578                    parameters,
1579                }))
1580            }
1581            MessageType::FetchOk => {
1582                let request_id = VarInt::decode(buf)?;
1583                let group_order = read_group_order_response(buf)?;
1584                let end_of_track = read_u8(buf)?;
1585                let end_location = Location::decode(buf)?;
1586                let parameters = decode_parameters(buf)?;
1587                Ok(ControlMessage::FetchOk(FetchOk {
1588                    request_id,
1589                    group_order,
1590                    end_of_track,
1591                    end_location,
1592                    parameters,
1593                }))
1594            }
1595            MessageType::FetchError => {
1596                let request_id = VarInt::decode(buf)?;
1597                let error_code = VarInt::decode(buf)?;
1598                let reason_phrase = read_reason_phrase(buf)?;
1599                Ok(ControlMessage::FetchError(FetchError { request_id, error_code, reason_phrase }))
1600            }
1601            MessageType::FetchCancel => {
1602                let request_id = VarInt::decode(buf)?;
1603                Ok(ControlMessage::FetchCancel(FetchCancel { request_id }))
1604            }
1605            MessageType::Publish => {
1606                let request_id = VarInt::decode(buf)?;
1607                let track_namespace = TrackNamespace::decode(buf)?;
1608                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1609                let track_name = read_bytes(buf, track_name_len)?;
1610                check_full_track_name(&track_namespace, &track_name)?;
1611                let track_alias = VarInt::decode(buf)?;
1612                let group_order = read_group_order_response(buf)?;
1613                let content_exists = read_content_exists(buf)?;
1614                let largest_location = read_largest_location(content_exists, buf)?;
1615                let forward = read_forward(buf)?;
1616                let parameters = decode_parameters(buf)?;
1617                Ok(ControlMessage::Publish(Publish {
1618                    request_id,
1619                    track_namespace,
1620                    track_name,
1621                    track_alias,
1622                    group_order,
1623                    content_exists,
1624                    largest_location,
1625                    forward,
1626                    parameters,
1627                }))
1628            }
1629            MessageType::PublishOk => {
1630                let request_id = VarInt::decode(buf)?;
1631                let forward = read_forward(buf)?;
1632                let subscriber_priority = read_u8(buf)?;
1633                let group_order = read_group_order_response(buf)?;
1634                let filter_type = read_filter_type(buf)?;
1635                let (start_group, start_object) = read_start_location(filter_type, buf)?;
1636                let end_group = read_end_group(filter_type, buf)?;
1637                let parameters = decode_parameters(buf)?;
1638                Ok(ControlMessage::PublishOk(PublishOk {
1639                    request_id,
1640                    forward,
1641                    subscriber_priority,
1642                    group_order,
1643                    filter_type,
1644                    start_group,
1645                    start_object,
1646                    end_group,
1647                    parameters,
1648                }))
1649            }
1650            MessageType::PublishError => {
1651                let request_id = VarInt::decode(buf)?;
1652                let error_code = VarInt::decode(buf)?;
1653                let reason_phrase = read_reason_phrase(buf)?;
1654                Ok(ControlMessage::PublishError(PublishError {
1655                    request_id,
1656                    error_code,
1657                    reason_phrase,
1658                }))
1659            }
1660        }
1661    }
1662
1663    pub fn message_type(&self) -> MessageType {
1664        match self {
1665            ControlMessage::ClientSetup(_) => MessageType::ClientSetup,
1666            ControlMessage::ServerSetup(_) => MessageType::ServerSetup,
1667            ControlMessage::GoAway(_) => MessageType::GoAway,
1668            ControlMessage::MaxRequestId(_) => MessageType::MaxRequestId,
1669            ControlMessage::RequestsBlocked(_) => MessageType::RequestsBlocked,
1670            ControlMessage::Subscribe(_) => MessageType::Subscribe,
1671            ControlMessage::SubscribeOk(_) => MessageType::SubscribeOk,
1672            ControlMessage::SubscribeError(_) => MessageType::SubscribeError,
1673            ControlMessage::SubscribeUpdate(_) => MessageType::SubscribeUpdate,
1674            ControlMessage::SubscribeDone(_) => MessageType::SubscribeDone,
1675            ControlMessage::Unsubscribe(_) => MessageType::Unsubscribe,
1676            ControlMessage::Announce(_) => MessageType::Announce,
1677            ControlMessage::AnnounceOk(_) => MessageType::AnnounceOk,
1678            ControlMessage::AnnounceError(_) => MessageType::AnnounceError,
1679            ControlMessage::AnnounceCancel(_) => MessageType::AnnounceCancel,
1680            ControlMessage::Unannounce(_) => MessageType::Unannounce,
1681            ControlMessage::SubscribeNamespace(_) => MessageType::SubscribeNamespace,
1682            ControlMessage::SubscribeNamespaceOk(_) => MessageType::SubscribeNamespaceOk,
1683            ControlMessage::SubscribeNamespaceError(_) => MessageType::SubscribeNamespaceError,
1684            ControlMessage::UnsubscribeNamespace(_) => MessageType::UnsubscribeNamespace,
1685            ControlMessage::TrackStatus(_) => MessageType::TrackStatus,
1686            ControlMessage::TrackStatusOk(_) => MessageType::TrackStatusOk,
1687            ControlMessage::TrackStatusError(_) => MessageType::TrackStatusError,
1688            ControlMessage::Fetch(_) => MessageType::Fetch,
1689            ControlMessage::FetchOk(_) => MessageType::FetchOk,
1690            ControlMessage::FetchError(_) => MessageType::FetchError,
1691            ControlMessage::FetchCancel(_) => MessageType::FetchCancel,
1692            ControlMessage::Publish(_) => MessageType::Publish,
1693            ControlMessage::PublishOk(_) => MessageType::PublishOk,
1694            ControlMessage::PublishError(_) => MessageType::PublishError,
1695        }
1696    }
1697}