volans_swarm/
error.rs

1use std::{error, fmt, io};
2
3use volans_core::{PeerId, TransportError, Multiaddr};
4
5use crate::dial_opts;
6
7#[derive(Debug, thiserror::Error)]
8#[error("Connection denied: {inner}")]
9pub struct ConnectionDenied {
10    inner: Box<dyn std::error::Error + Send + Sync + 'static>,
11}
12
13impl ConnectionDenied {
14    pub fn new(cause: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>) -> Self {
15        Self {
16            inner: cause.into(),
17        }
18    }
19
20    pub fn downcast<E>(self) -> Result<E, Self>
21    where
22        E: std::error::Error + Send + Sync + 'static,
23    {
24        let inner = self
25            .inner
26            .downcast::<E>()
27            .map_err(|inner| ConnectionDenied { inner })?;
28
29        Ok(*inner)
30    }
31
32    pub fn downcast_ref<E>(&self) -> Option<&E>
33    where
34        E: std::error::Error + Send + Sync + 'static,
35    {
36        self.inner.downcast_ref::<E>()
37    }
38}
39
40/// 拨号错误
41#[derive(Debug, thiserror::Error)]
42pub enum DialError {
43    LocalPeerId,
44    NoAddress,
45    PeerCondition(dial_opts::PeerCondition),
46    Aborted,
47    WrongPeerId {
48        obtained: PeerId,
49    },
50    Denied {
51        #[source]
52        cause: ConnectionDenied,
53    },
54    Transport {
55        addr: Multiaddr,
56        #[source]
57        error: TransportError<io::Error>,
58    },
59}
60
61impl From<PendingConnectionError> for DialError {
62    fn from(error: PendingConnectionError) -> Self {
63        match error {
64            PendingConnectionError::Transport { addr, error } => {
65                DialError::Transport { addr, error }
66            }
67            PendingConnectionError::Aborted => DialError::Aborted,
68            PendingConnectionError::WrongPeerId { obtained } => DialError::WrongPeerId { obtained },
69            PendingConnectionError::LocalPeerId => DialError::LocalPeerId,
70        }
71    }
72}
73
74impl fmt::Display for DialError {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        match self {
77            DialError::LocalPeerId => write!(f, "Local peer ID is not set"),
78            DialError::NoAddress => write!(f, "No address to dial"),
79            DialError::PeerCondition(condition) => write!(f, "Peer condition not met: {condition}"),
80            DialError::Aborted => write!(f, "Dialing was aborted"),
81            DialError::WrongPeerId { obtained } => {
82                write!(f, "Dialed wrong peer ID: {obtained}")
83            }
84            DialError::Denied { cause } => write!(f, "Dialing denied: {cause}"),
85            DialError::Transport { addr, error } => {
86                write!(f, "Transport error while dialing `{addr}`, ")?;
87                print_error_chain(f, error)
88            }
89        }
90    }
91}
92
93#[derive(Debug, thiserror::Error)]
94pub enum ListenError {
95    Aborted,
96    WrongPeerId {
97        obtained: PeerId,
98    },
99    LocalPeerId,
100    Denied {
101        #[source]
102        cause: ConnectionDenied,
103    },
104    Transport(#[source] TransportError<io::Error>),
105}
106
107impl From<PendingConnectionError> for ListenError {
108    fn from(error: PendingConnectionError) -> Self {
109        match error {
110            PendingConnectionError::Transport { addr: _, error } => {
111                ListenError::Transport(TransportError::from(error))
112            }
113            PendingConnectionError::Aborted => ListenError::Aborted,
114            PendingConnectionError::WrongPeerId { obtained } => {
115                ListenError::WrongPeerId { obtained }
116            }
117            PendingConnectionError::LocalPeerId => ListenError::LocalPeerId,
118        }
119    }
120}
121
122impl fmt::Display for ListenError {
123    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124        match self {
125            ListenError::Aborted => write!(f, "Listening was aborted"),
126            ListenError::WrongPeerId { obtained } => {
127                write!(f, "Listening on wrong peer ID: {obtained}")
128            }
129            ListenError::LocalPeerId => write!(f, "Local peer ID is not set"),
130            ListenError::Denied { cause } => write!(f, "Listening denied: {cause}"),
131            ListenError::Transport(error) => {
132                write!(f, "Transport error while listening, ")?;
133                print_error_chain(f, error)
134            }
135        }
136    }
137}
138
139fn print_error_chain(f: &mut fmt::Formatter<'_>, e: &dyn error::Error) -> fmt::Result {
140    write!(f, ": {e}")?;
141
142    if let Some(source) = e.source() {
143        print_error_chain(f, source)?;
144    }
145
146    Ok(())
147}
148
149#[derive(Debug, thiserror::Error)]
150pub enum ConnectionError {
151    #[error("Connection I/O error: {0}")]
152    Io(#[from] std::io::Error),
153    #[error("Connection keep-alive timeout")]
154    KeepAliveTimeout,
155    #[error("Connection closing")]
156    Closing,
157}
158
159#[derive(Debug)]
160pub enum PendingConnectionError {
161    Transport {
162        addr: Multiaddr,
163        error: TransportError<io::Error>,
164    },
165    Aborted,
166    WrongPeerId {
167        obtained: PeerId,
168    },
169    LocalPeerId,
170}