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#[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}