@@ -23,6 +23,7 @@ use serde::{de::Unexpected, Deserialize, Deserializer, Serialize};
2323use serde_with:: skip_serializing_none;
2424use strsim:: jaro_winkler;
2525use typed_builder:: TypedBuilder ;
26+ use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr } ;
2627
2728#[ cfg( any(
2829 feature = "zstd-compression" ,
@@ -197,60 +198,37 @@ impl ServerAddress {
197198 } ) ;
198199 }
199200 }
200- let mut parts = address. split ( ':' ) ;
201- let hostname = match parts. next ( ) {
202- Some ( part) => {
203- if part. is_empty ( ) {
204- return Err ( ErrorKind :: InvalidArgument {
205- message : format ! (
206- "invalid server address: \" {}\" ; hostname cannot be empty" ,
207- address
208- ) ,
209- }
210- . into ( ) ) ;
211- }
212- part
201+
202+ // Check if the address is IPv6, indicated by square brackets
203+ let ( hostname, port_str) = if address. starts_with ( '[' ) && address. ends_with ( ']' ) {
204+ // Strip brackets for IPv6
205+ let addr_without_brackets = & address[ 1 ..address. len ( ) - 1 ] ;
206+ match addr_without_brackets. rsplit_once ( ':' ) {
207+ Some ( ( host, port) ) => ( host, Some ( port) ) ,
208+ None => ( addr_without_brackets, None ) ,
213209 }
214- None => {
215- return Err ( ErrorKind :: InvalidArgument {
216- message : format ! ( "invalid server address: \" {}\" " , address) ,
217- }
218- . into ( ) )
210+ } else {
211+ match address. rsplit_once ( ':' ) {
212+ Some ( ( host, port) ) => ( host, Some ( port) ) ,
213+ None => ( address, None ) ,
219214 }
220215 } ;
221216
222- let port = match parts. next ( ) {
223- Some ( part) => {
224- let port = u16:: from_str ( part) . map_err ( |_| ErrorKind :: InvalidArgument {
225- message : format ! (
226- "port must be valid 16-bit unsigned integer, instead got: {}" ,
227- part
228- ) ,
229- } ) ?;
230-
231- if port == 0 {
232- return Err ( ErrorKind :: InvalidArgument {
233- message : format ! (
234- "invalid server address: \" {}\" ; port must be non-zero" ,
235- address
236- ) ,
237- }
238- . into ( ) ) ;
239- }
240- if parts. next ( ) . is_some ( ) {
241- return Err ( ErrorKind :: InvalidArgument {
242- message : format ! (
243- "address \" {}\" contains more than one unescaped ':'" ,
244- address
245- ) ,
246- }
247- . into ( ) ) ;
217+ // Validate that the hostname is either a valid IPv4 or IPv6 address
218+ print ! ( "Parsing address: {}\n " , hostname) ;
219+ let is_ipv4 = Ipv4Addr :: from_str ( hostname) . is_ok ( ) ;
220+ let is_ipv6 = Ipv6Addr :: from_str ( hostname) . is_ok ( ) ;
221+ let localhost_v4 = IpAddr :: V4 ( Ipv4Addr :: new ( 127 , 0 , 0 , 1 ) ) ;
222+ let localhost_v6 = IpAddr :: V6 ( Ipv6Addr :: new ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ) ) ;
223+ if !is_ipv4 && !is_ipv6 && "127.0.0.1" . parse ( ) != Ok ( localhost_v4) && "::1" . parse ( ) != Ok ( localhost_v6) {
224+ return Err ( ErrorKind :: InvalidArgument {
225+ message : format ! ( "invalid hostname: \" {}\" " , hostname) ,
248226 }
227+ . into ( ) )
228+ }
249229
250- Some ( port)
251- }
252- None => None ,
253- } ;
230+ // If there's a port, try to parse it
231+ let port = port_str. and_then ( |port| port. parse :: < u16 > ( ) . ok ( ) ) ;
254232
255233 Ok ( ServerAddress :: Tcp {
256234 host : hostname. to_lowercase ( ) ,
0 commit comments