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:
Jeff Olson 2012-06-17 20:42:48 -07:00 committed by Brian Anderson
parent b6b138630e
commit 334c783d36

View File

@ -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);
}
}
}
}