Merge remote-tracking branch 'brson/uv'

This commit is contained in:
Brian Anderson 2012-07-02 21:39:08 -07:00
commit 2ea8922b8a
7 changed files with 1305 additions and 585 deletions

View File

@ -31,6 +31,7 @@ export splitn;
export rsplit;
export rsplitn;
export shift;
export unshift;
export pop;
export push, push_all, push_all_move;
export grow;

View File

@ -4,16 +4,35 @@ Types/fns concerning Internet Protocol (IP), versions 4 & 6
import vec;
import uint;
import iotask = uv::iotask::iotask;
import interact = uv::iotask::interact;
import comm::methods;
import sockaddr_in = uv::ll::sockaddr_in;
import sockaddr_in6 = uv::ll::sockaddr_in6;
import addrinfo = uv::ll::addrinfo;
import uv_getaddrinfo_t = uv::ll::uv_getaddrinfo_t;
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;
import uv_getaddrinfo = uv::ll::getaddrinfo;
import uv_freeaddrinfo = uv::ll::freeaddrinfo;
import create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t;
import set_data_for_req = uv::ll::set_data_for_req;
import get_data_for_req = uv::ll::get_data_for_req;
import ll = uv::ll;
export ip_addr, parse_addr_err;
export format_addr;
export v4;
export v4, v6;
export get_addr;
#[doc = "An IP address"]
enum ip_addr {
#[doc="An IPv4 address"]
ipv4(u8, u8, u8, u8),
ipv6(u16,u16,u16,u16,u16,u16,u16,u16)
ipv4(sockaddr_in),
ipv6(sockaddr_in6)
}
#[doc="
@ -32,22 +51,88 @@ 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";
ipv6(addr) {
unsafe {
let result = uv_ip6_name(&addr);
if result == "" {
fail "failed to convert inner sockaddr_in address to str"
}
result
}
}
}
}
#[doc="
Represents errors returned from `net::ip::get_addr()`
"]
enum ip_get_addr_err {
get_addr_unknown_error
}
#[doc="
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
A `result<[ip_addr]/~, ip_get_addr_err>` instance that will contain
a vector of `ip_addr` results, in the case of success, or an error
object in the case of failure
"]
fn get_addr(++node: str, iotask: iotask)
-> result::result<[ip_addr]/~, ip_get_addr_err> unsafe {
do comm::listen |output_ch| {
do str::unpack_slice(node) |node_ptr, len| {
log(debug, #fmt("slice len %?", len));
let handle = create_uv_getaddrinfo_t();
let handle_ptr = ptr::addr_of(handle);
let handle_data: get_addr_data = {
output_ch: output_ch
};
let handle_data_ptr = ptr::addr_of(handle_data);
do interact(iotask) |loop_ptr| {
let result = uv_getaddrinfo(
loop_ptr,
handle_ptr,
get_addr_cb,
node_ptr,
ptr::null(),
ptr::null());
alt result {
0i32 {
set_data_for_req(handle_ptr, handle_data_ptr);
}
_ {
output_ch.send(result::err(get_addr_unknown_error));
}
}
};
output_ch.recv()
}
}
}
mod v4 {
#[doc = "
Convert a str to `ip_addr`
# Failure
j Fails if the string is not a valid IPv4 address
Fails if the string is not a valid IPv4 address
# Arguments
@ -59,13 +144,22 @@ 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 }
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> {
// the simple, old style numberic representation of
// ipv4
type ipv4_rep = { a: u8, b: u8, c: u8, d:u8 };
impl x for ipv4_rep {
// this is pretty dastardly, i know
unsafe fn as_u32() -> u32 {
*((ptr::addr_of(self)) as *u32)
}
}
fn parse_to_ipv4_rep(ip: str) -> result::result<ipv4_rep, str> {
let parts = vec::map(str::split_char(ip, '.'), |s| {
alt uint::from_str(s) {
some(n) if n <= 255u { n }
@ -73,31 +167,232 @@ j Fails if the string is not a valid IPv4 address
}
});
if vec::len(parts) != 4u {
result::err({err_msg: #fmt("'%s' doesn't have 4 parts",
ip)})
}
result::err(#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)})
}
result::err(#fmt("invalid octal in addr '%s'", ip))
}
else {
result::ok(ipv4(parts[0] as u8, parts[1] as u8,
parts[2] as u8, parts[3] as u8))
result::ok({a: parts[0] as u8, b: parts[1] as u8,
c: parts[2] as u8, d: parts[3] as u8})
}
}
fn try_parse_addr(ip: str) -> result::result<ip_addr,parse_addr_err> {
unsafe {
let INADDR_NONE = ll::get_INADDR_NONE();
let ip_rep_result = parse_to_ipv4_rep(ip);
if result::is_err(ip_rep_result) {
let err_str = result::get_err(ip_rep_result);
ret result::err({err_msg: err_str})
}
// ipv4_rep.as_u32 is unsafe :/
let input_is_inaddr_none =
result::get(ip_rep_result).as_u32() == INADDR_NONE;
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));
let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name);
if result::is_err(ref_ip_rep_result) {
let err_str = result::get_err(ref_ip_rep_result);
ret result::err({err_msg: err_str})
}
if result::get(ref_ip_rep_result).as_u32() == INADDR_NONE &&
!input_is_inaddr_none {
ret result::err(
{err_msg: "uv_ip4_name produced invalid result."})
}
else {
result::ok(ipv4(copy(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) {
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))
}
}
}
}
type get_addr_data = {
output_ch: comm::chan<result::result<[ip_addr]/~,ip_get_addr_err>>
};
crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int,
res: *addrinfo) unsafe {
log(debug, "in get_addr_cb");
let handle_data = get_data_for_req(handle) as
*get_addr_data;
if status == 0i32 {
if res != (ptr::null::<addrinfo>()) {
let mut out_vec = []/~;
log(debug, #fmt("initial addrinfo: %?", res));
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 {
log(debug, "curr_addr is not of family AF_INET or "+
"AF_INET6. Error.");
(*handle_data).output_ch.send(
result::err(get_addr_unknown_error));
break;
};
out_vec += [new_ip_addr]/~;
let next_addr = ll::get_next_addrinfo(curr_addr);
if next_addr == ptr::null::<addrinfo>() as *addrinfo {
log(debug, "null next_addr encountered. no mas");
break;
}
else {
curr_addr = next_addr;
log(debug, #fmt("next_addr addrinfo: %?", curr_addr));
}
}
log(debug, #fmt("successful process addrinfo result, len: %?",
vec::len(out_vec)));
(*handle_data).output_ch.send(result::ok(out_vec));
}
else {
log(debug, "addrinfo pointer is NULL");
(*handle_data).output_ch.send(
result::err(get_addr_unknown_error));
}
}
else {
log(debug, "status != 0 error in get_addr_cb");
(*handle_data).output_ch.send(
result::err(get_addr_unknown_error));
}
if res != (ptr::null::<addrinfo>()) {
uv_freeaddrinfo(res);
}
log(debug, "leaving get_addr_cb");
}
#[cfg(test)]
mod test {
#[test]
fn test_format_ip() {
assert (format_addr(ipv4(127u8, 0u8, 0u8, 1u8))
== "127.0.0.1")
fn test_ip_ipv4_parse_and_format_ip() {
let localhost_str = "127.0.0.1";
assert (format_addr(v4::parse_addr(localhost_str))
== localhost_str)
}
#[test]
fn test_parse_ip() {
assert (v4::parse_addr("127.0.0.1") ==
ipv4(127u8, 0u8, 0u8, 1u8));
fn test_ip_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_ip_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]
#[ignore(target_os="win32")]
fn test_ip_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);
}
}
}
#[test]
#[ignore(reason = "valgrind says it's leaky")]
fn test_ip_get_addr() {
let localhost_name = "localhost";
let iotask = uv::global_loop::get();
let ga_result = get_addr(localhost_name, iotask);
if result::is_err(ga_result) {
fail "got err result from net::ip::get_addr();"
}
// note really sure how to realiably test/assert
// this.. mostly just wanting to see it work, atm.
let results = result::unwrap(ga_result);
log(debug, #fmt("test_get_addr: Number of results for %s: %?",
localhost_name, vec::len(results)));
for vec::each(results) |r| {
let ipv_prefix = alt r {
ipv4(_) {
"IPv4"
}
ipv6(_) {
"IPv6"
}
};
log(debug, #fmt("test_get_addr: result %s: '%s'",
ipv_prefix, format_addr(r)));
}
// at least one result.. this is going to vary from system
// to system, based on stuff like the contents of /etc/hosts
assert vec::len(results) > 0;
}
#[test]
#[ignore(reason = "valgrind says it's leaky")]
fn test_ip_get_addr_bad_input() {
let localhost_name = "sjkl234m,./sdf";
let iotask = uv::global_loop::get();
let ga_result = get_addr(localhost_name, iotask);
assert result::is_err(ga_result);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
use core(vers = "0.2");
import core::*;
export net, net_tcp;
export net, net_tcp, net_ip;
export uv, uv_ll, uv_iotask, uv_global_loop;
export c_vec, util, timer;
export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap;

View File

@ -223,10 +223,82 @@ type sockaddr_in = {
mut sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8)
};
// unix size: 28 .. make due w/ 32
// unix size: 28 .. FIXME #1645
// stuck with 32 becuse of rust padding structs?
#[cfg(target_arch="x86_64")]
type sockaddr_in6 = {
a0: *u8, a1: *u8,
a2: *u8, a3: (u8, u8, u8, u8)
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
type sockaddr_in6 = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
a4: *u8, a5: *u8,
a6: *u8, a7: *u8
};
// unix size: 28 .. FIXME #1645
// stuck with 32 becuse of rust padding structs?
type addr_in = addr_in_impl::addr_in;
#[cfg(unix)]
mod addr_in_impl {
#[cfg(target_arch="x86_64")]
type addr_in = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
type addr_in = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
a4: *u8, a5: *u8,
a6: *u8, a7: *u8,
};
}
#[cfg(windows)]
mod addr_in_impl {
type addr_in = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8
};
}
// unix size: 48, 32bit: 32
type addrinfo = addrinfo_impl::addrinfo;
#[cfg(target_os="linux")]
mod addrinfo_impl {
#[cfg(target_arch="x86_64")]
type addrinfo = {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8
};
#[cfg(target_arch="x86")]
type addrinfo = {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8
};
}
#[cfg(target_os="macos")]
#[cfg(target_os="freebsd")]
mod addrinfo_impl {
type addrinfo = {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8
};
}
#[cfg(windows)]
mod addrinfo_impl {
type addrinfo = {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8
};
}
// unix size: 72
type uv_getaddrinfo_t = {
a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8,
a06: *u8, a07: *u8, a08: *u8
};
mod uv_ll_struct_stubgen {
@ -474,10 +546,18 @@ mod uv_ll_struct_stubgen {
a12: 0 as *u8
};
}
fn gen_stub_uv_getaddrinfo_t() -> uv_getaddrinfo_t {
{
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8, a07: 0 as *u8,
a08: 0 as *u8
}
}
}
#[nolink]
native mod rustrt {
// libuv public API
fn rust_uv_loop_new() -> *libc::c_void;
fn rust_uv_loop_delete(lp: *libc::c_void);
fn rust_uv_loop_refcount(loop_ptr: *libc::c_void) -> libc::c_int;
@ -500,6 +580,12 @@ native mod rustrt {
fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char;
fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int)
-> sockaddr_in;
fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int)
-> sockaddr_in6;
fn rust_uv_ip4_name(src: *sockaddr_in, dst: *u8, size: libc::size_t)
-> libc::c_int;
fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: libc::size_t)
-> libc::c_int;
// FIXME ref #2064
fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
@ -508,6 +594,14 @@ native mod rustrt {
// FIXME ref #2064
fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t,
++addr: *sockaddr_in) -> libc::c_int;
// FIXME ref #2064
fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
++after_cb: *u8,
++addr: *sockaddr_in6) -> libc::c_int;
// FIXME ref #2064
fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t,
++addr: *sockaddr_in6) -> libc::c_int;
fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int,
cb: *u8) -> libc::c_int;
fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void)
@ -527,7 +621,22 @@ native mod rustrt {
repeat: libc::c_uint) -> libc::c_int;
fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int;
fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void,
handle: *uv_getaddrinfo_t,
cb: *u8,
node_name_ptr: *u8,
service_name_ptr: *u8,
// should probably only pass ptr::null()
hints: *addrinfo) -> libc::c_int;
fn rust_uv_freeaddrinfo(res: *addrinfo);
// data accessors/helpers for rust-mapped uv structs
fn rust_uv_helper_get_INADDR_NONE() -> u32;
fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool;
fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool;
fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo;
fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in;
fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6;
fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8;
fn rust_uv_free_base_of_buf(++buf: uv_buf_t);
fn rust_uv_get_stream_handle_from_connect_req(
@ -558,8 +667,12 @@ native mod rustrt {
fn rust_uv_helper_uv_write_t_size() -> libc::c_uint;
fn rust_uv_helper_uv_err_t_size() -> libc::c_uint;
fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint;
fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint;
fn rust_uv_helper_uv_async_t_size() -> libc::c_uint;
fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint;
fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint;
fn rust_uv_helper_addrinfo_size() -> libc::c_uint;
fn rust_uv_helper_addr_in_size() -> libc::c_uint;
}
unsafe fn loop_new() -> *libc::c_void {
@ -598,11 +711,26 @@ unsafe fn tcp_connect(connect_ptr: *uv_connect_t,
after_connect_cb, addr_ptr);
}
// FIXME ref #2064
unsafe fn tcp_connect6(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in6,
++after_connect_cb: *u8)
-> libc::c_int {
ret rustrt::rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr,
after_connect_cb, addr_ptr);
}
// FIXME ref #2064
unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in) -> libc::c_int {
ret rustrt::rust_uv_tcp_bind(tcp_server_ptr,
addr_ptr);
}
// FIXME ref #2064
unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in6) -> libc::c_int {
ret rustrt::rust_uv_tcp_bind6(tcp_server_ptr,
addr_ptr);
}
unsafe fn listen<T>(stream: *T, backlog: libc::c_int,
cb: *u8) -> libc::c_int {
@ -677,14 +805,59 @@ unsafe fn buf_init(++input: *u8, len: uint) -> uv_buf_t {
}
unsafe fn ip4_addr(ip: str, port: int)
-> sockaddr_in {
let mut addr_vec = str::bytes(ip);
vec::push(addr_vec, 0u8); // add null terminator
let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec);
let ip_back = str::from_bytes(addr_vec);
log(debug, #fmt("vec val: '%s' length: %u",
ip_back, vec::len(addr_vec)));
ret rustrt::rust_uv_ip4_addr(addr_vec_ptr,
port as libc::c_int);
do str::as_c_str(ip) |ip_buf| {
rustrt::rust_uv_ip4_addr(ip_buf as *u8,
port as libc::c_int)
}
}
unsafe fn ip6_addr(ip: str, port: int)
-> sockaddr_in6 {
do str::as_c_str(ip) |ip_buf| {
rustrt::rust_uv_ip6_addr(ip_buf as *u8,
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;
do vec::as_buf(dst) |dst_buf| {
rustrt::rust_uv_ip4_name(src as *sockaddr_in,
dst_buf, size);
// seems that checking the result of uv_ip4_name
// doesn't work too well..
// you're stuck looking at the value of dst_buf
// to see if it is the string representation of
// INADDR_NONE (0xffffffff or 255.255.255.255 on
// many platforms)
str::unsafe::from_buf(dst_buf)
}
}
unsafe fn ip6_name(src: &sockaddr_in6) -> str {
// ipv6 addr max size: 45 + 1 trailing null byte
let dst: [u8]/~ = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8]/~;
let size = 46 as libc::size_t;
do vec::as_buf(dst) |dst_buf| {
let src_unsafe_ptr = src as *sockaddr_in6;
log(debug, #fmt("val of src *sockaddr_in6: %? sockaddr_in6: %?",
src_unsafe_ptr, src));
let result = rustrt::rust_uv_ip6_name(src_unsafe_ptr,
dst_buf, size);
alt result {
0i32 {
str::unsafe::from_buf(dst_buf)
}
_ {
""
}
}
}
}
unsafe fn timer_init(loop_ptr: *libc::c_void,
@ -699,6 +872,22 @@ unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint,
unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int {
ret rustrt::rust_uv_timer_stop(timer_ptr);
}
unsafe fn getaddrinfo(loop_ptr: *libc::c_void,
handle: *uv_getaddrinfo_t,
cb: *u8,
node_name_ptr: *u8,
service_name_ptr: *u8,
hints: *addrinfo) -> libc::c_int {
rustrt::rust_uv_getaddrinfo(loop_ptr,
handle,
cb,
node_name_ptr,
service_name_ptr,
hints)
}
unsafe fn freeaddrinfo(res: *addrinfo) {
rustrt::rust_uv_freeaddrinfo(res);
}
// libuv struct initializers
unsafe fn tcp_t() -> uv_tcp_t {
@ -716,6 +905,9 @@ unsafe fn async_t() -> uv_async_t {
unsafe fn timer_t() -> uv_timer_t {
ret uv_ll_struct_stubgen::gen_stub_uv_timer_t();
}
unsafe fn getaddrinfo_t() -> uv_getaddrinfo_t {
ret uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t();
}
// data access helpers
unsafe fn get_loop_for_uv_handle<T>(handle: *T)
@ -791,6 +983,25 @@ type uv_err_data = {
err_msg: str
};
unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool {
rustrt::rust_uv_is_ipv4_addrinfo(input)
}
unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool {
rustrt::rust_uv_is_ipv6_addrinfo(input)
}
unsafe fn get_INADDR_NONE() -> u32 {
rustrt::rust_uv_helper_get_INADDR_NONE()
}
unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo {
rustrt::rust_uv_get_next_addrinfo(input)
}
unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in {
rustrt::rust_uv_addrinfo_as_sockaddr_in(input)
}
unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 {
rustrt::rust_uv_addrinfo_as_sockaddr_in6(input)
}
#[cfg(test)]
mod test {
enum tcp_read_data {
@ -1366,6 +1577,33 @@ mod test {
log(debug, output);
assert foreign_handle_size as uint == rust_handle_size;
}
#[test]
#[ignore(cfg(target_os = "freebsd"))]
fn test_uv_ll_struct_size_sockaddr_in6() {
let native_handle_size =
rustrt::rust_uv_helper_sockaddr_in6_size();
let rust_handle_size = sys::size_of::<sockaddr_in6>();
let output = #fmt("sockaddr_in6 -- native: %u rust: %u",
native_handle_size as uint, rust_handle_size);
log(debug, output);
// FIXME #1645 .. rust appears to pad structs to the nearest byte..?
// .. can't get the uv::ll::sockaddr_in6 to == 28 :/
// .. so the type always appears to be 32 in size.. which is
// good, i guess.. better too big than too little
assert (4u+native_handle_size as uint) == rust_handle_size;
}
#[test]
#[ignore(reason = "questionable size calculations")]
fn test_uv_ll_struct_size_addr_in() {
let native_handle_size =
rustrt::rust_uv_helper_addr_in_size();
let rust_handle_size = sys::size_of::<addr_in>();
let output = #fmt("addr_in -- native: %u rust: %u",
native_handle_size as uint, rust_handle_size);
log(debug, output);
// FIXME #1645 .. see note above about struct padding
assert (4u+native_handle_size as uint) == rust_handle_size;
}
#[test]
#[ignore(cfg(target_os = "freebsd"))]
@ -1390,4 +1628,30 @@ mod test {
log(debug, output);
assert foreign_handle_size as uint == rust_handle_size;
}
#[test]
#[ignore(cfg(target_os = "freebsd"))]
#[ignore(cfg(target_os = "win32"))]
fn test_uv_ll_struct_size_uv_getaddrinfo_t() {
let native_handle_size =
rustrt::rust_uv_helper_uv_getaddrinfo_t_size();
let rust_handle_size = sys::size_of::<uv_getaddrinfo_t>();
let output = #fmt("uv_getaddrinfo_t -- native: %u rust: %u",
native_handle_size as uint, rust_handle_size);
log(debug, output);
assert native_handle_size as uint == rust_handle_size;
}
#[test]
#[ignore(cfg(target_os = "freebsd"))]
#[ignore(cfg(target_os = "macos"))]
#[ignore(cfg(target_os = "win32"))]
fn test_uv_ll_struct_size_addrinfo() {
let native_handle_size =
rustrt::rust_uv_helper_addrinfo_size();
let rust_handle_size = sys::size_of::<addrinfo>();
let output = #fmt("addrinfo -- native: %u rust: %u",
native_handle_size as uint, rust_handle_size);
log(debug, output);
assert native_handle_size as uint == rust_handle_size;
}
}

View File

@ -238,32 +238,36 @@ rust_uv_tcp_connect(uv_connect_t* connect_ptr,
uv_tcp_t* tcp_ptr,
uv_connect_cb cb,
sockaddr_in* addr_ptr) {
rust_task* task = rust_get_current_task();
LOG(task, stdlib, "inside rust_uv_tcp_connect");
// FIXME ref #2064
sockaddr_in addr = *addr_ptr;
LOG(task, stdlib, "before tcp_connect .. port: %d",
addr.sin_port);
LOG(task, stdlib, "before tcp_connect.. tcp stream:" \
"%lu cb ptr: %lu",
(unsigned long int)tcp_ptr, (unsigned long int)cb);
int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb);
LOG(task, stdlib, "leaving rust_uv_tcp_connect.." \
"and result: %d",
result);
return result;
}
extern "C" int
rust_uv_tcp_bind(uv_tcp_t* tcp_server, sockaddr_in* addr_ptr) {
// FIXME ref #2064
rust_task* task = rust_get_current_task();
sockaddr_in addr = *addr_ptr;
LOG(task, stdlib, "before uv_tcp_bind .. tcp_server:" \
"%lu port: %d",
(unsigned long int)tcp_server, addr.sin_port);
return uv_tcp_bind(tcp_server, addr);
}
extern "C" int
rust_uv_tcp_connect6(uv_connect_t* connect_ptr,
uv_tcp_t* tcp_ptr,
uv_connect_cb cb,
sockaddr_in6* addr_ptr) {
// FIXME ref #2064
sockaddr_in6 addr = *addr_ptr;
int result = uv_tcp_connect6(connect_ptr, tcp_ptr, addr, cb);
return result;
}
extern "C" int
rust_uv_tcp_bind6
(uv_tcp_t* tcp_server, sockaddr_in6* addr_ptr) {
// FIXME ref #2064
sockaddr_in6 addr = *addr_ptr;
return uv_tcp_bind6(tcp_server, addr);
}
extern "C" int
rust_uv_listen(uv_stream_t* stream, int backlog,
@ -301,6 +305,10 @@ rust_uv_helper_sockaddr_in_size() {
return sizeof(sockaddr_in);
}
extern "C" size_t
rust_uv_helper_sockaddr_in6_size() {
return sizeof(sockaddr_in6);
}
extern "C" size_t
rust_uv_helper_uv_async_t_size() {
return sizeof(uv_async_t);
}
@ -308,7 +316,22 @@ extern "C" size_t
rust_uv_helper_uv_timer_t_size() {
return sizeof(uv_timer_t);
}
extern "C" size_t
rust_uv_helper_addr_in_size() {
return sizeof(sockaddr_in6);
}
extern "C" size_t
rust_uv_helper_uv_getaddrinfo_t_size() {
return sizeof(uv_getaddrinfo_t);
}
extern "C" size_t
rust_uv_helper_addrinfo_size() {
return sizeof(addrinfo);
}
extern "C" unsigned int
rust_uv_helper_get_INADDR_NONE() {
return INADDR_NONE;
}
extern "C" uv_stream_t*
rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) {
return connect->handle;
@ -436,11 +459,27 @@ extern "C" struct sockaddr_in
rust_uv_ip4_addr(const char* ip, int port) {
rust_task* task = rust_get_current_task();
LOG(task, stdlib, "before creating addr_ptr.. ip %s" \
"port %d", ip, port);
" port %d\n", ip, port);
struct sockaddr_in addr = uv_ip4_addr(ip, port);
LOG(task, stdlib, "after creating .. port: %d", addr.sin_port);
return addr;
}
extern "C" struct sockaddr_in6
rust_uv_ip6_addr(const char* ip, int port) {
rust_task* task = rust_get_current_task();
LOG(task, stdlib, "before creating addr_ptr.. ip %s" \
" port %d\n", ip, port);
return uv_ip6_addr(ip, port);
}
extern "C" int
rust_uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) {
return uv_ip4_name(src, dst, size);
}
extern "C" int
rust_uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) {
int result = uv_ip6_name(src, dst, size);
return result;
}
extern "C" uintptr_t*
rust_uv_get_kernel_global_chan_ptr() {
@ -460,3 +499,35 @@ extern "C" void
rust_uv_current_kernel_free(void* mem) {
current_kernel_free(mem);
}
extern "C" int
rust_uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* handle,
uv_getaddrinfo_cb cb,
char* node, char* service,
addrinfo* hints) {
return uv_getaddrinfo(loop, handle, cb, node, service, hints);
}
extern "C" void
rust_uv_freeaddrinfo(addrinfo* res) {
uv_freeaddrinfo(res);
}
extern "C" bool
rust_uv_is_ipv4_addrinfo(addrinfo* input) {
return input->ai_family == AF_INET;
}
extern "C" bool
rust_uv_is_ipv6_addrinfo(addrinfo* input) {
return input->ai_family == AF_INET6;
}
extern "C" addrinfo*
rust_uv_get_next_addrinfo(addrinfo* input) {
return input->ai_next;
}
extern "C" sockaddr_in*
rust_uv_addrinfo_as_sockaddr_in(addrinfo* input) {
return (sockaddr_in*)input->ai_addr;
}
extern "C" sockaddr_in6*
rust_uv_addrinfo_as_sockaddr_in6(addrinfo* input) {
return (sockaddr_in6*)input->ai_addr;
}

View File

@ -111,8 +111,13 @@ rust_uv_last_error
rust_uv_strerror
rust_uv_err_name
rust_uv_ip4_addr
rust_uv_ip4_name
rust_uv_ip6_addr
rust_uv_ip6_name
rust_uv_tcp_connect
rust_uv_tcp_bind
rust_uv_tcp_connect6
rust_uv_tcp_bind6
rust_uv_listen
rust_uv_accept
rust_uv_write
@ -120,12 +125,22 @@ rust_uv_read_start
rust_uv_read_stop
rust_uv_malloc_buf_base_of
rust_uv_free_base_of_buf
rust_uv_is_ipv4_addrinfo
rust_uv_is_ipv6_addrinfo
rust_uv_get_next_addrinfo
rust_uv_addrinfo_as_sockaddr_in
rust_uv_addrinfo_as_sockaddr_in6
rust_uv_helper_uv_tcp_t_size
rust_uv_helper_uv_connect_t_size
rust_uv_helper_uv_buf_t_size
rust_uv_helper_uv_write_t_size
rust_uv_helper_uv_err_t_size
rust_uv_helper_sockaddr_in_size
rust_uv_helper_sockaddr_in6_size
rust_uv_helper_addr_in_size
rust_uv_helper_addrinfo_size
rust_uv_helper_uv_getaddrinfo_t_size
rust_uv_helper_get_INADDR_NONE
rust_uv_helper_uv_async_t_size
rust_uv_helper_uv_timer_t_size
rust_uv_get_stream_handle_from_connect_req
@ -142,6 +157,8 @@ rust_uv_get_len_from_buf
rust_uv_get_kernel_global_chan_ptr
rust_uv_current_kernel_malloc
rust_uv_current_kernel_free
rust_uv_getaddrinfo
rust_uv_freeaddrinfo
rust_dbg_lock_create
rust_dbg_lock_destroy
rust_dbg_lock_lock