1use crate::draft22::message::ControlMessage;
2use crate::fields::{FieldMap as Map, FieldValue as Value};
3use crate::kvp::{KeyValuePair, KvpValue};
4use crate::range_filter::RangeFilter;
5use crate::types::*;
6use crate::varint::{Moqt18 as Wire, VarInt};
7
8fn vi(v: u64) -> Value {
9 Value::Uint(v)
10}
11
12fn ns_to_json(ns: &TrackNamespace) -> Value {
13 Value::Array(
14 ns.0.iter().map(|e| Value::Text(String::from_utf8_lossy(e).into_owned())).collect(),
15 )
16}
17
18fn d20_param_name(key: u64) -> Option<&'static str> {
21 match key {
22 0x02 => Some("object_delivery_timeout"),
23 0x03 => Some("authorization_token"),
24 0x04 => Some("rendezvous_timeout"),
25 0x06 => Some("subgroup_delivery_timeout"),
26 0x08 => Some("expires"),
27 0x09 => Some("largest_object"),
28 0x0A => Some("fill_timeout"),
29 0x10 => Some("forward"),
30 0x20 => Some("subscriber_priority"),
31 0x21 => Some("location_filter"),
32 0x22 => Some("group_order"),
33 0x23 => Some("fill_parameters"),
34 0x25 => Some("subgroup_filter"),
35 0x26 => Some("objectid_filter"),
36 0x27 => Some("priority_filter"),
37 0x28 => Some("object_property_filter"),
38 0x29 => Some("track_property_filter"),
39 0x32 => Some("new_group_request"),
40 0x34 => Some("track_namespace_prefix"),
41 0x35 => Some("include_properties"),
42 _ => None,
43 }
44}
45
46fn d20_option_name(key: u64) -> Option<&'static str> {
49 match key {
50 0x01 => Some("path"),
51 0x03 => Some("authorization_token"),
52 0x04 => Some("max_auth_token_cache_size"),
53 0x05 => Some("authority"),
54 0x06 => Some("max_filter_ranges"),
55 0x07 => Some("moqt_implementation"),
56 0x08 => Some("max_request_updates"),
57 _ => None,
58 }
59}
60
61fn decode_range_filter(bytes: &[u8], parameter_type: u64) -> Value {
109 let mut o = Map::new();
110 if bytes.is_empty() {
111 o.insert("removed".into(), Value::Bool(true));
112 return Value::Map(o);
113 }
114 let Ok(filter) = RangeFilter::decode_moqt_structure::<Wire>(parameter_type, bytes) else {
115 return Value::Bytes(bytes.to_vec());
116 };
117 if let Err(broken) = filter.check_its_own_types() {
118 o.insert("violates".into(), Value::Text(broken.to_string()));
119 }
120 o.insert("set_id".into(), vi(filter.set_id as u64));
121 if let Some(property_type) = filter.property_type {
122 o.insert("property_type".into(), vi(property_type));
123 }
124 let ranges = filter
125 .ranges
126 .iter()
127 .map(|range| {
128 let mut r = Map::new();
129 r.insert("start".into(), vi(range.start));
130 if let Some(end) = range.end {
131 r.insert("end".into(), vi(end));
132 }
133 Value::Map(r)
134 })
135 .collect();
136 o.insert("ranges".into(), Value::Array(ranges));
137 Value::Map(o)
138}
139
140fn decode_location_filter(bytes: &[u8]) -> Value {
152 const NAMES: [&str; 4] = ["start_group", "start_object", "end_group_delta", "end_object"];
153 let (filter_type, fields) = crate::draft22::message::decode_location_filter(bytes)
154 .expect("the decoder accepted this parameter, so its value parses");
155 let mut obj = Map::new();
156 obj.insert("filter_type".into(), vi(filter_type));
157 for (name, value) in NAMES.iter().zip(fields) {
158 obj.insert((*name).to_string(), vi(value));
159 }
160 Value::Map(obj)
161}
162
163fn decode_fill_parameters(bytes: &[u8]) -> Value {
170 let nested = crate::draft22::message::decode_fill_parameters(bytes)
171 .expect("the decoder accepted this parameter, so its value parses");
172 params_to_json(&nested)
173}
174
175fn auth_token_to_json_d20(bytes: &[u8]) -> Value {
176 let mut buf = bytes;
177 let alias_type = match VarInt::decode_moqt::<Wire>(&mut buf) {
178 Ok(v) => v,
179 Err(_) => return Value::Bytes(bytes.to_vec()),
180 };
181 let at = alias_type.into_inner();
182 let mut o = Map::new();
183 o.insert("alias_type".into(), vi(at));
184 match at {
185 0 | 2 => {
186 if let Ok(ta) = VarInt::decode_moqt::<Wire>(&mut buf) {
187 o.insert("token_alias".into(), vi(ta.into_inner()));
188 }
189 }
190 1 => {
191 if let Ok(ta) = VarInt::decode_moqt::<Wire>(&mut buf) {
192 o.insert("token_alias".into(), vi(ta.into_inner()));
193 }
194 if let Ok(tt) = VarInt::decode_moqt::<Wire>(&mut buf) {
195 o.insert("token_type".into(), vi(tt.into_inner()));
196 }
197 o.insert("token_value".into(), Value::Bytes(buf.to_vec()));
200 }
201 _ => {
202 if let Ok(tt) = VarInt::decode_moqt::<Wire>(&mut buf) {
203 o.insert("token_type".into(), vi(tt.into_inner()));
204 }
205 o.insert("token_value".into(), Value::Bytes(buf.to_vec()));
206 }
207 }
208 Value::Map(o)
209}
210
211fn decode_largest_object(bytes: &[u8]) -> Value {
224 let mut buf = bytes;
225 let Ok(group) = VarInt::decode_moqt::<Wire>(&mut buf) else {
226 return Value::Bytes(bytes.to_vec());
227 };
228 let Ok(object) = VarInt::decode_moqt::<Wire>(&mut buf) else {
229 return Value::Bytes(bytes.to_vec());
230 };
231 let (group, object) = (group.into_inner(), object.into_inner());
232 let mut obj = Map::new();
233 obj.insert("group".into(), vi(group));
234 obj.insert("object".into(), vi(object));
235 Value::Map(obj)
236}
237
238fn decode_track_namespace_prefix(bytes: &[u8]) -> Value {
239 let mut buf = bytes;
240 match TrackNamespace::decode_allow_empty_moqt::<Wire>(&mut buf) {
241 Ok(ns) => ns_to_json(&ns),
242 Err(_) => Value::Bytes(bytes.to_vec()),
243 }
244}
245
246fn params_to_json(params: &[KeyValuePair]) -> Value {
247 crate::fields::kvp_entries(params, |key, value| {
248 let Some(name) = d20_param_name(key) else {
249 return (None, None);
250 };
251 let rendered = match (value, key) {
252 (KvpValue::Bytes(b), 0x21) => decode_location_filter(b),
253 (KvpValue::Bytes(b), 0x23) => decode_fill_parameters(b),
254 (KvpValue::Bytes(b), 0x25..=0x29) => decode_range_filter(b, key),
259 (KvpValue::Bytes(b), 0x09) => decode_largest_object(b),
260 (KvpValue::Bytes(b), 0x34) => decode_track_namespace_prefix(b),
261 (KvpValue::Bytes(b), _) if name == "authorization_token" => auth_token_to_json_d20(b),
262 (KvpValue::Varint(v), _) => vi(v.into_inner()),
263 (KvpValue::Bytes(b), _) => Value::Text(String::from_utf8_lossy(b).into_owned()),
264 };
265 (Some(name), Some(rendered))
266 })
267}
268
269pub(crate) fn options_to_json(options: &[KeyValuePair]) -> Value {
270 crate::fields::kvp_entries(options, |key, value| {
271 let Some(name) = d20_option_name(key) else {
272 return (None, None);
273 };
274 let rendered = match value {
275 KvpValue::Varint(v) => vi(v.into_inner()),
276 KvpValue::Bytes(b) if name == "authorization_token" => auth_token_to_json_d20(b),
277 KvpValue::Bytes(b) => Value::Text(String::from_utf8_lossy(b).into_owned()),
278 };
279 (Some(name), Some(rendered))
280 })
281}
282
283fn d20_track_prop_name(key: u64) -> Option<&'static str> {
284 match key {
285 0x02 => Some("object_delivery_timeout"),
286 0x04 => Some("max_cache_duration"),
287 0x06 => Some("subgroup_delivery_timeout"),
288 0x0b => Some("immutable_properties"),
289 0x0e => Some("default_publisher_priority"),
290 0x22 => Some("default_publisher_group_order"),
291 0x30 => Some("dynamic_groups"),
292 _ => None,
293 }
294}
295
296fn track_props_to_json(props: &[KeyValuePair]) -> Value {
297 crate::fields::kvp_entries(props, |key, value| {
298 let name = d20_track_prop_name(key);
299 let rendered = match value {
300 KvpValue::Varint(v) => Some(vi(v.into_inner())),
301 KvpValue::Bytes(_) => None,
305 };
306 (name, rendered)
307 })
308}
309
310pub fn message_fields(msg: &ControlMessage) -> Map {
316 let obj = match msg {
317 ControlMessage::Setup(m) => {
318 let mut o = Map::new();
319 o.insert("options".into(), options_to_json(&m.options));
320 o
321 }
322 ControlMessage::GoAway(m) => {
323 let mut o = Map::new();
324 o.insert(
325 "new_session_uri".into(),
326 Value::Text(String::from_utf8_lossy(&m.new_session_uri).into_owned()),
327 );
328 o.insert("timeout".into(), vi(m.timeout.into_inner()));
329 o
330 }
331 ControlMessage::RequestOk(m) => {
332 let mut o = Map::new();
333 o.insert("parameters".into(), params_to_json(&m.parameters));
334 o.insert("track_properties".into(), track_props_to_json(&m.track_properties));
335 o
336 }
337 ControlMessage::RequestError(m) => {
338 let mut o = Map::new();
339 o.insert("error_code".into(), vi(m.error_code.into_inner()));
340 o.insert("retry_interval".into(), vi(m.retry_interval.into_inner()));
341 o.insert(
342 "reason_phrase".into(),
343 Value::Text(String::from_utf8_lossy(&m.reason_phrase).into_owned()),
344 );
345 if let Some(r) = &m.redirect {
346 let mut r_obj = Map::new();
347 r_obj.insert(
348 "connect_uri".into(),
349 Value::Text(String::from_utf8_lossy(&r.connect_uri).into_owned()),
350 );
351 r_obj.insert("track_namespace".into(), ns_to_json(&r.track_namespace));
352 r_obj.insert(
353 "track_name".into(),
354 Value::Text(String::from_utf8_lossy(&r.track_name).into_owned()),
355 );
356 o.insert("redirect".into(), Value::Map(r_obj));
357 }
358 o
359 }
360 ControlMessage::Subscribe(m) => {
361 let mut o = Map::new();
362 o.insert("request_id".into(), vi(m.request_id.into_inner()));
363 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
364 o.insert(
365 "track_name".into(),
366 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
367 );
368 o.insert("parameters".into(), params_to_json(&m.parameters));
369 o
370 }
371 ControlMessage::SubscribeOk(m) => {
372 let mut o = Map::new();
373 o.insert("track_alias".into(), vi(m.track_alias.into_inner()));
374 o.insert("parameters".into(), params_to_json(&m.parameters));
375 o.insert("track_properties".into(), track_props_to_json(&m.track_properties));
376 o
377 }
378 ControlMessage::RequestUpdate(m) => {
379 let mut o = Map::new();
380 o.insert("request_id".into(), vi(m.request_id.into_inner()));
381 o.insert("parameters".into(), params_to_json(&m.parameters));
382 o
383 }
384 ControlMessage::Publish(m) => {
385 let mut o = Map::new();
386 o.insert("request_id".into(), vi(m.request_id.into_inner()));
387 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
388 o.insert(
389 "track_name".into(),
390 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
391 );
392 o.insert("track_alias".into(), vi(m.track_alias.into_inner()));
393 o.insert("parameters".into(), params_to_json(&m.parameters));
394 o.insert("track_properties".into(), track_props_to_json(&m.track_properties));
395 o
396 }
397 ControlMessage::PublishStateNotify(m) => {
400 let mut o = Map::new();
401 o.insert("parameters".into(), params_to_json(&m.parameters));
402 o
403 }
404 ControlMessage::PublishDone(m) => {
405 let mut o = Map::new();
406 o.insert("status_code".into(), vi(m.status_code.into_inner()));
407 o.insert("stream_count".into(), vi(m.stream_count.into_inner()));
408 o.insert(
409 "reason_phrase".into(),
410 Value::Text(String::from_utf8_lossy(&m.reason_phrase).into_owned()),
411 );
412 o
413 }
414 ControlMessage::PublishNamespace(m) => {
415 let mut o = Map::new();
416 o.insert("request_id".into(), vi(m.request_id.into_inner()));
417 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
418 o.insert("parameters".into(), params_to_json(&m.parameters));
419 o
420 }
421 ControlMessage::Namespace(m) => {
422 let mut o = Map::new();
423 o.insert("namespace_suffix".into(), ns_to_json(&m.namespace_suffix));
424 o
425 }
426 ControlMessage::NamespaceDone(m) => {
427 let mut o = Map::new();
428 o.insert("namespace_suffix".into(), ns_to_json(&m.namespace_suffix));
429 o
430 }
431 ControlMessage::SubscribeNamespace(m) => {
432 let mut o = Map::new();
433 o.insert("request_id".into(), vi(m.request_id.into_inner()));
434 o.insert("namespace_prefix".into(), ns_to_json(&m.namespace_prefix));
435 o.insert("parameters".into(), params_to_json(&m.parameters));
436 o
437 }
438 ControlMessage::SubscribeTracks(m) => {
439 let mut o = Map::new();
440 o.insert("request_id".into(), vi(m.request_id.into_inner()));
441 o.insert("namespace_prefix".into(), ns_to_json(&m.namespace_prefix));
442 o.insert("parameters".into(), params_to_json(&m.parameters));
443 o
444 }
445 ControlMessage::TrackStatus(m) => {
446 let mut o = Map::new();
447 o.insert("request_id".into(), vi(m.request_id.into_inner()));
448 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
449 o.insert(
450 "track_name".into(),
451 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
452 );
453 o.insert("parameters".into(), params_to_json(&m.parameters));
454 o
455 }
456 ControlMessage::Fetch(m) => {
459 let mut o = Map::new();
460 o.insert("request_id".into(), vi(m.request_id.into_inner()));
461 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
462 o.insert(
463 "track_name".into(),
464 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
465 );
466 o.insert("parameters".into(), params_to_json(&m.parameters));
467 o
468 }
469 ControlMessage::FetchOk(m) => {
470 let mut o = Map::new();
471 o.insert("end_of_track".into(), vi(m.end_of_track as u64));
472 o.insert("end_group".into(), vi(m.end_group.into_inner()));
473 o.insert("end_object".into(), vi(m.end_object.into_inner()));
474 o.insert("parameters".into(), params_to_json(&m.parameters));
475 o.insert("track_properties".into(), track_props_to_json(&m.track_properties));
476 o
477 }
478 ControlMessage::PublishSkipped(m) => {
479 let mut o = Map::new();
480 o.insert("namespace_suffix".into(), ns_to_json(&m.namespace_suffix));
481 o.insert(
482 "track_name".into(),
483 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
484 );
485 o
486 }
487 };
488 obj
489}