1use futures::task::SpawnError;
4use safelog::Sensitive;
5use std::{sync::Arc, time::Duration};
6use thiserror::Error;
7use tor_cell::relaycell::{StreamId, msg::EndReason};
8use tor_error::{Bug, ErrorKind, HasKind};
9use tor_linkspec::RelayIdType;
10
11use crate::HopNum;
12use crate::client::circuit::PathEntry;
13
14#[derive(Error, Debug, Clone)]
20#[non_exhaustive]
21pub enum Error {
22 #[error("Unable to parse {object}")]
25 BytesErr {
26 object: &'static str,
28 #[source]
30 err: tor_bytes::Error,
31 },
32 #[error("IO error on channel with peer")]
35 ChanIoErr(#[source] Arc<std::io::Error>),
36 #[error("IO error while handshaking with peer")]
38 HandshakeIoErr(#[source] Arc<std::io::Error>),
39 #[error("Unable to generate or encode {object}")]
41 CellEncodeErr {
42 object: &'static str,
44 #[source]
46 err: tor_cell::Error,
47 },
48 #[error("Error while parsing {object}")]
50 CellDecodeErr {
51 object: &'static str,
53 #[source]
55 err: tor_cell::Error,
56 },
57 #[error("Problem while encoding {object}")]
63 EncodeErr {
64 object: &'static str,
66 #[source]
68 err: tor_bytes::EncodeError,
69 },
70 #[error("Error while parsing {object}")]
72 #[cfg(feature = "relay")]
73 LinkspecDecodeErr {
74 object: &'static str,
76 #[source]
78 err: tor_linkspec::decode::ChanTargetDecodeError,
79 },
80 #[error("Problem with certificate on handshake")]
83 HandshakeCertErr(#[source] tor_cert::CertError),
84 #[error("Tried to extract too many bytes from a KDF")]
86 InvalidKDFOutputLength,
87 #[error("Tried to encrypt a cell for a nonexistent hop")]
89 NoSuchHop,
90 #[error("Bad relay cell authentication")]
93 BadCellAuth,
94 #[error("Circuit-extension handshake authentication failed")]
97 BadCircHandshakeAuth,
98 #[error("Handshake protocol violation: {0}")]
100 HandshakeProto(String),
101 #[error("Handshake failed due to expired certificates (possible clock skew)")]
106 HandshakeCertsExpired {
107 expired_by: Duration,
109 },
110 #[error("Channel protocol violation: {0}")]
113 ChanProto(String),
114 #[error("Circuit protocol violation: {0}")]
116 CircProto(String),
117 #[error("Channel closed")]
120 ChannelClosed(#[from] ChannelClosed),
121 #[error("Circuit closed")]
124 CircuitClosed,
125 #[error("Too many entries in map: can't allocate ID")]
127 IdRangeFull,
128 #[error("Stream ID {0} is already in use")]
130 IdUnavailable(StreamId),
131 #[error("Received a cell with a stream ID of zero")]
133 StreamIdZero,
134 #[error(
136 "Received a cell from {} on a closed or non-existent stream {}. \
137 Either they are violating the protocol, or we are expiring streams too aggressively",
138 src,
139 streamid
140 )]
141 UnknownStream {
142 src: Sensitive<PathEntry>,
144 streamid: StreamId,
146 },
147 #[error("Circuit extension refused: {0}")]
150 CircRefused(&'static str),
151 #[error("Invalid stream target address")]
153 BadStreamAddress,
154 #[error("Received an END cell with reason {0}")]
156 EndReceived(EndReason),
157 #[error("Stream not connected")]
159 NotConnected,
160 #[error("Stream protocol violation: {0}")]
162 StreamProto(String),
163
164 #[error("Received too many inbound cells")]
166 ExcessInboundCells,
167 #[error("Tried to send too many outbound cells")]
169 ExcessOutboundCells,
170
171 #[error("Received unexpected or excessive circuit padding from {}", _1.display())]
173 ExcessPadding(#[source] ExcessPadding, HopNum),
174
175 #[error("Peer identity mismatch: {0}")]
177 ChanMismatch(String),
178 #[error("Programming error")]
180 Bug(#[from] tor_error::Bug),
181 #[error("Remote resolve failed")]
183 ResolveError(#[source] ResolveError),
184 #[error("Relay has no {0} identity")]
187 MissingId(RelayIdType),
188 #[error("memory quota error")]
190 Memquota(#[from] tor_memquota::Error),
191
192 #[error("Unable to spawn {spawning}")]
197 Spawn {
198 spawning: &'static str,
200 #[source]
202 cause: Arc<SpawnError>,
203 },
204
205 #[cfg(feature = "relay")]
208 #[error("Authentication type {0} is unsupported")]
209 UnsupportedAuth(u16),
210}
211
212#[derive(Error, Debug, Clone)]
214#[error("Channel closed")]
215pub struct ChannelClosed;
216
217impl HasKind for ChannelClosed {
218 fn kind(&self) -> ErrorKind {
219 ErrorKind::CircuitCollapse
220 }
221}
222
223#[derive(Error, Debug, Clone)]
225#[non_exhaustive]
226pub enum ResolveError {
227 #[error("Received retriable transient error")]
229 Transient,
230 #[error("Received non-retriable error")]
232 Nontransient,
233 #[error("Received unrecognized result")]
235 Unrecognized,
236}
237
238impl Error {
239 pub(crate) fn from_cell_enc(err: tor_cell::Error, object: &'static str) -> Error {
242 Error::CellEncodeErr { object, err }
243 }
244
245 pub(crate) fn from_bytes_err(err: tor_bytes::Error, object: &'static str) -> Error {
248 Error::BytesErr { err, object }
249 }
250
251 pub(crate) fn from_bytes_enc(err: tor_bytes::EncodeError, object: &'static str) -> Error {
254 Error::EncodeErr { err, object }
255 }
256}
257
258impl From<std::io::Error> for Error {
259 fn from(err: std::io::Error) -> Self {
260 Self::ChanIoErr(Arc::new(err))
261 }
262}
263
264impl From<Error> for std::io::Error {
265 fn from(err: Error) -> std::io::Error {
266 use Error::*;
267 use std::io::ErrorKind;
268 let kind = match err {
269 ChanIoErr(e) | HandshakeIoErr(e) => match Arc::try_unwrap(e) {
270 Ok(e) => return e,
271 Err(arc) => return std::io::Error::new(arc.kind(), arc),
272 },
273
274 InvalidKDFOutputLength | NoSuchHop | BadStreamAddress => ErrorKind::InvalidInput,
275
276 NotConnected => ErrorKind::NotConnected,
277
278 EndReceived(end_reason) => end_reason.into(),
279
280 CircuitClosed => ErrorKind::ConnectionReset,
281
282 Memquota { .. } => ErrorKind::OutOfMemory,
283
284 BytesErr { .. }
285 | BadCellAuth
286 | BadCircHandshakeAuth
287 | HandshakeProto(_)
288 | HandshakeCertErr(_)
289 | ChanProto(_)
290 | HandshakeCertsExpired { .. }
291 | ChannelClosed(_)
292 | CircProto(_)
293 | CellDecodeErr { .. }
294 | CellEncodeErr { .. }
295 | EncodeErr { .. }
296 | ChanMismatch(_)
297 | StreamProto(_)
298 | MissingId(_)
299 | IdUnavailable(_)
300 | StreamIdZero
301 | UnknownStream { .. }
302 | ExcessInboundCells
303 | ExcessOutboundCells
304 | ExcessPadding(_, _) => ErrorKind::InvalidData,
305
306 #[cfg(feature = "relay")]
307 LinkspecDecodeErr { .. } => ErrorKind::InvalidData,
308 #[cfg(feature = "relay")]
309 UnsupportedAuth(_) => ErrorKind::Unsupported,
310
311 Bug(ref e) if e.kind() == tor_error::ErrorKind::BadApiUsage => ErrorKind::InvalidData,
312
313 IdRangeFull | CircRefused(_) | ResolveError(_) | Spawn { .. } | Bug(_) => {
314 ErrorKind::Other
315 }
316 };
317 std::io::Error::new(kind, err)
318 }
319}
320
321impl HasKind for Error {
322 fn kind(&self) -> ErrorKind {
323 use Error as E;
324 use ErrorKind as EK;
325 use tor_bytes::Error as BytesError;
326 match self {
327 E::BytesErr {
328 err: BytesError::Bug(e),
329 ..
330 } => e.kind(),
331 E::BytesErr { .. } => EK::TorProtocolViolation,
332 E::ChanIoErr(_) => EK::LocalNetworkError,
333 E::HandshakeIoErr(_) => EK::TorAccessFailed,
334 E::HandshakeCertErr(_) => EK::TorProtocolViolation,
335 E::CellEncodeErr { err, .. } => err.kind(),
336 E::CellDecodeErr { err, .. } => err.kind(),
337 #[cfg(feature = "relay")]
338 E::LinkspecDecodeErr { .. } => EK::TorProtocolViolation,
339 E::EncodeErr { .. } => EK::BadApiUsage,
340 E::InvalidKDFOutputLength => EK::Internal,
341 E::NoSuchHop => EK::BadApiUsage,
342 E::BadCellAuth => EK::TorProtocolViolation,
343 E::BadCircHandshakeAuth => EK::TorProtocolViolation,
344 E::HandshakeProto(_) => EK::TorAccessFailed,
345 E::HandshakeCertsExpired { .. } => EK::ClockSkew,
346 E::ChanProto(_) => EK::TorProtocolViolation,
347 E::CircProto(_) => EK::TorProtocolViolation,
348 E::ChannelClosed(e) => e.kind(),
349 E::CircuitClosed => EK::CircuitCollapse,
350 E::IdRangeFull => EK::BadApiUsage,
351 E::CircRefused(_) => EK::CircuitRefused,
352 E::BadStreamAddress => EK::BadApiUsage,
353 E::EndReceived(reason) => reason.kind(),
354 E::NotConnected => EK::BadApiUsage,
355 E::StreamProto(_) => EK::TorProtocolViolation,
356 E::ChanMismatch(_) => EK::RelayIdMismatch,
357 E::ResolveError(ResolveError::Nontransient) => EK::RemoteHostNotFound,
358 E::ResolveError(ResolveError::Transient) => EK::RemoteHostResolutionFailed,
359 E::ResolveError(ResolveError::Unrecognized) => EK::RemoteHostResolutionFailed,
360 E::MissingId(_) => EK::BadApiUsage,
361 E::IdUnavailable(_) => EK::BadApiUsage,
362 E::StreamIdZero => EK::BadApiUsage,
363 E::UnknownStream { .. } => EK::TorProtocolViolation,
364 E::ExcessInboundCells => EK::TorProtocolViolation,
365 E::ExcessOutboundCells => EK::Internal,
366 E::ExcessPadding(_, _) => EK::TorProtocolViolation,
367 E::Memquota(err) => err.kind(),
368 E::Spawn { cause, .. } => cause.kind(),
369 E::Bug(e) => e.kind(),
370 #[cfg(feature = "relay")]
371 E::UnsupportedAuth(_) => EK::RemoteProtocolViolation,
372 }
373 }
374}
375
376#[derive(Debug)]
379pub(crate) enum ReactorError {
380 Err(Error),
382 Shutdown,
384}
385
386impl From<Error> for ReactorError {
387 fn from(e: Error) -> ReactorError {
388 ReactorError::Err(e)
389 }
390}
391
392impl From<ChannelClosed> for ReactorError {
393 fn from(e: ChannelClosed) -> ReactorError {
394 ReactorError::Err(e.into())
395 }
396}
397
398impl From<Bug> for ReactorError {
399 fn from(e: Bug) -> ReactorError {
400 ReactorError::Err(e.into())
401 }
402}
403
404#[cfg(test)]
405impl ReactorError {
406 pub(crate) fn unwrap_err(self) -> Error {
408 match self {
409 ReactorError::Shutdown => panic!(),
410 ReactorError::Err(e) => e,
411 }
412 }
413}
414
415#[derive(Debug)]
417#[cfg(feature = "conflux")]
418#[allow(unused)] pub(crate) enum ConfluxHandshakeError {
420 Timeout,
422 Link(Error),
424 ChannelClosed,
426}
427
428#[derive(Debug, Clone, Error)]
430#[non_exhaustive]
431pub enum ExcessPadding {
432 #[error("Padding received when not negotiated with given hop")]
434 NoPaddingNegotiated,
435 #[error("Received padding in excess of negotiated framework's limit")]
437 PaddingExceedsLimit,
438}