Skip to main content

moqtap_codec/draft07/
message.rs

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