1use std::sync::Arc;
2
3use crate::ffi;
4
5pub const MOQ_ERROR_MOQ: i32 = -2;
8pub const MOQ_ERROR_URL: i32 = -3;
9pub const MOQ_ERROR_UTF8: i32 = -4;
10pub const MOQ_ERROR_CONNECT: i32 = -5;
11pub const MOQ_ERROR_INVALID_POINTER: i32 = -6;
12pub const MOQ_ERROR_INVALID_ID: i32 = -7;
13pub const MOQ_ERROR_NOT_FOUND: i32 = -8;
14pub const MOQ_ERROR_UNKNOWN_FORMAT: i32 = -9;
15pub const MOQ_ERROR_INIT_FAILED: i32 = -10;
16pub const MOQ_ERROR_TIMESTAMP_OVERFLOW: i32 = -13;
17pub const MOQ_ERROR_LEVEL: i32 = -14;
18pub const MOQ_ERROR_INVALID_CODE: i32 = -15;
19pub const MOQ_ERROR_PANIC: i32 = -16;
20pub const MOQ_ERROR_OFFLINE: i32 = -17;
21pub const MOQ_ERROR_HANG: i32 = -18;
22pub const MOQ_ERROR_NO_INDEX: i32 = -19;
23pub const MOQ_ERROR_NUL: i32 = -20;
24pub const MOQ_ERROR_SESSION_NOT_FOUND: i32 = -21;
25pub const MOQ_ERROR_ORIGIN_NOT_FOUND: i32 = -22;
26pub const MOQ_ERROR_ANNOUNCEMENT_NOT_FOUND: i32 = -23;
27pub const MOQ_ERROR_BROADCAST_NOT_FOUND: i32 = -24;
28pub const MOQ_ERROR_CATALOG_NOT_FOUND: i32 = -25;
29pub const MOQ_ERROR_MEDIA_NOT_FOUND: i32 = -26;
30pub const MOQ_ERROR_TRACK_NOT_FOUND: i32 = -27;
31pub const MOQ_ERROR_FRAME_NOT_FOUND: i32 = -28;
32pub const MOQ_ERROR_MUX: i32 = -29;
33pub const MOQ_ERROR_AUDIO: i32 = -30;
34pub const MOQ_ERROR_BUFFER_NOT_CONSUMED: i32 = -31;
35pub const MOQ_ERROR_GROUP_NOT_FOUND: i32 = -32;
36pub const MOQ_ERROR_NATIVE: i32 = -33;
37pub const MOQ_ERROR_UNAUTHORIZED: i32 = -34;
38pub const MOQ_ERROR_FORBIDDEN: i32 = -35;
39pub const MOQ_ERROR_VIDEO: i32 = -36;
40pub const MOQ_ERROR_JSON: i32 = -37;
41pub const MOQ_ERROR_JSON_TRACK: i32 = -38;
42pub const MOQ_ERROR_INVALID_CONFIG: i32 = -40;
43pub const MOQ_ERROR_UNRESOLVABLE_BROADCAST: i32 = -41;
44
45#[repr(C)]
47#[allow(non_camel_case_types)]
48#[derive(Clone, Copy, Debug)]
49pub enum moq_error_scope {
50 MOQ_ERROR_SCOPE_SESSION = 0,
52 MOQ_ERROR_SCOPE_STREAM = 1,
54}
55
56#[repr(C)]
59#[allow(non_camel_case_types)]
60#[derive(Clone, Copy, Debug)]
61pub enum moq_protocol_kind {
62 MOQ_PROTOCOL_KIND_CANCEL = 0,
64 MOQ_PROTOCOL_KIND_INTERNAL = 1,
66 MOQ_PROTOCOL_KIND_UNAUTHORIZED = 2,
68 MOQ_PROTOCOL_KIND_PROTOCOL_VIOLATION = 3,
70 MOQ_PROTOCOL_KIND_KEY_VALUE_FORMATTING = 4,
72 MOQ_PROTOCOL_KIND_GOAWAY_TIMEOUT = 5,
74 MOQ_PROTOCOL_KIND_TIMEOUT = 6,
76 MOQ_PROTOCOL_KIND_VERSION = 7,
78 MOQ_PROTOCOL_KIND_DELIVERY_TIMEOUT = 11,
81 MOQ_PROTOCOL_KIND_SESSION_CLOSED = 12,
83 MOQ_PROTOCOL_KIND_GOING_AWAY = 13,
85 MOQ_PROTOCOL_KIND_TOO_FAR_BEHIND = 14,
87 MOQ_PROTOCOL_KIND_MALFORMED_TRACK = 15,
89 MOQ_PROTOCOL_KIND_NOT_FOUND = 16,
91 MOQ_PROTOCOL_KIND_UNROUTABLE = 17,
93 MOQ_PROTOCOL_KIND_OLD = 18,
95 MOQ_PROTOCOL_KIND_EVICTED = 19,
97 MOQ_PROTOCOL_KIND_WRONG_SIZE = 20,
99 MOQ_PROTOCOL_KIND_FRAME_TOO_LARGE = 21,
101 MOQ_PROTOCOL_KIND_TIMESTAMP_MISMATCH = 22,
103 MOQ_PROTOCOL_KIND_APP = 23,
105 MOQ_PROTOCOL_KIND_UNKNOWN = 24,
107}
108
109#[repr(C)]
114#[allow(non_camel_case_types)]
115#[derive(Clone, Copy, Debug)]
116pub struct moq_protocol_error {
117 pub scope: u32,
119 pub code: u32,
121 pub kind: u32,
123}
124
125pub type Status = i32;
130
131#[derive(Debug, thiserror::Error, Clone)]
136#[non_exhaustive]
137pub enum Error {
138 #[error("moq error: {0}")]
140 Moq(#[from] moq_net::Error),
141
142 #[error("native error: {0}")]
144 Native(#[from] moq_tokio::Error),
145
146 #[error("url error: {0}")]
148 Url(String),
149
150 #[error("utf8 error: {0}")]
152 Utf8(#[from] std::str::Utf8Error),
153
154 #[error("connect error: {0}")]
156 Connect(Arc<anyhow::Error>),
157
158 #[error("invalid pointer")]
160 InvalidPointer,
161
162 #[error("invalid id")]
164 InvalidId,
165
166 #[error("not found")]
168 NotFound,
169
170 #[error("session not found")]
172 SessionNotFound,
173
174 #[error("origin not found")]
176 OriginNotFound,
177
178 #[error("announcement not found")]
180 AnnouncementNotFound,
181
182 #[error("broadcast not found")]
184 BroadcastNotFound,
185
186 #[error("catalog not found")]
188 CatalogNotFound,
189
190 #[error("media not found")]
192 MediaNotFound,
193
194 #[error("track not found")]
196 TrackNotFound,
197
198 #[error("group not found")]
200 GroupNotFound,
201
202 #[error("frame not found")]
204 FrameNotFound,
205
206 #[error("unknown format: {0}")]
208 UnknownFormat(String),
209
210 #[error("init failed: {0}")]
212 InitFailed(Arc<anyhow::Error>),
213
214 #[error("buffer was not fully consumed")]
216 BufferNotConsumed,
217
218 #[error("timestamp overflow")]
220 TimestampOverflow(#[from] moq_net::TimeOverflow),
221
222 #[error("level error: {0}")]
224 Level(String),
225
226 #[error("invalid code")]
228 InvalidCode,
229
230 #[error("panic")]
232 Panic,
233
234 #[error("offline")]
236 Offline,
237
238 #[error("unauthorized")]
240 Unauthorized,
241
242 #[error("forbidden")]
244 Forbidden,
245
246 #[error("hang error: {0}")]
248 Hang(#[from] hang::Error),
249
250 #[error("mux error: {0}")]
252 Mux(#[from] moq_mux::Error),
253
254 #[error("no index")]
256 NoIndex,
257
258 #[error("nul error")]
260 NulError(#[from] std::ffi::NulError),
261
262 #[error("audio error: {0}")]
264 Audio(Arc<moq_audio::Error>),
265
266 #[error("video error: {0}")]
268 Video(Arc<moq_video::Error>),
269
270 #[error("json error: {0}")]
272 Json(String),
273
274 #[error("json track error: {0}")]
276 JsonTrack(Arc<moq_json::Error>),
277
278 #[error("invalid config: {0}")]
280 InvalidConfig(String),
281
282 #[error("unresolvable broadcast reference: {0}")]
285 UnresolvableBroadcast(String),
286}
287
288impl From<moq_json::Error> for Error {
289 fn from(err: moq_json::Error) -> Self {
290 match err {
291 moq_json::Error::Net(e) => Error::Moq(e),
292 e => Error::JsonTrack(Arc::new(e)),
293 }
294 }
295}
296
297impl From<serde_json::Error> for Error {
300 fn from(err: serde_json::Error) -> Self {
301 Error::Json(err.to_string())
302 }
303}
304
305impl From<moq_net::InvalidPattern> for Error {
306 fn from(err: moq_net::InvalidPattern) -> Self {
307 Error::InvalidConfig(err.to_string())
308 }
309}
310
311impl From<url::ParseError> for Error {
312 fn from(err: url::ParseError) -> Self {
313 Error::Url(err.to_string())
314 }
315}
316
317impl From<moq_audio::Error> for Error {
318 fn from(err: moq_audio::Error) -> Self {
319 Error::Audio(Arc::new(err))
320 }
321}
322
323impl From<moq_video::Error> for Error {
324 fn from(err: moq_video::Error) -> Self {
325 Error::Video(Arc::new(err))
326 }
327}
328
329impl From<tracing::metadata::ParseLevelError> for Error {
330 fn from(err: tracing::metadata::ParseLevelError) -> Self {
331 Error::Level(err.to_string())
332 }
333}
334
335impl Error {
336 pub(crate) fn protocol(&self) -> Option<moq_protocol_error> {
338 std::iter::successors(Some(self as &(dyn std::error::Error + 'static)), |err| err.source())
339 .find_map(|err| err.downcast_ref::<moq_net::Error>().and_then(protocol_of_net))
340 }
341}
342
343fn protocol_of_net(err: &moq_net::Error) -> Option<moq_protocol_error> {
344 match err {
345 moq_net::Error::Transport(_) => None,
346 moq_net::Error::Session(err) => Some(from_session(err)),
347 moq_net::Error::Stream(err) => Some(from_stream(err)),
348 moq_net::Error::App(app) => Some(from_stream(&moq_net::StreamError::App(*app))),
349 _ => None,
350 }
351}
352
353fn from_session(err: &moq_net::SessionError) -> moq_protocol_error {
354 moq_protocol_error {
355 scope: moq_error_scope::MOQ_ERROR_SCOPE_SESSION as u32,
356 code: err.to_code(),
357 kind: session_kind(err) as u32,
358 }
359}
360
361fn from_stream(err: &moq_net::StreamError) -> moq_protocol_error {
362 moq_protocol_error {
363 scope: moq_error_scope::MOQ_ERROR_SCOPE_STREAM as u32,
364 code: err.to_code(),
365 kind: stream_kind(err) as u32,
366 }
367}
368
369fn session_kind(err: &moq_net::SessionError) -> moq_protocol_kind {
370 use moq_protocol_kind::*;
371 match err {
372 moq_net::SessionError::Cancel => MOQ_PROTOCOL_KIND_CANCEL,
373 moq_net::SessionError::Internal => MOQ_PROTOCOL_KIND_INTERNAL,
374 moq_net::SessionError::Unauthorized => MOQ_PROTOCOL_KIND_UNAUTHORIZED,
375 moq_net::SessionError::ProtocolViolation => MOQ_PROTOCOL_KIND_PROTOCOL_VIOLATION,
376 moq_net::SessionError::KeyValueFormatting => MOQ_PROTOCOL_KIND_KEY_VALUE_FORMATTING,
377 moq_net::SessionError::GoawayTimeout => MOQ_PROTOCOL_KIND_GOAWAY_TIMEOUT,
378 moq_net::SessionError::Timeout => MOQ_PROTOCOL_KIND_TIMEOUT,
379 moq_net::SessionError::Version => MOQ_PROTOCOL_KIND_VERSION,
380 moq_net::SessionError::App(_) => MOQ_PROTOCOL_KIND_APP,
381 moq_net::SessionError::Unknown(_) => MOQ_PROTOCOL_KIND_UNKNOWN,
382 _ => MOQ_PROTOCOL_KIND_UNKNOWN,
383 }
384}
385
386fn stream_kind(err: &moq_net::StreamError) -> moq_protocol_kind {
387 use moq_protocol_kind::*;
388 match err {
389 moq_net::StreamError::Session(_) => MOQ_PROTOCOL_KIND_SESSION_CLOSED,
390 moq_net::StreamError::Internal => MOQ_PROTOCOL_KIND_INTERNAL,
391 moq_net::StreamError::Cancel => MOQ_PROTOCOL_KIND_CANCEL,
392 moq_net::StreamError::DeliveryTimeout => MOQ_PROTOCOL_KIND_DELIVERY_TIMEOUT,
393 moq_net::StreamError::GoingAway => MOQ_PROTOCOL_KIND_GOING_AWAY,
394 moq_net::StreamError::TooFarBehind => MOQ_PROTOCOL_KIND_TOO_FAR_BEHIND,
395 moq_net::StreamError::MalformedTrack => MOQ_PROTOCOL_KIND_MALFORMED_TRACK,
396 moq_net::StreamError::NotFound => MOQ_PROTOCOL_KIND_NOT_FOUND,
397 moq_net::StreamError::Unroutable => MOQ_PROTOCOL_KIND_UNROUTABLE,
398 moq_net::StreamError::Old => MOQ_PROTOCOL_KIND_OLD,
399 moq_net::StreamError::Evicted => MOQ_PROTOCOL_KIND_EVICTED,
400 moq_net::StreamError::WrongSize => MOQ_PROTOCOL_KIND_WRONG_SIZE,
401 moq_net::StreamError::FrameTooLarge => MOQ_PROTOCOL_KIND_FRAME_TOO_LARGE,
402 moq_net::StreamError::TimestampMismatch => MOQ_PROTOCOL_KIND_TIMESTAMP_MISMATCH,
403 moq_net::StreamError::App(_) => MOQ_PROTOCOL_KIND_APP,
404 moq_net::StreamError::Unknown(_) => MOQ_PROTOCOL_KIND_UNKNOWN,
405 _ => MOQ_PROTOCOL_KIND_UNKNOWN,
406 }
407}
408
409impl ffi::ReturnCode for Error {
410 fn error(&self) -> Option<&Error> {
411 Some(self)
412 }
413
414 fn code(&self) -> i32 {
415 match self {
416 Error::Moq(_) => MOQ_ERROR_MOQ,
417 Error::Url(_) => MOQ_ERROR_URL,
418 Error::Utf8(_) => MOQ_ERROR_UTF8,
419 Error::Connect(_) => MOQ_ERROR_CONNECT,
420 Error::InvalidPointer => MOQ_ERROR_INVALID_POINTER,
421 Error::InvalidId => MOQ_ERROR_INVALID_ID,
422 Error::NotFound => MOQ_ERROR_NOT_FOUND,
423 Error::UnknownFormat(_) => MOQ_ERROR_UNKNOWN_FORMAT,
424 Error::InitFailed(_) => MOQ_ERROR_INIT_FAILED,
425 Error::TimestampOverflow(_) => MOQ_ERROR_TIMESTAMP_OVERFLOW,
426 Error::Level(_) => MOQ_ERROR_LEVEL,
427 Error::InvalidCode => MOQ_ERROR_INVALID_CODE,
428 Error::Panic => MOQ_ERROR_PANIC,
429 Error::Offline => MOQ_ERROR_OFFLINE,
430 Error::Hang(_) => MOQ_ERROR_HANG,
431 Error::NoIndex => MOQ_ERROR_NO_INDEX,
432 Error::NulError(_) => MOQ_ERROR_NUL,
433 Error::SessionNotFound => MOQ_ERROR_SESSION_NOT_FOUND,
434 Error::OriginNotFound => MOQ_ERROR_ORIGIN_NOT_FOUND,
435 Error::AnnouncementNotFound => MOQ_ERROR_ANNOUNCEMENT_NOT_FOUND,
436 Error::BroadcastNotFound => MOQ_ERROR_BROADCAST_NOT_FOUND,
437 Error::CatalogNotFound => MOQ_ERROR_CATALOG_NOT_FOUND,
438 Error::MediaNotFound => MOQ_ERROR_MEDIA_NOT_FOUND,
439 Error::TrackNotFound => MOQ_ERROR_TRACK_NOT_FOUND,
440 Error::FrameNotFound => MOQ_ERROR_FRAME_NOT_FOUND,
441 Error::Mux(_) => MOQ_ERROR_MUX,
442 Error::Audio(_) => MOQ_ERROR_AUDIO,
443 Error::BufferNotConsumed => MOQ_ERROR_BUFFER_NOT_CONSUMED,
444 Error::GroupNotFound => MOQ_ERROR_GROUP_NOT_FOUND,
445 Error::Native(_) => MOQ_ERROR_NATIVE,
446 Error::Unauthorized => MOQ_ERROR_UNAUTHORIZED,
447 Error::Forbidden => MOQ_ERROR_FORBIDDEN,
448 Error::Video(_) => MOQ_ERROR_VIDEO,
449 Error::Json(_) => MOQ_ERROR_JSON,
450 Error::JsonTrack(_) => MOQ_ERROR_JSON_TRACK,
451 Error::InvalidConfig(_) => MOQ_ERROR_INVALID_CONFIG,
452 Error::UnresolvableBroadcast(_) => MOQ_ERROR_UNRESOLVABLE_BROADCAST,
453 }
454 }
455}