Skip to main content

moqtap_codec/draft09/
message.rs

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