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("encode error")]
69	Encode,
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	#[error("dropped")]
81	Dropped,
82
83	#[error("closed")]
84	Closed,
85}
86
87impl Error {
88	/// An integer code that is sent over the wire.
89	pub fn to_code(&self) -> u32 {
90		match self {
91			Self::Cancel => 0,
92			Self::RequiredExtension => 1,
93			Self::Old => 2,
94			Self::Timeout => 3,
95			Self::Transport => 4,
96			Self::Decode => 5,
97			Self::Unauthorized => 6,
98			Self::Version => 9,
99			Self::UnexpectedStream => 10,
100			Self::BoundsExceeded => 11,
101			Self::Duplicate => 12,
102			Self::NotFound => 13,
103			Self::WrongSize => 14,
104			Self::ProtocolViolation => 15,
105			Self::UnexpectedMessage => 16,
106			Self::Unsupported => 17,
107			Self::Encode => 18,
108			Self::TooManyParameters => 19,
109			Self::InvalidRole => 20,
110			Self::UnknownAlpn(_) => 21,
111			Self::Dropped => 24,
112			Self::Closed => 25,
113			Self::App(app) => *app as u32 + 64,
114		}
115	}
116
117	/// Decode an error from a wire code.
118	pub fn from_code(code: u32) -> Self {
119		match code {
120			0 => Self::Cancel,
121			1 => Self::RequiredExtension,
122			2 => Self::Old,
123			3 => Self::Timeout,
124			4 => Self::Transport,
125			5 => Self::Decode,
126			6 => Self::Unauthorized,
127			9 => Self::Version,
128			10 => Self::UnexpectedStream,
129			11 => Self::BoundsExceeded,
130			12 => Self::Duplicate,
131			13 => Self::NotFound,
132			14 => Self::WrongSize,
133			15 => Self::ProtocolViolation,
134			16 => Self::UnexpectedMessage,
135			17 => Self::Unsupported,
136			18 => Self::Encode,
137			19 => Self::TooManyParameters,
138			20 => Self::InvalidRole,
139			24 => Self::Dropped,
140			25 => Self::Closed,
141			code if code >= 64 => match u16::try_from(code - 64) {
142				Ok(app) => Self::App(app),
143				Err(_) => Self::ProtocolViolation,
144			},
145			_ => Self::ProtocolViolation,
146		}
147	}
148
149	/// Convert a transport error into an [Error], decoding stream reset codes.
150	pub fn from_transport(err: impl web_transport_trait::Error) -> Self {
151		if let Some(code) = err.stream_error() {
152			return Self::from_code(code);
153		}
154
155		tracing::warn!(%err, "transport error");
156		Self::Transport
157	}
158}
159
160impl From<coding::DecodeError> for Error {
161	fn from(err: coding::DecodeError) -> Self {
162		tracing::warn!(%err, "decode error");
163		Error::Decode
164	}
165}
166
167impl From<coding::BoundsExceeded> for Error {
168	fn from(err: coding::BoundsExceeded) -> Self {
169		tracing::warn!(%err, "bounds exceeded");
170		Error::BoundsExceeded
171	}
172}
173
174impl From<coding::EncodeError> for Error {
175	fn from(err: coding::EncodeError) -> Self {
176		tracing::warn!(%err, "encode error");
177		Error::Encode
178	}
179}
180
181pub type Result<T> = std::result::Result<T, Error>;