Skip to main content

moq_lite/
error.rs

1use crate::coding;
2
3/// A list of possible errors that can occur during the session.
4#[derive(thiserror::Error, Debug, Clone)]
5#[non_exhaustive]
6pub enum Error {
7	#[error("transport error")]
8	Transport,
9
10	#[error("decode error")]
11	Decode,
12
13	// TODO move to a ConnectError
14	#[error("unsupported versions")]
15	Version,
16
17	/// A required extension was not present
18	#[error("extension required")]
19	RequiredExtension,
20
21	/// An unexpected stream type was received
22	#[error("unexpected stream type")]
23	UnexpectedStream,
24
25	/// Some VarInt was too large and we were too lazy to handle it
26	#[error("varint bounds exceeded")]
27	BoundsExceeded,
28
29	/// A duplicate ID was used
30	// The broadcast/track is a duplicate
31	#[error("duplicate")]
32	Duplicate,
33
34	// Cancel is returned when there are no more readers.
35	#[error("cancelled")]
36	Cancel,
37
38	/// It took too long to open or transmit a stream.
39	#[error("timeout")]
40	Timeout,
41
42	/// The group is older than the latest group and dropped.
43	#[error("old")]
44	Old,
45
46	// The application closes the stream with a code.
47	#[error("app code={0}")]
48	App(u16),
49
50	#[error("not found")]
51	NotFound,
52
53	#[error("wrong frame size")]
54	WrongSize,
55
56	#[error("protocol violation")]
57	ProtocolViolation,
58
59	#[error("unauthorized")]
60	Unauthorized,
61
62	#[error("unexpected message")]
63	UnexpectedMessage,
64
65	#[error("unsupported")]
66	Unsupported,
67
68	#[error("too large")]
69	TooLarge,
70
71	#[error("too many parameters")]
72	TooManyParameters,
73
74	#[error("invalid role")]
75	InvalidRole,
76
77	#[error("unknown ALPN: {0}")]
78	UnknownAlpn(String),
79}
80
81impl Error {
82	/// An integer code that is sent over the wire.
83	pub fn to_code(&self) -> u32 {
84		match self {
85			Self::Cancel => 0,
86			Self::RequiredExtension => 1,
87			Self::Old => 2,
88			Self::Timeout => 3,
89			Self::Transport => 4,
90			Self::Decode => 5,
91			Self::Unauthorized => 6,
92			Self::Version => 9,
93			Self::UnexpectedStream => 10,
94			Self::BoundsExceeded => 11,
95			Self::Duplicate => 12,
96			Self::NotFound => 13,
97			Self::WrongSize => 14,
98			Self::ProtocolViolation => 15,
99			Self::UnexpectedMessage => 16,
100			Self::Unsupported => 17,
101			Self::TooLarge => 18,
102			Self::TooManyParameters => 19,
103			Self::InvalidRole => 20,
104			Self::UnknownAlpn(_) => 21,
105			Self::App(app) => *app as u32 + 64,
106		}
107	}
108
109	/// Decode an error from a wire code.
110	pub fn from_code(code: u32) -> Self {
111		match code {
112			0 => Self::Cancel,
113			1 => Self::RequiredExtension,
114			2 => Self::Old,
115			3 => Self::Timeout,
116			4 => Self::Transport,
117			5 => Self::Decode,
118			6 => Self::Unauthorized,
119			9 => Self::Version,
120			10 => Self::UnexpectedStream,
121			11 => Self::BoundsExceeded,
122			12 => Self::Duplicate,
123			13 => Self::NotFound,
124			14 => Self::WrongSize,
125			15 => Self::ProtocolViolation,
126			16 => Self::UnexpectedMessage,
127			17 => Self::Unsupported,
128			18 => Self::TooLarge,
129			19 => Self::TooManyParameters,
130			20 => Self::InvalidRole,
131			code if code >= 64 => match u16::try_from(code - 64) {
132				Ok(app) => Self::App(app),
133				Err(_) => Self::ProtocolViolation,
134			},
135			_ => Self::ProtocolViolation,
136		}
137	}
138
139	/// Convert a transport error into an [Error], decoding stream reset codes.
140	pub fn from_transport(err: impl web_transport_trait::Error) -> Self {
141		if let Some(code) = err.stream_error() {
142			return Self::from_code(code);
143		}
144
145		tracing::warn!(%err, "transport error");
146		Self::Transport
147	}
148}
149
150impl From<coding::DecodeError> for Error {
151	fn from(err: coding::DecodeError) -> Self {
152		tracing::warn!(%err, "decode error");
153		Error::Decode
154	}
155}
156
157impl From<coding::BoundsExceeded> for Error {
158	fn from(err: coding::BoundsExceeded) -> Self {
159		tracing::warn!(%err, "bounds exceeded");
160		Error::BoundsExceeded
161	}
162}
163
164pub type Result<T> = std::result::Result<T, Error>;