@@ -48,6 +48,7 @@ use core::ops::Deref;
4848use core:: str:: FromStr ;
4949#[ cfg( feature = "std" ) ]
5050use std:: net:: SocketAddr ;
51+ use core:: fmt:: Display ;
5152use crate :: io:: { self , Cursor , Read } ;
5253use crate :: io_extras:: read_to_end;
5354
@@ -1017,6 +1018,35 @@ pub fn parse_onion_address(host: &str, port: u16) -> Result<SocketAddress, Socke
10171018 }
10181019}
10191020
1021+ impl Display for SocketAddress {
1022+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
1023+ match self {
1024+ SocketAddress :: TcpIpV4 { addr, port} => write ! (
1025+ f, "{}.{}.{}.{}:{}" , addr[ 0 ] , addr[ 1 ] , addr[ 2 ] , addr[ 3 ] , port) ?,
1026+ SocketAddress :: TcpIpV6 { addr, port} => write ! (
1027+ f,
1028+ "[{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}]:{}" ,
1029+ 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
1030+ ) ?,
1031+ SocketAddress :: OnionV2 ( bytes) => write ! ( f, "OnionV2({:?})" , bytes) ?,
1032+ SocketAddress :: OnionV3 {
1033+ ed25519_pubkey,
1034+ checksum,
1035+ version,
1036+ port,
1037+ } => {
1038+ let [ first_checksum_flag, second_checksum_flag] = checksum. to_be_bytes ( ) ;
1039+ let mut addr = vec ! [ * version, first_checksum_flag, second_checksum_flag] ;
1040+ addr. extend_from_slice ( ed25519_pubkey) ;
1041+ let onion = base32:: Alphabet :: RFC4648 { padding : false } . encode ( & addr) ;
1042+ write ! ( f, "{}.onion:{}" , onion, port) ?
1043+ } ,
1044+ SocketAddress :: Hostname { hostname, port } => write ! ( f, "{}:{}" , hostname, port) ?,
1045+ }
1046+ Ok ( ( ) )
1047+ }
1048+ }
1049+
10201050#[ cfg( feature = "std" ) ]
10211051impl FromStr for SocketAddress {
10221052 type Err = SocketAddressParseError ;
@@ -4104,32 +4134,41 @@ mod tests {
41044134 #[ test]
41054135 #[ cfg( feature = "std" ) ]
41064136 fn test_socket_address_from_str ( ) {
4107- assert_eq ! ( SocketAddress :: TcpIpV4 {
4137+ let tcpip_v4 = SocketAddress :: TcpIpV4 {
41084138 addr : Ipv4Addr :: new ( 127 , 0 , 0 , 1 ) . octets ( ) ,
41094139 port : 1234 ,
4110- } , SocketAddress :: from_str( "127.0.0.1:1234" ) . unwrap( ) ) ;
4140+ } ;
4141+ assert_eq ! ( tcpip_v4, SocketAddress :: from_str( "127.0.0.1:1234" ) . unwrap( ) ) ;
4142+ assert_eq ! ( tcpip_v4, SocketAddress :: from_str( & tcpip_v4. to_string( ) ) . unwrap( ) ) ;
41114143
4112- assert_eq ! ( SocketAddress :: TcpIpV6 {
4144+ let tcpip_v6 = SocketAddress :: TcpIpV6 {
41134145 addr : Ipv6Addr :: new ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ) . octets ( ) ,
41144146 port : 1234 ,
4115- } , SocketAddress :: from_str( "[0:0:0:0:0:0:0:1]:1234" ) . unwrap( ) ) ;
4116- assert_eq ! (
4117- SocketAddress :: Hostname {
4147+ } ;
4148+ assert_eq ! ( tcpip_v6, SocketAddress :: from_str( "[0:0:0:0:0:0:0:1]:1234" ) . unwrap( ) ) ;
4149+ assert_eq ! ( tcpip_v6, SocketAddress :: from_str( & tcpip_v6. to_string( ) ) . unwrap( ) ) ;
4150+
4151+ let hostname = SocketAddress :: Hostname {
41184152 hostname : Hostname :: try_from ( "lightning-node.mydomain.com" . to_string ( ) ) . unwrap ( ) ,
41194153 port : 1234 ,
4120- } , SocketAddress :: from_str( "lightning-node.mydomain.com:1234" ) . unwrap( ) ) ;
4121- assert_eq ! (
4122- SocketAddress :: Hostname {
4123- hostname: Hostname :: try_from( "example.com" . to_string( ) ) . unwrap( ) ,
4124- port: 1234 ,
4125- } , SocketAddress :: from_str( "example.com:1234" ) . unwrap( ) ) ;
4126- assert_eq ! ( SocketAddress :: OnionV3 {
4154+ } ;
4155+ assert_eq ! ( hostname, SocketAddress :: from_str( "lightning-node.mydomain.com:1234" ) . unwrap( ) ) ;
4156+ assert_eq ! ( hostname, SocketAddress :: from_str( & hostname. to_string( ) ) . unwrap( ) ) ;
4157+
4158+ let onion_v2 = SocketAddress :: OnionV2 ( [ 40 , 4 , 64 , 185 , 202 , 19 , 162 , 75 , 90 , 200 , 38 , 7 ] , ) ;
4159+ assert_eq ! ( "OnionV2([40, 4, 64, 185, 202, 19, 162, 75, 90, 200, 38, 7])" , & onion_v2. to_string( ) ) ;
4160+ assert_eq ! ( Err ( SocketAddressParseError :: InvalidOnionV3 ) , SocketAddress :: from_str( "FACEBOOKCOREWWWI.onion:9735" ) ) ;
4161+
4162+ let onion_v3 = SocketAddress :: OnionV3 {
41274163 ed25519_pubkey : [ 37 , 24 , 75 , 5 , 25 , 73 , 117 , 194 , 139 , 102 , 182 , 107 , 4 , 105 , 247 , 246 , 85 ,
41284164 111 , 177 , 172 , 49 , 137 , 167 , 155 , 64 , 221 , 163 , 47 , 31 , 33 , 71 , 3 ] ,
41294165 checksum : 48326 ,
41304166 version : 121 ,
41314167 port : 1234
4132- } , SocketAddress :: from_str( "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234" ) . unwrap( ) ) ;
4168+ } ;
4169+ assert_eq ! ( onion_v3, SocketAddress :: from_str( "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234" ) . unwrap( ) ) ;
4170+ assert_eq ! ( onion_v3, SocketAddress :: from_str( & onion_v3. to_string( ) ) . unwrap( ) ) ;
4171+
41334172 assert_eq ! ( Err ( SocketAddressParseError :: InvalidOnionV3 ) , SocketAddress :: from_str( "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6.onion:1234" ) ) ;
41344173 assert_eq ! ( Err ( SocketAddressParseError :: InvalidInput ) , SocketAddress :: from_str( "127.0.0.1@1234" ) ) ;
41354174 assert_eq ! ( Err ( SocketAddressParseError :: InvalidInput ) , "" . parse:: <SocketAddress >( ) ) ;
0 commit comments