Skip to content

Commit 213b85b

Browse files
committed
p2p: remove io::Error from exposed API
Part of the process to break the p2p package's dependency on the old io package.
1 parent 4c249f7 commit 213b85b

File tree

1 file changed

+71
-21
lines changed

1 file changed

+71
-21
lines changed

p2p/src/address.rs

Lines changed: 71 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ impl Address {
4747
}
4848

4949
/// Extracts socket address from an [Address] message.
50-
/// This will return [io::Error] [io::ErrorKind::AddrNotAvailable]
51-
/// if the message contains a Tor address.
52-
pub fn socket_addr(&self) -> Result<SocketAddr, io::Error> {
50+
///
51+
/// # Errors
52+
///
53+
/// Returns an error if the message contains a Tor V2 onion address.
54+
pub fn socket_addr(&self) -> Result<SocketAddr, UnroutableAddressError> {
5355
let addr = &self.address;
5456
if addr[0..3] == ONION {
55-
return Err(io::Error::from(io::ErrorKind::AddrNotAvailable));
57+
return Err(UnroutableAddressError::TorV2);
5658
}
5759
let ipv6 =
5860
Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]);
@@ -126,7 +128,9 @@ impl fmt::Debug for Address {
126128
impl ToSocketAddrs for Address {
127129
type Iter = iter::Once<SocketAddr>;
128130
fn to_socket_addrs(&self) -> Result<Self::Iter, std::io::Error> {
129-
Ok(iter::once(self.socket_addr()?))
131+
self.socket_addr()
132+
.map(iter::once)
133+
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))
130134
}
131135
}
132136

@@ -148,16 +152,16 @@ pub enum AddrV2 {
148152
}
149153

150154
impl TryFrom<AddrV2> for IpAddr {
151-
type Error = AddrV2ToIpAddrError;
155+
type Error = UnroutableAddressError;
152156

153157
fn try_from(addr: AddrV2) -> Result<Self, Self::Error> {
154158
match addr {
155159
AddrV2::Ipv4(ip) => Ok(Self::V4(ip)),
156160
AddrV2::Ipv6(ip) => Ok(Self::V6(ip)),
157-
AddrV2::Cjdns(_) => Err(AddrV2ToIpAddrError::Cjdns),
158-
AddrV2::TorV3(_) => Err(AddrV2ToIpAddrError::TorV3),
159-
AddrV2::I2p(_) => Err(AddrV2ToIpAddrError::I2p),
160-
AddrV2::Unknown(_, _) => Err(AddrV2ToIpAddrError::Unknown),
161+
AddrV2::Cjdns(_) => Err(UnroutableAddressError::Cjdns),
162+
AddrV2::TorV3(_) => Err(UnroutableAddressError::TorV3),
163+
AddrV2::I2p(_) => Err(UnroutableAddressError::I2p),
164+
AddrV2::Unknown(_, _) => Err(UnroutableAddressError::Unknown),
161165
}
162166
}
163167
}
@@ -202,11 +206,15 @@ impl From<IpAddr> for AddrV2 {
202206
}
203207

204208
impl From<Ipv4Addr> for AddrV2 {
205-
fn from(addr: Ipv4Addr) -> Self { Self::Ipv4(addr) }
209+
fn from(addr: Ipv4Addr) -> Self {
210+
Self::Ipv4(addr)
211+
}
206212
}
207213

208214
impl From<Ipv6Addr> for AddrV2 {
209-
fn from(addr: Ipv6Addr) -> Self { Self::Ipv6(addr) }
215+
fn from(addr: Ipv6Addr) -> Self {
216+
Self::Ipv6(addr)
217+
}
210218
}
211219

212220
impl Encodable for AddrV2 {
@@ -317,13 +325,19 @@ pub struct AddrV2Message {
317325

318326
impl AddrV2Message {
319327
/// Extracts socket address from an [AddrV2Message] message.
320-
/// This will return [io::Error] [io::ErrorKind::AddrNotAvailable]
321-
/// if the address type can't be converted into a [SocketAddr].
322-
pub fn socket_addr(&self) -> Result<SocketAddr, io::Error> {
328+
///
329+
/// # Errors
330+
///
331+
/// Returns an error if the address type cannot be converted to a socket address
332+
/// (e.g. Tor, I2P, CJDNS addresses).
333+
pub fn socket_addr(&self) -> Result<SocketAddr, UnroutableAddressError> {
323334
match self.addr {
324335
AddrV2::Ipv4(addr) => Ok(SocketAddr::V4(SocketAddrV4::new(addr, self.port))),
325336
AddrV2::Ipv6(addr) => Ok(SocketAddr::V6(SocketAddrV6::new(addr, self.port, 0, 0))),
326-
_ => Err(io::Error::from(io::ErrorKind::AddrNotAvailable)),
337+
AddrV2::TorV3(_) => Err(UnroutableAddressError::TorV3),
338+
AddrV2::I2p(_) => Err(UnroutableAddressError::I2p),
339+
AddrV2::Cjdns(_) => Err(UnroutableAddressError::Cjdns),
340+
AddrV2::Unknown(_, _) => Err(UnroutableAddressError::Unknown),
327341
}
328342
}
329343
}
@@ -356,10 +370,46 @@ impl Decodable for AddrV2Message {
356370
impl ToSocketAddrs for AddrV2Message {
357371
type Iter = iter::Once<SocketAddr>;
358372
fn to_socket_addrs(&self) -> Result<Self::Iter, std::io::Error> {
359-
Ok(iter::once(self.socket_addr()?))
373+
self.socket_addr()
374+
.map(iter::once)
375+
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))
360376
}
361377
}
362378

379+
/// Error returned when an address cannot be converted to an IP-based address.
380+
///
381+
/// Addresses like Tor, I2P, and CJDNS use different routing mechanisms
382+
/// and cannot be represented as standard IP addresses or socket addresses.
383+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
384+
#[non_exhaustive]
385+
pub enum UnroutableAddressError {
386+
/// Tor V2 onion address.
387+
TorV2,
388+
/// Tor V3 onion address.
389+
TorV3,
390+
/// I2P address.
391+
I2p,
392+
/// CJDNS address.
393+
Cjdns,
394+
/// Unknown address type.
395+
Unknown,
396+
}
397+
398+
impl fmt::Display for UnroutableAddressError {
399+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
400+
match self {
401+
Self::TorV2 => write!(f, "Tor v2 addresses cannot be converted to IP addresses"),
402+
Self::TorV3 => write!(f, "Tor v3 addresses cannot be converted to IP addresses"),
403+
Self::I2p => write!(f, "I2P addresses cannot be converted to IP addresses"),
404+
Self::Cjdns => write!(f, "CJDNS addresses cannot be converted to IP addresses"),
405+
Self::Unknown => write!(f, "unknown address type cannot be converted to IP addresses"),
406+
}
407+
}
408+
}
409+
410+
#[cfg(feature = "std")]
411+
impl std::error::Error for UnroutableAddressError {}
412+
363413
/// Error types for [`AddrV2`] to [`IpAddr`] conversion.
364414
#[derive(Debug, PartialEq, Eq)]
365415
pub enum AddrV2ToIpAddrError {
@@ -794,7 +844,7 @@ mod test {
794844
let result = IpAddr::try_from(addr);
795845

796846
assert!(result.is_err());
797-
assert_eq!(result.unwrap_err(), AddrV2ToIpAddrError::Cjdns);
847+
assert_eq!(result.unwrap_err(), UnroutableAddressError::Cjdns);
798848
}
799849

800850
#[test]
@@ -803,7 +853,7 @@ mod test {
803853
let result = IpAddr::try_from(addr);
804854

805855
assert!(result.is_err());
806-
assert_eq!(result.unwrap_err(), AddrV2ToIpAddrError::TorV3);
856+
assert_eq!(result.unwrap_err(), UnroutableAddressError::TorV3);
807857
}
808858

809859
#[test]
@@ -812,7 +862,7 @@ mod test {
812862
let result = IpAddr::try_from(addr);
813863

814864
assert!(result.is_err());
815-
assert_eq!(result.unwrap_err(), AddrV2ToIpAddrError::I2p);
865+
assert_eq!(result.unwrap_err(), UnroutableAddressError::I2p);
816866
}
817867

818868
#[test]
@@ -821,7 +871,7 @@ mod test {
821871
let result = IpAddr::try_from(addr);
822872

823873
assert!(result.is_err());
824-
assert_eq!(result.unwrap_err(), AddrV2ToIpAddrError::Unknown);
874+
assert_eq!(result.unwrap_err(), UnroutableAddressError::Unknown);
825875
}
826876

827877
#[test]

0 commit comments

Comments
 (0)