1use std::time::Duration;
2
3use bencode::SerializeError;
4
5#[derive(thiserror::Error, Debug)]
6#[error("error looking up {hostname}: {err:#}")]
7pub struct LookupError {
8 hostname: Box<str>,
9 #[source]
10 err: std::io::Error,
11}
12
13#[derive(thiserror::Error, Debug)]
14pub enum Error {
15 #[error("error binding UDP socket: {0:#}")]
16 Bind(#[source] Box<librqbit_dualstack_sockets::Error>),
17
18 #[error("bootstrapping failed")]
19 BootstrapFailed,
20
21 #[error("{0} failed: {1:?}")]
22 TaskFailed(&'static &'static str, #[source] Box<Error>),
23
24 #[error("{0} finished unexpectedly with no error")]
25 TaskQuit(&'static &'static str),
26
27 #[error("no successful lookups, {errors} errors")]
28 NoSuccessfulLookups { errors: usize },
29
30 #[error("dht is dead")]
31 DhtDead,
32
33 #[error("receiver is dead")]
34 ReceiverDead,
35
36 #[error("error response")]
37 ErrorResponse,
38
39 #[error("timeout at {0:?}")]
40 ResponseTimeout(Duration),
41
42 #[error("bad transaction id")]
43 BadTransactionId,
44
45 #[error("outstanding request not found")]
46 RequestNotFound,
47
48 #[error(transparent)]
49 BootstrapLookup(Box<LookupError>),
50
51 #[error("error sending: {0:#}")]
52 Send(#[source] std::io::Error),
53 #[error("error in recv: {0:#}")]
54 Recv(#[source] std::io::Error),
55
56 #[error("bencode serialize error: {0:#}")]
57 Serialize(#[source] Box<SerializeError>),
58}
59
60impl From<SerializeError> for Error {
61 fn from(value: SerializeError) -> Self {
62 Error::Serialize(Box::new(value))
63 }
64}
65
66impl Error {
67 pub fn lookup(hostname: &str, err: std::io::Error) -> Error {
68 Error::BootstrapLookup(Box::new(LookupError {
69 hostname: hostname.into(),
70 err,
71 }))
72 }
73
74 pub fn task_finished(name: &'static &'static str, result: Result<()>) -> Result<()> {
75 match result {
76 Ok(()) => Err(Error::TaskQuit(name)),
77 Err(e) => Err(Error::TaskFailed(name, Box::new(e))),
78 }
79 }
80}
81
82pub type Result<T> = core::result::Result<T, Error>;