(&self) -> Result {
62 | P::decode(&mut bytes::Bytes::from(self.value.clone()))
63 | }
64 | }
65 |
66 | /// Tuple
67 | #[derive(Clone, Debug, Default)]
68 | pub struct Tuple {
69 | pub fields: Vec,
70 | }
71 |
72 | impl Hash for Tuple {
73 | fn hash(&self, state: &mut H) {
74 | self.fields.hash(state);
75 | }
76 | }
77 |
78 | impl Eq for Tuple {}
79 |
80 | impl PartialEq for Tuple {
81 | fn eq(&self, other: &Self) -> bool {
82 | self.fields.eq(&other.fields)
83 | }
84 | }
85 |
86 | impl Decode for Tuple {
87 | fn decode(r: &mut R) -> Result {
88 | let count = u64::decode(r)? as usize;
89 | let mut fields = Vec::new();
90 | for _ in 0..count {
91 | fields.push(TupleField::decode(r)?);
92 | }
93 | Ok(Self { fields })
94 | }
95 | }
96 |
97 | impl Encode for Tuple {
98 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
99 | self.fields.len().encode(w)?;
100 | for field in &self.fields {
101 | field.encode(w)?;
102 | }
103 | Ok(())
104 | }
105 | }
106 |
107 | impl Tuple {
108 | pub fn new() -> Self {
109 | Self::default()
110 | }
111 |
112 | pub fn add(&mut self, field: TupleField) {
113 | self.fields.push(field);
114 | }
115 |
116 | pub fn get(&self, index: usize) -> Result {
117 | self.fields[index].get()
118 | }
119 |
120 | pub fn set(&mut self, index: usize, f: TupleField) -> Result<(), EncodeError> {
121 | self.fields[index].set(f)
122 | }
123 |
124 | pub fn clear(&mut self) {
125 | self.fields.clear();
126 | }
127 |
128 | pub fn from_utf8_path(path: &str) -> Self {
129 | let mut tuple = Tuple::new();
130 | for part in path.split('/') {
131 | tuple.add(TupleField::from_utf8(part));
132 | }
133 | tuple
134 | }
135 |
136 | pub fn to_utf8_path(&self) -> String {
137 | let mut path = String::new();
138 | for field in &self.fields {
139 | path.push('/');
140 | path.push_str(&String::from_utf8_lossy(&field.value));
141 | }
142 | path
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/moq-transport/src/data/datagram.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 | use crate::data::ObjectStatus;
3 |
4 | #[derive(Clone, Debug)]
5 | pub struct Datagram {
6 | // The subscribe ID.
7 | pub subscribe_id: u64,
8 |
9 | // The track alias.
10 | pub track_alias: u64,
11 |
12 | // The sequence number within the track.
13 | pub group_id: u64,
14 |
15 | // The object ID within the group.
16 | pub object_id: u64,
17 |
18 | // Publisher priority, where **smaller** values are sent first.
19 | pub publisher_priority: u8,
20 |
21 | // Object status
22 | pub object_status: ObjectStatus,
23 |
24 | // The payload length.
25 | pub payload_len: u64,
26 |
27 | // The payload.
28 | pub payload: bytes::Bytes,
29 | }
30 |
31 | impl Decode for Datagram {
32 | fn decode(r: &mut R) -> Result {
33 | let subscribe_id = u64::decode(r)?;
34 | let track_alias = u64::decode(r)?;
35 | let group_id = u64::decode(r)?;
36 | let object_id = u64::decode(r)?;
37 | let publisher_priority = u8::decode(r)?;
38 | let object_status = ObjectStatus::decode(r)?;
39 | let payload_len = u64::decode(r)?;
40 | if payload_len != r.remaining() as u64 {
41 | return Err(DecodeError::InvalidLength(
42 | payload_len as usize,
43 | r.remaining(),
44 | ));
45 | }
46 | let payload = r.copy_to_bytes(r.remaining());
47 |
48 | Ok(Self {
49 | subscribe_id,
50 | track_alias,
51 | group_id,
52 | object_id,
53 | publisher_priority,
54 | object_status,
55 | payload_len,
56 | payload,
57 | })
58 | }
59 | }
60 |
61 | impl Encode for Datagram {
62 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
63 | self.subscribe_id.encode(w)?;
64 | self.track_alias.encode(w)?;
65 | self.group_id.encode(w)?;
66 | self.object_id.encode(w)?;
67 | self.publisher_priority.encode(w)?;
68 | self.object_status.encode(w)?;
69 | self.payload_len.encode(w)?;
70 | Self::encode_remaining(w, self.payload.len())?;
71 | w.put_slice(&self.payload);
72 |
73 | Ok(())
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/moq-transport/src/data/header.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 | use paste::paste;
3 | use std::fmt;
4 |
5 | use super::{SubgroupHeader, TrackHeader};
6 |
7 | // Use a macro to generate the message types rather than copy-paste.
8 | // This implements a decode/encode method that uses the specified type.
9 | macro_rules! header_types {
10 | {$($name:ident = $val:expr,)*} => {
11 | /// All supported message types.
12 | #[derive(Clone)]
13 | pub enum Header {
14 | $($name(paste! { [<$name Header>] })),*
15 | }
16 |
17 | impl Decode for Header {
18 | fn decode(r: &mut R) -> Result {
19 | let t = u64::decode(r)?;
20 |
21 | match t {
22 | $($val => {
23 | let msg = ] }>::decode(r)?;
24 | Ok(Self::$name(msg))
25 | })*
26 | _ => Err(DecodeError::InvalidMessage(t)),
27 | }
28 | }
29 | }
30 |
31 | impl Encode for Header {
32 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
33 | match self {
34 | $(Self::$name(ref m) => {
35 | self.id().encode(w)?;
36 | m.encode(w)
37 | },)*
38 | }
39 | }
40 | }
41 |
42 | impl Header {
43 | pub fn id(&self) -> u64 {
44 | match self {
45 | $(Self::$name(_) => {
46 | $val
47 | },)*
48 | }
49 | }
50 |
51 | pub fn subscribe_id(&self) -> u64 {
52 | match self {
53 | $(Self::$name(o) => o.subscribe_id,)*
54 | }
55 | }
56 |
57 | pub fn track_alias(&self) -> u64 {
58 | match self {
59 | $(Self::$name(o) => o.track_alias,)*
60 | }
61 | }
62 |
63 | pub fn publisher_priority(&self) -> u8 {
64 | match self {
65 | $(Self::$name(o) => o.publisher_priority,)*
66 | }
67 | }
68 | }
69 |
70 | $(impl From] }> for Header {
71 | fn from(m: paste! { [<$name Header>] }) -> Self {
72 | Self::$name(m)
73 | }
74 | })*
75 |
76 | impl fmt::Debug for Header {
77 | // Delegate to the message formatter
78 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 | match self {
80 | $(Self::$name(ref m) => m.fmt(f),)*
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
87 | // Each stream type is prefixed with the given VarInt type.
88 | // https://www.ietf.org/archive/id/draft-ietf-moq-transport-06.html#section-7
89 | header_types! {
90 | //Datagram = 0x1,
91 | Track = 0x2,
92 | Subgroup = 0x4,
93 | }
94 |
--------------------------------------------------------------------------------
/moq-transport/src/data/mod.rs:
--------------------------------------------------------------------------------
1 | mod datagram;
2 | mod header;
3 | mod object;
4 | mod subgroup;
5 | mod track;
6 |
7 | pub use datagram::*;
8 | pub use header::*;
9 | pub use object::*;
10 | pub use subgroup::*;
11 | pub use track::*;
12 |
--------------------------------------------------------------------------------
/moq-transport/src/data/object.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | #[derive(Clone, Copy, Debug, PartialEq)]
4 | pub enum ObjectStatus {
5 | Object = 0x0,
6 | ObjectDoesNotExist = 0x1,
7 | EndOfGroup = 0x3,
8 | EndOfTrack = 0x4,
9 | EndOfSubgroup = 0x5,
10 | }
11 |
12 | impl Decode for ObjectStatus {
13 | fn decode(r: &mut B) -> Result {
14 | match u64::decode(r)? {
15 | 0x0 => Ok(Self::Object),
16 | 0x1 => Ok(Self::ObjectDoesNotExist),
17 | 0x3 => Ok(Self::EndOfGroup),
18 | 0x4 => Ok(Self::EndOfTrack),
19 | 0x5 => Ok(Self::EndOfSubgroup),
20 | _ => Err(DecodeError::InvalidObjectStatus),
21 | }
22 | }
23 | }
24 |
25 | impl Encode for ObjectStatus {
26 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
27 | match self {
28 | Self::Object => (0x0_u64).encode(w),
29 | Self::ObjectDoesNotExist => (0x1_u64).encode(w),
30 | Self::EndOfGroup => (0x3_u64).encode(w),
31 | Self::EndOfTrack => (0x4_u64).encode(w),
32 | Self::EndOfSubgroup => (0x5_u64).encode(w),
33 | }
34 | }
35 | }
36 |
37 | #[derive(Clone, Debug)]
38 | pub struct ObjectHeader {
39 | // The subscribe ID.
40 | pub subscribe_id: u64,
41 |
42 | // The track alias.
43 | pub track_alias: u64,
44 |
45 | // The sequence number within the track.
46 | pub group_id: u64,
47 |
48 | // The sequence number within the group.
49 | pub object_id: u64,
50 |
51 | // Publisher priority, where **smaller** values are sent first.
52 | pub publisher_priority: u8,
53 |
54 | // The object status
55 | pub object_status: ObjectStatus,
56 | }
57 |
58 | impl Decode for ObjectHeader {
59 | fn decode(r: &mut R) -> Result {
60 | Ok(Self {
61 | subscribe_id: u64::decode(r)?,
62 | track_alias: u64::decode(r)?,
63 | group_id: u64::decode(r)?,
64 | object_id: u64::decode(r)?,
65 | publisher_priority: u8::decode(r)?,
66 | object_status: ObjectStatus::decode(r)?,
67 | })
68 | }
69 | }
70 |
71 | impl Encode for ObjectHeader {
72 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
73 | self.subscribe_id.encode(w)?;
74 | self.track_alias.encode(w)?;
75 | self.group_id.encode(w)?;
76 | self.object_id.encode(w)?;
77 | self.publisher_priority.encode(w)?;
78 | self.object_status.encode(w)?;
79 |
80 | Ok(())
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/moq-transport/src/data/subgroup.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 | use crate::data::ObjectStatus;
3 |
4 | #[derive(Clone, Debug)]
5 | pub struct SubgroupHeader {
6 | // The subscribe ID.
7 | pub subscribe_id: u64,
8 |
9 | // The track alias.
10 | pub track_alias: u64,
11 |
12 | // The group sequence number
13 | pub group_id: u64,
14 |
15 | // The subgroup sequence number
16 | pub subgroup_id: u64,
17 |
18 | // Publisher priority, where **smaller** values are sent first.
19 | pub publisher_priority: u8,
20 | }
21 |
22 | impl Decode for SubgroupHeader {
23 | fn decode(r: &mut R) -> Result {
24 | Ok(Self {
25 | subscribe_id: u64::decode(r)?,
26 | track_alias: u64::decode(r)?,
27 | group_id: u64::decode(r)?,
28 | subgroup_id: u64::decode(r)?,
29 | publisher_priority: u8::decode(r)?,
30 | })
31 | }
32 | }
33 |
34 | impl Encode for SubgroupHeader {
35 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
36 | self.subscribe_id.encode(w)?;
37 | self.track_alias.encode(w)?;
38 | self.group_id.encode(w)?;
39 | self.subgroup_id.encode(w)?;
40 | self.publisher_priority.encode(w)?;
41 |
42 | Ok(())
43 | }
44 | }
45 |
46 | #[derive(Clone, Debug)]
47 | pub struct SubgroupObject {
48 | pub object_id: u64,
49 | pub size: usize,
50 | pub status: ObjectStatus,
51 | }
52 |
53 | impl Decode for SubgroupObject {
54 | fn decode(r: &mut R) -> Result {
55 | let object_id = u64::decode(r)?;
56 | let size = usize::decode(r)?;
57 |
58 | // If the size is 0, then the status is sent explicitly.
59 | // Otherwise, the status is assumed to be 0x0 (Object).
60 | let status = if size == 0 {
61 | ObjectStatus::decode(r)?
62 | } else {
63 | ObjectStatus::Object
64 | };
65 |
66 | Ok(Self {
67 | object_id,
68 | size,
69 | status,
70 | })
71 | }
72 | }
73 |
74 | impl Encode for SubgroupObject {
75 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
76 | self.object_id.encode(w)?;
77 | self.size.encode(w)?;
78 |
79 | // If the size is 0, then the status is sent explicitly.
80 | // Otherwise, the status is assumed to be 0x0 (Object).
81 | if self.size == 0 {
82 | self.status.encode(w)?;
83 | }
84 |
85 | Ok(())
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/moq-transport/src/data/track.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 | use crate::data::ObjectStatus;
3 |
4 | #[derive(Clone, Debug)]
5 | pub struct TrackHeader {
6 | // The subscribe ID.
7 | pub subscribe_id: u64,
8 |
9 | // The track ID.
10 | pub track_alias: u64,
11 |
12 | // Publisher priority, where **smaller** values are sent first.
13 | pub publisher_priority: u8,
14 | }
15 |
16 | impl Decode for TrackHeader {
17 | fn decode(r: &mut R) -> Result {
18 | Ok(Self {
19 | subscribe_id: u64::decode(r)?,
20 | track_alias: u64::decode(r)?,
21 | publisher_priority: u8::decode(r)?,
22 | })
23 | }
24 | }
25 |
26 | impl Encode for TrackHeader {
27 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
28 | self.subscribe_id.encode(w)?;
29 | self.track_alias.encode(w)?;
30 | self.publisher_priority.encode(w)?;
31 |
32 | Ok(())
33 | }
34 | }
35 |
36 | #[derive(Clone, Debug)]
37 | pub struct TrackObject {
38 | pub group_id: u64,
39 | pub object_id: u64,
40 | pub size: usize,
41 | pub status: ObjectStatus,
42 | }
43 |
44 | impl Decode for TrackObject {
45 | fn decode(r: &mut R) -> Result {
46 | let group_id = u64::decode(r)?;
47 |
48 | let object_id = u64::decode(r)?;
49 | let size = usize::decode(r)?;
50 |
51 | // If the size is 0, then the status is sent explicitly.
52 | // Otherwise, the status is assumed to be 0x0 (Object).
53 | let status = if size == 0 {
54 | ObjectStatus::decode(r)?
55 | } else {
56 | ObjectStatus::Object
57 | };
58 |
59 | Ok(Self {
60 | group_id,
61 | object_id,
62 | size,
63 | status,
64 | })
65 | }
66 | }
67 |
68 | impl Encode for TrackObject {
69 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
70 | self.group_id.encode(w)?;
71 | self.object_id.encode(w)?;
72 | self.size.encode(w)?;
73 |
74 | // If the size is 0, then the status is sent explicitly.
75 | // Otherwise, the status is assumed to be 0x0 (Object).
76 | if self.size == 0 {
77 | self.status.encode(w)?;
78 | }
79 |
80 | Ok(())
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/moq-transport/src/error.rs:
--------------------------------------------------------------------------------
1 | /// An error that causes the session to close.
2 | #[derive(thiserror::Error, Debug)]
3 | pub enum SessionError {
4 | // Official error codes
5 | #[error("no error")]
6 | NoError,
7 |
8 | #[error("internal error")]
9 | InternalError,
10 |
11 | #[error("unauthorized")]
12 | Unauthorized,
13 |
14 | #[error("protocol violation")]
15 | ProtocolViolation,
16 |
17 | #[error("duplicate track alias")]
18 | DuplicateTrackAlias,
19 |
20 | #[error("parameter length mismatch")]
21 | ParameterLengthMismatch,
22 |
23 | #[error("too many subscribes")]
24 | TooManySubscribes,
25 |
26 | #[error("goaway timeout")]
27 | GoawayTimeout,
28 |
29 | #[error("unknown error: code={0}")]
30 | Unknown(u64),
31 | // Unofficial error codes
32 | }
33 |
34 | pub trait MoqError {
35 | /// An integer code that is sent over the wire.
36 | fn code(&self) -> u64;
37 | }
38 |
39 | impl MoqError for SessionError {
40 | /// An integer code that is sent over the wire.
41 | fn code(&self) -> u64 {
42 | match self {
43 | // Official error codes
44 | Self::NoError => 0x0,
45 | Self::InternalError => 0x1,
46 | Self::Unauthorized => 0x2,
47 | Self::ProtocolViolation => 0x3,
48 | Self::DuplicateTrackAlias => 0x4,
49 | Self::ParameterLengthMismatch => 0x5,
50 | Self::TooManySubscribes => 0x6,
51 | Self::GoawayTimeout => 0x10,
52 | Self::Unknown(code) => *code,
53 | // Unofficial error codes
54 | }
55 | }
56 | }
57 |
58 | /// An error that causes the subscribe to be rejected immediately.
59 | #[derive(thiserror::Error, Debug)]
60 | pub enum SubscribeError {
61 | // Official error codes
62 | #[error("internal error")]
63 | InternalError,
64 |
65 | #[error("invalid range")]
66 | InvalidRange,
67 |
68 | #[error("retry track alias")]
69 | RetryTrackAlias,
70 |
71 | #[error("track does not exist")]
72 | TrackDoesNotExist,
73 |
74 | #[error("unauthorized")]
75 | Unauthorized,
76 |
77 | #[error("timeout")]
78 | Timeout,
79 |
80 | #[error("unknown error: code={0}")]
81 | Unknown(u64),
82 | // Unofficial error codes
83 | }
84 |
85 | impl MoqError for SubscribeError {
86 | /// An integer code that is sent over the wire.
87 | fn code(&self) -> u64 {
88 | match self {
89 | // Official error codes
90 | Self::InternalError => 0x0,
91 | Self::InvalidRange => 0x1,
92 | Self::RetryTrackAlias => 0x2,
93 | Self::TrackDoesNotExist => 0x3,
94 | Self::Unauthorized => 0x4,
95 | Self::Timeout => 0x5,
96 | Self::Unknown(code) => *code,
97 | // Unofficial error codes
98 | }
99 | }
100 | }
101 |
102 | /// An error that causes the subscribe to be terminated.
103 | #[derive(thiserror::Error, Debug)]
104 | pub enum SubscribeDone {
105 | // Official error codes
106 | #[error("unsubscribed")]
107 | Unsubscribed,
108 |
109 | #[error("internal error")]
110 | InternalError,
111 |
112 | // TODO This should be in SubscribeError
113 | #[error("unauthorized")]
114 | Unauthorized,
115 |
116 | #[error("track ended")]
117 | TrackEnded,
118 |
119 | // TODO What the heck is this?
120 | #[error("subscription ended")]
121 | SubscriptionEnded,
122 |
123 | #[error("going away")]
124 | GoingAway,
125 |
126 | #[error("expired")]
127 | Expired,
128 |
129 | #[error("unknown error: code={0}")]
130 | Unknown(u64),
131 | }
132 |
133 | impl From for SubscribeDone {
134 | fn from(code: u64) -> Self {
135 | match code {
136 | 0x0 => Self::Unsubscribed,
137 | 0x1 => Self::InternalError,
138 | 0x2 => Self::Unauthorized,
139 | 0x3 => Self::TrackEnded,
140 | 0x4 => Self::SubscriptionEnded,
141 | 0x5 => Self::GoingAway,
142 | 0x6 => Self::Expired,
143 | _ => Self::Unknown(code),
144 | }
145 | }
146 | }
147 |
148 | impl MoqError for SubscribeDone {
149 | /// An integer code that is sent over the wire.
150 | fn code(&self) -> u64 {
151 | match self {
152 | // Official error codes
153 | Self::Unsubscribed => 0x0,
154 | Self::InternalError => 0x1,
155 | Self::Unauthorized => 0x2,
156 | Self::TrackEnded => 0x3,
157 | Self::SubscriptionEnded => 0x4,
158 | Self::GoingAway => 0x5,
159 | Self::Expired => 0x6,
160 | Self::Unknown(code) => *code,
161 | // Unofficial error codes
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/moq-transport/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! An implementation of the MoQ Transport protocol.
2 | //!
3 | //! MoQ Transport is a pub/sub protocol over QUIC.
4 | //! While originally designed for live media, MoQ Transport is generic and can be used for other live applications.
5 | //! The specification is a work in progress and will change.
6 | //! See the [specification](https://datatracker.ietf.org/doc/draft-ietf-moq-transport/) and [github](https://github.com/moq-wg/moq-transport) for any updates.
7 | pub mod coding;
8 | pub mod data;
9 | pub mod error;
10 | pub mod message;
11 | pub mod serve;
12 | pub mod session;
13 | pub mod setup;
14 | pub mod watch;
15 |
--------------------------------------------------------------------------------
/moq-transport/src/message/announce.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Params, Tuple};
2 |
3 | /// Sent by the publisher to announce the availability of a group of tracks.
4 | #[derive(Clone, Debug)]
5 | pub struct Announce {
6 | /// The track namespace
7 | pub namespace: Tuple,
8 |
9 | /// Optional parameters
10 | pub params: Params,
11 | }
12 |
13 | impl Decode for Announce {
14 | fn decode(r: &mut R) -> Result {
15 | let namespace = Tuple::decode(r)?;
16 | let params = Params::decode(r)?;
17 |
18 | Ok(Self { namespace, params })
19 | }
20 | }
21 |
22 | impl Encode for Announce {
23 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
24 | self.namespace.encode(w)?;
25 | self.params.encode(w)?;
26 |
27 | Ok(())
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/moq-transport/src/message/announce_cancel.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | /// Sent by the subscriber to reject an Announce after ANNOUNCE_OK
4 | #[derive(Clone, Debug)]
5 | pub struct AnnounceCancel {
6 | // Echo back the namespace that was reset
7 | pub namespace: Tuple,
8 | // An error code.
9 | pub error_code: u64,
10 | // An optional, human-readable reason.
11 | pub reason_phrase: String,
12 | }
13 |
14 | impl Decode for AnnounceCancel {
15 | fn decode(r: &mut R) -> Result {
16 | let namespace = Tuple::decode(r)?;
17 | let error_code = u64::decode(r)?;
18 | let reason_phrase = String::decode(r)?;
19 |
20 | Ok(Self {
21 | namespace,
22 | error_code,
23 | reason_phrase,
24 | })
25 | }
26 | }
27 |
28 | impl Encode for AnnounceCancel {
29 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
30 | self.namespace.encode(w)?;
31 | self.error_code.encode(w)?;
32 | self.reason_phrase.encode(w)?;
33 |
34 | Ok(())
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/moq-transport/src/message/announce_error.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | /// Sent by the subscriber to reject an Announce.
4 | #[derive(Clone, Debug)]
5 | pub struct AnnounceError {
6 | // Echo back the namespace that was reset
7 | pub namespace: Tuple,
8 |
9 | // An error code.
10 | pub error_code: u64,
11 |
12 | // An optional, human-readable reason.
13 | pub reason_phrase: String,
14 | }
15 |
16 | impl Decode for AnnounceError {
17 | fn decode(r: &mut R) -> Result {
18 | let namespace = Tuple::decode(r)?;
19 | let error_code = u64::decode(r)?;
20 | let reason_phrase = String::decode(r)?;
21 |
22 | Ok(Self {
23 | namespace,
24 | error_code,
25 | reason_phrase,
26 | })
27 | }
28 | }
29 |
30 | impl Encode for AnnounceError {
31 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
32 | self.namespace.encode(w)?;
33 | self.error_code.encode(w)?;
34 | self.reason_phrase.encode(w)?;
35 |
36 | Ok(())
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/moq-transport/src/message/announce_ok.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | /// Sent by the subscriber to accept an Announce.
4 | #[derive(Clone, Debug)]
5 | pub struct AnnounceOk {
6 | // Echo back the namespace that was announced.
7 | // TODO Propose using an ID to save bytes.
8 | pub namespace: Tuple,
9 | }
10 |
11 | impl Decode for AnnounceOk {
12 | fn decode(r: &mut R) -> Result {
13 | let namespace = Tuple::decode(r)?;
14 | Ok(Self { namespace })
15 | }
16 | }
17 |
18 | impl Encode for AnnounceOk {
19 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
20 | self.namespace.encode(w)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/moq-transport/src/message/fetch.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Params, Tuple};
2 | use crate::message::GroupOrder;
3 |
4 | /// Sent by the subscriber to request to request a range
5 | /// of already published objects within a track.
6 | #[derive(Clone, Debug)]
7 | pub struct Fetch {
8 | /// The subscription ID
9 | pub id: u64,
10 |
11 | /// Track properties
12 | pub track_namespace: Tuple,
13 | pub track_name: String,
14 |
15 | /// Subscriber Priority
16 | pub subscriber_priority: u8,
17 |
18 | pub group_order: GroupOrder,
19 |
20 | /// The start/end group/object.
21 | pub start_group: u64,
22 | pub start_object: u64,
23 | pub end_group: u64,
24 | pub end_object: u64,
25 |
26 | /// Optional parameters
27 | pub params: Params,
28 | }
29 |
30 | impl Decode for Fetch {
31 | fn decode(r: &mut R) -> Result {
32 | let id = u64::decode(r)?;
33 |
34 | let track_namespace = Tuple::decode(r)?;
35 | let track_name = String::decode(r)?;
36 |
37 | let subscriber_priority = u8::decode(r)?;
38 |
39 | let group_order = GroupOrder::decode(r)?;
40 |
41 | let start_group = u64::decode(r)?;
42 | let start_object = u64::decode(r)?;
43 | let end_group = u64::decode(r)?;
44 | let end_object = u64::decode(r)?;
45 |
46 | let params = Params::decode(r)?;
47 |
48 | Ok(Self {
49 | id,
50 | track_namespace,
51 | track_name,
52 | subscriber_priority,
53 | group_order,
54 | start_group,
55 | start_object,
56 | end_group,
57 | end_object,
58 | params,
59 | })
60 | }
61 | }
62 |
63 | impl Encode for Fetch {
64 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
65 | self.id.encode(w)?;
66 |
67 | self.track_namespace.encode(w)?;
68 | self.track_name.encode(w)?;
69 |
70 | self.subscriber_priority.encode(w)?;
71 |
72 | self.group_order.encode(w)?;
73 |
74 | self.start_group.encode(w)?;
75 | self.start_object.encode(w)?;
76 | self.end_group.encode(w)?;
77 | self.end_object.encode(w)?;
78 |
79 | self.params.encode(w)?;
80 |
81 | Ok(())
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/moq-transport/src/message/fetch_cancel.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// A subscriber issues a FETCH_CANCEL message to a publisher indicating it is
4 | /// no longer interested in receiving Objects for the fetch specified by 'Subscribe ID'.
5 | #[derive(Clone, Debug)]
6 | pub struct FetchCancel {
7 | /// The subscription ID
8 | pub id: u64,
9 | }
10 |
11 | impl Decode for FetchCancel {
12 | fn decode(r: &mut R) -> Result {
13 | let id = u64::decode(r)?;
14 | Ok(Self { id })
15 | }
16 | }
17 |
18 | impl Encode for FetchCancel {
19 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
20 | self.id.encode(w)?;
21 |
22 | Ok(())
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/moq-transport/src/message/fetch_error.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Sent by the server to indicate that the client should connect to a different server.
4 | #[derive(Clone, Debug)]
5 | pub struct FetchError {
6 | /// The ID for this subscription.
7 | pub id: u64,
8 |
9 | /// An error code.
10 | pub code: u64,
11 |
12 | /// An optional, human-readable reason.
13 | pub reason: String,
14 | }
15 |
16 | impl Decode for FetchError {
17 | fn decode(r: &mut R) -> Result {
18 | let id = u64::decode(r)?;
19 |
20 | let code = u64::decode(r)?;
21 | let reason = String::decode(r)?;
22 |
23 | Ok(Self { id, code, reason })
24 | }
25 | }
26 |
27 | impl Encode for FetchError {
28 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
29 | self.id.encode(w)?;
30 |
31 | self.code.encode(w)?;
32 | self.reason.encode(w)?;
33 |
34 | Ok(())
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/moq-transport/src/message/fetch_ok.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Params};
2 |
3 | /// A publisher sends a FETCH_OK control message in response to successful fetches.
4 | #[derive(Clone, Debug)]
5 | pub struct FetchOk {
6 | /// The subscription ID
7 | pub id: u64,
8 |
9 | /// Order groups will be delivered in
10 | pub group_order: u8,
11 |
12 | /// True if all objects have been published on this track
13 | pub end_of_track: u8,
14 |
15 | /// The largest Group ID available for this track (last if end_of_track)
16 | pub largest_group_id: u64,
17 | /// The largest Object ID available within the largest Group ID for this track (last if end_of_track)
18 | pub largest_object_id: u64,
19 |
20 | /// Optional parameters
21 | pub params: Params,
22 | }
23 |
24 | impl Decode for FetchOk {
25 | fn decode(r: &mut R) -> Result {
26 | let id = u64::decode(r)?;
27 |
28 | let group_order = u8::decode(r)?;
29 |
30 | let end_of_track = u8::decode(r)?;
31 |
32 | let largest_group_id = u64::decode(r)?;
33 | let largest_object_id = u64::decode(r)?;
34 |
35 | let params = Params::decode(r)?;
36 |
37 | Ok(Self {
38 | id,
39 | group_order,
40 | end_of_track,
41 | largest_group_id,
42 | largest_object_id,
43 | params,
44 | })
45 | }
46 | }
47 |
48 | impl Encode for FetchOk {
49 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
50 | self.id.encode(w)?;
51 |
52 | self.group_order.encode(w)?;
53 |
54 | self.end_of_track.encode(w)?;
55 |
56 | self.largest_group_id.encode(w)?;
57 | self.largest_object_id.encode(w)?;
58 |
59 | self.params.encode(w)?;
60 |
61 | Ok(())
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/moq-transport/src/message/filter_type.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Filter Types
4 | /// https://www.ietf.org/archive/id/draft-ietf-moq-transport-04.html#name-filter-types
5 | #[derive(Clone, Debug, PartialEq)]
6 | pub enum FilterType {
7 | LatestGroup = 0x1,
8 | LatestObject = 0x2,
9 | AbsoluteStart = 0x3,
10 | AbsoluteRange = 0x4,
11 | }
12 |
13 | impl Encode for FilterType {
14 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
15 | match self {
16 | Self::LatestGroup => (0x1_u64).encode(w),
17 | Self::LatestObject => (0x2_u64).encode(w),
18 | Self::AbsoluteStart => (0x3_u64).encode(w),
19 | Self::AbsoluteRange => (0x4_u64).encode(w),
20 | }
21 | }
22 | }
23 |
24 | impl Decode for FilterType {
25 | fn decode(r: &mut R) -> Result {
26 | match u64::decode(r)? {
27 | 0x01 => Ok(Self::LatestGroup),
28 | 0x02 => Ok(Self::LatestObject),
29 | 0x03 => Ok(Self::AbsoluteStart),
30 | 0x04 => Ok(Self::AbsoluteRange),
31 | _ => Err(DecodeError::InvalidFilterType),
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/moq-transport/src/message/go_away.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Sent by the server to indicate that the client should connect to a different server.
4 | #[derive(Clone, Debug)]
5 | pub struct GoAway {
6 | pub url: String,
7 | }
8 |
9 | impl Decode for GoAway {
10 | fn decode(r: &mut R) -> Result {
11 | let url = String::decode(r)?;
12 | Ok(Self { url })
13 | }
14 | }
15 |
16 | impl Encode for GoAway {
17 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
18 | self.url.encode(w)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/moq-transport/src/message/group_order.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Group Order
4 | /// https://www.ietf.org/archive/id/draft-ietf-moq-transport-05.html#section-6.4.2-4.6.1
5 | /// https://www.ietf.org/archive/id/draft-ietf-moq-transport-05.html#priorities
6 | #[derive(Clone, Debug, PartialEq)]
7 | pub enum GroupOrder {
8 | Publisher = 0x0,
9 | Ascending = 0x1,
10 | Descending = 0x2,
11 | }
12 |
13 | impl Encode for GroupOrder {
14 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
15 | match self {
16 | Self::Publisher => (0x0_u8).encode(w),
17 | Self::Ascending => (0x1_u8).encode(w),
18 | Self::Descending => (0x2_u8).encode(w),
19 | }
20 | }
21 | }
22 |
23 | impl Decode for GroupOrder {
24 | fn decode(r: &mut R) -> Result {
25 | match u8::decode(r)? {
26 | 0x0 => Ok(Self::Publisher),
27 | 0x1 => Ok(Self::Ascending),
28 | 0x2 => Ok(Self::Descending),
29 | _ => Err(DecodeError::InvalidGroupOrder),
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/moq-transport/src/message/max_subscribe_id.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Sent by the publisher to update the max allowed subscription ID for the session.
4 | #[derive(Clone, Debug)]
5 | pub struct MaxSubscribeId {
6 | /// The max allowed subscription ID
7 | pub id: u64,
8 | }
9 |
10 | impl Decode for MaxSubscribeId {
11 | fn decode(r: &mut R) -> Result {
12 | let id = u64::decode(r)?;
13 |
14 | Ok(Self { id })
15 | }
16 | }
17 |
18 | impl Encode for MaxSubscribeId {
19 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
20 | self.id.encode(w)?;
21 |
22 | Ok(())
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/moq-transport/src/message/publisher.rs:
--------------------------------------------------------------------------------
1 | use crate::message::{self, Message};
2 | use std::fmt;
3 |
4 | macro_rules! publisher_msgs {
5 | {$($name:ident,)*} => {
6 | #[derive(Clone)]
7 | pub enum Publisher {
8 | $($name(message::$name)),*
9 | }
10 |
11 | $(impl From for Publisher {
12 | fn from(msg: message::$name) -> Self {
13 | Publisher::$name(msg)
14 | }
15 | })*
16 |
17 | impl From for Message {
18 | fn from(p: Publisher) -> Self {
19 | match p {
20 | $(Publisher::$name(m) => Message::$name(m),)*
21 | }
22 | }
23 | }
24 |
25 | impl TryFrom for Publisher {
26 | type Error = Message;
27 |
28 | fn try_from(m: Message) -> Result {
29 | match m {
30 | $(Message::$name(m) => Ok(Publisher::$name(m)),)*
31 | _ => Err(m),
32 | }
33 | }
34 | }
35 |
36 | impl fmt::Debug for Publisher {
37 | // Delegate to the message formatter
38 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 | match self {
40 | $(Self::$name(ref m) => m.fmt(f),)*
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
47 | publisher_msgs! {
48 | Announce,
49 | Unannounce,
50 | SubscribeOk,
51 | SubscribeError,
52 | SubscribeDone,
53 | MaxSubscribeId,
54 | TrackStatus,
55 | FetchOk,
56 | FetchError,
57 | }
58 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscribe_done.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Sent by the publisher to cleanly terminate a Subscribe.
4 | #[derive(Clone, Debug)]
5 | pub struct SubscribeDone {
6 | /// The ID for this subscription.
7 | pub id: u64,
8 |
9 | /// The error code
10 | pub code: u64,
11 |
12 | /// An optional error reason
13 | pub reason: String,
14 |
15 | /// The final group/object sent on this subscription.
16 | pub last: Option<(u64, u64)>,
17 | }
18 |
19 | impl Decode for SubscribeDone {
20 | fn decode(r: &mut R) -> Result {
21 | let id = u64::decode(r)?;
22 | let code = u64::decode(r)?;
23 | let reason = String::decode(r)?;
24 |
25 | Self::decode_remaining(r, 1)?;
26 | let last = match r.get_u8() {
27 | 0 => None,
28 | 1 => Some((u64::decode(r)?, u64::decode(r)?)),
29 | _ => return Err(DecodeError::InvalidValue),
30 | };
31 |
32 | Ok(Self {
33 | id,
34 | code,
35 | reason,
36 | last,
37 | })
38 | }
39 | }
40 |
41 | impl Encode for SubscribeDone {
42 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
43 | self.id.encode(w)?;
44 | self.code.encode(w)?;
45 | self.reason.encode(w)?;
46 |
47 | Self::encode_remaining(w, 1)?;
48 |
49 | if let Some((group, object)) = self.last {
50 | w.put_u8(1);
51 | group.encode(w)?;
52 | object.encode(w)?;
53 | } else {
54 | w.put_u8(0);
55 | }
56 |
57 | Ok(())
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscribe_error.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Sent by the publisher to reject a Subscribe.
4 | #[derive(Clone, Debug)]
5 | pub struct SubscribeError {
6 | // The ID for this subscription.
7 | pub id: u64,
8 |
9 | // An error code.
10 | pub code: u64,
11 |
12 | // An optional, human-readable reason.
13 | pub reason: String,
14 |
15 | /// An optional track alias, only used when error == Retry Track Alias
16 | pub alias: u64,
17 | }
18 |
19 | impl Decode for SubscribeError {
20 | fn decode(r: &mut R) -> Result {
21 | let id = u64::decode(r)?;
22 | let code = u64::decode(r)?;
23 | let reason = String::decode(r)?;
24 | let alias = u64::decode(r)?;
25 |
26 | Ok(Self {
27 | id,
28 | code,
29 | reason,
30 | alias,
31 | })
32 | }
33 | }
34 |
35 | impl Encode for SubscribeError {
36 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
37 | self.id.encode(w)?;
38 | self.code.encode(w)?;
39 | self.reason.encode(w)?;
40 | self.alias.encode(w)?;
41 |
42 | Ok(())
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscribe_namespace.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Params, Tuple};
2 |
3 | /// Subscribe Namespace
4 | /// https://www.ietf.org/archive/id/draft-ietf-moq-transport-06.html#section-6.11
5 | #[derive(Clone, Debug)]
6 | pub struct SubscribeNamespace {
7 | /// The track namespace
8 | pub namespace_prefix: Tuple,
9 |
10 | /// Optional parameters
11 | pub params: Params,
12 | }
13 |
14 | impl Decode for SubscribeNamespace {
15 | fn decode(r: &mut R) -> Result {
16 | let namespace_prefix = Tuple::decode(r)?;
17 | let params = Params::decode(r)?;
18 |
19 | Ok(Self {
20 | namespace_prefix,
21 | params,
22 | })
23 | }
24 | }
25 |
26 | impl Encode for SubscribeNamespace {
27 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
28 | self.namespace_prefix.encode(w)?;
29 | self.params.encode(w)?;
30 |
31 | Ok(())
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscribe_namespace_error.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | /// Subscribe Namespace Error
4 | /// https://www.ietf.org/archive/id/draft-ietf-moq-transport-06.html#name-subscribe_namespace_error
5 | #[derive(Clone, Debug)]
6 | pub struct SubscribeNamespaceError {
7 | // Echo back the namespace that was reset
8 | pub namespace_prefix: Tuple,
9 |
10 | // An error code.
11 | pub code: u64,
12 |
13 | // An optional, human-readable reason.
14 | pub reason: String,
15 | }
16 |
17 | impl Decode for SubscribeNamespaceError {
18 | fn decode(r: &mut R) -> Result {
19 | let namespace_prefix = Tuple::decode(r)?;
20 | let code = u64::decode(r)?;
21 | let reason = String::decode(r)?;
22 |
23 | Ok(Self {
24 | namespace_prefix,
25 | code,
26 | reason,
27 | })
28 | }
29 | }
30 |
31 | impl Encode for SubscribeNamespaceError {
32 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
33 | self.namespace_prefix.encode(w)?;
34 | self.code.encode(w)?;
35 | self.reason.encode(w)?;
36 |
37 | Ok(())
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscribe_namespace_ok.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | /// Subscribe Namespace Ok
4 | /// https://www.ietf.org/archive/id/draft-ietf-moq-transport-06.html#name-subscribe_namespace_ok
5 | #[derive(Clone, Debug)]
6 | pub struct SubscribeNamespaceOk {
7 | // Echo back the namespace that was announced.
8 | pub namespace_prefix: Tuple,
9 | }
10 |
11 | impl Decode for SubscribeNamespaceOk {
12 | fn decode(r: &mut R) -> Result {
13 | let namespace_prefix = Tuple::decode(r)?;
14 | Ok(Self { namespace_prefix })
15 | }
16 | }
17 |
18 | impl Encode for SubscribeNamespaceOk {
19 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
20 | self.namespace_prefix.encode(w)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscribe_ok.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 | use crate::message::GroupOrder;
3 |
4 | /// Sent by the publisher to accept a Subscribe.
5 | #[derive(Clone, Debug)]
6 | pub struct SubscribeOk {
7 | /// The ID for this subscription.
8 | pub id: u64,
9 |
10 | /// The subscription will expire in this many milliseconds.
11 | pub expires: Option,
12 |
13 | // Order groups will be delivered in
14 | pub group_order: GroupOrder,
15 |
16 | /// The latest group and object for the track.
17 | pub latest: Option<(u64, u64)>,
18 | }
19 |
20 | impl Decode for SubscribeOk {
21 | fn decode(r: &mut R) -> Result {
22 | let id = u64::decode(r)?;
23 | let expires = match u64::decode(r)? {
24 | 0 => None,
25 | expires => Some(expires),
26 | };
27 |
28 | let group_order = GroupOrder::decode(r)?;
29 |
30 | Self::decode_remaining(r, 1)?;
31 |
32 | let latest = match r.get_u8() {
33 | 0 => None,
34 | 1 => Some((u64::decode(r)?, u64::decode(r)?)),
35 | _ => return Err(DecodeError::InvalidValue),
36 | };
37 |
38 | // Skip the parameters.
39 | // TODO: Implement parameters for SubscribeOk
40 | let _ = u8::decode(r)?;
41 |
42 | Ok(Self {
43 | id,
44 | expires,
45 | group_order,
46 | latest,
47 | })
48 | }
49 | }
50 |
51 | impl Encode for SubscribeOk {
52 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
53 | self.id.encode(w)?;
54 | self.expires.unwrap_or(0).encode(w)?;
55 |
56 | self.group_order.encode(w)?;
57 |
58 | Self::encode_remaining(w, 1)?;
59 |
60 | match self.latest {
61 | Some((group, object)) => {
62 | w.put_u8(1);
63 | group.encode(w)?;
64 | object.encode(w)?;
65 | }
66 | None => {
67 | w.put_u8(0);
68 | }
69 | }
70 |
71 | // Add 0 for the length of the parameters
72 | w.put_u8(0);
73 |
74 | Ok(())
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscribe_update.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Params, Tuple};
2 | use crate::message::subscribe::{SubscribeLocation, SubscribePair};
3 | use crate::message::FilterType;
4 | use crate::message::GroupOrder;
5 |
6 | /// Sent by the subscriber to request all future objects for the given track.
7 | ///
8 | /// Objects will use the provided ID instead of the full track name, to save bytes.
9 | #[derive(Clone, Debug)]
10 | pub struct SubscribeUpdate {
11 | /// The subscription ID
12 | pub id: u64,
13 |
14 | /// Track properties
15 | pub track_alias: u64, // This alias is useless but part of the spec
16 | pub track_namespace: Tuple,
17 | pub track_name: String,
18 |
19 | // Subscriber Priority
20 | pub subscriber_priority: u8,
21 | pub group_order: GroupOrder,
22 |
23 | /// Filter type
24 | pub filter_type: FilterType,
25 |
26 | /// The start/end group/object. (TODO: Make optional)
27 | pub start: Option, // TODO: Make optional
28 | pub end: Option, // TODO: Make optional
29 |
30 | /// Optional parameters
31 | pub params: Params,
32 | }
33 |
34 | impl Decode for SubscribeUpdate {
35 | fn decode(r: &mut R) -> Result {
36 | let id = u64::decode(r)?;
37 | let track_alias = u64::decode(r)?;
38 | let track_namespace = Tuple::decode(r)?;
39 | let track_name = String::decode(r)?;
40 |
41 | let subscriber_priority = u8::decode(r)?;
42 | let group_order = GroupOrder::decode(r)?;
43 |
44 | let filter_type = FilterType::decode(r)?;
45 |
46 | let start: Option;
47 | let end: Option;
48 | match filter_type {
49 | FilterType::AbsoluteStart => {
50 | if r.remaining() < 2 {
51 | return Err(DecodeError::MissingField);
52 | }
53 | start = Some(SubscribePair::decode(r)?);
54 | end = None;
55 | }
56 | FilterType::AbsoluteRange => {
57 | if r.remaining() < 4 {
58 | return Err(DecodeError::MissingField);
59 | }
60 | start = Some(SubscribePair::decode(r)?);
61 | end = Some(SubscribePair::decode(r)?);
62 | }
63 | _ => {
64 | start = None;
65 | end = None;
66 | }
67 | }
68 |
69 | if let Some(s) = &start {
70 | // You can't have a start object without a start group.
71 | if s.group == SubscribeLocation::None && s.object != SubscribeLocation::None {
72 | return Err(DecodeError::InvalidSubscribeLocation);
73 | }
74 | }
75 | if let Some(e) = &end {
76 | // You can't have an end object without an end group.
77 | if e.group == SubscribeLocation::None && e.object != SubscribeLocation::None {
78 | return Err(DecodeError::InvalidSubscribeLocation);
79 | }
80 | }
81 |
82 | // NOTE: There's some more location restrictions in the draft, but they're enforced at a higher level.
83 |
84 | let params = Params::decode(r)?;
85 |
86 | Ok(Self {
87 | id,
88 | track_alias,
89 | track_namespace,
90 | track_name,
91 | subscriber_priority,
92 | group_order,
93 | filter_type,
94 | start,
95 | end,
96 | params,
97 | })
98 | }
99 | }
100 |
101 | impl Encode for SubscribeUpdate {
102 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
103 | self.id.encode(w)?;
104 | self.track_alias.encode(w)?;
105 | self.track_namespace.encode(w)?;
106 | self.track_name.encode(w)?;
107 |
108 | self.subscriber_priority.encode(w)?;
109 | self.group_order.encode(w)?;
110 |
111 | self.filter_type.encode(w)?;
112 |
113 | if self.filter_type == FilterType::AbsoluteStart
114 | || self.filter_type == FilterType::AbsoluteRange
115 | {
116 | if self.start.is_none() || self.end.is_none() {
117 | return Err(EncodeError::MissingField);
118 | }
119 | if let Some(start) = &self.start {
120 | start.encode(w)?;
121 | }
122 | if let Some(end) = &self.end {
123 | end.encode(w)?;
124 | }
125 | }
126 |
127 | self.params.encode(w)?;
128 |
129 | Ok(())
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/moq-transport/src/message/subscriber.rs:
--------------------------------------------------------------------------------
1 | use crate::message::{self, Message};
2 | use std::fmt;
3 |
4 | macro_rules! subscriber_msgs {
5 | {$($name:ident,)*} => {
6 | #[derive(Clone)]
7 | pub enum Subscriber {
8 | $($name(message::$name)),*
9 | }
10 |
11 | $(impl From for Subscriber {
12 | fn from(msg: message::$name) -> Self {
13 | Subscriber::$name(msg)
14 | }
15 | })*
16 |
17 | impl From for Message {
18 | fn from(p: Subscriber) -> Self {
19 | match p {
20 | $(Subscriber::$name(m) => Message::$name(m),)*
21 | }
22 | }
23 | }
24 |
25 | impl TryFrom for Subscriber {
26 | type Error = Message;
27 |
28 | fn try_from(m: Message) -> Result {
29 | match m {
30 | $(Message::$name(m) => Ok(Subscriber::$name(m)),)*
31 | _ => Err(m),
32 | }
33 | }
34 | }
35 |
36 | impl fmt::Debug for Subscriber {
37 | // Delegate to the message formatter
38 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 | match self {
40 | $(Self::$name(ref m) => m.fmt(f),)*
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
47 | subscriber_msgs! {
48 | AnnounceOk,
49 | AnnounceError,
50 | AnnounceCancel,
51 | Subscribe,
52 | Unsubscribe,
53 | SubscribeUpdate,
54 | TrackStatusRequest,
55 | SubscribeNamespace,
56 | SubscribeNamespaceOk,
57 | SubscribeNamespaceError,
58 | UnsubscribeNamespace,
59 | Fetch,
60 | FetchCancel,
61 | }
62 |
--------------------------------------------------------------------------------
/moq-transport/src/message/track_status.rs:
--------------------------------------------------------------------------------
1 | use super::TrackStatusCode;
2 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
3 |
4 | #[derive(Clone, Debug)]
5 | pub struct TrackStatus {
6 | /// Track Namespace
7 | pub track_namespace: Tuple,
8 | /// Track Name
9 | pub track_name: String,
10 | /// Status Code
11 | pub status_code: TrackStatusCode,
12 | /// Last Group ID
13 | pub last_group_id: u64,
14 | /// Last Object ID
15 | pub last_object_id: u64,
16 | }
17 |
18 | impl Decode for TrackStatus {
19 | fn decode(r: &mut R) -> Result {
20 | Ok(Self {
21 | track_namespace: Tuple::decode(r)?,
22 | track_name: String::decode(r)?,
23 | status_code: TrackStatusCode::decode(r)?,
24 | last_group_id: u64::decode(r)?,
25 | last_object_id: u64::decode(r)?,
26 | })
27 | }
28 | }
29 |
30 | impl Encode for TrackStatus {
31 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
32 | self.track_namespace.encode(w)?;
33 | self.track_name.encode(w)?;
34 | self.status_code.encode(w)?;
35 | self.last_group_id.encode(w)?;
36 | self.last_object_id.encode(w)?;
37 | Ok(())
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/moq-transport/src/message/track_status_request.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | #[derive(Clone, Debug)]
4 | pub struct TrackStatusRequest {
5 | /// Track Namespace
6 | pub track_namespace: Tuple,
7 | /// Track Name
8 | pub track_name: String,
9 | }
10 |
11 | impl Decode for TrackStatusRequest {
12 | fn decode(r: &mut R) -> Result {
13 | let track_namespace = Tuple::decode(r)?;
14 | let track_name = String::decode(r)?;
15 |
16 | Ok(Self {
17 | track_namespace,
18 | track_name,
19 | })
20 | }
21 | }
22 |
23 | impl Encode for TrackStatusRequest {
24 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
25 | self.track_namespace.encode(w)?;
26 | self.track_name.encode(w)?;
27 |
28 | Ok(())
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/moq-transport/src/message/unannounce.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | /// Sent by the publisher to terminate an Announce.
4 | #[derive(Clone, Debug)]
5 | pub struct Unannounce {
6 | // Echo back the namespace that was reset
7 | pub namespace: Tuple,
8 | }
9 |
10 | impl Decode for Unannounce {
11 | fn decode(r: &mut R) -> Result {
12 | let namespace = Tuple::decode(r)?;
13 |
14 | Ok(Self { namespace })
15 | }
16 | }
17 |
18 | impl Encode for Unannounce {
19 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
20 | self.namespace.encode(w)?;
21 |
22 | Ok(())
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/moq-transport/src/message/unsubscribe.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError};
2 |
3 | /// Sent by the subscriber to terminate a Subscribe.
4 | #[derive(Clone, Debug)]
5 | pub struct Unsubscribe {
6 | // The ID for this subscription.
7 | pub id: u64,
8 | }
9 |
10 | impl Decode for Unsubscribe {
11 | fn decode(r: &mut R) -> Result {
12 | let id = u64::decode(r)?;
13 | Ok(Self { id })
14 | }
15 | }
16 |
17 | impl Encode for Unsubscribe {
18 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
19 | self.id.encode(w)?;
20 | Ok(())
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/moq-transport/src/message/unsubscribe_namespace.rs:
--------------------------------------------------------------------------------
1 | use crate::coding::{Decode, DecodeError, Encode, EncodeError, Tuple};
2 |
3 | /// Unsubscribe Namespace
4 | /// https://www.ietf.org/archive/id/draft-ietf-moq-transport-06.html#name-unsubscribe_namespace
5 | #[derive(Clone, Debug)]
6 | pub struct UnsubscribeNamespace {
7 | // Echo back the namespace that was reset
8 | pub namespace_prefix: Tuple,
9 | }
10 |
11 | impl Decode for UnsubscribeNamespace {
12 | fn decode(r: &mut R) -> Result {
13 | let namespace_prefix = Tuple::decode(r)?;
14 | Ok(Self { namespace_prefix })
15 | }
16 | }
17 |
18 | impl Encode for UnsubscribeNamespace {
19 | fn encode(&self, w: &mut W) -> Result<(), EncodeError> {
20 | self.namespace_prefix.encode(w)?;
21 | Ok(())
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/moq-transport/src/serve/broadcast.rs:
--------------------------------------------------------------------------------
1 | //! A broadcast is a collection of tracks, split into two handles: [Writer] and [Reader].
2 | //!
3 | //! The [Writer] can create tracks, either manually or on request.
4 | //! It receives all requests by a [Reader] for a tracks that don't exist.
5 | //! The simplest implementation is to close every unknown track with [ServeError::NotFound].
6 | //!
7 | //! A [Reader] can request tracks by name.
8 | //! If the track already exists, it will be returned.
9 | //! If the track doesn't exist, it will be sent to [Unknown] to be handled.
10 | //! A [Reader] can be cloned to create multiple subscriptions.
11 | //!
12 | //! The broadcast is automatically closed with [ServeError::Done] when [Writer] is dropped, or all [Reader]s are dropped.
13 | use std::{
14 | collections::{hash_map, HashMap},
15 | ops::Deref,
16 | sync::Arc,
17 | };
18 |
19 | use super::{ServeError, Track, TrackReader, TrackWriter};
20 | use crate::util::State;
21 |
22 | /// Static information about a broadcast.
23 | #[derive(Debug)]
24 | pub struct Broadcast {
25 | pub namespace: String,
26 | }
27 |
28 | impl Broadcast {
29 | pub fn new(namespace: &str) -> Self {
30 | Self {
31 | namespace: namespace.to_owned(),
32 | }
33 | }
34 |
35 | pub fn produce(self) -> (BroadcastWriter, BroadcastReader) {
36 | let (send, recv) = State::init();
37 | let info = Arc::new(self);
38 |
39 | let writer = BroadcastWriter::new(send, info.clone());
40 | let reader = BroadcastReader::new(recv, info);
41 |
42 | (writer, reader)
43 | }
44 | }
45 |
46 | /// Dynamic information about the broadcast.
47 | struct BroadcastState {
48 | tracks: HashMap,
49 | closed: Result<(), ServeError>,
50 | }
51 |
52 | impl BroadcastState {
53 | pub fn get(&self, name: &str) -> Result