moq_lite/ietf/
publish.rs

1/*
29.13. PUBLISH
3The publisher sends the PUBLISH control message to initiate a subscription to a track. The receiver verifies the publisher is authorized to publish this track.
4
5PUBLISH Message {
6  Type (i) = 0x1D,
7  Length (i),
8  Request ID (i),
9  Track Namespace (tuple),
10  Track Name Length (i),
11  Track Name (..),
12  Track Alias (i),
13  Group Order (8),
14  Content Exists (8),
15  [Largest Location (Location),]
16  Forward (8),
17  Number of Parameters (i),
18  Parameters (..) ...,
19}
20Figure 15: MOQT PUBLISH Message
21Request ID: See Section 9.1.
22
23Track Namespace: Identifies a track's namespace as defined in (Section 2.4.1)
24
25Track Name: Identifies the track name as defined in (Section 2.4.1).
26
27Track Alias: The identifer used for this track in Subgroups or Datagrams (see Section 10.1). The same Track Alias MUST NOT be used to refer to two different Tracks simultaneously. If a subscriber receives a PUBLISH that uses the same Track Alias as a different track with an active subscription, it MUST close the session with error DUPLICATE_TRACK_ALIAS.
28
29Group Order: Indicates the subscription will be delivered in Ascending (0x1) or Descending (0x2) order by group. See Section 7. Values of 0x0 and those larger than 0x2 are a protocol error.
30
31Content Exists: 1 if an object has been published on this track, 0 if not. If 0, then the Largest Group ID and Largest Object ID fields will not be present. Any other value is a protocol error and MUST terminate the session with a PROTOCOL_VIOLATION (Section 3.4).
32
33Largest Location: The location of the largest object available for this track.
34
35Forward: The forward mode for this subscription. Any value other than 0 or 1 is a PROTOCOL_VIOLATION. 0 indicates the publisher will not transmit any objects until the subscriber sets the Forward State to 1. 1 indicates the publisher will start transmitting objects immediately, even before PUBLISH_OK.
36
37Parameters: The parameters are defined in Section 9.2.1.
38
39A subscriber receiving a PUBLISH for a Track it does not wish to receive SHOULD send PUBLISH_ERROR with error code UNINTERESTED, and abandon reading any publisher initiated streams associated with that subscription using a STOP_SENDING frame.
40
419.14. PUBLISH_OK
42The subscriber sends a PUBLISH_OK control message to acknowledge the successful authorization and acceptance of a PUBLISH message, and establish a subscription.
43
44PUBLISH_OK Message {
45  Type (i) = 0x1E,
46  Length (i),
47  Request ID (i),
48  Forward (8),
49  Subscriber Priority (8),
50  Group Order (8),
51  Filter Type (i),
52  [Start Location (Location)],
53  [End Group (i)],
54  Number of Parameters (i),
55  Parameters (..) ...,
56}
57Figure 16: MOQT PUBLISH_OK Message
58Request ID: The Request ID of the PUBLISH this message is replying to Section 9.13.
59
60Forward: The Forward State for this subscription, either 0 (don't forward) or 1 (forward).
61
62Subscriber Priority: The Subscriber Priority for this subscription.
63
64Group Order: Indicates the subscription will be delivered in Ascending (0x1) or Descending (0x2) order by group. See Section 7. Values of 0x0 and those larger than 0x2 are a protocol error. This overwrites the GroupOrder specified PUBLISH.
65
66Filter Type, Start Location, End Group: See Section 9.7.
67
68Parameters: Parameters associated with this message.
69
709.15. PUBLISH_ERROR
71The subscriber sends a PUBLISH_ERROR control message to reject a subscription initiated by PUBLISH.
72
73PUBLISH_ERROR Message {
74  Type (i) = 0x1F,
75  Length (i),
76  Request ID (i),
77  Error Code (i),
78  Error Reason (Reason Phrase),
79}
80Figure 17: MOQT PUBLISH_ERROR Message
81Request ID: The Request ID of the PUBLISH this message is replying to Section 9.13.
82
83Error Code: Identifies an integer error code for failure.
84
85Error Reason: Provides the reason for subscription error. See Section 1.4.3.
86
87The application SHOULD use a relevant error code in PUBLISH_ERROR, as defined below:
88
89INTERNAL_ERROR (0x0):
90An implementation specific or generic error occurred.
91
92UNAUTHORIZED (0x1):
93The publisher is not authorized to publish the given namespace or track.
94
95TIMEOUT (0x2):
96The subscription could not be established before an implementation specific timeout.
97
98NOT_SUPPORTED (0x3):
99The endpoint does not support the PUBLISH method.
100
101UNINTERESTED (0x4):
102The namespace or track is not of interest to the endpoint.
103
104
105*/
106
107use std::borrow::Cow;
108
109use crate::{
110	coding::{Decode, DecodeError, Encode},
111	ietf::{
112		namespace::{decode_namespace, encode_namespace},
113		FilterType, GroupOrder, Location, Message, Parameters, RequestId, Version,
114	},
115	Path,
116};
117
118/// Used to be called SubscribeDone
119#[derive(Clone, Debug)]
120pub struct PublishDone<'a> {
121	pub request_id: RequestId,
122	pub status_code: u64,
123	pub stream_count: u64,
124	pub reason_phrase: Cow<'a, str>,
125}
126
127impl<'a> Message for PublishDone<'a> {
128	const ID: u64 = 0x0b;
129
130	fn encode_msg<W: bytes::BufMut>(&self, w: &mut W, version: Version) {
131		self.request_id.encode(w, version);
132		self.status_code.encode(w, version);
133		self.stream_count.encode(w, version);
134		self.reason_phrase.encode(w, version);
135	}
136
137	fn decode_msg<R: bytes::Buf>(r: &mut R, version: Version) -> Result<Self, DecodeError> {
138		let request_id = RequestId::decode(r, version)?;
139		let status_code = u64::decode(r, version)?;
140		let stream_count = u64::decode(r, version)?;
141		let reason_phrase = Cow::<str>::decode(r, version)?;
142
143		Ok(Self {
144			request_id,
145			status_code,
146			stream_count,
147			reason_phrase,
148		})
149	}
150}
151
152#[derive(Debug)]
153pub struct Publish<'a> {
154	pub request_id: RequestId,
155	pub track_namespace: Path<'a>,
156	pub track_name: Cow<'a, str>,
157	pub track_alias: u64,
158	pub group_order: GroupOrder,
159	pub largest_location: Option<Location>,
160	pub forward: bool,
161	// pub parameters: Parameters,
162}
163
164impl<'a> Message for Publish<'a> {
165	const ID: u64 = 0x1D;
166
167	fn encode_msg<W: bytes::BufMut>(&self, w: &mut W, version: Version) {
168		self.request_id.encode(w, version);
169		encode_namespace(w, &self.track_namespace, version);
170		self.track_name.encode(w, version);
171		self.track_alias.encode(w, version);
172		self.group_order.encode(w, version);
173		if let Some(location) = &self.largest_location {
174			true.encode(w, version);
175			location.encode(w, version);
176		} else {
177			false.encode(w, version);
178		}
179
180		self.forward.encode(w, version);
181		// parameters
182		0u8.encode(w, version);
183	}
184
185	fn decode_msg<R: bytes::Buf>(r: &mut R, version: Version) -> Result<Self, DecodeError> {
186		let request_id = RequestId::decode(r, version)?;
187		let track_namespace = decode_namespace(r, version)?;
188		let track_name = Cow::<str>::decode(r, version)?;
189		let track_alias = u64::decode(r, version)?;
190		let group_order = GroupOrder::decode(r, version)?;
191		let content_exists = bool::decode(r, version)?;
192		let largest_location = match content_exists {
193			true => Some(Location::decode(r, version)?),
194			false => None,
195		};
196		let forward = bool::decode(r, version)?;
197		// parameters
198		let _params = Parameters::decode(r, version)?;
199		Ok(Self {
200			request_id,
201			track_namespace,
202			track_name,
203			track_alias,
204			group_order,
205			largest_location,
206			forward,
207		})
208	}
209}
210
211#[derive(Debug)]
212pub struct PublishOk {
213	pub request_id: RequestId,
214	pub forward: bool,
215	pub subscriber_priority: u8,
216	pub group_order: GroupOrder,
217	pub filter_type: FilterType,
218	// pub parameters: Parameters,
219}
220
221impl Message for PublishOk {
222	const ID: u64 = 0x1E;
223
224	fn encode_msg<W: bytes::BufMut>(&self, w: &mut W, version: Version) {
225		self.request_id.encode(w, version);
226		self.forward.encode(w, version);
227		self.subscriber_priority.encode(w, version);
228		self.group_order.encode(w, version);
229		self.filter_type.encode(w, version);
230		assert!(
231			matches!(self.filter_type, FilterType::LargestObject | FilterType::NextGroup),
232			"absolute subscribe not supported"
233		);
234		// no parameters
235		0u8.encode(w, version);
236	}
237
238	fn decode_msg<R: bytes::Buf>(r: &mut R, version: Version) -> Result<Self, DecodeError> {
239		let request_id = RequestId::decode(r, version)?;
240		let forward = bool::decode(r, version)?;
241		let subscriber_priority = u8::decode(r, version)?;
242		let group_order = GroupOrder::decode(r, version)?;
243		let filter_type = FilterType::decode(r, version)?;
244		match filter_type {
245			FilterType::AbsoluteStart => {
246				let _start = Location::decode(r, version)?;
247			}
248			FilterType::AbsoluteRange => {
249				let _start = Location::decode(r, version)?;
250				let _end_group = u64::decode(r, version)?;
251			}
252			FilterType::NextGroup | FilterType::LargestObject => {}
253		};
254
255		// no parameters
256		let _params = Parameters::decode(r, version)?;
257
258		Ok(Self {
259			request_id,
260			forward,
261			subscriber_priority,
262			group_order,
263			filter_type,
264		})
265	}
266}
267
268#[derive(Debug)]
269pub struct PublishError<'a> {
270	pub request_id: RequestId,
271	pub error_code: u64,
272	pub reason_phrase: Cow<'a, str>,
273}
274impl<'a> Message for PublishError<'a> {
275	const ID: u64 = 0x1F;
276
277	fn encode_msg<W: bytes::BufMut>(&self, w: &mut W, version: Version) {
278		self.request_id.encode(w, version);
279		self.error_code.encode(w, version);
280		self.reason_phrase.encode(w, version);
281	}
282
283	fn decode_msg<R: bytes::Buf>(r: &mut R, version: Version) -> Result<Self, DecodeError> {
284		let request_id = RequestId::decode(r, version)?;
285		let error_code = u64::decode(r, version)?;
286		let reason_phrase = Cow::<str>::decode(r, version)?;
287		Ok(Self {
288			request_id,
289			error_code,
290			reason_phrase,
291		})
292	}
293}