@@ -904,9 +904,23 @@ impl Readable for NetAddress {
904
904
}
905
905
}
906
906
907
+ /// NetAddress error variants
908
+ #[ cfg( feature = "std" ) ]
909
+ #[ derive( Debug ) ]
910
+ pub enum NetAddressError {
911
+ /// Socket address(IPv4/IPv6) parsing error
912
+ SocketAdrrParseError ( std:: net:: AddrParseError ) ,
913
+ /// Invalid input format
914
+ InvalidInput ( String ) ,
915
+ /// Invalid port
916
+ InvalidPort ,
917
+ /// Invalid onion v3 address
918
+ InvalidOnionV3 ,
919
+ }
920
+
907
921
#[ cfg( feature = "std" ) ]
908
922
impl FromStr for NetAddress {
909
- type Err = std :: net :: AddrParseError ;
923
+ type Err = NetAddressError ;
910
924
911
925
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
912
926
match std:: net:: SocketAddr :: from_str ( s) {
@@ -924,41 +938,42 @@ impl FromStr for NetAddress {
924
938
}
925
939
} ,
926
940
Err ( e) => {
927
- let trimmed_input = match s. rfind ( ":" ) {
928
- Some ( pos) => pos,
929
- None => return Err ( e) ,
930
- } ;
931
- let host = & s[ ..trimmed_input] ;
932
- let port: u16 = match s[ trimmed_input + 1 ..] . parse ( ) {
933
- Ok ( port) => port,
934
- Err ( _) => return Err ( e) ,
935
- } ;
936
- if host. ends_with ( ".onion" ) {
937
- let onion = match host. split ( ".onion" ) . nth ( 0 ) {
938
- Some ( onion) => onion,
939
- None => return Err ( e) ,
940
- } ;
941
- let decoded_onion = base32:: Alphabet :: RFC4648 { padding : false } . decode ( & onion) ;
942
- let onion = match decoded_onion {
943
- Ok ( onion) => onion,
944
- Err ( _) => return Err ( e)
945
- } ;
946
- let version = match onion. get ( 0 ) {
947
- Some ( version) => version,
948
- None => return Err ( e) ,
949
- } ;
950
- let checksum = u16:: from_be_bytes ( [ onion[ 1 ] , onion[ 2 ] ] ) ;
951
- let ed25519_pubkey = match onion[ 3 ..35 ] . try_into ( ) {
952
- Ok ( ed25519_pubkey) => ed25519_pubkey,
953
- Err ( _) => return Err ( e) ,
954
- } ;
955
- return Ok ( NetAddress :: OnionV3 { ed25519_pubkey, checksum, version : * version, port } ) ;
941
+ let trimmed_input = match s. rfind ( ":" ) {
942
+ Some ( pos) => pos,
943
+ None => return Err ( NetAddressError :: InvalidInput ( "Invalid input. Expected format: \" <host>:<port>\" " . to_string ( ) ) ) ,
944
+ } ;
945
+ let host = & s[ ..trimmed_input] ;
946
+ let port: u16 = match s[ trimmed_input + 1 ..] . parse ( ) {
947
+ Ok ( port) => port,
948
+ Err ( _) => return Err ( NetAddressError :: InvalidPort ) ,
949
+ } ;
950
+ if host. ends_with ( ".onion" ) {
951
+ let onion = match host. split ( ".onion" ) . nth ( 0 ) {
952
+ Some ( onion) => onion,
953
+ None => return Err ( NetAddressError :: InvalidOnionV3 ) ,
954
+ } ;
955
+ let onion = match ( base32:: Alphabet :: RFC4648 { padding : false } . decode ( & onion) ) {
956
+ Ok ( onion) => onion,
957
+ Err ( _) => return Err ( NetAddressError :: InvalidOnionV3 ) ,
958
+ } ;
959
+ match ( onion. get ( 0 ) , onion. get ( 1 ) , onion. get ( 2 ) ) {
960
+ ( Some ( version) , Some ( first_checksum_flag) , Some ( second_checksum_flag) ) => {
961
+ let checksum = u16:: from_be_bytes ( [ * first_checksum_flag, * second_checksum_flag] ) ;
962
+ let ed25519_pubkey = match onion[ 3 ..35 ] . try_into ( ) {
963
+ Ok ( ed25519_pubkey) => ed25519_pubkey,
964
+ Err ( _) => return Err ( NetAddressError :: InvalidOnionV3 ) ,
965
+ } ;
966
+ return Ok ( NetAddress :: OnionV3 { ed25519_pubkey, checksum, version : * version, port } ) ;
967
+
968
+ } ,
969
+ _ => return Err ( NetAddressError :: InvalidOnionV3 ) ,
970
+ }
956
971
}
957
972
958
973
if let Ok ( hostname) = Hostname :: try_from ( host. to_string ( ) ) {
959
974
return Ok ( NetAddress :: Hostname { hostname, port } ) ;
960
975
}
961
- return Err ( e )
976
+ return Err ( NetAddressError :: SocketAdrrParseError ( e ) )
962
977
} ,
963
978
}
964
979
}
0 commit comments