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