X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fmsgs.rs;h=6043bf35b99d4d85ae79a5656cc75b82e7d6c09e;hb=297390a882222ca044756f71cb3da3d639dae8d6;hp=477524a9d5433eaadf536cc5af3c8d35ede96eee;hpb=1852715fc8163262e370f49995e81ea6efb1cf83;p=rust-lightning diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 477524a9..6043bf35 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -46,6 +46,9 @@ use core::fmt::Debug; use core::ops::Deref; #[cfg(feature = "std")] use core::str::FromStr; +#[cfg(feature = "std")] +use std::net::SocketAddr; +use core::fmt::Display; use crate::io::{self, Cursor, Read}; use crate::io_extras::read_to_end; @@ -958,6 +961,37 @@ impl From for SocketAddress { } } +#[cfg(feature = "std")] +impl std::net::ToSocketAddrs for SocketAddress { + type Iter = std::vec::IntoIter; + + fn to_socket_addrs(&self) -> std::io::Result { + match self { + SocketAddress::TcpIpV4 { addr, port } => { + let ip_addr = std::net::Ipv4Addr::from(*addr); + let socket_addr = SocketAddr::new(ip_addr.into(), *port); + Ok(vec![socket_addr].into_iter()) + } + SocketAddress::TcpIpV6 { addr, port } => { + let ip_addr = std::net::Ipv6Addr::from(*addr); + let socket_addr = SocketAddr::new(ip_addr.into(), *port); + Ok(vec![socket_addr].into_iter()) + } + SocketAddress::Hostname { ref hostname, port } => { + (hostname.as_str(), *port).to_socket_addrs() + } + SocketAddress::OnionV2(..) => { + Err(std::io::Error::new(std::io::ErrorKind::Other, "Resolution of OnionV2 \ + addresses is currently unsupported.")) + } + SocketAddress::OnionV3 { .. } => { + Err(std::io::Error::new(std::io::ErrorKind::Other, "Resolution of OnionV3 \ + addresses is currently unsupported.")) + } + } + } +} + /// Parses an OnionV3 host and port into a [`SocketAddress::OnionV3`]. /// /// The host part must end with ".onion". @@ -984,6 +1018,35 @@ pub fn parse_onion_address(host: &str, port: u16) -> Result) -> core::fmt::Result { + match self { + SocketAddress::TcpIpV4{addr, port} => write!( + f, "{}.{}.{}.{}:{}", addr[0], addr[1], addr[2], addr[3], port)?, + SocketAddress::TcpIpV6{addr, port} => write!( + f, + "[{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}]:{}", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15], port + )?, + SocketAddress::OnionV2(bytes) => write!(f, "OnionV2({:?})", bytes)?, + SocketAddress::OnionV3 { + ed25519_pubkey, + checksum, + version, + port, + } => { + let [first_checksum_flag, second_checksum_flag] = checksum.to_be_bytes(); + let mut addr = vec![*version, first_checksum_flag, second_checksum_flag]; + addr.extend_from_slice(ed25519_pubkey); + let onion = base32::Alphabet::RFC4648 { padding: false }.encode(&addr); + write!(f, "{}.onion:{}", onion, port)? + }, + SocketAddress::Hostname { hostname, port } => write!(f, "{}:{}", hostname, port)?, + } + Ok(()) + } +} + #[cfg(feature = "std")] impl FromStr for SocketAddress { type Err = SocketAddressParseError; @@ -2681,7 +2744,8 @@ mod tests { use crate::chain::transaction::OutPoint; #[cfg(feature = "std")] - use std::net::{Ipv4Addr, Ipv6Addr}; + use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; + #[cfg(feature = "std")] use crate::ln::msgs::SocketAddressParseError; #[test] @@ -4071,32 +4135,41 @@ mod tests { #[test] #[cfg(feature = "std")] fn test_socket_address_from_str() { - assert_eq!(SocketAddress::TcpIpV4 { + let tcpip_v4 = SocketAddress::TcpIpV4 { addr: Ipv4Addr::new(127, 0, 0, 1).octets(), port: 1234, - }, SocketAddress::from_str("127.0.0.1:1234").unwrap()); + }; + assert_eq!(tcpip_v4, SocketAddress::from_str("127.0.0.1:1234").unwrap()); + assert_eq!(tcpip_v4, SocketAddress::from_str(&tcpip_v4.to_string()).unwrap()); - assert_eq!(SocketAddress::TcpIpV6 { + let tcpip_v6 = SocketAddress::TcpIpV6 { addr: Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).octets(), port: 1234, - }, SocketAddress::from_str("[0:0:0:0:0:0:0:1]:1234").unwrap()); - assert_eq!( - SocketAddress::Hostname { + }; + assert_eq!(tcpip_v6, SocketAddress::from_str("[0:0:0:0:0:0:0:1]:1234").unwrap()); + assert_eq!(tcpip_v6, SocketAddress::from_str(&tcpip_v6.to_string()).unwrap()); + + let hostname = SocketAddress::Hostname { hostname: Hostname::try_from("lightning-node.mydomain.com".to_string()).unwrap(), port: 1234, - }, SocketAddress::from_str("lightning-node.mydomain.com:1234").unwrap()); - assert_eq!( - SocketAddress::Hostname { - hostname: Hostname::try_from("example.com".to_string()).unwrap(), - port: 1234, - }, SocketAddress::from_str("example.com:1234").unwrap()); - assert_eq!(SocketAddress::OnionV3 { + }; + assert_eq!(hostname, SocketAddress::from_str("lightning-node.mydomain.com:1234").unwrap()); + assert_eq!(hostname, SocketAddress::from_str(&hostname.to_string()).unwrap()); + + let onion_v2 = SocketAddress::OnionV2 ([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7],); + assert_eq!("OnionV2([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7])", &onion_v2.to_string()); + assert_eq!(Err(SocketAddressParseError::InvalidOnionV3), SocketAddress::from_str("FACEBOOKCOREWWWI.onion:9735")); + + let onion_v3 = SocketAddress::OnionV3 { ed25519_pubkey: [37, 24, 75, 5, 25, 73, 117, 194, 139, 102, 182, 107, 4, 105, 247, 246, 85, 111, 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, 33, 71, 3], checksum: 48326, version: 121, port: 1234 - }, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap()); + }; + assert_eq!(onion_v3, SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234").unwrap()); + assert_eq!(onion_v3, SocketAddress::from_str(&onion_v3.to_string()).unwrap()); + assert_eq!(Err(SocketAddressParseError::InvalidOnionV3), SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6.onion:1234")); assert_eq!(Err(SocketAddressParseError::InvalidInput), SocketAddress::from_str("127.0.0.1@1234")); assert_eq!(Err(SocketAddressParseError::InvalidInput), "".parse::()); @@ -4110,4 +4183,22 @@ mod tests { assert!("invalid-address".parse::().is_err()); assert!(SocketAddress::from_str("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.onion:1234").is_err()); } + + #[test] + #[cfg(feature = "std")] + fn test_socket_address_to_socket_addrs() { + assert_eq!(SocketAddress::TcpIpV4 {addr:[0u8; 4], port: 1337,}.to_socket_addrs().unwrap().next().unwrap(), + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0,0,0,0), 1337))); + assert_eq!(SocketAddress::TcpIpV6 {addr:[0u8; 16], port: 1337,}.to_socket_addrs().unwrap().next().unwrap(), + SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from([0u8; 16]), 1337, 0, 0))); + assert_eq!(SocketAddress::Hostname { hostname: Hostname::try_from("0.0.0.0".to_string()).unwrap(), port: 0 } + .to_socket_addrs().unwrap().next().unwrap(), SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([0u8; 4]),0))); + assert!(SocketAddress::OnionV2([0u8; 12]).to_socket_addrs().is_err()); + assert!(SocketAddress::OnionV3{ ed25519_pubkey: [37, 24, 75, 5, 25, 73, 117, 194, 139, 102, + 182, 107, 4, 105, 247, 246, 85, 111, 177, 172, 49, 137, 167, 155, 64, 221, 163, 47, 31, + 33, 71, 3], + checksum: 48326, + version: 121, + port: 1234 }.to_socket_addrs().is_err()); + } }