std: adding net::ip::v6 utils and rudimentary tests, huzzah! (see caveats)
libuv's own ip vetting code appears to in a somewhat woeful state, for both ipv4 and ipv6 (there are some notes in the tests for net_ip, as well as stuff added in uv_ll). They are aware of this and welcome patches. I have rudimentary code in place that can verify whether the provided str ip was, in fact, validly parsed by libuv, making a few assumptions: * for ipv4, we assume that the platform's INADDR_NONE val is 0xffffffff , I should write a helper to return this value from the platform's libc headers instead of hard-coding it in rust. * for ipv6, we assume that the library will always return '::' for malformed inputs.. as is the case in 64bit ubuntu. I need to verify this on other platforms.. but at least the debugging output is in place, so if expectations don't line up, it'll be straightforward to address
This commit is contained in:
parent
b6b138630e
commit
334c783d36
@ -9,6 +9,8 @@ import sockaddr_in = uv::ll::sockaddr_in;
|
||||
import sockaddr_in6 = uv::ll::sockaddr_in6;
|
||||
import uv_ip4_addr = uv::ll::ip4_addr;
|
||||
import uv_ip4_name = uv::ll::ip4_name;
|
||||
import uv_ip6_addr = uv::ll::ip6_addr;
|
||||
import uv_ip6_name = uv::ll::ip6_name;
|
||||
|
||||
export ip_addr, parse_addr_err;
|
||||
export format_addr;
|
||||
@ -18,7 +20,7 @@ export v4;
|
||||
enum ip_addr {
|
||||
#[doc="An IPv4 address"]
|
||||
ipv4(sockaddr_in),
|
||||
ipv6(u16,u16,u16,u16,u16,u16,u16,u16)
|
||||
ipv6(sockaddr_in6)
|
||||
}
|
||||
|
||||
#[doc="
|
||||
@ -46,8 +48,14 @@ fn format_addr(ip: ip_addr) -> str {
|
||||
result
|
||||
}
|
||||
}
|
||||
ipv6(_, _, _, _, _, _, _, _) {
|
||||
fail "FIXME (#2651) impl parsing of ipv6 addr";
|
||||
ipv6(addr) {
|
||||
unsafe {
|
||||
let result = uv_ip6_name(&addr);
|
||||
if result == "" {
|
||||
fail "failed to convert inner sockaddr_in address to str"
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,7 +66,7 @@ mod v4 {
|
||||
|
||||
# Failure
|
||||
|
||||
j Fails if the string is not a valid IPv4 address
|
||||
Fails if the string is not a valid IPv4 address
|
||||
|
||||
# Arguments
|
||||
|
||||
@ -82,16 +90,107 @@ j Fails if the string is not a valid IPv4 address
|
||||
fn try_parse_addr(ip: str) -> result::result<ip_addr,parse_addr_err> {
|
||||
unsafe {
|
||||
// need to figure out how to establish a parse failure..
|
||||
result::ok(ipv4(uv_ip4_addr(ip, 22)))
|
||||
let new_addr = uv_ip4_addr(ip, 22);
|
||||
let reformatted_name = uv_ip4_name(&new_addr);
|
||||
log(debug, #fmt("try_parse_addr: input ip: %s reparsed ip: %s",
|
||||
ip, reformatted_name));
|
||||
// here we're going to
|
||||
let inaddr_none_val = "255.255.255.255";
|
||||
if ip != inaddr_none_val && reformatted_name == inaddr_none_val {
|
||||
result::err({err_msg:#fmt("failed to parse '%s'",
|
||||
ip)})
|
||||
}
|
||||
else {
|
||||
result::ok(ipv4(new_addr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mod v6 {
|
||||
#[doc = "
|
||||
Convert a str to `ip_addr`
|
||||
|
||||
# Failure
|
||||
|
||||
Fails if the string is not a valid IPv6 address
|
||||
|
||||
# Arguments
|
||||
|
||||
* ip - an ipv6 string. See RFC2460 for spec.
|
||||
|
||||
# Returns
|
||||
|
||||
* an `ip_addr` of the `ipv6` variant
|
||||
"]
|
||||
fn parse_addr(ip: str) -> ip_addr {
|
||||
alt try_parse_addr(ip) {
|
||||
// FIXME: more copies brought to light to due the implicit
|
||||
// copy compiler warning.. what can be done? out pointers,
|
||||
// ala c#?
|
||||
result::ok(addr) { copy(addr) }
|
||||
result::err(err_data) {
|
||||
fail err_data.err_msg
|
||||
}
|
||||
}
|
||||
}
|
||||
fn try_parse_addr(ip: str) -> result::result<ip_addr,parse_addr_err> {
|
||||
unsafe {
|
||||
// need to figure out how to establish a parse failure..
|
||||
let new_addr = uv_ip6_addr(ip, 22);
|
||||
let reparsed_name = uv_ip6_name(&new_addr);
|
||||
log(debug, #fmt("v6::try_parse_addr ip: '%s' reparsed '%s'",
|
||||
ip, reparsed_name));
|
||||
// '::' appears to be uv_ip6_name() returns for bogus
|
||||
// parses..
|
||||
if ip != "::" && reparsed_name == "::" {
|
||||
result::err({err_msg:#fmt("failed to parse '%s'",
|
||||
ip)})
|
||||
}
|
||||
else {
|
||||
result::ok(ipv6(new_addr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
//#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
fn test_ipv4_parse_and_format_ip() {
|
||||
assert (format_addr(v4::parse_addr("127.0.0.1"))
|
||||
== "127.0.0.1")
|
||||
let localhost_str = "127.0.0.1";
|
||||
assert (format_addr(v4::parse_addr(localhost_str))
|
||||
== localhost_str)
|
||||
}
|
||||
#[test]
|
||||
fn test_ipv6_parse_and_format_ip() {
|
||||
let localhost_str = "::1";
|
||||
let format_result = format_addr(v6::parse_addr(localhost_str));
|
||||
log(debug, #fmt("results: expected: '%s' actual: '%s'",
|
||||
localhost_str, format_result));
|
||||
assert format_result == localhost_str;
|
||||
}
|
||||
#[test]
|
||||
fn test_ipv4_bad_parse() {
|
||||
alt v4::try_parse_addr("b4df00d") {
|
||||
result::err(err_info) {
|
||||
log(debug, #fmt("got error as expected %?", err_info));
|
||||
assert true;
|
||||
}
|
||||
result::ok(addr) {
|
||||
fail #fmt("Expected failure, but got addr %?", addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_ipv6_bad_parse() {
|
||||
alt v6::try_parse_addr("::,~2234k;") {
|
||||
result::err(err_info) {
|
||||
log(debug, #fmt("got error as expected %?", err_info));
|
||||
assert true;
|
||||
}
|
||||
result::ok(addr) {
|
||||
fail #fmt("Expected failure, but got addr %?", addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user