std: adding uv::ll::ip4_name and refactored net::ip to use it
replaces net::ip's previously, hand-rolled impl for ipv4 addr parsing.. we're relying on libuv, now
This commit is contained in:
parent
c027292846
commit
30f26ddbc9
@ -5,6 +5,11 @@ Types/fns concerning Internet Protocol (IP), versions 4 & 6
|
||||
import vec;
|
||||
import uint;
|
||||
|
||||
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;
|
||||
|
||||
export ip_addr, parse_addr_err;
|
||||
export format_addr;
|
||||
export v4;
|
||||
@ -12,7 +17,7 @@ export v4;
|
||||
#[doc = "An IP address"]
|
||||
enum ip_addr {
|
||||
#[doc="An IPv4 address"]
|
||||
ipv4(u8, u8, u8, u8),
|
||||
ipv4(sockaddr_in),
|
||||
ipv6(u16,u16,u16,u16,u16,u16,u16,u16)
|
||||
}
|
||||
|
||||
@ -32,8 +37,14 @@ Convert a `ip_addr` to a str
|
||||
"]
|
||||
fn format_addr(ip: ip_addr) -> str {
|
||||
alt ip {
|
||||
ipv4(a, b, c, d) {
|
||||
#fmt["%u.%u.%u.%u", a as uint, b as uint, c as uint, d as uint]
|
||||
ipv4(addr) {
|
||||
unsafe {
|
||||
let result = uv_ip4_name(&addr);
|
||||
if result == "" {
|
||||
fail "failed to convert inner sockaddr_in address to str"
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
ipv6(_, _, _, _, _, _, _, _) {
|
||||
fail "FIXME (#2651) impl parsing of ipv6 addr";
|
||||
@ -59,30 +70,19 @@ j Fails if the string is not a valid IPv4 address
|
||||
"]
|
||||
fn parse_addr(ip: str) -> ip_addr {
|
||||
alt try_parse_addr(ip) {
|
||||
result::ok(addr) { addr }
|
||||
// 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> {
|
||||
let parts = vec::map(str::split_char(ip, '.'), {|s|
|
||||
alt uint::from_str(s) {
|
||||
some(n) if n <= 255u { n }
|
||||
_ { 256u }
|
||||
}
|
||||
});
|
||||
if vec::len(parts) != 4u {
|
||||
result::err({err_msg: #fmt("'%s' doesn't have 4 parts",
|
||||
ip)})
|
||||
}
|
||||
else if vec::contains(parts, 256u) {
|
||||
result::err({err_msg: #fmt("invalid octal in provided addr '%s'",
|
||||
ip)})
|
||||
}
|
||||
else {
|
||||
result::ok(ipv4(parts[0] as u8, parts[1] as u8,
|
||||
parts[2] as u8, parts[3] as u8))
|
||||
unsafe {
|
||||
// need to figure out how to establish a parse failure..
|
||||
result::ok(ipv4(uv_ip4_addr(ip, 22)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,14 +90,8 @@ j Fails if the string is not a valid IPv4 address
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
fn test_format_ip() {
|
||||
assert (format_addr(ipv4(127u8, 0u8, 0u8, 1u8))
|
||||
fn test_ipv4_parse_and_format_ip() {
|
||||
assert (format_addr(v4::parse_addr("127.0.0.1"))
|
||||
== "127.0.0.1")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_ip() {
|
||||
assert (v4::parse_addr("127.0.0.1") ==
|
||||
ipv4(127u8, 0u8, 0u8, 1u8));
|
||||
}
|
||||
}
|
@ -126,7 +126,7 @@ that can be used to send and receive data to/from the remote host. In the
|
||||
event of failure, a `net::tcp::tcp_connect_err_data` instance will be
|
||||
returned
|
||||
"]
|
||||
fn connect(input_ip: ip::ip_addr, port: uint,
|
||||
fn connect(-input_ip: ip::ip_addr, port: uint,
|
||||
iotask: iotask)
|
||||
-> result::result<tcp_socket, tcp_connect_err_data> unsafe {
|
||||
let result_po = comm::port::<conn_attempt>();
|
||||
@ -551,7 +551,7 @@ a `result` instance containing empty data of type `()` on a
|
||||
successful/normal shutdown, and a `tcp_listen_err_data` enum in the event
|
||||
of listen exiting because of an error
|
||||
"]
|
||||
fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint,
|
||||
fn listen(-host_ip: ip::ip_addr, port: uint, backlog: uint,
|
||||
iotask: iotask,
|
||||
on_establish_cb: fn~(comm::chan<option<tcp_err_data>>),
|
||||
+new_connect_cb: fn~(tcp_new_connection,
|
||||
@ -568,7 +568,7 @@ fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint,
|
||||
}
|
||||
}
|
||||
|
||||
fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint,
|
||||
fn listen_common(-host_ip: ip::ip_addr, port: uint, backlog: uint,
|
||||
iotask: iotask,
|
||||
on_establish_cb: fn~(comm::chan<option<tcp_err_data>>),
|
||||
-on_connect_cb: fn~(*uv::ll::uv_tcp_t))
|
||||
@ -589,8 +589,15 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint,
|
||||
let server_data_ptr = ptr::addr_of(server_data);
|
||||
|
||||
let setup_result = comm::listen {|setup_ch|
|
||||
// FIXME this is to address a compiler warning about
|
||||
// an implicit copy.. it seems that double nested
|
||||
// will defeat a move sigil, as is done to the host_ip
|
||||
// arg above.. this same pattern works w/o complaint in
|
||||
// tcp::connect (because the iotask::interact cb isn't
|
||||
// nested within a comm::listen block)
|
||||
let loc_ip = copy(host_ip);
|
||||
iotask::interact(iotask) {|loop_ptr|
|
||||
let tcp_addr = ipv4_ip_addr_to_sockaddr_in(host_ip,
|
||||
let tcp_addr = ipv4_ip_addr_to_sockaddr_in(loc_ip,
|
||||
port);
|
||||
alt uv::ll::tcp_init(loop_ptr, server_stream_ptr) {
|
||||
0i32 {
|
||||
@ -1201,9 +1208,10 @@ type tcp_buffered_socket_data = {
|
||||
fn ipv4_ip_addr_to_sockaddr_in(input_ip: ip::ip_addr,
|
||||
port: uint) -> uv::ll::sockaddr_in unsafe {
|
||||
// FIXME (#2656): ipv6
|
||||
let addr_str = ip::format_addr(input_ip);
|
||||
alt input_ip {
|
||||
ip::ipv4(_,_,_,_) {
|
||||
uv::ll::ip4_addr(ip::format_addr(input_ip), port as int)
|
||||
ip::ipv4(addr) {
|
||||
uv::ll::ip4_addr(addr_str, port as int)
|
||||
}
|
||||
ip::ipv6(_,_,_,_,_,_,_,_) {
|
||||
fail "FIXME (#2656) ipv6 not yet supported";
|
||||
|
@ -704,6 +704,24 @@ unsafe fn ip6_addr(ip: str, port: int)
|
||||
ret rustrt::rust_uv_ip6_addr(addr_vec_ptr,
|
||||
port as libc::c_int);
|
||||
}
|
||||
unsafe fn ip4_name(src: &sockaddr_in) -> str {
|
||||
// ipv4 addr max size: 15 + 1 trailing null byte
|
||||
let dst: [u8] = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
|
||||
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8];
|
||||
let size = 16 as libc::size_t;
|
||||
vec::as_buf(dst) {|dst_buf|
|
||||
let result = rustrt::rust_uv_ip4_name(src as *sockaddr_in,
|
||||
dst_buf, size);
|
||||
alt result {
|
||||
0i32 {
|
||||
str::unsafe::from_buf(dst_buf)
|
||||
}
|
||||
_ {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn timer_init(loop_ptr: *libc::c_void,
|
||||
timer_ptr: *uv_timer_t) -> libc::c_int {
|
||||
|
Loading…
x
Reference in New Issue
Block a user