From e8ddef93da5f112795eff66ff7dc7ccccc1baa86 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 12 Mar 2013 00:48:41 -0700 Subject: [PATCH 01/12] core: Cleanup rt::context --- src/libcore/rt/context.rs | 41 ++++++++++++++++++++++++++++++--------- src/libcore/rt/sched.rs | 10 ++-------- src/libcore/rt/stack.rs | 1 + 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/libcore/rt/context.rs b/src/libcore/rt/context.rs index dfb7bdf04c3bd..11512c3fe7acb 100644 --- a/src/libcore/rt/context.rs +++ b/src/libcore/rt/context.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use option::*; use super::stack::StackSegment; use libc::c_void; use cast::{transmute, transmute_mut_unsafe, @@ -16,17 +17,30 @@ use cast::{transmute, transmute_mut_unsafe, // XXX: Registers is boxed so that it is 16-byte aligned, for storing // SSE regs. It would be marginally better not to do this. In C++ we // use an attribute on a struct. -pub struct Context(~Registers); +// XXX: It would be nice to define regs as `~Option` since +// the registers are sometimes empty, but the discriminant would +// then misalign the regs again. +pub struct Context { + /// The context entry point, saved here for later destruction + start: Option<~~fn()>, + /// Hold the registers while the task or scheduler is suspended + regs: ~Registers +} pub impl Context { static fn empty() -> Context { - Context(new_regs()) + Context { + start: None, + regs: new_regs() + } } /// Create a new context that will resume execution by running ~fn() - /// # Safety Note - /// The `start` closure must remain valid for the life of the Task - static fn new(start: &~fn(), stack: &mut StackSegment) -> Context { + static fn new(start: ~fn(), stack: &mut StackSegment) -> Context { + // XXX: Putting main into a ~ so it's a thin pointer and can + // be passed to the spawn function. Another unfortunate + // allocation + let start = ~start; // The C-ABI function that is the task entry point extern fn task_start_wrapper(f: &~fn()) { (*f)() } @@ -46,15 +60,24 @@ pub impl Context { initialize_call_frame(&mut *regs, fp, argp, sp); - return Context(regs); + return Context { + start: Some(start), + regs: regs + } } + /* Switch contexts + + Suspend the current execution context and resume another by + saving the registers values of the executing thread to a Context + then loading the registers from a previously saved Context. + */ static fn swap(out_context: &mut Context, in_context: &Context) { let out_regs: &mut Registers = match out_context { - &Context(~ref mut r) => r + &Context { regs: ~ref mut r, _ } => r }; let in_regs: &Registers = match in_context { - &Context(~ref r) => r + &Context { regs: ~ref r, _ } => r }; unsafe { swap_registers(out_regs, in_regs) }; @@ -88,7 +111,7 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { let sp = align_down(sp); - let sp = mut_offset(sp, -4); // XXX: -4 words? Needs this be done at all? + let sp = mut_offset(sp, -4); unsafe { *sp = arg as uint; } let sp = mut_offset(sp, -1); diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 8f315452e5e5c..ff0b3d28e8d70 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -285,8 +285,6 @@ pub impl Scheduler { const TASK_MIN_STACK_SIZE: uint = 10000000; // XXX: Too much stack pub struct Task { - /// The task entry point, saved here for later destruction - priv start: ~~fn(), /// The segment of stack on which the task is currently running or, /// if the task is blocked, on which the task will resume execution priv current_stack_segment: StackSegment, @@ -297,15 +295,11 @@ pub struct Task { impl Task { static fn new(stack_pool: &mut StackPool, start: ~fn()) -> Task { - // XXX: Putting main into a ~ so it's a thin pointer and can - // be passed to the spawn function. Another unfortunate - // allocation - let start = ~Task::build_start_wrapper(start); + let start = Task::build_start_wrapper(start); let mut stack = stack_pool.take_segment(TASK_MIN_STACK_SIZE); // NB: Context holds a pointer to that ~fn - let initial_context = Context::new(&*start, &mut stack); + let initial_context = Context::new(start, &mut stack); return Task { - start: start, current_stack_segment: stack, saved_context: initial_context, }; diff --git a/src/libcore/rt/stack.rs b/src/libcore/rt/stack.rs index 02c47218ed83f..ef48025ffe672 100644 --- a/src/libcore/rt/stack.rs +++ b/src/libcore/rt/stack.rs @@ -27,6 +27,7 @@ pub impl StackSegment { } } + /// Point one word beyond the high end of the allocated stack fn end(&self) -> *uint { unsafe { vec::raw::to_ptr(self.buf).offset(self.buf.len()) as *uint From d30c75897416621092023063b885494f2a64e406 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 12 Mar 2013 14:06:19 -0700 Subject: [PATCH 02/12] Give core::rt and std::net their own uvll bindings I intend to do some big refactoring and don't want to deal w/ std just now --- src/libcore/rt/mod.rs | 1 + src/libcore/rt/uv.rs | 2 +- src/libcore/{unstable => rt}/uvll.rs | 0 src/libcore/unstable.rs | 2 - src/libstd/net_ip.rs | 28 +- src/libstd/std.rc | 2 +- src/libstd/uv.rs | 2 +- src/libstd/uv_ll.rs | 1939 ++++++++++++++++++++++++++ 8 files changed, 1957 insertions(+), 19 deletions(-) rename src/libcore/{unstable => rt}/uvll.rs (100%) create mode 100644 src/libstd/uv_ll.rs diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index a1a9884aeca2c..e48367d7202f3 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -37,6 +37,7 @@ macro_rules! rtdebug ( mod sched; mod io; +pub mod uvll; mod uvio; mod uv; // FIXME #5248: The import in `sched` doesn't resolve unless this is pub! diff --git a/src/libcore/rt/uv.rs b/src/libcore/rt/uv.rs index c947e4dde4c15..c450a6319554f 100644 --- a/src/libcore/rt/uv.rs +++ b/src/libcore/rt/uv.rs @@ -43,7 +43,7 @@ use libc::{c_void, c_int, size_t, malloc, free, ssize_t}; use cast::{transmute, transmute_mut_region}; use ptr::null; use sys::size_of; -use unstable::uvll; +use super::uvll; use super::io::{IpAddr, Ipv4, Ipv6}; #[cfg(test)] use unstable::run_in_bare_thread; diff --git a/src/libcore/unstable/uvll.rs b/src/libcore/rt/uvll.rs similarity index 100% rename from src/libcore/unstable/uvll.rs rename to src/libcore/rt/uvll.rs diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index 9b6dcc312347a..ac5e7e90ea6e7 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -35,8 +35,6 @@ pub mod extfmt; #[path = "unstable/lang.rs"] #[cfg(notest)] pub mod lang; -#[path = "unstable/uvll.rs"] -pub mod uvll; mod rustrt { use unstable::{raw_thread, rust_little_lock}; diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 04283674d88be..15593571b43ca 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -21,20 +21,20 @@ use core::vec; use iotask = uv::iotask::IoTask; use interact = uv::iotask::interact; -use sockaddr_in = core::unstable::uvll::sockaddr_in; -use sockaddr_in6 = core::unstable::uvll::sockaddr_in6; -use addrinfo = core::unstable::uvll::addrinfo; -use uv_getaddrinfo_t = core::unstable::uvll::uv_getaddrinfo_t; -use uv_ip4_name = core::unstable::uvll::ip4_name; -use uv_ip4_port = core::unstable::uvll::ip4_port; -use uv_ip6_name = core::unstable::uvll::ip6_name; -use uv_ip6_port = core::unstable::uvll::ip6_port; -use uv_getaddrinfo = core::unstable::uvll::getaddrinfo; -use uv_freeaddrinfo = core::unstable::uvll::freeaddrinfo; -use create_uv_getaddrinfo_t = core::unstable::uvll::getaddrinfo_t; -use set_data_for_req = core::unstable::uvll::set_data_for_req; -use get_data_for_req = core::unstable::uvll::get_data_for_req; -use ll = core::unstable::uvll; +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; /// An IP address pub enum IpAddr { diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 85e914a60a140..6a7576645b8f8 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -36,7 +36,7 @@ not required in or otherwise suitable for the core library. extern mod core(vers = "0.6"); use core::*; -pub use uv_ll = core::unstable::uvll; +pub mod uv_ll; // General io and system-services modules diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index aaddc9b6836f3..e055b40705773 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -33,6 +33,6 @@ * facilities. */ -pub use ll = core::unstable::uvll; +pub use ll = super::uv_ll; pub use iotask = uv_iotask; pub use global_loop = uv_global_loop; diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs new file mode 100644 index 0000000000000..682939975ef28 --- /dev/null +++ b/src/libstd/uv_ll.rs @@ -0,0 +1,1939 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * Low-level bindings to the libuv library. + * + * This module contains a set of direct, 'bare-metal' wrappers around + * the libuv C-API. + * + * Also contained herein are a set of rust records that map, in + * approximate memory-size, to the libuv data structures. The record + * implementations are adjusted, per-platform, to match their respective + * representations. + * + * There are also a collection of helper functions to ease interacting + * with the low-level API (such as a function to return the latest + * libuv error as a rust-formatted string). + * + * As new functionality, existant in uv.h, is added to the rust stdlib, + * the mappings should be added in this module. + * + * This module's implementation will hopefully be, eventually, replaced + * with per-platform, generated source files from rust-bindgen. + */ + +#[allow(non_camel_case_types)]; // C types + +use core::libc::size_t; +use core::libc::c_void; +use core::prelude::*; +use core::ptr::to_unsafe_ptr; + +pub type uv_handle_t = c_void; +pub type uv_loop_t = c_void; +pub type uv_idle_t = c_void; +pub type uv_idle_cb = *u8; + +// libuv struct mappings +pub struct uv_ip4_addr { + ip: ~[u8], + port: int, +} +pub type uv_ip6_addr = uv_ip4_addr; + +pub enum uv_handle_type { + UNKNOWN_HANDLE = 0, + UV_TCP, + UV_UDP, + UV_NAMED_PIPE, + UV_TTY, + UV_FILE, + UV_TIMER, + UV_PREPARE, + UV_CHECK, + UV_IDLE, + UV_ASYNC, + UV_ARES_TASK, + UV_ARES_EVENT, + UV_PROCESS, + UV_FS_EVENT +} + +pub type handle_type = libc::c_uint; + +pub struct uv_handle_fields { + loop_handle: *libc::c_void, + type_: handle_type, + close_cb: *u8, + data: *libc::c_void, +} + +// unix size: 8 +pub struct uv_err_t { + code: libc::c_int, + sys_errno_: libc::c_int +} + +// don't create one of these directly. instead, +// count on it appearing in libuv callbacks or embedded +// in other types as a pointer to be used in other +// operations (so mostly treat it as opaque, once you +// have it in this form..) +pub struct uv_stream_t { + fields: uv_handle_fields, +} + +// 64bit unix size: 216 +#[cfg(target_os="macos")] +pub struct uv_tcp_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, a11: *u8, + a12: *u8, a13: *u8, a14: *u8, a15: *u8, + a16: *u8, a17: *u8, a18: *u8, a19: *u8, + a20: *u8, a21: *u8, a22: *u8, + a23: uv_tcp_t_osx_riders +} +#[cfg(target_arch="x86_64")] +pub struct uv_tcp_t_osx_riders { + a23: *u8, +} +#[cfg(target_arch="x86")] +#[cfg(target_arch="arm")] +pub struct uv_tcp_t_osx_riders { + a23: *u8, + a24: *u8, a25: *u8, +} +#[cfg(target_os="linux")] +#[cfg(target_os="freebsd")] +#[cfg(target_os="android")] +pub struct uv_tcp_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, a11: *u8, + a12: *u8, a13: *u8, a14: *u8, a15: *u8, + a16: *u8, a17: *u8, a18: *u8, a19: *u8, + a20: *u8, a21: *u8, + a22: uv_tcp_t_32bit_unix_riders, +} +// 32bit unix size: 328 (164) +#[cfg(target_arch="x86_64")] +pub struct uv_tcp_t_32bit_unix_riders { + a29: *u8, +} +#[cfg(target_arch="x86")] +#[cfg(target_arch="arm")] +#[cfg(target_arch="mips")] +pub struct uv_tcp_t_32bit_unix_riders { + a29: *u8, a30: *u8, a31: *u8, +} + +// 32bit win32 size: 240 (120) +#[cfg(windows)] +pub struct uv_tcp_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, a11: *u8, + a12: *u8, a13: *u8, a14: *u8, a15: *u8, + a16: *u8, a17: *u8, a18: *u8, a19: *u8, + a20: *u8, a21: *u8, a22: *u8, a23: *u8, + a24: *u8, a25: *u8, +} + +// unix size: 64 +#[cfg(unix)] +pub struct uv_connect_t { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8 +} +// win32 size: 88 (44) +#[cfg(windows)] +pub struct uv_connect_t { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, +} + +// unix size: 16 +pub struct uv_buf_t { + base: *u8, + len: libc::size_t, +} +// no gen stub method.. should create +// it via uv::direct::buf_init() + +// unix size: 160 +#[cfg(unix)] +pub struct uv_write_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, a11: *u8, + a12: *u8, + a14: uv_write_t_32bit_unix_riders, +} +#[cfg(target_arch="x86_64")] +pub struct uv_write_t_32bit_unix_riders { + a13: *u8, a14: *u8, a15: *u8 +} +#[cfg(target_arch="x86")] +#[cfg(target_arch="arm")] +#[cfg(target_arch="mips")] +pub struct uv_write_t_32bit_unix_riders { + a13: *u8, a14: *u8, a15: *u8, + a16: *u8, +} +// win32 size: 136 (68) +#[cfg(windows)] +pub struct uv_write_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, a11: *u8, + a12: *u8, +} +// 64bit unix size: 96 +// 32bit unix size: 152 (76) +#[cfg(unix)] +pub struct uv_async_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, + a07: uv_async_t_32bit_unix_riders, +} +#[cfg(target_arch="x86_64")] +pub struct uv_async_t_32bit_unix_riders { + a10: *u8, +} +#[cfg(target_arch="x86")] +#[cfg(target_arch="arm")] +#[cfg(target_arch="mips")] +pub struct uv_async_t_32bit_unix_riders { + a10: *u8, +} +// win32 size 132 (68) +#[cfg(windows)] +pub struct uv_async_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, a11: *u8, + a12: *u8, +} + +// 64bit unix size: 120 +// 32bit unix size: 84 +#[cfg(unix)] +pub struct uv_timer_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, + a11: uv_timer_t_32bit_unix_riders, +} +#[cfg(target_arch="x86_64")] +pub struct uv_timer_t_32bit_unix_riders { + a10: *u8, +} +#[cfg(target_arch="x86")] +#[cfg(target_arch="arm")] +#[cfg(target_arch="mips")] +pub struct uv_timer_t_32bit_unix_riders { + a10: *u8, a11: *u8, a12: *u8 +} +// win32 size: 64 +#[cfg(windows)] +pub struct uv_timer_t { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8, a11: *u8, +} + +// unix size: 16 +pub struct sockaddr_in { + sin_family: u16, + sin_port: u16, + sin_addr: u32, // in_addr: this is an opaque, per-platform struct + sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8), +} + +// unix size: 28 .. FIXME #1645 +// stuck with 32 becuse of rust padding structs? +#[cfg(target_arch="x86_64")] +pub struct sockaddr_in6 { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8, +} +#[cfg(target_arch="x86")] +#[cfg(target_arch="arm")] +#[cfg(target_arch="mips")] +pub struct 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? +pub type addr_in = addr_in_impl::addr_in; +#[cfg(unix)] +pub mod addr_in_impl { + #[cfg(target_arch="x86_64")] + pub struct addr_in { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8, + } + #[cfg(target_arch="x86")] + #[cfg(target_arch="arm")] + #[cfg(target_arch="mips")] + pub struct addr_in { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8, + a4: *u8, a5: *u8, + a6: *u8, a7: *u8, + } +} +#[cfg(windows)] +pub mod addr_in_impl { + pub struct addr_in { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8, + } +} + +// unix size: 48, 32bit: 32 +pub type addrinfo = addrinfo_impl::addrinfo; +#[cfg(target_os="linux")] +#[cfg(target_os="android")] +pub mod addrinfo_impl { + #[cfg(target_arch="x86_64")] + pub struct addrinfo { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, + } + #[cfg(target_arch="x86")] + #[cfg(target_arch="arm")] + #[cfg(target_arch="mips")] + pub struct 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")] +pub mod addrinfo_impl { + pub struct addrinfo { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, + } +} +#[cfg(windows)] +pub mod addrinfo_impl { + pub struct addrinfo { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, + } +} + +// unix size: 72 +pub struct uv_getaddrinfo_t { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8, + a06: *u8, a07: *u8, a08: *u8, a09: *u8, + a10: *u8, a11: *u8, a12: *u8, a13: *u8, a14: *u8, a15: *u8 +} + +pub mod uv_ll_struct_stubgen { + + use core::ptr; + + use super::{ + uv_async_t, + uv_connect_t, + uv_getaddrinfo_t, + uv_handle_fields, + uv_tcp_t, + uv_timer_t, + uv_write_t, + }; + + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + use super::{ + uv_async_t_32bit_unix_riders, + uv_tcp_t_32bit_unix_riders, + uv_timer_t_32bit_unix_riders, + uv_write_t_32bit_unix_riders, + }; + + pub fn gen_stub_uv_tcp_t() -> uv_tcp_t { + return gen_stub_os(); + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + #[cfg(target_os = "freebsd")] + pub fn gen_stub_os() -> uv_tcp_t { + return gen_stub_arch(); + #[cfg(target_arch="x86_64")] + pub fn gen_stub_arch() -> uv_tcp_t { + uv_tcp_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, + a15: 0 as *u8, + a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, + a19: 0 as *u8, + a20: 0 as *u8, a21: 0 as *u8, + a22: uv_tcp_t_32bit_unix_riders { a29: 0 as *u8 }, + } + } + #[cfg(target_arch="x86")] + #[cfg(target_arch="arm")] + #[cfg(target_arch="mips")] + pub fn gen_stub_arch() -> uv_tcp_t { + uv_tcp_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, + a15: 0 as *u8, + a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, + a19: 0 as *u8, + a20: 0 as *u8, a21: 0 as *u8, + a22: uv_tcp_t_32bit_unix_riders { + a29: 0 as *u8, a30: 0 as *u8, a31: 0 as *u8, + }, + } + } + } + #[cfg(windows)] + pub fn gen_stub_os() -> uv_tcp_t { + uv_tcp_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, + a15: 0 as *u8, + a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, + a19: 0 as *u8, + a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8, + a23: 0 as *u8, + a24: 0 as *u8, a25: 0 as *u8, + } + } + #[cfg(target_os = "macos")] + pub fn gen_stub_os() -> uv_tcp_t { + use super::uv_tcp_t_osx_riders; + + return gen_stub_arch(); + + #[cfg(target_arch = "x86_64")] + fn gen_stub_arch() -> uv_tcp_t { + uv_tcp_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, + a15: 0 as *u8, + a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, + a19: 0 as *u8, + a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8, + a23: uv_tcp_t_osx_riders { + a23: 0 as *u8, + } + } + } + + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "arm")] + fn gen_stub_arch() -> uv_tcp_t { + uv_tcp_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, + a15: 0 as *u8, + a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, + a19: 0 as *u8, + a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8, + a23: uv_tcp_t_osx_riders { + a23: 0 as *u8, + a24: 0 as *u8, a25: 0 as *u8, + } + } + } + } + } + #[cfg(unix)] + pub fn gen_stub_uv_connect_t() -> uv_connect_t { + uv_connect_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 + } + } + #[cfg(windows)] + pub fn gen_stub_uv_connect_t() -> uv_connect_t { + uv_connect_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, a09: 0 as *u8, a10: 0 as *u8, + } + } + #[cfg(unix)] + pub fn gen_stub_uv_async_t() -> uv_async_t { + return gen_stub_arch(); + #[cfg(target_arch = "x86_64")] + pub fn gen_stub_arch() -> uv_async_t { + uv_async_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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: uv_async_t_32bit_unix_riders { a10: 0 as *u8 }, + } + } + #[cfg(target_arch = "x86")] + #[cfg(target_arch="arm")] + #[cfg(target_arch="mips")] + pub fn gen_stub_arch() -> uv_async_t { + uv_async_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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: uv_async_t_32bit_unix_riders { + a10: 0 as *u8, + } + } + } + } + #[cfg(windows)] + pub fn gen_stub_uv_async_t() -> uv_async_t { + uv_async_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, + } + } + #[cfg(unix)] + pub fn gen_stub_uv_timer_t() -> uv_timer_t { + return gen_stub_arch(); + #[cfg(target_arch = "x86_64")] + pub fn gen_stub_arch() -> uv_timer_t { + uv_timer_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, + a11: uv_timer_t_32bit_unix_riders { + a10: 0 as *u8 + }, + } + } + #[cfg(target_arch = "x86")] + #[cfg(target_arch="arm")] + #[cfg(target_arch="mips")] + pub fn gen_stub_arch() -> uv_timer_t { + uv_timer_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, + a11: uv_timer_t_32bit_unix_riders { + a10: 0 as *u8, a11: 0 as *u8, + a12: 0 as *u8, + }, + } + } + } + #[cfg(windows)] + pub fn gen_stub_uv_timer_t() -> uv_timer_t { + uv_timer_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + } + } + #[cfg(unix)] + pub fn gen_stub_uv_write_t() -> uv_write_t { + return gen_stub_arch(); + #[cfg(target_arch="x86_64")] + pub fn gen_stub_arch() -> uv_write_t { + uv_write_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, + a14: uv_write_t_32bit_unix_riders { a13: 0 as *u8, + a14: 0 as *u8, + a15: 0 as *u8}, + } + } + #[cfg(target_arch="x86")] + #[cfg(target_arch="arm")] + #[cfg(target_arch="mips")] + pub fn gen_stub_arch() -> uv_write_t { + uv_write_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8, + a14: uv_write_t_32bit_unix_riders { + a13: 0 as *u8, + a14: 0 as *u8, + a15: 0 as *u8, + a16: 0 as *u8, + } + } + } + } + #[cfg(windows)] + pub fn gen_stub_uv_write_t() -> uv_write_t { + uv_write_t { + fields: uv_handle_fields { + loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + data: ptr::null(), + }, + 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, a09: 0 as *u8, a10: 0 as *u8, + a11: 0 as *u8, + a12: 0 as *u8 + } + } + pub fn gen_stub_uv_getaddrinfo_t() -> 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, a09: 0 as *u8, + a10: 1 as *u8, a11: 1 as *u8, a12: 1 as *u8, a13: 1 as *u8, + a14: 1 as *u8, a15: 1 as *u8 + } + } +} + +#[nolink] +extern mod rustrt { + + // libuv public API + unsafe fn rust_uv_loop_new() -> *libc::c_void; + unsafe fn rust_uv_loop_delete(lp: *libc::c_void); + unsafe fn rust_uv_run(loop_handle: *libc::c_void); + unsafe fn rust_uv_close(handle: *libc::c_void, cb: *u8); + unsafe fn rust_uv_walk(loop_handle: *libc::c_void, cb: *u8, + arg: *libc::c_void); + + unsafe fn rust_uv_idle_new() -> *uv_idle_t; + unsafe fn rust_uv_idle_delete(handle: *uv_idle_t); + unsafe fn rust_uv_idle_init(loop_handle: *uv_loop_t, + handle: *uv_idle_t) -> libc::c_int; + unsafe fn rust_uv_idle_start(handle: *uv_idle_t, + cb: uv_idle_cb) -> libc::c_int; + unsafe fn rust_uv_idle_stop(handle: *uv_idle_t) -> libc::c_int; + + unsafe fn rust_uv_async_send(handle: *uv_async_t); + unsafe fn rust_uv_async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int; + unsafe fn rust_uv_tcp_init( + loop_handle: *libc::c_void, + handle_ptr: *uv_tcp_t) -> libc::c_int; + // FIXME ref #2604 .. ? + unsafe fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, + len: libc::size_t); + unsafe fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; + // FIXME ref #2064 + unsafe fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char; + // FIXME ref #2064 + unsafe fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char; + unsafe fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) + -> sockaddr_in; + unsafe fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int) + -> sockaddr_in6; + unsafe fn rust_uv_ip4_name(src: *sockaddr_in, + dst: *u8, + size: libc::size_t) + -> libc::c_int; + unsafe fn rust_uv_ip6_name(src: *sockaddr_in6, + dst: *u8, + size: libc::size_t) + -> libc::c_int; + unsafe fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint; + unsafe fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint; + // FIXME ref #2064 + unsafe fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + ++after_cb: *u8, + ++addr: *sockaddr_in) -> libc::c_int; + // FIXME ref #2064 + unsafe fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, + ++addr: *sockaddr_in) -> libc::c_int; + // FIXME ref #2064 + unsafe 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 + unsafe fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, + ++addr: *sockaddr_in6) -> libc::c_int; + unsafe fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, + ++name: *sockaddr_in) -> libc::c_int; + unsafe fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, + ++name: *sockaddr_in6) ->libc::c_int; + unsafe fn rust_uv_listen(stream: *libc::c_void, + backlog: libc::c_int, + cb: *u8) -> libc::c_int; + unsafe fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) + -> libc::c_int; + unsafe fn rust_uv_write(req: *libc::c_void, + stream: *libc::c_void, + ++buf_in: *uv_buf_t, + buf_cnt: libc::c_int, + cb: *u8) + -> libc::c_int; + unsafe fn rust_uv_read_start(stream: *libc::c_void, + on_alloc: *u8, + on_read: *u8) + -> libc::c_int; + unsafe fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int; + unsafe fn rust_uv_timer_init(loop_handle: *libc::c_void, + timer_handle: *uv_timer_t) + -> libc::c_int; + unsafe fn rust_uv_timer_start( + timer_handle: *uv_timer_t, + cb: *u8, + timeout: libc::c_uint, + repeat: libc::c_uint) -> libc::c_int; + unsafe fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int; + + unsafe 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; + unsafe fn rust_uv_freeaddrinfo(res: *addrinfo); + + // data accessors/helpers for rust-mapped uv structs + unsafe fn rust_uv_helper_get_INADDR_NONE() -> u32; + unsafe fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool; + unsafe fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool; + unsafe fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo; + unsafe fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo) + -> *sockaddr_in; + unsafe fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo) + -> *sockaddr_in6; + unsafe fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; + unsafe fn rust_uv_free_base_of_buf(++buf: uv_buf_t); + unsafe fn rust_uv_get_stream_handle_from_connect_req( + connect_req: *uv_connect_t) + -> *uv_stream_t; + unsafe fn rust_uv_get_stream_handle_from_write_req( + write_req: *uv_write_t) + -> *uv_stream_t; + unsafe fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void) + -> *libc::c_void; + unsafe fn rust_uv_get_data_for_uv_loop(loop_ptr: *libc::c_void) + -> *libc::c_void; + unsafe fn rust_uv_set_data_for_uv_loop(loop_ptr: *libc::c_void, + data: *libc::c_void); + unsafe fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void) + -> *libc::c_void; + unsafe fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void, + data: *libc::c_void); + unsafe fn rust_uv_get_data_for_req(req: *libc::c_void) + -> *libc::c_void; + unsafe fn rust_uv_set_data_for_req(req: *libc::c_void, + data: *libc::c_void); + unsafe fn rust_uv_get_base_from_buf(++buf: uv_buf_t) -> *u8; + unsafe fn rust_uv_get_len_from_buf(++buf: uv_buf_t) -> libc::size_t; + + // sizeof testing helpers + unsafe fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_uv_write_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_uv_err_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; + unsafe fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint; + unsafe fn rust_uv_helper_uv_async_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint; + unsafe fn rust_uv_helper_addrinfo_size() -> libc::c_uint; + unsafe fn rust_uv_helper_addr_in_size() -> libc::c_uint; +} + +pub unsafe fn loop_new() -> *libc::c_void { + return rustrt::rust_uv_loop_new(); +} + +pub unsafe fn loop_delete(loop_handle: *libc::c_void) { + rustrt::rust_uv_loop_delete(loop_handle); +} + +pub unsafe fn run(loop_handle: *libc::c_void) { + rustrt::rust_uv_run(loop_handle); +} + +pub unsafe fn close(handle: *T, cb: *u8) { + rustrt::rust_uv_close(handle as *libc::c_void, cb); +} + +pub unsafe fn walk(loop_handle: *libc::c_void, cb: *u8, arg: *libc::c_void) { + rustrt::rust_uv_walk(loop_handle, cb, arg); +} + +pub unsafe fn idle_new() -> *uv_idle_t { + rustrt::rust_uv_idle_new() +} + +pub unsafe fn idle_delete(handle: *uv_idle_t) { + rustrt::rust_uv_idle_delete(handle) +} + +pub unsafe fn idle_init(loop_handle: *uv_loop_t, + handle: *uv_idle_t) -> libc::c_int { + rustrt::rust_uv_idle_init(loop_handle, handle) +} + +pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> libc::c_int { + rustrt::rust_uv_idle_start(handle, cb) +} + +pub unsafe fn idle_stop(handle: *uv_idle_t) -> libc::c_int { + rustrt::rust_uv_idle_stop(handle) +} + +pub unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t) + -> libc::c_int { + return rustrt::rust_uv_tcp_init(loop_handle, handle); +} +// FIXME ref #2064 +pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in, + after_connect_cb: *u8) +-> libc::c_int { + log(debug, fmt!("b4 foreign tcp_connect--addr port: %u cb: %u", + (*addr_ptr).sin_port as uint, after_connect_cb as uint)); + return rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); +} +// FIXME ref #2064 +pub 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 { + return rustrt::rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); +} +// FIXME ref #2064 +pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in) -> libc::c_int { + return rustrt::rust_uv_tcp_bind(tcp_server_ptr, + addr_ptr); +} +// FIXME ref #2064 +pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in6) -> libc::c_int { + return rustrt::rust_uv_tcp_bind6(tcp_server_ptr, + addr_ptr); +} + +pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in) -> libc::c_int { + return rustrt::rust_uv_tcp_getpeername(tcp_handle_ptr, name); +} + +pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in6) ->libc::c_int { + return rustrt::rust_uv_tcp_getpeername6(tcp_handle_ptr, name); +} + +pub unsafe fn listen(stream: *T, backlog: libc::c_int, + cb: *u8) -> libc::c_int { + return rustrt::rust_uv_listen(stream as *libc::c_void, backlog, cb); +} + +pub unsafe fn accept(server: *libc::c_void, client: *libc::c_void) + -> libc::c_int { + return rustrt::rust_uv_accept(server as *libc::c_void, + client as *libc::c_void); +} + +pub unsafe fn write(req: *uv_write_t, stream: *T, + buf_in: *~[uv_buf_t], cb: *u8) -> libc::c_int { + let buf_ptr = vec::raw::to_ptr(*buf_in); + let buf_cnt = vec::len(*buf_in) as i32; + return rustrt::rust_uv_write(req as *libc::c_void, + stream as *libc::c_void, + buf_ptr, buf_cnt, cb); +} +pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, + on_read: *u8) -> libc::c_int { + return rustrt::rust_uv_read_start(stream as *libc::c_void, + on_alloc, on_read); +} + +pub unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int { + return rustrt::rust_uv_read_stop(stream as *libc::c_void); +} + +pub unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t { + return rustrt::rust_uv_last_error(loop_handle); +} + +pub unsafe fn strerror(err: *uv_err_t) -> *libc::c_char { + return rustrt::rust_uv_strerror(err); +} +pub unsafe fn err_name(err: *uv_err_t) -> *libc::c_char { + return rustrt::rust_uv_err_name(err); +} + +pub unsafe fn async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int { + return rustrt::rust_uv_async_init(loop_handle, + async_handle, + cb); +} + +pub unsafe fn async_send(async_handle: *uv_async_t) { + return rustrt::rust_uv_async_send(async_handle); +} +pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { + let out_buf = uv_buf_t { base: ptr::null(), len: 0 as libc::size_t }; + let out_buf_ptr = ptr::addr_of(&out_buf); + log(debug, fmt!("buf_init - input %u len %u out_buf: %u", + input as uint, + len as uint, + out_buf_ptr as uint)); + // yuck :/ + rustrt::rust_uv_buf_init(out_buf_ptr, input, len as size_t); + //let result = rustrt::rust_uv_buf_init_2(input, len as size_t); + log(debug, ~"after rust_uv_buf_init"); + let res_base = get_base_from_buf(out_buf); + let res_len = get_len_from_buf(out_buf); + //let res_base = get_base_from_buf(result); + log(debug, fmt!("buf_init - result %u len %u", + res_base as uint, + res_len as uint)); + return out_buf; + //return result; +} +pub unsafe fn ip4_addr(ip: &str, port: int) +-> sockaddr_in { + do str::as_c_str(ip) |ip_buf| { + rustrt::rust_uv_ip4_addr(ip_buf as *u8, + port as libc::c_int) + } +} +pub 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) + } +} +pub 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]; + do vec::as_imm_buf(dst) |dst_buf, size| { + rustrt::rust_uv_ip4_name(to_unsafe_ptr(src), + dst_buf, size as libc::size_t); + // 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::raw::from_buf(dst_buf) + } +} +pub 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]; + do vec::as_imm_buf(dst) |dst_buf, size| { + let src_unsafe_ptr = to_unsafe_ptr(src); + 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 as libc::size_t); + match result { + 0i32 => str::raw::from_buf(dst_buf), + _ => ~"" + } + } +} +pub unsafe fn ip4_port(src: &sockaddr_in) -> uint { + rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint +} +pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint { + rustrt::rust_uv_ip6_port(to_unsafe_ptr(src)) as uint +} + +pub unsafe fn timer_init(loop_ptr: *libc::c_void, + timer_ptr: *uv_timer_t) -> libc::c_int { + return rustrt::rust_uv_timer_init(loop_ptr, timer_ptr); +} +pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint, + repeat: uint) -> libc::c_int { + return rustrt::rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint, + repeat as libc::c_uint); +} +pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int { + return rustrt::rust_uv_timer_stop(timer_ptr); +} +pub 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) +} +pub unsafe fn freeaddrinfo(res: *addrinfo) { + rustrt::rust_uv_freeaddrinfo(res); +} + +// libuv struct initializers +pub unsafe fn tcp_t() -> uv_tcp_t { + return uv_ll_struct_stubgen::gen_stub_uv_tcp_t(); +} +pub unsafe fn connect_t() -> uv_connect_t { + return uv_ll_struct_stubgen::gen_stub_uv_connect_t(); +} +pub unsafe fn write_t() -> uv_write_t { + return uv_ll_struct_stubgen::gen_stub_uv_write_t(); +} +pub unsafe fn async_t() -> uv_async_t { + return uv_ll_struct_stubgen::gen_stub_uv_async_t(); +} +pub unsafe fn timer_t() -> uv_timer_t { + return uv_ll_struct_stubgen::gen_stub_uv_timer_t(); +} +pub unsafe fn getaddrinfo_t() -> uv_getaddrinfo_t { + return uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t(); +} + +// data access helpers +pub unsafe fn get_loop_for_uv_handle(handle: *T) + -> *libc::c_void { + return rustrt::rust_uv_get_loop_for_uv_handle(handle as *libc::c_void); +} +pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) + -> *uv_stream_t { + return rustrt::rust_uv_get_stream_handle_from_connect_req( + connect); +} +pub unsafe fn get_stream_handle_from_write_req( + write_req: *uv_write_t) + -> *uv_stream_t { + return rustrt::rust_uv_get_stream_handle_from_write_req( + write_req); +} +pub unsafe fn get_data_for_uv_loop(loop_ptr: *libc::c_void) -> *libc::c_void { + rustrt::rust_uv_get_data_for_uv_loop(loop_ptr) +} +pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void, + data: *libc::c_void) { + rustrt::rust_uv_set_data_for_uv_loop(loop_ptr, data); +} +pub unsafe fn get_data_for_uv_handle(handle: *T) -> *libc::c_void { + return rustrt::rust_uv_get_data_for_uv_handle(handle as *libc::c_void); +} +pub unsafe fn set_data_for_uv_handle(handle: *T, + data: *U) { + rustrt::rust_uv_set_data_for_uv_handle(handle as *libc::c_void, + data as *libc::c_void); +} +pub unsafe fn get_data_for_req(req: *T) -> *libc::c_void { + return rustrt::rust_uv_get_data_for_req(req as *libc::c_void); +} +pub unsafe fn set_data_for_req(req: *T, + data: *U) { + rustrt::rust_uv_set_data_for_req(req as *libc::c_void, + data as *libc::c_void); +} +pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { + return rustrt::rust_uv_get_base_from_buf(buf); +} +pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t { + return rustrt::rust_uv_get_len_from_buf(buf); +} +pub unsafe fn malloc_buf_base_of(suggested_size: libc::size_t) + -> *u8 { + return rustrt::rust_uv_malloc_buf_base_of(suggested_size); +} +pub unsafe fn free_base_of_buf(buf: uv_buf_t) { + rustrt::rust_uv_free_base_of_buf(buf); +} + +pub unsafe fn get_last_err_info(uv_loop: *libc::c_void) -> ~str { + let err = last_error(uv_loop); + let err_ptr = ptr::addr_of(&err); + let err_name = str::raw::from_c_str(err_name(err_ptr)); + let err_msg = str::raw::from_c_str(strerror(err_ptr)); + return fmt!("LIBUV ERROR: name: %s msg: %s", + err_name, err_msg); +} + +pub unsafe fn get_last_err_data(uv_loop: *libc::c_void) -> uv_err_data { + let err = last_error(uv_loop); + let err_ptr = ptr::addr_of(&err); + let err_name = str::raw::from_c_str(err_name(err_ptr)); + let err_msg = str::raw::from_c_str(strerror(err_ptr)); + uv_err_data { err_name: err_name, err_msg: err_msg } +} + +pub struct uv_err_data { + err_name: ~str, + err_msg: ~str, +} + +pub unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool { + rustrt::rust_uv_is_ipv4_addrinfo(input) +} +pub unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool { + rustrt::rust_uv_is_ipv6_addrinfo(input) +} +pub unsafe fn get_INADDR_NONE() -> u32 { + rustrt::rust_uv_helper_get_INADDR_NONE() +} +pub unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo { + rustrt::rust_uv_get_next_addrinfo(input) +} +pub unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in { + rustrt::rust_uv_addrinfo_as_sockaddr_in(input) +} +pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 { + rustrt::rust_uv_addrinfo_as_sockaddr_in6(input) +} + +#[cfg(test)] +pub mod test { + use prelude::*; + use super::*; + use comm::{SharedChan, stream, GenericChan, GenericPort}; + + enum tcp_read_data { + tcp_read_eof, + tcp_read_more(~[u8]), + tcp_read_error + } + + struct request_wrapper { + write_req: *uv_write_t, + req_buf: *~[uv_buf_t], + read_chan: SharedChan<~str>, + } + + extern fn after_close_cb(handle: *libc::c_void) { + log(debug, fmt!("after uv_close! handle ptr: %?", + handle)); + } + + extern fn on_alloc_cb(handle: *libc::c_void, + suggested_size: libc::size_t) + -> uv_buf_t { + unsafe { + log(debug, ~"on_alloc_cb!"); + let char_ptr = malloc_buf_base_of(suggested_size); + log(debug, fmt!("on_alloc_cb h: %? char_ptr: %u sugsize: %u", + handle, + char_ptr as uint, + suggested_size as uint)); + return buf_init(char_ptr, suggested_size as uint); + } + } + + extern fn on_read_cb(stream: *uv_stream_t, + nread: libc::ssize_t, + ++buf: uv_buf_t) { + unsafe { + let nread = nread as int; + log(debug, fmt!("CLIENT entering on_read_cb nred: %d", + nread)); + if (nread > 0) { + // we have data + log(debug, fmt!("CLIENT read: data! nread: %d", nread)); + read_stop(stream); + let client_data = + get_data_for_uv_handle(stream as *libc::c_void) + as *request_wrapper; + let buf_base = get_base_from_buf(buf); + let bytes = vec::from_buf(buf_base, nread as uint); + let read_chan = (*client_data).read_chan.clone(); + let msg_from_server = str::from_bytes(bytes); + read_chan.send(msg_from_server); + close(stream as *libc::c_void, after_close_cb) + } + else if (nread == -1) { + // err .. possibly EOF + log(debug, ~"read: eof!"); + } + else { + // nread == 0 .. do nothing, just free buf as below + log(debug, ~"read: do nothing!"); + } + // when we're done + free_base_of_buf(buf); + log(debug, ~"CLIENT exiting on_read_cb"); + } + } + + extern fn on_write_complete_cb(write_req: *uv_write_t, + status: libc::c_int) { + unsafe { + log(debug, + fmt!("CLIENT beginning on_write_complete_cb status: %d", + status as int)); + let stream = get_stream_handle_from_write_req(write_req); + log(debug, + fmt!("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", + stream as int, write_req as int)); + let result = read_start(stream, on_alloc_cb, on_read_cb); + log(debug, + fmt!("CLIENT ending on_write_complete_cb .. status: %d", + result as int)); + } + } + + extern fn on_connect_cb(connect_req_ptr: *uv_connect_t, + status: libc::c_int) { + unsafe { + log(debug, fmt!("beginning on_connect_cb .. status: %d", + status as int)); + let stream = + get_stream_handle_from_connect_req(connect_req_ptr); + if (status == 0i32) { + log(debug, ~"on_connect_cb: in status=0 if.."); + let client_data = get_data_for_req( + connect_req_ptr as *libc::c_void) + as *request_wrapper; + let write_handle = (*client_data).write_req; + log(debug, fmt!("on_connect_cb: tcp: %d write_hdl: %d", + stream as int, write_handle as int)); + let write_result = write(write_handle, + stream as *libc::c_void, + (*client_data).req_buf, + on_write_complete_cb); + log(debug, fmt!("on_connect_cb: write() status: %d", + write_result as int)); + } + else { + let test_loop = get_loop_for_uv_handle( + stream as *libc::c_void); + let err_msg = get_last_err_info(test_loop); + log(debug, err_msg); + fail_unless!(false); + } + log(debug, ~"finishing on_connect_cb"); + } + } + + fn impl_uv_tcp_request(ip: &str, port: int, req_str: &str, + client_chan: SharedChan<~str>) { + unsafe { + let test_loop = loop_new(); + let tcp_handle = tcp_t(); + let tcp_handle_ptr = ptr::addr_of(&tcp_handle); + let connect_handle = connect_t(); + let connect_req_ptr = ptr::addr_of(&connect_handle); + + // this is the persistent payload of data that we + // need to pass around to get this example to work. + // In C, this would be a malloc'd or stack-allocated + // struct that we'd cast to a void* and store as the + // data field in our uv_connect_t struct + let req_str_bytes = str::to_bytes(req_str); + let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes); + log(debug, fmt!("req_msg ptr: %u", req_msg_ptr as uint)); + let req_msg = ~[ + buf_init(req_msg_ptr, vec::len(req_str_bytes)) + ]; + // this is the enclosing record, we'll pass a ptr to + // this to C.. + let write_handle = write_t(); + let write_handle_ptr = ptr::addr_of(&write_handle); + log(debug, fmt!("tcp req: tcp stream: %d write_handle: %d", + tcp_handle_ptr as int, + write_handle_ptr as int)); + let client_data = request_wrapper { + write_req: write_handle_ptr, + req_buf: ptr::addr_of(&req_msg), + read_chan: client_chan + }; + + let tcp_init_result = tcp_init( + test_loop as *libc::c_void, tcp_handle_ptr); + if (tcp_init_result == 0i32) { + log(debug, ~"sucessful tcp_init_result"); + + log(debug, ~"building addr..."); + let addr = ip4_addr(ip, port); + // FIXME ref #2064 + let addr_ptr = ptr::addr_of(&addr); + log(debug, fmt!("after build addr in rust. port: %u", + addr.sin_port as uint)); + + // this should set up the connection request.. + log(debug, fmt!("b4 call tcp_connect connect cb: %u ", + on_connect_cb as uint)); + let tcp_connect_result = tcp_connect( + connect_req_ptr, tcp_handle_ptr, + addr_ptr, on_connect_cb); + if (tcp_connect_result == 0i32) { + // not set the data on the connect_req + // until its initialized + set_data_for_req( + connect_req_ptr as *libc::c_void, + ptr::addr_of(&client_data) as *libc::c_void); + set_data_for_uv_handle( + tcp_handle_ptr as *libc::c_void, + ptr::addr_of(&client_data) as *libc::c_void); + log(debug, ~"before run tcp req loop"); + run(test_loop); + log(debug, ~"after run tcp req loop"); + } + else { + log(debug, ~"tcp_connect() failure"); + fail_unless!(false); + } + } + else { + log(debug, ~"tcp_init() failure"); + fail_unless!(false); + } + loop_delete(test_loop); + } + } + + extern fn server_after_close_cb(handle: *libc::c_void) { + unsafe { + log(debug, fmt!("SERVER server stream closed, should exit. h: %?", + handle)); + } + } + + extern fn client_stream_after_close_cb(handle: *libc::c_void) { + unsafe { + log(debug, + ~"SERVER: closed client stream, now closing server stream"); + let client_data = get_data_for_uv_handle( + handle) as + *tcp_server_data; + close((*client_data).server as *libc::c_void, + server_after_close_cb); + } + } + + extern fn after_server_resp_write(req: *uv_write_t) { + unsafe { + let client_stream_ptr = + get_stream_handle_from_write_req(req); + log(debug, ~"SERVER: resp sent... closing client stream"); + close(client_stream_ptr as *libc::c_void, + client_stream_after_close_cb) + } + } + + extern fn on_server_read_cb(client_stream_ptr: *uv_stream_t, + nread: libc::ssize_t, + ++buf: uv_buf_t) { + unsafe { + let nread = nread as int; + if (nread > 0) { + // we have data + log(debug, fmt!("SERVER read: data! nread: %d", nread)); + + // pull out the contents of the write from the client + let buf_base = get_base_from_buf(buf); + let buf_len = get_len_from_buf(buf) as uint; + log(debug, fmt!("SERVER buf base: %u, len: %u, nread: %d", + buf_base as uint, + buf_len as uint, + nread)); + let bytes = vec::from_buf(buf_base, nread as uint); + let request_str = str::from_bytes(bytes); + + let client_data = get_data_for_uv_handle( + client_stream_ptr as *libc::c_void) as *tcp_server_data; + + let server_kill_msg = copy (*client_data).server_kill_msg; + let write_req = (*client_data).server_write_req; + if str::contains(request_str, server_kill_msg) { + log(debug, ~"SERVER: client req contains kill_msg!"); + log(debug, ~"SERVER: sending response to client"); + read_stop(client_stream_ptr); + let server_chan = (*client_data).server_chan.clone(); + server_chan.send(request_str); + let write_result = write( + write_req, + client_stream_ptr as *libc::c_void, + (*client_data).server_resp_buf, + after_server_resp_write); + log(debug, fmt!("SERVER: resp write result: %d", + write_result as int)); + if (write_result != 0i32) { + log(debug, ~"bad result for server resp write()"); + log(debug, get_last_err_info( + get_loop_for_uv_handle(client_stream_ptr + as *libc::c_void))); + fail_unless!(false); + } + } + else { + log(debug, ~"SERVER: client req !contain kill_msg!"); + } + } + else if (nread == -1) { + // err .. possibly EOF + log(debug, ~"read: eof!"); + } + else { + // nread == 0 .. do nothing, just free buf as below + log(debug, ~"read: do nothing!"); + } + // when we're done + free_base_of_buf(buf); + log(debug, ~"SERVER exiting on_read_cb"); + } + } + + extern fn server_connection_cb(server_stream_ptr: + *uv_stream_t, + status: libc::c_int) { + unsafe { + log(debug, ~"client connecting!"); + let test_loop = get_loop_for_uv_handle( + server_stream_ptr as *libc::c_void); + if status != 0i32 { + let err_msg = get_last_err_info(test_loop); + log(debug, fmt!("server_connect_cb: non-zero status: %?", + err_msg)); + return; + } + let server_data = get_data_for_uv_handle( + server_stream_ptr as *libc::c_void) as *tcp_server_data; + let client_stream_ptr = (*server_data).client; + let client_init_result = tcp_init(test_loop, + client_stream_ptr); + set_data_for_uv_handle( + client_stream_ptr as *libc::c_void, + server_data as *libc::c_void); + if (client_init_result == 0i32) { + log(debug, ~"successfully initialized client stream"); + let accept_result = accept(server_stream_ptr as + *libc::c_void, + client_stream_ptr as + *libc::c_void); + if (accept_result == 0i32) { + // start reading + let read_result = read_start( + client_stream_ptr as *uv_stream_t, + on_alloc_cb, + on_server_read_cb); + if (read_result == 0i32) { + log(debug, ~"successful server read start"); + } + else { + log(debug, fmt!("server_connection_cb: bad read:%d", + read_result as int)); + fail_unless!(false); + } + } + else { + log(debug, fmt!("server_connection_cb: bad accept: %d", + accept_result as int)); + fail_unless!(false); + } + } + else { + log(debug, fmt!("server_connection_cb: bad client init: %d", + client_init_result as int)); + fail_unless!(false); + } + } + } + + struct tcp_server_data { + client: *uv_tcp_t, + server: *uv_tcp_t, + server_kill_msg: ~str, + server_resp_buf: *~[uv_buf_t], + server_chan: SharedChan<~str>, + server_write_req: *uv_write_t, + } + + struct async_handle_data { + continue_chan: SharedChan, + } + + extern fn async_close_cb(handle: *libc::c_void) { + log(debug, fmt!("SERVER: closing async cb... h: %?", + handle)); + } + + extern fn continue_async_cb(async_handle: *uv_async_t, + status: libc::c_int) { + unsafe { + // once we're in the body of this callback, + // the tcp server's loop is set up, so we + // can continue on to let the tcp client + // do its thang + let data = get_data_for_uv_handle( + async_handle as *libc::c_void) as *async_handle_data; + let continue_chan = (*data).continue_chan.clone(); + let should_continue = status == 0i32; + continue_chan.send(should_continue); + close(async_handle as *libc::c_void, async_close_cb); + } + } + + fn impl_uv_tcp_server(server_ip: &str, + server_port: int, + kill_server_msg: ~str, + server_resp_msg: ~str, + server_chan: SharedChan<~str>, + continue_chan: SharedChan) { + unsafe { + let test_loop = loop_new(); + let tcp_server = tcp_t(); + let tcp_server_ptr = ptr::addr_of(&tcp_server); + + let tcp_client = tcp_t(); + let tcp_client_ptr = ptr::addr_of(&tcp_client); + + let server_write_req = write_t(); + let server_write_req_ptr = ptr::addr_of(&server_write_req); + + let resp_str_bytes = str::to_bytes(server_resp_msg); + let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes); + log(debug, fmt!("resp_msg ptr: %u", resp_msg_ptr as uint)); + let resp_msg = ~[ + buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) + ]; + + let continue_async_handle = async_t(); + let continue_async_handle_ptr = + ptr::addr_of(&continue_async_handle); + let async_data = + async_handle_data { continue_chan: continue_chan }; + let async_data_ptr = ptr::addr_of(&async_data); + + let server_data = tcp_server_data { + client: tcp_client_ptr, + server: tcp_server_ptr, + server_kill_msg: kill_server_msg, + server_resp_buf: ptr::addr_of(&resp_msg), + server_chan: server_chan, + server_write_req: server_write_req_ptr + }; + let server_data_ptr = ptr::addr_of(&server_data); + set_data_for_uv_handle(tcp_server_ptr as *libc::c_void, + server_data_ptr as *libc::c_void); + + // uv_tcp_init() + let tcp_init_result = tcp_init( + test_loop as *libc::c_void, tcp_server_ptr); + if (tcp_init_result == 0i32) { + let server_addr = ip4_addr(server_ip, server_port); + // FIXME ref #2064 + let server_addr_ptr = ptr::addr_of(&server_addr); + + // uv_tcp_bind() + let bind_result = tcp_bind(tcp_server_ptr, + server_addr_ptr); + if (bind_result == 0i32) { + log(debug, ~"successful uv_tcp_bind, listening"); + + // uv_listen() + let listen_result = listen(tcp_server_ptr as + *libc::c_void, + 128i32, + server_connection_cb); + if (listen_result == 0i32) { + // let the test know it can set up the tcp server, + // now.. this may still present a race, not sure.. + let async_result = async_init(test_loop, + continue_async_handle_ptr, + continue_async_cb); + if (async_result == 0i32) { + set_data_for_uv_handle( + continue_async_handle_ptr as *libc::c_void, + async_data_ptr as *libc::c_void); + async_send(continue_async_handle_ptr); + // uv_run() + run(test_loop); + log(debug, ~"server uv::run() has returned"); + } + else { + log(debug, fmt!("uv_async_init failure: %d", + async_result as int)); + fail_unless!(false); + } + } + else { + log(debug, fmt!("non-zero result on uv_listen: %d", + listen_result as int)); + fail_unless!(false); + } + } + else { + log(debug, fmt!("non-zero result on uv_tcp_bind: %d", + bind_result as int)); + fail_unless!(false); + } + } + else { + log(debug, fmt!("non-zero result on uv_tcp_init: %d", + tcp_init_result as int)); + fail_unless!(false); + } + loop_delete(test_loop); + } + } + + // this is the impl for a test that is (maybe) ran on a + // per-platform/arch basis below + pub fn impl_uv_tcp_server_and_request() { + unsafe { + let bind_ip = ~"0.0.0.0"; + let request_ip = ~"127.0.0.1"; + let port = 8886; + let kill_server_msg = ~"does a dog have buddha nature?"; + let server_resp_msg = ~"mu!"; + let (client_port, client_chan) = stream::<~str>(); + let client_chan = SharedChan(client_chan); + let (server_port, server_chan) = stream::<~str>(); + let server_chan = SharedChan(server_chan); + + let (continue_port, continue_chan) = stream::(); + let continue_chan = SharedChan(continue_chan); + + let kill_server_msg_copy = copy kill_server_msg; + let server_resp_msg_copy = copy server_resp_msg; + do task::spawn_sched(task::ManualThreads(1)) { + impl_uv_tcp_server(bind_ip, port, + copy kill_server_msg_copy, + copy server_resp_msg_copy, + server_chan.clone(), + continue_chan.clone()); + }; + + // block until the server up is.. possibly a race? + log(debug, ~"before receiving on server continue_port"); + continue_port.recv(); + log(debug, ~"received on continue port, set up tcp client"); + + let kill_server_msg_copy = copy kill_server_msg; + do task::spawn_sched(task::ManualThreads(1u)) { + impl_uv_tcp_request(request_ip, port, + kill_server_msg_copy, + client_chan.clone()); + }; + + let msg_from_client = server_port.recv(); + let msg_from_server = client_port.recv(); + + fail_unless!(str::contains(msg_from_client, kill_server_msg)); + fail_unless!(str::contains(msg_from_server, server_resp_msg)); + } + } + + // FIXME don't run on fbsd or linux 32 bit(#2064) + #[cfg(target_os="win32")] + #[cfg(target_os="darwin")] + #[cfg(target_os="linux")] + #[cfg(target_os="android")] + pub mod tcp_and_server_client_test { + #[cfg(target_arch="x86_64")] + pub mod impl64 { + #[test] + pub fn test_uv_ll_tcp_server_and_request() { + unsafe { + super::super::impl_uv_tcp_server_and_request(); + } + } + } + #[cfg(target_arch="x86")] + #[cfg(target_arch="arm")] + #[cfg(target_arch="mips")] + pub mod impl32 { + #[test] + #[ignore(cfg(target_os = "linux"))] + pub fn test_uv_ll_tcp_server_and_request() { + unsafe { + super::super::impl_uv_tcp_server_and_request(); + } + } + } + } + + fn struct_size_check_common(t_name: ~str, + foreign_size: libc::c_uint) { + unsafe { + let rust_size = sys::size_of::(); + let sizes_match = foreign_size as uint == rust_size; + if !sizes_match { + let output = fmt!( + "STRUCT_SIZE FAILURE: %s -- actual: %u expected: %u", + t_name, rust_size, foreign_size as uint); + log(debug, output); + } + fail_unless!(sizes_match); + } + } + + // struct size tests + #[test] + fn test_uv_ll_struct_size_uv_tcp_t() { + unsafe { + struct_size_check_common::( + ~"uv_tcp_t", + super::rustrt::rust_uv_helper_uv_tcp_t_size() + ); + } + } + #[test] + fn test_uv_ll_struct_size_uv_connect_t() { + unsafe { + struct_size_check_common::( + ~"uv_connect_t", + super::rustrt::rust_uv_helper_uv_connect_t_size() + ); + } + } + #[test] + fn test_uv_ll_struct_size_uv_buf_t() { + unsafe { + struct_size_check_common::( + ~"uv_buf_t", + super::rustrt::rust_uv_helper_uv_buf_t_size() + ); + } + } + #[test] + fn test_uv_ll_struct_size_uv_write_t() { + unsafe { + struct_size_check_common::( + ~"uv_write_t", + super::rustrt::rust_uv_helper_uv_write_t_size() + ); + } + } + + #[test] + fn test_uv_ll_struct_size_sockaddr_in() { + unsafe { + struct_size_check_common::( + ~"sockaddr_in", + super::rustrt::rust_uv_helper_sockaddr_in_size() + ); + } + } + #[test] + fn test_uv_ll_struct_size_sockaddr_in6() { + unsafe { + let foreign_handle_size = + super::rustrt::rust_uv_helper_sockaddr_in6_size(); + let rust_handle_size = sys::size_of::(); + let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u", + foreign_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 + fail_unless!((4u+foreign_handle_size as uint) == + rust_handle_size); + } + } + #[test] + #[ignore(reason = "questionable size calculations")] + fn test_uv_ll_struct_size_addr_in() { + unsafe { + let foreign_handle_size = + super::rustrt::rust_uv_helper_addr_in_size(); + let rust_handle_size = sys::size_of::(); + let output = fmt!("addr_in -- foreign: %u rust: %u", + foreign_handle_size as uint, rust_handle_size); + log(debug, output); + // FIXME #1645 .. see note above about struct padding + fail_unless!((4u+foreign_handle_size as uint) == + rust_handle_size); + } + } + + #[test] + fn test_uv_ll_struct_size_uv_async_t() { + unsafe { + struct_size_check_common::( + ~"uv_async_t", + super::rustrt::rust_uv_helper_uv_async_t_size() + ); + } + } + + #[test] + fn test_uv_ll_struct_size_uv_timer_t() { + unsafe { + struct_size_check_common::( + ~"uv_timer_t", + super::rustrt::rust_uv_helper_uv_timer_t_size() + ); + } + } + + #[test] + #[ignore(cfg(target_os = "win32"))] + fn test_uv_ll_struct_size_uv_getaddrinfo_t() { + unsafe { + struct_size_check_common::( + ~"uv_getaddrinfo_t", + super::rustrt::rust_uv_helper_uv_getaddrinfo_t_size() + ); + } + } + #[test] + #[ignore(cfg(target_os = "macos"))] + #[ignore(cfg(target_os = "win32"))] + fn test_uv_ll_struct_size_addrinfo() { + unsafe { + struct_size_check_common::( + ~"addrinfo", + super::rustrt::rust_uv_helper_uv_timer_t_size() + ); + } + } +} From 723d2247c1e310a49dd49afc80e7c8a153bd1432 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 12 Mar 2013 15:40:32 -0700 Subject: [PATCH 03/12] core: Don't use printf in rtdebug! The bots were showing a segfault that I can't reproduce. Assuming it's varargs related so let's not use printf --- src/libcore/rt/mod.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index e48367d7202f3..556431e931534 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -15,16 +15,10 @@ macro_rules! rtdebug_ ( dumb_println(fmt!( $($arg),+ )); fn dumb_println(s: &str) { - use str::as_c_str; - use libc::c_char; - - extern { - fn printf(s: *c_char); - } - - do as_c_str(s.to_str() + "\n") |s| { - unsafe { printf(s); } - } + use io::WriterUtil; + let dbg = ::libc::STDERR_FILENO as ::io::fd_t; + dbg.write_str(s); + dbg.write_str("\n"); } } ) From 54bb7226e16090b471d791af5615016d01000504 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 12 Mar 2013 20:04:25 -0700 Subject: [PATCH 04/12] core: Simplify uvll bindings and strip out currently-unused bits No more mapping uv structs to Rust structs --- src/libcore/rt/uv.rs | 56 +- src/libcore/rt/uvll.rs | 2029 ++++++---------------------------------- src/libstd/uv_ll.rs | 18 - src/rt/rust_uv.cpp | 48 + src/rt/rustrt.def.in | 9 + 5 files changed, 372 insertions(+), 1788 deletions(-) diff --git a/src/libcore/rt/uv.rs b/src/libcore/rt/uv.rs index c450a6319554f..8280359eb2bfc 100644 --- a/src/libcore/rt/uv.rs +++ b/src/libcore/rt/uv.rs @@ -44,21 +44,28 @@ use cast::{transmute, transmute_mut_region}; use ptr::null; use sys::size_of; use super::uvll; +use super::uvll::*; use super::io::{IpAddr, Ipv4, Ipv6}; +use unstable::finally::Finally; #[cfg(test)] use unstable::run_in_bare_thread; #[cfg(test)] use super::thread::Thread; #[cfg(test)] use cell::Cell; -fn ip4_to_uv_ip4(addr: IpAddr) -> uvll::sockaddr_in { +fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) { match addr { Ipv4(a, b, c, d, p) => { unsafe { - uvll::ip4_addr(fmt!("%u.%u.%u.%u", - a as uint, - b as uint, - c as uint, - d as uint), p as int) + let addr = malloc_ip4_addr(fmt!("%u.%u.%u.%u", + a as uint, + b as uint, + c as uint, + d as uint), p as int); + do (|| { + f(addr); + }).finally { + free_ip4_addr(addr); + } } } Ipv6 => fail!() @@ -301,7 +308,7 @@ pub impl StreamWatcher { data.close_cb.swap_unwrap()(); } drop_watcher_data(&mut stream_watcher); - unsafe { free(handle as *c_void) } + unsafe { free_handle(handle as *c_void) } } } } @@ -330,8 +337,7 @@ impl Callback for ConnectionCallback { } pub impl TcpWatcher { static fn new(loop_: &mut Loop) -> TcpWatcher { unsafe { - let size = size_of::() as size_t; - let handle = malloc(size) as *uvll::uv_tcp_t; + let handle = malloc_handle(UV_TCP); fail_unless!(handle.is_not_null()); fail_unless!(0 == uvll::tcp_init(loop_.native_handle(), handle)); let mut watcher = NativeHandle::from_native_handle(handle); @@ -343,12 +349,13 @@ pub impl TcpWatcher { fn bind(&mut self, address: IpAddr) { match address { Ipv4(*) => { - let addr = ip4_to_uv_ip4(address); - let result = unsafe { - uvll::tcp_bind(self.native_handle(), &addr) - }; - // XXX: bind is likely to fail. need real error handling - fail_unless!(result == 0); + do ip4_as_uv_ip4(address) |addr| { + let result = unsafe { + uvll::tcp_bind(self.native_handle(), addr) + }; + // XXX: bind is likely to fail. need real error handling + fail_unless!(result == 0); + } } _ => fail!() } @@ -363,11 +370,12 @@ pub impl TcpWatcher { let connect_handle = connect_watcher.native_handle(); match address { Ipv4(*) => { - let addr = ip4_to_uv_ip4(address); - rtdebug!("connect_t: %x", connect_handle as uint); - fail_unless!(0 == uvll::tcp_connect(connect_handle, - self.native_handle(), - &addr, connect_cb)); + do ip4_as_uv_ip4(address) |addr| { + rtdebug!("connect_t: %x", connect_handle as uint); + fail_unless!(0 == uvll::tcp_connect(connect_handle, + self.native_handle(), + addr, connect_cb)); + } } _ => fail!() } @@ -443,7 +451,7 @@ impl ConnectRequest { static fn new() -> ConnectRequest { let connect_handle = unsafe { - malloc(size_of::() as size_t) + malloc_req(UV_CONNECT) }; fail_unless!(connect_handle.is_not_null()); let connect_handle = connect_handle as *uvll::uv_connect_t; @@ -460,7 +468,7 @@ impl ConnectRequest { } fn delete(self) { - unsafe { free(self.native_handle() as *c_void) } + unsafe { free_req(self.native_handle() as *c_void) } } } @@ -482,7 +490,7 @@ impl WriteRequest { static fn new() -> WriteRequest { let write_handle = unsafe { - malloc(size_of::() as size_t) + malloc_req(UV_WRITE) }; fail_unless!(write_handle.is_not_null()); let write_handle = write_handle as *uvll::uv_write_t; @@ -498,7 +506,7 @@ impl WriteRequest { } fn delete(self) { - unsafe { free(self.native_handle() as *c_void) } + unsafe { free_req(self.native_handle() as *c_void) } } } diff --git a/src/libcore/rt/uvll.rs b/src/libcore/rt/uvll.rs index 80f04cf4ac0c1..1332ddf112732 100644 --- a/src/libcore/rt/uvll.rs +++ b/src/libcore/rt/uvll.rs @@ -14,1190 +14,356 @@ * This module contains a set of direct, 'bare-metal' wrappers around * the libuv C-API. * - * Also contained herein are a set of rust records that map, in - * approximate memory-size, to the libuv data structures. The record - * implementations are adjusted, per-platform, to match their respective - * representations. + * We're not bothering yet to redefine uv's structs as Rust structs + * because they are quite large and change often between versions. + * The maintenance burden is just too high. Instead we use the uv's + * `uv_handle_size` and `uv_req_size` to find the correct size of the + * structs and allocate them on the heap. This can be revisited later. * * There are also a collection of helper functions to ease interacting - * with the low-level API (such as a function to return the latest - * libuv error as a rust-formatted string). + * with the low-level API. * * As new functionality, existant in uv.h, is added to the rust stdlib, * the mappings should be added in this module. - * - * This module's implementation will hopefully be, eventually, replaced - * with per-platform, generated source files from rust-bindgen. */ #[allow(non_camel_case_types)]; // C types -use libc::size_t; -use libc::c_void; +use libc::{size_t, c_int, c_uint, c_void, c_char, uintptr_t}; +use libc::{malloc, free}; use prelude::*; use ptr::to_unsafe_ptr; +pub struct uv_err_t { + code: c_int, + sys_errno_: c_int +} + +pub struct uv_buf_t { + base: *u8, + len: libc::size_t, +} + pub type uv_handle_t = c_void; pub type uv_loop_t = c_void; pub type uv_idle_t = c_void; +pub type uv_tcp_t = c_void; +pub type uv_connect_t = c_void; +pub type uv_write_t = c_void; +pub type uv_async_t = c_void; +pub type uv_timer_t = c_void; +pub type uv_stream_t = c_void; + pub type uv_idle_cb = *u8; -// libuv struct mappings -pub struct uv_ip4_addr { - ip: ~[u8], - port: int, -} -pub type uv_ip6_addr = uv_ip4_addr; +pub type sockaddr_in = c_void; +pub type sockaddr_in6 = c_void; +#[deriving_eq] pub enum uv_handle_type { - UNKNOWN_HANDLE = 0, - UV_TCP, - UV_UDP, - UV_NAMED_PIPE, - UV_TTY, - UV_FILE, - UV_TIMER, - UV_PREPARE, + UV_UNKNOWN_HANDLE, + UV_ASYNC, UV_CHECK, + UV_FS_EVENT, + UV_FS_POLL, + UV_HANDLE, UV_IDLE, - UV_ASYNC, - UV_ARES_TASK, - UV_ARES_EVENT, + UV_NAMED_PIPE, + UV_POLL, + UV_PREPARE, UV_PROCESS, - UV_FS_EVENT -} - -pub type handle_type = libc::c_uint; - -pub struct uv_handle_fields { - loop_handle: *libc::c_void, - type_: handle_type, - close_cb: *u8, - data: *libc::c_void, -} - -// unix size: 8 -pub struct uv_err_t { - code: libc::c_int, - sys_errno_: libc::c_int -} - -// don't create one of these directly. instead, -// count on it appearing in libuv callbacks or embedded -// in other types as a pointer to be used in other -// operations (so mostly treat it as opaque, once you -// have it in this form..) -pub struct uv_stream_t { - fields: uv_handle_fields, -} - -// 64bit unix size: 216 -#[cfg(target_os="macos")] -pub struct uv_tcp_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, a11: *u8, - a12: *u8, a13: *u8, a14: *u8, a15: *u8, - a16: *u8, a17: *u8, a18: *u8, a19: *u8, - a20: *u8, a21: *u8, a22: *u8, - a23: uv_tcp_t_osx_riders -} -#[cfg(target_arch="x86_64")] -pub struct uv_tcp_t_osx_riders { - a23: *u8, -} -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -pub struct uv_tcp_t_osx_riders { - a23: *u8, - a24: *u8, a25: *u8, -} -#[cfg(target_os="linux")] -#[cfg(target_os="freebsd")] -#[cfg(target_os="android")] -pub struct uv_tcp_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, a11: *u8, - a12: *u8, a13: *u8, a14: *u8, a15: *u8, - a16: *u8, a17: *u8, a18: *u8, a19: *u8, - a20: *u8, a21: *u8, - a22: uv_tcp_t_32bit_unix_riders, -} -// 32bit unix size: 328 (164) -#[cfg(target_arch="x86_64")] -pub struct uv_tcp_t_32bit_unix_riders { - a29: *u8, -} -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -pub struct uv_tcp_t_32bit_unix_riders { - a29: *u8, a30: *u8, a31: *u8, -} - -// 32bit win32 size: 240 (120) -#[cfg(windows)] -pub struct uv_tcp_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, a11: *u8, - a12: *u8, a13: *u8, a14: *u8, a15: *u8, - a16: *u8, a17: *u8, a18: *u8, a19: *u8, - a20: *u8, a21: *u8, a22: *u8, a23: *u8, - a24: *u8, a25: *u8, -} - -// unix size: 64 -#[cfg(unix)] -pub struct uv_connect_t { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8 -} -// win32 size: 88 (44) -#[cfg(windows)] -pub struct uv_connect_t { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, -} - -// unix size: 16 -pub struct uv_buf_t { - base: *u8, - len: libc::size_t, + UV_STREAM, + UV_TCP, + UV_TIMER, + UV_TTY, + UV_UDP, + UV_SIGNAL, + UV_FILE, + UV_HANDLE_TYPE_MAX } -// no gen stub method.. should create -// it via uv::direct::buf_init() -// unix size: 160 -#[cfg(unix)] -pub struct uv_write_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, a11: *u8, - a12: *u8, - a14: uv_write_t_32bit_unix_riders, -} -#[cfg(target_arch="x86_64")] -pub struct uv_write_t_32bit_unix_riders { - a13: *u8, a14: *u8, a15: *u8 -} -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -pub struct uv_write_t_32bit_unix_riders { - a13: *u8, a14: *u8, a15: *u8, - a16: *u8, -} -// win32 size: 136 (68) -#[cfg(windows)] -pub struct uv_write_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, a11: *u8, - a12: *u8, -} -// 64bit unix size: 96 -// 32bit unix size: 152 (76) -#[cfg(unix)] -pub struct uv_async_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, - a07: uv_async_t_32bit_unix_riders, -} -#[cfg(target_arch="x86_64")] -pub struct uv_async_t_32bit_unix_riders { - a10: *u8, -} -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -pub struct uv_async_t_32bit_unix_riders { - a10: *u8, -} -// win32 size 132 (68) -#[cfg(windows)] -pub struct uv_async_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, a11: *u8, - a12: *u8, +#[deriving_eq] +pub enum uv_req_type { + UV_UNKNOWN_REQ, + UV_REQ, + UV_CONNECT, + UV_WRITE, + UV_SHUTDOWN, + UV_UDP_SEND, + UV_FS, + UV_WORK, + UV_GETADDRINFO, + UV_REQ_TYPE_MAX } -// 64bit unix size: 120 -// 32bit unix size: 84 -#[cfg(unix)] -pub struct uv_timer_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, - a11: uv_timer_t_32bit_unix_riders, -} -#[cfg(target_arch="x86_64")] -pub struct uv_timer_t_32bit_unix_riders { - a10: *u8, -} -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -pub struct uv_timer_t_32bit_unix_riders { - a10: *u8, a11: *u8, a12: *u8 -} -// win32 size: 64 -#[cfg(windows)] -pub struct uv_timer_t { - fields: uv_handle_fields, - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, a06: *u8, a07: *u8, - a08: *u8, a09: *u8, a10: *u8, a11: *u8, +pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void { + fail_unless!(handle != UV_UNKNOWN_HANDLE && handle != UV_HANDLE_TYPE_MAX); + let size = unsafe { rust_uv_handle_size(handle as uint) }; + let p = malloc(size); + fail_unless!(p.is_not_null()); + return p; } -// unix size: 16 -pub struct sockaddr_in { - sin_family: u16, - sin_port: u16, - sin_addr: u32, // in_addr: this is an opaque, per-platform struct - sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8), +pub unsafe fn free_handle(v: *c_void) { + free(v) } -// unix size: 28 .. FIXME #1645 -// stuck with 32 becuse of rust padding structs? -#[cfg(target_arch="x86_64")] -pub struct sockaddr_in6 { - a0: *u8, a1: *u8, - a2: *u8, a3: *u8, -} -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -pub struct sockaddr_in6 { - a0: *u8, a1: *u8, - a2: *u8, a3: *u8, - a4: *u8, a5: *u8, - a6: *u8, a7: *u8, +pub unsafe fn malloc_req(req: uv_req_type) -> *c_void { + fail_unless!(req != UV_UNKNOWN_REQ && req != UV_REQ_TYPE_MAX); + let size = unsafe { rust_uv_req_size(req as uint) }; + let p = malloc(size); + fail_unless!(p.is_not_null()); + return p; } -// unix size: 28 .. FIXME #1645 -// stuck with 32 becuse of rust padding structs? -pub type addr_in = addr_in_impl::addr_in; -#[cfg(unix)] -pub mod addr_in_impl { - #[cfg(target_arch="x86_64")] - pub struct addr_in { - a0: *u8, a1: *u8, - a2: *u8, a3: *u8, - } - #[cfg(target_arch="x86")] - #[cfg(target_arch="arm")] - #[cfg(target_arch="mips")] - pub struct addr_in { - a0: *u8, a1: *u8, - a2: *u8, a3: *u8, - a4: *u8, a5: *u8, - a6: *u8, a7: *u8, - } -} -#[cfg(windows)] -pub mod addr_in_impl { - pub struct addr_in { - a0: *u8, a1: *u8, - a2: *u8, a3: *u8, - } +pub unsafe fn free_req(v: *c_void) { + free(v) } -// unix size: 48, 32bit: 32 -pub type addrinfo = addrinfo_impl::addrinfo; -#[cfg(target_os="linux")] -#[cfg(target_os="android")] -pub mod addrinfo_impl { - #[cfg(target_arch="x86_64")] - pub struct addrinfo { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, - } - #[cfg(target_arch="x86")] - #[cfg(target_arch="arm")] - #[cfg(target_arch="mips")] - pub struct 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")] -pub mod addrinfo_impl { - pub struct addrinfo { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, - } -} -#[cfg(windows)] -pub mod addrinfo_impl { - pub struct addrinfo { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8, +#[test] +fn handle_sanity_check() { + unsafe { + fail_unless!(UV_HANDLE_TYPE_MAX as uint == rust_uv_handle_type_max()); } } -// unix size: 72 -pub struct uv_getaddrinfo_t { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8, - a06: *u8, a07: *u8, a08: *u8, a09: *u8, - a10: *u8, a11: *u8, a12: *u8, a13: *u8, a14: *u8, a15: *u8 -} - -pub mod uv_ll_struct_stubgen { - - use ptr; - - use super::{ - uv_async_t, - uv_connect_t, - uv_getaddrinfo_t, - uv_handle_fields, - uv_tcp_t, - uv_timer_t, - uv_write_t, - }; - - #[cfg(target_os = "linux")] - #[cfg(target_os = "android")] - #[cfg(target_os = "macos")] - #[cfg(target_os = "freebsd")] - use super::{ - uv_async_t_32bit_unix_riders, - uv_tcp_t_32bit_unix_riders, - uv_timer_t_32bit_unix_riders, - uv_write_t_32bit_unix_riders, - }; - - pub fn gen_stub_uv_tcp_t() -> uv_tcp_t { - return gen_stub_os(); - #[cfg(target_os = "linux")] - #[cfg(target_os = "android")] - #[cfg(target_os = "freebsd")] - pub fn gen_stub_os() -> uv_tcp_t { - return gen_stub_arch(); - #[cfg(target_arch="x86_64")] - pub fn gen_stub_arch() -> uv_tcp_t { - uv_tcp_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, - a15: 0 as *u8, - a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, - a19: 0 as *u8, - a20: 0 as *u8, a21: 0 as *u8, - a22: uv_tcp_t_32bit_unix_riders { a29: 0 as *u8 }, - } - } - #[cfg(target_arch="x86")] - #[cfg(target_arch="arm")] - #[cfg(target_arch="mips")] - pub fn gen_stub_arch() -> uv_tcp_t { - uv_tcp_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, - a15: 0 as *u8, - a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, - a19: 0 as *u8, - a20: 0 as *u8, a21: 0 as *u8, - a22: uv_tcp_t_32bit_unix_riders { - a29: 0 as *u8, a30: 0 as *u8, a31: 0 as *u8, - }, - } - } - } - #[cfg(windows)] - pub fn gen_stub_os() -> uv_tcp_t { - uv_tcp_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, - a15: 0 as *u8, - a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, - a19: 0 as *u8, - a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8, - a23: 0 as *u8, - a24: 0 as *u8, a25: 0 as *u8, - } - } - #[cfg(target_os = "macos")] - pub fn gen_stub_os() -> uv_tcp_t { - use super::uv_tcp_t_osx_riders; - - return gen_stub_arch(); - - #[cfg(target_arch = "x86_64")] - fn gen_stub_arch() -> uv_tcp_t { - uv_tcp_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, - a15: 0 as *u8, - a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, - a19: 0 as *u8, - a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8, - a23: uv_tcp_t_osx_riders { - a23: 0 as *u8, - } - } - } - - #[cfg(target_arch = "x86")] - #[cfg(target_arch = "arm")] - fn gen_stub_arch() -> uv_tcp_t { - uv_tcp_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8, - a15: 0 as *u8, - a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8, - a19: 0 as *u8, - a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8, - a23: uv_tcp_t_osx_riders { - a23: 0 as *u8, - a24: 0 as *u8, a25: 0 as *u8, - } - } - } - } - } - #[cfg(unix)] - pub fn gen_stub_uv_connect_t() -> uv_connect_t { - uv_connect_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 - } - } - #[cfg(windows)] - pub fn gen_stub_uv_connect_t() -> uv_connect_t { - uv_connect_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, a09: 0 as *u8, a10: 0 as *u8, - } - } - #[cfg(unix)] - pub fn gen_stub_uv_async_t() -> uv_async_t { - return gen_stub_arch(); - #[cfg(target_arch = "x86_64")] - pub fn gen_stub_arch() -> uv_async_t { - uv_async_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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: uv_async_t_32bit_unix_riders { a10: 0 as *u8 }, - } - } - #[cfg(target_arch = "x86")] - #[cfg(target_arch="arm")] - #[cfg(target_arch="mips")] - pub fn gen_stub_arch() -> uv_async_t { - uv_async_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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: uv_async_t_32bit_unix_riders { - a10: 0 as *u8, - } - } - } - } - #[cfg(windows)] - pub fn gen_stub_uv_async_t() -> uv_async_t { - uv_async_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, - } - } - #[cfg(unix)] - pub fn gen_stub_uv_timer_t() -> uv_timer_t { - return gen_stub_arch(); - #[cfg(target_arch = "x86_64")] - pub fn gen_stub_arch() -> uv_timer_t { - uv_timer_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, - a11: uv_timer_t_32bit_unix_riders { - a10: 0 as *u8 - }, - } - } - #[cfg(target_arch = "x86")] - #[cfg(target_arch="arm")] - #[cfg(target_arch="mips")] - pub fn gen_stub_arch() -> uv_timer_t { - uv_timer_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, - a11: uv_timer_t_32bit_unix_riders { - a10: 0 as *u8, a11: 0 as *u8, - a12: 0 as *u8, - }, - } - } +#[test] +fn request_sanity_check() { + unsafe { + fail_unless!(UV_REQ_TYPE_MAX as uint == rust_uv_req_type_max()); } - #[cfg(windows)] - pub fn gen_stub_uv_timer_t() -> uv_timer_t { - uv_timer_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - } - } - #[cfg(unix)] - pub fn gen_stub_uv_write_t() -> uv_write_t { - return gen_stub_arch(); - #[cfg(target_arch="x86_64")] - pub fn gen_stub_arch() -> uv_write_t { - uv_write_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, - a14: uv_write_t_32bit_unix_riders { a13: 0 as *u8, - a14: 0 as *u8, - a15: 0 as *u8}, - } - } - #[cfg(target_arch="x86")] - #[cfg(target_arch="arm")] - #[cfg(target_arch="mips")] - pub fn gen_stub_arch() -> uv_write_t { - uv_write_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8, - a14: uv_write_t_32bit_unix_riders { - a13: 0 as *u8, - a14: 0 as *u8, - a15: 0 as *u8, - a16: 0 as *u8, - } - } - } - } - #[cfg(windows)] - pub fn gen_stub_uv_write_t() -> uv_write_t { - uv_write_t { - fields: uv_handle_fields { - loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - data: ptr::null(), - }, - 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, a09: 0 as *u8, a10: 0 as *u8, - a11: 0 as *u8, - a12: 0 as *u8 - } - } - pub fn gen_stub_uv_getaddrinfo_t() -> 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, a09: 0 as *u8, - a10: 1 as *u8, a11: 1 as *u8, a12: 1 as *u8, a13: 1 as *u8, - a14: 1 as *u8, a15: 1 as *u8 - } - } -} - -#[nolink] -extern mod rustrt { - - // libuv public API - unsafe fn rust_uv_loop_new() -> *libc::c_void; - unsafe fn rust_uv_loop_delete(lp: *libc::c_void); - unsafe fn rust_uv_run(loop_handle: *libc::c_void); - unsafe fn rust_uv_close(handle: *libc::c_void, cb: *u8); - unsafe fn rust_uv_walk(loop_handle: *libc::c_void, cb: *u8, - arg: *libc::c_void); - - unsafe fn rust_uv_idle_new() -> *uv_idle_t; - unsafe fn rust_uv_idle_delete(handle: *uv_idle_t); - unsafe fn rust_uv_idle_init(loop_handle: *uv_loop_t, - handle: *uv_idle_t) -> libc::c_int; - unsafe fn rust_uv_idle_start(handle: *uv_idle_t, - cb: uv_idle_cb) -> libc::c_int; - unsafe fn rust_uv_idle_stop(handle: *uv_idle_t) -> libc::c_int; - - unsafe fn rust_uv_async_send(handle: *uv_async_t); - unsafe fn rust_uv_async_init(loop_handle: *libc::c_void, - async_handle: *uv_async_t, - cb: *u8) -> libc::c_int; - unsafe fn rust_uv_tcp_init( - loop_handle: *libc::c_void, - handle_ptr: *uv_tcp_t) -> libc::c_int; - // FIXME ref #2604 .. ? - unsafe fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, - len: libc::size_t); - unsafe fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; - // FIXME ref #2064 - unsafe fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char; - // FIXME ref #2064 - unsafe fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char; - unsafe fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) - -> sockaddr_in; - unsafe fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int) - -> sockaddr_in6; - unsafe fn rust_uv_ip4_name(src: *sockaddr_in, - dst: *u8, - size: libc::size_t) - -> libc::c_int; - unsafe fn rust_uv_ip6_name(src: *sockaddr_in6, - dst: *u8, - size: libc::size_t) - -> libc::c_int; - unsafe fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint; - unsafe fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint; - // FIXME ref #2064 - unsafe fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, - tcp_handle_ptr: *uv_tcp_t, - ++after_cb: *u8, - ++addr: *sockaddr_in) -> libc::c_int; - // FIXME ref #2064 - unsafe fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, - ++addr: *sockaddr_in) -> libc::c_int; - // FIXME ref #2064 - unsafe 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 - unsafe fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, - ++addr: *sockaddr_in6) -> libc::c_int; - unsafe fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, - ++name: *sockaddr_in) -> libc::c_int; - unsafe fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, - ++name: *sockaddr_in6) ->libc::c_int; - unsafe fn rust_uv_listen(stream: *libc::c_void, - backlog: libc::c_int, - cb: *u8) -> libc::c_int; - unsafe fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) - -> libc::c_int; - unsafe fn rust_uv_write(req: *libc::c_void, - stream: *libc::c_void, - ++buf_in: *uv_buf_t, - buf_cnt: libc::c_int, - cb: *u8) - -> libc::c_int; - unsafe fn rust_uv_read_start(stream: *libc::c_void, - on_alloc: *u8, - on_read: *u8) - -> libc::c_int; - unsafe fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int; - unsafe fn rust_uv_timer_init(loop_handle: *libc::c_void, - timer_handle: *uv_timer_t) - -> libc::c_int; - unsafe fn rust_uv_timer_start( - timer_handle: *uv_timer_t, - cb: *u8, - timeout: libc::c_uint, - repeat: libc::c_uint) -> libc::c_int; - unsafe fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int; - - unsafe 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; - unsafe fn rust_uv_freeaddrinfo(res: *addrinfo); - - // data accessors/helpers for rust-mapped uv structs - unsafe fn rust_uv_helper_get_INADDR_NONE() -> u32; - unsafe fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool; - unsafe fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool; - unsafe fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo; - unsafe fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo) - -> *sockaddr_in; - unsafe fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo) - -> *sockaddr_in6; - unsafe fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; - unsafe fn rust_uv_free_base_of_buf(++buf: uv_buf_t); - unsafe fn rust_uv_get_stream_handle_from_connect_req( - connect_req: *uv_connect_t) - -> *uv_stream_t; - unsafe fn rust_uv_get_stream_handle_from_write_req( - write_req: *uv_write_t) - -> *uv_stream_t; - unsafe fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void) - -> *libc::c_void; - unsafe fn rust_uv_get_data_for_uv_loop(loop_ptr: *libc::c_void) - -> *libc::c_void; - unsafe fn rust_uv_set_data_for_uv_loop(loop_ptr: *libc::c_void, - data: *libc::c_void); - unsafe fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void) - -> *libc::c_void; - unsafe fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void, - data: *libc::c_void); - unsafe fn rust_uv_get_data_for_req(req: *libc::c_void) - -> *libc::c_void; - unsafe fn rust_uv_set_data_for_req(req: *libc::c_void, - data: *libc::c_void); - unsafe fn rust_uv_get_base_from_buf(++buf: uv_buf_t) -> *u8; - unsafe fn rust_uv_get_len_from_buf(++buf: uv_buf_t) -> libc::size_t; - - // sizeof testing helpers - unsafe fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_uv_write_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_uv_err_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; - unsafe fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint; - unsafe fn rust_uv_helper_uv_async_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint; - unsafe fn rust_uv_helper_addrinfo_size() -> libc::c_uint; - unsafe fn rust_uv_helper_addr_in_size() -> libc::c_uint; } -pub unsafe fn loop_new() -> *libc::c_void { - return rustrt::rust_uv_loop_new(); +pub unsafe fn loop_new() -> *c_void { + return rust_uv_loop_new(); } -pub unsafe fn loop_delete(loop_handle: *libc::c_void) { - rustrt::rust_uv_loop_delete(loop_handle); +pub unsafe fn loop_delete(loop_handle: *c_void) { + rust_uv_loop_delete(loop_handle); } -pub unsafe fn run(loop_handle: *libc::c_void) { - rustrt::rust_uv_run(loop_handle); +pub unsafe fn run(loop_handle: *c_void) { + rust_uv_run(loop_handle); } pub unsafe fn close(handle: *T, cb: *u8) { - rustrt::rust_uv_close(handle as *libc::c_void, cb); + rust_uv_close(handle as *c_void, cb); } -pub unsafe fn walk(loop_handle: *libc::c_void, cb: *u8, arg: *libc::c_void) { - rustrt::rust_uv_walk(loop_handle, cb, arg); +pub unsafe fn walk(loop_handle: *c_void, cb: *u8, arg: *c_void) { + rust_uv_walk(loop_handle, cb, arg); } pub unsafe fn idle_new() -> *uv_idle_t { - rustrt::rust_uv_idle_new() + rust_uv_idle_new() } pub unsafe fn idle_delete(handle: *uv_idle_t) { - rustrt::rust_uv_idle_delete(handle) + rust_uv_idle_delete(handle) } pub unsafe fn idle_init(loop_handle: *uv_loop_t, - handle: *uv_idle_t) -> libc::c_int { - rustrt::rust_uv_idle_init(loop_handle, handle) + handle: *uv_idle_t) -> c_int { + rust_uv_idle_init(loop_handle, handle) } -pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> libc::c_int { - rustrt::rust_uv_idle_start(handle, cb) +pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int { + rust_uv_idle_start(handle, cb) } -pub unsafe fn idle_stop(handle: *uv_idle_t) -> libc::c_int { - rustrt::rust_uv_idle_stop(handle) +pub unsafe fn idle_stop(handle: *uv_idle_t) -> c_int { + rust_uv_idle_stop(handle) } -pub unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t) - -> libc::c_int { - return rustrt::rust_uv_tcp_init(loop_handle, handle); +pub unsafe fn tcp_init(loop_handle: *c_void, handle: *uv_tcp_t) -> c_int { + return rust_uv_tcp_init(loop_handle, handle); } + // FIXME ref #2064 pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t, - tcp_handle_ptr: *uv_tcp_t, - addr_ptr: *sockaddr_in, - after_connect_cb: *u8) + tcp_handle_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in, + after_connect_cb: *u8) -> libc::c_int { - debug!("b4 foreign tcp_connect--addr port: %u cb: %u", - (*addr_ptr).sin_port as uint, after_connect_cb as uint); - return rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, - after_connect_cb, addr_ptr); + return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); } // FIXME ref #2064 pub 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 { - return rustrt::rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr, - after_connect_cb, addr_ptr); + tcp_handle_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in6, + after_connect_cb: *u8) -> c_int { + return rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); } // FIXME ref #2064 pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, - addr_ptr: *sockaddr_in) -> libc::c_int { - return rustrt::rust_uv_tcp_bind(tcp_server_ptr, + addr_ptr: *sockaddr_in) -> c_int { + return rust_uv_tcp_bind(tcp_server_ptr, addr_ptr); } // FIXME ref #2064 pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, - addr_ptr: *sockaddr_in6) -> libc::c_int { - return rustrt::rust_uv_tcp_bind6(tcp_server_ptr, + addr_ptr: *sockaddr_in6) -> c_int { + return rust_uv_tcp_bind6(tcp_server_ptr, addr_ptr); } pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, - name: *sockaddr_in) -> libc::c_int { - return rustrt::rust_uv_tcp_getpeername(tcp_handle_ptr, name); + name: *sockaddr_in) -> c_int { + return rust_uv_tcp_getpeername(tcp_handle_ptr, name); } pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, - name: *sockaddr_in6) ->libc::c_int { - return rustrt::rust_uv_tcp_getpeername6(tcp_handle_ptr, name); + name: *sockaddr_in6) ->c_int { + return rust_uv_tcp_getpeername6(tcp_handle_ptr, name); } -pub unsafe fn listen(stream: *T, backlog: libc::c_int, - cb: *u8) -> libc::c_int { - return rustrt::rust_uv_listen(stream as *libc::c_void, backlog, cb); +pub unsafe fn listen(stream: *T, backlog: c_int, + cb: *u8) -> c_int { + return rust_uv_listen(stream as *c_void, backlog, cb); } -pub unsafe fn accept(server: *libc::c_void, client: *libc::c_void) - -> libc::c_int { - return rustrt::rust_uv_accept(server as *libc::c_void, - client as *libc::c_void); +pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int { + return rust_uv_accept(server as *c_void, + client as *c_void); } pub unsafe fn write(req: *uv_write_t, stream: *T, - buf_in: *~[uv_buf_t], cb: *u8) -> libc::c_int { + buf_in: *~[uv_buf_t], cb: *u8) -> c_int { let buf_ptr = vec::raw::to_ptr(*buf_in); let buf_cnt = vec::len(*buf_in) as i32; - return rustrt::rust_uv_write(req as *libc::c_void, - stream as *libc::c_void, + return rust_uv_write(req as *c_void, + stream as *c_void, buf_ptr, buf_cnt, cb); } pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, - on_read: *u8) -> libc::c_int { - return rustrt::rust_uv_read_start(stream as *libc::c_void, + on_read: *u8) -> c_int { + return rust_uv_read_start(stream as *c_void, on_alloc, on_read); } -pub unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int { - return rustrt::rust_uv_read_stop(stream as *libc::c_void); +pub unsafe fn read_stop(stream: *uv_stream_t) -> c_int { + return rust_uv_read_stop(stream as *c_void); } -pub unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t { - return rustrt::rust_uv_last_error(loop_handle); +pub unsafe fn last_error(loop_handle: *c_void) -> uv_err_t { + return rust_uv_last_error(loop_handle); } -pub unsafe fn strerror(err: *uv_err_t) -> *libc::c_char { - return rustrt::rust_uv_strerror(err); +pub unsafe fn strerror(err: *uv_err_t) -> *c_char { + return rust_uv_strerror(err); } -pub unsafe fn err_name(err: *uv_err_t) -> *libc::c_char { - return rustrt::rust_uv_err_name(err); +pub unsafe fn err_name(err: *uv_err_t) -> *c_char { + return rust_uv_err_name(err); } -pub unsafe fn async_init(loop_handle: *libc::c_void, - async_handle: *uv_async_t, - cb: *u8) -> libc::c_int { - return rustrt::rust_uv_async_init(loop_handle, - async_handle, - cb); +pub unsafe fn async_init(loop_handle: *c_void, + async_handle: *uv_async_t, + cb: *u8) -> c_int { + return rust_uv_async_init(loop_handle, + async_handle, + cb); } pub unsafe fn async_send(async_handle: *uv_async_t) { - return rustrt::rust_uv_async_send(async_handle); + return rust_uv_async_send(async_handle); } pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { - let out_buf = uv_buf_t { base: ptr::null(), len: 0 as libc::size_t }; + let out_buf = uv_buf_t { base: ptr::null(), len: 0 as size_t }; let out_buf_ptr = ptr::addr_of(&out_buf); - debug!("buf_init - input %u len %u out_buf: %u", - input as uint, - len as uint, - out_buf_ptr as uint); - // yuck :/ - rustrt::rust_uv_buf_init(out_buf_ptr, input, len as size_t); - //let result = rustrt::rust_uv_buf_init_2(input, len as size_t); - debug!("after rust_uv_buf_init"); - let res_base = get_base_from_buf(out_buf); - let res_len = get_len_from_buf(out_buf); - //let res_base = get_base_from_buf(result); - debug!("buf_init - result %u len %u", - res_base as uint, - res_len as uint); + rust_uv_buf_init(out_buf_ptr, input, len as size_t); return out_buf; - //return result; -} -pub unsafe fn ip4_addr(ip: &str, port: int) --> sockaddr_in { - do str::as_c_str(ip) |ip_buf| { - rustrt::rust_uv_ip4_addr(ip_buf as *u8, - port as libc::c_int) - } -} -pub 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) - } -} -pub 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]; - do vec::as_imm_buf(dst) |dst_buf, size| { - rustrt::rust_uv_ip4_name(to_unsafe_ptr(src), - dst_buf, size as libc::size_t); - // 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::raw::from_buf(dst_buf) - } -} -pub 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]; - do vec::as_imm_buf(dst) |dst_buf, size| { - let src_unsafe_ptr = to_unsafe_ptr(src); - debug!("val of src *sockaddr_in6: %? sockaddr_in6: %?", - src_unsafe_ptr, src); - let result = rustrt::rust_uv_ip6_name(src_unsafe_ptr, - dst_buf, size as libc::size_t); - match result { - 0i32 => str::raw::from_buf(dst_buf), - _ => ~"" - } - } -} -pub unsafe fn ip4_port(src: &sockaddr_in) -> uint { - rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint -} -pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint { - rustrt::rust_uv_ip6_port(to_unsafe_ptr(src)) as uint } -pub unsafe fn timer_init(loop_ptr: *libc::c_void, - timer_ptr: *uv_timer_t) -> libc::c_int { - return rustrt::rust_uv_timer_init(loop_ptr, timer_ptr); +pub unsafe fn timer_init(loop_ptr: *c_void, + timer_ptr: *uv_timer_t) -> c_int { + return rust_uv_timer_init(loop_ptr, timer_ptr); } pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint, - repeat: uint) -> libc::c_int { - return rustrt::rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint, - repeat as libc::c_uint); + repeat: uint) -> c_int { + return rust_uv_timer_start(timer_ptr, cb, timeout as c_uint, + repeat as c_uint); } -pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int { - return rustrt::rust_uv_timer_stop(timer_ptr); -} -pub 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) -} -pub unsafe fn freeaddrinfo(res: *addrinfo) { - rustrt::rust_uv_freeaddrinfo(res); +pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> c_int { + return rust_uv_timer_stop(timer_ptr); } -// libuv struct initializers -pub unsafe fn tcp_t() -> uv_tcp_t { - return uv_ll_struct_stubgen::gen_stub_uv_tcp_t(); -} -pub unsafe fn connect_t() -> uv_connect_t { - return uv_ll_struct_stubgen::gen_stub_uv_connect_t(); -} -pub unsafe fn write_t() -> uv_write_t { - return uv_ll_struct_stubgen::gen_stub_uv_write_t(); +pub unsafe fn malloc_ip4_addr(ip: &str, port: int) +-> *sockaddr_in { + do str::as_c_str(ip) |ip_buf| { + rust_uv_ip4_addrp(ip_buf as *u8, + port as libc::c_int) + } } -pub unsafe fn async_t() -> uv_async_t { - return uv_ll_struct_stubgen::gen_stub_uv_async_t(); +pub unsafe fn malloc_ip6_addr(ip: &str, port: int) +-> *sockaddr_in6 { + do str::as_c_str(ip) |ip_buf| { + rust_uv_ip6_addrp(ip_buf as *u8, + port as libc::c_int) + } } -pub unsafe fn timer_t() -> uv_timer_t { - return uv_ll_struct_stubgen::gen_stub_uv_timer_t(); + +pub unsafe fn free_ip4_addr(addr: *sockaddr_in) { + rust_uv_free_ip4_addr(addr); } -pub unsafe fn getaddrinfo_t() -> uv_getaddrinfo_t { - return uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t(); + +pub unsafe fn free_ip6_addr(addr: *sockaddr_in6) { + rust_uv_free_ip6_addr(addr); } // data access helpers -pub unsafe fn get_loop_for_uv_handle(handle: *T) - -> *libc::c_void { - return rustrt::rust_uv_get_loop_for_uv_handle(handle as *libc::c_void); +pub unsafe fn get_loop_for_uv_handle(handle: *T) -> *c_void { + return rust_uv_get_loop_for_uv_handle(handle as *c_void); } pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) -> *uv_stream_t { - return rustrt::rust_uv_get_stream_handle_from_connect_req( + return rust_uv_get_stream_handle_from_connect_req( connect); } pub unsafe fn get_stream_handle_from_write_req( write_req: *uv_write_t) -> *uv_stream_t { - return rustrt::rust_uv_get_stream_handle_from_write_req( + return rust_uv_get_stream_handle_from_write_req( write_req); } -pub unsafe fn get_data_for_uv_loop(loop_ptr: *libc::c_void) -> *libc::c_void { - rustrt::rust_uv_get_data_for_uv_loop(loop_ptr) +pub unsafe fn get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void { + rust_uv_get_data_for_uv_loop(loop_ptr) } -pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void, - data: *libc::c_void) { - rustrt::rust_uv_set_data_for_uv_loop(loop_ptr, data); +pub unsafe fn set_data_for_uv_loop(loop_ptr: *c_void, + data: *c_void) { + rust_uv_set_data_for_uv_loop(loop_ptr, data); } -pub unsafe fn get_data_for_uv_handle(handle: *T) -> *libc::c_void { - return rustrt::rust_uv_get_data_for_uv_handle(handle as *libc::c_void); +pub unsafe fn get_data_for_uv_handle(handle: *T) -> *c_void { + return rust_uv_get_data_for_uv_handle(handle as *c_void); } pub unsafe fn set_data_for_uv_handle(handle: *T, data: *U) { - rustrt::rust_uv_set_data_for_uv_handle(handle as *libc::c_void, - data as *libc::c_void); + rust_uv_set_data_for_uv_handle(handle as *c_void, + data as *c_void); } -pub unsafe fn get_data_for_req(req: *T) -> *libc::c_void { - return rustrt::rust_uv_get_data_for_req(req as *libc::c_void); +pub unsafe fn get_data_for_req(req: *T) -> *c_void { + return rust_uv_get_data_for_req(req as *c_void); } pub unsafe fn set_data_for_req(req: *T, - data: *U) { - rustrt::rust_uv_set_data_for_req(req as *libc::c_void, - data as *libc::c_void); + data: *U) { + rust_uv_set_data_for_req(req as *c_void, + data as *c_void); } pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { - return rustrt::rust_uv_get_base_from_buf(buf); + return rust_uv_get_base_from_buf(buf); } -pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t { - return rustrt::rust_uv_get_len_from_buf(buf); +pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> size_t { + return rust_uv_get_len_from_buf(buf); } -pub unsafe fn malloc_buf_base_of(suggested_size: libc::size_t) - -> *u8 { - return rustrt::rust_uv_malloc_buf_base_of(suggested_size); +pub unsafe fn malloc_buf_base_of(suggested_size: size_t) -> *u8 { + return rust_uv_malloc_buf_base_of(suggested_size); } pub unsafe fn free_base_of_buf(buf: uv_buf_t) { - rustrt::rust_uv_free_base_of_buf(buf); + rust_uv_free_base_of_buf(buf); } -pub unsafe fn get_last_err_info(uv_loop: *libc::c_void) -> ~str { +pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str { let err = last_error(uv_loop); let err_ptr = ptr::addr_of(&err); let err_name = str::raw::from_c_str(err_name(err_ptr)); @@ -1219,721 +385,92 @@ pub struct uv_err_data { err_msg: ~str, } -pub unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool { - rustrt::rust_uv_is_ipv4_addrinfo(input) -} -pub unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool { - rustrt::rust_uv_is_ipv6_addrinfo(input) -} -pub unsafe fn get_INADDR_NONE() -> u32 { - rustrt::rust_uv_helper_get_INADDR_NONE() -} -pub unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo { - rustrt::rust_uv_get_next_addrinfo(input) -} -pub unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in { - rustrt::rust_uv_addrinfo_as_sockaddr_in(input) -} -pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 { - rustrt::rust_uv_addrinfo_as_sockaddr_in6(input) -} - -#[cfg(test)] -pub mod test { - use prelude::*; - use super::*; - use comm::{SharedChan, stream, GenericChan, GenericPort}; +extern { - enum tcp_read_data { - tcp_read_eof, - tcp_read_more(~[u8]), - tcp_read_error - } - - struct request_wrapper { - write_req: *uv_write_t, - req_buf: *~[uv_buf_t], - read_chan: SharedChan<~str>, - } + fn rust_uv_handle_size(type_: uintptr_t) -> size_t; + fn rust_uv_req_size(type_: uintptr_t) -> size_t; + fn rust_uv_handle_type_max() -> uintptr_t; + fn rust_uv_req_type_max() -> uintptr_t; - extern fn after_close_cb(handle: *libc::c_void) { - debug!("after uv_close! handle ptr: %?", - handle); - } - - extern fn on_alloc_cb(handle: *libc::c_void, - suggested_size: libc::size_t) - -> uv_buf_t { - unsafe { - debug!("on_alloc_cb!"); - let char_ptr = malloc_buf_base_of(suggested_size); - debug!("on_alloc_cb h: %? char_ptr: %u sugsize: %u", - handle, - char_ptr as uint, - suggested_size as uint); - return buf_init(char_ptr, suggested_size as uint); - } - } - - extern fn on_read_cb(stream: *uv_stream_t, - nread: libc::ssize_t, - ++buf: uv_buf_t) { - unsafe { - let nread = nread as int; - debug!("CLIENT entering on_read_cb nred: %d", - nread); - if (nread > 0) { - // we have data - debug!("CLIENT read: data! nread: %d", nread); - read_stop(stream); - let client_data = - get_data_for_uv_handle(stream as *libc::c_void) - as *request_wrapper; - let buf_base = get_base_from_buf(buf); - let bytes = vec::from_buf(buf_base, nread as uint); - let read_chan = (*client_data).read_chan.clone(); - let msg_from_server = str::from_bytes(bytes); - read_chan.send(msg_from_server); - close(stream as *libc::c_void, after_close_cb) - } - else if (nread == -1) { - // err .. possibly EOF - debug!("read: eof!"); - } - else { - // nread == 0 .. do nothing, just free buf as below - debug!("read: do nothing!"); - } - // when we're done - free_base_of_buf(buf); - debug!("CLIENT exiting on_read_cb"); - } - } - - extern fn on_write_complete_cb(write_req: *uv_write_t, - status: libc::c_int) { - unsafe { - debug!( - "CLIENT beginning on_write_complete_cb status: %d", - status as int); - let stream = get_stream_handle_from_write_req(write_req); - debug!( - "CLIENT on_write_complete_cb: tcp:%d write_handle:%d", - stream as int, write_req as int); - let result = read_start(stream, on_alloc_cb, on_read_cb); - debug!( - "CLIENT ending on_write_complete_cb .. status: %d", - result as int); - } - } - - extern fn on_connect_cb(connect_req_ptr: *uv_connect_t, - status: libc::c_int) { - unsafe { - debug!("beginning on_connect_cb .. status: %d", - status as int); - let stream = - get_stream_handle_from_connect_req(connect_req_ptr); - if (status == 0i32) { - debug!("on_connect_cb: in status=0 if.."); - let client_data = get_data_for_req( - connect_req_ptr as *libc::c_void) - as *request_wrapper; - let write_handle = (*client_data).write_req; - debug!("on_connect_cb: tcp: %d write_hdl: %d", - stream as int, write_handle as int); - let write_result = write(write_handle, - stream as *libc::c_void, - (*client_data).req_buf, - on_write_complete_cb); - debug!("on_connect_cb: write() status: %d", - write_result as int); - } - else { - let test_loop = get_loop_for_uv_handle( - stream as *libc::c_void); - let err_msg = get_last_err_info(test_loop); - debug!("%?", err_msg); - fail_unless!(false); - } - debug!("finishing on_connect_cb"); - } - } - - fn impl_uv_tcp_request(ip: &str, port: int, req_str: &str, - client_chan: SharedChan<~str>) { - unsafe { - let test_loop = loop_new(); - let tcp_handle = tcp_t(); - let tcp_handle_ptr = ptr::addr_of(&tcp_handle); - let connect_handle = connect_t(); - let connect_req_ptr = ptr::addr_of(&connect_handle); - - // this is the persistent payload of data that we - // need to pass around to get this example to work. - // In C, this would be a malloc'd or stack-allocated - // struct that we'd cast to a void* and store as the - // data field in our uv_connect_t struct - let req_str_bytes = str::to_bytes(req_str); - let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes); - debug!("req_msg ptr: %u", req_msg_ptr as uint); - let req_msg = ~[ - buf_init(req_msg_ptr, vec::len(req_str_bytes)) - ]; - // this is the enclosing record, we'll pass a ptr to - // this to C.. - let write_handle = write_t(); - let write_handle_ptr = ptr::addr_of(&write_handle); - debug!("tcp req: tcp stream: %d write_handle: %d", - tcp_handle_ptr as int, - write_handle_ptr as int); - let client_data = request_wrapper { - write_req: write_handle_ptr, - req_buf: ptr::addr_of(&req_msg), - read_chan: client_chan - }; - - let tcp_init_result = tcp_init( - test_loop as *libc::c_void, tcp_handle_ptr); - if (tcp_init_result == 0i32) { - debug!("sucessful tcp_init_result"); - - debug!("building addr..."); - let addr = ip4_addr(ip, port); - // FIXME ref #2064 - let addr_ptr = ptr::addr_of(&addr); - debug!("after build addr in rust. port: %u", - addr.sin_port as uint); - - // this should set up the connection request.. - debug!("b4 call tcp_connect connect cb: %u ", - on_connect_cb as uint); - let tcp_connect_result = tcp_connect( - connect_req_ptr, tcp_handle_ptr, - addr_ptr, on_connect_cb); - if (tcp_connect_result == 0i32) { - // not set the data on the connect_req - // until its initialized - set_data_for_req( - connect_req_ptr as *libc::c_void, - ptr::addr_of(&client_data) as *libc::c_void); - set_data_for_uv_handle( - tcp_handle_ptr as *libc::c_void, - ptr::addr_of(&client_data) as *libc::c_void); - debug!("before run tcp req loop"); - run(test_loop); - debug!("after run tcp req loop"); - } - else { - debug!("tcp_connect() failure"); - fail_unless!(false); - } - } - else { - debug!("tcp_init() failure"); - fail_unless!(false); - } - loop_delete(test_loop); - } - } - - extern fn server_after_close_cb(handle: *libc::c_void) { - unsafe { - debug!("SERVER server stream closed, should exit. h: %?", - handle); - } - } - - extern fn client_stream_after_close_cb(handle: *libc::c_void) { - unsafe { - debug!( - "SERVER: closed client stream, now closing server stream"); - let client_data = get_data_for_uv_handle( - handle) as - *tcp_server_data; - close((*client_data).server as *libc::c_void, - server_after_close_cb); - } - } - - extern fn after_server_resp_write(req: *uv_write_t) { - unsafe { - let client_stream_ptr = - get_stream_handle_from_write_req(req); - debug!("SERVER: resp sent... closing client stream"); - close(client_stream_ptr as *libc::c_void, - client_stream_after_close_cb) - } - } - - extern fn on_server_read_cb(client_stream_ptr: *uv_stream_t, - nread: libc::ssize_t, - ++buf: uv_buf_t) { - unsafe { - let nread = nread as int; - if (nread > 0) { - // we have data - debug!("SERVER read: data! nread: %d", nread); - - // pull out the contents of the write from the client - let buf_base = get_base_from_buf(buf); - let buf_len = get_len_from_buf(buf) as uint; - debug!("SERVER buf base: %u, len: %u, nread: %d", - buf_base as uint, - buf_len as uint, - nread); - let bytes = vec::from_buf(buf_base, nread as uint); - let request_str = str::from_bytes(bytes); - - let client_data = get_data_for_uv_handle( - client_stream_ptr as *libc::c_void) as *tcp_server_data; - - let server_kill_msg = copy (*client_data).server_kill_msg; - let write_req = (*client_data).server_write_req; - if str::contains(request_str, server_kill_msg) { - debug!("SERVER: client req contains kill_msg!"); - debug!("SERVER: sending response to client"); - read_stop(client_stream_ptr); - let server_chan = (*client_data).server_chan.clone(); - server_chan.send(request_str); - let write_result = write( - write_req, - client_stream_ptr as *libc::c_void, - (*client_data).server_resp_buf, - after_server_resp_write); - debug!("SERVER: resp write result: %d", - write_result as int); - if (write_result != 0i32) { - debug!("bad result for server resp write()"); - debug!("%s", get_last_err_info( - get_loop_for_uv_handle(client_stream_ptr - as *libc::c_void))); - fail_unless!(false); - } - } - else { - debug!("SERVER: client req !contain kill_msg!"); - } - } - else if (nread == -1) { - // err .. possibly EOF - debug!("read: eof!"); - } - else { - // nread == 0 .. do nothing, just free buf as below - debug!("read: do nothing!"); - } - // when we're done - free_base_of_buf(buf); - debug!("SERVER exiting on_read_cb"); - } - } - - extern fn server_connection_cb(server_stream_ptr: - *uv_stream_t, - status: libc::c_int) { - unsafe { - debug!("client connecting!"); - let test_loop = get_loop_for_uv_handle( - server_stream_ptr as *libc::c_void); - if status != 0i32 { - let err_msg = get_last_err_info(test_loop); - debug!("server_connect_cb: non-zero status: %?", - err_msg); - return; - } - let server_data = get_data_for_uv_handle( - server_stream_ptr as *libc::c_void) as *tcp_server_data; - let client_stream_ptr = (*server_data).client; - let client_init_result = tcp_init(test_loop, - client_stream_ptr); - set_data_for_uv_handle( - client_stream_ptr as *libc::c_void, - server_data as *libc::c_void); - if (client_init_result == 0i32) { - debug!("successfully initialized client stream"); - let accept_result = accept(server_stream_ptr as - *libc::c_void, - client_stream_ptr as - *libc::c_void); - if (accept_result == 0i32) { - // start reading - let read_result = read_start( - client_stream_ptr as *uv_stream_t, - on_alloc_cb, - on_server_read_cb); - if (read_result == 0i32) { - debug!("successful server read start"); - } - else { - debug!("server_connection_cb: bad read:%d", - read_result as int); - fail_unless!(false); - } - } - else { - debug!("server_connection_cb: bad accept: %d", - accept_result as int); - fail_unless!(false); - } - } - else { - debug!("server_connection_cb: bad client init: %d", - client_init_result as int); - fail_unless!(false); - } - } - } - - struct tcp_server_data { - client: *uv_tcp_t, - server: *uv_tcp_t, - server_kill_msg: ~str, - server_resp_buf: *~[uv_buf_t], - server_chan: SharedChan<~str>, - server_write_req: *uv_write_t, - } - - struct async_handle_data { - continue_chan: SharedChan, - } - - extern fn async_close_cb(handle: *libc::c_void) { - debug!("SERVER: closing async cb... h: %?", - handle); - } - - extern fn continue_async_cb(async_handle: *uv_async_t, - status: libc::c_int) { - unsafe { - // once we're in the body of this callback, - // the tcp server's loop is set up, so we - // can continue on to let the tcp client - // do its thang - let data = get_data_for_uv_handle( - async_handle as *libc::c_void) as *async_handle_data; - let continue_chan = (*data).continue_chan.clone(); - let should_continue = status == 0i32; - continue_chan.send(should_continue); - close(async_handle as *libc::c_void, async_close_cb); - } - } - - fn impl_uv_tcp_server(server_ip: &str, - server_port: int, - kill_server_msg: ~str, - server_resp_msg: ~str, - server_chan: SharedChan<~str>, - continue_chan: SharedChan) { - unsafe { - let test_loop = loop_new(); - let tcp_server = tcp_t(); - let tcp_server_ptr = ptr::addr_of(&tcp_server); - - let tcp_client = tcp_t(); - let tcp_client_ptr = ptr::addr_of(&tcp_client); - - let server_write_req = write_t(); - let server_write_req_ptr = ptr::addr_of(&server_write_req); - - let resp_str_bytes = str::to_bytes(server_resp_msg); - let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes); - debug!("resp_msg ptr: %u", resp_msg_ptr as uint); - let resp_msg = ~[ - buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) - ]; - - let continue_async_handle = async_t(); - let continue_async_handle_ptr = - ptr::addr_of(&continue_async_handle); - let async_data = - async_handle_data { continue_chan: continue_chan }; - let async_data_ptr = ptr::addr_of(&async_data); - - let server_data = tcp_server_data { - client: tcp_client_ptr, - server: tcp_server_ptr, - server_kill_msg: kill_server_msg, - server_resp_buf: ptr::addr_of(&resp_msg), - server_chan: server_chan, - server_write_req: server_write_req_ptr - }; - let server_data_ptr = ptr::addr_of(&server_data); - set_data_for_uv_handle(tcp_server_ptr as *libc::c_void, - server_data_ptr as *libc::c_void); - - // uv_tcp_init() - let tcp_init_result = tcp_init( - test_loop as *libc::c_void, tcp_server_ptr); - if (tcp_init_result == 0i32) { - let server_addr = ip4_addr(server_ip, server_port); - // FIXME ref #2064 - let server_addr_ptr = ptr::addr_of(&server_addr); - - // uv_tcp_bind() - let bind_result = tcp_bind(tcp_server_ptr, - server_addr_ptr); - if (bind_result == 0i32) { - debug!("successful uv_tcp_bind, listening"); - - // uv_listen() - let listen_result = listen(tcp_server_ptr as - *libc::c_void, - 128i32, - server_connection_cb); - if (listen_result == 0i32) { - // let the test know it can set up the tcp server, - // now.. this may still present a race, not sure.. - let async_result = async_init(test_loop, - continue_async_handle_ptr, - continue_async_cb); - if (async_result == 0i32) { - set_data_for_uv_handle( - continue_async_handle_ptr as *libc::c_void, - async_data_ptr as *libc::c_void); - async_send(continue_async_handle_ptr); - // uv_run() - run(test_loop); - debug!("server uv::run() has returned"); - } - else { - debug!("uv_async_init failure: %d", - async_result as int); - fail_unless!(false); - } - } - else { - debug!("non-zero result on uv_listen: %d", - listen_result as int); - fail_unless!(false); - } - } - else { - debug!("non-zero result on uv_tcp_bind: %d", - bind_result as int); - fail_unless!(false); - } - } - else { - debug!("non-zero result on uv_tcp_init: %d", - tcp_init_result as int); - fail_unless!(false); - } - loop_delete(test_loop); - } - } - - // this is the impl for a test that is (maybe) ran on a - // per-platform/arch basis below - pub fn impl_uv_tcp_server_and_request() { - unsafe { - let bind_ip = ~"0.0.0.0"; - let request_ip = ~"127.0.0.1"; - let port = 8886; - let kill_server_msg = ~"does a dog have buddha nature?"; - let server_resp_msg = ~"mu!"; - let (client_port, client_chan) = stream::<~str>(); - let client_chan = SharedChan(client_chan); - let (server_port, server_chan) = stream::<~str>(); - let server_chan = SharedChan(server_chan); - - let (continue_port, continue_chan) = stream::(); - let continue_chan = SharedChan(continue_chan); - - let kill_server_msg_copy = copy kill_server_msg; - let server_resp_msg_copy = copy server_resp_msg; - do task::spawn_sched(task::ManualThreads(1)) { - impl_uv_tcp_server(bind_ip, port, - copy kill_server_msg_copy, - copy server_resp_msg_copy, - server_chan.clone(), - continue_chan.clone()); - }; - - // block until the server up is.. possibly a race? - debug!("before receiving on server continue_port"); - continue_port.recv(); - debug!("received on continue port, set up tcp client"); - - let kill_server_msg_copy = copy kill_server_msg; - do task::spawn_sched(task::ManualThreads(1u)) { - impl_uv_tcp_request(request_ip, port, - kill_server_msg_copy, - client_chan.clone()); - }; - - let msg_from_client = server_port.recv(); - let msg_from_server = client_port.recv(); - - fail_unless!(str::contains(msg_from_client, kill_server_msg)); - fail_unless!(str::contains(msg_from_server, server_resp_msg)); - } - } - - // FIXME don't run on fbsd or linux 32 bit(#2064) - #[cfg(target_os="win32")] - #[cfg(target_os="darwin")] - #[cfg(target_os="linux")] - #[cfg(target_os="android")] - pub mod tcp_and_server_client_test { - #[cfg(target_arch="x86_64")] - pub mod impl64 { - #[test] - pub fn test_uv_ll_tcp_server_and_request() { - unsafe { - super::super::impl_uv_tcp_server_and_request(); - } - } - } - #[cfg(target_arch="x86")] - #[cfg(target_arch="arm")] - #[cfg(target_arch="mips")] - pub mod impl32 { - #[test] - #[ignore(cfg(target_os = "linux"))] - pub fn test_uv_ll_tcp_server_and_request() { - unsafe { - super::super::impl_uv_tcp_server_and_request(); - } - } - } - } - - fn struct_size_check_common(t_name: ~str, - foreign_size: libc::c_uint) { - unsafe { - let rust_size = sys::size_of::(); - let sizes_match = foreign_size as uint == rust_size; - if !sizes_match { - let output = fmt!( - "STRUCT_SIZE FAILURE: %s -- actual: %u expected: %u", - t_name, rust_size, foreign_size as uint); - debug!("%s", output); - } - fail_unless!(sizes_match); - } - } - - // struct size tests - #[test] - fn test_uv_ll_struct_size_uv_tcp_t() { - unsafe { - struct_size_check_common::( - ~"uv_tcp_t", - super::rustrt::rust_uv_helper_uv_tcp_t_size() - ); - } - } - #[test] - fn test_uv_ll_struct_size_uv_connect_t() { - unsafe { - struct_size_check_common::( - ~"uv_connect_t", - super::rustrt::rust_uv_helper_uv_connect_t_size() - ); - } - } - #[test] - fn test_uv_ll_struct_size_uv_buf_t() { - unsafe { - struct_size_check_common::( - ~"uv_buf_t", - super::rustrt::rust_uv_helper_uv_buf_t_size() - ); - } - } - #[test] - fn test_uv_ll_struct_size_uv_write_t() { - unsafe { - struct_size_check_common::( - ~"uv_write_t", - super::rustrt::rust_uv_helper_uv_write_t_size() - ); - } - } - - #[test] - fn test_uv_ll_struct_size_sockaddr_in() { - unsafe { - struct_size_check_common::( - ~"sockaddr_in", - super::rustrt::rust_uv_helper_sockaddr_in_size() - ); - } - } - #[test] - fn test_uv_ll_struct_size_sockaddr_in6() { - unsafe { - let foreign_handle_size = - super::rustrt::rust_uv_helper_sockaddr_in6_size(); - let rust_handle_size = sys::size_of::(); - let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u", - foreign_handle_size as uint, rust_handle_size); - 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 - fail_unless!((4u+foreign_handle_size as uint) == - rust_handle_size); - } - } - #[test] - #[ignore(reason = "questionable size calculations")] - fn test_uv_ll_struct_size_addr_in() { - unsafe { - let foreign_handle_size = - super::rustrt::rust_uv_helper_addr_in_size(); - let rust_handle_size = sys::size_of::(); - let output = fmt!("addr_in -- foreign: %u rust: %u", - foreign_handle_size as uint, rust_handle_size); - debug!(output); - // FIXME #1645 .. see note above about struct padding - fail_unless!((4u+foreign_handle_size as uint) == - rust_handle_size); - } - } - - #[test] - fn test_uv_ll_struct_size_uv_async_t() { - unsafe { - struct_size_check_common::( - ~"uv_async_t", - super::rustrt::rust_uv_helper_uv_async_t_size() - ); - } - } - - #[test] - fn test_uv_ll_struct_size_uv_timer_t() { - unsafe { - struct_size_check_common::( - ~"uv_timer_t", - super::rustrt::rust_uv_helper_uv_timer_t_size() - ); - } - } - - #[test] - #[ignore(cfg(target_os = "win32"))] - fn test_uv_ll_struct_size_uv_getaddrinfo_t() { - unsafe { - struct_size_check_common::( - ~"uv_getaddrinfo_t", - super::rustrt::rust_uv_helper_uv_getaddrinfo_t_size() - ); - } - } - #[test] - #[ignore(cfg(target_os = "macos"))] - #[ignore(cfg(target_os = "win32"))] - fn test_uv_ll_struct_size_addrinfo() { - unsafe { - struct_size_check_common::( - ~"addrinfo", - super::rustrt::rust_uv_helper_uv_timer_t_size() - ); - } - } + // libuv public API + fn rust_uv_loop_new() -> *c_void; + fn rust_uv_loop_delete(lp: *c_void); + fn rust_uv_run(loop_handle: *c_void); + fn rust_uv_close(handle: *c_void, cb: *u8); + fn rust_uv_walk(loop_handle: *c_void, cb: *u8, arg: *c_void); + + fn rust_uv_idle_new() -> *uv_idle_t; + fn rust_uv_idle_delete(handle: *uv_idle_t); + fn rust_uv_idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int; + fn rust_uv_idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int; + fn rust_uv_idle_stop(handle: *uv_idle_t) -> c_int; + + fn rust_uv_async_send(handle: *uv_async_t); + fn rust_uv_async_init(loop_handle: *c_void, + async_handle: *uv_async_t, + cb: *u8) -> c_int; + fn rust_uv_tcp_init(loop_handle: *c_void, handle_ptr: *uv_tcp_t) -> c_int; + // FIXME ref #2604 .. ? + fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, len: size_t); + fn rust_uv_last_error(loop_handle: *c_void) -> uv_err_t; + // FIXME ref #2064 + fn rust_uv_strerror(err: *uv_err_t) -> *c_char; + // FIXME ref #2064 + fn rust_uv_err_name(err: *uv_err_t) -> *c_char; + fn rust_uv_ip4_addrp(ip: *u8, port: c_int) -> *sockaddr_in; + fn rust_uv_ip6_addrp(ip: *u8, port: c_int) -> *sockaddr_in6; + fn rust_uv_free_ip4_addr(addr: *sockaddr_in); + fn rust_uv_free_ip6_addr(addr: *sockaddr_in6); + fn rust_uv_ip4_name(src: *sockaddr_in, dst: *u8, size: size_t) -> c_int; + fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: size_t) -> c_int; + fn rust_uv_ip4_port(src: *sockaddr_in) -> c_uint; + fn rust_uv_ip6_port(src: *sockaddr_in6) -> c_uint; + // FIXME ref #2064 + fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + ++after_cb: *u8, + ++addr: *sockaddr_in) -> c_int; + // FIXME ref #2064 + fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, ++addr: *sockaddr_in) -> 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) -> c_int; + // FIXME ref #2064 + fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, ++addr: *sockaddr_in6) -> c_int; + fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, ++name: *sockaddr_in) -> c_int; + fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, ++name: *sockaddr_in6) ->c_int; + fn rust_uv_listen(stream: *c_void, backlog: c_int, cb: *u8) -> c_int; + fn rust_uv_accept(server: *c_void, client: *c_void) -> c_int; + fn rust_uv_write(req: *c_void, + stream: *c_void, + ++buf_in: *uv_buf_t, + buf_cnt: c_int, + cb: *u8) -> c_int; + fn rust_uv_read_start(stream: *c_void, + on_alloc: *u8, + on_read: *u8) -> c_int; + fn rust_uv_read_stop(stream: *c_void) -> c_int; + fn rust_uv_timer_init(loop_handle: *c_void, + timer_handle: *uv_timer_t) -> c_int; + fn rust_uv_timer_start(timer_handle: *uv_timer_t, + cb: *u8, + timeout: c_uint, + repeat: c_uint) -> c_int; + fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int; + + fn rust_uv_malloc_buf_base_of(sug_size: size_t) -> *u8; + fn rust_uv_free_base_of_buf(++buf: uv_buf_t); + fn rust_uv_get_stream_handle_from_connect_req(connect_req: *uv_connect_t) -> *uv_stream_t; + fn rust_uv_get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t; + fn rust_uv_get_loop_for_uv_handle(handle: *c_void) -> *c_void; + fn rust_uv_get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void; + fn rust_uv_set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void); + fn rust_uv_get_data_for_uv_handle(handle: *c_void) -> *c_void; + fn rust_uv_set_data_for_uv_handle(handle: *c_void, data: *c_void); + fn rust_uv_get_data_for_req(req: *c_void) -> *c_void; + fn rust_uv_set_data_for_req(req: *c_void, data: *c_void); + fn rust_uv_get_base_from_buf(++buf: uv_buf_t) -> *u8; + fn rust_uv_get_len_from_buf(++buf: uv_buf_t) -> size_t; } diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 682939975ef28..b89441d055d77 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -930,8 +930,6 @@ pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t, addr_ptr: *sockaddr_in, after_connect_cb: *u8) -> libc::c_int { - log(debug, fmt!("b4 foreign tcp_connect--addr port: %u cb: %u", - (*addr_ptr).sin_port as uint, after_connect_cb as uint)); return rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr); } @@ -1021,22 +1019,8 @@ pub unsafe fn async_send(async_handle: *uv_async_t) { pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { let out_buf = uv_buf_t { base: ptr::null(), len: 0 as libc::size_t }; let out_buf_ptr = ptr::addr_of(&out_buf); - log(debug, fmt!("buf_init - input %u len %u out_buf: %u", - input as uint, - len as uint, - out_buf_ptr as uint)); - // yuck :/ rustrt::rust_uv_buf_init(out_buf_ptr, input, len as size_t); - //let result = rustrt::rust_uv_buf_init_2(input, len as size_t); - log(debug, ~"after rust_uv_buf_init"); - let res_base = get_base_from_buf(out_buf); - let res_len = get_len_from_buf(out_buf); - //let res_base = get_base_from_buf(result); - log(debug, fmt!("buf_init - result %u len %u", - res_base as uint, - res_len as uint)); return out_buf; - //return result; } pub unsafe fn ip4_addr(ip: &str, port: int) -> sockaddr_in { @@ -1078,8 +1062,6 @@ pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str { 0u8,0u8,0u8,0u8,0u8,0u8]; do vec::as_imm_buf(dst) |dst_buf, size| { let src_unsafe_ptr = to_unsafe_ptr(src); - 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 as libc::size_t); match result { diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 5159434873733..325b10b92df6b 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -479,6 +479,34 @@ extern "C" struct sockaddr_in6 rust_uv_ip6_addr(const char* ip, int port) { return uv_ip6_addr(ip, port); } + +extern "C" struct sockaddr_in* +rust_uv_ip4_addrp(const char* ip, int port) { + struct sockaddr_in addr = uv_ip4_addr(ip, port); + struct sockaddr_in *addrp = (sockaddr_in*)malloc(sizeof(struct sockaddr_in)); + assert(addrp); + memcpy(addrp, &addr, sizeof(struct sockaddr_in)); + return addrp; +} +extern "C" struct sockaddr_in6* +rust_uv_ip6_addrp(const char* ip, int port) { + struct sockaddr_in6 addr = uv_ip6_addr(ip, port); + struct sockaddr_in6 *addrp = (sockaddr_in6*)malloc(sizeof(struct sockaddr_in6)); + assert(addrp); + memcpy(addrp, &addr, sizeof(struct sockaddr_in6)); + return addrp; +} + +extern "C" void +rust_uv_free_ip4_addr(sockaddr_in *addrp) { + free(addrp); +} + +extern "C" void +rust_uv_free_ip6_addr(sockaddr_in6 *addrp) { + free(addrp); +} + extern "C" int rust_uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) { return uv_ip4_name(src, dst, size); @@ -563,3 +591,23 @@ extern "C" int rust_uv_idle_stop(uv_idle_t* idle) { return uv_idle_stop(idle); } + +extern "C" size_t +rust_uv_handle_size(uintptr_t type) { + return uv_handle_size((uv_handle_type)type); +} + +extern "C" size_t +rust_uv_req_size(uintptr_t type) { + return uv_req_size((uv_req_type)type); +} + +extern "C" uintptr_t +rust_uv_handle_type_max() { + return UV_HANDLE_TYPE_MAX; +} + +extern "C" uintptr_t +rust_uv_req_type_max() { + return UV_REQ_TYPE_MAX; +} diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 5a8868f33f9f9..4fde952ba9565 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -202,3 +202,12 @@ rust_dbg_extern_identity_TwoU64s rust_dbg_extern_identity_double rust_dbg_extern_identity_u8 rust_get_rt_env +rust_uv_handle_size +rust_uv_req_size +rust_uv_handle_type_max +rust_uv_req_type_max +rust_uv_ip4_addrp +rust_uv_ip6_addrp +rust_uv_free_ip4_addr +rust_uv_free_ip6_addr + From 42cba98509c6da6e7f99d1d8c87f3051cb9598d4 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 13 Mar 2013 17:58:23 -0700 Subject: [PATCH 05/12] core: Convert some multiline statements to single-line --- src/libcore/rt/context.rs | 15 ++---- src/libcore/rt/sched.rs | 14 +++--- src/libcore/rt/uv.rs | 62 ++++++++---------------- src/libcore/rt/uvio.rs | 12 ++--- src/libcore/rt/uvll.rs | 99 +++++++++++++-------------------------- 5 files changed, 67 insertions(+), 135 deletions(-) diff --git a/src/libcore/rt/context.rs b/src/libcore/rt/context.rs index 11512c3fe7acb..55ea2eb3f5097 100644 --- a/src/libcore/rt/context.rs +++ b/src/libcore/rt/context.rs @@ -54,8 +54,7 @@ pub impl Context { // which we will then modify to call the given function when restored let mut regs = new_regs(); unsafe { - swap_registers(transmute_mut_region(&mut *regs), - transmute_region(&*regs)) + swap_registers(transmute_mut_region(&mut *regs), transmute_region(&*regs)) }; initialize_call_frame(&mut *regs, fp, argp, sp); @@ -107,8 +106,7 @@ fn new_regs() -> ~Registers { } #[cfg(target_arch = "x86")] -fn initialize_call_frame(regs: &mut Registers, - fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { let sp = align_down(sp); let sp = mut_offset(sp, -4); @@ -131,8 +129,7 @@ type Registers = [uint * 22]; fn new_regs() -> ~Registers { ~[0, .. 22] } #[cfg(target_arch = "x86_64")] -fn initialize_call_frame(regs: &mut Registers, - fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { // Redefinitions from regs.h const RUSTRT_ARG0: uint = 3; @@ -166,8 +163,7 @@ type Registers = [uint * 32]; fn new_regs() -> ~Registers { ~[0, .. 32] } #[cfg(target_arch = "arm")] -fn initialize_call_frame(regs: &mut Registers, - fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { let sp = mut_offset(sp, -1); // The final return address. 0 indicates the bottom of the stack @@ -185,8 +181,7 @@ type Registers = [uint * 32]; fn new_regs() -> ~Registers { ~[0, .. 32] } #[cfg(target_arch = "mips")] -fn initialize_call_frame(regs: &mut Registers, - fptr: *c_void, arg: *c_void, sp: *mut uint) { +fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { let sp = mut_offset(sp, -1); // The final return address. 0 indicates the bottom of the stack diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index ff0b3d28e8d70..74867dd7f1224 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -183,8 +183,7 @@ pub impl Scheduler { let blocked_task = self.current_task.swap_unwrap(); let f_fake_region = unsafe { - transmute::<&fn(&mut Scheduler, ~Task), - &fn(&mut Scheduler, ~Task)>(f) + transmute::<&fn(&mut Scheduler, ~Task), &fn(&mut Scheduler, ~Task)>(f) }; let f_opaque = HackAroundBorrowCk::from_fn(f_fake_region); self.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); @@ -233,8 +232,7 @@ pub impl Scheduler { Context::swap(task_context, scheduler_context); } - priv fn swap_in_task_from_running_task(&mut self, - running_task: &mut Task) { + priv fn swap_in_task_from_running_task(&mut self, running_task: &mut Task) { let running_task_context = &mut running_task.saved_context; let next_context = &self.current_task.get_ref().saved_context; Context::swap(running_task_context, next_context); @@ -344,8 +342,7 @@ impl ThreadLocalScheduler { fn put_scheduler(&mut self, scheduler: ~Scheduler) { unsafe { let key = match self { &ThreadLocalScheduler(key) => key }; - let value: *mut c_void = - transmute::<~Scheduler, *mut c_void>(scheduler); + let value: *mut c_void = transmute::<~Scheduler, *mut c_void>(scheduler); tls::set(key, value); } } @@ -357,8 +354,9 @@ impl ThreadLocalScheduler { fail_unless!(value.is_not_null()); { let value_ptr = &mut value; - let sched: &mut ~Scheduler = - transmute::<&mut *mut c_void, &mut ~Scheduler>(value_ptr); + let sched: &mut ~Scheduler = { + transmute::<&mut *mut c_void, &mut ~Scheduler>(value_ptr) + }; let sched: &mut Scheduler = &mut **sched; return sched; } diff --git a/src/libcore/rt/uv.rs b/src/libcore/rt/uv.rs index 8280359eb2bfc..3bbd54b306f84 100644 --- a/src/libcore/rt/uv.rs +++ b/src/libcore/rt/uv.rs @@ -157,10 +157,8 @@ pub impl IdleWatcher { }; extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) { - let idle_watcher: IdleWatcher = - NativeHandle::from_native_handle(handle); - let cb: &IdleCallback = - borrow_callback_from_watcher(&idle_watcher); + let idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle); + let cb: &IdleCallback = borrow_callback_from_watcher(&idle_watcher); let status = status_to_maybe_uv_error(handle, status); (*cb)(idle_watcher, status); } @@ -175,9 +173,7 @@ pub impl IdleWatcher { extern fn close_cb(handle: *uvll::uv_idle_t) { let mut idle_watcher = NativeHandle::from_native_handle(handle); - drop_watcher_callback::(&mut idle_watcher); + drop_watcher_callback::(&mut idle_watcher); unsafe { uvll::idle_delete(handle) }; } } @@ -220,21 +216,17 @@ pub impl StreamWatcher { let handle = self.native_handle(); unsafe { uvll::read_start(handle, alloc_cb, read_cb); } - extern fn alloc_cb(stream: *uvll::uv_stream_t, - suggested_size: size_t) -> Buf { - let mut stream_watcher: StreamWatcher = - NativeHandle::from_native_handle(stream); + extern fn alloc_cb(stream: *uvll::uv_stream_t, suggested_size: size_t) -> Buf { + let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream); let data = get_watcher_data(&mut stream_watcher); let alloc_cb = data.alloc_cb.get_ref(); return (*alloc_cb)(suggested_size as uint); } - extern fn read_cb(stream: *uvll::uv_stream_t, - nread: ssize_t, ++buf: Buf) { + extern fn read_cb(stream: *uvll::uv_stream_t, nread: ssize_t, ++buf: Buf) { rtdebug!("buf addr: %x", buf.base as uint); rtdebug!("buf len: %d", buf.len as int); - let mut stream_watcher: StreamWatcher = - NativeHandle::from_native_handle(stream); + let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream); let data = get_watcher_data(&mut stream_watcher); let cb = data.read_cb.get_ref(); let status = status_to_maybe_uv_error(stream, nread as c_int); @@ -270,14 +262,11 @@ pub impl StreamWatcher { let _v = vec_from_uv_buf(buf); extern fn write_cb(req: *uvll::uv_write_t, status: c_int) { - let write_request: WriteRequest = - NativeHandle::from_native_handle(req); + let write_request: WriteRequest = NativeHandle::from_native_handle(req); let mut stream_watcher = write_request.stream(); write_request.delete(); - let cb = get_watcher_data(&mut stream_watcher) - .write_cb.swap_unwrap(); - let status = status_to_maybe_uv_error( - stream_watcher.native_handle(), status); + let cb = get_watcher_data(&mut stream_watcher).write_cb.swap_unwrap(); + let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status); cb(stream_watcher, status); } } @@ -301,8 +290,7 @@ pub impl StreamWatcher { unsafe { uvll::close(self.native_handle(), close_cb); } extern fn close_cb(handle: *uvll::uv_stream_t) { - let mut stream_watcher: StreamWatcher = - NativeHandle::from_native_handle(handle); + let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle); { let mut data = get_watcher_data(&mut stream_watcher); data.close_cb.swap_unwrap()(); @@ -382,16 +370,14 @@ pub impl TcpWatcher { extern fn connect_cb(req: *uvll::uv_connect_t, status: c_int) { rtdebug!("connect_t: %x", req as uint); - let connect_request: ConnectRequest = - NativeHandle::from_native_handle(req); + let connect_request: ConnectRequest = NativeHandle::from_native_handle(req); let mut stream_watcher = connect_request.stream(); connect_request.delete(); let cb: ConnectionCallback = { let data = get_watcher_data(&mut stream_watcher); data.connect_cb.swap_unwrap() }; - let status = status_to_maybe_uv_error( - stream_watcher.native_handle(), status); + let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status); cb(stream_watcher, status); } } @@ -412,19 +398,15 @@ pub impl TcpWatcher { extern fn connection_cb(handle: *uvll::uv_stream_t, status: c_int) { rtdebug!("connection_cb"); - let mut stream_watcher: StreamWatcher = - NativeHandle::from_native_handle(handle); - let cb = get_watcher_data(&mut stream_watcher) - .connect_cb.swap_unwrap(); - let status = status_to_maybe_uv_error( - stream_watcher.native_handle(), status); + let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle); + let cb = get_watcher_data(&mut stream_watcher).connect_cb.swap_unwrap(); + let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status); cb(stream_watcher, status); } } fn as_stream(&self) -> StreamWatcher { - NativeHandle::from_native_handle( - self.native_handle() as *uvll::uv_stream_t) + NativeHandle::from_native_handle(self.native_handle() as *uvll::uv_stream_t) } } @@ -460,9 +442,7 @@ impl ConnectRequest { fn stream(&self) -> StreamWatcher { unsafe { - let stream_handle = - uvll::get_stream_handle_from_connect_req( - self.native_handle()); + let stream_handle = uvll::get_stream_handle_from_connect_req(self.native_handle()); NativeHandle::from_native_handle(stream_handle) } } @@ -499,8 +479,7 @@ impl WriteRequest { fn stream(&self) -> StreamWatcher { unsafe { - let stream_handle = - uvll::get_stream_handle_from_write_req(self.native_handle()); + let stream_handle = uvll::get_stream_handle_from_write_req(self.native_handle()); NativeHandle::from_native_handle(stream_handle) } } @@ -609,8 +588,7 @@ fn drop_watcher_callback, CB: Callback>( // Take ownership of the callback and drop it let _cb = transmute::<*c_void, ~CB>(handle_data); // Make sure the pointer is zeroed - uvll::set_data_for_uv_handle( - watcher.native_handle(), null::<()>()); + uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>()); } } } diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index f7275652e7f39..53156ccc73d1f 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -189,12 +189,9 @@ impl TcpListener for UvTcpListener { do server_tcp_watcher.listen |server_stream_watcher, status| { let maybe_stream = if status.is_none() { let mut server_stream_watcher = server_stream_watcher; - let mut loop_ = - loop_from_watcher(&server_stream_watcher); - let mut client_tcp_watcher = - TcpWatcher::new(&mut loop_); - let mut client_tcp_watcher = - client_tcp_watcher.as_stream(); + let mut loop_ = loop_from_watcher(&server_stream_watcher); + let mut client_tcp_watcher = TcpWatcher::new(&mut loop_); + let mut client_tcp_watcher = client_tcp_watcher.as_stream(); // XXX: Need's to be surfaced in interface server_stream_watcher.accept(client_tcp_watcher); Some(~UvStream::new(client_tcp_watcher)) @@ -425,8 +422,7 @@ fn test_read_and_block() { // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it - do scheduler.block_running_task_and_then - |scheduler, task| { + do scheduler.block_running_task_and_then |scheduler, task| { scheduler.task_queue.push_back(task); } } diff --git a/src/libcore/rt/uvll.rs b/src/libcore/rt/uvll.rs index 1332ddf112732..3606c9f4dd651 100644 --- a/src/libcore/rt/uvll.rs +++ b/src/libcore/rt/uvll.rs @@ -162,8 +162,7 @@ pub unsafe fn idle_delete(handle: *uv_idle_t) { rust_uv_idle_delete(handle) } -pub unsafe fn idle_init(loop_handle: *uv_loop_t, - handle: *uv_idle_t) -> c_int { +pub unsafe fn idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int { rust_uv_idle_init(loop_handle, handle) } @@ -183,8 +182,7 @@ pub unsafe fn tcp_init(loop_handle: *c_void, handle: *uv_tcp_t) -> c_int { pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in, - after_connect_cb: *u8) --> libc::c_int { + after_connect_cb: *u8) -> c_int { return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr); } @@ -197,50 +195,37 @@ pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t, after_connect_cb, addr_ptr); } // FIXME ref #2064 -pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, - addr_ptr: *sockaddr_in) -> c_int { - return rust_uv_tcp_bind(tcp_server_ptr, - addr_ptr); +pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in) -> c_int { + return rust_uv_tcp_bind(tcp_server_ptr, addr_ptr); } // FIXME ref #2064 -pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, - addr_ptr: *sockaddr_in6) -> c_int { - return rust_uv_tcp_bind6(tcp_server_ptr, - addr_ptr); +pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in6) -> c_int { + return rust_uv_tcp_bind6(tcp_server_ptr, addr_ptr); } -pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, - name: *sockaddr_in) -> c_int { +pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in) -> c_int { return rust_uv_tcp_getpeername(tcp_handle_ptr, name); } -pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, - name: *sockaddr_in6) ->c_int { +pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in6) ->c_int { return rust_uv_tcp_getpeername6(tcp_handle_ptr, name); } -pub unsafe fn listen(stream: *T, backlog: c_int, - cb: *u8) -> c_int { +pub unsafe fn listen(stream: *T, backlog: c_int, cb: *u8) -> c_int { return rust_uv_listen(stream as *c_void, backlog, cb); } pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int { - return rust_uv_accept(server as *c_void, - client as *c_void); + return rust_uv_accept(server as *c_void, client as *c_void); } -pub unsafe fn write(req: *uv_write_t, stream: *T, - buf_in: *~[uv_buf_t], cb: *u8) -> c_int { +pub unsafe fn write(req: *uv_write_t, stream: *T, buf_in: *~[uv_buf_t], cb: *u8) -> c_int { let buf_ptr = vec::raw::to_ptr(*buf_in); let buf_cnt = vec::len(*buf_in) as i32; - return rust_uv_write(req as *c_void, - stream as *c_void, - buf_ptr, buf_cnt, cb); + return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb); } -pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, - on_read: *u8) -> c_int { - return rust_uv_read_start(stream as *c_void, - on_alloc, on_read); +pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, on_read: *u8) -> c_int { + return rust_uv_read_start(stream as *c_void, on_alloc, on_read); } pub unsafe fn read_stop(stream: *uv_stream_t) -> c_int { @@ -258,12 +243,8 @@ pub unsafe fn err_name(err: *uv_err_t) -> *c_char { return rust_uv_err_name(err); } -pub unsafe fn async_init(loop_handle: *c_void, - async_handle: *uv_async_t, - cb: *u8) -> c_int { - return rust_uv_async_init(loop_handle, - async_handle, - cb); +pub unsafe fn async_init(loop_handle: *c_void, async_handle: *uv_async_t, cb: *u8) -> c_int { + return rust_uv_async_init(loop_handle, async_handle, cb); } pub unsafe fn async_send(async_handle: *uv_async_t) { @@ -276,31 +257,25 @@ pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { return out_buf; } -pub unsafe fn timer_init(loop_ptr: *c_void, - timer_ptr: *uv_timer_t) -> c_int { +pub unsafe fn timer_init(loop_ptr: *c_void, timer_ptr: *uv_timer_t) -> c_int { return rust_uv_timer_init(loop_ptr, timer_ptr); } pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint, repeat: uint) -> c_int { - return rust_uv_timer_start(timer_ptr, cb, timeout as c_uint, - repeat as c_uint); + return rust_uv_timer_start(timer_ptr, cb, timeout as c_uint, repeat as c_uint); } pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> c_int { return rust_uv_timer_stop(timer_ptr); } -pub unsafe fn malloc_ip4_addr(ip: &str, port: int) --> *sockaddr_in { +pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in { do str::as_c_str(ip) |ip_buf| { - rust_uv_ip4_addrp(ip_buf as *u8, - port as libc::c_int) + rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int) } } -pub unsafe fn malloc_ip6_addr(ip: &str, port: int) --> *sockaddr_in6 { +pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 { do str::as_c_str(ip) |ip_buf| { - rust_uv_ip6_addrp(ip_buf as *u8, - port as libc::c_int) + rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int) } } @@ -316,39 +291,29 @@ pub unsafe fn free_ip6_addr(addr: *sockaddr_in6) { pub unsafe fn get_loop_for_uv_handle(handle: *T) -> *c_void { return rust_uv_get_loop_for_uv_handle(handle as *c_void); } -pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) - -> *uv_stream_t { - return rust_uv_get_stream_handle_from_connect_req( - connect); +pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) -> *uv_stream_t { + return rust_uv_get_stream_handle_from_connect_req(connect); } -pub unsafe fn get_stream_handle_from_write_req( - write_req: *uv_write_t) - -> *uv_stream_t { - return rust_uv_get_stream_handle_from_write_req( - write_req); +pub unsafe fn get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t { + return rust_uv_get_stream_handle_from_write_req(write_req); } pub unsafe fn get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void { rust_uv_get_data_for_uv_loop(loop_ptr) } -pub unsafe fn set_data_for_uv_loop(loop_ptr: *c_void, - data: *c_void) { +pub unsafe fn set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void) { rust_uv_set_data_for_uv_loop(loop_ptr, data); } pub unsafe fn get_data_for_uv_handle(handle: *T) -> *c_void { return rust_uv_get_data_for_uv_handle(handle as *c_void); } -pub unsafe fn set_data_for_uv_handle(handle: *T, - data: *U) { - rust_uv_set_data_for_uv_handle(handle as *c_void, - data as *c_void); +pub unsafe fn set_data_for_uv_handle(handle: *T, data: *U) { + rust_uv_set_data_for_uv_handle(handle as *c_void, data as *c_void); } pub unsafe fn get_data_for_req(req: *T) -> *c_void { return rust_uv_get_data_for_req(req as *c_void); } -pub unsafe fn set_data_for_req(req: *T, - data: *U) { - rust_uv_set_data_for_req(req as *c_void, - data as *c_void); +pub unsafe fn set_data_for_req(req: *T, data: *U) { + rust_uv_set_data_for_req(req as *c_void, data as *c_void); } pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { return rust_uv_get_base_from_buf(buf); @@ -372,7 +337,7 @@ pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str { err_name, err_msg); } -pub unsafe fn get_last_err_data(uv_loop: *libc::c_void) -> uv_err_data { +pub unsafe fn get_last_err_data(uv_loop: *c_void) -> uv_err_data { let err = last_error(uv_loop); let err_ptr = ptr::addr_of(&err); let err_name = str::raw::from_c_str(err_name(err_ptr)); From 9a075f264a1024a3c03edc033be59971ad590171 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 13 Mar 2013 18:21:47 -0700 Subject: [PATCH 06/12] core: Rename rt::io to rt::rtio This is an internal interface. I want to use rt::io for public interfaces. --- src/libcore/rt/mod.rs | 2 +- src/libcore/rt/{io.rs => rtio.rs} | 0 src/libcore/rt/sched.rs | 2 +- src/libcore/rt/uv.rs | 2 +- src/libcore/rt/uvio.rs | 4 +--- 5 files changed, 4 insertions(+), 6 deletions(-) rename src/libcore/rt/{io.rs => rtio.rs} (100%) diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 556431e931534..bc0efc01fbb75 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -30,7 +30,7 @@ macro_rules! rtdebug ( ) mod sched; -mod io; +mod rtio; pub mod uvll; mod uvio; mod uv; diff --git a/src/libcore/rt/io.rs b/src/libcore/rt/rtio.rs similarity index 100% rename from src/libcore/rt/io.rs rename to src/libcore/rt/rtio.rs diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 74867dd7f1224..f47f86fd5fde6 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -16,7 +16,7 @@ use ptr::mut_null; use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; -use super::io::{EventLoop, EventLoopObject}; +use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; use tls = super::thread_local_storage; diff --git a/src/libcore/rt/uv.rs b/src/libcore/rt/uv.rs index 3bbd54b306f84..cc9e2fe8a7a82 100644 --- a/src/libcore/rt/uv.rs +++ b/src/libcore/rt/uv.rs @@ -45,7 +45,7 @@ use ptr::null; use sys::size_of; use super::uvll; use super::uvll::*; -use super::io::{IpAddr, Ipv4, Ipv6}; +use super::rtio::{IpAddr, Ipv4, Ipv6}; use unstable::finally::Finally; #[cfg(test)] use unstable::run_in_bare_thread; diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index 53156ccc73d1f..1806da55efa74 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -12,13 +12,11 @@ use option::*; use result::*; use super::uv::*; -use super::io::*; +use super::rtio::*; use ops::Drop; use cell::{Cell, empty_cell}; use cast::transmute; -use super::StreamObject; use super::sched::Scheduler; -use super::IoFactoryObject; #[cfg(test)] use super::sched::Task; #[cfg(test)] use unstable::run_in_bare_thread; From 5e6dacf32edc5b8529e6f0aafd17754d0e2e2284 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 14 Mar 2013 15:37:38 -0700 Subject: [PATCH 07/12] mk: If NO_REBUILD is set then don't rebuild core/std before testing Can make turnaround of testing changes to core/std/syntax much faster. --- mk/tests.mk | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/mk/tests.mk b/mk/tests.mk index 33a828d6e6785..f96b7325f60d4 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -244,21 +244,29 @@ $(foreach host,$(CFG_HOST_TRIPLES), \ define TEST_RUNNER +# If NO_REBUILD is set then break the dependencies on std so we can +# test crates without rebuilding core and std first +ifeq ($(NO_REBUILD),) +STDTESTDEP_$(1)_$(2)_$(3) = $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2)) +else +STDTESTDEP_$(1)_$(2)_$(3) = +endif + $(3)/test/coretest.stage$(1)-$(2)$$(X_$(2)): \ $$(CORELIB_CRATE) $$(CORELIB_INPUTS) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2)) + $$(STDTESTDEP_$(1)_$(2)_$(3)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test $(3)/test/stdtest.stage$(1)-$(2)$$(X_$(2)): \ $$(STDLIB_CRATE) $$(STDLIB_INPUTS) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2)) + $$(STDTESTDEP_$(1)_$(2)_$(3)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test $(3)/test/syntaxtest.stage$(1)-$(2)$$(X_$(2)): \ $$(LIBSYNTAX_CRATE) $$(LIBSYNTAX_INPUTS) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2)) + $$(STDTESTDEP_$(1)_$(2)_$(3)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test From 57e85b5f947387195cec1338fcb94b7cfb88bd86 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 13 Mar 2013 20:02:48 -0700 Subject: [PATCH 08/12] core: Add rt::io and start sketching the API --- Makefile.in | 2 +- src/libcore/rt/io/file.rs | 45 +++++++++++++++++++++++++++++++++++++++ src/libcore/rt/io/mod.rs | 45 +++++++++++++++++++++++++++++++++++++++ src/libcore/rt/mod.rs | 2 ++ 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 src/libcore/rt/io/file.rs create mode 100644 src/libcore/rt/io/mod.rs diff --git a/Makefile.in b/Makefile.in index 268a25d72fc19..dd2e6a95861bd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -238,7 +238,7 @@ $(foreach target,$(CFG_TARGET_TRIPLES),\ CORELIB_CRATE := $(S)src/libcore/core.rc CORELIB_INPUTS := $(wildcard $(addprefix $(S)src/libcore/, \ - core.rc *.rs */*.rs)) + core.rc *.rs */*.rs */*/*rs)) ###################################################################### # Standard library variables diff --git a/src/libcore/rt/io/file.rs b/src/libcore/rt/io/file.rs new file mode 100644 index 0000000000000..02ad6a00a149d --- /dev/null +++ b/src/libcore/rt/io/file.rs @@ -0,0 +1,45 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::super::sched::*; +use super::super::rtio::*; +use super::Stream; + +pub struct FileStream; + +pub impl FileStream { + static fn new(path: Path) -> FileStream { + fail!() + } +} + +impl Stream for FileStream { + fn read(&mut self, buf: &mut [u8]) -> uint { + fail!() + } + + fn eof(&mut self) -> bool { + fail!() + } + + fn write(&mut self, v: &const [u8]) { + fail!() + } +} + +#[test] +#[ignore] +fn super_simple_smoke_test_lets_go_read_some_files_and_have_a_good_time() { + let message = "it's alright. have a good time"; + let filename = Path("test.txt"); + let mut outstream = FileStream::new(filename); + outstream.write(message.to_bytes()); +} diff --git a/src/libcore/rt/io/mod.rs b/src/libcore/rt/io/mod.rs new file mode 100644 index 0000000000000..f82092b829c9b --- /dev/null +++ b/src/libcore/rt/io/mod.rs @@ -0,0 +1,45 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use option::*; +use comm::{GenericPort, GenericChan}; + +pub mod file; + +// FIXME #5370 Strongly want this to be StreamError(&mut Stream) +pub struct StreamError; + +// XXX: Can't put doc comments on macros +// Raised by `Stream` instances on error. Returning `true` from the handler +// indicates that the `Stream` should continue, `false` that it should fail. +condition! { + stream_error: super::StreamError -> bool; +} + +pub trait Stream { + /// Read bytes, up to the length of `buf` and place them in `buf`, + /// returning the number of bytes read or an `IoError`. Reads + /// 0 bytes on EOF. + /// + /// # Failure + /// + /// Raises the `reader_error` condition on error + fn read(&mut self, buf: &mut [u8]) -> uint; + + /// Return whether the Reader has reached the end of the stream + fn eof(&mut self) -> bool; + + /// Write the given buffer + /// + /// # Failure + /// + /// Raises the `writer_error` condition on error + fn write(&mut self, v: &const [u8]); +} diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index bc0efc01fbb75..c00162287fd33 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -34,6 +34,8 @@ mod rtio; pub mod uvll; mod uvio; mod uv; +#[path = "io/mod.rs"] +mod io; // FIXME #5248: The import in `sched` doesn't resolve unless this is pub! pub mod thread_local_storage; mod work_queue; From 7ef54c7ecd625376de092cbd741621987673c45f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 14 Mar 2013 19:54:04 -0700 Subject: [PATCH 09/12] core: Begin uv file system bindings --- src/libcore/rt/uv.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/libcore/rt/uv.rs b/src/libcore/rt/uv.rs index cc9e2fe8a7a82..aab6d898ea881 100644 --- a/src/libcore/rt/uv.rs +++ b/src/libcore/rt/uv.rs @@ -498,6 +498,42 @@ impl NativeHandle<*uvll::uv_write_t> for WriteRequest { } } +type FsCallback = ~fn(FsRequest, Option); +impl Callback for FsCallback { } + +pub struct FsRequest(*uvll::uv_fs_t); + +impl Request for FsRequest; + +impl FsRequest { + static fn new() -> FsRequest { + let fs_req = unsafe { malloc_req(UV_FS) }; + fail_unless!(fs_req.is_not_null()); + let fs_req = fs_req as *uvll::uv_write_t; + uvll::set_data_for_uv_req(fs_req, null::<()>()); + Native(fs_req) + } + + fn delete(self) { + unsafe { free_req(self.native_handle() as *c_void) } + } + + fn open(&mut self, loop_: &EventLoop, cb: FsCallback) { + } + + fn close(&mut self, loop_: &EventLoop, cb: FsCallback) { + } +} + +impl NativeHandle<*uvll::uv_fs_t> for FsRequest { + static fn from_native_handle(handle: *uvll:: uv_fs_t) -> FsRequest { + FsRequest(handle) + } + fn native_handle(&self) -> *uvll::uv_fs_t { + match self { &FsRequest(ptr) => ptr } + } +} + // XXX: Need to define the error constants like EOF so they can be // compared to the UvError type From a882554a785152c74c96cee036d252b071ed5ce1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 15 Mar 2013 18:07:36 -0700 Subject: [PATCH 10/12] core: Refactor uv bindings I can already see these are going to get massive. Putting them into multiple files. --- src/libcore/rt/io/file.rs | 6 +- src/libcore/rt/mod.rs | 1 + src/libcore/rt/thread.rs | 4 +- src/libcore/rt/uv/file.rs | 52 +++ src/libcore/rt/uv/mod.rs | 456 +++++++++++++++++++++++++ src/libcore/rt/{uv.rs => uv/net.rs} | 498 ++-------------------------- src/libcore/rt/uvll.rs | 1 + 7 files changed, 535 insertions(+), 483 deletions(-) create mode 100644 src/libcore/rt/uv/file.rs create mode 100644 src/libcore/rt/uv/mod.rs rename src/libcore/rt/{uv.rs => uv/net.rs} (53%) diff --git a/src/libcore/rt/io/file.rs b/src/libcore/rt/io/file.rs index 02ad6a00a149d..621cdca89e8f4 100644 --- a/src/libcore/rt/io/file.rs +++ b/src/libcore/rt/io/file.rs @@ -16,13 +16,13 @@ use super::Stream; pub struct FileStream; pub impl FileStream { - static fn new(path: Path) -> FileStream { + static fn new(_path: Path) -> FileStream { fail!() } } impl Stream for FileStream { - fn read(&mut self, buf: &mut [u8]) -> uint { + fn read(&mut self, _buf: &mut [u8]) -> uint { fail!() } @@ -30,7 +30,7 @@ impl Stream for FileStream { fail!() } - fn write(&mut self, v: &const [u8]) { + fn write(&mut self, _v: &const [u8]) { fail!() } } diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index c00162287fd33..1e919af4d14d1 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -33,6 +33,7 @@ mod sched; mod rtio; pub mod uvll; mod uvio; +#[path = "uv/mod.rs"] mod uv; #[path = "io/mod.rs"] mod io; diff --git a/src/libcore/rt/thread.rs b/src/libcore/rt/thread.rs index be1d86c9cf741..5eb951be7848c 100644 --- a/src/libcore/rt/thread.rs +++ b/src/libcore/rt/thread.rs @@ -14,12 +14,12 @@ use ops::Drop; #[allow(non_camel_case_types)] // runtime type type raw_thread = libc::c_void; -struct Thread { +pub struct Thread { main: ~fn(), raw_thread: *raw_thread } -impl Thread { +pub impl Thread { static fn start(main: ~fn()) -> Thread { fn substart(main: &fn()) -> *raw_thread { unsafe { rust_raw_thread_start(&main) } diff --git a/src/libcore/rt/uv/file.rs b/src/libcore/rt/uv/file.rs new file mode 100644 index 0000000000000..3a7b7f135d586 --- /dev/null +++ b/src/libcore/rt/uv/file.rs @@ -0,0 +1,52 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use ptr::null; +use libc::c_void; +use super::{UvError, Callback, Request, NativeHandle, Loop}; +use super::super::uvll; +use super::super::uvll::*; + +pub type FsCallback = ~fn(FsRequest, Option); +impl Callback for FsCallback { } + +pub struct FsRequest(*uvll::uv_fs_t); + +impl Request for FsRequest; + +impl FsRequest { + static fn new() -> FsRequest { + let fs_req = unsafe { malloc_req(UV_FS) }; + fail_unless!(fs_req.is_not_null()); + let fs_req = fs_req as *uvll::uv_write_t; + unsafe { uvll::set_data_for_req(fs_req, null::<()>()); } + NativeHandle::from_native_handle(fs_req) + } + + fn delete(self) { + unsafe { free_req(self.native_handle() as *c_void) } + } + + fn open(&mut self, _loop_: &Loop, _cb: FsCallback) { + } + + fn close(&mut self, _loop_: &Loop, _cb: FsCallback) { + } +} + +impl NativeHandle<*uvll::uv_fs_t> for FsRequest { + static fn from_native_handle(handle: *uvll:: uv_fs_t) -> FsRequest { + FsRequest(handle) + } + fn native_handle(&self) -> *uvll::uv_fs_t { + match self { &FsRequest(ptr) => ptr } + } +} diff --git a/src/libcore/rt/uv/mod.rs b/src/libcore/rt/uv/mod.rs new file mode 100644 index 0000000000000..c44998532ebaa --- /dev/null +++ b/src/libcore/rt/uv/mod.rs @@ -0,0 +1,456 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +Bindings to libuv. + +UV types consist of the event loop (Loop), Watchers, Requests and +Callbacks. + +Watchers and Requests encapsulate pointers to uv *handles*, which have +subtyping relationships with each other. This subtyping is reflected +in the bindings with explicit or implicit coercions. For example, an +upcast from TcpWatcher to StreamWatcher is done with +`tcp_watcher.as_stream()`. In other cases a callback on a specific +type of watcher will be passed a watcher of a supertype. + +Currently all use of Request types (connect/write requests) are +encapsulated in the bindings and don't need to be dealt with by the +caller. + +# Safety note + +Due to the complex lifecycle of uv handles, as well as compiler bugs, +this module is not memory safe and requires explicit memory management, +via `close` and `delete` methods. + +*/ + +use option::*; +use str::raw::from_c_str; +use to_str::ToStr; +use vec; +use ptr; +use libc::{c_void, c_int, size_t, malloc, free, ssize_t}; +use cast::{transmute, transmute_mut_region}; +use ptr::null; +use sys::size_of; +use super::uvll; +use super::uvll::*; +use unstable::finally::Finally; + +#[cfg(test)] use unstable::run_in_bare_thread; +#[cfg(test)] use super::thread::Thread; +#[cfg(test)] use cell::Cell; + +pub use self::file::{FsRequest, FsCallback}; +pub use self::net::{StreamWatcher, TcpWatcher}; +pub use self::net::{ReadCallback, AllocCallback, ConnectionCallback, ConnectCallback}; + +pub mod file; +pub mod net; + +/// A trait for callbacks to implement. Provides a little extra type safety +/// for generic, unsafe interop functions like `set_watcher_callback`. +pub trait Callback { } + +pub trait Request { } + +/// The trait implemented by uv 'watchers' (handles). Watchers are +/// non-owning wrappers around the uv handles and are not completely +/// safe - there may be multiple instances for a single underlying +/// handle. Watchers are generally created, then `start`ed, `stop`ed +/// and `close`ed, but due to their complex life cycle may not be +/// entirely memory safe if used in unanticipated patterns. +pub trait Watcher { + fn event_loop(&self) -> Loop; +} + +pub type NullCallback = ~fn(); +impl Callback for NullCallback { } + +/// A type that wraps a native handle +pub trait NativeHandle { + static pub fn from_native_handle(T) -> Self; + pub fn native_handle(&self) -> T; +} + +/// XXX: Loop(*handle) is buggy with destructors. Normal structs +/// with dtors may not be destructured, but tuple structs can, +/// but the results are not correct. +pub struct Loop { + handle: *uvll::uv_loop_t +} + +pub impl Loop { + static fn new() -> Loop { + let handle = unsafe { uvll::loop_new() }; + fail_unless!(handle.is_not_null()); + NativeHandle::from_native_handle(handle) + } + + fn run(&mut self) { + unsafe { uvll::run(self.native_handle()) }; + } + + fn close(&mut self) { + unsafe { uvll::loop_delete(self.native_handle()) }; + } +} + +impl NativeHandle<*uvll::uv_loop_t> for Loop { + static fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop { + Loop { handle: handle } + } + fn native_handle(&self) -> *uvll::uv_loop_t { + self.handle + } +} + +pub struct IdleWatcher(*uvll::uv_idle_t); + +impl Watcher for IdleWatcher { + fn event_loop(&self) -> Loop { + loop_from_watcher(self) + } +} + +pub type IdleCallback = ~fn(IdleWatcher, Option); +impl Callback for IdleCallback { } + +pub impl IdleWatcher { + static fn new(loop_: &mut Loop) -> IdleWatcher { + unsafe { + let handle = uvll::idle_new(); + fail_unless!(handle.is_not_null()); + fail_unless!(0 == uvll::idle_init(loop_.native_handle(), handle)); + uvll::set_data_for_uv_handle(handle, null::<()>()); + NativeHandle::from_native_handle(handle) + } + } + + fn start(&mut self, cb: IdleCallback) { + + set_watcher_callback(self, cb); + unsafe { + fail_unless!(0 == uvll::idle_start(self.native_handle(), idle_cb)) + }; + + extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) { + let idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle); + let cb: &IdleCallback = borrow_callback_from_watcher(&idle_watcher); + let status = status_to_maybe_uv_error(handle, status); + (*cb)(idle_watcher, status); + } + } + + fn stop(&mut self) { + unsafe { fail_unless!(0 == uvll::idle_stop(self.native_handle())); } + } + + fn close(self) { + unsafe { uvll::close(self.native_handle(), close_cb) }; + + extern fn close_cb(handle: *uvll::uv_idle_t) { + let mut idle_watcher = NativeHandle::from_native_handle(handle); + drop_watcher_callback::(&mut idle_watcher); + unsafe { uvll::idle_delete(handle) }; + } + } +} + +impl NativeHandle<*uvll::uv_idle_t> for IdleWatcher { + static fn from_native_handle(handle: *uvll::uv_idle_t) -> IdleWatcher { + IdleWatcher(handle) + } + fn native_handle(&self) -> *uvll::uv_idle_t { + match self { &IdleWatcher(ptr) => ptr } + } +} + +// XXX: Need to define the error constants like EOF so they can be +// compared to the UvError type + +pub struct UvError(uvll::uv_err_t); + +pub impl UvError { + + pure fn name(&self) -> ~str { + unsafe { + let inner = match self { &UvError(ref a) => a }; + let name_str = uvll::err_name(inner); + fail_unless!(name_str.is_not_null()); + from_c_str(name_str) + } + } + + pure fn desc(&self) -> ~str { + unsafe { + let inner = match self { &UvError(ref a) => a }; + let desc_str = uvll::strerror(inner); + fail_unless!(desc_str.is_not_null()); + from_c_str(desc_str) + } + } +} + +impl ToStr for UvError { + pure fn to_str(&self) -> ~str { + fmt!("%s: %s", self.name(), self.desc()) + } +} + +#[test] +fn error_smoke_test() { + let err = uvll::uv_err_t { code: 1, sys_errno_: 1 }; + let err: UvError = UvError(err); + fail_unless!(err.to_str() == ~"EOF: end of file"); +} + + +/// Given a uv handle, convert a callback status to a UvError +// XXX: Follow the pattern below by parameterizing over T: Watcher, not T +pub fn status_to_maybe_uv_error(handle: *T, status: c_int) -> Option { + if status != -1 { + None + } else { + unsafe { + rtdebug!("handle: %x", handle as uint); + let loop_ = uvll::get_loop_for_uv_handle(handle); + rtdebug!("loop: %x", loop_ as uint); + let err = uvll::last_error(loop_); + Some(UvError(err)) + } + } +} + +/// Get the uv event loop from a Watcher +pub fn loop_from_watcher>( + watcher: &W) -> Loop { + + let handle = watcher.native_handle(); + let loop_ = unsafe { uvll::get_loop_for_uv_handle(handle) }; + NativeHandle::from_native_handle(loop_) +} + +/// Set the custom data on a handle to a callback Note: This is only +/// suitable for watchers that make just one type of callback. For +/// others use WatcherData +pub fn set_watcher_callback, CB: Callback>( + watcher: &mut W, cb: CB) { + + drop_watcher_callback::(watcher); + // XXX: Boxing the callback so it fits into a + // pointer. Unfortunate extra allocation + let boxed_cb = ~cb; + let data = unsafe { transmute::<~CB, *c_void>(boxed_cb) }; + unsafe { uvll::set_data_for_uv_handle(watcher.native_handle(), data) }; +} + +/// Delete a callback from a handle's custom data +pub fn drop_watcher_callback, CB: Callback>( + watcher: &mut W) { + + unsafe { + let handle = watcher.native_handle(); + let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); + if handle_data.is_not_null() { + // Take ownership of the callback and drop it + let _cb = transmute::<*c_void, ~CB>(handle_data); + // Make sure the pointer is zeroed + uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>()); + } + } +} + +/// Take a pointer to the callback installed as custom data +pub fn borrow_callback_from_watcher, + CB: Callback>(watcher: &W) -> &CB { + + unsafe { + let handle = watcher.native_handle(); + let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); + fail_unless!(handle_data.is_not_null()); + let cb = transmute::<&*c_void, &~CB>(&handle_data); + return &**cb; + } +} + +/// Take ownership of the callback installed as custom data +pub fn take_callback_from_watcher, CB: Callback>( + watcher: &mut W) -> CB { + + unsafe { + let handle = watcher.native_handle(); + let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); + fail_unless!(handle_data.is_not_null()); + uvll::set_data_for_uv_handle(handle, null::<()>()); + let cb: ~CB = transmute::<*c_void, ~CB>(handle_data); + let cb = match cb { ~cb => cb }; + return cb; + } +} + +/// Callbacks used by StreamWatchers, set as custom data on the foreign handle +struct WatcherData { + read_cb: Option, + write_cb: Option, + connect_cb: Option, + close_cb: Option, + alloc_cb: Option +} + +pub fn install_watcher_data>(watcher: &mut W) { + unsafe { + let data = ~WatcherData { + read_cb: None, + write_cb: None, + connect_cb: None, + close_cb: None, + alloc_cb: None + }; + let data = transmute::<~WatcherData, *c_void>(data); + uvll::set_data_for_uv_handle(watcher.native_handle(), data); + } +} + +pub fn get_watcher_data>( + watcher: &r/mut W) -> &r/mut WatcherData { + + unsafe { + let data = uvll::get_data_for_uv_handle(watcher.native_handle()); + let data = transmute::<&*c_void, &mut ~WatcherData>(&data); + return &mut **data; + } +} + +pub fn drop_watcher_data>(watcher: &mut W) { + unsafe { + let data = uvll::get_data_for_uv_handle(watcher.native_handle()); + let _data = transmute::<*c_void, ~WatcherData>(data); + uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>()); + } +} + +#[test] +fn test_slice_to_uv_buf() { + let slice = [0, .. 20]; + let buf = slice_to_uv_buf(slice); + + fail_unless!(buf.len == 20); + + unsafe { + let base = transmute::<*u8, *mut u8>(buf.base); + (*base) = 1; + (*ptr::mut_offset(base, 1)) = 2; + } + + fail_unless!(slice[0] == 1); + fail_unless!(slice[1] == 2); +} + +/// The uv buffer type +pub type Buf = uvll::uv_buf_t; + +/// Borrow a slice to a Buf +pub fn slice_to_uv_buf(v: &[u8]) -> Buf { + let data = unsafe { vec::raw::to_ptr(v) }; + unsafe { uvll::buf_init(data, v.len()) } +} + +// XXX: Do these conversions without copying + +/// Transmute an owned vector to a Buf +pub fn vec_to_uv_buf(v: ~[u8]) -> Buf { + let data = unsafe { malloc(v.len() as size_t) } as *u8; + fail_unless!(data.is_not_null()); + do vec::as_imm_buf(v) |b, l| { + let data = data as *mut u8; + unsafe { ptr::copy_memory(data, b, l) } + } + let buf = unsafe { uvll::buf_init(data, v.len()) }; + return buf; +} + +/// Transmute a Buf that was once a ~[u8] back to ~[u8] +pub fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> { + if !(buf.len == 0 && buf.base.is_null()) { + let v = unsafe { vec::from_buf(buf.base, buf.len as uint) }; + unsafe { free(buf.base as *c_void) }; + return Some(v); + } else { + // No buffer + return None; + } +} + +#[test] +fn loop_smoke_test() { + do run_in_bare_thread { + let mut loop_ = Loop::new(); + loop_.run(); + loop_.close(); + } +} + +#[test] +#[ignore(reason = "valgrind - loop destroyed before watcher?")] +fn idle_new_then_close() { + do run_in_bare_thread { + let mut loop_ = Loop::new(); + let mut idle_watcher = { IdleWatcher::new(&mut loop_) }; + idle_watcher.close(); + } +} + +#[test] +fn idle_smoke_test() { + do run_in_bare_thread { + let mut loop_ = Loop::new(); + let mut idle_watcher = { IdleWatcher::new(&mut loop_) }; + let mut count = 10; + let count_ptr: *mut int = &mut count; + do idle_watcher.start |idle_watcher, status| { + let mut idle_watcher = idle_watcher; + fail_unless!(status.is_none()); + if unsafe { *count_ptr == 10 } { + idle_watcher.stop(); + idle_watcher.close(); + } else { + unsafe { *count_ptr = *count_ptr + 1; } + } + } + loop_.run(); + loop_.close(); + fail_unless!(count == 10); + } +} + +#[test] +fn idle_start_stop_start() { + do run_in_bare_thread { + let mut loop_ = Loop::new(); + let mut idle_watcher = { IdleWatcher::new(&mut loop_) }; + do idle_watcher.start |idle_watcher, status| { + let mut idle_watcher = idle_watcher; + fail_unless!(status.is_none()); + idle_watcher.stop(); + do idle_watcher.start |idle_watcher, status| { + fail_unless!(status.is_none()); + let mut idle_watcher = idle_watcher; + idle_watcher.stop(); + idle_watcher.close(); + } + } + loop_.run(); + loop_.close(); + } +} diff --git a/src/libcore/rt/uv.rs b/src/libcore/rt/uv/net.rs similarity index 53% rename from src/libcore/rt/uv.rs rename to src/libcore/rt/uv/net.rs index aab6d898ea881..bcbb1b2d02e42 100644 --- a/src/libcore/rt/uv.rs +++ b/src/libcore/rt/uv/net.rs @@ -8,49 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Bindings to libuv. - -UV types consist of the event loop (Loop), Watchers, Requests and -Callbacks. - -Watchers and Requests encapsulate pointers to uv *handles*, which have -subtyping relationships with each other. This subtyping is reflected -in the bindings with explicit or implicit coercions. For example, an -upcast from TcpWatcher to StreamWatcher is done with -`tcp_watcher.as_stream()`. In other cases a callback on a specific -type of watcher will be passed a watcher of a supertype. - -Currently all use of Request types (connect/write requests) are -encapsulated in the bindings and don't need to be dealt with by the -caller. - -# Safety note - -Due to the complex lifecycle of uv handles, as well as compiler bugs, -this module is not memory safe and requires explicit memory management, -via `close` and `delete` methods. - -*/ - -use option::*; -use str::raw::from_c_str; -use to_str::ToStr; -use vec; -use ptr; -use libc::{c_void, c_int, size_t, malloc, free, ssize_t}; +use prelude::*; +use libc::{size_t, ssize_t, c_int, c_void}; use cast::{transmute, transmute_mut_region}; -use ptr::null; -use sys::size_of; -use super::uvll; -use super::uvll::*; -use super::rtio::{IpAddr, Ipv4, Ipv6}; -use unstable::finally::Finally; - -#[cfg(test)] use unstable::run_in_bare_thread; -#[cfg(test)] use super::thread::Thread; -#[cfg(test)] use cell::Cell; +use super::super::uvll; +use super::super::uvll::*; +use super::{Loop, Watcher, Request, UvError, Buf, Callback, NativeHandle, NullCallback, + loop_from_watcher, status_to_maybe_uv_error, + install_watcher_data, get_watcher_data, drop_watcher_data, + vec_to_uv_buf, vec_from_uv_buf}; +use super::super::rtio::{IpAddr, Ipv4, Ipv6}; + +#[cfg(test)] +use unstable::run_in_bare_thread; +#[cfg(test)] +use super::super::thread::Thread; +#[cfg(test)] +use cell::Cell; fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) { match addr { @@ -72,122 +46,6 @@ fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) { } } -/// A trait for callbacks to implement. Provides a little extra type safety -/// for generic, unsafe interop functions like `set_watcher_callback`. -trait Callback { } - -type NullCallback = ~fn(); -impl Callback for NullCallback { } - -/// A type that wraps a native handle -trait NativeHandle { - static pub fn from_native_handle(T) -> Self; - pub fn native_handle(&self) -> T; -} - -/// XXX: Loop(*handle) is buggy with destructors. Normal structs -/// with dtors may not be destructured, but tuple structs can, -/// but the results are not correct. -pub struct Loop { - handle: *uvll::uv_loop_t -} - -pub impl Loop { - static fn new() -> Loop { - let handle = unsafe { uvll::loop_new() }; - fail_unless!(handle.is_not_null()); - NativeHandle::from_native_handle(handle) - } - - fn run(&mut self) { - unsafe { uvll::run(self.native_handle()) }; - } - - fn close(&mut self) { - unsafe { uvll::loop_delete(self.native_handle()) }; - } -} - -impl NativeHandle<*uvll::uv_loop_t> for Loop { - static fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop { - Loop { handle: handle } - } - fn native_handle(&self) -> *uvll::uv_loop_t { - self.handle - } -} - -/// The trait implemented by uv 'watchers' (handles). Watchers are -/// non-owning wrappers around the uv handles and are not completely -/// safe - there may be multiple instances for a single underlying -/// handle. Watchers are generally created, then `start`ed, `stop`ed -/// and `close`ed, but due to their complex life cycle may not be -/// entirely memory safe if used in unanticipated patterns. -trait Watcher { - fn event_loop(&self) -> Loop; -} - -pub struct IdleWatcher(*uvll::uv_idle_t); - -impl Watcher for IdleWatcher { - fn event_loop(&self) -> Loop { - loop_from_watcher(self) - } -} - -type IdleCallback = ~fn(IdleWatcher, Option); -impl Callback for IdleCallback { } - -pub impl IdleWatcher { - static fn new(loop_: &mut Loop) -> IdleWatcher { - unsafe { - let handle = uvll::idle_new(); - fail_unless!(handle.is_not_null()); - fail_unless!(0 == uvll::idle_init(loop_.native_handle(), handle)); - uvll::set_data_for_uv_handle(handle, null::<()>()); - NativeHandle::from_native_handle(handle) - } - } - - fn start(&mut self, cb: IdleCallback) { - - set_watcher_callback(self, cb); - unsafe { - fail_unless!(0 == uvll::idle_start(self.native_handle(), idle_cb)) - }; - - extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) { - let idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle); - let cb: &IdleCallback = borrow_callback_from_watcher(&idle_watcher); - let status = status_to_maybe_uv_error(handle, status); - (*cb)(idle_watcher, status); - } - } - - fn stop(&mut self) { - unsafe { fail_unless!(0 == uvll::idle_stop(self.native_handle())); } - } - - fn close(self) { - unsafe { uvll::close(self.native_handle(), close_cb) }; - - extern fn close_cb(handle: *uvll::uv_idle_t) { - let mut idle_watcher = NativeHandle::from_native_handle(handle); - drop_watcher_callback::(&mut idle_watcher); - unsafe { uvll::idle_delete(handle) }; - } - } -} - -impl NativeHandle<*uvll::uv_idle_t> for IdleWatcher { - static fn from_native_handle(handle: *uvll::uv_idle_t) -> IdleWatcher { - IdleWatcher(handle) - } - fn native_handle(&self) -> *uvll::uv_idle_t { - match self { &IdleWatcher(ptr) => ptr } - } -} - // uv_stream t is the parent class of uv_tcp_t, uv_pipe_t, uv_tty_t // and uv_file_t pub struct StreamWatcher(*uvll::uv_stream_t); @@ -198,7 +56,7 @@ impl Watcher for StreamWatcher { } } -type ReadCallback = ~fn(StreamWatcher, int, Buf, Option); +pub type ReadCallback = ~fn(StreamWatcher, int, Buf, Option); impl Callback for ReadCallback { } // XXX: The uv alloc callback also has a *uv_handle_t arg @@ -319,7 +177,7 @@ impl Watcher for TcpWatcher { } } -type ConnectionCallback = ~fn(StreamWatcher, Option); +pub type ConnectionCallback = ~fn(StreamWatcher, Option); impl Callback for ConnectionCallback { } pub impl TcpWatcher { @@ -419,9 +277,7 @@ impl NativeHandle<*uvll::uv_tcp_t> for TcpWatcher { } } -trait Request { } - -type ConnectCallback = ~fn(ConnectRequest, Option); +pub type ConnectCallback = ~fn(ConnectRequest, Option); impl Callback for ConnectCallback { } // uv_connect_t is a subclass of uv_req_t @@ -466,7 +322,7 @@ pub struct WriteRequest(*uvll::uv_write_t); impl Request for WriteRequest { } -impl WriteRequest { +pub impl WriteRequest { static fn new() -> WriteRequest { let write_handle = unsafe { @@ -498,320 +354,6 @@ impl NativeHandle<*uvll::uv_write_t> for WriteRequest { } } -type FsCallback = ~fn(FsRequest, Option); -impl Callback for FsCallback { } - -pub struct FsRequest(*uvll::uv_fs_t); - -impl Request for FsRequest; - -impl FsRequest { - static fn new() -> FsRequest { - let fs_req = unsafe { malloc_req(UV_FS) }; - fail_unless!(fs_req.is_not_null()); - let fs_req = fs_req as *uvll::uv_write_t; - uvll::set_data_for_uv_req(fs_req, null::<()>()); - Native(fs_req) - } - - fn delete(self) { - unsafe { free_req(self.native_handle() as *c_void) } - } - - fn open(&mut self, loop_: &EventLoop, cb: FsCallback) { - } - - fn close(&mut self, loop_: &EventLoop, cb: FsCallback) { - } -} - -impl NativeHandle<*uvll::uv_fs_t> for FsRequest { - static fn from_native_handle(handle: *uvll:: uv_fs_t) -> FsRequest { - FsRequest(handle) - } - fn native_handle(&self) -> *uvll::uv_fs_t { - match self { &FsRequest(ptr) => ptr } - } -} - -// XXX: Need to define the error constants like EOF so they can be -// compared to the UvError type - -struct UvError(uvll::uv_err_t); - -impl UvError { - - pure fn name(&self) -> ~str { - unsafe { - let inner = match self { &UvError(ref a) => a }; - let name_str = uvll::err_name(inner); - fail_unless!(name_str.is_not_null()); - from_c_str(name_str) - } - } - - pure fn desc(&self) -> ~str { - unsafe { - let inner = match self { &UvError(ref a) => a }; - let desc_str = uvll::strerror(inner); - fail_unless!(desc_str.is_not_null()); - from_c_str(desc_str) - } - } -} - -impl ToStr for UvError { - pure fn to_str(&self) -> ~str { - fmt!("%s: %s", self.name(), self.desc()) - } -} - -#[test] -fn error_smoke_test() { - let err = uvll::uv_err_t { code: 1, sys_errno_: 1 }; - let err: UvError = UvError(err); - fail_unless!(err.to_str() == ~"EOF: end of file"); -} - - -/// Given a uv handle, convert a callback status to a UvError -// XXX: Follow the pattern below by parameterizing over T: Watcher, not T -fn status_to_maybe_uv_error(handle: *T, status: c_int) -> Option { - if status != -1 { - None - } else { - unsafe { - rtdebug!("handle: %x", handle as uint); - let loop_ = uvll::get_loop_for_uv_handle(handle); - rtdebug!("loop: %x", loop_ as uint); - let err = uvll::last_error(loop_); - Some(UvError(err)) - } - } -} - -/// Get the uv event loop from a Watcher -pub fn loop_from_watcher>( - watcher: &W) -> Loop { - - let handle = watcher.native_handle(); - let loop_ = unsafe { uvll::get_loop_for_uv_handle(handle) }; - NativeHandle::from_native_handle(loop_) -} - -/// Set the custom data on a handle to a callback Note: This is only -/// suitable for watchers that make just one type of callback. For -/// others use WatcherData -fn set_watcher_callback, CB: Callback>( - watcher: &mut W, cb: CB) { - - drop_watcher_callback::(watcher); - // XXX: Boxing the callback so it fits into a - // pointer. Unfortunate extra allocation - let boxed_cb = ~cb; - let data = unsafe { transmute::<~CB, *c_void>(boxed_cb) }; - unsafe { uvll::set_data_for_uv_handle(watcher.native_handle(), data) }; -} - -/// Delete a callback from a handle's custom data -fn drop_watcher_callback, CB: Callback>( - watcher: &mut W) { - - unsafe { - let handle = watcher.native_handle(); - let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); - if handle_data.is_not_null() { - // Take ownership of the callback and drop it - let _cb = transmute::<*c_void, ~CB>(handle_data); - // Make sure the pointer is zeroed - uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>()); - } - } -} - -/// Take a pointer to the callback installed as custom data -fn borrow_callback_from_watcher, - CB: Callback>(watcher: &W) -> &CB { - - unsafe { - let handle = watcher.native_handle(); - let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); - fail_unless!(handle_data.is_not_null()); - let cb = transmute::<&*c_void, &~CB>(&handle_data); - return &**cb; - } -} - -/// Take ownership of the callback installed as custom data -fn take_callback_from_watcher, CB: Callback>( - watcher: &mut W) -> CB { - - unsafe { - let handle = watcher.native_handle(); - let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); - fail_unless!(handle_data.is_not_null()); - uvll::set_data_for_uv_handle(handle, null::<()>()); - let cb: ~CB = transmute::<*c_void, ~CB>(handle_data); - let cb = match cb { ~cb => cb }; - return cb; - } -} - -/// Callbacks used by StreamWatchers, set as custom data on the foreign handle -struct WatcherData { - read_cb: Option, - write_cb: Option, - connect_cb: Option, - close_cb: Option, - alloc_cb: Option -} - -fn install_watcher_data>(watcher: &mut W) { - unsafe { - let data = ~WatcherData { - read_cb: None, - write_cb: None, - connect_cb: None, - close_cb: None, - alloc_cb: None - }; - let data = transmute::<~WatcherData, *c_void>(data); - uvll::set_data_for_uv_handle(watcher.native_handle(), data); - } -} - -fn get_watcher_data>( - watcher: &r/mut W) -> &r/mut WatcherData { - - unsafe { - let data = uvll::get_data_for_uv_handle(watcher.native_handle()); - let data = transmute::<&*c_void, &mut ~WatcherData>(&data); - return &mut **data; - } -} - -fn drop_watcher_data>(watcher: &mut W) { - unsafe { - let data = uvll::get_data_for_uv_handle(watcher.native_handle()); - let _data = transmute::<*c_void, ~WatcherData>(data); - uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>()); - } -} - -#[test] -fn test_slice_to_uv_buf() { - let slice = [0, .. 20]; - let buf = slice_to_uv_buf(slice); - - fail_unless!(buf.len == 20); - - unsafe { - let base = transmute::<*u8, *mut u8>(buf.base); - (*base) = 1; - (*ptr::mut_offset(base, 1)) = 2; - } - - fail_unless!(slice[0] == 1); - fail_unless!(slice[1] == 2); -} - -/// The uv buffer type -pub type Buf = uvll::uv_buf_t; - -/// Borrow a slice to a Buf -pub fn slice_to_uv_buf(v: &[u8]) -> Buf { - let data = unsafe { vec::raw::to_ptr(v) }; - unsafe { uvll::buf_init(data, v.len()) } -} - -// XXX: Do these conversions without copying - -/// Transmute an owned vector to a Buf -fn vec_to_uv_buf(v: ~[u8]) -> Buf { - let data = unsafe { malloc(v.len() as size_t) } as *u8; - fail_unless!(data.is_not_null()); - do vec::as_imm_buf(v) |b, l| { - let data = data as *mut u8; - unsafe { ptr::copy_memory(data, b, l) } - } - let buf = unsafe { uvll::buf_init(data, v.len()) }; - return buf; -} - -/// Transmute a Buf that was once a ~[u8] back to ~[u8] -fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> { - if !(buf.len == 0 && buf.base.is_null()) { - let v = unsafe { vec::from_buf(buf.base, buf.len as uint) }; - unsafe { free(buf.base as *c_void) }; - return Some(v); - } else { - // No buffer - return None; - } -} - -#[test] -fn loop_smoke_test() { - do run_in_bare_thread { - let mut loop_ = Loop::new(); - loop_.run(); - loop_.close(); - } -} - -#[test] -#[ignore(reason = "valgrind - loop destroyed before watcher?")] -fn idle_new_then_close() { - do run_in_bare_thread { - let mut loop_ = Loop::new(); - let mut idle_watcher = { IdleWatcher::new(&mut loop_) }; - idle_watcher.close(); - } -} - -#[test] -fn idle_smoke_test() { - do run_in_bare_thread { - let mut loop_ = Loop::new(); - let mut idle_watcher = { IdleWatcher::new(&mut loop_) }; - let mut count = 10; - let count_ptr: *mut int = &mut count; - do idle_watcher.start |idle_watcher, status| { - let mut idle_watcher = idle_watcher; - fail_unless!(status.is_none()); - if unsafe { *count_ptr == 10 } { - idle_watcher.stop(); - idle_watcher.close(); - } else { - unsafe { *count_ptr = *count_ptr + 1; } - } - } - loop_.run(); - loop_.close(); - fail_unless!(count == 10); - } -} - -#[test] -fn idle_start_stop_start() { - do run_in_bare_thread { - let mut loop_ = Loop::new(); - let mut idle_watcher = { IdleWatcher::new(&mut loop_) }; - do idle_watcher.start |idle_watcher, status| { - let mut idle_watcher = idle_watcher; - fail_unless!(status.is_none()); - idle_watcher.stop(); - do idle_watcher.start |idle_watcher, status| { - fail_unless!(status.is_none()); - let mut idle_watcher = idle_watcher; - idle_watcher.stop(); - idle_watcher.close(); - } - } - loop_.run(); - loop_.close(); - } -} #[test] #[ignore(reason = "ffi struct issues")] diff --git a/src/libcore/rt/uvll.rs b/src/libcore/rt/uvll.rs index 3606c9f4dd651..a91e37d92e4cd 100644 --- a/src/libcore/rt/uvll.rs +++ b/src/libcore/rt/uvll.rs @@ -53,6 +53,7 @@ pub type uv_write_t = c_void; pub type uv_async_t = c_void; pub type uv_timer_t = c_void; pub type uv_stream_t = c_void; +pub type uv_fs_t = c_void; pub type uv_idle_cb = *u8; From 044703435ba7e1338456f7a83393eb2c6fecf238 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 15 Mar 2013 18:06:19 -0700 Subject: [PATCH 11/12] Add a way to run the test suite with the new scheduler TESTARGS=--newrt make check-stage1-rpass Conflicts: src/rt/rustrt.def.in --- src/compiletest/common.rs | 3 +++ src/compiletest/compiletest.rc | 5 ++++- src/compiletest/runtest.rs | 10 +++++++++- src/libcore/rt/mod.rs | 31 +++++++++++++++++++++++++++++++ src/libcore/unstable/lang.rs | 19 ++++++++++++++----- src/rt/rust.cpp | 15 --------------- src/rt/rust_builtin.cpp | 31 +++++++++++++++++++++++++++++++ src/rt/rustrt.def.in | 3 +++ 8 files changed, 95 insertions(+), 22 deletions(-) diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index b7c4e26c4b15c..36691380e17a1 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -63,6 +63,9 @@ pub struct config { // Run tests using the JIT jit: bool, + // Run tests using the new runtime + newrt: bool, + // Explain what's going on verbose: bool diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 7d53b29e04029..0c1f328ad09fa 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -61,7 +61,8 @@ pub fn parse_config(args: ~[~str]) -> config { getopts::optopt(~"runtool"), getopts::optopt(~"rustcflags"), getopts::optflag(~"verbose"), getopts::optopt(~"logfile"), - getopts::optflag(~"jit")]; + getopts::optflag(~"jit"), + getopts::optflag(~"newrt")]; fail_unless!(!args.is_empty()); let args_ = vec::tail(args); @@ -95,6 +96,7 @@ pub fn parse_config(args: ~[~str]) -> config { runtool: getopts::opt_maybe_str(matches, ~"runtool"), rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"), jit: getopts::opt_present(matches, ~"jit"), + newrt: getopts::opt_present(matches, ~"newrt"), verbose: getopts::opt_present(matches, ~"verbose") } } @@ -114,6 +116,7 @@ pub fn log_config(config: config) { logv(c, fmt!("runtool: %s", opt_str(config.runtool))); logv(c, fmt!("rustcflags: %s", opt_str(config.rustcflags))); logv(c, fmt!("jit: %b", config.jit)); + logv(c, fmt!("newrt: %b", config.newrt)); logv(c, fmt!("verbose: %b", config.verbose)); logv(c, fmt!("\n")); } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 03f3fa9fcf6b2..736aa4eebf0cb 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -483,9 +483,17 @@ fn compile_test_(config: config, props: TestProps, fn exec_compiled_test(config: config, props: TestProps, testfile: &Path) -> ProcRes { + + // If testing the new runtime then set the RUST_NEWRT env var + let env = if config.newrt { + props.exec_env + ~[(~"RUST_NEWRT", ~"1")] + } else { + props.exec_env + }; + compose_and_run(config, testfile, make_run_args(config, props, testfile), - props.exec_env, + env, config.run_lib_path, None) } diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 1e919af4d14d1..f900747c99604 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use libc::c_char; // Some basic logging macro_rules! rtdebug_ ( @@ -44,3 +45,33 @@ mod stack; mod context; mod thread; pub mod env; + +pub fn initialize() { + unsafe { rust_initialize_global_state(); } + extern { + fn rust_initialize_global_state(); + } +} + +pub fn start(main: *u8, _argc: int, _argv: *c_char, _crate_map: *u8) -> int { + use self::sched::{Scheduler, Task}; + use self::uvio::UvEventLoop; + + // XXX: Would rather do this lazily in Scheduler + initialize(); + + let loop_ = ~UvEventLoop::new(); + let mut sched = ~Scheduler::new(loop_); + let main_task = ~do Task::new(&mut sched.stack_pool) { + // XXX: Can't call a C function pointer from Rust yet + unsafe { rust_call_nullary_fn(main) }; + }; + sched.task_queue.push_back(main_task); + sched.run(); + return 0; + + extern { + fn rust_call_nullary_fn(f: *u8); + } +} + diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index db0b1cc33cd67..855c6b250ec0d 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -120,16 +120,25 @@ pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str { #[lang="start"] pub fn start(main: *u8, argc: int, argv: *c_char, crate_map: *u8) -> int { + use libc::getenv; + use rt::start; + + unsafe { + let use_new_rt = do str::as_c_str("RUST_NEWRT") |s| { + getenv(s).is_null() + }; + if use_new_rt { + return rust_start(main as *c_void, argc as c_int, argv, + crate_map as *c_void) as int; + } else { + return start(main, argc, argv, crate_map); + } + } extern { fn rust_start(main: *c_void, argc: c_int, argv: *c_char, crate_map: *c_void) -> c_int; } - - unsafe { - return rust_start(main as *c_void, argc as c_int, argv, - crate_map as *c_void) as int; - } } // Local Variables: diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index d9ef6a52dbef6..803da32cbc8ac 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -21,17 +21,6 @@ void* global_crate_map = NULL; -#ifndef _WIN32 -pthread_key_t sched_key; -#else -DWORD sched_key; -#endif - -extern "C" void* -rust_get_sched_tls_key() { - return &sched_key; -} - /** The runtime entrypoint. The (C ABI) main function generated by rustc calls `rust_start`, providing the address of the Rust ABI main function, the @@ -41,10 +30,6 @@ rust_get_sched_tls_key() { extern "C" CDECL int rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) { -#ifndef _WIN32 - pthread_key_create(&sched_key, NULL); -#endif - // Load runtime configuration options from the environment. // FIXME #1497: Should provide a way to get these from the command // line as well. diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index a2053c115bbbf..9349db17d569e 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -882,6 +882,37 @@ rust_get_rt_env() { return task->kernel->env; } +typedef void *(*nullary_fn)(); + +extern "C" CDECL void +rust_call_nullary_fn(nullary_fn f) { + f(); +} + + +#ifndef _WIN32 +pthread_key_t sched_key; +#else +DWORD sched_key; +#endif + +extern "C" void* +rust_get_sched_tls_key() { + return &sched_key; +} + +extern "C" CDECL void +rust_initialize_global_state() { + +#ifndef _WIN32 + assert(!pthread_key_create(&sched_key, NULL)); +#else + sched_key = TlsAlloc(); + assert(sched_key != TLS_OUT_OF_INDEXES); +#endif + +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 4fde952ba9565..59fd8991622c6 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -210,4 +210,7 @@ rust_uv_ip4_addrp rust_uv_ip6_addrp rust_uv_free_ip4_addr rust_uv_free_ip6_addr +rust_call_nullary_fn +rust_initialize_global_state + From 5af5766512b0e90a3a076a09b35286aca332e48e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 15 Mar 2013 18:35:33 -0700 Subject: [PATCH 12/12] core: Initialize global state lazily in the Scheduler ctor I don't want any global one-time initalization functions because that will make embedding harder. --- src/libcore/rt/mod.rs | 10 ---------- src/libcore/rt/sched.rs | 7 +++++++ src/rt/rust_builtin.cpp | 17 +++++++++++++---- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index f900747c99604..04891a1673c0a 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -46,20 +46,10 @@ mod context; mod thread; pub mod env; -pub fn initialize() { - unsafe { rust_initialize_global_state(); } - extern { - fn rust_initialize_global_state(); - } -} - pub fn start(main: *u8, _argc: int, _argv: *c_char, _crate_map: *u8) -> int { use self::sched::{Scheduler, Task}; use self::uvio::UvEventLoop; - // XXX: Would rather do this lazily in Scheduler - initialize(); - let loop_ = ~UvEventLoop::new(); let mut sched = ~Scheduler::new(loop_); let main_task = ~do Task::new(&mut sched.stack_pool) { diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index f47f86fd5fde6..312c6655f55f3 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -71,6 +71,13 @@ enum CleanupJob { pub impl Scheduler { static fn new(event_loop: ~EventLoopObject) -> Scheduler { + + // Lazily initialize the global state, currently the scheduler TLS key + unsafe { rust_initialize_global_state(); } + extern { + fn rust_initialize_global_state(); + } + Scheduler { event_loop: event_loop, task_queue: WorkQueue::new(), diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 9349db17d569e..f586e05772b76 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -889,7 +889,6 @@ rust_call_nullary_fn(nullary_fn f) { f(); } - #ifndef _WIN32 pthread_key_t sched_key; #else @@ -901,16 +900,26 @@ rust_get_sched_tls_key() { return &sched_key; } +// Initialize the global state required by the new scheduler extern "C" CDECL void rust_initialize_global_state() { + static lock_and_signal init_lock; + static bool initialized = false; + + scoped_lock with(init_lock); + + if (!initialized) { + #ifndef _WIN32 - assert(!pthread_key_create(&sched_key, NULL)); + assert(!pthread_key_create(&sched_key, NULL)); #else - sched_key = TlsAlloc(); - assert(sched_key != TLS_OUT_OF_INDEXES); + sched_key = TlsAlloc(); + assert(sched_key != TLS_OUT_OF_INDEXES); #endif + initialized = true; + } } //