2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Types/fns concerning Internet Protocol (IP), versions 4 & 6
|
2012-04-29 23:53:17 -05:00
|
|
|
|
2013-05-28 22:11:41 -05:00
|
|
|
#[allow(missing_doc)];
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::libc;
|
2013-02-02 05:10:12 -06:00
|
|
|
use core::comm::{stream, SharedChan};
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::ptr;
|
|
|
|
use core::result;
|
|
|
|
use core::str;
|
|
|
|
|
2012-09-04 13:23:53 -05:00
|
|
|
use iotask = uv::iotask::IoTask;
|
|
|
|
use interact = uv::iotask::interact;
|
2012-04-29 23:53:17 -05:00
|
|
|
|
2013-03-12 16:06:19 -05:00
|
|
|
use sockaddr_in = super::uv_ll::sockaddr_in;
|
|
|
|
use sockaddr_in6 = super::uv_ll::sockaddr_in6;
|
|
|
|
use addrinfo = super::uv_ll::addrinfo;
|
|
|
|
use uv_getaddrinfo_t = super::uv_ll::uv_getaddrinfo_t;
|
|
|
|
use uv_ip4_name = super::uv_ll::ip4_name;
|
|
|
|
use uv_ip4_port = super::uv_ll::ip4_port;
|
|
|
|
use uv_ip6_name = super::uv_ll::ip6_name;
|
|
|
|
use uv_ip6_port = super::uv_ll::ip6_port;
|
|
|
|
use uv_getaddrinfo = super::uv_ll::getaddrinfo;
|
|
|
|
use uv_freeaddrinfo = super::uv_ll::freeaddrinfo;
|
|
|
|
use create_uv_getaddrinfo_t = super::uv_ll::getaddrinfo_t;
|
|
|
|
use set_data_for_req = super::uv_ll::set_data_for_req;
|
|
|
|
use get_data_for_req = super::uv_ll::get_data_for_req;
|
|
|
|
use ll = super::uv_ll;
|
2012-04-29 23:53:17 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// An IP address
|
2012-10-03 18:43:56 -05:00
|
|
|
pub enum IpAddr {
|
2012-07-04 16:53:12 -05:00
|
|
|
/// An IPv4 address
|
2012-08-30 13:01:39 -05:00
|
|
|
Ipv4(sockaddr_in),
|
|
|
|
Ipv6(sockaddr_in6)
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Human-friendly feedback on why a parse_addr attempt failed
|
2013-01-22 10:44:24 -06:00
|
|
|
pub struct ParseAddrErr {
|
|
|
|
err_msg: ~str,
|
|
|
|
}
|
2012-05-19 16:06:48 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
2012-10-19 18:28:58 -05:00
|
|
|
* Convert a `IpAddr` to a str
|
2012-07-04 16:53:12 -05:00
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
2012-10-19 18:28:58 -05:00
|
|
|
* * ip - a `std::net::ip::IpAddr`
|
2012-07-04 16:53:12 -05:00
|
|
|
*/
|
2012-10-03 18:43:56 -05:00
|
|
|
pub fn format_addr(ip: &IpAddr) -> ~str {
|
2012-09-03 00:18:08 -05:00
|
|
|
match *ip {
|
2012-09-28 02:22:18 -05:00
|
|
|
Ipv4(ref addr) => unsafe {
|
|
|
|
let result = uv_ip4_name(addr);
|
2012-08-03 21:59:04 -05:00
|
|
|
if result == ~"" {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("failed to convert inner sockaddr_in address to str")
|
2012-06-17 22:36:36 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
result
|
2012-08-06 19:14:32 -05:00
|
|
|
},
|
2012-09-28 02:22:18 -05:00
|
|
|
Ipv6(ref addr) => unsafe {
|
|
|
|
let result = uv_ip6_name(addr);
|
2012-08-03 21:59:04 -05:00
|
|
|
if result == ~"" {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("failed to convert inner sockaddr_in address to str")
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
result
|
2012-05-05 11:21:19 -05:00
|
|
|
}
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-19 18:28:58 -05:00
|
|
|
/**
|
|
|
|
* Get the associated port
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
* * ip - a `std::net::ip::IpAddr`
|
|
|
|
*/
|
|
|
|
pub fn get_port(ip: &IpAddr) -> uint {
|
|
|
|
match *ip {
|
|
|
|
Ipv4(ref addr) => unsafe {
|
|
|
|
uv_ip4_port(addr)
|
|
|
|
},
|
|
|
|
Ipv6(ref addr) => unsafe {
|
|
|
|
uv_ip6_port(addr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Represents errors returned from `net::ip::get_addr()`
|
2012-08-30 13:01:39 -05:00
|
|
|
enum IpGetAddrErr {
|
|
|
|
GetAddrUnknownError
|
2012-06-22 17:31:56 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Attempts name resolution on the provided `node` string
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
|
|
|
* * `node` - a string representing some host address
|
|
|
|
* * `iotask` - a `uv::iotask` used to interact with the underlying event loop
|
|
|
|
*
|
|
|
|
* # Returns
|
|
|
|
*
|
2012-07-11 18:49:02 -05:00
|
|
|
* A `result<~[ip_addr], ip_get_addr_err>` instance that will contain
|
2012-07-04 16:53:12 -05:00
|
|
|
* a vector of `ip_addr` results, in the case of success, or an error
|
|
|
|
* object in the case of failure
|
2013-01-25 02:52:50 -06:00
|
|
|
*/
|
2013-01-20 01:38:17 -06:00
|
|
|
pub fn get_addr(node: &str, iotask: &iotask)
|
2013-04-22 16:27:30 -05:00
|
|
|
-> result::Result<~[IpAddr], IpGetAddrErr> {
|
2013-01-25 02:52:50 -06:00
|
|
|
let (output_po, output_ch) = stream();
|
2013-04-17 01:45:29 -05:00
|
|
|
let mut output_ch = Some(SharedChan::new(output_ch));
|
2013-01-25 02:52:50 -06:00
|
|
|
do str::as_buf(node) |node_ptr, len| {
|
2013-01-10 12:59:58 -06:00
|
|
|
let output_ch = output_ch.swap_unwrap();
|
2013-04-09 00:31:42 -05:00
|
|
|
debug!("slice len %?", len);
|
|
|
|
let handle = create_uv_getaddrinfo_t();
|
2013-04-22 16:27:30 -05:00
|
|
|
let handle_ptr: *uv_getaddrinfo_t = &handle;
|
2013-04-09 00:31:42 -05:00
|
|
|
let handle_data = GetAddrData {
|
|
|
|
output_ch: output_ch.clone()
|
|
|
|
};
|
2013-04-22 16:27:30 -05:00
|
|
|
let handle_data_ptr: *GetAddrData = &handle_data;
|
2013-04-09 00:31:42 -05:00
|
|
|
do interact(iotask) |loop_ptr| {
|
|
|
|
unsafe {
|
|
|
|
let result = uv_getaddrinfo(
|
|
|
|
loop_ptr,
|
|
|
|
handle_ptr,
|
|
|
|
get_addr_cb,
|
|
|
|
node_ptr,
|
|
|
|
ptr::null(),
|
|
|
|
ptr::null());
|
|
|
|
match result {
|
|
|
|
0i32 => {
|
|
|
|
set_data_for_req(handle_ptr, handle_data_ptr);
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
output_ch.send(result::Err(GetAddrUnknownError));
|
2013-01-23 13:43:58 -06:00
|
|
|
}
|
2013-01-25 02:52:50 -06:00
|
|
|
}
|
2013-04-09 00:31:42 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
output_po.recv()
|
2012-06-22 17:31:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-03 18:43:56 -05:00
|
|
|
pub mod v4 {
|
2013-05-17 17:28:44 -05:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2013-03-26 15:38:07 -05:00
|
|
|
use net::ip::{IpAddr, Ipv4, ParseAddrErr};
|
2012-12-23 16:41:37 -06:00
|
|
|
use uv::ll;
|
2013-01-08 21:37:25 -06:00
|
|
|
use uv_ip4_addr = uv::ll::ip4_addr;
|
|
|
|
use uv_ip4_name = uv::ll::ip4_name;
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2013-04-28 12:53:42 -05:00
|
|
|
use core::cast::transmute;
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::result;
|
|
|
|
use core::uint;
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Convert a str to `ip_addr`
|
|
|
|
*
|
|
|
|
* # Failure
|
|
|
|
*
|
|
|
|
* Fails if the string is not a valid IPv4 address
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
|
|
|
* * ip - a string of the format `x.x.x.x`
|
|
|
|
*
|
|
|
|
* # Returns
|
|
|
|
*
|
|
|
|
* * an `ip_addr` of the `ipv4` variant
|
|
|
|
*/
|
2012-10-03 18:43:56 -05:00
|
|
|
pub fn parse_addr(ip: &str) -> IpAddr {
|
2012-08-06 14:34:08 -05:00
|
|
|
match try_parse_addr(ip) {
|
2013-02-15 01:30:30 -06:00
|
|
|
result::Ok(addr) => addr,
|
2013-05-08 21:44:43 -05:00
|
|
|
result::Err(ref err_data) => fail!(copy err_data.err_msg)
|
2012-05-19 16:06:48 -05:00
|
|
|
}
|
|
|
|
}
|
2012-06-26 11:07:24 -05:00
|
|
|
// the simple, old style numberic representation of
|
|
|
|
// ipv4
|
2013-01-22 10:44:24 -06:00
|
|
|
pub struct Ipv4Rep { a: u8, b: u8, c: u8, d: u8 }
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2012-10-03 18:43:56 -05:00
|
|
|
pub trait AsUnsafeU32 {
|
2013-03-07 20:11:09 -06:00
|
|
|
unsafe fn as_u32(&self) -> u32;
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl AsUnsafeU32 for Ipv4Rep {
|
2012-06-26 11:07:24 -05:00
|
|
|
// this is pretty dastardly, i know
|
2013-03-07 20:11:09 -06:00
|
|
|
unsafe fn as_u32(&self) -> u32 {
|
2013-04-22 16:27:30 -05:00
|
|
|
let this: &mut u32 = transmute(self);
|
|
|
|
*this
|
2012-06-26 11:07:24 -05:00
|
|
|
}
|
|
|
|
}
|
2012-10-03 18:43:56 -05:00
|
|
|
pub fn parse_to_ipv4_rep(ip: &str) -> result::Result<Ipv4Rep, ~str> {
|
2013-06-09 08:10:50 -05:00
|
|
|
let parts: ~[uint] = ip.split_iter('.').transform(|s| {
|
|
|
|
match uint::from_str(s) {
|
|
|
|
Some(n) if n <= 255 => n,
|
|
|
|
_ => 256
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
2013-06-09 08:10:50 -05:00
|
|
|
}).collect();
|
2012-09-28 14:22:33 -05:00
|
|
|
if parts.len() != 4 {
|
2013-01-22 10:44:24 -06:00
|
|
|
Err(fmt!("'%s' doesn't have 4 parts", ip))
|
2013-06-17 18:43:22 -05:00
|
|
|
} else if parts.iter().any_(|x| *x == 256u) {
|
2013-01-22 10:44:24 -06:00
|
|
|
Err(fmt!("invalid octal in addr '%s'", ip))
|
|
|
|
} else {
|
|
|
|
Ok(Ipv4Rep {
|
|
|
|
a: parts[0] as u8, b: parts[1] as u8,
|
|
|
|
c: parts[2] as u8, d: parts[3] as u8,
|
|
|
|
})
|
2012-06-26 11:07:24 -05:00
|
|
|
}
|
|
|
|
}
|
2012-10-03 18:43:56 -05:00
|
|
|
pub fn try_parse_addr(ip: &str) -> result::Result<IpAddr,ParseAddrErr> {
|
2012-06-17 22:36:36 -05:00
|
|
|
unsafe {
|
2012-06-26 11:07:24 -05:00
|
|
|
let INADDR_NONE = ll::get_INADDR_NONE();
|
2012-06-26 14:47:44 -05:00
|
|
|
let ip_rep_result = parse_to_ipv4_rep(ip);
|
2012-09-25 18:23:04 -05:00
|
|
|
if result::is_err(&ip_rep_result) {
|
|
|
|
let err_str = result::get_err(&ip_rep_result);
|
2013-01-22 10:44:24 -06:00
|
|
|
return result::Err(ParseAddrErr { err_msg: err_str })
|
2012-06-26 11:07:24 -05:00
|
|
|
}
|
|
|
|
// ipv4_rep.as_u32 is unsafe :/
|
|
|
|
let input_is_inaddr_none =
|
2012-09-25 18:23:04 -05:00
|
|
|
result::get(&ip_rep_result).as_u32() == INADDR_NONE;
|
2012-06-26 11:07:24 -05:00
|
|
|
|
2013-05-29 13:10:16 -05:00
|
|
|
let new_addr = uv_ip4_addr(ip, 22);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
let reformatted_name = uv_ip4_name(&new_addr);
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("try_parse_addr: input ip: %s reparsed ip: %s",
|
|
|
|
ip, reformatted_name);
|
2012-06-26 14:47:44 -05:00
|
|
|
let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name);
|
2012-09-25 18:23:04 -05:00
|
|
|
if result::is_err(&ref_ip_rep_result) {
|
|
|
|
let err_str = result::get_err(&ref_ip_rep_result);
|
2013-01-22 10:44:24 -06:00
|
|
|
return Err(ParseAddrErr { err_msg: err_str })
|
2012-06-26 11:07:24 -05:00
|
|
|
}
|
2013-01-22 10:44:24 -06:00
|
|
|
|
2012-09-25 18:23:04 -05:00
|
|
|
if result::get(&ref_ip_rep_result).as_u32() == INADDR_NONE &&
|
2012-06-26 11:07:24 -05:00
|
|
|
!input_is_inaddr_none {
|
2013-01-22 10:44:24 -06:00
|
|
|
Err(ParseAddrErr {
|
|
|
|
err_msg: ~"uv_ip4_name produced invalid result.",
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Ok(Ipv4(copy(new_addr)))
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
2012-05-19 16:06:48 -05:00
|
|
|
}
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
|
|
|
}
|
2012-10-03 18:43:56 -05:00
|
|
|
pub mod v6 {
|
2013-05-17 17:28:44 -05:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2013-01-08 21:37:25 -06:00
|
|
|
use net::ip::{IpAddr, Ipv6, ParseAddrErr};
|
|
|
|
use uv_ip6_addr = uv::ll::ip6_addr;
|
|
|
|
use uv_ip6_name = uv::ll::ip6_name;
|
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::result;
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2012-10-03 18:43:56 -05:00
|
|
|
pub fn parse_addr(ip: &str) -> IpAddr {
|
2012-08-06 14:34:08 -05:00
|
|
|
match try_parse_addr(ip) {
|
2013-02-15 01:30:30 -06:00
|
|
|
result::Ok(addr) => addr,
|
2013-05-29 18:59:33 -05:00
|
|
|
result::Err(err_data) => fail!(copy err_data.err_msg)
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
|
|
|
}
|
2012-10-03 18:43:56 -05:00
|
|
|
pub fn try_parse_addr(ip: &str) -> result::Result<IpAddr,ParseAddrErr> {
|
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
2012-06-17 22:42:48 -05:00
|
|
|
unsafe {
|
|
|
|
// need to figure out how to establish a parse failure..
|
2013-05-29 13:10:16 -05:00
|
|
|
let new_addr = uv_ip6_addr(ip, 22);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
let reparsed_name = uv_ip6_name(&new_addr);
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("v6::try_parse_addr ip: '%s' reparsed '%s'",
|
|
|
|
ip, reparsed_name);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
// '::' appears to be uv_ip6_name() returns for bogus
|
|
|
|
// parses..
|
2012-09-03 00:18:08 -05:00
|
|
|
if ip != &"::" && reparsed_name == ~"::" {
|
2013-01-22 10:44:24 -06:00
|
|
|
Err(ParseAddrErr { err_msg:fmt!("failed to parse '%s'", ip) })
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
|
|
|
else {
|
2013-01-22 10:44:24 -06:00
|
|
|
Ok(Ipv6(new_addr))
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-22 10:44:24 -06:00
|
|
|
struct GetAddrData {
|
2013-01-25 02:52:50 -06:00
|
|
|
output_ch: SharedChan<result::Result<~[IpAddr],IpGetAddrErr>>
|
2013-01-22 10:44:24 -06:00
|
|
|
}
|
2012-06-27 17:59:04 -05:00
|
|
|
|
2013-04-22 16:27:30 -05:00
|
|
|
extern fn get_addr_cb(handle: *uv_getaddrinfo_t,
|
|
|
|
status: libc::c_int,
|
2013-01-23 13:43:58 -06:00
|
|
|
res: *addrinfo) {
|
|
|
|
unsafe {
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("in get_addr_cb");
|
2013-01-23 13:43:58 -06:00
|
|
|
let handle_data = get_data_for_req(handle) as
|
|
|
|
*GetAddrData;
|
2013-01-25 02:52:50 -06:00
|
|
|
let output_ch = (*handle_data).output_ch.clone();
|
2013-01-23 13:43:58 -06:00
|
|
|
if status == 0i32 {
|
|
|
|
if res != (ptr::null::<addrinfo>()) {
|
|
|
|
let mut out_vec = ~[];
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("initial addrinfo: %?", res);
|
2013-01-23 13:43:58 -06:00
|
|
|
let mut curr_addr = res;
|
|
|
|
loop {
|
|
|
|
let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) {
|
|
|
|
Ipv4(copy((
|
|
|
|
*ll::addrinfo_as_sockaddr_in(curr_addr))))
|
|
|
|
}
|
|
|
|
else if ll::is_ipv6_addrinfo(curr_addr) {
|
|
|
|
Ipv6(copy((
|
|
|
|
*ll::addrinfo_as_sockaddr_in6(curr_addr))))
|
|
|
|
}
|
|
|
|
else {
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("curr_addr is not of family AF_INET or \
|
|
|
|
AF_INET6. Error.");
|
2013-01-25 02:52:50 -06:00
|
|
|
output_ch.send(
|
2013-01-23 13:43:58 -06:00
|
|
|
result::Err(GetAddrUnknownError));
|
|
|
|
break;
|
|
|
|
};
|
2013-02-15 01:30:30 -06:00
|
|
|
out_vec.push(new_ip_addr);
|
2012-06-27 17:59:04 -05:00
|
|
|
|
2013-01-23 13:43:58 -06:00
|
|
|
let next_addr = ll::get_next_addrinfo(curr_addr);
|
|
|
|
if next_addr == ptr::null::<addrinfo>() as *addrinfo {
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("null next_addr encountered. no mas");
|
2013-01-23 13:43:58 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
curr_addr = next_addr;
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("next_addr addrinfo: %?", curr_addr);
|
2013-01-23 13:43:58 -06:00
|
|
|
}
|
2012-06-27 17:59:04 -05:00
|
|
|
}
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("successful process addrinfo result, len: %?",
|
2013-05-14 04:52:12 -05:00
|
|
|
out_vec.len());
|
2013-02-15 01:30:30 -06:00
|
|
|
output_ch.send(result::Ok(out_vec));
|
2013-01-23 13:43:58 -06:00
|
|
|
}
|
|
|
|
else {
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("addrinfo pointer is NULL");
|
2013-01-25 02:52:50 -06:00
|
|
|
output_ch.send(
|
2013-01-23 13:43:58 -06:00
|
|
|
result::Err(GetAddrUnknownError));
|
2012-06-27 17:59:04 -05:00
|
|
|
}
|
2012-05-19 16:06:48 -05:00
|
|
|
}
|
|
|
|
else {
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("status != 0 error in get_addr_cb");
|
2013-01-25 02:52:50 -06:00
|
|
|
output_ch.send(
|
2012-08-30 13:01:39 -05:00
|
|
|
result::Err(GetAddrUnknownError));
|
2012-05-19 16:06:48 -05:00
|
|
|
}
|
2013-01-23 13:43:58 -06:00
|
|
|
if res != (ptr::null::<addrinfo>()) {
|
|
|
|
uv_freeaddrinfo(res);
|
|
|
|
}
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("leaving get_addr_cb");
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2013-01-08 21:37:25 -06:00
|
|
|
|
|
|
|
use net_ip::*;
|
2012-12-28 14:46:08 -06:00
|
|
|
use net_ip::v4;
|
|
|
|
use net_ip::v6;
|
|
|
|
use uv;
|
|
|
|
|
|
|
|
use core::result;
|
|
|
|
|
2012-04-29 23:53:17 -05:00
|
|
|
#[test]
|
2012-06-26 18:13:50 -05:00
|
|
|
fn test_ip_ipv4_parse_and_format_ip() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let localhost_str = ~"127.0.0.1";
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(format_addr(&v4::parse_addr(localhost_str))
|
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
2012-06-17 22:42:48 -05:00
|
|
|
== localhost_str)
|
|
|
|
}
|
|
|
|
#[test]
|
2012-06-26 18:13:50 -05:00
|
|
|
fn test_ip_ipv6_parse_and_format_ip() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let localhost_str = ~"::1";
|
2012-09-03 00:18:08 -05:00
|
|
|
let format_result = format_addr(&v6::parse_addr(localhost_str));
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("results: expected: '%s' actual: '%s'",
|
|
|
|
localhost_str, format_result);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(format_result, localhost_str);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
|
|
|
#[test]
|
2012-06-26 18:13:50 -05:00
|
|
|
fn test_ip_ipv4_bad_parse() {
|
2013-05-23 11:39:00 -05:00
|
|
|
match v4::try_parse_addr("b4df00d") {
|
2012-09-28 04:26:20 -05:00
|
|
|
result::Err(ref err_info) => {
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("got error as expected %?", err_info);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(true);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
2012-09-28 04:26:20 -05:00
|
|
|
result::Ok(ref addr) => {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("Expected failure, but got addr %?", addr);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[test]
|
2012-06-27 17:28:03 -05:00
|
|
|
#[ignore(target_os="win32")]
|
2012-06-26 18:13:50 -05:00
|
|
|
fn test_ip_ipv6_bad_parse() {
|
2013-05-23 11:39:00 -05:00
|
|
|
match v6::try_parse_addr("::,~2234k;") {
|
2012-09-28 04:26:20 -05:00
|
|
|
result::Err(ref err_info) => {
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("got error as expected %?", err_info);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(true);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
2012-09-28 04:26:20 -05:00
|
|
|
result::Ok(ref addr) => {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("Expected failure, but got addr %?", addr);
|
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
2012-06-17 22:42:48 -05:00
|
|
|
}
|
|
|
|
}
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
2012-06-25 10:02:34 -05:00
|
|
|
#[test]
|
2012-06-29 17:35:47 -05:00
|
|
|
#[ignore(reason = "valgrind says it's leaky")]
|
2012-06-26 18:13:50 -05:00
|
|
|
fn test_ip_get_addr() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let localhost_name = ~"localhost";
|
2013-01-20 01:38:17 -06:00
|
|
|
let iotask = &uv::global_loop::get();
|
2012-06-25 10:02:34 -05:00
|
|
|
let ga_result = get_addr(localhost_name, iotask);
|
2012-09-25 18:23:04 -05:00
|
|
|
if result::is_err(&ga_result) {
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("got err result from net::ip::get_addr();")
|
2012-06-25 10:02:34 -05:00
|
|
|
}
|
2013-05-08 12:34:47 -05:00
|
|
|
// note really sure how to reliably test/assert
|
2012-06-25 10:02:34 -05:00
|
|
|
// this.. mostly just wanting to see it work, atm.
|
2013-02-15 01:30:30 -06:00
|
|
|
let results = result::unwrap(ga_result);
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("test_get_addr: Number of results for %s: %?",
|
2013-05-14 04:52:12 -05:00
|
|
|
localhost_name, results.len());
|
2013-05-08 03:49:00 -05:00
|
|
|
for results.each |r| {
|
2012-09-18 23:41:37 -05:00
|
|
|
let ipv_prefix = match *r {
|
2012-08-30 13:01:39 -05:00
|
|
|
Ipv4(_) => ~"IPv4",
|
|
|
|
Ipv6(_) => ~"IPv6"
|
2012-06-25 10:02:34 -05:00
|
|
|
};
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!("test_get_addr: result %s: '%s'",
|
|
|
|
ipv_prefix, format_addr(r));
|
2012-06-25 10:02:34 -05:00
|
|
|
}
|
2012-06-26 13:29:57 -05:00
|
|
|
// at least one result.. this is going to vary from system
|
|
|
|
// to system, based on stuff like the contents of /etc/hosts
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(!results.is_empty());
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
|
|
|
#[test]
|
2012-06-29 17:35:47 -05:00
|
|
|
#[ignore(reason = "valgrind says it's leaky")]
|
2012-06-26 18:13:50 -05:00
|
|
|
fn test_ip_get_addr_bad_input() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let localhost_name = ~"sjkl234m,./sdf";
|
2013-01-20 01:38:17 -06:00
|
|
|
let iotask = &uv::global_loop::get();
|
2012-06-26 13:29:57 -05:00
|
|
|
let ga_result = get_addr(localhost_name, iotask);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(result::is_err(&ga_result));
|
2012-04-29 23:53:17 -05:00
|
|
|
}
|
2012-07-06 21:06:58 -05:00
|
|
|
}
|