Skip to main content

moqtap_codec/draft10/
message.rs

1//! Draft-10 control message encoding and decoding.
2//!
3//! The wire format is draft-09's, unchanged: the same 26 message types with the
4//! same field lists. Only the section numbering moves, which is why the
5//! citations here are one chapter later than draft-09's.
6//!
7//! Filter Type `0x1` is absent, as it is on draft-09 - it was withdrawn there,
8//! not here.
9
10use crate::error::CodecError;
11use crate::kvp::KeyValuePair;
12use crate::types::read_bytes;
13use crate::types::*;
14use crate::types::{check_group_range, check_location_range, check_open_ended_group_range};
15use crate::varint::VarInt;
16use bytes::{Buf, BufMut};
17
18/// Control message type IDs (draft-10).
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20#[repr(u64)]
21pub enum MessageType {
22    /// SubscribeUpdate (type 0x02).
23    SubscribeUpdate = 0x02,
24    /// Subscribe (type 0x03).
25    Subscribe = 0x03,
26    /// SubscribeOk (type 0x04).
27    SubscribeOk = 0x04,
28    /// SubscribeError (type 0x05).
29    SubscribeError = 0x05,
30    /// Announce (type 0x06).
31    Announce = 0x06,
32    /// AnnounceOk (type 0x07).
33    AnnounceOk = 0x07,
34    /// AnnounceError (type 0x08).
35    AnnounceError = 0x08,
36    /// Unannounce (type 0x09).
37    Unannounce = 0x09,
38    /// Unsubscribe (type 0x0A).
39    Unsubscribe = 0x0A,
40    /// SubscribeDone (type 0x0B).
41    SubscribeDone = 0x0B,
42    /// AnnounceCancel (type 0x0C).
43    AnnounceCancel = 0x0C,
44    /// TrackStatusRequest (type 0x0D).
45    TrackStatusRequest = 0x0D,
46    /// TrackStatus (type 0x0E).
47    TrackStatus = 0x0E,
48    /// GoAway (type 0x10).
49    GoAway = 0x10,
50    /// SubscribeAnnounces (type 0x11).
51    SubscribeAnnounces = 0x11,
52    /// SubscribeAnnouncesOk (type 0x12).
53    SubscribeAnnouncesOk = 0x12,
54    /// SubscribeAnnouncesError (type 0x13).
55    SubscribeAnnouncesError = 0x13,
56    /// UnsubscribeAnnounces (type 0x14).
57    UnsubscribeAnnounces = 0x14,
58    /// MaxSubscribeId (type 0x15).
59    MaxSubscribeId = 0x15,
60    /// Fetch (type 0x16).
61    Fetch = 0x16,
62    /// FetchCancel (type 0x17).
63    FetchCancel = 0x17,
64    /// FetchOk (type 0x18).
65    FetchOk = 0x18,
66    /// FetchError (type 0x19).
67    FetchError = 0x19,
68    /// SubscribesBlocked (type 0x1A).
69    SubscribesBlocked = 0x1A,
70    /// ClientSetup (type 0x40).
71    ClientSetup = 0x40,
72    /// ServerSetup (type 0x41).
73    ServerSetup = 0x41,
74}
75
76impl MessageType {
77    /// Look up a message type by its wire ID.
78    pub fn from_id(id: u64) -> Option<Self> {
79        match id {
80            0x02 => Some(MessageType::SubscribeUpdate),
81            0x03 => Some(MessageType::Subscribe),
82            0x04 => Some(MessageType::SubscribeOk),
83            0x05 => Some(MessageType::SubscribeError),
84            0x06 => Some(MessageType::Announce),
85            0x07 => Some(MessageType::AnnounceOk),
86            0x08 => Some(MessageType::AnnounceError),
87            0x09 => Some(MessageType::Unannounce),
88            0x0A => Some(MessageType::Unsubscribe),
89            0x0B => Some(MessageType::SubscribeDone),
90            0x0C => Some(MessageType::AnnounceCancel),
91            0x0D => Some(MessageType::TrackStatusRequest),
92            0x0E => Some(MessageType::TrackStatus),
93            0x10 => Some(MessageType::GoAway),
94            0x11 => Some(MessageType::SubscribeAnnounces),
95            0x12 => Some(MessageType::SubscribeAnnouncesOk),
96            0x13 => Some(MessageType::SubscribeAnnouncesError),
97            0x14 => Some(MessageType::UnsubscribeAnnounces),
98            0x15 => Some(MessageType::MaxSubscribeId),
99            0x16 => Some(MessageType::Fetch),
100            0x17 => Some(MessageType::FetchCancel),
101            0x18 => Some(MessageType::FetchOk),
102            0x19 => Some(MessageType::FetchError),
103            0x1A => Some(MessageType::SubscribesBlocked),
104            0x40 => Some(MessageType::ClientSetup),
105            0x41 => Some(MessageType::ServerSetup),
106            _ => None,
107        }
108    }
109
110    /// Return the wire ID for this message type.
111    pub fn id(&self) -> u64 {
112        *self as u64
113    }
114}
115
116// ============================================================
117// Session Lifecycle Messages
118// ============================================================
119
120/// CLIENT_SETUP message (type 0x40).
121#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct ClientSetup {
123    /// The list of MoQT versions supported by the client.
124    pub supported_versions: Vec<VarInt>,
125    /// Setup parameters sent by the client.
126    pub parameters: Vec<KeyValuePair>,
127}
128
129/// SERVER_SETUP message (type 0x41).
130#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct ServerSetup {
132    /// The MoQT version selected by the server.
133    pub selected_version: VarInt,
134    /// Setup parameters sent by the server.
135    pub parameters: Vec<KeyValuePair>,
136}
137
138/// GOAWAY message (type 0x10).
139#[derive(Debug, Clone, PartialEq, Eq)]
140pub struct GoAway {
141    /// The URI for the new session the client should connect to.
142    pub new_session_uri: Vec<u8>,
143}
144
145/// MAX_SUBSCRIBE_ID message (type 0x15).
146#[derive(Debug, Clone, PartialEq, Eq)]
147pub struct MaxSubscribeId {
148    /// The maximum subscribe ID the peer is willing to accept.
149    pub subscribe_id: VarInt,
150}
151
152/// SUBSCRIBES_BLOCKED message (type 0x1A).
153#[derive(Debug, Clone, PartialEq, Eq)]
154pub struct SubscribesBlocked {
155    /// The maximum subscribe ID advertised by the peer.
156    pub maximum_subscribe_id: VarInt,
157}
158
159// ============================================================
160// Subscribe Messages
161// ============================================================
162
163/// SUBSCRIBE message (type 0x03).
164///
165/// Filter Type `0x1` is rejected on decode. It was withdrawn at draft-09 and
166/// draft-10 does not bring it back.
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub struct Subscribe {
169    /// The subscribe ID for this request.
170    pub subscribe_id: VarInt,
171    /// The track alias assigned by the subscriber.
172    pub track_alias: VarInt,
173    /// The track namespace to subscribe to.
174    pub track_namespace: TrackNamespace,
175    /// The track name within the namespace.
176    pub track_name: Vec<u8>,
177    /// The priority of this subscriber relative to others.
178    pub subscriber_priority: u8,
179    /// The requested group delivery order.
180    pub group_order: GroupOrder,
181    /// The filter type controlling which objects are delivered.
182    pub filter_type: FilterType,
183    /// Present only for AbsoluteStart and AbsoluteRange filter types.
184    pub start_location: Option<Location>,
185    /// Present only for AbsoluteRange filter type (end_group only, no end_object).
186    pub end_group: Option<VarInt>,
187    /// Subscribe parameters.
188    pub parameters: Vec<KeyValuePair>,
189}
190
191/// SUBSCRIBE_OK message (type 0x04).
192#[derive(Debug, Clone, PartialEq, Eq)]
193pub struct SubscribeOk {
194    /// The subscribe ID this response corresponds to.
195    pub subscribe_id: VarInt,
196    /// The expiration time for this subscription in milliseconds.
197    pub expires: VarInt,
198    /// The group delivery order chosen by the publisher.
199    pub group_order: GroupOrder,
200    /// Whether the largest location is included.
201    pub content_exists: ContentExists,
202    /// Present only when content_exists == HasLargestLocation.
203    pub largest_group_id: Option<VarInt>,
204    /// Present only when content_exists == HasLargestLocation.
205    pub largest_object_id: Option<VarInt>,
206    /// Subscribe OK parameters.
207    pub parameters: Vec<KeyValuePair>,
208}
209
210/// SUBSCRIBE_ERROR message (type 0x05).
211#[derive(Debug, Clone, PartialEq, Eq)]
212pub struct SubscribeError {
213    /// The subscribe ID this error corresponds to.
214    pub subscribe_id: VarInt,
215    /// The error code indicating the reason for failure.
216    pub error_code: VarInt,
217    /// A human-readable reason for the error.
218    pub reason_phrase: Vec<u8>,
219    /// The track alias from the original subscribe request.
220    pub track_alias: VarInt,
221}
222
223/// SUBSCRIBE_UPDATE message (type 0x02).
224#[derive(Debug, Clone, PartialEq, Eq)]
225pub struct SubscribeUpdate {
226    /// The subscribe ID to update.
227    pub subscribe_id: VarInt,
228    /// The new start group.
229    pub start_group: VarInt,
230    /// The new start object.
231    pub start_object: VarInt,
232    /// The new end group.
233    pub end_group: VarInt,
234    /// The updated subscriber priority.
235    pub subscriber_priority: u8,
236    /// Updated subscribe parameters.
237    pub parameters: Vec<KeyValuePair>,
238}
239
240/// SUBSCRIBE_DONE message (type 0x0B).
241#[derive(Debug, Clone, PartialEq, Eq)]
242pub struct SubscribeDone {
243    /// The subscribe ID this message refers to.
244    pub subscribe_id: VarInt,
245    /// The status code for the subscription completion.
246    pub status_code: VarInt,
247    /// Number of streams delivered.
248    pub stream_count: VarInt,
249    /// A human-readable reason phrase.
250    pub reason_phrase: Vec<u8>,
251}
252
253/// UNSUBSCRIBE message (type 0x0A).
254#[derive(Debug, Clone, PartialEq, Eq)]
255pub struct Unsubscribe {
256    /// The subscribe ID to unsubscribe from.
257    pub subscribe_id: VarInt,
258}
259
260// ============================================================
261// Announce Messages
262// ============================================================
263
264/// ANNOUNCE message (type 0x06).
265#[derive(Debug, Clone, PartialEq, Eq)]
266pub struct Announce {
267    /// The track namespace being announced.
268    pub track_namespace: TrackNamespace,
269    /// Announce parameters.
270    pub parameters: Vec<KeyValuePair>,
271}
272
273/// ANNOUNCE_OK message (type 0x07).
274#[derive(Debug, Clone, PartialEq, Eq)]
275pub struct AnnounceOk {
276    /// The track namespace that was accepted.
277    pub track_namespace: TrackNamespace,
278}
279
280/// ANNOUNCE_ERROR message (type 0x08).
281#[derive(Debug, Clone, PartialEq, Eq)]
282pub struct AnnounceError {
283    /// The track namespace that was rejected.
284    pub track_namespace: TrackNamespace,
285    /// The error code indicating the reason for failure.
286    pub error_code: VarInt,
287    /// A human-readable reason for the error.
288    pub reason_phrase: Vec<u8>,
289}
290
291/// ANNOUNCE_CANCEL message (type 0x0C).
292#[derive(Debug, Clone, PartialEq, Eq)]
293pub struct AnnounceCancel {
294    /// The track namespace being cancelled.
295    pub track_namespace: TrackNamespace,
296    /// The error code indicating the reason for cancellation.
297    pub error_code: VarInt,
298    /// A human-readable reason for the cancellation.
299    pub reason_phrase: Vec<u8>,
300}
301
302/// UNANNOUNCE message (type 0x09).
303#[derive(Debug, Clone, PartialEq, Eq)]
304pub struct Unannounce {
305    /// The track namespace being unannounced.
306    pub track_namespace: TrackNamespace,
307}
308
309// ============================================================
310// Subscribe Announces Messages
311// ============================================================
312
313/// SUBSCRIBE_ANNOUNCES message (type 0x11).
314#[derive(Debug, Clone, PartialEq, Eq)]
315pub struct SubscribeAnnounces {
316    /// The track namespace prefix to subscribe to announcements for.
317    pub track_namespace_prefix: TrackNamespace,
318    /// Subscribe announces parameters.
319    pub parameters: Vec<KeyValuePair>,
320}
321
322/// SUBSCRIBE_ANNOUNCES_OK message (type 0x12).
323#[derive(Debug, Clone, PartialEq, Eq)]
324pub struct SubscribeAnnouncesOk {
325    /// The track namespace prefix that was accepted.
326    pub track_namespace_prefix: TrackNamespace,
327}
328
329/// SUBSCRIBE_ANNOUNCES_ERROR message (type 0x13).
330#[derive(Debug, Clone, PartialEq, Eq)]
331pub struct SubscribeAnnouncesError {
332    /// The track namespace prefix that was rejected.
333    pub track_namespace_prefix: TrackNamespace,
334    /// The error code indicating the reason for failure.
335    pub error_code: VarInt,
336    /// A human-readable reason for the error.
337    pub reason_phrase: Vec<u8>,
338}
339
340/// UNSUBSCRIBE_ANNOUNCES message (type 0x14).
341#[derive(Debug, Clone, PartialEq, Eq)]
342pub struct UnsubscribeAnnounces {
343    /// The track namespace prefix to unsubscribe from.
344    pub track_namespace_prefix: TrackNamespace,
345}
346
347// ============================================================
348// Track Status Messages
349// ============================================================
350
351/// TRACK_STATUS_REQUEST message (type 0x0D).
352#[derive(Debug, Clone, PartialEq, Eq)]
353pub struct TrackStatusRequest {
354    /// The track namespace to query status for.
355    pub track_namespace: TrackNamespace,
356    /// The track name to query status for.
357    pub track_name: Vec<u8>,
358}
359
360/// TRACK_STATUS message (type 0x0E).
361#[derive(Debug, Clone, PartialEq, Eq)]
362pub struct TrackStatus {
363    /// The track namespace this status is for.
364    pub track_namespace: TrackNamespace,
365    /// The track name this status is for.
366    pub track_name: Vec<u8>,
367    /// The status code for the track.
368    pub status_code: VarInt,
369    /// The last group ID available on this track.
370    pub last_group_id: VarInt,
371    /// The last object ID available on this track.
372    pub last_object_id: VarInt,
373}
374
375// ============================================================
376// Fetch Messages
377// ============================================================
378
379/// Fetch type for FETCH message (draft-10).
380#[derive(Debug, Clone, Copy, PartialEq, Eq)]
381#[repr(u64)]
382pub enum FetchType {
383    /// Standalone fetch with explicit track and range.
384    Standalone = 1,
385    /// Joining fetch referencing an existing subscription.
386    Joining = 2,
387}
388
389impl FetchType {
390    /// Convert a raw value to a `FetchType`, if valid.
391    pub fn from_u64(v: u64) -> Option<Self> {
392        match v {
393            1 => Some(FetchType::Standalone),
394            2 => Some(FetchType::Joining),
395            _ => None,
396        }
397    }
398}
399
400/// FETCH message (type 0x16).
401#[derive(Debug, Clone, PartialEq, Eq)]
402pub struct Fetch {
403    /// The subscribe ID for this fetch request.
404    pub subscribe_id: VarInt,
405    /// The priority of this subscriber relative to others.
406    pub subscriber_priority: u8,
407    /// The requested group delivery order.
408    pub group_order: GroupOrder,
409    /// The fetch type (standalone or joining).
410    pub fetch_type: FetchType,
411    /// Track namespace (standalone only).
412    pub track_namespace: Option<TrackNamespace>,
413    /// Track name (standalone only).
414    pub track_name: Option<Vec<u8>>,
415    /// Start group (standalone only).
416    pub start_group: Option<VarInt>,
417    /// Start object (standalone only).
418    pub start_object: Option<VarInt>,
419    /// End group (standalone only).
420    pub end_group: Option<VarInt>,
421    /// End object (standalone only).
422    pub end_object: Option<VarInt>,
423    /// Joining subscribe ID (joining only).
424    pub joining_subscribe_id: Option<VarInt>,
425    /// Preceding group offset (joining only).
426    pub preceding_group_offset: Option<VarInt>,
427    /// Fetch parameters.
428    pub parameters: Vec<KeyValuePair>,
429}
430
431/// FETCH_OK message (type 0x18).
432#[derive(Debug, Clone, PartialEq, Eq)]
433pub struct FetchOk {
434    /// The subscribe ID this response corresponds to.
435    pub subscribe_id: VarInt,
436    /// The group delivery order chosen by the publisher.
437    pub group_order: GroupOrder,
438    /// Whether this fetch reaches the end of the track (1 = yes).
439    pub end_of_track: u8,
440    /// The largest group ID available.
441    pub largest_group_id: VarInt,
442    /// The largest object ID available.
443    pub largest_object_id: VarInt,
444    /// Fetch OK parameters.
445    pub parameters: Vec<KeyValuePair>,
446}
447
448/// FETCH_ERROR message (type 0x19).
449#[derive(Debug, Clone, PartialEq, Eq)]
450pub struct FetchError {
451    /// The subscribe ID this error corresponds to.
452    pub subscribe_id: VarInt,
453    /// The error code indicating the reason for failure.
454    pub error_code: VarInt,
455    /// A human-readable reason for the error.
456    pub reason_phrase: Vec<u8>,
457}
458
459/// FETCH_CANCEL message (type 0x17).
460#[derive(Debug, Clone, PartialEq, Eq)]
461pub struct FetchCancel {
462    /// The subscribe ID for the fetch to cancel.
463    pub subscribe_id: VarInt,
464}
465
466// ============================================================
467// Unified Message Enum
468// ============================================================
469
470/// Read a Group Order from a message that must name a real order.
471///
472/// SUBSCRIBE_OK and FETCH_OK each say
473/// "Values of 0x0 and those larger than 0x2 are a protocol error": a responder
474/// reports the order it settled on, so deferring to the publisher is not an
475/// answer it can give. SUBSCRIBE and FETCH are the requests, and there
476/// 0x0 is exactly how a subscriber says it has no preference — "the original
477/// publisher's Group Order SHOULD be used". The two readers cannot be merged
478/// without either refusing traffic the requests permit or accepting a reply
479/// that tells the subscriber nothing.
480fn read_group_order_response(buf: &mut impl Buf) -> Result<GroupOrder, CodecError> {
481    if !buf.has_remaining() {
482        return Err(CodecError::UnexpectedEnd);
483    }
484    match GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)? {
485        GroupOrder::Publisher => Err(CodecError::InvalidField),
486        order => Ok(order),
487    }
488}
489
490/// Hold a TRACK_STATUS Status Code and the fields after it to Section 8.17.
491///
492/// "The 'Status Code' field provides additional information about the status of
493/// the track. It MUST hold one of the following values. Any other value is a
494/// malformed message." Two of those values - 0x01 and 0x02 - add "Subsequent
495/// fields MUST be zero, and any other value is a malformed message".
496///
497/// Applied on both sides. A malformed message is one this codec must not read
498/// and equally must not write: an encoder that emits an unassigned Status Code
499/// hands a conforming peer a message it is required to reject.
500fn check_track_status(
501    status_code: VarInt,
502    last_group_id: VarInt,
503    last_object_id: VarInt,
504) -> Result<(), CodecError> {
505    let code = crate::draft10::error_codes::TrackStatusCode::from_u64(status_code.into_inner())
506        .ok_or(CodecError::InvalidField)?;
507    if code.requires_zero_location()
508        && (last_group_id.into_inner() != 0 || last_object_id.into_inner() != 0)
509    {
510        return Err(CodecError::InvalidField);
511    }
512    Ok(())
513}
514
515/// Refuse a message whose optional fields disagree with the field that decides
516/// whether they are on the wire.
517///
518/// Presence is not a property of the Rust value: the decoder derives it from a
519/// Filter Type, a Content Exists flag or a Fetch Type, and reads exactly the
520/// fields that discriminator names. An encoder that instead writes whatever
521/// happens to be `Some` produces a frame its own reader refuses - short by the
522/// missing fields, so the declared length runs out mid-payload, or long by the
523/// surplus ones, so bytes are left over. Section 8 makes either a session
524/// close, which is why this refuses rather than papering over it.
525fn check_discriminators(message: &ControlMessage) -> Result<(), CodecError> {
526    match message {
527        ControlMessage::Subscribe(m) => {
528            // This draft dropped Filter Type 0x1, and the decoder refuses it.
529            if m.filter_type == FilterType::NextGroupStart {
530                return Err(CodecError::InvalidField);
531            }
532            let wants_start =
533                matches!(m.filter_type, FilterType::AbsoluteStart | FilterType::AbsoluteRange);
534            if wants_start != m.start_location.is_some() {
535                return Err(CodecError::InvalidField);
536            }
537            if (m.filter_type == FilterType::AbsoluteRange) != m.end_group.is_some() {
538                return Err(CodecError::InvalidField);
539            }
540            Ok(())
541        }
542        ControlMessage::SubscribeOk(m) => {
543            let has = m.content_exists == ContentExists::HasLargestLocation;
544            if has != m.largest_group_id.is_some() || has != m.largest_object_id.is_some() {
545                return Err(CodecError::InvalidField);
546            }
547            Ok(())
548        }
549        ControlMessage::Fetch(m) => {
550            let standalone = m.fetch_type == FetchType::Standalone;
551            let standalone_fields = [
552                m.track_namespace.is_some(),
553                m.track_name.is_some(),
554                m.start_group.is_some(),
555                m.start_object.is_some(),
556                m.end_group.is_some(),
557                m.end_object.is_some(),
558            ];
559            if standalone_fields.iter().any(|present| *present != standalone) {
560                return Err(CodecError::InvalidField);
561            }
562            let joining_fields =
563                [m.joining_subscribe_id.is_some(), m.preceding_group_offset.is_some()];
564            if joining_fields.contains(&standalone) {
565                return Err(CodecError::InvalidField);
566            }
567            Ok(())
568        }
569        _ => Ok(()),
570    }
571}
572
573/// Refuse a Group Order of 0x0 on the messages that forbid it.
574///
575/// The decoders refuse it on the way in; without this the codec would still
576/// write a frame its own reader rejects.
577fn check_group_order(message: &ControlMessage) -> Result<(), CodecError> {
578    let order = match message {
579        ControlMessage::SubscribeOk(m) => m.group_order,
580        ControlMessage::FetchOk(m) => m.group_order,
581        _ => return Ok(()),
582    };
583    if order == GroupOrder::Publisher {
584        return Err(CodecError::InvalidField);
585    }
586    Ok(())
587}
588
589/// A decoded MoQT control message (draft-10).
590#[derive(Debug, Clone, PartialEq, Eq)]
591pub enum ControlMessage {
592    /// ClientSetup (type 0x40).
593    ClientSetup(ClientSetup),
594    /// ServerSetup (type 0x41).
595    ServerSetup(ServerSetup),
596    /// GoAway (type 0x10).
597    GoAway(GoAway),
598    /// MaxSubscribeId (type 0x15).
599    MaxSubscribeId(MaxSubscribeId),
600    /// SubscribesBlocked (type 0x1A).
601    SubscribesBlocked(SubscribesBlocked),
602    /// Subscribe (type 0x03).
603    Subscribe(Subscribe),
604    /// SubscribeOk (type 0x04).
605    SubscribeOk(SubscribeOk),
606    /// SubscribeError (type 0x05).
607    SubscribeError(SubscribeError),
608    /// SubscribeUpdate (type 0x02).
609    SubscribeUpdate(SubscribeUpdate),
610    /// SubscribeDone (type 0x0B).
611    SubscribeDone(SubscribeDone),
612    /// Unsubscribe (type 0x0A).
613    Unsubscribe(Unsubscribe),
614    /// Announce (type 0x06).
615    Announce(Announce),
616    /// AnnounceOk (type 0x07).
617    AnnounceOk(AnnounceOk),
618    /// AnnounceError (type 0x08).
619    AnnounceError(AnnounceError),
620    /// AnnounceCancel (type 0x0C).
621    AnnounceCancel(AnnounceCancel),
622    /// Unannounce (type 0x09).
623    Unannounce(Unannounce),
624    /// SubscribeAnnounces (type 0x11).
625    SubscribeAnnounces(SubscribeAnnounces),
626    /// SubscribeAnnouncesOk (type 0x12).
627    SubscribeAnnouncesOk(SubscribeAnnouncesOk),
628    /// SubscribeAnnouncesError (type 0x13).
629    SubscribeAnnouncesError(SubscribeAnnouncesError),
630    /// UnsubscribeAnnounces (type 0x14).
631    UnsubscribeAnnounces(UnsubscribeAnnounces),
632    /// TrackStatusRequest (type 0x0D).
633    TrackStatusRequest(TrackStatusRequest),
634    /// TrackStatus (type 0x0E).
635    TrackStatus(TrackStatus),
636    /// Fetch (type 0x16).
637    Fetch(Fetch),
638    /// FetchOk (type 0x18).
639    FetchOk(FetchOk),
640    /// FetchError (type 0x19).
641    FetchError(FetchError),
642    /// FetchCancel (type 0x17).
643    FetchCancel(FetchCancel),
644}
645
646/// Refuse a request whose range ends before it starts.
647///
648/// SUBSCRIBE's AbsoluteRange filter (Section 8.6), SUBSCRIBE_UPDATE
649/// (Section 8.9) and FETCH (Section 8.12) each state it, and the fields
650/// are not spelled the same way in the three places: an End Group is inclusive
651/// on SUBSCRIBE and FETCH and is the last group plus one on SUBSCRIBE_UPDATE,
652/// where zero means open ended, and an End Object is the last object plus one
653/// with zero meaning the whole group. The helpers this calls carry those
654/// conventions, one per shape.
655///
656/// Applied on both sides. A range that ends before it starts selects nothing,
657/// and the peer's only recourse is an error response or a session close, so
658/// writing one is not a way to ask for anything.
659fn check_ranges(message: &ControlMessage) -> Result<(), CodecError> {
660    match message {
661        ControlMessage::Subscribe(m) => match (&m.start_location, &m.end_group) {
662            (Some(start), Some(end_group)) => {
663                check_group_range(start.group.into_inner(), end_group.into_inner())
664            }
665            _ => Ok(()),
666        },
667        ControlMessage::SubscribeUpdate(m) => {
668            check_open_ended_group_range(m.start_group.into_inner(), m.end_group.into_inner())
669        }
670        ControlMessage::Fetch(m) => {
671            match (&m.start_group, &m.start_object, &m.end_group, &m.end_object) {
672                (Some(start_group), Some(start_object), Some(end_group), Some(end_object)) => {
673                    check_location_range(
674                        start_group.into_inner(),
675                        start_object.into_inner(),
676                        end_group.into_inner(),
677                        end_object.into_inner(),
678                    )
679                }
680                _ => Ok(()),
681            }
682        }
683        _ => Ok(()),
684    }
685}
686
687/// Refuse a parameter list that names the same Parameter Type twice.
688///
689/// Section 8.1: "Senders MUST NOT repeat the same parameter type in a
690/// message. Receivers SHOULD check that there are no duplicate
691/// parameters and close the session as a 'Protocol Violation' if found."
692///
693/// Applied on both sides. Code that scans a parameter list for a key takes
694/// whichever copy it meets first, so one frame carrying two values for one type
695/// is read differently by two conforming implementations - which is what makes
696/// the sender's half a MUST NOT rather than advice.
697fn check_no_duplicate_parameters(parameters: &[KeyValuePair]) -> Result<(), CodecError> {
698    for (i, parameter) in parameters.iter().enumerate() {
699        if parameters[..i].iter().any(|earlier| earlier.key == parameter.key) {
700            return Err(CodecError::DuplicateParameter(parameter.key.into_inner()));
701        }
702    }
703    Ok(())
704}
705
706/// The setup parameters this draft describes as carrying a single integer.
707///
708/// Section 8.2.2.2 gives MAX_SUBSCRIBE_ID as "an initial value for the Maximum
709/// Subscribe ID". PATH (Section 8.2.2.1) is a URI string and carries no implied
710/// length, so it is absent; ROLE, the other varint-valued setup parameter,
711/// belongs to draft-07 and this draft does not define it.
712const SETUP_VARINT_PARAMETERS: &[u64] = &[0x02];
713
714/// The version-specific parameters this draft describes as carrying a single
715/// integer.
716///
717/// Section 8.1.1.2 gives DELIVERY TIMEOUT as "the duration in milliseconds"
718/// and Section 8.1.1.3 gives MAX CACHE DURATION as "An integer expressing a
719/// number of milliseconds". AUTHORIZATION INFO is "an ASCII string" and is
720/// absent for the same reason PATH is.
721///
722/// The two lists are not interchangeable. Setup parameters and version-specific
723/// parameters use separate namespaces, and 0x02 is MAX_SUBSCRIBE_ID in one and
724/// AUTHORIZATION INFO in the other - applying the setup list to a SUBSCRIBE
725/// would refuse every authorization string that is not accidentally a varint.
726const VERSION_VARINT_PARAMETERS: &[u64] = &[0x03, 0x04];
727
728/// Refuse a parameter whose value is not the shape its type implies.
729///
730/// Section 8.1: "If a receiver understands a parameter type, and the parameter
731/// length implied by that type does not match the Parameter Length field, the
732/// receiver MUST terminate the session with error code 'Parameter Length
733/// Mismatch'."
734///
735/// This draft frames every parameter as {Type, Length, Value} with no per-key
736/// table, so a parameter that came off the wire always arrives as bytes and its
737/// declared length is whatever the sender wrote. For a type whose definition
738/// says the value is one integer, the implied length is that varint's own
739/// length, and the two agree only when the value is exactly one varint with
740/// nothing after it.
741///
742/// A value already held as a varint is not checked: [`KeyValuePair::encode_d07`]
743/// derives its length field from the varint it is about to write, so those two
744/// cannot disagree. Only bytes can.
745fn check_parameter_lengths(
746    parameters: &[KeyValuePair],
747    varint_typed: &[u64],
748) -> Result<(), CodecError> {
749    for parameter in parameters {
750        let key = parameter.key.into_inner();
751        if !varint_typed.contains(&key) {
752            continue;
753        }
754        if let crate::kvp::KvpValue::Bytes(bytes) = &parameter.value {
755            let mut cursor = &bytes[..];
756            let one_varint = VarInt::decode(&mut cursor).is_ok() && !cursor.has_remaining();
757            if !one_varint {
758                return Err(CodecError::ParameterLengthMismatch(key));
759            }
760        }
761    }
762    Ok(())
763}
764
765/// Decode a version-specific parameter list, refusing a repeated type and a
766/// value whose length disagrees with its type.
767fn decode_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
768    let parameters = KeyValuePair::decode_list_d07(buf)?;
769    check_no_duplicate_parameters(&parameters)?;
770    check_parameter_lengths(&parameters, VERSION_VARINT_PARAMETERS)?;
771    Ok(parameters)
772}
773
774/// Encode a version-specific parameter list, refusing a repeated type and a
775/// value whose length disagrees with its type.
776fn encode_parameters(parameters: &[KeyValuePair], buf: &mut impl BufMut) -> Result<(), CodecError> {
777    check_no_duplicate_parameters(parameters)?;
778    check_parameter_lengths(parameters, VERSION_VARINT_PARAMETERS)?;
779    KeyValuePair::encode_list_d07(parameters, buf);
780    Ok(())
781}
782
783/// Decode a setup parameter list.
784///
785/// Setup parameters use a namespace of their own, so the same key number means
786/// something different here than it does in every other message and the implied
787/// lengths are read from a different list.
788fn decode_setup_parameters(buf: &mut impl Buf) -> Result<Vec<KeyValuePair>, CodecError> {
789    let parameters = KeyValuePair::decode_list_d07(buf)?;
790    check_no_duplicate_parameters(&parameters)?;
791    check_parameter_lengths(&parameters, SETUP_VARINT_PARAMETERS)?;
792    Ok(parameters)
793}
794
795/// Encode a setup parameter list, under the setup namespace's implied lengths.
796fn encode_setup_parameters(
797    parameters: &[KeyValuePair],
798    buf: &mut impl BufMut,
799) -> Result<(), CodecError> {
800    check_no_duplicate_parameters(parameters)?;
801    check_parameter_lengths(parameters, SETUP_VARINT_PARAMETERS)?;
802    KeyValuePair::encode_list_d07(parameters, buf);
803    Ok(())
804}
805
806impl ControlMessage {
807    /// Return the message type for this control message.
808    pub fn message_type(&self) -> MessageType {
809        match self {
810            ControlMessage::ClientSetup(_) => MessageType::ClientSetup,
811            ControlMessage::ServerSetup(_) => MessageType::ServerSetup,
812            ControlMessage::GoAway(_) => MessageType::GoAway,
813            ControlMessage::MaxSubscribeId(_) => MessageType::MaxSubscribeId,
814            ControlMessage::SubscribesBlocked(_) => MessageType::SubscribesBlocked,
815            ControlMessage::Subscribe(_) => MessageType::Subscribe,
816            ControlMessage::SubscribeOk(_) => MessageType::SubscribeOk,
817            ControlMessage::SubscribeError(_) => MessageType::SubscribeError,
818            ControlMessage::SubscribeUpdate(_) => MessageType::SubscribeUpdate,
819            ControlMessage::SubscribeDone(_) => MessageType::SubscribeDone,
820            ControlMessage::Unsubscribe(_) => MessageType::Unsubscribe,
821            ControlMessage::Announce(_) => MessageType::Announce,
822            ControlMessage::AnnounceOk(_) => MessageType::AnnounceOk,
823            ControlMessage::AnnounceError(_) => MessageType::AnnounceError,
824            ControlMessage::AnnounceCancel(_) => MessageType::AnnounceCancel,
825            ControlMessage::Unannounce(_) => MessageType::Unannounce,
826            ControlMessage::SubscribeAnnounces(_) => MessageType::SubscribeAnnounces,
827            ControlMessage::SubscribeAnnouncesOk(_) => MessageType::SubscribeAnnouncesOk,
828            ControlMessage::SubscribeAnnouncesError(_) => MessageType::SubscribeAnnouncesError,
829            ControlMessage::UnsubscribeAnnounces(_) => MessageType::UnsubscribeAnnounces,
830            ControlMessage::TrackStatusRequest(_) => MessageType::TrackStatusRequest,
831            ControlMessage::TrackStatus(_) => MessageType::TrackStatus,
832            ControlMessage::Fetch(_) => MessageType::Fetch,
833            ControlMessage::FetchOk(_) => MessageType::FetchOk,
834            ControlMessage::FetchError(_) => MessageType::FetchError,
835            ControlMessage::FetchCancel(_) => MessageType::FetchCancel,
836        }
837    }
838
839    /// Encode this control message (type ID + length prefix + payload).
840    pub fn encode(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
841        check_discriminators(self)?;
842        check_group_order(self)?;
843        check_ranges(self)?;
844        let mut payload = Vec::with_capacity(256);
845        self.encode_payload(&mut payload)?;
846
847        // No cap here. This draft frames a control message with a varint
848        // Length and states no maximum, and this module's own decoder applies
849        // none either - a ceiling on encode would refuse to write a message
850        // this codec will read. The 65,535-byte limit belongs to draft-11 and
851        // later, where the Length field is 16 bits wide and the limit is a
852        // consequence of the framing.
853
854        VarInt::from_usize(self.message_type().id() as usize).encode(buf);
855        VarInt::from_usize(payload.len()).encode(buf);
856        buf.put_slice(&payload);
857        Ok(())
858    }
859
860    /// Decode a control message from bytes.
861    pub fn decode(buf: &mut impl Buf) -> Result<Self, CodecError> {
862        let type_id = VarInt::decode(buf)?.into_inner();
863        let msg_type =
864            MessageType::from_id(type_id).ok_or(CodecError::UnknownMessageType(type_id))?;
865        let payload_len = VarInt::decode(buf)?.into_inner() as usize;
866        if buf.remaining() < payload_len {
867            return Err(CodecError::UnexpectedEnd);
868        }
869        let payload_bytes = buf.copy_to_bytes(payload_len);
870        let mut payload = &payload_bytes[..];
871        let msg = match Self::decode_payload(msg_type, &mut payload) {
872            Ok(msg) => msg,
873            // The fields wanted more bytes than the Length allowed. This buffer
874            // is already bounded by that Length, so running out inside it cannot
875            // mean the message is still arriving - which is what the same error
876            // means everywhere else, and why a reader loops on it rather than
877            // closing. Here there is nothing left to arrive.
878            Err(
879                CodecError::UnexpectedEnd
880                | CodecError::Kvp(crate::kvp::KvpError::UnexpectedEnd)
881                | CodecError::Kvp(crate::kvp::KvpError::VarInt(
882                    crate::varint::VarIntError::UnexpectedEnd,
883                ))
884                | CodecError::VarInt(crate::varint::VarIntError::UnexpectedEnd),
885            ) => {
886                return Err(CodecError::ControlMessageLengthMismatch {
887                    declared: payload_len,
888                    detail: "its fields ran past the end",
889                });
890            }
891            Err(e) => return Err(e),
892        };
893        check_ranges(&msg)?;
894        // The declared length is part of the message, not a hint. Bytes left over
895        // after the fields have been read mean the sender and this reader disagree
896        // about the shape of the message, and guessing which of the two is right
897        // is how a trailing field gets silently dropped.
898        if payload.has_remaining() {
899            return Err(CodecError::ControlMessageLengthMismatch {
900                declared: payload_len,
901                detail: "its fields left bytes unread",
902            });
903        }
904        Ok(msg)
905    }
906
907    fn encode_payload(&self, buf: &mut impl BufMut) -> Result<(), CodecError> {
908        match self {
909            ControlMessage::ClientSetup(m) => {
910                VarInt::from_usize(m.supported_versions.len()).encode(buf);
911                for v in &m.supported_versions {
912                    v.encode(buf);
913                }
914                encode_setup_parameters(&m.parameters, buf)?;
915            }
916            ControlMessage::ServerSetup(m) => {
917                m.selected_version.encode(buf);
918                encode_setup_parameters(&m.parameters, buf)?;
919            }
920            ControlMessage::GoAway(m) => {
921                VarInt::from_usize(m.new_session_uri.len()).encode(buf);
922                buf.put_slice(&m.new_session_uri);
923            }
924            ControlMessage::MaxSubscribeId(m) => {
925                m.subscribe_id.encode(buf);
926            }
927            ControlMessage::SubscribesBlocked(m) => {
928                m.maximum_subscribe_id.encode(buf);
929            }
930            ControlMessage::Subscribe(m) => {
931                m.subscribe_id.encode(buf);
932                m.track_alias.encode(buf);
933                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
934                m.track_namespace.encode(buf);
935                VarInt::from_usize(m.track_name.len()).encode(buf);
936                buf.put_slice(&m.track_name);
937                buf.put_u8(m.subscriber_priority);
938                buf.put_u8(m.group_order as u8);
939                VarInt::from_usize(m.filter_type as usize).encode(buf);
940                if let Some(loc) = &m.start_location {
941                    loc.encode(buf);
942                }
943                if let Some(eg) = &m.end_group {
944                    eg.encode(buf);
945                }
946                encode_parameters(&m.parameters, buf)?;
947            }
948            ControlMessage::SubscribeOk(m) => {
949                m.subscribe_id.encode(buf);
950                m.expires.encode(buf);
951                buf.put_u8(m.group_order as u8);
952                buf.put_u8(m.content_exists as u8);
953                if let Some(gid) = &m.largest_group_id {
954                    gid.encode(buf);
955                }
956                if let Some(oid) = &m.largest_object_id {
957                    oid.encode(buf);
958                }
959                encode_parameters(&m.parameters, buf)?;
960            }
961            ControlMessage::SubscribeError(m) => {
962                m.subscribe_id.encode(buf);
963                m.error_code.encode(buf);
964                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
965                buf.put_slice(&m.reason_phrase);
966                m.track_alias.encode(buf);
967            }
968            ControlMessage::SubscribeUpdate(m) => {
969                m.subscribe_id.encode(buf);
970                m.start_group.encode(buf);
971                m.start_object.encode(buf);
972                m.end_group.encode(buf);
973                buf.put_u8(m.subscriber_priority);
974                encode_parameters(&m.parameters, buf)?;
975            }
976            ControlMessage::SubscribeDone(m) => {
977                m.subscribe_id.encode(buf);
978                m.status_code.encode(buf);
979                m.stream_count.encode(buf);
980                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
981                buf.put_slice(&m.reason_phrase);
982            }
983            ControlMessage::Unsubscribe(m) => {
984                m.subscribe_id.encode(buf);
985            }
986            ControlMessage::Announce(m) => {
987                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
988                m.track_namespace.encode(buf);
989                encode_parameters(&m.parameters, buf)?;
990            }
991            ControlMessage::AnnounceOk(m) => {
992                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
993                m.track_namespace.encode(buf);
994            }
995            ControlMessage::AnnounceError(m) => {
996                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
997                m.track_namespace.encode(buf);
998                m.error_code.encode(buf);
999                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1000                buf.put_slice(&m.reason_phrase);
1001            }
1002            ControlMessage::AnnounceCancel(m) => {
1003                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
1004                m.track_namespace.encode(buf);
1005                m.error_code.encode(buf);
1006                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1007                buf.put_slice(&m.reason_phrase);
1008            }
1009            ControlMessage::Unannounce(m) => {
1010                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
1011                m.track_namespace.encode(buf);
1012            }
1013            ControlMessage::SubscribeAnnounces(m) => {
1014                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(10))?;
1015                m.track_namespace_prefix.encode(buf);
1016                encode_parameters(&m.parameters, buf)?;
1017            }
1018            ControlMessage::SubscribeAnnouncesOk(m) => {
1019                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(10))?;
1020                m.track_namespace_prefix.encode(buf);
1021            }
1022            ControlMessage::SubscribeAnnouncesError(m) => {
1023                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(10))?;
1024                m.track_namespace_prefix.encode(buf);
1025                m.error_code.encode(buf);
1026                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1027                buf.put_slice(&m.reason_phrase);
1028            }
1029            ControlMessage::UnsubscribeAnnounces(m) => {
1030                m.track_namespace_prefix.validate(TrackNamespaceRules::for_draft(10))?;
1031                m.track_namespace_prefix.encode(buf);
1032            }
1033            ControlMessage::TrackStatusRequest(m) => {
1034                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
1035                m.track_namespace.encode(buf);
1036                VarInt::from_usize(m.track_name.len()).encode(buf);
1037                buf.put_slice(&m.track_name);
1038            }
1039            ControlMessage::TrackStatus(m) => {
1040                m.track_namespace.validate(TrackNamespaceRules::for_draft(10))?;
1041                m.track_namespace.encode(buf);
1042                VarInt::from_usize(m.track_name.len()).encode(buf);
1043                buf.put_slice(&m.track_name);
1044                check_track_status(m.status_code, m.last_group_id, m.last_object_id)?;
1045                m.status_code.encode(buf);
1046                m.last_group_id.encode(buf);
1047                m.last_object_id.encode(buf);
1048            }
1049            ControlMessage::Fetch(m) => {
1050                m.subscribe_id.encode(buf);
1051                buf.put_u8(m.subscriber_priority);
1052                buf.put_u8(m.group_order as u8);
1053                VarInt::from_usize(m.fetch_type as usize).encode(buf);
1054                match m.fetch_type {
1055                    FetchType::Standalone => {
1056                        if let Some(ns) = &m.track_namespace {
1057                            ns.encode(buf);
1058                        }
1059                        if let Some(name) = &m.track_name {
1060                            VarInt::from_usize(name.len()).encode(buf);
1061                            buf.put_slice(name);
1062                        }
1063                        if let Some(sg) = &m.start_group {
1064                            sg.encode(buf);
1065                        }
1066                        if let Some(so) = &m.start_object {
1067                            so.encode(buf);
1068                        }
1069                        if let Some(eg) = &m.end_group {
1070                            eg.encode(buf);
1071                        }
1072                        if let Some(eo) = &m.end_object {
1073                            eo.encode(buf);
1074                        }
1075                    }
1076                    FetchType::Joining => {
1077                        if let Some(jsi) = &m.joining_subscribe_id {
1078                            jsi.encode(buf);
1079                        }
1080                        if let Some(pgo) = &m.preceding_group_offset {
1081                            pgo.encode(buf);
1082                        }
1083                    }
1084                }
1085                encode_parameters(&m.parameters, buf)?;
1086            }
1087            ControlMessage::FetchOk(m) => {
1088                m.subscribe_id.encode(buf);
1089                buf.put_u8(m.group_order as u8);
1090                buf.put_u8(m.end_of_track);
1091                m.largest_group_id.encode(buf);
1092                m.largest_object_id.encode(buf);
1093                encode_parameters(&m.parameters, buf)?;
1094            }
1095            ControlMessage::FetchError(m) => {
1096                m.subscribe_id.encode(buf);
1097                m.error_code.encode(buf);
1098                VarInt::from_usize(m.reason_phrase.len()).encode(buf);
1099                buf.put_slice(&m.reason_phrase);
1100            }
1101            ControlMessage::FetchCancel(m) => {
1102                m.subscribe_id.encode(buf);
1103            }
1104        }
1105        Ok(())
1106    }
1107
1108    fn decode_payload(msg_type: MessageType, buf: &mut impl Buf) -> Result<Self, CodecError> {
1109        match msg_type {
1110            MessageType::ClientSetup => {
1111                let num_versions = VarInt::decode(buf)?.into_inner() as usize;
1112                // Not a rule this draft states. It says only that the server
1113                // "MUST reply with one of the versions offered by the client"
1114                // and that a peer with no version in common "MUST close the
1115                // session" - outcomes of negotiation rather than parse errors,
1116                // and a CLIENT_SETUP offering nothing decodes cleanly under the
1117                // figure. It is refused here because there is no version a
1118                // reply could name, so the session is already over and the
1119                // early close is the more useful answer than a well-formed
1120                // message no caller can act on.
1121                if num_versions == 0 {
1122                    return Err(CodecError::InvalidField);
1123                }
1124                let mut supported_versions = crate::types::reserve_bounded(num_versions, buf);
1125                for _ in 0..num_versions {
1126                    supported_versions.push(VarInt::decode(buf)?);
1127                }
1128                let parameters = decode_setup_parameters(buf)?;
1129                Ok(ControlMessage::ClientSetup(ClientSetup { supported_versions, parameters }))
1130            }
1131            MessageType::ServerSetup => {
1132                let selected_version = VarInt::decode(buf)?;
1133                let parameters = decode_setup_parameters(buf)?;
1134                Ok(ControlMessage::ServerSetup(ServerSetup { selected_version, parameters }))
1135            }
1136            MessageType::GoAway => {
1137                let uri_len = VarInt::decode(buf)?.into_inner() as usize;
1138                let uri = read_bytes(buf, uri_len)?;
1139                Ok(ControlMessage::GoAway(GoAway { new_session_uri: uri }))
1140            }
1141            MessageType::MaxSubscribeId => {
1142                let subscribe_id = VarInt::decode(buf)?;
1143                Ok(ControlMessage::MaxSubscribeId(MaxSubscribeId { subscribe_id }))
1144            }
1145            MessageType::SubscribesBlocked => {
1146                let maximum_subscribe_id = VarInt::decode(buf)?;
1147                Ok(ControlMessage::SubscribesBlocked(SubscribesBlocked { maximum_subscribe_id }))
1148            }
1149            MessageType::Subscribe => {
1150                let subscribe_id = VarInt::decode(buf)?;
1151                let track_alias = VarInt::decode(buf)?;
1152                let track_namespace = TrackNamespace::decode(buf)?;
1153                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1154                let track_name = read_bytes(buf, track_name_len)?;
1155                if buf.remaining() < 2 {
1156                    return Err(CodecError::UnexpectedEnd);
1157                }
1158                let subscriber_priority = buf.get_u8();
1159                let group_order =
1160                    GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)?;
1161                let filter_val = VarInt::decode(buf)?.into_inner();
1162                // Filter Type 0x1 (NextGroupStart/LatestGroup) is not a value
1163                // this draft assigns.
1164                if filter_val == 1 {
1165                    return Err(CodecError::InvalidFilterType(filter_val));
1166                }
1167                let filter_type = FilterType::from_u64(filter_val)
1168                    .ok_or(CodecError::InvalidFilterType(filter_val))?;
1169                let start_location = match filter_type {
1170                    FilterType::AbsoluteStart | FilterType::AbsoluteRange => {
1171                        Some(Location::decode(buf)?)
1172                    }
1173                    _ => None,
1174                };
1175                let end_group = match filter_type {
1176                    FilterType::AbsoluteRange => Some(VarInt::decode(buf)?),
1177                    _ => None,
1178                };
1179                let parameters = decode_parameters(buf)?;
1180                Ok(ControlMessage::Subscribe(Subscribe {
1181                    subscribe_id,
1182                    track_alias,
1183                    track_namespace,
1184                    track_name,
1185                    subscriber_priority,
1186                    group_order,
1187                    filter_type,
1188                    start_location,
1189                    end_group,
1190                    parameters,
1191                }))
1192            }
1193            MessageType::SubscribeOk => {
1194                let subscribe_id = VarInt::decode(buf)?;
1195                let expires = VarInt::decode(buf)?;
1196                if buf.remaining() < 2 {
1197                    return Err(CodecError::UnexpectedEnd);
1198                }
1199                let group_order = read_group_order_response(buf)?;
1200                let content_exists_val = buf.get_u8();
1201                let content_exists = match content_exists_val {
1202                    0 => ContentExists::NoLargestLocation,
1203                    1 => ContentExists::HasLargestLocation,
1204                    other => return Err(CodecError::InvalidContentExists(other)),
1205                };
1206                let (largest_group_id, largest_object_id) =
1207                    if content_exists == ContentExists::HasLargestLocation {
1208                        let gid = VarInt::decode(buf)?;
1209                        let oid = VarInt::decode(buf)?;
1210                        (Some(gid), Some(oid))
1211                    } else {
1212                        (None, None)
1213                    };
1214                let parameters = decode_parameters(buf)?;
1215                Ok(ControlMessage::SubscribeOk(SubscribeOk {
1216                    subscribe_id,
1217                    expires,
1218                    group_order,
1219                    content_exists,
1220                    largest_group_id,
1221                    largest_object_id,
1222                    parameters,
1223                }))
1224            }
1225            MessageType::SubscribeError => {
1226                let subscribe_id = VarInt::decode(buf)?;
1227                let error_code = VarInt::decode(buf)?;
1228                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1229                let reason_phrase = read_bytes(buf, reason_len)?;
1230                let track_alias = VarInt::decode(buf)?;
1231                Ok(ControlMessage::SubscribeError(SubscribeError {
1232                    subscribe_id,
1233                    error_code,
1234                    reason_phrase,
1235                    track_alias,
1236                }))
1237            }
1238            MessageType::SubscribeUpdate => {
1239                let subscribe_id = VarInt::decode(buf)?;
1240                let start_group = VarInt::decode(buf)?;
1241                let start_object = VarInt::decode(buf)?;
1242                let end_group = VarInt::decode(buf)?;
1243                if buf.remaining() < 1 {
1244                    return Err(CodecError::UnexpectedEnd);
1245                }
1246                let subscriber_priority = buf.get_u8();
1247                let parameters = decode_parameters(buf)?;
1248                Ok(ControlMessage::SubscribeUpdate(SubscribeUpdate {
1249                    subscribe_id,
1250                    start_group,
1251                    start_object,
1252                    end_group,
1253                    subscriber_priority,
1254                    parameters,
1255                }))
1256            }
1257            MessageType::SubscribeDone => {
1258                let subscribe_id = VarInt::decode(buf)?;
1259                let status_code = VarInt::decode(buf)?;
1260                let stream_count = VarInt::decode(buf)?;
1261                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1262                let reason_phrase = read_bytes(buf, reason_len)?;
1263                Ok(ControlMessage::SubscribeDone(SubscribeDone {
1264                    subscribe_id,
1265                    status_code,
1266                    stream_count,
1267                    reason_phrase,
1268                }))
1269            }
1270            MessageType::Unsubscribe => {
1271                let subscribe_id = VarInt::decode(buf)?;
1272                Ok(ControlMessage::Unsubscribe(Unsubscribe { subscribe_id }))
1273            }
1274            MessageType::Announce => {
1275                let track_namespace = TrackNamespace::decode(buf)?;
1276                let parameters = decode_parameters(buf)?;
1277                Ok(ControlMessage::Announce(Announce { track_namespace, parameters }))
1278            }
1279            MessageType::AnnounceOk => {
1280                let track_namespace = TrackNamespace::decode(buf)?;
1281                Ok(ControlMessage::AnnounceOk(AnnounceOk { track_namespace }))
1282            }
1283            MessageType::AnnounceError => {
1284                let track_namespace = TrackNamespace::decode(buf)?;
1285                let error_code = VarInt::decode(buf)?;
1286                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1287                let reason_phrase = read_bytes(buf, reason_len)?;
1288                Ok(ControlMessage::AnnounceError(AnnounceError {
1289                    track_namespace,
1290                    error_code,
1291                    reason_phrase,
1292                }))
1293            }
1294            MessageType::AnnounceCancel => {
1295                let track_namespace = TrackNamespace::decode(buf)?;
1296                let error_code = VarInt::decode(buf)?;
1297                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1298                let reason_phrase = read_bytes(buf, reason_len)?;
1299                Ok(ControlMessage::AnnounceCancel(AnnounceCancel {
1300                    track_namespace,
1301                    error_code,
1302                    reason_phrase,
1303                }))
1304            }
1305            MessageType::Unannounce => {
1306                let track_namespace = TrackNamespace::decode(buf)?;
1307                Ok(ControlMessage::Unannounce(Unannounce { track_namespace }))
1308            }
1309            MessageType::SubscribeAnnounces => {
1310                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1311                let parameters = decode_parameters(buf)?;
1312                Ok(ControlMessage::SubscribeAnnounces(SubscribeAnnounces {
1313                    track_namespace_prefix,
1314                    parameters,
1315                }))
1316            }
1317            MessageType::SubscribeAnnouncesOk => {
1318                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1319                Ok(ControlMessage::SubscribeAnnouncesOk(SubscribeAnnouncesOk {
1320                    track_namespace_prefix,
1321                }))
1322            }
1323            MessageType::SubscribeAnnouncesError => {
1324                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1325                let error_code = VarInt::decode(buf)?;
1326                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1327                let reason_phrase = read_bytes(buf, reason_len)?;
1328                Ok(ControlMessage::SubscribeAnnouncesError(SubscribeAnnouncesError {
1329                    track_namespace_prefix,
1330                    error_code,
1331                    reason_phrase,
1332                }))
1333            }
1334            MessageType::UnsubscribeAnnounces => {
1335                let track_namespace_prefix = TrackNamespace::decode(buf)?;
1336                Ok(ControlMessage::UnsubscribeAnnounces(UnsubscribeAnnounces {
1337                    track_namespace_prefix,
1338                }))
1339            }
1340            MessageType::TrackStatusRequest => {
1341                let track_namespace = TrackNamespace::decode(buf)?;
1342                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1343                let track_name = read_bytes(buf, track_name_len)?;
1344                Ok(ControlMessage::TrackStatusRequest(TrackStatusRequest {
1345                    track_namespace,
1346                    track_name,
1347                }))
1348            }
1349            MessageType::TrackStatus => {
1350                let track_namespace = TrackNamespace::decode(buf)?;
1351                let track_name_len = VarInt::decode(buf)?.into_inner() as usize;
1352                let track_name = read_bytes(buf, track_name_len)?;
1353                let status_code = VarInt::decode(buf)?;
1354                let last_group_id = VarInt::decode(buf)?;
1355                let last_object_id = VarInt::decode(buf)?;
1356                check_track_status(status_code, last_group_id, last_object_id)?;
1357                Ok(ControlMessage::TrackStatus(TrackStatus {
1358                    track_namespace,
1359                    track_name,
1360                    status_code,
1361                    last_group_id,
1362                    last_object_id,
1363                }))
1364            }
1365            MessageType::Fetch => {
1366                let subscribe_id = VarInt::decode(buf)?;
1367                if buf.remaining() < 2 {
1368                    return Err(CodecError::UnexpectedEnd);
1369                }
1370                let subscriber_priority = buf.get_u8();
1371                let group_order =
1372                    GroupOrder::from_u8(buf.get_u8()).ok_or(CodecError::InvalidField)?;
1373                let fetch_type_val = VarInt::decode(buf)?.into_inner();
1374                let fetch_type = FetchType::from_u64(fetch_type_val)
1375                    .ok_or(CodecError::InvalidFetchType(fetch_type_val))?;
1376                let (
1377                    track_namespace,
1378                    track_name,
1379                    start_group,
1380                    start_object,
1381                    end_group,
1382                    end_object,
1383                    joining_subscribe_id,
1384                    preceding_group_offset,
1385                ) = match fetch_type {
1386                    FetchType::Standalone => {
1387                        let ns = TrackNamespace::decode(buf)?;
1388                        let name_len = VarInt::decode(buf)?.into_inner() as usize;
1389                        let name = read_bytes(buf, name_len)?;
1390                        let sg = VarInt::decode(buf)?;
1391                        let so = VarInt::decode(buf)?;
1392                        let eg = VarInt::decode(buf)?;
1393                        let eo = VarInt::decode(buf)?;
1394                        (Some(ns), Some(name), Some(sg), Some(so), Some(eg), Some(eo), None, None)
1395                    }
1396                    FetchType::Joining => {
1397                        let jsi = VarInt::decode(buf)?;
1398                        let pgo = VarInt::decode(buf)?;
1399                        (None, None, None, None, None, None, Some(jsi), Some(pgo))
1400                    }
1401                };
1402                let parameters = decode_parameters(buf)?;
1403                Ok(ControlMessage::Fetch(Fetch {
1404                    subscribe_id,
1405                    subscriber_priority,
1406                    group_order,
1407                    fetch_type,
1408                    track_namespace,
1409                    track_name,
1410                    start_group,
1411                    start_object,
1412                    end_group,
1413                    end_object,
1414                    joining_subscribe_id,
1415                    preceding_group_offset,
1416                    parameters,
1417                }))
1418            }
1419            MessageType::FetchOk => {
1420                let subscribe_id = VarInt::decode(buf)?;
1421                if buf.remaining() < 2 {
1422                    return Err(CodecError::UnexpectedEnd);
1423                }
1424                let group_order = read_group_order_response(buf)?;
1425                let end_of_track = buf.get_u8();
1426                let largest_group_id = VarInt::decode(buf)?;
1427                let largest_object_id = VarInt::decode(buf)?;
1428                let parameters = decode_parameters(buf)?;
1429                Ok(ControlMessage::FetchOk(FetchOk {
1430                    subscribe_id,
1431                    group_order,
1432                    end_of_track,
1433                    largest_group_id,
1434                    largest_object_id,
1435                    parameters,
1436                }))
1437            }
1438            MessageType::FetchError => {
1439                let subscribe_id = VarInt::decode(buf)?;
1440                let error_code = VarInt::decode(buf)?;
1441                let reason_len = VarInt::decode(buf)?.into_inner() as usize;
1442                let reason_phrase = read_bytes(buf, reason_len)?;
1443                Ok(ControlMessage::FetchError(FetchError {
1444                    subscribe_id,
1445                    error_code,
1446                    reason_phrase,
1447                }))
1448            }
1449            MessageType::FetchCancel => {
1450                let subscribe_id = VarInt::decode(buf)?;
1451                Ok(ControlMessage::FetchCancel(FetchCancel { subscribe_id }))
1452            }
1453        }
1454    }
1455}