1#![allow(clippy::enum_variant_names)]
23
24use crate::{
30 protocol::Direction,
31 transport::manager::limits::ConnectionLimitsError,
32 types::{protocol::ProtocolName, ConnectionId, SubstreamId},
33 PeerId,
34};
35
36use multiaddr::Multiaddr;
37use multihash::{Multihash, MultihashGeneric};
38
39use std::io::{self, ErrorKind};
40
41#[allow(clippy::large_enum_variant)]
42#[derive(Debug, thiserror::Error)]
43pub enum Error {
44 #[error("Peer `{0}` does not exist")]
45 PeerDoesntExist(PeerId),
46 #[error("Peer `{0}` already exists")]
47 PeerAlreadyExists(PeerId),
48 #[error("Protocol `{0}` not supported")]
49 ProtocolNotSupported(String),
50 #[error("Address error: `{0}`")]
51 AddressError(#[from] AddressError),
52 #[error("Parse error: `{0}`")]
53 ParseError(ParseError),
54 #[error("I/O error: `{0}`")]
55 IoError(ErrorKind),
56 #[error("Negotiation error: `{0}`")]
57 NegotiationError(#[from] NegotiationError),
58 #[error("Substream error: `{0}`")]
59 SubstreamError(#[from] SubstreamError),
60 #[error("Substream error: `{0}`")]
61 NotificationError(NotificationError),
62 #[error("Essential task closed")]
63 EssentialTaskClosed,
64 #[error("Unknown error occurred")]
65 Unknown,
66 #[error("Cannot dial self: `{0}`")]
67 CannotDialSelf(Multiaddr),
68 #[error("Transport not supported")]
69 TransportNotSupported(Multiaddr),
70 #[error("Yamux error for substream `{0:?}`: `{1}`")]
71 YamuxError(Direction, crate::yamux::ConnectionError),
72 #[error("Operation not supported: `{0}`")]
73 NotSupported(String),
74 #[error("Other error occurred: `{0}`")]
75 Other(String),
76 #[error("Protocol already exists: `{0:?}`")]
77 ProtocolAlreadyExists(ProtocolName),
78 #[error("Operation timed out")]
79 Timeout,
80 #[error("Invalid state transition")]
81 InvalidState,
82 #[error("DNS address resolution failed")]
83 DnsAddressResolutionFailed,
84 #[error("Transport error: `{0}`")]
85 TransportError(String),
86 #[cfg(feature = "quic")]
87 #[error("Failed to generate certificate: `{0}`")]
88 CertificateGeneration(#[from] crate::crypto::tls::certificate::GenError),
89 #[error("Invalid data")]
90 InvalidData,
91 #[error("Input rejected")]
92 InputRejected,
93 #[cfg(feature = "websocket")]
94 #[error("WebSocket error: `{0}`")]
95 WebSocket(#[from] tokio_tungstenite::tungstenite::error::Error),
96 #[error("Insufficient peers")]
97 InsufficientPeers,
98 #[error("Substream doens't exist")]
99 SubstreamDoesntExist,
100 #[cfg(feature = "webrtc")]
101 #[error("`str0m` error: `{0}`")]
102 WebRtc(#[from] str0m::RtcError),
103 #[error("Remote peer disconnected")]
104 Disconnected,
105 #[error("Channel does not exist")]
106 ChannelDoesntExist,
107 #[error("Tried to dial self")]
108 TriedToDialSelf,
109 #[error("Litep2p is already connected to the peer")]
110 AlreadyConnected,
111 #[error("No addres available for `{0}`")]
112 NoAddressAvailable(PeerId),
113 #[error("Connection closed")]
114 ConnectionClosed,
115 #[cfg(feature = "quic")]
116 #[error("Quinn error: `{0}`")]
117 Quinn(quinn::ConnectionError),
118 #[error("Invalid certificate")]
119 InvalidCertificate,
120 #[error("Peer ID mismatch: expected `{0}`, got `{1}`")]
121 PeerIdMismatch(PeerId, PeerId),
122 #[error("Channel is clogged")]
123 ChannelClogged,
124 #[error("Connection doesn't exist: `{0:?}`")]
125 ConnectionDoesntExist(ConnectionId),
126 #[error("Exceeded connection limits `{0:?}`")]
127 ConnectionLimit(ConnectionLimitsError),
128 #[error("Failed to dial peer immediately")]
129 ImmediateDialError(#[from] ImmediateDialError),
130}
131
132#[derive(Debug, thiserror::Error)]
134pub enum AddressError {
135 #[error("Invalid address for protocol")]
140 InvalidProtocol,
141 #[error("Invalid URL")]
143 InvalidUrl,
144 #[error("`PeerId` missing from the address")]
146 PeerIdMissing,
147 #[error("Address not available")]
149 AddressNotAvailable,
150 #[error("Multihash does not contain a valid peer ID : `{0:?}`")]
152 InvalidPeerId(Multihash),
153}
154
155#[derive(Debug, thiserror::Error, PartialEq)]
156pub enum ParseError {
157 #[error("Failed to decode protobuf message: `{0:?}`")]
159 ProstDecodeError(#[from] prost::DecodeError),
160 #[error("Failed to encode protobuf message: `{0:?}`")]
162 ProstEncodeError(#[from] prost::EncodeError),
163 #[error("Unknown key type from protobuf message: `{0}`")]
169 UnknownKeyType(i32),
170 #[error("Invalid public key")]
177 InvalidPublicKey,
178 #[error("Invalid data")]
182 InvalidData,
183}
184
185#[derive(Debug, thiserror::Error, PartialEq)]
186pub enum SubstreamError {
187 #[error("Connection closed")]
188 ConnectionClosed,
189 #[error("Connection channel clogged")]
190 ChannelClogged,
191 #[error("Connection to peer does not exist: `{0}`")]
192 PeerDoesNotExist(PeerId),
193 #[error("I/O error: `{0}`")]
194 IoError(ErrorKind),
195 #[error("yamux error: `{0}`")]
196 YamuxError(crate::yamux::ConnectionError, Direction),
197 #[error("Failed to read from substream, substream id `{0:?}`")]
198 ReadFailure(Option<SubstreamId>),
199 #[error("Failed to write to substream, substream id `{0:?}`")]
200 WriteFailure(Option<SubstreamId>),
201 #[error("Negotiation error: `{0:?}`")]
202 NegotiationError(#[from] NegotiationError),
203}
204
205#[derive(Debug, thiserror::Error)]
207pub enum NegotiationError {
208 #[error("multistream-select error: `{0:?}`")]
210 MultistreamSelectError(#[from] crate::multistream_select::NegotiationError),
211 #[error("multistream-select error: `{0:?}`")]
213 SnowError(#[from] snow::Error),
214 #[error("`PeerId` missing from Noise handshake")]
216 PeerIdMissing,
217 #[error("Operation timed out")]
219 Timeout,
220 #[error("Parse error: `{0}`")]
222 ParseError(#[from] ParseError),
223 #[error("I/O error: `{0}`")]
225 IoError(ErrorKind),
226 #[error("Expected a different state")]
228 StateMismatch,
229 #[error("Peer ID mismatch: expected `{0}`, got `{1}`")]
232 PeerIdMismatch(PeerId, PeerId),
233 #[cfg(feature = "quic")]
235 #[error("QUIC error: `{0}`")]
236 Quic(#[from] QuicError),
237 #[cfg(feature = "websocket")]
239 #[error("WebSocket error: `{0}`")]
240 WebSocket(#[from] tokio_tungstenite::tungstenite::error::Error),
241}
242
243impl PartialEq for NegotiationError {
244 fn eq(&self, other: &Self) -> bool {
245 match (self, other) {
246 (Self::MultistreamSelectError(lhs), Self::MultistreamSelectError(rhs)) => lhs == rhs,
247 (Self::SnowError(lhs), Self::SnowError(rhs)) => lhs == rhs,
248 (Self::ParseError(lhs), Self::ParseError(rhs)) => lhs == rhs,
249 (Self::IoError(lhs), Self::IoError(rhs)) => lhs == rhs,
250 (Self::PeerIdMismatch(lhs, lhs_1), Self::PeerIdMismatch(rhs, rhs_1)) =>
251 lhs == rhs && lhs_1 == rhs_1,
252 #[cfg(feature = "quic")]
253 (Self::Quic(lhs), Self::Quic(rhs)) => lhs == rhs,
254 #[cfg(feature = "websocket")]
255 (Self::WebSocket(lhs), Self::WebSocket(rhs)) =>
256 core::mem::discriminant(lhs) == core::mem::discriminant(rhs),
257 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
258 }
259 }
260}
261
262#[derive(Debug, thiserror::Error)]
263pub enum NotificationError {
264 #[error("Peer already exists")]
265 PeerAlreadyExists,
266 #[error("Peer is in invalid state")]
267 InvalidState,
268 #[error("Notifications clogged")]
269 NotificationsClogged,
270 #[error("Notification stream closed")]
271 NotificationStreamClosed(PeerId),
272}
273
274#[derive(Debug, thiserror::Error)]
279pub enum DialError {
280 #[error("Dial timed out")]
285 Timeout,
286 #[error("Address error: `{0}`")]
288 AddressError(#[from] AddressError),
289 #[error("DNS lookup error for `{0}`")]
294 DnsError(#[from] DnsError),
295 #[error("Negotiation error: `{0}`")]
297 NegotiationError(#[from] NegotiationError),
298}
299
300#[derive(Debug, thiserror::Error, Copy, Clone, Eq, PartialEq)]
302pub enum ImmediateDialError {
303 #[error("`PeerId` missing from the address")]
305 PeerIdMissing,
306 #[error("Tried to dial self")]
308 TriedToDialSelf,
309 #[error("Already connected to peer")]
311 AlreadyConnected,
312 #[error("No address available for peer")]
314 NoAddressAvailable,
315 #[error("TaskClosed")]
317 TaskClosed,
318 #[error("Connection channel clogged")]
320 ChannelClogged,
321}
322
323#[cfg(feature = "quic")]
325#[derive(Debug, thiserror::Error, PartialEq)]
326pub enum QuicError {
327 #[error("Invalid certificate")]
329 InvalidCertificate,
330 #[error("Failed to negotiate QUIC: `{0}`")]
332 ConnectionError(#[from] quinn::ConnectionError),
333 #[error("Failed to connect to peer: `{0}`")]
335 ConnectError(#[from] quinn::ConnectError),
336}
337
338#[derive(Debug, thiserror::Error, PartialEq)]
340pub enum DnsError {
341 #[error("DNS failed to resolve url `{0}`")]
343 ResolveError(String),
344 #[error("DNS type is different from the provided IP address")]
348 IpVersionMismatch,
349}
350
351impl From<MultihashGeneric<64>> for Error {
352 fn from(hash: MultihashGeneric<64>) -> Self {
353 Error::AddressError(AddressError::InvalidPeerId(hash))
354 }
355}
356
357impl From<io::Error> for Error {
358 fn from(error: io::Error) -> Error {
359 Error::IoError(error.kind())
360 }
361}
362
363impl From<io::Error> for SubstreamError {
364 fn from(error: io::Error) -> SubstreamError {
365 SubstreamError::IoError(error.kind())
366 }
367}
368
369impl From<io::Error> for DialError {
370 fn from(error: io::Error) -> Self {
371 DialError::NegotiationError(NegotiationError::IoError(error.kind()))
372 }
373}
374
375impl From<crate::multistream_select::NegotiationError> for Error {
376 fn from(error: crate::multistream_select::NegotiationError) -> Error {
377 Error::NegotiationError(NegotiationError::MultistreamSelectError(error))
378 }
379}
380
381impl From<snow::Error> for Error {
382 fn from(error: snow::Error) -> Self {
383 Error::NegotiationError(NegotiationError::SnowError(error))
384 }
385}
386
387impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error {
388 fn from(_: tokio::sync::mpsc::error::SendError<T>) -> Self {
389 Error::EssentialTaskClosed
390 }
391}
392
393impl From<tokio::sync::oneshot::error::RecvError> for Error {
394 fn from(_: tokio::sync::oneshot::error::RecvError) -> Self {
395 Error::EssentialTaskClosed
396 }
397}
398
399impl From<prost::DecodeError> for Error {
400 fn from(error: prost::DecodeError) -> Self {
401 Error::ParseError(ParseError::ProstDecodeError(error))
402 }
403}
404
405impl From<prost::EncodeError> for Error {
406 fn from(error: prost::EncodeError) -> Self {
407 Error::ParseError(ParseError::ProstEncodeError(error))
408 }
409}
410
411impl From<io::Error> for NegotiationError {
412 fn from(error: io::Error) -> Self {
413 NegotiationError::IoError(error.kind())
414 }
415}
416
417impl From<ParseError> for Error {
418 fn from(error: ParseError) -> Self {
419 Error::ParseError(error)
420 }
421}
422
423impl From<MultihashGeneric<64>> for AddressError {
424 fn from(hash: MultihashGeneric<64>) -> Self {
425 AddressError::InvalidPeerId(hash)
426 }
427}
428
429#[cfg(feature = "quic")]
430impl From<quinn::ConnectionError> for Error {
431 fn from(error: quinn::ConnectionError) -> Self {
432 match error {
433 quinn::ConnectionError::TimedOut => Error::Timeout,
434 error => Error::Quinn(error),
435 }
436 }
437}
438
439#[cfg(feature = "quic")]
440impl From<quinn::ConnectionError> for DialError {
441 fn from(error: quinn::ConnectionError) -> Self {
442 match error {
443 quinn::ConnectionError::TimedOut => DialError::Timeout,
444 error => DialError::NegotiationError(NegotiationError::Quic(error.into())),
445 }
446 }
447}
448
449#[cfg(feature = "quic")]
450impl From<quinn::ConnectError> for DialError {
451 fn from(error: quinn::ConnectError) -> Self {
452 DialError::NegotiationError(NegotiationError::Quic(error.into()))
453 }
454}
455
456impl From<ConnectionLimitsError> for Error {
457 fn from(error: ConnectionLimitsError) -> Self {
458 Error::ConnectionLimit(error)
459 }
460}
461
462#[cfg(test)]
463mod tests {
464 use super::*;
465 use tokio::sync::mpsc::{channel, Sender};
466
467 #[tokio::test]
468 async fn try_from_errors() {
469 let (tx, rx) = channel(1);
470 drop(rx);
471
472 async fn test(tx: Sender<()>) -> crate::Result<()> {
473 tx.send(()).await.map_err(From::from)
474 }
475
476 match test(tx).await.unwrap_err() {
477 Error::EssentialTaskClosed => {}
478 _ => panic!("invalid error"),
479 }
480 }
481}