1#![allow(clippy::enum_variant_names)]
23
24use crate::{
27 protocol::Direction,
28 transport::manager::limits::ConnectionLimitsError,
29 types::{protocol::ProtocolName, ConnectionId, SubstreamId},
30 PeerId,
31};
32
33use multiaddr::Multiaddr;
34use multihash::{Multihash, MultihashGeneric};
35
36use std::io::{self, ErrorKind};
37
38#[allow(clippy::large_enum_variant)]
41#[derive(Debug, thiserror::Error)]
42pub enum Error {
43 #[error("Peer `{0}` does not exist")]
44 PeerDoesntExist(PeerId),
45 #[error("Peer `{0}` already exists")]
46 PeerAlreadyExists(PeerId),
47 #[error("Protocol `{0}` not supported")]
48 ProtocolNotSupported(String),
49 #[error("Address error: `{0}`")]
50 AddressError(#[from] AddressError),
51 #[error("Parse error: `{0}`")]
52 ParseError(ParseError),
53 #[error("I/O error: `{0}`")]
54 IoError(ErrorKind),
55 #[error("Negotiation error: `{0}`")]
56 NegotiationError(#[from] NegotiationError),
57 #[error("Substream error: `{0}`")]
58 SubstreamError(#[from] SubstreamError),
59 #[error("Substream error: `{0}`")]
60 NotificationError(NotificationError),
61 #[error("Essential task closed")]
62 EssentialTaskClosed,
63 #[error("Unknown error occurred")]
64 Unknown,
65 #[error("Cannot dial self: `{0}`")]
66 CannotDialSelf(Multiaddr),
67 #[error("Transport not supported")]
68 TransportNotSupported(Multiaddr),
69 #[error("Yamux error for substream `{0:?}`: `{1}`")]
70 YamuxError(Direction, crate::yamux::ConnectionError),
71 #[error("Operation not supported: `{0}`")]
72 NotSupported(String),
73 #[error("Other error occurred: `{0}`")]
74 Other(String),
75 #[error("Protocol already exists: `{0:?}`")]
76 ProtocolAlreadyExists(ProtocolName),
77 #[error("Operation timed out")]
78 Timeout,
79 #[error("Invalid state transition")]
80 InvalidState,
81 #[error("DNS address resolution failed")]
82 DnsAddressResolutionFailed,
83 #[error("Transport error: `{0}`")]
84 TransportError(String),
85 #[cfg(feature = "quic")]
86 #[error("Failed to generate certificate: `{0}`")]
87 CertificateGeneration(#[from] crate::crypto::tls::certificate::GenError),
88 #[error("Invalid data")]
89 InvalidData,
90 #[error("Input rejected")]
91 InputRejected,
92 #[cfg(feature = "websocket")]
93 #[error("WebSocket error: `{0}`")]
94 WebSocket(#[from] tokio_tungstenite::tungstenite::error::Error),
95 #[error("Insufficient peers")]
96 InsufficientPeers,
97 #[error("Substream doens't exist")]
98 SubstreamDoesntExist,
99 #[cfg(feature = "webrtc")]
100 #[error("`str0m` error: `{0}`")]
101 WebRtc(#[from] str0m::RtcError),
102 #[error("Remote peer disconnected")]
103 Disconnected,
104 #[error("Channel does not exist")]
105 ChannelDoesntExist,
106 #[error("Tried to dial self")]
107 TriedToDialSelf,
108 #[error("Litep2p is already connected to the peer")]
109 AlreadyConnected,
110 #[error("No addres available for `{0}`")]
111 NoAddressAvailable(PeerId),
112 #[error("Connection closed")]
113 ConnectionClosed,
114 #[cfg(feature = "quic")]
115 #[error("Quinn error: `{0}`")]
116 Quinn(quinn::ConnectionError),
117 #[error("Invalid certificate")]
118 InvalidCertificate,
119 #[error("Peer ID mismatch: expected `{0}`, got `{1}`")]
120 PeerIdMismatch(PeerId, PeerId),
121 #[error("Channel is clogged")]
122 ChannelClogged,
123 #[error("Connection doesn't exist: `{0:?}`")]
124 ConnectionDoesntExist(ConnectionId),
125 #[error("Exceeded connection limits `{0:?}`")]
126 ConnectionLimit(ConnectionLimitsError),
127 #[error("Failed to dial peer immediately")]
128 ImmediateDialError(#[from] ImmediateDialError),
129 #[error("Cannot read system DNS config: `{0}`")]
130 CannotReadSystemDnsConfig(hickory_resolver::ResolveError),
131}
132
133#[derive(Debug, thiserror::Error)]
135pub enum AddressError {
136 #[error("Invalid address for protocol")]
141 InvalidProtocol,
142 #[error("Invalid URL")]
144 InvalidUrl,
145 #[error("`PeerId` missing from the address")]
147 PeerIdMissing,
148 #[error("Address not available")]
150 AddressNotAvailable,
151 #[error("Multihash does not contain a valid peer ID : `{0:?}`")]
153 InvalidPeerId(Multihash),
154}
155
156#[derive(Debug, thiserror::Error, PartialEq)]
157pub enum ParseError {
158 #[error("Failed to decode protobuf message: `{0:?}`")]
160 ProstDecodeError(#[from] prost::DecodeError),
161 #[error("Failed to encode protobuf message: `{0:?}`")]
163 ProstEncodeError(#[from] prost::EncodeError),
164 #[error("Unknown key type from protobuf message: `{0}`")]
170 UnknownKeyType(i32),
171 #[error("Invalid public key")]
178 InvalidPublicKey,
179 #[error("Invalid data")]
183 InvalidData,
184 #[error("Invalid reply length")]
186 InvalidReplyLength,
187}
188
189#[derive(Debug, thiserror::Error)]
190pub enum SubstreamError {
191 #[error("Connection closed")]
192 ConnectionClosed,
193 #[error("Connection channel clogged")]
194 ChannelClogged,
195 #[error("Connection to peer does not exist: `{0}`")]
196 PeerDoesNotExist(PeerId),
197 #[error("I/O error: `{0}`")]
198 IoError(ErrorKind),
199 #[error("yamux error: `{0}`")]
200 YamuxError(crate::yamux::ConnectionError, Direction),
201 #[error("Failed to read from substream, substream id `{0:?}`")]
202 ReadFailure(Option<SubstreamId>),
203 #[error("Failed to write to substream, substream id `{0:?}`")]
204 WriteFailure(Option<SubstreamId>),
205 #[error("Negotiation error: `{0:?}`")]
206 NegotiationError(#[from] NegotiationError),
207}
208
209impl PartialEq for SubstreamError {
211 fn eq(&self, other: &Self) -> bool {
212 match (self, other) {
213 (Self::ConnectionClosed, Self::ConnectionClosed) => true,
214 (Self::ChannelClogged, Self::ChannelClogged) => true,
215 (Self::PeerDoesNotExist(lhs), Self::PeerDoesNotExist(rhs)) => lhs == rhs,
216 (Self::IoError(lhs), Self::IoError(rhs)) => lhs == rhs,
217 (Self::YamuxError(lhs, lhs_1), Self::YamuxError(rhs, rhs_1)) => {
218 if lhs_1 != rhs_1 {
219 return false;
220 }
221
222 match (lhs, rhs) {
223 (
224 crate::yamux::ConnectionError::Io(lhs),
225 crate::yamux::ConnectionError::Io(rhs),
226 ) => lhs.kind() == rhs.kind(),
227 (
228 crate::yamux::ConnectionError::Decode(lhs),
229 crate::yamux::ConnectionError::Decode(rhs),
230 ) => match (lhs, rhs) {
231 (
232 crate::yamux::FrameDecodeError::Io(lhs),
233 crate::yamux::FrameDecodeError::Io(rhs),
234 ) => lhs.kind() == rhs.kind(),
235 (
236 crate::yamux::FrameDecodeError::FrameTooLarge(lhs),
237 crate::yamux::FrameDecodeError::FrameTooLarge(rhs),
238 ) => lhs == rhs,
239 (
240 crate::yamux::FrameDecodeError::Header(lhs),
241 crate::yamux::FrameDecodeError::Header(rhs),
242 ) => match (lhs, rhs) {
243 (
244 crate::yamux::HeaderDecodeError::Version(lhs),
245 crate::yamux::HeaderDecodeError::Version(rhs),
246 ) => lhs == rhs,
247 (
248 crate::yamux::HeaderDecodeError::Type(lhs),
249 crate::yamux::HeaderDecodeError::Type(rhs),
250 ) => lhs == rhs,
251 _ => false,
252 },
253 _ => false,
254 },
255 (
256 crate::yamux::ConnectionError::NoMoreStreamIds,
257 crate::yamux::ConnectionError::NoMoreStreamIds,
258 ) => true,
259 (
260 crate::yamux::ConnectionError::Closed,
261 crate::yamux::ConnectionError::Closed,
262 ) => true,
263 (
264 crate::yamux::ConnectionError::TooManyStreams,
265 crate::yamux::ConnectionError::TooManyStreams,
266 ) => true,
267 _ => false,
268 }
269 }
270
271 (Self::ReadFailure(lhs), Self::ReadFailure(rhs)) => lhs == rhs,
272 (Self::WriteFailure(lhs), Self::WriteFailure(rhs)) => lhs == rhs,
273 (Self::NegotiationError(lhs), Self::NegotiationError(rhs)) => lhs == rhs,
274 _ => false,
275 }
276 }
277}
278
279#[derive(Debug, thiserror::Error)]
281pub enum NegotiationError {
282 #[error("multistream-select error: `{0:?}`")]
284 MultistreamSelectError(#[from] crate::multistream_select::NegotiationError),
285 #[error("multistream-select error: `{0:?}`")]
287 SnowError(#[from] snow::Error),
288 #[error("`PeerId` missing from Noise handshake")]
290 PeerIdMissing,
291 #[error("The signature of the remote identity's public key does not verify")]
293 BadSignature,
294 #[error("Operation timed out")]
296 Timeout,
297 #[error("Parse error: `{0}`")]
299 ParseError(#[from] ParseError),
300 #[error("I/O error: `{0}`")]
302 IoError(ErrorKind),
303 #[error("Expected a different state")]
305 StateMismatch,
306 #[error("Peer ID mismatch: expected `{0}`, got `{1}`")]
309 PeerIdMismatch(PeerId, PeerId),
310 #[cfg(feature = "quic")]
312 #[error("QUIC error: `{0}`")]
313 Quic(#[from] QuicError),
314 #[cfg(feature = "websocket")]
316 #[error("WebSocket error: `{0}`")]
317 WebSocket(#[from] tokio_tungstenite::tungstenite::error::Error),
318}
319
320impl PartialEq for NegotiationError {
321 fn eq(&self, other: &Self) -> bool {
322 match (self, other) {
323 (Self::MultistreamSelectError(lhs), Self::MultistreamSelectError(rhs)) => lhs == rhs,
324 (Self::SnowError(lhs), Self::SnowError(rhs)) => lhs == rhs,
325 (Self::ParseError(lhs), Self::ParseError(rhs)) => lhs == rhs,
326 (Self::IoError(lhs), Self::IoError(rhs)) => lhs == rhs,
327 (Self::PeerIdMismatch(lhs, lhs_1), Self::PeerIdMismatch(rhs, rhs_1)) =>
328 lhs == rhs && lhs_1 == rhs_1,
329 #[cfg(feature = "quic")]
330 (Self::Quic(lhs), Self::Quic(rhs)) => lhs == rhs,
331 #[cfg(feature = "websocket")]
332 (Self::WebSocket(lhs), Self::WebSocket(rhs)) =>
333 core::mem::discriminant(lhs) == core::mem::discriminant(rhs),
334 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
335 }
336 }
337}
338
339#[derive(Debug, thiserror::Error)]
340pub enum NotificationError {
341 #[error("Peer already exists")]
342 PeerAlreadyExists,
343 #[error("Peer is in invalid state")]
344 InvalidState,
345 #[error("Notifications clogged")]
346 NotificationsClogged,
347 #[error("Notification stream closed")]
348 NotificationStreamClosed(PeerId),
349}
350
351#[derive(Debug, thiserror::Error)]
356pub enum DialError {
357 #[error("Dial timed out")]
362 Timeout,
363 #[error("Address error: `{0}`")]
365 AddressError(#[from] AddressError),
366 #[error("DNS lookup error for `{0}`")]
371 DnsError(#[from] DnsError),
372 #[error("Negotiation error: `{0}`")]
374 NegotiationError(#[from] NegotiationError),
375}
376
377#[derive(Debug, thiserror::Error, Copy, Clone, Eq, PartialEq)]
379pub enum ImmediateDialError {
380 #[error("`PeerId` missing from the address")]
382 PeerIdMissing,
383 #[error("Tried to dial self")]
385 TriedToDialSelf,
386 #[error("Already connected to peer")]
388 AlreadyConnected,
389 #[error("No address available for peer")]
391 NoAddressAvailable,
392 #[error("TaskClosed")]
394 TaskClosed,
395 #[error("Connection channel clogged")]
397 ChannelClogged,
398}
399
400#[cfg(feature = "quic")]
402#[derive(Debug, thiserror::Error, PartialEq)]
403pub enum QuicError {
404 #[error("Invalid certificate")]
406 InvalidCertificate,
407 #[error("Failed to negotiate QUIC: `{0}`")]
409 ConnectionError(#[from] quinn::ConnectionError),
410 #[error("Failed to connect to peer: `{0}`")]
412 ConnectError(#[from] quinn::ConnectError),
413}
414
415#[derive(Debug, thiserror::Error, PartialEq)]
417pub enum DnsError {
418 #[error("DNS failed to resolve url `{0}`")]
420 ResolveError(String),
421 #[error("DNS type is different from the provided IP address")]
425 IpVersionMismatch,
426}
427
428impl From<MultihashGeneric<64>> for Error {
429 fn from(hash: MultihashGeneric<64>) -> Self {
430 Error::AddressError(AddressError::InvalidPeerId(hash))
431 }
432}
433
434impl From<io::Error> for Error {
435 fn from(error: io::Error) -> Error {
436 Error::IoError(error.kind())
437 }
438}
439
440impl From<io::Error> for SubstreamError {
441 fn from(error: io::Error) -> SubstreamError {
442 SubstreamError::IoError(error.kind())
443 }
444}
445
446impl From<io::Error> for DialError {
447 fn from(error: io::Error) -> Self {
448 DialError::NegotiationError(NegotiationError::IoError(error.kind()))
449 }
450}
451
452impl From<crate::multistream_select::NegotiationError> for Error {
453 fn from(error: crate::multistream_select::NegotiationError) -> Error {
454 Error::NegotiationError(NegotiationError::MultistreamSelectError(error))
455 }
456}
457
458impl From<snow::Error> for Error {
459 fn from(error: snow::Error) -> Self {
460 Error::NegotiationError(NegotiationError::SnowError(error))
461 }
462}
463
464impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error {
465 fn from(_: tokio::sync::mpsc::error::SendError<T>) -> Self {
466 Error::EssentialTaskClosed
467 }
468}
469
470impl From<tokio::sync::oneshot::error::RecvError> for Error {
471 fn from(_: tokio::sync::oneshot::error::RecvError) -> Self {
472 Error::EssentialTaskClosed
473 }
474}
475
476impl From<prost::DecodeError> for Error {
477 fn from(error: prost::DecodeError) -> Self {
478 Error::ParseError(ParseError::ProstDecodeError(error))
479 }
480}
481
482impl From<prost::EncodeError> for Error {
483 fn from(error: prost::EncodeError) -> Self {
484 Error::ParseError(ParseError::ProstEncodeError(error))
485 }
486}
487
488impl From<io::Error> for NegotiationError {
489 fn from(error: io::Error) -> Self {
490 NegotiationError::IoError(error.kind())
491 }
492}
493
494impl From<ParseError> for Error {
495 fn from(error: ParseError) -> Self {
496 Error::ParseError(error)
497 }
498}
499
500impl From<MultihashGeneric<64>> for AddressError {
501 fn from(hash: MultihashGeneric<64>) -> Self {
502 AddressError::InvalidPeerId(hash)
503 }
504}
505
506#[cfg(feature = "quic")]
507impl From<quinn::ConnectionError> for Error {
508 fn from(error: quinn::ConnectionError) -> Self {
509 match error {
510 quinn::ConnectionError::TimedOut => Error::Timeout,
511 error => Error::Quinn(error),
512 }
513 }
514}
515
516#[cfg(feature = "quic")]
517impl From<quinn::ConnectionError> for DialError {
518 fn from(error: quinn::ConnectionError) -> Self {
519 match error {
520 quinn::ConnectionError::TimedOut => DialError::Timeout,
521 error => DialError::NegotiationError(NegotiationError::Quic(error.into())),
522 }
523 }
524}
525
526#[cfg(feature = "quic")]
527impl From<quinn::ConnectError> for DialError {
528 fn from(error: quinn::ConnectError) -> Self {
529 DialError::NegotiationError(NegotiationError::Quic(error.into()))
530 }
531}
532
533impl From<ConnectionLimitsError> for Error {
534 fn from(error: ConnectionLimitsError) -> Self {
535 Error::ConnectionLimit(error)
536 }
537}
538
539#[cfg(test)]
540mod tests {
541 use super::*;
542 use tokio::sync::mpsc::{channel, Sender};
543
544 #[tokio::test]
545 async fn try_from_errors() {
546 let (tx, rx) = channel(1);
547 drop(rx);
548
549 async fn test(tx: Sender<()>) -> crate::Result<()> {
550 tx.send(()).await.map_err(From::from)
551 }
552
553 match test(tx).await.unwrap_err() {
554 Error::EssentialTaskClosed => {}
555 _ => panic!("invalid error"),
556 }
557 }
558}