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