@@ -1273,27 +1273,27 @@ impl std::net::ToSocketAddrs for SocketAddress {
12731273pub fn parse_onion_address (
12741274 host : & str , port : u16 ,
12751275) -> Result < SocketAddress , SocketAddressParseError > {
1276- if host. ends_with ( ".onion" ) {
1277- let domain = & host[ ..host. len ( ) - ".onion" . len ( ) ] ;
1278- if domain. len ( ) != 56 {
1279- return Err ( SocketAddressParseError :: InvalidOnionV3 ) ;
1280- }
1281- let onion = base32:: Alphabet :: RFC4648 { padding : false }
1282- . decode ( & domain)
1283- . map_err ( |_| SocketAddressParseError :: InvalidOnionV3 ) ?;
1284- if onion. len ( ) != 35 {
1285- return Err ( SocketAddressParseError :: InvalidOnionV3 ) ;
1286- }
1287- let version = onion[ 0 ] ;
1288- let first_checksum_flag = onion[ 1 ] ;
1289- let second_checksum_flag = onion[ 2 ] ;
1290- let mut ed25519_pubkey = [ 0 ; 32 ] ;
1291- ed25519_pubkey. copy_from_slice ( & onion[ 3 ..35 ] ) ;
1292- let checksum = u16:: from_be_bytes ( [ first_checksum_flag, second_checksum_flag] ) ;
1293- return Ok ( SocketAddress :: OnionV3 { ed25519_pubkey, checksum, version, port } ) ;
1294- } else {
1276+ if !host. ends_with ( ".onion" ) {
12951277 return Err ( SocketAddressParseError :: InvalidInput ) ;
12961278 }
1279+ let domain = & host[ ..host. len ( ) - ".onion" . len ( ) ] ;
1280+ if domain. len ( ) != 56 {
1281+ return Err ( SocketAddressParseError :: InvalidOnionV3 ) ;
1282+ }
1283+ let onion = base32:: Alphabet :: RFC4648 { padding : false }
1284+ . decode ( domain)
1285+ . map_err ( |_| SocketAddressParseError :: InvalidOnionV3 ) ?;
1286+ if onion. len ( ) != 35 {
1287+ return Err ( SocketAddressParseError :: InvalidOnionV3 ) ;
1288+ }
1289+
1290+ let mut ed25519_pubkey = [ 0u8 ; 32 ] ;
1291+ ed25519_pubkey. copy_from_slice ( & onion[ 0 ..32 ] ) ;
1292+
1293+ let checksum = u16:: from_be_bytes ( [ onion[ 32 ] , onion[ 33 ] ] ) ;
1294+ let version = onion[ 34 ] ;
1295+
1296+ Ok ( SocketAddress :: OnionV3 { ed25519_pubkey, checksum, version, port } )
12971297}
12981298
12991299impl Display for SocketAddress {
@@ -1313,10 +1313,13 @@ impl Display for SocketAddress {
13131313 version,
13141314 port,
13151315 } => {
1316- let [ first_checksum_flag, second_checksum_flag] = checksum. to_be_bytes ( ) ;
1317- let mut addr = vec ! [ * version, first_checksum_flag, second_checksum_flag] ;
1316+ let mut addr = Vec :: with_capacity ( 35 ) ;
13181317 addr. extend_from_slice ( ed25519_pubkey) ;
1319- let onion = base32:: Alphabet :: RFC4648 { padding : false } . encode ( & addr) ;
1318+ let [ c0, c1] = checksum. to_be_bytes ( ) ;
1319+ addr. push ( c0) ;
1320+ addr. push ( c1) ;
1321+ addr. push ( * version) ;
1322+ let onion = base32:: Alphabet :: RFC4648 { padding : false } . encode ( & addr) . to_lowercase ( ) ;
13201323 write ! ( f, "{}.onion:{}" , onion, port) ?
13211324 } ,
13221325 SocketAddress :: Hostname { hostname, port } => write ! ( f, "{}:{}" , hostname, port) ?,
@@ -6666,21 +6669,21 @@ mod tests {
66666669
66676670 let onion_v3 = SocketAddress :: OnionV3 {
66686671 ed25519_pubkey : [
6669- 37 , 24 , 75 , 5 , 25 , 73 , 117 , 194 , 139 , 102 , 182 , 107 , 4 , 105 , 247 , 246 , 85 , 111 ,
6670- 177 , 172 , 49 , 137 , 167 , 155 , 64 , 221 , 163 , 47 , 31 , 33 , 71 , 3 ,
6672+ 121 , 188 , 198 , 37 , 24 , 75 , 5 , 25 , 73 , 117 , 194 , 139 , 102 , 182 , 107 , 4 , 105 , 247 ,
6673+ 246 , 85 , 111 , 177 , 172 , 49 , 137 , 167 , 155 , 64 , 221 , 163 , 47 , 31 ,
66716674 ] ,
6672- checksum : 48326 ,
6673- version : 121 ,
6675+ checksum : 8519 ,
6676+ version : 3 ,
66746677 port : 1234 ,
66756678 } ;
6676- assert_eq ! (
6677- onion_v3 ,
6678- SocketAddress :: from_str (
6679- "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234"
6680- )
6681- . unwrap ( )
6682- ) ;
6683- assert_eq ! ( onion_v3 , SocketAddress :: from_str ( & onion_v3 . to_string ( ) ) . unwrap ( ) ) ;
6679+ let onion_v3_str = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:1234" ;
6680+ let parsed = SocketAddress :: from_str ( onion_v3_str ) . unwrap ( ) ;
6681+ assert_eq ! ( onion_v3 , parsed ) ;
6682+ assert_eq ! ( onion_v3_str , parsed . to_string ( ) ) ;
6683+ match parsed {
6684+ SocketAddress :: OnionV3 { version , .. } => assert_eq ! ( version , 3 ) ,
6685+ _ => panic ! ( "expected OnionV3" ) ,
6686+ }
66846687
66856688 assert_eq ! (
66866689 Err ( SocketAddressParseError :: InvalidOnionV3 ) ,
0 commit comments