@@ -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