@@ -774,8 +774,12 @@ pub enum SocketAddress {
774774 /// An old-style Tor onion address/port on which the peer is listening.
775775 ///
776776 /// This field is deprecated and the Tor network generally no longer supports V2 Onion
777- /// addresses. Thus, the details are not parsed here.
778- OnionV2 ( [ u8 ; 12 ] ) ,
777+ /// addresses.
778+ OnionV2 {
779+ /// The base32 of first 80 bits
780+ addr : [ u8 ; 10 ] ,
781+ port : u16 ,
782+ } ,
779783 /// A new-style Tor onion address/port on which the peer is listening.
780784 ///
781785 /// To create the human-readable "hostname", concatenate the ED25519 pubkey, checksum, and version,
@@ -805,7 +809,7 @@ impl SocketAddress {
805809 match self {
806810 & SocketAddress :: TcpIpV4 { ..} => { 1 } ,
807811 & SocketAddress :: TcpIpV6 { ..} => { 2 } ,
808- & SocketAddress :: OnionV2 ( _ ) => { 3 } ,
812+ & SocketAddress :: OnionV2 { .. } => { 3 } ,
809813 & SocketAddress :: OnionV3 { ..} => { 4 } ,
810814 & SocketAddress :: Hostname { ..} => { 5 } ,
811815 }
@@ -816,7 +820,7 @@ impl SocketAddress {
816820 match self {
817821 & SocketAddress :: TcpIpV4 { .. } => { 6 } ,
818822 & SocketAddress :: TcpIpV6 { .. } => { 18 } ,
819- & SocketAddress :: OnionV2 ( _ ) => { 12 } ,
823+ & SocketAddress :: OnionV2 { .. } => { 12 } ,
820824 & SocketAddress :: OnionV3 { .. } => { 37 } ,
821825 // Consists of 1-byte hostname length, hostname bytes, and 2-byte port.
822826 & SocketAddress :: Hostname { ref hostname, .. } => { u16:: from ( hostname. len ( ) ) + 3 } ,
@@ -842,9 +846,10 @@ impl Writeable for SocketAddress {
842846 addr. write ( writer) ?;
843847 port. write ( writer) ?;
844848 } ,
845- & SocketAddress :: OnionV2 ( bytes ) => {
849+ & SocketAddress :: OnionV2 { ref addr , ref port } => {
846850 3u8 . write ( writer) ?;
847- bytes. write ( writer) ?;
851+ addr. write ( writer) ?;
852+ port. write ( writer) ?;
848853 } ,
849854 & SocketAddress :: OnionV3 { ref ed25519_pubkey, ref checksum, ref version, ref port } => {
850855 4u8 . write ( writer) ?;
@@ -879,7 +884,10 @@ impl Readable for Result<SocketAddress, u8> {
879884 port : Readable :: read ( reader) ?,
880885 } ) )
881886 } ,
882- 3 => Ok ( Ok ( SocketAddress :: OnionV2 ( Readable :: read ( reader) ?) ) ) ,
887+ 3 => Ok ( Ok ( SocketAddress :: OnionV2 {
888+ addr : Readable :: read ( reader) ?,
889+ port : Readable :: read ( reader) ?,
890+ } ) ) ,
883891 4 => {
884892 Ok ( Ok ( SocketAddress :: OnionV3 {
885893 ed25519_pubkey : Readable :: read ( reader) ?,
@@ -961,40 +969,24 @@ impl From<std::net::SocketAddr> for SocketAddress {
961969 }
962970}
963971
964- /// Parses an OnionV2 host and port into a [`SocketAddress::OnionV2`].
965- ///
966- /// The host part must end with ".onion".
967- pub fn parse_onion_v2_address ( host : & str ) -> Result < SocketAddress , SocketAddressParseError > {
968- if host. ends_with ( ".onion" ) {
969- let domain = & host[ ..host. len ( ) - ".onion" . len ( ) ] ;
970- if domain. len ( ) != 16 {
971- return Err ( SocketAddressParseError :: InvalidOnionV2 ) ;
972- }
973- let onion = base32:: Alphabet :: RFC4648 { padding : false } . decode ( & domain) . map_err ( |_| SocketAddressParseError :: InvalidOnionV2 ) ?;
974- if onion. len ( ) != 12 {
975- return Err ( SocketAddressParseError :: InvalidOnionV2 ) ;
976- }
977- let mut bytes = [ 0 ; 12 ] ;
978- bytes. copy_from_slice ( & onion) ;
979- return Ok ( SocketAddress :: OnionV2 ( bytes) ) ;
980- } else {
981- return Err ( SocketAddressParseError :: InvalidInput ) ;
982- }
983- }
984-
985- /// Parses an OnionV3 host and port into a [`SocketAddress::OnionV3`].
972+ /// Parses an Onion host and port into a [`SocketAddress::OnionV3`].
986973///
987974/// The host part must end with ".onion".
988- pub fn parse_onion_v3_address ( host : & str , port : u16 ) -> Result < SocketAddress , SocketAddressParseError > {
975+ pub fn parse_onion_address ( host : & str , port : u16 ) -> Result < SocketAddress , SocketAddressParseError > {
989976 if host. ends_with ( ".onion" ) {
990977 let domain = & host[ ..host. len ( ) - ".onion" . len ( ) ] ;
991- if domain. len ( ) != 56 {
978+ if domain. len ( ) != 56 && domain . len ( ) != 16 {
992979 return Err ( SocketAddressParseError :: InvalidOnionV3 ) ;
993980 }
994981 let onion = base32:: Alphabet :: RFC4648 { padding : false } . decode ( & domain) . map_err ( |_| SocketAddressParseError :: InvalidOnionV3 ) ?;
995- if onion. len ( ) != 35 {
982+ if onion. len ( ) != 35 && onion . len ( ) != 10 {
996983 return Err ( SocketAddressParseError :: InvalidOnionV3 ) ;
997984 }
985+ if onion. len ( ) == 10 {
986+ let mut addr = [ 0 ; 10 ] ;
987+ addr. copy_from_slice ( & onion) ;
988+ return Ok ( SocketAddress :: OnionV2 { addr, port } ) ;
989+ }
998990 let version = onion[ 0 ] ;
999991 let first_checksum_flag = onion[ 1 ] ;
1000992 let second_checksum_flag = onion[ 2 ] ;
@@ -1009,9 +1001,9 @@ pub fn parse_onion_v3_address(host: &str, port: u16) -> Result<SocketAddress, So
10091001}
10101002
10111003/// [`SocketAddress::OnionV2`] to onion address string
1012- pub fn to_onion_v2_string ( bytes : & [ u8 ; 12 ] ) -> String {
1013- let onion = base32:: Alphabet :: RFC4648 { padding : false } . encode ( & bytes [ ..] ) ;
1014- format ! ( "{onion}.onion" )
1004+ pub fn to_onion_v2_string ( addr : & [ u8 ; 10 ] , port : & u16 ) -> String {
1005+ let onion = base32:: Alphabet :: RFC4648 { padding : false } . encode ( & addr [ ..] ) ;
1006+ format ! ( "{onion}.onion:{port} " )
10151007}
10161008
10171009/// [`SocketAddress::OnionV3`] to onion address string
@@ -1029,7 +1021,7 @@ impl Display for SocketAddress {
10291021 match self {
10301022 SocketAddress :: TcpIpV4 { addr, port} => write ! ( f, "{}:{port}" , std:: net:: Ipv4Addr :: from( * addr) ) ?,
10311023 SocketAddress :: TcpIpV6 { addr, port} => write ! ( f, "[{}]:{port}" , std:: net:: Ipv6Addr :: from( * addr) ) ?,
1032- SocketAddress :: OnionV2 ( bytes ) => write ! ( f, "{}" , to_onion_v2_string( & bytes ) ) ?,
1024+ SocketAddress :: OnionV2 { addr , port } => write ! ( f, "{}" , to_onion_v2_string( addr , port ) ) ?,
10331025 SocketAddress :: OnionV3 {
10341026 ed25519_pubkey,
10351027 checksum,
@@ -1052,13 +1044,12 @@ impl FromStr for SocketAddress {
10521044 Err ( _) => {
10531045 let trimmed_input = match s. rfind ( ":" ) {
10541046 Some ( pos) => pos,
1055- None if s. ends_with ( ".onion" ) => return parse_onion_v2_address ( s) ,
1056- _ => return Err ( SocketAddressParseError :: InvalidInput ) ,
1047+ None => return Err ( SocketAddressParseError :: InvalidInput ) ,
10571048 } ;
10581049 let host = & s[ ..trimmed_input] ;
10591050 let port: u16 = s[ trimmed_input + 1 ..] . parse ( ) . map_err ( |_| SocketAddressParseError :: InvalidPort ) ?;
10601051 if host. ends_with ( ".onion" ) {
1061- return parse_onion_v3_address ( host, port) ;
1052+ return parse_onion_address ( host, port) ;
10621053 } ;
10631054 if let Ok ( hostname) = Hostname :: try_from ( s[ ..trimmed_input] . to_string ( ) ) {
10641055 return Ok ( SocketAddress :: Hostname { hostname, port } ) ;
@@ -2915,9 +2906,10 @@ mod tests {
29152906 } ) ;
29162907 }
29172908 if onionv2 {
2918- addresses. push ( msgs:: SocketAddress :: OnionV2 (
2919- [ 255 , 254 , 253 , 252 , 251 , 250 , 249 , 248 , 247 , 246 , 38 , 7 ]
2920- ) ) ;
2909+ addresses. push ( msgs:: SocketAddress :: OnionV2 {
2910+ addr : [ 255 , 254 , 253 , 252 , 251 , 250 , 249 , 248 , 247 , 246 ] ,
2911+ port : 9735 ,
2912+ } ) ;
29212913 }
29222914 if onionv3 {
29232915 addresses. push ( msgs:: SocketAddress :: OnionV3 {
@@ -4125,19 +4117,19 @@ mod tests {
41254117 #[ test]
41264118 #[ cfg( feature = "std" ) ]
41274119 fn test_socket_address_from_str ( ) {
4128- let v4 = SocketAddress :: TcpIpV4 {
4120+ let tcpip_v4 = SocketAddress :: TcpIpV4 {
41294121 addr : Ipv4Addr :: new ( 127 , 0 , 0 , 1 ) . octets ( ) ,
41304122 port : 1234 ,
41314123 } ;
4132- assert_eq ! ( v4 , SocketAddress :: from_str( "127.0.0.1:1234" ) . unwrap( ) ) ;
4133- assert_eq ! ( v4 , SocketAddress :: from_str( & v4 . to_string( ) ) . unwrap( ) ) ;
4124+ assert_eq ! ( tcpip_v4 , SocketAddress :: from_str( "127.0.0.1:1234" ) . unwrap( ) ) ;
4125+ assert_eq ! ( tcpip_v4 , SocketAddress :: from_str( & tcpip_v4 . to_string( ) ) . unwrap( ) ) ;
41344126
4135- let v6 = SocketAddress :: TcpIpV6 {
4127+ let tcpip_v6 = SocketAddress :: TcpIpV6 {
41364128 addr : Ipv6Addr :: new ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ) . octets ( ) ,
41374129 port : 1234 ,
41384130 } ;
4139- assert_eq ! ( v6 , SocketAddress :: from_str( "[0:0:0:0:0:0:0:1]:1234" ) . unwrap( ) ) ;
4140- assert_eq ! ( v6 , SocketAddress :: from_str( & v6 . to_string( ) ) . unwrap( ) ) ;
4131+ assert_eq ! ( tcpip_v6 , SocketAddress :: from_str( "[0:0:0:0:0:0:0:1]:1234" ) . unwrap( ) ) ;
4132+ assert_eq ! ( tcpip_v6 , SocketAddress :: from_str( & tcpip_v6 . to_string( ) ) . unwrap( ) ) ;
41414133
41424134 let hostname = SocketAddress :: Hostname {
41434135 hostname : Hostname :: try_from ( "lightning-node.mydomain.com" . to_string ( ) ) . unwrap ( ) ,
@@ -4146,19 +4138,22 @@ mod tests {
41464138 assert_eq ! ( hostname, SocketAddress :: from_str( "lightning-node.mydomain.com:1234" ) . unwrap( ) ) ;
41474139 assert_eq ! ( hostname, SocketAddress :: from_str( & hostname. to_string( ) ) . unwrap( ) ) ;
41484140
4149- let v2 = SocketAddress :: OnionV2 ( [ 37 , 24 , 75 , 5 , 25 , 73 , 117 , 194 , 139 , 102 , 182 , 107 ] ) ;
4150- assert_eq ! ( v2, SocketAddress :: from_str( "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234" ) . unwrap( ) ) ;
4151- assert_eq ! ( v2, SocketAddress :: from_str( & v2. to_string( ) ) . unwrap( ) ) ;
4141+ let onion_v2 = SocketAddress :: OnionV2 {
4142+ addr : [ 40 , 4 , 64 , 185 , 202 , 19 , 162 , 75 , 90 , 200 ] ,
4143+ port : 80 ,
4144+ } ;
4145+ assert_eq ! ( onion_v2, SocketAddress :: from_str( "facebookcorewwwi.onion:80" ) . unwrap( ) ) ;
4146+ assert_eq ! ( onion_v2, SocketAddress :: from_str( & onion_v2. to_string( ) ) . unwrap( ) ) ;
41524147
4153- let v3 = SocketAddress :: OnionV3 {
4148+ let onion_v3 = SocketAddress :: OnionV3 {
41544149 ed25519_pubkey : [ 37 , 24 , 75 , 5 , 25 , 73 , 117 , 194 , 139 , 102 , 182 , 107 , 4 , 105 , 247 , 246 , 85 ,
41554150 111 , 177 , 172 , 49 , 137 , 167 , 155 , 64 , 221 , 163 , 47 , 31 , 33 , 71 , 3 ] ,
41564151 checksum : 48326 ,
41574152 version : 121 ,
41584153 port : 1234
41594154 } ;
4160- assert_eq ! ( v3 , SocketAddress :: from_str( "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234" ) . unwrap( ) ) ;
4161- assert_eq ! ( v3 , SocketAddress :: from_str( & v3 . to_string( ) ) . unwrap( ) ) ;
4155+ assert_eq ! ( onion_v3 , SocketAddress :: from_str( "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234" ) . unwrap( ) ) ;
4156+ assert_eq ! ( onion_v3 , SocketAddress :: from_str( & onion_v3 . to_string( ) ) . unwrap( ) ) ;
41624157
41634158 assert_eq ! ( Err ( SocketAddressParseError :: InvalidOnionV3 ) , SocketAddress :: from_str( "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6.onion:1234" ) ) ;
41644159 assert_eq ! ( Err ( SocketAddressParseError :: InvalidInput ) , SocketAddress :: from_str( "127.0.0.1@1234" ) ) ;
0 commit comments