1use crate::draft15::message::ControlMessage;
2use crate::fields::{FieldMap as Map, FieldValue as Value};
3use crate::kvp::{KeyValuePair, KvpValue};
4use crate::types::*;
5use crate::varint::VarInt;
6
7fn vi(v: u64) -> Value {
8 Value::Uint(v)
9}
10
11fn ns_to_json(ns: &TrackNamespace) -> Value {
12 Value::Array(
13 ns.0.iter().map(|e| Value::Text(String::from_utf8_lossy(e).into_owned())).collect(),
14 )
15}
16
17fn d15_setup_param_name(key: u64) -> Option<&'static str> {
18 match key {
19 0x01 => Some("path"),
20 0x02 => Some("max_request_id"),
21 0x03 => Some("authorization_token"),
22 0x04 => Some("max_auth_token_cache_size"),
23 0x05 => Some("authority"),
24 0x07 => Some("moqt_implementation"),
25 _ => None,
26 }
27}
28
29fn d15_msg_param_name(key: u64) -> Option<&'static str> {
30 match key {
31 0x02 => Some("delivery_timeout"),
32 0x03 => Some("authorization_token"),
33 0x04 => Some("max_cache_duration"),
34 0x08 => Some("expires"),
35 0x09 => Some("largest_object"),
36 0x0e => Some("publisher_priority"),
37 0x10 => Some("forward"),
38 0x20 => Some("subscriber_priority"),
39 0x21 => Some("subscription_filter"),
40 0x22 => Some("group_order"),
41 0x30 => Some("dynamic_groups"),
42 0x32 => Some("new_group_request"),
43 _ => None,
44 }
45}
46
47fn decode_subscription_filter(bytes: &[u8]) -> Value {
48 let mut buf = bytes;
49 let filter_type = VarInt::decode(&mut buf).unwrap().into_inner();
50 let mut obj = Map::new();
51 obj.insert("filter_type".into(), vi(filter_type));
52 match filter_type {
53 3 => {
54 let start_group = VarInt::decode(&mut buf).unwrap().into_inner();
56 let start_object = VarInt::decode(&mut buf).unwrap().into_inner();
57 obj.insert("start_group".into(), vi(start_group));
58 obj.insert("start_object".into(), vi(start_object));
59 }
60 4 => {
61 let start_group = VarInt::decode(&mut buf).unwrap().into_inner();
63 let start_object = VarInt::decode(&mut buf).unwrap().into_inner();
64 let end_group = VarInt::decode(&mut buf).unwrap().into_inner();
65 obj.insert("start_group".into(), vi(start_group));
66 obj.insert("start_object".into(), vi(start_object));
67 obj.insert("end_group".into(), vi(end_group));
68 }
69 _ => {
70 }
72 }
73 Value::Map(obj)
74}
75
76fn decode_largest_object(bytes: &[u8]) -> Value {
102 let mut buf = bytes;
103 let Ok(group) = VarInt::decode(&mut buf) else {
104 return Value::Bytes(bytes.to_vec());
105 };
106 let Ok(object) = VarInt::decode(&mut buf) else {
107 return Value::Bytes(bytes.to_vec());
108 };
109 let mut obj = Map::new();
110 obj.insert("group".into(), vi(group.into_inner()));
111 obj.insert("object".into(), vi(object.into_inner()));
112 Value::Map(obj)
113}
114
115fn auth_token_to_json_d15(bytes: &[u8]) -> Value {
117 let mut buf = bytes;
118 let alias_type = match VarInt::decode(&mut buf) {
119 Ok(v) => v,
120 Err(_) => return Value::Bytes(bytes.to_vec()),
121 };
122 let at = alias_type.into_inner();
123 let mut o = Map::new();
124 o.insert("alias_type".into(), vi(at));
125 match at {
126 0 | 2 => {
127 if let Ok(ta) = VarInt::decode(&mut buf) {
128 o.insert("token_alias".into(), vi(ta.into_inner()));
129 }
130 }
131 1 => {
132 if let Ok(ta) = VarInt::decode(&mut buf) {
133 o.insert("token_alias".into(), vi(ta.into_inner()));
134 }
135 if let Ok(tt) = VarInt::decode(&mut buf) {
136 o.insert("token_type".into(), vi(tt.into_inner()));
137 }
138 o.insert("token_value".into(), Value::Bytes(buf.to_vec()));
139 }
140 _ => {
141 if let Ok(tt) = VarInt::decode(&mut buf) {
142 o.insert("token_type".into(), vi(tt.into_inner()));
143 }
144 o.insert("token_value".into(), Value::Bytes(buf.to_vec()));
145 }
146 }
147 Value::Map(o)
148}
149
150fn kvp_to_json_d15_inner(
151 params: &[KeyValuePair],
152 name_fn: fn(u64) -> Option<&'static str>,
153) -> Value {
154 crate::fields::kvp_entries(params, |key, value| {
155 let Some(name) = name_fn(key) else {
156 return (None, None);
157 };
158 let rendered = match (value, key) {
159 (KvpValue::Bytes(b), 0x21) => decode_subscription_filter(b),
160 (KvpValue::Bytes(b), 0x09) => decode_largest_object(b),
161 (KvpValue::Bytes(b), _) if name == "authorization_token" => auth_token_to_json_d15(b),
162 (KvpValue::Varint(v), _) => vi(v.into_inner()),
163 (KvpValue::Bytes(b), _) => Value::Text(String::from_utf8_lossy(b).into_owned()),
164 };
165 (Some(name), Some(rendered))
166 })
167}
168
169fn kvp_to_json_d15(params: &[KeyValuePair]) -> Value {
170 kvp_to_json_d15_inner(params, d15_msg_param_name)
171}
172
173fn kvp_to_json_d15_setup(params: &[KeyValuePair]) -> Value {
174 kvp_to_json_d15_inner(params, d15_setup_param_name)
175}
176
177pub fn message_fields(msg: &ControlMessage) -> Map {
183 let obj = match msg {
184 ControlMessage::ClientSetup(m) => {
185 let mut o = Map::new();
186 o.insert("parameters".into(), kvp_to_json_d15_setup(&m.parameters));
187 o
188 }
189 ControlMessage::ServerSetup(m) => {
190 let mut o = Map::new();
191 o.insert("parameters".into(), kvp_to_json_d15_setup(&m.parameters));
192 o
193 }
194 ControlMessage::GoAway(m) => {
195 let mut o = Map::new();
196 o.insert(
197 "new_session_uri".into(),
198 Value::Text(String::from_utf8_lossy(&m.new_session_uri).into_owned()),
199 );
200 o
201 }
202 ControlMessage::MaxRequestId(m) => {
203 let mut o = Map::new();
204 o.insert("max_request_id".into(), vi(m.request_id.into_inner()));
205 o
206 }
207 ControlMessage::RequestsBlocked(m) => {
208 let mut o = Map::new();
209 o.insert("maximum_request_id".into(), vi(m.maximum_request_id.into_inner()));
210 o
211 }
212 ControlMessage::RequestOk(m) => {
213 let mut o = Map::new();
214 o.insert("request_id".into(), vi(m.request_id.into_inner()));
215 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
216 o
217 }
218 ControlMessage::RequestError(m) => {
219 let mut o = Map::new();
220 o.insert("request_id".into(), vi(m.request_id.into_inner()));
221 o.insert("error_code".into(), vi(m.error_code.into_inner()));
222 o.insert(
223 "reason_phrase".into(),
224 Value::Text(String::from_utf8_lossy(&m.reason_phrase).into_owned()),
225 );
226 o
227 }
228 ControlMessage::Subscribe(m) => {
229 let mut o = Map::new();
230 o.insert("request_id".into(), vi(m.request_id.into_inner()));
231 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
232 o.insert(
233 "track_name".into(),
234 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
235 );
236 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
237 o
238 }
239 ControlMessage::SubscribeOk(m) => {
240 let mut o = Map::new();
241 o.insert("request_id".into(), vi(m.request_id.into_inner()));
242 o.insert("track_alias".into(), vi(m.track_alias.into_inner()));
243 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
244 o
245 }
246 ControlMessage::SubscribeUpdate(m) => {
247 let mut o = Map::new();
248 o.insert("request_id".into(), vi(m.request_id.into_inner()));
249 o.insert("subscription_request_id".into(), vi(m.subscription_request_id.into_inner()));
250 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
251 o
252 }
253 ControlMessage::Unsubscribe(m) => {
254 let mut o = Map::new();
255 o.insert("request_id".into(), vi(m.request_id.into_inner()));
256 o
257 }
258 ControlMessage::Publish(m) => {
259 let mut o = Map::new();
260 o.insert("request_id".into(), vi(m.request_id.into_inner()));
261 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
262 o.insert(
263 "track_name".into(),
264 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
265 );
266 o.insert("track_alias".into(), vi(m.track_alias.into_inner()));
267 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
268 o
269 }
270 ControlMessage::PublishOk(m) => {
271 let mut o = Map::new();
272 o.insert("request_id".into(), vi(m.request_id.into_inner()));
273 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
274 o
275 }
276 ControlMessage::PublishDone(m) => {
277 let mut o = Map::new();
278 o.insert("request_id".into(), vi(m.request_id.into_inner()));
279 o.insert("status_code".into(), vi(m.status_code.into_inner()));
280 o.insert("stream_count".into(), vi(m.stream_count.into_inner()));
281 o.insert(
282 "reason_phrase".into(),
283 Value::Text(String::from_utf8_lossy(&m.reason_phrase).into_owned()),
284 );
285 o
286 }
287 ControlMessage::PublishNamespace(m) => {
288 let mut o = Map::new();
289 o.insert("request_id".into(), vi(m.request_id.into_inner()));
290 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
291 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
292 o
293 }
294 ControlMessage::PublishNamespaceDone(m) => {
295 let mut o = Map::new();
296 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
297 o
298 }
299 ControlMessage::PublishNamespaceCancel(m) => {
300 let mut o = Map::new();
301 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
302 o.insert("error_code".into(), vi(m.error_code.into_inner()));
303 o.insert(
304 "reason_phrase".into(),
305 Value::Text(String::from_utf8_lossy(&m.reason_phrase).into_owned()),
306 );
307 o
308 }
309 ControlMessage::SubscribeNamespace(m) => {
310 let mut o = Map::new();
311 o.insert("request_id".into(), vi(m.request_id.into_inner()));
312 o.insert("namespace_prefix".into(), ns_to_json(&m.namespace_prefix));
313 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
314 o
315 }
316 ControlMessage::UnsubscribeNamespace(m) => {
317 let mut o = Map::new();
318 o.insert("request_id".into(), vi(m.request_id.into_inner()));
319 o
320 }
321 ControlMessage::TrackStatus(m) => {
322 let mut o = Map::new();
323 o.insert("request_id".into(), vi(m.request_id.into_inner()));
324 o.insert("track_namespace".into(), ns_to_json(&m.track_namespace));
325 o.insert(
326 "track_name".into(),
327 Value::Text(String::from_utf8_lossy(&m.track_name).into_owned()),
328 );
329 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
330 o
331 }
332 ControlMessage::Fetch(m) => {
333 let mut o = Map::new();
334 o.insert("request_id".into(), vi(m.request_id.into_inner()));
335 o.insert("fetch_type".into(), vi(m.fetch_type as u64));
336 match &m.fetch_payload {
337 crate::draft15::message::FetchPayload::Standalone {
338 track_namespace,
339 track_name,
340 start_group,
341 start_object,
342 end_group,
343 end_object,
344 } => {
345 o.insert("track_namespace".into(), ns_to_json(track_namespace));
346 o.insert(
347 "track_name".into(),
348 Value::Text(String::from_utf8_lossy(track_name).into_owned()),
349 );
350 o.insert("start_group".into(), vi(start_group.into_inner()));
351 o.insert("start_object".into(), vi(start_object.into_inner()));
352 o.insert("end_group".into(), vi(end_group.into_inner()));
353 o.insert("end_object".into(), vi(end_object.into_inner()));
354 }
355 crate::draft15::message::FetchPayload::Joining {
356 joining_request_id,
357 joining_start,
358 } => {
359 o.insert("joining_request_id".into(), vi(joining_request_id.into_inner()));
360 o.insert("joining_start".into(), vi(joining_start.into_inner()));
361 }
362 }
363 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
364 o
365 }
366 ControlMessage::FetchOk(m) => {
367 let mut o = Map::new();
368 o.insert("request_id".into(), vi(m.request_id.into_inner()));
369 o.insert("end_of_track".into(), vi(m.end_of_track as u64));
370 o.insert("end_group".into(), vi(m.end_group.into_inner()));
371 o.insert("end_object".into(), vi(m.end_object.into_inner()));
372 o.insert("parameters".into(), kvp_to_json_d15(&m.parameters));
373 o
374 }
375 ControlMessage::FetchCancel(m) => {
376 let mut o = Map::new();
377 o.insert("request_id".into(), vi(m.request_id.into_inner()));
378 o
379 }
380 };
381 obj
382}