diff --git a/src/lib.rs b/src/lib.rs index 92a31fb..3d4fee5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ use std::{ convert::TryFrom, fmt, io, iter::FromIterator, - net::{IpAddr, Ipv4Addr, Ipv6Addr}, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, result::Result as StdResult, str::FromStr, sync::Arc, @@ -199,6 +199,30 @@ impl Multiaddr { pub fn protocol_stack(&self) -> ProtoStackIter { ProtoStackIter { parts: self.iter() } } + + pub fn into_tcp_socket(&self) -> Result { + match (self.iter().next(), self.iter().nth(1)) { + (Some(Protocol::Ip4(ip4)), Some(Protocol::Tcp(port))) => { + Ok(SocketAddr::V4(SocketAddrV4::new(ip4, port))) + } + (Some(Protocol::Ip6(ip6)), Some(Protocol::Tcp(port))) => { + Ok(SocketAddr::V6(SocketAddrV6::new(ip6, port, 0, 0))) + } + _ => Err(Error::InvalidMultiaddr), + } + } + + pub fn into_udp_socket(&self) -> Result { + match (self.iter().next(), self.iter().nth(1)) { + (Some(Protocol::Ip4(ip4)), Some(Protocol::Udp(port))) => { + Ok(SocketAddr::V4(SocketAddrV4::new(ip4, port))) + } + (Some(Protocol::Ip6(ip6)), Some(Protocol::Udp(port))) => { + Ok(SocketAddr::V6(SocketAddrV6::new(ip6, port, 0, 0))) + } + _ => Err(Error::InvalidMultiaddr), + } + } } impl fmt::Debug for Multiaddr { @@ -478,3 +502,16 @@ macro_rules! multiaddr { } } } + +impl From for Multiaddr { + fn from(socket: SocketAddr) -> Self { + match socket { + SocketAddr::V4(sock) => Self::empty() + .with(Protocol::Ip4(*sock.ip())) + .with(Protocol::Tcp(sock.port())), + SocketAddr::V6(sock) => Self::empty() + .with(Protocol::Ip6(*sock.ip())) + .with(Protocol::Tcp(sock.port())), + } + } +} diff --git a/tests/lib.rs b/tests/lib.rs index 071a4ce..8c339fa 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -7,7 +7,7 @@ use std::{ borrow::Cow, convert::{TryFrom, TryInto}, iter::{self, FromIterator}, - net::{Ipv4Addr, Ipv6Addr}, + net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, str::FromStr, }; @@ -661,3 +661,97 @@ fn arbitrary_impl_for_all_proto_variants() { let variants = core::mem::variant_count::() as u8; assert_eq!(variants, Proto::IMPL_VARIANT_COUNT); } + +#[test] +fn from_ipv4_socket() { + let socket_addr: SocketAddr = + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80)); + let expected_multiaddr: Multiaddr = Multiaddr::empty() + .with(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .with(Protocol::Tcp(80)); + + let actual_multiaddr: Multiaddr = socket_addr.into(); + + assert_eq!(actual_multiaddr, expected_multiaddr); +} + +#[test] +fn from_ipv6_socket() { + let socket_addr: SocketAddr = SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), + 80, + 0, + 0, + )); + let expected_multiaddr: Multiaddr = Multiaddr::empty() + .with(Protocol::Ip6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))) + .with(Protocol::Tcp(80)); + + let actual_multiaddr: Multiaddr = socket_addr.into(); + + assert_eq!(actual_multiaddr, expected_multiaddr); +} + +#[test] +fn into_ipv4_tcp_socket() { + let multiaddr: Multiaddr = Multiaddr::empty() + .with(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .with(Protocol::Tcp(80)); + let expected_socket_addr: SocketAddr = + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80)); + + let actual_socket_addr: Result = multiaddr.into_tcp_socket(); + + assert!(actual_socket_addr.is_ok()); + assert_eq!(actual_socket_addr.unwrap(), expected_socket_addr); +} + +#[test] +fn into_ipv6_tcp_socket() { + let multiaddr: Multiaddr = Multiaddr::empty() + .with(Protocol::Ip6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))) + .with(Protocol::Tcp(80)); + let expected_socket_addr: SocketAddr = SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), + 80, + 0, + 0, + )); + + let actual_socket_addr: Result = multiaddr.into_tcp_socket(); + + assert!(actual_socket_addr.is_ok()); + assert_eq!(actual_socket_addr.unwrap(), expected_socket_addr); +} + +#[test] +fn into_ipv4_udp_socket() { + let multiaddr: Multiaddr = Multiaddr::empty() + .with(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .with(Protocol::Udp(80)); + let expected_socket_addr: SocketAddr = + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80)); + + let actual_socket_addr: Result = multiaddr.into_udp_socket(); + + assert!(actual_socket_addr.is_ok()); + assert_eq!(actual_socket_addr.unwrap(), expected_socket_addr); +} + +#[test] +fn into_ipv6_udp_socket() { + let multiaddr: Multiaddr = Multiaddr::empty() + .with(Protocol::Ip6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))) + .with(Protocol::Udp(80)); + let expected_socket_addr: SocketAddr = SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), + 80, + 0, + 0, + )); + + let actual_socket_addr: Result = multiaddr.into_udp_socket(); + + assert!(actual_socket_addr.is_ok()); + assert_eq!(actual_socket_addr.unwrap(), expected_socket_addr); +}