Skip to content

Commit fd4ccbe

Browse files
pdhanoyasplunkParam Dhanoya
authored andcommitted
Added support to parse ipv6 address
1 parent 57a6a70 commit fd4ccbe

File tree

1 file changed

+57
-41
lines changed

1 file changed

+57
-41
lines changed

src/client/options.rs

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use serde::{de::Unexpected, Deserialize, Deserializer, Serialize};
2323
use serde_with::skip_serializing_none;
2424
use strsim::jaro_winkler;
2525
use typed_builder::TypedBuilder;
26+
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
2627

2728
#[cfg(any(
2829
feature = "zstd-compression",
@@ -197,64 +198,78 @@ 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() {
201+
202+
// Check if the address is IPv6, indicated by square brackets
203+
let (hostname, port_str) = if address.starts_with('[') {
204+
match address.rfind(']') {
205+
Some(bracket_pos) => {
206+
let addr_without_brackets = &address[1..bracket_pos];
207+
let port = if bracket_pos + 1 < address.len() {
208+
if !address[bracket_pos + 1..].starts_with(':') {
209+
return Err(ErrorKind::InvalidArgument {
210+
message: format!("invalid IPv6 address format: expected ':' after ']' in \"{}\"", address),
211+
}.into());
212+
}
213+
Some(&address[bracket_pos + 2..])
214+
} else {
215+
None
216+
};
217+
(addr_without_brackets, port)
218+
},
219+
None => {
204220
return Err(ErrorKind::InvalidArgument {
205-
message: format!(
206-
"invalid server address: \"{}\"; hostname cannot be empty",
207-
address
208-
),
209-
}
210-
.into());
221+
message: format!("invalid IPv6 address format: missing closing bracket in \"{}\"", address),
222+
}.into());
211223
}
212-
part
213224
}
214-
None => {
215-
return Err(ErrorKind::InvalidArgument {
216-
message: format!("invalid server address: \"{}\"", address),
225+
} else {
226+
match address.rsplit_once(':') {
227+
Some((host, port)) => (host, Some(port)),
228+
None => {
229+
return Err(ErrorKind::InvalidArgument {
230+
message: format!("invalid server address: \"{}\"; port is required", address),
231+
}.into())
217232
}
218-
.into())
219233
}
220234
};
221235

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-
})?;
236+
// Validate that the hostname is either a valid IPv4 or IPv6 address
237+
let is_ipv4 = Ipv4Addr::from_str(hostname).is_ok();
238+
let is_ipv6 = Ipv6Addr::from_str(hostname).is_ok();
239+
let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
240+
let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
241+
if !is_ipv4 && !is_ipv6 && "127.0.0.1".parse() != Ok(localhost_v4) && "::1".parse() != Ok(localhost_v6) {
242+
return Err(ErrorKind::InvalidArgument {
243+
message: format!("invalid hostname: \"{}\"", hostname),
244+
}
245+
.into())
246+
}
230247

231-
if port == 0 {
248+
// Validate port
249+
let port = match port_str {
250+
None => {
251+
return Err(ErrorKind::InvalidArgument {
252+
message: format!("invalid server address: \"{}\"; port is required", address),
253+
}.into())
254+
}
255+
Some(port_str) => match port_str.parse::<u16>() {
256+
Ok(0) => {
232257
return Err(ErrorKind::InvalidArgument {
233-
message: format!(
234-
"invalid server address: \"{}\"; port must be non-zero",
235-
address
236-
),
237-
}
238-
.into());
258+
message: format!("invalid server address: \"{}\"; port cannot be 0", address),
259+
}.into())
239260
}
240-
if parts.next().is_some() {
261+
Ok(port) => port,
262+
Err(_) => {
241263
return Err(ErrorKind::InvalidArgument {
242-
message: format!(
243-
"address \"{}\" contains more than one unescaped ':'",
244-
address
245-
),
246-
}
247-
.into());
264+
message: format!("invalid server address: \"{}\"; invalid port number", address),
265+
}.into())
248266
}
249-
250-
Some(port)
251267
}
252-
None => None,
253268
};
254269

255270
Ok(ServerAddress::Tcp {
256271
host: hostname.to_lowercase(),
257-
port,
272+
port: Some(port),
258273
})
259274
}
260275

@@ -266,6 +281,7 @@ impl ServerAddress {
266281
Self::Unix { path } => path.to_string_lossy(),
267282
}
268283
}
284+
}
269285
}
270286

271287
impl fmt::Display for ServerAddress {

0 commit comments

Comments
 (0)