1use std::{sync::Arc, time::Duration};
3use thiserror::Error;
4use tor_cell::relaycell::{StreamId, msg::EndReason};
5use tor_error::{Bug, ErrorKind, HasKind};
6use tor_linkspec::RelayIdType;
7
8use crate::HopNum;
9
10#[derive(Error, Debug, Clone)]
16#[non_exhaustive]
17pub enum Error {
18 #[error("Unable to parse {object}")]
21 BytesErr {
22 object: &'static str,
24 #[source]
26 err: tor_bytes::Error,
27 },
28 #[error("IO error on channel with peer")]
31 ChanIoErr(#[source] Arc<std::io::Error>),
32 #[error("IO error while handshaking with peer")]
34 HandshakeIoErr(#[source] Arc<std::io::Error>),
35 #[error("Unable to generate or encode {object}")]
37 CellEncodeErr {
38 object: &'static str,
40 #[source]
42 err: tor_cell::Error,
43 },
44 #[error("Error while parsing {object}")]
46 CellDecodeErr {
47 object: &'static str,
49 #[source]
51 err: tor_cell::Error,
52 },
53 #[error("Problem while encoding {object}")]
59 EncodeErr {
60 object: &'static str,
62 #[source]
64 err: tor_bytes::EncodeError,
65 },
66 #[error("Problem with certificate on handshake")]
69 HandshakeCertErr(#[source] tor_cert::CertError),
70 #[error("Tried to extract too many bytes from a KDF")]
72 InvalidKDFOutputLength,
73 #[error("Tried to encrypt a cell for a nonexistent hop")]
75 NoSuchHop,
76 #[error("Bad relay cell authentication")]
79 BadCellAuth,
80 #[error("Circuit-extension handshake authentication failed")]
83 BadCircHandshakeAuth,
84 #[error("Handshake protocol violation: {0}")]
86 HandshakeProto(String),
87 #[error("Handshake failed due to expired certificates (possible clock skew)")]
92 HandshakeCertsExpired {
93 expired_by: Duration,
95 },
96 #[error("Channel protocol violation: {0}")]
99 ChanProto(String),
100 #[error("Circuit protocol violation: {0}")]
102 CircProto(String),
103 #[error("Channel closed")]
106 ChannelClosed(#[from] ChannelClosed),
107 #[error("Circuit closed")]
110 CircuitClosed,
111 #[error("Too many entries in map: can't allocate ID")]
113 IdRangeFull,
114 #[error("Stream ID {0} is already in use")]
116 IdUnavailable(StreamId),
117 #[error("Received a cell with a stream ID of zero")]
119 StreamIdZero,
120 #[error("Circuit extension refused: {0}")]
123 CircRefused(&'static str),
124 #[error("Invalid stream target address")]
126 BadStreamAddress,
127 #[error("Received an END cell with reason {0}")]
129 EndReceived(EndReason),
130 #[error("Stream not connected")]
132 NotConnected,
133 #[error("Stream protocol violation: {0}")]
135 StreamProto(String),
136
137 #[error("Received too many inbound cells")]
139 ExcessInboundCells,
140 #[error("Tried to send too many outbound cells")]
142 ExcessOutboundCells,
143
144 #[error("Received unexpected or excessive circuit padding from {}", _1.display())]
146 ExcessPadding(#[source] ExcessPadding, HopNum),
147
148 #[error("Peer identity mismatch: {0}")]
150 ChanMismatch(String),
151 #[error("Programming error")]
153 Bug(#[from] tor_error::Bug),
154 #[error("Remote resolve failed")]
156 ResolveError(#[source] ResolveError),
157 #[error("Relay has no {0} identity")]
160 MissingId(RelayIdType),
161 #[error("memory quota error")]
163 Memquota(#[from] tor_memquota::Error),
164}
165
166#[derive(Error, Debug, Clone)]
168#[error("Channel closed")]
169pub struct ChannelClosed;
170
171impl HasKind for ChannelClosed {
172 fn kind(&self) -> ErrorKind {
173 ErrorKind::CircuitCollapse
174 }
175}
176
177#[derive(Error, Debug, Clone)]
179#[non_exhaustive]
180pub enum ResolveError {
181 #[error("Received retriable transient error")]
183 Transient,
184 #[error("Received non-retriable error")]
186 Nontransient,
187 #[error("Received unrecognized result")]
189 Unrecognized,
190}
191
192impl Error {
193 pub(crate) fn from_cell_enc(err: tor_cell::Error, object: &'static str) -> Error {
196 Error::CellEncodeErr { object, err }
197 }
198
199 pub(crate) fn from_bytes_err(err: tor_bytes::Error, object: &'static str) -> Error {
202 Error::BytesErr { err, object }
203 }
204
205 pub(crate) fn from_bytes_enc(err: tor_bytes::EncodeError, object: &'static str) -> Error {
208 Error::EncodeErr { err, object }
209 }
210}
211
212impl From<std::io::Error> for Error {
213 fn from(err: std::io::Error) -> Self {
214 Self::ChanIoErr(Arc::new(err))
215 }
216}
217
218impl From<Error> for std::io::Error {
219 fn from(err: Error) -> std::io::Error {
220 use Error::*;
221 use std::io::ErrorKind;
222 let kind = match err {
223 ChanIoErr(e) | HandshakeIoErr(e) => match Arc::try_unwrap(e) {
224 Ok(e) => return e,
225 Err(arc) => return std::io::Error::new(arc.kind(), arc),
226 },
227
228 InvalidKDFOutputLength | NoSuchHop | BadStreamAddress => ErrorKind::InvalidInput,
229
230 NotConnected => ErrorKind::NotConnected,
231
232 EndReceived(end_reason) => end_reason.into(),
233
234 CircuitClosed => ErrorKind::ConnectionReset,
235
236 Memquota { .. } => ErrorKind::OutOfMemory,
237
238 BytesErr { .. }
239 | BadCellAuth
240 | BadCircHandshakeAuth
241 | HandshakeProto(_)
242 | HandshakeCertErr(_)
243 | ChanProto(_)
244 | HandshakeCertsExpired { .. }
245 | ChannelClosed(_)
246 | CircProto(_)
247 | CellDecodeErr { .. }
248 | CellEncodeErr { .. }
249 | EncodeErr { .. }
250 | ChanMismatch(_)
251 | StreamProto(_)
252 | MissingId(_)
253 | IdUnavailable(_)
254 | StreamIdZero
255 | ExcessInboundCells
256 | ExcessOutboundCells
257 | ExcessPadding(_, _) => ErrorKind::InvalidData,
258
259 Bug(ref e) if e.kind() == tor_error::ErrorKind::BadApiUsage => ErrorKind::InvalidData,
260
261 IdRangeFull | CircRefused(_) | ResolveError(_) | Bug(_) => ErrorKind::Other,
262 };
263 std::io::Error::new(kind, err)
264 }
265}
266
267impl HasKind for Error {
268 fn kind(&self) -> ErrorKind {
269 use Error as E;
270 use ErrorKind as EK;
271 use tor_bytes::Error as BytesError;
272 match self {
273 E::BytesErr {
274 err: BytesError::Bug(e),
275 ..
276 } => e.kind(),
277 E::BytesErr { .. } => EK::TorProtocolViolation,
278 E::ChanIoErr(_) => EK::LocalNetworkError,
279 E::HandshakeIoErr(_) => EK::TorAccessFailed,
280 E::HandshakeCertErr(_) => EK::TorProtocolViolation,
281 E::CellEncodeErr { err, .. } => err.kind(),
282 E::CellDecodeErr { err, .. } => err.kind(),
283 E::EncodeErr { .. } => EK::BadApiUsage,
284 E::InvalidKDFOutputLength => EK::Internal,
285 E::NoSuchHop => EK::BadApiUsage,
286 E::BadCellAuth => EK::TorProtocolViolation,
287 E::BadCircHandshakeAuth => EK::TorProtocolViolation,
288 E::HandshakeProto(_) => EK::TorAccessFailed,
289 E::HandshakeCertsExpired { .. } => EK::ClockSkew,
290 E::ChanProto(_) => EK::TorProtocolViolation,
291 E::CircProto(_) => EK::TorProtocolViolation,
292 E::ChannelClosed(e) => e.kind(),
293 E::CircuitClosed => EK::CircuitCollapse,
294 E::IdRangeFull => EK::BadApiUsage,
295 E::CircRefused(_) => EK::CircuitRefused,
296 E::BadStreamAddress => EK::BadApiUsage,
297 E::EndReceived(reason) => reason.kind(),
298 E::NotConnected => EK::BadApiUsage,
299 E::StreamProto(_) => EK::TorProtocolViolation,
300 E::ChanMismatch(_) => EK::RelayIdMismatch,
301 E::ResolveError(ResolveError::Nontransient) => EK::RemoteHostNotFound,
302 E::ResolveError(ResolveError::Transient) => EK::RemoteHostResolutionFailed,
303 E::ResolveError(ResolveError::Unrecognized) => EK::RemoteHostResolutionFailed,
304 E::MissingId(_) => EK::BadApiUsage,
305 E::IdUnavailable(_) => EK::BadApiUsage,
306 E::StreamIdZero => EK::BadApiUsage,
307 E::ExcessInboundCells => EK::TorProtocolViolation,
308 E::ExcessOutboundCells => EK::Internal,
309 E::ExcessPadding(_, _) => EK::TorProtocolViolation,
310 E::Memquota(err) => err.kind(),
311 E::Bug(e) => e.kind(),
312 }
313 }
314}
315
316#[derive(Debug)]
319pub(crate) enum ReactorError {
320 Err(Error),
322 Shutdown,
324}
325
326impl From<Error> for ReactorError {
327 fn from(e: Error) -> ReactorError {
328 ReactorError::Err(e)
329 }
330}
331
332impl From<ChannelClosed> for ReactorError {
333 fn from(e: ChannelClosed) -> ReactorError {
334 ReactorError::Err(e.into())
335 }
336}
337
338impl From<Bug> for ReactorError {
339 fn from(e: Bug) -> ReactorError {
340 ReactorError::Err(e.into())
341 }
342}
343
344#[cfg(test)]
345impl ReactorError {
346 pub(crate) fn unwrap_err(self) -> Error {
348 match self {
349 ReactorError::Shutdown => panic!(),
350 ReactorError::Err(e) => e,
351 }
352 }
353}
354
355#[derive(Debug)]
357#[cfg(feature = "conflux")]
358#[allow(unused)] pub(crate) enum ConfluxHandshakeError {
360 Timeout,
362 Link(Error),
364 ChannelClosed,
366}
367
368#[derive(Debug, Clone, Error)]
369#[non_exhaustive]
370pub enum ExcessPadding {
371 #[error("Padding received when not negotiated with given hop")]
373 NoPaddingNegotiated,
374 #[error("Received padding in excess of negotiated framework's limit")]
376 PaddingExceedsLimit,
377}