Skip to content

Commit 150f5ad

Browse files
committed
fix: ipv6 strip brackets for parsing, account for optional colon, add tests
1 parent 187365d commit 150f5ad

File tree

2 files changed

+194
-7
lines changed

2 files changed

+194
-7
lines changed

src/server.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -888,16 +888,29 @@ pub fn parse_address_components(
888888

889889
// If so, parse it as an ipv6 address
890890
if no_port {
891-
return match Ipv6Addr::from_str(input) {
891+
// Remove the brackets (and colon from the end of the address) if it's there
892+
let ipv6_str = if input.ends_with("]:") {
893+
&input[1..input.len() - 2]
894+
} else {
895+
&input[1..input.len() - 1]
896+
};
897+
898+
return match Ipv6Addr::from_str(ipv6_str) {
892899
Ok(addr) => Ok(OneOf::new(IpAddr::V6(addr))),
893-
Err(e) => Err(OneOf::new(e)),
900+
Err(e) => Err(OneOf::new(anyhow::Error::msg(format!(
901+
"Failed to parse IPv6 address '{}': {}",
902+
input, e
903+
)))),
894904
};
895905
}
896906

897907
// Otherwise, we'll assume it's an ipv6 address with a port
898908
return match SocketAddrV6::from_str(input) {
899909
Ok(addr) => Ok(OneOf::new(SocketAddr::V6(addr))),
900-
Err(e) => Err(OneOf::new(e)),
910+
Err(e) => Err(OneOf::new(anyhow::Error::msg(format!(
911+
"Failed to parse IPv6 socket address '{}': {}",
912+
input, e
913+
)))),
901914
};
902915
}
903916

@@ -924,16 +937,36 @@ pub fn parse_address_components(
924937
// Now just parse the components individually or together, and return the appropriate type
925938
match (host, port) {
926939
(Some(host), Some(port)) => {
927-
let host = host.parse::<Ipv4Addr>().map_err(OneOf::new)?;
928-
let port = port.parse::<u16>().map_err(OneOf::new)?;
940+
let host = host.parse::<Ipv4Addr>().map_err(|e| {
941+
OneOf::new(anyhow::Error::msg(format!(
942+
"Failed to parse IPv4 host '{}' in address '{}': {}",
943+
host, input, e
944+
)))
945+
})?;
946+
let port = port.parse::<u16>().map_err(|e| {
947+
OneOf::new(anyhow::Error::msg(format!(
948+
"Failed to parse port '{}' in address '{}': {}",
949+
port, input, e
950+
)))
951+
})?;
929952
Ok(OneOf::new(SocketAddr::from((host, port))))
930953
}
931954
(Some(host), None) => {
932-
let host = host.parse::<Ipv4Addr>().map_err(OneOf::new)?;
955+
let host = host.parse::<Ipv4Addr>().map_err(|e| {
956+
OneOf::new(anyhow::Error::msg(format!(
957+
"Failed to parse IPv4 address '{}': {}",
958+
input, e
959+
)))
960+
})?;
933961
Ok(OneOf::new(IpAddr::V4(host)))
934962
}
935963
(None, Some(port)) => {
936-
let port = port.parse::<u16>().map_err(OneOf::new)?;
964+
let port = port.parse::<u16>().map_err(|e| {
965+
OneOf::new(anyhow::Error::msg(format!(
966+
"Failed to parse port '{}' in address '{}': {}",
967+
port, input, e
968+
)))
969+
})?;
937970
Ok(OneOf::new(port))
938971
}
939972
(None, None) => Err(OneOf::new(anyhow::Error::msg(format!(

tests/server_tests.rs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,157 @@ fn test_scale_parameter_length_validation() {
174174
};
175175
assert_eq!(parse_scale_parameter(&query), None);
176176
}
177+
178+
#[test]
179+
fn test_parse_address_components_ipv6() {
180+
use glim::server::parse_address_components;
181+
use std::net::{IpAddr, SocketAddr};
182+
183+
// Test IPv6 addresses without ports
184+
let result = parse_address_components("[::]");
185+
assert!(
186+
result.as_ref().is_ok()
187+
&& matches!(
188+
result.as_ref().unwrap().as_enum(),
189+
terrors::E3::B(IpAddr::V6(_))
190+
),
191+
"Expected Ok(IpAddr::V6(_)), got {:?}",
192+
result
193+
);
194+
195+
let result = parse_address_components("[::1]");
196+
assert!(
197+
result.as_ref().is_ok()
198+
&& matches!(
199+
result.as_ref().unwrap().as_enum(),
200+
terrors::E3::B(IpAddr::V6(_))
201+
),
202+
"Expected Ok(IpAddr::V6(_)), got {:?}",
203+
result
204+
);
205+
206+
// Test IPv6 addresses with ports
207+
let result = parse_address_components("[::]:8080");
208+
assert!(
209+
result.as_ref().is_ok()
210+
&& matches!(
211+
result.as_ref().unwrap().as_enum(),
212+
terrors::E3::A(SocketAddr::V6(_))
213+
),
214+
"Expected Ok(SocketAddr::V6(_)), got {:?}",
215+
result
216+
);
217+
218+
let result = parse_address_components("[::1]:3000");
219+
assert!(
220+
result.as_ref().is_ok()
221+
&& matches!(
222+
result.as_ref().unwrap().as_enum(),
223+
terrors::E3::A(SocketAddr::V6(_))
224+
),
225+
"Expected Ok(SocketAddr::V6(_)), got {:?}",
226+
result
227+
);
228+
229+
// Test IPv6 addresses with empty port (should be treated as no port)
230+
let result = parse_address_components("[::]:");
231+
assert!(
232+
result.as_ref().is_ok()
233+
&& matches!(
234+
result.as_ref().unwrap().as_enum(),
235+
terrors::E3::B(IpAddr::V6(_))
236+
),
237+
"Expected Ok(IpAddr::V6(_)), got {:?}",
238+
result
239+
);
240+
}
241+
242+
#[test]
243+
fn test_parse_address_components_ipv4() {
244+
use glim::server::parse_address_components;
245+
use std::net::{IpAddr, SocketAddr};
246+
247+
// Test IPv4 addresses without ports
248+
let result = parse_address_components("127.0.0.1");
249+
assert!(
250+
result.as_ref().is_ok()
251+
&& matches!(
252+
result.as_ref().unwrap().as_enum(),
253+
terrors::E3::B(IpAddr::V4(_))
254+
),
255+
"Expected Ok(IpAddr::V4(_)), got {:?}",
256+
result
257+
);
258+
259+
// Test IPv4 addresses with ports
260+
let result = parse_address_components("127.0.0.1:8080");
261+
assert!(
262+
result.as_ref().is_ok()
263+
&& matches!(
264+
result.as_ref().unwrap().as_enum(),
265+
terrors::E3::A(SocketAddr::V4(_))
266+
),
267+
"Expected Ok(SocketAddr::V4(_)), got {:?}",
268+
result
269+
);
270+
271+
// Test just port
272+
let result = parse_address_components("8080");
273+
assert!(
274+
result.as_ref().is_ok()
275+
&& matches!(result.as_ref().unwrap().as_enum(), terrors::E3::C(8080)),
276+
"Expected Ok(8080), got {:?}",
277+
result
278+
);
279+
280+
let result = parse_address_components(":8080");
281+
assert!(
282+
result.as_ref().is_ok()
283+
&& matches!(result.as_ref().unwrap().as_enum(), terrors::E3::C(8080)),
284+
"Expected Ok(8080), got {:?}",
285+
result
286+
);
287+
}
288+
289+
#[test]
290+
fn test_parse_address_components_invalid() {
291+
use glim::server::parse_address_components;
292+
293+
// Test invalid IPv6 addresses
294+
let result = parse_address_components("[invalid]");
295+
assert!(result.is_err());
296+
297+
let result = parse_address_components("[::]:invalid");
298+
assert!(result.is_err());
299+
300+
// Test invalid IPv4 addresses
301+
let result = parse_address_components("256.256.256.256");
302+
assert!(result.is_err());
303+
304+
let result = parse_address_components("127.0.0.1:99999");
305+
assert!(result.is_err());
306+
307+
// Test invalid port
308+
let result = parse_address_components("99999");
309+
assert!(result.is_err());
310+
311+
// Test empty input
312+
let result = parse_address_components("");
313+
assert!(result.is_err());
314+
}
315+
316+
#[test]
317+
fn test_debug_ipv6_parsing() {
318+
use glim::server::parse_address_components;
319+
use std::net::Ipv6Addr;
320+
use std::str::FromStr;
321+
322+
println!("Testing [::] parsing...");
323+
let result = parse_address_components("[::]");
324+
println!("Result: {:?}", result);
325+
326+
// Also test the raw Ipv6Addr parsing
327+
println!("Testing raw :: parsing...");
328+
let ipv6_result = Ipv6Addr::from_str("::");
329+
println!("Ipv6Addr result: {:?}", ipv6_result);
330+
}

0 commit comments

Comments
 (0)