Skip to main content

moqtap_codec/draft08/
message.rs

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