tor_dirserver/err.rs
1//! Error module for `tor-dirserver`.
2
3use std::net::SocketAddr;
4
5use thiserror::Error;
6
7/// An error while communicating with a directory authority.
8///
9/// This error should be returned by all functions that download or upload
10/// resources to authorities, in other words: every function that interacts or
11/// communicates with a directory authority.
12#[derive(Debug, Error)]
13#[non_exhaustive]
14pub(crate) enum AuthorityCommunicationError {
15 /// A TCP connection to an authority failed.
16 ///
17 /// A failure of this implies that both, the V4 and V6 (if present), have
18 /// failed.
19 #[error("TCP connection failure: {endpoints:?}: {error}")]
20 TcpConnect {
21 /// The [`SocketAddr`] items we tried to connect to, most typically
22 /// the IPv4 and IPv6 address + port of the directory authority.
23 endpoints: Vec<SocketAddr>,
24
25 /// The actual I/O error that happened.
26 error: std::io::Error,
27 },
28
29 /// A failure related to [`tor_dirclient`].
30 ///
31 /// Most likely, this will be of type [`tor_dirclient::Error::RequestFailed`],
32 /// but in order to stay compatible with `non_exhaustive` we map the error.
33 ///
34 /// The value is in a [`Box`] to satisfy `clippy::large_enum_variant`.
35 /// It is already noted in a TODO within the respective crate.
36 #[error("dirclient error: {0}")]
37 Dirclient(#[from] Box<tor_dirclient::Error>),
38
39 /// An internal error.
40 #[error("internal error")]
41 Bug(#[from] tor_error::Bug),
42}
43
44/// An error while interacting with a database.
45///
46/// This error should be returned by all functions that interact with the
47/// database in one way or another.
48#[derive(Debug, Error)]
49#[non_exhaustive]
50pub(crate) enum DatabaseError {
51 /// A low-level SQLite error has occurred, which can have a bascially
52 /// infinite amount of reasons, all of them outlined in the actual SQLite
53 /// and [`rusqlite`] documentation.
54 #[error("low-level rusqlite error: {0}")]
55 LowLevel(#[from] rusqlite::Error),
56
57 /// This is an application level error meaning that the database can be
58 /// successfully accessed but its content implies it is of a schema version
59 /// we do not support.
60 ///
61 /// Keep in mind that an unrecognized schema is not equal to no schema.
62 /// In the latter case we actually initialize the database, whereas in the
63 /// previous one, we fail early in order to not corrupt an existing database.
64 /// Future versions of this crate should continue with this promise in order
65 /// to ensure forward compatability.
66 #[error("incompatible schema version: {version}")]
67 IncompatibleSchema {
68 /// The incompatible schema version found in the database.
69 version: String,
70 },
71
72 /// Interaction with our database pool, [`r2d2`], has failed.
73 ///
74 /// Unlike other database pools, this error is fairly straightforward and
75 /// may only be obtained in the cases in which we try to obtain a connection
76 /// handle from the pool. Notably, it does not fail if, for example,
77 /// the low-level [`rusqlite`] has a failure.
78 #[error("pool error: {0}")]
79 Pool(#[from] r2d2::Error),
80
81 /// An internal error.
82 #[error("Internal error")]
83 Bug(#[from] tor_error::Bug),
84}
85
86/// An unrecoverable error during daemon operation.
87///
88/// This error is inteded for functions that generally run forever, unless they
89/// encounter an error that is not recoverable, in which case, they will return
90/// this error type.
91#[derive(Debug, Error)]
92#[non_exhaustive]
93pub(crate) enum FatalError {
94 /// The selection of a consensus from the database has failed.
95 ///
96 /// This most likely indicates that something with the underlying database
97 /// is wrong in a persistent fashion, i.e. retries will not work anymore.
98 #[error("consensus selection error: {0}")]
99 ConsensusSelection(DatabaseError),
100}