use std::{
io::ErrorKind,
net::{IpAddr, SocketAddr},
};
use memberlist_core::transport::TransportError;
use nodecraft::resolver::AddressResolver;
#[derive(thiserror::Error)]
pub enum NetTransportError<A: AddressResolver> {
#[error("no private IP address found, and explicit IP not provided")]
NoPrivateIP,
#[error("at least one bind address is required")]
EmptyBindAddresses,
#[error("the ip {0} is blocked")]
BlockedIp(IpAddr),
#[error("failed to start packet listener on {0}: {1}")]
ListenPacket(SocketAddr, std::io::Error),
#[error("failed to start promised listener on {0}: {1}")]
ListenPromised(SocketAddr, std::io::Error),
#[error("failed to create resolver: {0}")]
Resolver(A::Error),
#[error("failed to resolve address {addr}: {err}")]
Resolve {
addr: A::Address,
err: A::Error,
},
#[error("packet too large, the maximum packet can be sent is 65535, got {0}")]
PacketTooLarge(usize),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("{0}")]
Custom(std::borrow::Cow<'static, str>),
}
impl<A: AddressResolver> core::fmt::Debug for NetTransportError<A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
core::fmt::Display::fmt(&self, f)
}
}
impl<A> TransportError for NetTransportError<A>
where
A: AddressResolver,
A::Address: Send + Sync + 'static,
{
fn is_remote_failure(&self) -> bool {
match self {
Self::Io(err) => matches!(
err.kind(),
ErrorKind::ConnectionRefused
| ErrorKind::ConnectionReset
| ErrorKind::ConnectionAborted
| ErrorKind::BrokenPipe
| ErrorKind::TimedOut
| ErrorKind::NotConnected
),
_ => false,
}
}
fn custom(err: std::borrow::Cow<'static, str>) -> Self {
Self::Custom(err)
}
}