diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 64cded848d1a..106f1baa8c5b 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -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 { - 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)); - } } \ No newline at end of file diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 6718e3729f74..7c3349efae4b 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -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 unsafe { let result_po = comm::port::(); @@ -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>), +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>), -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"; diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 42dd5b93ea95..fb8ba36acd34 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -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 {