Skip to main content

moqtap_codec/draft10/
message.rs

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