From 6a34b5ea1dd95827218bfc4394575e908dc80de3 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 15 Mar 2012 21:42:07 -0700 Subject: [PATCH 01/33] adding uv::direct and beginning to work out tcp request case lots of changes, here.. should've commited sooner. - added uv::direct module that contains rust fns that map, neatly, to the libuv c library as much as possible. they operate on ptrs to libuv structs mapped in rust, as much as possible (there are some notable exceptions). these uv::direct fns should only take inputs from rust and, as neccesary, translate them into C-friendly types and then pass to the C functions. We want to them to return ints, as the libuv functions do, so we can start tracking status. - the notable exceptions for structs above is due to ref gh-1402, which prevents us from passing structs, by value, across the Rust<->C barrier (they turn to garbage, pretty much). So in the cases where we get back by-val structs from C (uv_buf_init(), uv_ip4_addr(), uv_err_t in callbacks) , we're going to use *ctypes::void (or just errnum ints for uv_err_t) until gh-1402 is resolved. - using crust functions, in these uv::direct fns, for callbacks from libuv, will eschew uv_err_t, if possible, in favor a struct int.. if at all possible (probably isn't.. hm.. i know libuv wants to eventually move to replace uv_err_t with an int, as well.. so hm). - started flushing out a big, gnarly test case to exercise the tcp request side of the uv::direct functions. I'm at the point where, after the connection is established, we write to the stream... when the writing is done, we will read from it, then tear the whole thing down. overall, it turns out that doing "close to the metal" interaction with c libraries is painful (and more chatty) when orchestrated from rust. My understanding is that not much, at all, is written in this fashion in the existant core/std codebase.. malloc'ing in C has been preferred, from what I've gathered. So we're treading new ground, here! --- src/libstd/uv.rs | 486 ++++++++++++++++++++++++++++++++++++++++++++- src/rt/rust_uv.cpp | 100 ++++++++++ 2 files changed, 585 insertions(+), 1 deletion(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index f6f42de148a1e..67508df491698 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -2,6 +2,7 @@ import map::hashmap; export loop_new, loop_delete, run, close, run_in_bg; export async_init, async_send; export timer_init, timer_start, timer_stop; +export uv_ip4_addr, uv_ip6_addr; // these are processed solely in the // process_operation() crust fn below @@ -16,7 +17,7 @@ enum uv_operation { enum uv_handle { uv_async([u8], uv_loop), - uv_timer([u8], uv_loop) + uv_timer([u8], uv_loop), } enum uv_msg { @@ -50,6 +51,191 @@ enum uv_loop { uv_loop_new(comm::chan, *libc::c_void) } +// libuv struct mappings +type uv_ip4_addr = { + ip: [u8], + port: int +}; +type uv_ip6_addr = uv_ip4_addr; + +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 +} + +type handle_type = ctypes::enum; + +type uv_handle_fields = { + loop_handle: *ctypes::void, + type_: handle_type, + close_cb: *u8, + mutable data: *ctypes::void, +}; + +// unix size: 8 +type uv_err_t = { + code: ctypes::c_int, + sys_errno_: ctypes::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..) +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type uv_stream_t = { + fields: uv_handle_fields +}; + +// unix size: 272 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type 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, a26: *u8, a27: *u8, + a28: *u8, a29: *u8 +}; +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +fn gen_stub_uv_tcp_t() -> uv_tcp_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mutable 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, a26: 0 as *u8, a27: 0 as *u8, + a28: 0 as *u8, a29: 0 as *u8 + }; +} + +#[cfg(target_os = "win32")] +type uv_tcp_t = { + loop_handle: *ctypes::void +}; +#[cfg(target_os = "win32")] +fn gen_stub_uv_tcp_t() -> uv_tcp_t { + ret { loop_handle: ptr::null() }; +} + +// unix size: 48 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type uv_connect_t = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8 +}; +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +fn gen_stub_uv_connect_t() -> uv_connect_t { + ret { + a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, + a04: 0 as *u8, a05: 0 as *u8 + }; +} + +// ref #1402 .. don't use this, like sockaddr_in +// unix size: 16 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type uv_buf_t = { + base: *u8, + len: ctypes::size_t +}; +// no gen stub method.. should create +// it via uv::direct::buf_init() + +#[cfg(target_os = "win32")] +type uv_connect_t = { + loop_handle: *ctypes::void +}; +#[cfg(target_os = "win32")] +fn gen_stub_uv_connect_t() -> uv_connect_t { + ret { loop_handle: ptr::null() }; +} + +// unix size: 144 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type 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, a13: *u8 +}; +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +fn gen_stub_uv_write_t() -> uv_write_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mutable 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 + }; +} +#[cfg(target_os = "win32")] +type uv_write_t = { + loop_handle: *ctypes::void +}; +#[cfg(target_os = "win32")] +fn gen_stub_uv_write_t() -> uv_write_t { + ret { loop_handle: ptr::null() }; +} + +// not going to use this type, for now, because of +// github issue #1402 +// unix size: 16 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type sockaddr_in = { + sin_family: u16, + sin_port: u16, + sin_addr: u32, // in_addr: this is an opaque, per-platform struct + sin_zero: *u8 +}; + +// unix size: 28 .. make due w/ 32 +type sockaddr_in6 = { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8 +}; + #[nolink] native mod rustrt { fn rust_uv_loop_new() -> *libc::c_void; @@ -78,6 +264,130 @@ native mod rustrt { timeout: libc::c_uint, repeat: libc::c_uint); fn rust_uv_timer_stop(handle: *libc::c_void); + + //////////// + // NOT IN rustrt.def.in + //////////// + fn rust_uv_free(ptr: *ctypes::void); + fn rust_uv_tcp_init( + loop_handle: *ctypes::void, + handle_ptr: *uv_tcp_t) -> ctypes::c_int; + fn rust_uv_buf_init(base: *u8, len: ctypes::size_t) + -> uv_buf_t; + fn rust_uv_last_error(loop_handle: *ctypes::void) -> uv_err_t; + fn rust_uv_ip4_addr(ip: *u8, port: ctypes::c_int) + -> *ctypes::void; + fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + addr: *ctypes::void, + after_cb: *u8) -> ctypes::c_int; + + // sizeof testing helpers + fn rust_uv_helper_uv_tcp_t_size() -> ctypes::c_uint; + fn rust_uv_helper_uv_connect_t_size() -> ctypes::c_uint; + fn rust_uv_helper_uv_buf_t_size() -> ctypes::c_uint; + fn rust_uv_helper_uv_write_t_size() -> ctypes::c_uint; + fn rust_uv_helper_uv_err_t_size() -> ctypes::c_uint; + fn rust_uv_helper_sockaddr_in_size() -> ctypes::c_uint; + + // data accessors for rust-mapped uv structs + fn rust_uv_get_stream_handle_for_connect(connect: *uv_connect_t) + -> *uv_stream_t; + fn rust_uv_get_loop_for_uv_handle(handle: *ctypes::void) + -> *ctypes::void; + fn rust_uv_get_data_for_uv_handle(handle: *ctypes::void) + -> *ctypes::void; + fn rust_uv_set_data_for_uv_handle(handle: *ctypes::void, + data: *ctypes::void); + fn rust_uv_get_data_for_req(req: *ctypes::void) -> *ctypes::void; + fn rust_uv_set_data_for_req(req: *ctypes::void, + data: *ctypes::void); +} + +// this module is structured around functions that directly +// expose libuv functionality and data structures. for use +// in higher level mappings +mod direct { + unsafe fn loop_new() -> *ctypes::void { + ret rustrt::rust_uv_loop_new(); + } + + unsafe fn loop_delete(loop_handle: *ctypes::void) { + rustrt::rust_uv_loop_delete(loop_handle); + } + + unsafe fn run(loop_handle: *ctypes::void) { + rustrt::rust_uv_run(loop_handle); + } + + unsafe fn tcp_init(loop_handle: *ctypes::void, handle: *uv_tcp_t) + -> ctypes::c_int { + ret rustrt::rust_uv_tcp_init(loop_handle, handle); + } + unsafe fn tcp_connect(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + address: *ctypes::void, + after_connect_cb: *u8) + -> ctypes::c_int { + ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, + address, after_connect_cb); + } + + unsafe fn write(req: *ctypes::void, stream: *ctypes::void, + buf: *[uv_buf_t], cb: *u8) -> ctypes::c_int { + ret rustrt::rust_uv_write( + } + + unsafe fn uv_last_error(loop_handle: *ctypes::void) -> uv_err_t { + ret rustrt::rust_uv_last_error(loop_handle); + } + + // libuv struct initializers + unsafe fn tcp_t() -> uv_tcp_t { + ret gen_stub_uv_tcp_t(); + } + unsafe fn connect_t() -> uv_connect_t { + ret gen_stub_uv_connect_t(); + } + unsafe fn write_t() -> uv_write_t { + ret gen_stub_uv_write_t(); + } + // FIXME: see github issue #1402 + unsafe fn buf_init(input: *u8, len: uint) -> *ctypes::void { + ret rustrt::rust_uv_buf_init(input, len); + } + unsafe fn get_loop_for_uv_handle(handle: *ctypes::void) + -> *ctypes::void { + ret rustrt::rust_uv_get_loop_for_uv_handle(handle); + } + unsafe fn get_stream_handle_for_connect(connect: *uv_connect_t) + -> *uv_stream_t { + ret rustrt::rust_uv_get_stream_handle_for_connect(connect); + } + + unsafe fn get_data_for_req(req: *ctypes::void) -> *ctypes::void { + ret rustrt::rust_uv_get_data_for_req(req); + } + unsafe fn set_data_for_req(req: *ctypes::void, + data: *ctypes::void) { + rustrt::rust_uv_set_data_for_req(req, data); + } + // FIXME: see github issue #1402 + unsafe fn ip4_addr(ip: str, port: ctypes::c_int) + -> *ctypes::void { + let addr_vec = str::bytes(ip); + addr_vec += [0u8]; // add null terminator + let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); + let ip_back = str::from_bytes(addr_vec); + io::println(#fmt("vec val: '%s' length: %u",ip_back, vec::len(addr_vec))); + ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port); + } + + // this is lame. + // FIXME: see github issue #1402 + unsafe fn ip4_addr_free(ptr: *ctypes::void) { + rustrt::rust_uv_free(ptr); + } } // public functions @@ -626,3 +936,177 @@ fn test_uv_timer() { assert comm::recv(exit_port); uv::loop_delete(test_loop); } + +// BEGIN TCP REQUEST TEST SUITE + +type request_wrapper = { + write_req: *uv_write_t, + req_buf: *[uv_buf_t] +}; + +crust fn on_alloc(handle: *ctypes::void, + suggested_size: ctypes::size_t) -> uv_buf_t + unsafe { + io::println("beginning on_alloc..."); + io::println("ending on_alloc..."); + let new_vec: @[u8] = @[]; + let ptr = vec::unsafe::to_ptr(*new_vec); + ret direct::buf_init(ptr, vec::len(*new_vec)); +} + +crust fn on_write_complete_cb(write_handle: *uv_write_t, + status: ctypes::c_int) unsafe { + io::println("beginning on_write_complete_cb"); + io::println("ending on_write_complete_cb"); +} + +crust fn on_connect_cb(connect_handle_ptr: *uv_connect_t, + status: ctypes::c_int) unsafe { + io::println(#fmt("beginning on_connect_cb .. status: %d", + status as int)); + let stream = direct::get_stream_handle_for_connect(connect_handle_ptr); + if (status == 0i32) { + io::println("on_connect_cb: in status=0 if.."); + let data = direct::get_data_for_req( + connect_handle_ptr as *ctypes::void) + as *request_wrapper; + let write_handle = (*data).write_req as *ctypes::void; + io::println(#fmt("on_connect_cb: tcp stream: %d write_handle addr %d", + stream as int, write_handle as int)); + direct::write(write_handle, + stream as *ctypes::void, + (*data).req_buf, + on_write_complete_cb); + io::println("on_connect_cb: after direct::write()"); + } + else { + let loop_handle = direct::get_loop_for_uv_handle( + stream as *ctypes::void); + let err = direct::uv_last_error(loop_handle); + } + io::println("finishing on_connect_cb"); +} + +fn impl_uv_tcp_request() unsafe { + let test_loop = direct::loop_new(); + let tcp_handle = direct::tcp_t(); + let tcp_handle_ptr = ptr::addr_of(tcp_handle); + let connect_handle = direct::connect_t(); + let connect_handle_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 = str::bytes("GET / HTTP/1.1\r\nHost: google.com" + + "\r\n\r\n\r\n"); + let req_msg_ptr: *u8 = vec::unsafe::to_ptr(req_str); + let req_msg = [ + direct::buf_init(req_msg_ptr, vec::len(req_str)) + ]; + // this is the enclosing record, we'll pass a ptr to + // this to C.. + let write_handle = direct::write_t(); + let write_handle_ptr = ptr::addr_of(write_handle); + io::println(#fmt("tcp req setup: tcp stream: %d write_handle addr %d", + tcp_handle_ptr as int, write_handle_ptr as int)); + let req = { writer_handle: write_handle_ptr, + req_buf: ptr::addr_of(req_msg) }; + io::println("building addr..."); + let addr = direct::ip4_addr("173.194.33.40", 80i32); + + let tcp_init_result = direct::tcp_init( + test_loop as *ctypes::void, tcp_handle_ptr); + if (tcp_init_result == 0i32) { + io::println("sucessful tcp_init_result"); + // this should set up the connection request.. + let tcp_connect_result = direct::tcp_connect( + connect_handle_ptr, tcp_handle_ptr, + addr, on_connect_cb); + if (tcp_connect_result == 0i32) { + // not set the data on the connect_req until its initialized + direct::set_data_for_req( + connect_handle_ptr as *ctypes::void, + ptr::addr_of(req) as *ctypes::void); + io::println("before run tcp req loop"); + direct::run(test_loop); + io::println("after run tcp req loop"); + // FIXME: see github issue #1402 + direct::ip4_addr_free(addr); + } + else { + io::println("direct::tcp_connect() failure"); + assert false; + } + } + else { + io::println("direct::tcp_init() failure"); + assert false; + } + +} +// START HERE AND WORK YOUR WAY UP VIA CALLBACKS +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_tcp_request() unsafe { + impl_uv_tcp_request(); +} +// END TCP REQUEST TEST SUITE + +// struct size tests +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_struct_size_uv_tcp_t() { + let native_handle_size = rustrt::rust_uv_helper_uv_tcp_t_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("uv_tcp_t -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + io::println(output); + assert native_handle_size as uint == rust_handle_size; +} +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_struct_size_uv_connect_t() { + let native_handle_size = + rustrt::rust_uv_helper_uv_connect_t_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("uv_connect_t -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + io::println(output); + assert native_handle_size as uint == rust_handle_size; +} +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_struct_size_uv_buf_t() { + let native_handle_size = + rustrt::rust_uv_helper_uv_buf_t_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("uv_buf_t -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + io::println(output); + assert native_handle_size as uint == rust_handle_size; +} +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_struct_size_uv_write_t() { + let native_handle_size = + rustrt::rust_uv_helper_uv_write_t_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("uv_write_t -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + io::println(output); + assert native_handle_size as uint == rust_handle_size; +} + +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_struct_size_sockaddr_in() { + let native_handle_size = + rustrt::rust_uv_helper_sockaddr_in_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("sockaddr_in -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + io::println(output); + assert native_handle_size as uint == rust_handle_size; +} diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index e6d6c2e52ba1d..2a575bd00e387 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -80,6 +80,10 @@ native_close_op_cb(uv_handle_t* op_handle) { } // native fns bound in rust +extern "C" void +rust_uv_free(void* ptr) { + current_kernel_free(ptr); +} extern "C" void* rust_uv_loop_new() { return (void*)uv_loop_new(); @@ -195,3 +199,99 @@ rust_uv_timer_stop(uv_timer_t* the_timer) { uv_timer_stop(the_timer); } +extern "C" int +rust_uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { + return uv_tcp_init(loop, handle); +} + +extern "C" size_t +rust_uv_helper_uv_tcp_t_size() { + return sizeof(uv_tcp_t); +} +extern "C" size_t +rust_uv_helper_uv_connect_t_size() { + return sizeof(uv_connect_t); +} +extern "C" size_t +rust_uv_helper_uv_buf_t_size() { + return sizeof(uv_buf_t); +} +extern "C" size_t +rust_uv_helper_uv_write_t_size() { + return sizeof(uv_write_t); +} +extern "C" size_t +rust_uv_helper_uv_err_t_size() { + return sizeof(uv_err_t); +} +extern "C" size_t +rust_uv_helper_sockaddr_in_size() { + return sizeof(sockaddr_in); +} + +extern "C" uv_stream_t* +rust_uv_get_stream_handle_for_connect(uv_connect_t* connect) { + return connect->handle; +} + +extern "C" uv_buf_t +rust_uv_buf_init(char* base, size_t len) { + return uv_buf_init(base, len); +} + +extern "C" uv_loop_t* +rust_uv_get_loop_for_uv_handle(uv_handle_t* handle) { + return handle->loop; +} + +extern "C" void* +rust_uv_get_data_for_uv_handle(uv_handle_t* handle) { + return handle->data; +} + +extern "C" void +rust_uv_set_data_for_uv_handle(uv_handle_t* handle, + void* data) { + handle->data = data; +} + +extern "C" void* +rust_uv_get_data_for_req(uv_req_t* req) { + return req->data; +} + +extern "C" void +rust_uv_set_data_for_req(uv_req_t* req, void* data) { + req->data = data; +} + +extern "C" uv_err_t +rust_uv_last_error(uv_loop_t* loop) { + return uv_last_error(loop); +} + +extern "C" int +rust_uv_tcp_connect(uv_connect_t* connect_ptr, + uv_tcp_t* tcp_ptr, + void* addr_ptr, + uv_connect_cb cb) { + //return uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); + printf("inside rust_uv_tcp_connect\n"); + sockaddr_in addr_tmp = *((sockaddr_in*)addr_ptr); + sockaddr_in addr = addr_tmp; + printf("before tcp_connect .. port: %d\n", addr.sin_port); + int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); + printf ("leaving rust_uv_tcp_connect.. and result: %d\n", result); + return result; +} + +extern "C" void* +rust_uv_ip4_addr(const char* ip, int port) { + sockaddr_in* addr_ptr = (sockaddr_in*)current_kernel_malloc( + sizeof(sockaddr_in), + "sockaddr_in"); + printf("before creating addr_ptr.. ip %s port %d\n", ip, port); + *addr_ptr = uv_ip4_addr("173.194.33.40", 80); + printf("after creating .. port: %d\n", addr_ptr->sin_port); + return (void*)addr_ptr; +} From 533031a90a880288b11261e9a4eac0e8fcbac514 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 21 Mar 2012 08:56:05 -0700 Subject: [PATCH 02/33] some more stuff for libuv dealing w/ 1402.. should go away soon --- src/libstd/uv.rs | 15 +++++++-------- src/rt/rust_uv.cpp | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 67508df491698..c280caf0372da 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -273,7 +273,7 @@ native mod rustrt { loop_handle: *ctypes::void, handle_ptr: *uv_tcp_t) -> ctypes::c_int; fn rust_uv_buf_init(base: *u8, len: ctypes::size_t) - -> uv_buf_t; + -> *ctypes::void; fn rust_uv_last_error(loop_handle: *ctypes::void) -> uv_err_t; fn rust_uv_ip4_addr(ip: *u8, port: ctypes::c_int) -> *ctypes::void; @@ -352,10 +352,6 @@ mod direct { unsafe fn write_t() -> uv_write_t { ret gen_stub_uv_write_t(); } - // FIXME: see github issue #1402 - unsafe fn buf_init(input: *u8, len: uint) -> *ctypes::void { - ret rustrt::rust_uv_buf_init(input, len); - } unsafe fn get_loop_for_uv_handle(handle: *ctypes::void) -> *ctypes::void { ret rustrt::rust_uv_get_loop_for_uv_handle(handle); @@ -373,6 +369,10 @@ mod direct { rustrt::rust_uv_set_data_for_req(req, data); } // FIXME: see github issue #1402 + unsafe fn buf_init(input: *u8, len: uint) -> *ctypes::void { + ret rustrt::rust_uv_buf_init(input, len); + } + // FIXME: see github issue #1402 unsafe fn ip4_addr(ip: str, port: ctypes::c_int) -> *ctypes::void { let addr_vec = str::bytes(ip); @@ -382,10 +382,9 @@ mod direct { io::println(#fmt("vec val: '%s' length: %u",ip_back, vec::len(addr_vec))); ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port); } - // this is lame. // FIXME: see github issue #1402 - unsafe fn ip4_addr_free(ptr: *ctypes::void) { + unsafe fn free_1402(ptr: *ctypes::void) { rustrt::rust_uv_free(ptr); } } @@ -1033,7 +1032,7 @@ fn impl_uv_tcp_request() unsafe { direct::run(test_loop); io::println("after run tcp req loop"); // FIXME: see github issue #1402 - direct::ip4_addr_free(addr); + direct::free_1402(addr); } else { io::println("direct::tcp_connect() failure"); diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 2a575bd00e387..4735abdedcde2 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -234,9 +234,22 @@ rust_uv_get_stream_handle_for_connect(uv_connect_t* connect) { return connect->handle; } -extern "C" uv_buf_t +static uv_buf_t +current_kernel_malloc_alloc_cb(uv_handle_t* handle, + size_t suggested_size) { + char* base_ptr = (char*)current_kernel_malloc(sizeof(char) + * suggested_size, + "uv_buf_t_base_val"); + return uv_buf_init(base_ptr, suggested_size); +} + +// FIXME see issue #1402 +extern "C" void* rust_uv_buf_init(char* base, size_t len) { - return uv_buf_init(base, len); + uv_buf_t* buf_ptr = current_kernel_malloc(sizeof(uv_buf_t), + "uv_buf_t_1402"); + *buf_ptr = uv_buf_init(base, len); + return buf_ptr; } extern "C" uv_loop_t* From 566a04505a3089a95d1de8910c3c7678858bc1db Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 22 Mar 2012 06:44:44 -0700 Subject: [PATCH 03/33] changing ctypes:: to libc:: and impl of uv::direct::write() --- src/libstd/uv.rs | 139 +++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 66 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index c280caf0372da..96e8b10c5f218 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -76,19 +76,19 @@ enum uv_handle_type { UV_FS_EVENT } -type handle_type = ctypes::enum; +type handle_type = libc::c_uint; type uv_handle_fields = { - loop_handle: *ctypes::void, + loop_handle: *libc::c_void, type_: handle_type, close_cb: *u8, - mutable data: *ctypes::void, + mutable data: *libc::c_void, }; // unix size: 8 type uv_err_t = { - code: ctypes::c_int, - sys_errno_: ctypes::c_int + code: libc::c_int, + sys_errno_: libc::c_int }; // don't create one of these directly. instead, @@ -138,7 +138,7 @@ fn gen_stub_uv_tcp_t() -> uv_tcp_t { #[cfg(target_os = "win32")] type uv_tcp_t = { - loop_handle: *ctypes::void + loop_handle: *libc::c_void }; #[cfg(target_os = "win32")] fn gen_stub_uv_tcp_t() -> uv_tcp_t { @@ -170,14 +170,14 @@ fn gen_stub_uv_connect_t() -> uv_connect_t { #[cfg(target_os = "freebsd")] type uv_buf_t = { base: *u8, - len: ctypes::size_t + len: libc::size_t }; // no gen stub method.. should create // it via uv::direct::buf_init() #[cfg(target_os = "win32")] type uv_connect_t = { - loop_handle: *ctypes::void + loop_handle: *libc::c_void }; #[cfg(target_os = "win32")] fn gen_stub_uv_connect_t() -> uv_connect_t { @@ -210,7 +210,7 @@ fn gen_stub_uv_write_t() -> uv_write_t { } #[cfg(target_os = "win32")] type uv_write_t = { - loop_handle: *ctypes::void + loop_handle: *libc::c_void }; #[cfg(target_os = "win32")] fn gen_stub_uv_write_t() -> uv_write_t { @@ -268,77 +268,82 @@ native mod rustrt { //////////// // NOT IN rustrt.def.in //////////// - fn rust_uv_free(ptr: *ctypes::void); + fn rust_uv_free(ptr: *libc::c_void); fn rust_uv_tcp_init( - loop_handle: *ctypes::void, - handle_ptr: *uv_tcp_t) -> ctypes::c_int; - fn rust_uv_buf_init(base: *u8, len: ctypes::size_t) - -> *ctypes::void; - fn rust_uv_last_error(loop_handle: *ctypes::void) -> uv_err_t; - fn rust_uv_ip4_addr(ip: *u8, port: ctypes::c_int) - -> *ctypes::void; + loop_handle: *libc::c_void, + handle_ptr: *uv_tcp_t) -> libc::c_int; + fn rust_uv_buf_init(base: *u8, len: libc::size_t) + -> *libc::c_void; + fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; + fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) + -> *libc::c_void; fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, - addr: *ctypes::void, - after_cb: *u8) -> ctypes::c_int; + addr: *libc::c_void, + after_cb: *u8) -> libc::c_int; + 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; // sizeof testing helpers - fn rust_uv_helper_uv_tcp_t_size() -> ctypes::c_uint; - fn rust_uv_helper_uv_connect_t_size() -> ctypes::c_uint; - fn rust_uv_helper_uv_buf_t_size() -> ctypes::c_uint; - fn rust_uv_helper_uv_write_t_size() -> ctypes::c_uint; - fn rust_uv_helper_uv_err_t_size() -> ctypes::c_uint; - fn rust_uv_helper_sockaddr_in_size() -> ctypes::c_uint; + fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint; + fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint; + fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint; + fn rust_uv_helper_uv_write_t_size() -> libc::c_uint; + fn rust_uv_helper_uv_err_t_size() -> libc::c_uint; + fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; // data accessors for rust-mapped uv structs fn rust_uv_get_stream_handle_for_connect(connect: *uv_connect_t) -> *uv_stream_t; - fn rust_uv_get_loop_for_uv_handle(handle: *ctypes::void) - -> *ctypes::void; - fn rust_uv_get_data_for_uv_handle(handle: *ctypes::void) - -> *ctypes::void; - fn rust_uv_set_data_for_uv_handle(handle: *ctypes::void, - data: *ctypes::void); - fn rust_uv_get_data_for_req(req: *ctypes::void) -> *ctypes::void; - fn rust_uv_set_data_for_req(req: *ctypes::void, - data: *ctypes::void); + fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void) + -> *libc::c_void; + fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void) + -> *libc::c_void; + fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void, + data: *libc::c_void); + fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void; + fn rust_uv_set_data_for_req(req: *libc::c_void, + data: *libc::c_void); } // this module is structured around functions that directly // expose libuv functionality and data structures. for use // in higher level mappings mod direct { - unsafe fn loop_new() -> *ctypes::void { + unsafe fn loop_new() -> *libc::c_void { ret rustrt::rust_uv_loop_new(); } - unsafe fn loop_delete(loop_handle: *ctypes::void) { + unsafe fn loop_delete(loop_handle: *libc::c_void) { rustrt::rust_uv_loop_delete(loop_handle); } - unsafe fn run(loop_handle: *ctypes::void) { + unsafe fn run(loop_handle: *libc::c_void) { rustrt::rust_uv_run(loop_handle); } - unsafe fn tcp_init(loop_handle: *ctypes::void, handle: *uv_tcp_t) - -> ctypes::c_int { + unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t) + -> libc::c_int { ret rustrt::rust_uv_tcp_init(loop_handle, handle); } unsafe fn tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, - address: *ctypes::void, + address: *libc::c_void, after_connect_cb: *u8) - -> ctypes::c_int { + -> libc::c_int { ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, address, after_connect_cb); } - unsafe fn write(req: *ctypes::void, stream: *ctypes::void, - buf: *[uv_buf_t], cb: *u8) -> ctypes::c_int { - ret rustrt::rust_uv_write( + unsafe fn write(req: *libc::c_void, stream: *libc::c_void, + buf_in: *[uv_buf_t], cb: *u8) -> libc::c_int { + let buf_ptr = vec::unsafe::to_ptr(*buf_in); + let buf_cnt = vec::len(*buf_in) as i32; + ret rustrt::rust_uv_write(req, stream, buf_ptr, buf_cnt, cb); } - unsafe fn uv_last_error(loop_handle: *ctypes::void) -> uv_err_t { + unsafe fn uv_last_error(loop_handle: *libc::c_void) -> uv_err_t { ret rustrt::rust_uv_last_error(loop_handle); } @@ -352,8 +357,8 @@ mod direct { unsafe fn write_t() -> uv_write_t { ret gen_stub_uv_write_t(); } - unsafe fn get_loop_for_uv_handle(handle: *ctypes::void) - -> *ctypes::void { + unsafe fn get_loop_for_uv_handle(handle: *libc::c_void) + -> *libc::c_void { ret rustrt::rust_uv_get_loop_for_uv_handle(handle); } unsafe fn get_stream_handle_for_connect(connect: *uv_connect_t) @@ -361,20 +366,20 @@ mod direct { ret rustrt::rust_uv_get_stream_handle_for_connect(connect); } - unsafe fn get_data_for_req(req: *ctypes::void) -> *ctypes::void { + unsafe fn get_data_for_req(req: *libc::c_void) -> *libc::c_void { ret rustrt::rust_uv_get_data_for_req(req); } - unsafe fn set_data_for_req(req: *ctypes::void, - data: *ctypes::void) { + unsafe fn set_data_for_req(req: *libc::c_void, + data: *libc::c_void) { rustrt::rust_uv_set_data_for_req(req, data); } // FIXME: see github issue #1402 - unsafe fn buf_init(input: *u8, len: uint) -> *ctypes::void { + unsafe fn buf_init(input: *u8, len: uint) -> *libc::c_void { ret rustrt::rust_uv_buf_init(input, len); } // FIXME: see github issue #1402 - unsafe fn ip4_addr(ip: str, port: ctypes::c_int) - -> *ctypes::void { + unsafe fn ip4_addr(ip: str, port: libc::c_int) + -> *libc::c_void { let addr_vec = str::bytes(ip); addr_vec += [0u8]; // add null terminator let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); @@ -384,7 +389,7 @@ mod direct { } // this is lame. // FIXME: see github issue #1402 - unsafe fn free_1402(ptr: *ctypes::void) { + unsafe fn free_1402(ptr: *libc::c_void) { rustrt::rust_uv_free(ptr); } } @@ -943,44 +948,46 @@ type request_wrapper = { req_buf: *[uv_buf_t] }; -crust fn on_alloc(handle: *ctypes::void, - suggested_size: ctypes::size_t) -> uv_buf_t +crust fn on_alloc(handle: *libc::c_void, + suggested_size: libc::size_t) -> uv_buf_t unsafe { io::println("beginning on_alloc..."); io::println("ending on_alloc..."); let new_vec: @[u8] = @[]; let ptr = vec::unsafe::to_ptr(*new_vec); - ret direct::buf_init(ptr, vec::len(*new_vec)); + let buf = direct::buf_init(ptr, vec::len(*new_vec)); + ret *(buf as *uv_buf_t); + } crust fn on_write_complete_cb(write_handle: *uv_write_t, - status: ctypes::c_int) unsafe { + status: libc::c_int) unsafe { io::println("beginning on_write_complete_cb"); io::println("ending on_write_complete_cb"); } crust fn on_connect_cb(connect_handle_ptr: *uv_connect_t, - status: ctypes::c_int) unsafe { + status: libc::c_int) unsafe { io::println(#fmt("beginning on_connect_cb .. status: %d", status as int)); let stream = direct::get_stream_handle_for_connect(connect_handle_ptr); if (status == 0i32) { io::println("on_connect_cb: in status=0 if.."); let data = direct::get_data_for_req( - connect_handle_ptr as *ctypes::void) + connect_handle_ptr as *libc::c_void) as *request_wrapper; - let write_handle = (*data).write_req as *ctypes::void; + let write_handle = (*data).write_req as *libc::c_void; io::println(#fmt("on_connect_cb: tcp stream: %d write_handle addr %d", stream as int, write_handle as int)); direct::write(write_handle, - stream as *ctypes::void, + stream as *libc::c_void, (*data).req_buf, on_write_complete_cb); io::println("on_connect_cb: after direct::write()"); } else { let loop_handle = direct::get_loop_for_uv_handle( - stream as *ctypes::void); + stream as *libc::c_void); let err = direct::uv_last_error(loop_handle); } io::println("finishing on_connect_cb"); @@ -1016,7 +1023,7 @@ fn impl_uv_tcp_request() unsafe { let addr = direct::ip4_addr("173.194.33.40", 80i32); let tcp_init_result = direct::tcp_init( - test_loop as *ctypes::void, tcp_handle_ptr); + test_loop as *libc::c_void, tcp_handle_ptr); if (tcp_init_result == 0i32) { io::println("sucessful tcp_init_result"); // this should set up the connection request.. @@ -1026,8 +1033,8 @@ fn impl_uv_tcp_request() unsafe { if (tcp_connect_result == 0i32) { // not set the data on the connect_req until its initialized direct::set_data_for_req( - connect_handle_ptr as *ctypes::void, - ptr::addr_of(req) as *ctypes::void); + connect_handle_ptr as *libc::c_void, + ptr::addr_of(req) as *libc::c_void); io::println("before run tcp req loop"); direct::run(test_loop); io::println("after run tcp req loop"); From ebab03acc6db046b77980c0fb2ba47f2bf7916fe Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 22 Mar 2012 06:45:06 -0700 Subject: [PATCH 04/33] impl of rustrt::rust_uv_write in c++ and whitespace cleanup --- src/rt/rust_uv.cpp | 83 +++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 4735abdedcde2..52a857a779117 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -196,91 +196,92 @@ rust_uv_timer_start(uv_timer_t* the_timer, uint32_t timeout, extern "C" void rust_uv_timer_stop(uv_timer_t* the_timer) { - uv_timer_stop(the_timer); + uv_timer_stop(the_timer); } extern "C" int rust_uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { - return uv_tcp_init(loop, handle); + return uv_tcp_init(loop, handle); } extern "C" size_t rust_uv_helper_uv_tcp_t_size() { - return sizeof(uv_tcp_t); + return sizeof(uv_tcp_t); } extern "C" size_t rust_uv_helper_uv_connect_t_size() { - return sizeof(uv_connect_t); + return sizeof(uv_connect_t); } extern "C" size_t rust_uv_helper_uv_buf_t_size() { - return sizeof(uv_buf_t); + return sizeof(uv_buf_t); } extern "C" size_t rust_uv_helper_uv_write_t_size() { - return sizeof(uv_write_t); + return sizeof(uv_write_t); } extern "C" size_t rust_uv_helper_uv_err_t_size() { - return sizeof(uv_err_t); + return sizeof(uv_err_t); } extern "C" size_t rust_uv_helper_sockaddr_in_size() { - return sizeof(sockaddr_in); + return sizeof(sockaddr_in); } extern "C" uv_stream_t* rust_uv_get_stream_handle_for_connect(uv_connect_t* connect) { - return connect->handle; + return connect->handle; } -static uv_buf_t +extern "C" uv_buf_t current_kernel_malloc_alloc_cb(uv_handle_t* handle, size_t suggested_size) { - char* base_ptr = (char*)current_kernel_malloc(sizeof(char) - * suggested_size, - "uv_buf_t_base_val"); - return uv_buf_init(base_ptr, suggested_size); + char* base_ptr = (char*)current_kernel_malloc(sizeof(char) + * suggested_size, + "uv_buf_t_base_val"); + return uv_buf_init(base_ptr, suggested_size); } // FIXME see issue #1402 extern "C" void* rust_uv_buf_init(char* base, size_t len) { - uv_buf_t* buf_ptr = current_kernel_malloc(sizeof(uv_buf_t), - "uv_buf_t_1402"); - *buf_ptr = uv_buf_init(base, len); - return buf_ptr; + uv_buf_t* buf_ptr = (uv_buf_t*)current_kernel_malloc( + sizeof(uv_buf_t), + "uv_buf_t_1402"); + *buf_ptr = uv_buf_init(base, len); + return buf_ptr; } extern "C" uv_loop_t* rust_uv_get_loop_for_uv_handle(uv_handle_t* handle) { - return handle->loop; + return handle->loop; } extern "C" void* rust_uv_get_data_for_uv_handle(uv_handle_t* handle) { - return handle->data; + return handle->data; } extern "C" void rust_uv_set_data_for_uv_handle(uv_handle_t* handle, void* data) { - handle->data = data; + handle->data = data; } extern "C" void* rust_uv_get_data_for_req(uv_req_t* req) { - return req->data; + return req->data; } extern "C" void rust_uv_set_data_for_req(uv_req_t* req, void* data) { - req->data = data; + req->data = data; } extern "C" uv_err_t rust_uv_last_error(uv_loop_t* loop) { - return uv_last_error(loop); + return uv_last_error(loop); } extern "C" int @@ -288,23 +289,31 @@ rust_uv_tcp_connect(uv_connect_t* connect_ptr, uv_tcp_t* tcp_ptr, void* addr_ptr, uv_connect_cb cb) { - //return uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); - printf("inside rust_uv_tcp_connect\n"); - sockaddr_in addr_tmp = *((sockaddr_in*)addr_ptr); - sockaddr_in addr = addr_tmp; - printf("before tcp_connect .. port: %d\n", addr.sin_port); - int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); - printf ("leaving rust_uv_tcp_connect.. and result: %d\n", result); - return result; + //return uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); + printf("inside rust_uv_tcp_connect\n"); + sockaddr_in addr_tmp = *((sockaddr_in*)addr_ptr); + sockaddr_in addr = addr_tmp; + printf("before tcp_connect .. port: %d\n", addr.sin_port); + int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); + printf ("leaving rust_uv_tcp_connect.. and result: %d\n", + result); + return result; +} + +extern "C" int +rust_uv_write(uv_write_t* req, uv_stream_t* handle, + uv_buf_t* bufs, int buf_cnt, + uv_write_cb cb) { + return uv_write(req, handle, bufs, buf_cnt, cb); } extern "C" void* rust_uv_ip4_addr(const char* ip, int port) { - sockaddr_in* addr_ptr = (sockaddr_in*)current_kernel_malloc( + sockaddr_in* addr_ptr = (sockaddr_in*)current_kernel_malloc( sizeof(sockaddr_in), "sockaddr_in"); - printf("before creating addr_ptr.. ip %s port %d\n", ip, port); - *addr_ptr = uv_ip4_addr("173.194.33.40", 80); - printf("after creating .. port: %d\n", addr_ptr->sin_port); - return (void*)addr_ptr; + printf("before creating addr_ptr.. ip %s port %d\n", ip, port); + *addr_ptr = uv_ip4_addr("173.194.33.40", 80); + printf("after creating .. port: %d\n", addr_ptr->sin_port); + return (void*)addr_ptr; } From c7e42d7670a505c4572e110d093aa07b98f6927e Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 22 Mar 2012 07:28:30 -0700 Subject: [PATCH 05/33] uv_write works, buffer passing still broke, can get sockaddr_in by val .. but passing sockaddr_in by val back to C is broken, still passing by ptr .. the uv_write_cb is processed, but we have a status -1.. there is also valgrind spew.. so buf passing is broken, still. --- src/libstd/uv.rs | 41 +++++++++++++++++++++++++---------------- src/rt/rust_uv.cpp | 11 ++++------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 96e8b10c5f218..906771d53c87b 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -276,7 +276,7 @@ native mod rustrt { -> *libc::c_void; fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) - -> *libc::c_void; + -> sockaddr_in; fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, addr: *libc::c_void, @@ -373,14 +373,14 @@ mod direct { data: *libc::c_void) { rustrt::rust_uv_set_data_for_req(req, data); } - // FIXME: see github issue #1402 + // TODO: see github issue #1402 unsafe fn buf_init(input: *u8, len: uint) -> *libc::c_void { ret rustrt::rust_uv_buf_init(input, len); } - // FIXME: see github issue #1402 + // TODO: see github issue #1402 unsafe fn ip4_addr(ip: str, port: libc::c_int) - -> *libc::c_void { - let addr_vec = str::bytes(ip); + -> sockaddr_in { + let mut addr_vec = str::bytes(ip); addr_vec += [0u8]; // add null terminator let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); let ip_back = str::from_bytes(addr_vec); @@ -388,7 +388,7 @@ mod direct { ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port); } // this is lame. - // FIXME: see github issue #1402 + // TODO: see github issue #1402 unsafe fn free_1402(ptr: *libc::c_void) { rustrt::rust_uv_free(ptr); } @@ -962,7 +962,8 @@ crust fn on_alloc(handle: *libc::c_void, crust fn on_write_complete_cb(write_handle: *uv_write_t, status: libc::c_int) unsafe { - io::println("beginning on_write_complete_cb"); + io::println(#fmt("beginning on_write_complete_cb status: %d", + status as int)); io::println("ending on_write_complete_cb"); } @@ -979,11 +980,12 @@ crust fn on_connect_cb(connect_handle_ptr: *uv_connect_t, let write_handle = (*data).write_req as *libc::c_void; io::println(#fmt("on_connect_cb: tcp stream: %d write_handle addr %d", stream as int, write_handle as int)); - direct::write(write_handle, + let write_result = direct::write(write_handle, stream as *libc::c_void, (*data).req_buf, on_write_complete_cb); - io::println("on_connect_cb: after direct::write()"); + io::println(#fmt("on_connect_cb: direct::write() status: %d", + write_result as int)); } else { let loop_handle = direct::get_loop_for_uv_handle( @@ -1015,31 +1017,38 @@ fn impl_uv_tcp_request() unsafe { // this to C.. let write_handle = direct::write_t(); let write_handle_ptr = ptr::addr_of(write_handle); - io::println(#fmt("tcp req setup: tcp stream: %d write_handle addr %d", - tcp_handle_ptr as int, write_handle_ptr as int)); + io::println(#fmt("tcp req: tcp stream: %d write_handle: %d", + tcp_handle_ptr as int, + write_handle_ptr as int)); let req = { writer_handle: write_handle_ptr, req_buf: ptr::addr_of(req_msg) }; - io::println("building addr..."); - let addr = direct::ip4_addr("173.194.33.40", 80i32); let tcp_init_result = direct::tcp_init( test_loop as *libc::c_void, tcp_handle_ptr); if (tcp_init_result == 0i32) { io::println("sucessful tcp_init_result"); + + io::println("building addr..."); + let addr_val = direct::ip4_addr("173.194.33.40", 80i32); + io::println(#fmt("after build addr in rust. port: %u", + addr_val.sin_port as uint)); + let addr: *libc::c_void = ptr::addr_of(addr_val) as + *libc::c_void; + // this should set up the connection request.. let tcp_connect_result = direct::tcp_connect( connect_handle_ptr, tcp_handle_ptr, addr, on_connect_cb); if (tcp_connect_result == 0i32) { - // not set the data on the connect_req until its initialized + // not set the data on the connect_req + // until its initialized direct::set_data_for_req( connect_handle_ptr as *libc::c_void, ptr::addr_of(req) as *libc::c_void); io::println("before run tcp req loop"); direct::run(test_loop); io::println("after run tcp req loop"); - // FIXME: see github issue #1402 - direct::free_1402(addr); + // TODO: see github issue #1402 } else { io::println("direct::tcp_connect() failure"); diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 52a857a779117..54b95ac6fcbc9 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -307,13 +307,10 @@ rust_uv_write(uv_write_t* req, uv_stream_t* handle, return uv_write(req, handle, bufs, buf_cnt, cb); } -extern "C" void* +extern "C" sockaddr_in rust_uv_ip4_addr(const char* ip, int port) { - sockaddr_in* addr_ptr = (sockaddr_in*)current_kernel_malloc( - sizeof(sockaddr_in), - "sockaddr_in"); printf("before creating addr_ptr.. ip %s port %d\n", ip, port); - *addr_ptr = uv_ip4_addr("173.194.33.40", 80); - printf("after creating .. port: %d\n", addr_ptr->sin_port); - return (void*)addr_ptr; + sockaddr_in addr = uv_ip4_addr("173.194.33.40", 80); + printf("after creating .. port: %d\n", addr.sin_port); + return addr; } From 8d6c4040a49a4c4683559d650581268016b4d365 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 22 Mar 2012 11:48:40 -0700 Subject: [PATCH 06/33] fixed passing in uv_buf_t ptr array in uv_write.. return status 0 ways to go, still.. --- src/libstd/uv.rs | 9 ++++++--- src/rt/rust_uv.cpp | 10 ++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 906771d53c87b..30c8cbd9c4e0f 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -282,7 +282,7 @@ native mod rustrt { addr: *libc::c_void, after_cb: *u8) -> libc::c_int; fn rust_uv_write(req: *libc::c_void, stream: *libc::c_void, - buf_in: *uv_buf_t, buf_cnt: libc::c_int, + buf_in: **libc::c_void, buf_cnt: libc::c_int, cb: *u8) -> libc::c_int; // sizeof testing helpers @@ -336,8 +336,11 @@ mod direct { address, after_connect_cb); } + // TODO github #1402 -- the buf_in is a vector of pointers + // to malloc'd buffers .. these will have to be translated + // back into their value types in c. sigh. unsafe fn write(req: *libc::c_void, stream: *libc::c_void, - buf_in: *[uv_buf_t], cb: *u8) -> libc::c_int { + buf_in: *[*libc::c_void], cb: *u8) -> libc::c_int { let buf_ptr = vec::unsafe::to_ptr(*buf_in); let buf_cnt = vec::len(*buf_in) as i32; ret rustrt::rust_uv_write(req, stream, buf_ptr, buf_cnt, cb); @@ -945,7 +948,7 @@ fn test_uv_timer() { type request_wrapper = { write_req: *uv_write_t, - req_buf: *[uv_buf_t] + req_buf: *[*libc::c_void] }; crust fn on_alloc(handle: *libc::c_void, diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 54b95ac6fcbc9..c62af8edf4058 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -302,9 +302,15 @@ rust_uv_tcp_connect(uv_connect_t* connect_ptr, extern "C" int rust_uv_write(uv_write_t* req, uv_stream_t* handle, - uv_buf_t* bufs, int buf_cnt, + void** bufs, int buf_cnt, uv_write_cb cb) { - return uv_write(req, handle, bufs, buf_cnt, cb); + // TODO github #1402 -- convert this array of pointers to + // uv_buf_t into an array of uv_buf_t values + uv_buf_t buf_vals[buf_cnt]; + for(int ctr = 0; ctr < buf_cnt; ctr++) { + buf_vals[ctr] = *((uv_buf_t*)bufs[ctr]); + } + return uv_write(req, handle, buf_vals, buf_cnt, cb); } extern "C" sockaddr_in From a67155ff93c6c6f7feb2f486cb80c5a67fc9d8c7 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 22 Mar 2012 21:15:39 -0700 Subject: [PATCH 07/33] fixed by-val from rust->c, use ++ sigil in native fn sig <-- NEVAR FORGET have to use ++ sigil in rust-side extern fn decls in order to have rust actually copy the struct, by value, onto the C stack. gotcha, indeed. also adding a helper method to verify/remind how to pass a struct by-val into C... check out the rust fn sig for rust_uv_ip4_test_verify_port_val() for more infos --- src/libstd/uv.rs | 46 +++++++++++++++++++++++++++++++--------------- src/rt/rust_uv.cpp | 17 ++++++++++++----- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 30c8cbd9c4e0f..e52b1121a6f6d 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -217,17 +217,15 @@ fn gen_stub_uv_write_t() -> uv_write_t { ret { loop_handle: ptr::null() }; } -// not going to use this type, for now, because of -// github issue #1402 // unix size: 16 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] type sockaddr_in = { - sin_family: u16, - sin_port: u16, - sin_addr: u32, // in_addr: this is an opaque, per-platform struct - sin_zero: *u8 + mut sin_family: u16, + mut sin_port: u16, + mut sin_addr: u32, // in_addr: this is an opaque, per-platform struct + mut sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8) }; // unix size: 28 .. make due w/ 32 @@ -275,11 +273,14 @@ native mod rustrt { fn rust_uv_buf_init(base: *u8, len: libc::size_t) -> *libc::c_void; fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; + fn rust_uv_ip4_test_verify_port_val(++addr: sockaddr_in, + expected: libc::c_uint) + -> bool; fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) -> sockaddr_in; fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, - addr: *libc::c_void, + ++addr: sockaddr_in, after_cb: *u8) -> libc::c_int; fn rust_uv_write(req: *libc::c_void, stream: *libc::c_void, buf_in: **libc::c_void, buf_cnt: libc::c_int, @@ -329,9 +330,10 @@ mod direct { } unsafe fn tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, - address: *libc::c_void, + address: sockaddr_in, after_connect_cb: *u8) -> libc::c_int { + io::println(#fmt("before native tcp_connect -- addr port: %u", address.sin_port as uint)); ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, address, after_connect_cb); } @@ -380,15 +382,15 @@ mod direct { unsafe fn buf_init(input: *u8, len: uint) -> *libc::c_void { ret rustrt::rust_uv_buf_init(input, len); } - // TODO: see github issue #1402 - unsafe fn ip4_addr(ip: str, port: libc::c_int) + unsafe fn ip4_addr(ip: str, port: int) -> sockaddr_in { let mut addr_vec = str::bytes(ip); addr_vec += [0u8]; // add null terminator let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); let ip_back = str::from_bytes(addr_vec); io::println(#fmt("vec val: '%s' length: %u",ip_back, vec::len(addr_vec))); - ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port); + ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, + port as libc::c_int); } // this is lame. // TODO: see github issue #1402 @@ -1032,11 +1034,11 @@ fn impl_uv_tcp_request() unsafe { io::println("sucessful tcp_init_result"); io::println("building addr..."); - let addr_val = direct::ip4_addr("173.194.33.40", 80i32); + let addr = direct::ip4_addr("173.194.33.40", 80); io::println(#fmt("after build addr in rust. port: %u", - addr_val.sin_port as uint)); - let addr: *libc::c_void = ptr::addr_of(addr_val) as - *libc::c_void; + addr.sin_port as uint)); + //let addr: *libc::c_void = ptr::addr_of(addr_val) as + // *libc::c_void; // this should set up the connection request.. let tcp_connect_result = direct::tcp_connect( @@ -1128,3 +1130,17 @@ fn test_uv_struct_size_sockaddr_in() { io::println(output); assert native_handle_size as uint == rust_handle_size; } + +fn impl_uv_byval_test() unsafe { + let addr = direct::ip4_addr("173.194.33.111", 80); + io::println(#fmt("after build addr in rust. port: %u", + addr.sin_port as uint)); + assert rustrt::rust_uv_ip4_test_verify_port_val(addr, + addr.sin_port as libc::c_uint); + io::println(#fmt("after build addr in rust. port: %u", + addr.sin_port as uint)); +} +#[test] +fn test_uv_ip4_byval_passing_test() { + impl_uv_byval_test(); +} diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index c62af8edf4058..cfe3b78b10838 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -287,12 +287,12 @@ rust_uv_last_error(uv_loop_t* loop) { extern "C" int rust_uv_tcp_connect(uv_connect_t* connect_ptr, uv_tcp_t* tcp_ptr, - void* addr_ptr, + struct sockaddr_in addr, uv_connect_cb cb) { //return uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); printf("inside rust_uv_tcp_connect\n"); - sockaddr_in addr_tmp = *((sockaddr_in*)addr_ptr); - sockaddr_in addr = addr_tmp; + //sockaddr_in addr_tmp = *((sockaddr_in*)addr_ptr); + //sockaddr_in addr = addr_tmp; printf("before tcp_connect .. port: %d\n", addr.sin_port); int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); printf ("leaving rust_uv_tcp_connect.. and result: %d\n", @@ -313,10 +313,17 @@ rust_uv_write(uv_write_t* req, uv_stream_t* handle, return uv_write(req, handle, buf_vals, buf_cnt, cb); } -extern "C" sockaddr_in +extern "C" struct sockaddr_in rust_uv_ip4_addr(const char* ip, int port) { printf("before creating addr_ptr.. ip %s port %d\n", ip, port); - sockaddr_in addr = uv_ip4_addr("173.194.33.40", 80); + struct sockaddr_in addr = uv_ip4_addr(ip, port); printf("after creating .. port: %d\n", addr.sin_port); return addr; } + +extern "C" bool +rust_uv_ip4_test_verify_port_val(struct sockaddr_in addr, + unsigned int expected) { + printf("inside c++ ip4_test .. port: %u\n", addr.sin_port); + return addr.sin_port == expected; +} From b91f7b8c1b2277dc99c5c0560195d058ef4e919d Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 22 Mar 2012 21:49:48 -0700 Subject: [PATCH 08/33] uv_buf_t's for uv_write() passed by-val .. no more mallocs or ptr cop-outs so we're now adhering the libuv C api and passing structs by-val where it is expected, instead of pulling pointer trickery (or worse having to malloc structs in c++ to be passed back to rust and then into C again) --- src/libstd/uv.rs | 22 +++++----------------- src/rt/rust_uv.cpp | 18 ++++-------------- 2 files changed, 9 insertions(+), 31 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index e52b1121a6f6d..33676bc470d0c 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -271,7 +271,7 @@ native mod rustrt { loop_handle: *libc::c_void, handle_ptr: *uv_tcp_t) -> libc::c_int; fn rust_uv_buf_init(base: *u8, len: libc::size_t) - -> *libc::c_void; + -> uv_buf_t; fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; fn rust_uv_ip4_test_verify_port_val(++addr: sockaddr_in, expected: libc::c_uint) @@ -283,7 +283,7 @@ native mod rustrt { ++addr: sockaddr_in, after_cb: *u8) -> libc::c_int; fn rust_uv_write(req: *libc::c_void, stream: *libc::c_void, - buf_in: **libc::c_void, buf_cnt: libc::c_int, + ++buf_in: *uv_buf_t, buf_cnt: libc::c_int, cb: *u8) -> libc::c_int; // sizeof testing helpers @@ -342,7 +342,7 @@ mod direct { // to malloc'd buffers .. these will have to be translated // back into their value types in c. sigh. unsafe fn write(req: *libc::c_void, stream: *libc::c_void, - buf_in: *[*libc::c_void], cb: *u8) -> libc::c_int { + buf_in: *[uv_buf_t], cb: *u8) -> libc::c_int { let buf_ptr = vec::unsafe::to_ptr(*buf_in); let buf_cnt = vec::len(*buf_in) as i32; ret rustrt::rust_uv_write(req, stream, buf_ptr, buf_cnt, cb); @@ -379,7 +379,7 @@ mod direct { rustrt::rust_uv_set_data_for_req(req, data); } // TODO: see github issue #1402 - unsafe fn buf_init(input: *u8, len: uint) -> *libc::c_void { + unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { ret rustrt::rust_uv_buf_init(input, len); } unsafe fn ip4_addr(ip: str, port: int) @@ -950,21 +950,9 @@ fn test_uv_timer() { type request_wrapper = { write_req: *uv_write_t, - req_buf: *[*libc::c_void] + req_buf: *[uv_buf_t] }; -crust fn on_alloc(handle: *libc::c_void, - suggested_size: libc::size_t) -> uv_buf_t - unsafe { - io::println("beginning on_alloc..."); - io::println("ending on_alloc..."); - let new_vec: @[u8] = @[]; - let ptr = vec::unsafe::to_ptr(*new_vec); - let buf = direct::buf_init(ptr, vec::len(*new_vec)); - ret *(buf as *uv_buf_t); - -} - crust fn on_write_complete_cb(write_handle: *uv_write_t, status: libc::c_int) unsafe { io::println(#fmt("beginning on_write_complete_cb status: %d", diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index cfe3b78b10838..b4694ccf37c57 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -244,13 +244,9 @@ current_kernel_malloc_alloc_cb(uv_handle_t* handle, } // FIXME see issue #1402 -extern "C" void* +extern "C" uv_buf_t rust_uv_buf_init(char* base, size_t len) { - uv_buf_t* buf_ptr = (uv_buf_t*)current_kernel_malloc( - sizeof(uv_buf_t), - "uv_buf_t_1402"); - *buf_ptr = uv_buf_init(base, len); - return buf_ptr; + return uv_buf_init(base, len); } extern "C" uv_loop_t* @@ -302,15 +298,9 @@ rust_uv_tcp_connect(uv_connect_t* connect_ptr, extern "C" int rust_uv_write(uv_write_t* req, uv_stream_t* handle, - void** bufs, int buf_cnt, + uv_buf_t* bufs, int buf_cnt, uv_write_cb cb) { - // TODO github #1402 -- convert this array of pointers to - // uv_buf_t into an array of uv_buf_t values - uv_buf_t buf_vals[buf_cnt]; - for(int ctr = 0; ctr < buf_cnt; ctr++) { - buf_vals[ctr] = *((uv_buf_t*)bufs[ctr]); - } - return uv_write(req, handle, buf_vals, buf_cnt, cb); + return uv_write(req, handle, bufs, buf_cnt, cb); } extern "C" struct sockaddr_in From 5e880705a371a2ac1f4e91cc0e71c665f56b2079 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 26 Mar 2012 11:09:57 -0700 Subject: [PATCH 09/33] wired up uv_read_start and some helper funcs around uv_alloc_cb tasks --- src/libstd/uv.rs | 146 +++++++++++++++++++++++++++++++++++++-------- src/rt/rust_uv.cpp | 31 +++++++++- 2 files changed, 150 insertions(+), 27 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 33676bc470d0c..fe22df30ae140 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -285,6 +285,10 @@ native mod rustrt { 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; + fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8, + on_read: *u8) -> libc::c_int; + fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; + fn rust_uv_free_base_of_buf(++buf: uv_buf_t); // sizeof testing helpers fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint; @@ -295,7 +299,11 @@ native mod rustrt { fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; // data accessors for rust-mapped uv structs - fn rust_uv_get_stream_handle_for_connect(connect: *uv_connect_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: *libc::c_void) -> *libc::c_void; @@ -347,6 +355,11 @@ mod direct { let buf_cnt = vec::len(*buf_in) as i32; ret rustrt::rust_uv_write(req, stream, buf_ptr, buf_cnt, cb); } + unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, + on_read: *u8) -> libc::c_int { + ret rustrt::rust_uv_read_start(stream as *libc::c_void, + on_alloc, on_read); + } unsafe fn uv_last_error(loop_handle: *libc::c_void) -> uv_err_t { ret rustrt::rust_uv_last_error(loop_handle); @@ -366,9 +379,16 @@ mod direct { -> *libc::c_void { ret rustrt::rust_uv_get_loop_for_uv_handle(handle); } - unsafe fn get_stream_handle_for_connect(connect: *uv_connect_t) + unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) + -> *uv_stream_t { + ret rustrt::rust_uv_get_stream_handle_from_connect_req( + connect); + } + unsafe fn get_stream_handle_from_write_req( + write_req: *uv_write_t) -> *uv_stream_t { - ret rustrt::rust_uv_get_stream_handle_for_connect(connect); + ret rustrt::rust_uv_get_stream_handle_from_write_req( + write_req); } unsafe fn get_data_for_req(req: *libc::c_void) -> *libc::c_void { @@ -392,10 +412,12 @@ mod direct { ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port as libc::c_int); } - // this is lame. - // TODO: see github issue #1402 - unsafe fn free_1402(ptr: *libc::c_void) { - rustrt::rust_uv_free(ptr); + unsafe fn malloc_buf_base_of(suggested_size: libc::size_t) + -> *u8 { + ret rustrt::rust_uv_malloc_buf_base_of(suggested_size); + } + unsafe fn free_base_of_buf(buf: uv_buf_t) { + rustrt::rust_uv_free_base_of_buf(buf); } } @@ -948,42 +970,80 @@ fn test_uv_timer() { // BEGIN TCP REQUEST TEST SUITE +enum tcp_read_data { + tcp_read_eof, + tcp_read_more([u8]), + tcp_read_error +} + type request_wrapper = { write_req: *uv_write_t, - req_buf: *[uv_buf_t] + req_buf: *[uv_buf_t], + read_chan: comm::chan }; -crust fn on_write_complete_cb(write_handle: *uv_write_t, +crust fn on_alloc_cb(handle: *libc::c_void, + suggested_size: libc::size_t) -> uv_buf_t + unsafe { + io::println("on_alloc_cb!"); + let char_ptr = direct::malloc_buf_base_of(suggested_size); + ret direct::buf_init(char_ptr, suggested_size); +} + +// do I need the explicit copy on the buf param? +crust fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, + ++buf: uv_buf_t) unsafe { + if (nread > 0) { + // we have data + io::println(#fmt("read: data! nread: %d", nread)); + } + else if (nread == -1) { + // err .. possibly EOF + io::println("read: eof!"); + } + else { + // nread == 0 .. do nothing, just free buf as below + io::println("read: do nothing!"); + } + // when we're done + direct::free_base_of_buf(buf); + io::println("exiting on_read_cb"); +} + +crust fn on_write_complete_cb(write_req: *uv_write_t, status: libc::c_int) unsafe { io::println(#fmt("beginning on_write_complete_cb status: %d", status as int)); - io::println("ending on_write_complete_cb"); + let stream = direct::get_stream_handle_from_write_req(write_req); + io::println(#fmt("on_write_complete_cb: tcp stream: %d write_handle addr %d", + stream as int, write_req as int)); + let result = direct::read_start(stream, on_alloc_cb, on_read_cb); + io::println(#fmt("ending on_write_complete_cb .. uv_read_start status: %d", result as int)); } -crust fn on_connect_cb(connect_handle_ptr: *uv_connect_t, +crust fn on_connect_cb(connect_req_ptr: *uv_connect_t, status: libc::c_int) unsafe { io::println(#fmt("beginning on_connect_cb .. status: %d", status as int)); - let stream = direct::get_stream_handle_for_connect(connect_handle_ptr); + let stream = + direct::get_stream_handle_from_connect_req(connect_req_ptr); if (status == 0i32) { io::println("on_connect_cb: in status=0 if.."); - let data = direct::get_data_for_req( - connect_handle_ptr as *libc::c_void) + let client_data = direct::get_data_for_req( + connect_req_ptr as *libc::c_void) as *request_wrapper; - let write_handle = (*data).write_req as *libc::c_void; + let write_handle = (*client_data).write_req as *libc::c_void; io::println(#fmt("on_connect_cb: tcp stream: %d write_handle addr %d", stream as int, write_handle as int)); let write_result = direct::write(write_handle, stream as *libc::c_void, - (*data).req_buf, + (*client_data).req_buf, on_write_complete_cb); io::println(#fmt("on_connect_cb: direct::write() status: %d", write_result as int)); } else { - let loop_handle = direct::get_loop_for_uv_handle( - stream as *libc::c_void); - let err = direct::uv_last_error(loop_handle); + io::println("non-zero status for on_connect_cb.."); } io::println("finishing on_connect_cb"); } @@ -993,7 +1053,7 @@ fn impl_uv_tcp_request() unsafe { let tcp_handle = direct::tcp_t(); let tcp_handle_ptr = ptr::addr_of(tcp_handle); let connect_handle = direct::connect_t(); - let connect_handle_ptr = ptr::addr_of(connect_handle); + 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. @@ -1013,8 +1073,11 @@ fn impl_uv_tcp_request() unsafe { io::println(#fmt("tcp req: tcp stream: %d write_handle: %d", tcp_handle_ptr as int, write_handle_ptr as int)); - let req = { writer_handle: write_handle_ptr, - req_buf: ptr::addr_of(req_msg) }; + let read_port = comm::port::(); + let read_chan = comm::chan::(read_port); + let client_data = { writer_handle: write_handle_ptr, + req_buf: ptr::addr_of(req_msg), + read_chan: read_chan }; let tcp_init_result = direct::tcp_init( test_loop as *libc::c_void, tcp_handle_ptr); @@ -1030,18 +1093,48 @@ fn impl_uv_tcp_request() unsafe { // this should set up the connection request.. let tcp_connect_result = direct::tcp_connect( - connect_handle_ptr, tcp_handle_ptr, + connect_req_ptr, tcp_handle_ptr, addr, on_connect_cb); if (tcp_connect_result == 0i32) { // not set the data on the connect_req // until its initialized direct::set_data_for_req( - connect_handle_ptr as *libc::c_void, - ptr::addr_of(req) as *libc::c_void); + connect_req_ptr as *libc::c_void, + ptr::addr_of(client_data) as *libc::c_void); io::println("before run tcp req loop"); direct::run(test_loop); io::println("after run tcp req loop"); - // TODO: see github issue #1402 + + // now we read from the port to get data + let mut read_bytes: [u8] = [0u8]; + let mut more_data = true; + while(more_data) { + alt comm::recv(read_port) { + tcp_read_eof { + more_data = false; + } + tcp_read_more(new_bytes) { + if (vec::len(read_bytes) == 1u && + read_bytes[0] == 0u8) { + // the "first" read.. replace + // the stubbed out vec above + // with our initial set of read + // data + } + else { + // otherwise append + read_bytes = new_bytes; + } + } + _ { + assert false; + } + } + } + io::println("finished reading data"); + let read_str = str::from_bytes(read_bytes); + + } else { io::println("direct::tcp_connect() failure"); @@ -1129,6 +1222,7 @@ fn impl_uv_byval_test() unsafe { addr.sin_port as uint)); } #[test] +#[ignore(cfg(target_os = "freebsd"))] fn test_uv_ip4_byval_passing_test() { impl_uv_byval_test(); } diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index b4694ccf37c57..f753c55c69e1a 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -230,9 +230,13 @@ rust_uv_helper_sockaddr_in_size() { } extern "C" uv_stream_t* -rust_uv_get_stream_handle_for_connect(uv_connect_t* connect) { +rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) { return connect->handle; } +extern "C" uv_stream_t* +rust_uv_get_stream_handle_from_write_req(uv_write_t* write_req) { + return write_req->handle; +} extern "C" uv_buf_t current_kernel_malloc_alloc_cb(uv_handle_t* handle, @@ -275,6 +279,16 @@ rust_uv_set_data_for_req(uv_req_t* req, void* data) { req->data = data; } +extern "C" char* +rust_uv_get_base_from_buf(uv_buf_t buf) { + return buf.base; +} + +extern "C" size_t +rust_uv_get_len_from_buf(uv_buf_t buf) { + return buf.len; +} + extern "C" uv_err_t rust_uv_last_error(uv_loop_t* loop) { return uv_last_error(loop); @@ -302,6 +316,21 @@ rust_uv_write(uv_write_t* req, uv_stream_t* handle, uv_write_cb cb) { return uv_write(req, handle, bufs, buf_cnt, cb); } +extern "C" int +rust_uv_read_start(uv_stream_t* stream, uv_alloc_cb on_alloc, + uv_read_cb on_read) { + return uv_read_start(stream, on_alloc, on_read); +} + +extern "C" char* +rust_uv_malloc_buf_base_of(size_t suggested_size) { + return (char*) current_kernel_malloc(sizeof(char)*suggested_size, + "uv_buf_t base"); +} +extern "C" void +rust_uv_free_base_of_buf(uv_buf_t buf) { + current_kernel_free(buf.base); +} extern "C" struct sockaddr_in rust_uv_ip4_addr(const char* ip, int port) { From 7cb131aaf02fb7186430c353e77345ee95ebbae8 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 26 Mar 2012 22:51:18 -0700 Subject: [PATCH 10/33] test_uv_tcp_request() fully working on linux .. up next: windows! .. impl'd uv::direct::read_stop() and uv::direct::close() to wrap things up .. demonstrated sending data out of the uv_read_cb via a channel (which we block on to recv all of it, complete w/ EOF notification) that is read from after the loop exits. .. helpers to read the guts of a uv_buf_t .. an idea im kicking around: starting to pile up all of these hideous data accessor functions in uv::direct .. I might make impl/iface pairs for the various uv_* types that I'm using, in order to encapsulate those data access functions and, perhaps, make the access look a little cleaner (it still won't be straight field access, but it'll be a lot better) .. formatting cleanup to satisfy make check --- src/libstd/uv.rs | 84 +++++++++++++++++++++++++++++++++++----------- src/rt/rust_uv.cpp | 5 +++ 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index fe22df30ae140..1539fbb392b95 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -82,7 +82,7 @@ type uv_handle_fields = { loop_handle: *libc::c_void, type_: handle_type, close_cb: *u8, - mutable data: *libc::c_void, + mut data: *libc::c_void, }; // unix size: 8 @@ -124,7 +124,7 @@ type uv_tcp_t = { fn gen_stub_uv_tcp_t() -> uv_tcp_t { ret { fields: { loop_handle: ptr::null(), type_: 0u32, close_cb: ptr::null(), - mutable data: ptr::null() }, + mut 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, @@ -157,13 +157,13 @@ type uv_connect_t = { #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] fn gen_stub_uv_connect_t() -> uv_connect_t { - ret { + ret { a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, a04: 0 as *u8, a05: 0 as *u8 }; } -// ref #1402 .. don't use this, like sockaddr_in +// ref #1402 .. don't use this, like sockaddr_in // unix size: 16 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] @@ -201,7 +201,7 @@ type uv_write_t = { fn gen_stub_uv_write_t() -> uv_write_t { ret { fields: { loop_handle: ptr::null(), type_: 0u32, close_cb: ptr::null(), - mutable data: ptr::null() }, + mut 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, @@ -287,6 +287,7 @@ native mod rustrt { cb: *u8) -> libc::c_int; fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8, on_read: *u8) -> libc::c_int; + fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int; fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; fn rust_uv_free_base_of_buf(++buf: uv_buf_t); @@ -314,6 +315,8 @@ native mod rustrt { fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void; fn rust_uv_set_data_for_req(req: *libc::c_void, data: *libc::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) -> libc::size_t; } // this module is structured around functions that directly @@ -332,6 +335,10 @@ mod direct { rustrt::rust_uv_run(loop_handle); } + unsafe fn close(handle: *libc::c_void, cb: *u8) { + rustrt::rust_uv_close(handle, cb); + } + unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t) -> libc::c_int { ret rustrt::rust_uv_tcp_init(loop_handle, handle); @@ -341,7 +348,8 @@ mod direct { address: sockaddr_in, after_connect_cb: *u8) -> libc::c_int { - io::println(#fmt("before native tcp_connect -- addr port: %u", address.sin_port as uint)); + io::println(#fmt("b4 native tcp_connect--addr port: %u", + address.sin_port as uint)); ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, address, after_connect_cb); } @@ -361,6 +369,10 @@ mod direct { on_alloc, on_read); } + unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int { + ret rustrt::rust_uv_read_stop(stream as *libc::c_void); + } + unsafe fn uv_last_error(loop_handle: *libc::c_void) -> uv_err_t { ret rustrt::rust_uv_last_error(loop_handle); } @@ -391,6 +403,13 @@ mod direct { write_req); } + unsafe fn get_data_for_uv_handle(handle: *libc::c_void) -> *libc::c_void { + ret rustrt::rust_uv_get_data_for_uv_handle(handle); + } + unsafe fn set_data_for_uv_handle(handle: *libc::c_void, + data: *libc::c_void) { + rustrt::rust_uv_set_data_for_uv_handle(handle, data); + } unsafe fn get_data_for_req(req: *libc::c_void) -> *libc::c_void { ret rustrt::rust_uv_get_data_for_req(req); } @@ -398,7 +417,12 @@ mod direct { data: *libc::c_void) { rustrt::rust_uv_set_data_for_req(req, data); } - // TODO: see github issue #1402 + unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { + ret rustrt::rust_uv_get_base_from_buf(buf); + } + unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t { + ret rustrt::rust_uv_get_len_from_buf(buf); + } unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { ret rustrt::rust_uv_buf_init(input, len); } @@ -408,7 +432,8 @@ mod direct { addr_vec += [0u8]; // add null terminator let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); let ip_back = str::from_bytes(addr_vec); - io::println(#fmt("vec val: '%s' length: %u",ip_back, vec::len(addr_vec))); + io::println(#fmt("vec val: '%s' length: %u", + ip_back, vec::len(addr_vec))); ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port as libc::c_int); } @@ -982,6 +1007,10 @@ type request_wrapper = { read_chan: comm::chan }; +crust fn after_close_cb(handle: *libc::c_void) { + io::println("after uv_close!"); +} + crust fn on_alloc_cb(handle: *libc::c_void, suggested_size: libc::size_t) -> uv_buf_t unsafe { @@ -990,12 +1019,22 @@ crust fn on_alloc_cb(handle: *libc::c_void, ret direct::buf_init(char_ptr, suggested_size); } -// do I need the explicit copy on the buf param? crust fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, ++buf: uv_buf_t) unsafe { if (nread > 0) { // we have data io::println(#fmt("read: data! nread: %d", nread)); + direct::read_stop(stream); + let client_data = direct:: + get_data_for_uv_handle(stream as *libc::c_void) + as *request_wrapper; + let buf_base = direct::get_base_from_buf(buf); + let buf_len = direct::get_len_from_buf(buf); + let bytes = vec::unsafe::from_buf(buf_base, buf_len); + let read_chan = (*client_data).read_chan; + comm::send(read_chan, tcp_read_more(bytes)); + comm::send(read_chan, tcp_read_eof); + direct::close(stream as *libc::c_void, after_close_cb) } else if (nread == -1) { // err .. possibly EOF @@ -1015,10 +1054,11 @@ crust fn on_write_complete_cb(write_req: *uv_write_t, io::println(#fmt("beginning on_write_complete_cb status: %d", status as int)); let stream = direct::get_stream_handle_from_write_req(write_req); - io::println(#fmt("on_write_complete_cb: tcp stream: %d write_handle addr %d", + io::println(#fmt("on_write_complete_cb: tcp:%d write_handle:%d", stream as int, write_req as int)); let result = direct::read_start(stream, on_alloc_cb, on_read_cb); - io::println(#fmt("ending on_write_complete_cb .. uv_read_start status: %d", result as int)); + io::println(#fmt("ending on_write_complete_cb .. status: %d", + result as int)); } crust fn on_connect_cb(connect_req_ptr: *uv_connect_t, @@ -1078,19 +1118,19 @@ fn impl_uv_tcp_request() unsafe { let client_data = { writer_handle: write_handle_ptr, req_buf: ptr::addr_of(req_msg), read_chan: read_chan }; - + let tcp_init_result = direct::tcp_init( test_loop as *libc::c_void, tcp_handle_ptr); if (tcp_init_result == 0i32) { io::println("sucessful tcp_init_result"); - + io::println("building addr..."); let addr = direct::ip4_addr("173.194.33.40", 80); io::println(#fmt("after build addr in rust. port: %u", addr.sin_port as uint)); //let addr: *libc::c_void = ptr::addr_of(addr_val) as // *libc::c_void; - + // this should set up the connection request.. let tcp_connect_result = direct::tcp_connect( connect_req_ptr, tcp_handle_ptr, @@ -1101,6 +1141,9 @@ fn impl_uv_tcp_request() unsafe { direct::set_data_for_req( connect_req_ptr as *libc::c_void, ptr::addr_of(client_data) as *libc::c_void); + direct::set_data_for_uv_handle( + tcp_handle_ptr as *libc::c_void, + ptr::addr_of(client_data) as *libc::c_void); io::println("before run tcp req loop"); direct::run(test_loop); io::println("after run tcp req loop"); @@ -1120,10 +1163,11 @@ fn impl_uv_tcp_request() unsafe { // the stubbed out vec above // with our initial set of read // data + read_bytes = new_bytes; } else { // otherwise append - read_bytes = new_bytes; + read_bytes += new_bytes; } } _ { @@ -1131,10 +1175,12 @@ fn impl_uv_tcp_request() unsafe { } } } - io::println("finished reading data"); + io::println("finished reading data, output to follow:"); let read_str = str::from_bytes(read_bytes); - - + + io::println(read_str); + io::println(">>>>EOF<<<<"); + direct::loop_delete(test_loop); } else { io::println("direct::tcp_connect() failure"); @@ -1145,7 +1191,7 @@ fn impl_uv_tcp_request() unsafe { io::println("direct::tcp_init() failure"); assert false; } - + } // START HERE AND WORK YOUR WAY UP VIA CALLBACKS #[test] diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index f753c55c69e1a..90832f7c3cdf2 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -322,6 +322,11 @@ rust_uv_read_start(uv_stream_t* stream, uv_alloc_cb on_alloc, return uv_read_start(stream, on_alloc, on_read); } +extern "C" int +rust_uv_read_stop(uv_stream_t* stream) { + return uv_read_stop(stream); +} + extern "C" char* rust_uv_malloc_buf_base_of(size_t suggested_size) { return (char*) current_kernel_malloc(sizeof(char)*suggested_size, From c4eeb08e7f501b08b75ed2ae805b31ae83a92356 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 27 Mar 2012 14:28:05 -0700 Subject: [PATCH 11/33] win32 tweaks --- src/libstd/uv.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 1539fbb392b95..32d292bd14266 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -99,6 +99,7 @@ type uv_err_t = { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] type uv_stream_t = { fields: uv_handle_fields }; @@ -107,6 +108,7 @@ type uv_stream_t = { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] type uv_tcp_t = { fields: uv_handle_fields, a00: *u8, a01: *u8, a02: *u8, a03: *u8, @@ -121,6 +123,7 @@ type uv_tcp_t = { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] fn gen_stub_uv_tcp_t() -> uv_tcp_t { ret { fields: { loop_handle: ptr::null(), type_: 0u32, close_cb: ptr::null(), @@ -136,6 +139,7 @@ fn gen_stub_uv_tcp_t() -> uv_tcp_t { }; } +/* #[cfg(target_os = "win32")] type uv_tcp_t = { loop_handle: *libc::c_void @@ -144,11 +148,13 @@ type uv_tcp_t = { fn gen_stub_uv_tcp_t() -> uv_tcp_t { ret { loop_handle: ptr::null() }; } +*/ // unix size: 48 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] type uv_connect_t = { a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8 @@ -156,6 +162,7 @@ type uv_connect_t = { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] fn gen_stub_uv_connect_t() -> uv_connect_t { ret { a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, @@ -168,6 +175,7 @@ fn gen_stub_uv_connect_t() -> uv_connect_t { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] type uv_buf_t = { base: *u8, len: libc::size_t @@ -175,19 +183,11 @@ type uv_buf_t = { // no gen stub method.. should create // it via uv::direct::buf_init() -#[cfg(target_os = "win32")] -type uv_connect_t = { - loop_handle: *libc::c_void -}; -#[cfg(target_os = "win32")] -fn gen_stub_uv_connect_t() -> uv_connect_t { - ret { loop_handle: ptr::null() }; -} - // unix size: 144 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] type uv_write_t = { fields: uv_handle_fields, a00: *u8, a01: *u8, a02: *u8, a03: *u8, @@ -198,6 +198,7 @@ type uv_write_t = { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] fn gen_stub_uv_write_t() -> uv_write_t { ret { fields: { loop_handle: ptr::null(), type_: 0u32, close_cb: ptr::null(), @@ -208,19 +209,12 @@ fn gen_stub_uv_write_t() -> uv_write_t { a12: 0 as *u8, a13: 0 as *u8 }; } -#[cfg(target_os = "win32")] -type uv_write_t = { - loop_handle: *libc::c_void -}; -#[cfg(target_os = "win32")] -fn gen_stub_uv_write_t() -> uv_write_t { - ret { loop_handle: ptr::null() }; -} // unix size: 16 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] type sockaddr_in = { mut sin_family: u16, mut sin_port: u16, @@ -229,6 +223,10 @@ type sockaddr_in = { }; // unix size: 28 .. make due w/ 32 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] type sockaddr_in6 = { a0: *u8, a1: *u8, a2: *u8, a3: *u8 From 4e29a7da5eb9140527eff9c1867ba339aac431fa Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 28 Mar 2012 08:33:38 -0700 Subject: [PATCH 12/33] adding missing rust_uv_* entries in rustrt.def.in --- src/rt/rustrt.def.in | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index c392b7142e15a..744f4999d8605 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -94,6 +94,33 @@ rust_uv_async_init rust_uv_timer_init rust_uv_timer_start rust_uv_timer_stop +rust_uv_free +rust_uv_tcp_init +rust_uv_buf_init +rust_uv_last_error +rust_uv_ip4_test_verify_port_val +rust_uv_ip4_addr +rust_uv_tcp_connect +rust_uv_write +rust_uv_read_start +rust_uv_read_stop +rust_uv_malloc_buf_base_of +rust_uv_free_base_of_buf +rust_uv_helper_uv_tcp_t_size +rust_uv_helper_uv_connect_t_size +rust_uv_helper_uv_buf_t_size +rust_uv_helper_uv_write_t_size +rust_uv_helper_uv_err_t_size +rust_uv_helper_sockaddr_in_size +rust_uv_get_stream_handle_from_connect_req +rust_uv_get_stream_handle_from_write_req +rust_uv_get_loop_for_uv_handle +rust_uv_get_data_for_uv_handle +rust_uv_set_data_for_uv_handle +rust_uv_get_data_for_req +rust_uv_set_data_for_req +rust_uv_get_base_from_buf +rust_uv_get_len_from_buf rust_dbg_lock_create rust_dbg_lock_destroy rust_dbg_lock_lock From b0ecc80a5dfb37351a0672fbab397b2dfa830d9f Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 28 Mar 2012 08:34:03 -0700 Subject: [PATCH 13/33] massaging out struct-size differences between unix and win32 --- src/libstd/uv.rs | 78 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 32d292bd14266..69168cc5c600d 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -108,7 +108,6 @@ type uv_stream_t = { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] type uv_tcp_t = { fields: uv_handle_fields, a00: *u8, a01: *u8, a02: *u8, a03: *u8, @@ -120,10 +119,21 @@ type uv_tcp_t = { a24: *u8, a25: *u8, a26: *u8, a27: *u8, a28: *u8, a29: *u8 }; +// win32 size: 240 (120) +#[cfg(target_os = "win32")] +type 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 +}; #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] fn gen_stub_uv_tcp_t() -> uv_tcp_t { ret { fields: { loop_handle: ptr::null(), type_: 0u32, close_cb: ptr::null(), @@ -138,35 +148,51 @@ fn gen_stub_uv_tcp_t() -> uv_tcp_t { a28: 0 as *u8, a29: 0 as *u8 }; } - -/* -#[cfg(target_os = "win32")] -type uv_tcp_t = { - loop_handle: *libc::c_void -}; #[cfg(target_os = "win32")] fn gen_stub_uv_tcp_t() -> uv_tcp_t { - ret { loop_handle: ptr::null() }; + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 + }; } -*/ // unix size: 48 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] type uv_connect_t = { a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8 }; +// win32 size: 88 (44) +#[cfg(target_os = "win32")] +type 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 +}; #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] fn gen_stub_uv_connect_t() -> uv_connect_t { ret { a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, - a04: 0 as *u8, a05: 0 as *u8 + a01: 0 as *u8, a05: 0 as *u8 + }; +} +#[cfg(target_os = "win32")] +fn gen_stub_uv_connect_t() -> uv_connect_t { + ret { + 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 }; } @@ -187,7 +213,6 @@ type uv_buf_t = { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] type uv_write_t = { fields: uv_handle_fields, a00: *u8, a01: *u8, a02: *u8, a03: *u8, @@ -195,10 +220,18 @@ type uv_write_t = { a08: *u8, a09: *u8, a10: *u8, a11: *u8, a12: *u8, a13: *u8 }; +// win32 size: 136 (68) +#[cfg(target_os = "win32")] +type 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 +}; #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] fn gen_stub_uv_write_t() -> uv_write_t { ret { fields: { loop_handle: ptr::null(), type_: 0u32, close_cb: ptr::null(), @@ -209,6 +242,17 @@ fn gen_stub_uv_write_t() -> uv_write_t { a12: 0 as *u8, a13: 0 as *u8 }; } +#[cfg(target_os = "win32")] +fn gen_stub_uv_write_t() -> uv_write_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 + }; +} // unix size: 16 #[cfg(target_os = "linux")] @@ -260,10 +304,6 @@ native mod rustrt { timeout: libc::c_uint, repeat: libc::c_uint); fn rust_uv_timer_stop(handle: *libc::c_void); - - //////////// - // NOT IN rustrt.def.in - //////////// fn rust_uv_free(ptr: *libc::c_void); fn rust_uv_tcp_init( loop_handle: *libc::c_void, From b6aa8527ea6c0903f03e5dd3837c33036b9dbb86 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 28 Mar 2012 08:51:44 -0700 Subject: [PATCH 14/33] fixed unix uv struct err from prev commit, also starting uv docs --- src/libstd/uv.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 69168cc5c600d..a6aeb5c9ffa83 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -1,8 +1,30 @@ +#[doc = " +Rust mappings to libuv (http://github.com/joyent/libuv) + +This crate provides a low-level mapping to libuv, a library for +running an asynchronous event loop, with extensive IO operations. + +This crate is seeing heavy work, currently, and the final API layout +should not be inferred from its current form. + +The base module contains a set of safe functions for creating +an event loop that runs within a single task, but allows operations +against it from other tasks, but funneling it through a uv_async +request which reads from a port that users write to. + +The 'll' module contains low-level, bare-metal mappings to the libuv +C-api. All functions within this module are marked unsafe and should +be used, primarily, for composing rust-idiomatic abstractions. In +lieu of satisfactory documention for the 'll' module, itself, libuv's +uv.h should be consulted. +"]; + import map::hashmap; export loop_new, loop_delete, run, close, run_in_bg; export async_init, async_send; export timer_init, timer_start, timer_stop; export uv_ip4_addr, uv_ip6_addr; +export direct; // these are processed solely in the // process_operation() crust fn below @@ -184,7 +206,7 @@ type uv_connect_t = { fn gen_stub_uv_connect_t() -> uv_connect_t { ret { a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, - a01: 0 as *u8, a05: 0 as *u8 + a04: 0 as *u8, a05: 0 as *u8 }; } #[cfg(target_os = "win32")] From ea87457d2c4fc74b9051c68dcbf4d0896c874d3a Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 28 Mar 2012 14:00:58 -0700 Subject: [PATCH 15/33] fixing libuv stuff in win32 (see #2064) .. pass sockaddr_in by-ref, for now --- src/libstd/uv.rs | 22 +++++++++++++--------- src/rt/rust_uv.cpp | 8 +++++--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index a6aeb5c9ffa83..6f9e5a5186a66 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -340,8 +340,8 @@ native mod rustrt { -> sockaddr_in; fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, - ++addr: sockaddr_in, - after_cb: *u8) -> libc::c_int; + ++after_cb: *u8, + ++addr: *sockaddr_in) -> libc::c_int; 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; @@ -405,13 +405,14 @@ mod direct { } unsafe fn tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, - address: sockaddr_in, - after_connect_cb: *u8) + addr_ptr: *sockaddr_in, + ++after_connect_cb: *u8) -> libc::c_int { - io::println(#fmt("b4 native tcp_connect--addr port: %u", - address.sin_port as uint)); + let address = *addr_ptr; + io::println(#fmt("b4 native tcp_connect--addr port: %u cb: %u", + address.sin_port as uint, after_connect_cb as uint)); ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, - address, after_connect_cb); + after_connect_cb, addr_ptr); } // TODO github #1402 -- the buf_in is a vector of pointers @@ -1185,16 +1186,19 @@ fn impl_uv_tcp_request() unsafe { io::println("sucessful tcp_init_result"); io::println("building addr..."); - let addr = direct::ip4_addr("173.194.33.40", 80); + let addr = direct::ip4_addr("74.125.227.16", 80); + let addr_ptr = ptr::addr_of(addr); io::println(#fmt("after build addr in rust. port: %u", addr.sin_port as uint)); //let addr: *libc::c_void = ptr::addr_of(addr_val) as // *libc::c_void; // this should set up the connection request.. + io::println(#fmt("before calling tcp_connect .. connect cb ptr: %u ", + on_connect_cb as uint)); let tcp_connect_result = direct::tcp_connect( connect_req_ptr, tcp_handle_ptr, - addr, on_connect_cb); + addr_ptr, on_connect_cb); if (tcp_connect_result == 0i32) { // not set the data on the connect_req // until its initialized diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 90832f7c3cdf2..7ed4124a690e1 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -293,17 +293,19 @@ extern "C" uv_err_t rust_uv_last_error(uv_loop_t* loop) { return uv_last_error(loop); } - extern "C" int rust_uv_tcp_connect(uv_connect_t* connect_ptr, uv_tcp_t* tcp_ptr, - struct sockaddr_in addr, - uv_connect_cb cb) { + uv_connect_cb cb, + sockaddr_in* addr_ptr) { //return uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); printf("inside rust_uv_tcp_connect\n"); //sockaddr_in addr_tmp = *((sockaddr_in*)addr_ptr); //sockaddr_in addr = addr_tmp; + sockaddr_in addr = *addr_ptr; printf("before tcp_connect .. port: %d\n", addr.sin_port); + //int result = uv_tcp_connect(connect_ptr, tcp_ptr, loc_addr, cb); + printf("before tcp_connect.. tcp stream: %lu cb ptr: %lu\n", (unsigned long int)tcp_ptr, (unsigned long int)cb); int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); printf ("leaving rust_uv_tcp_connect.. and result: %d\n", result); From 527b7c48baeeaa8937371ff7109e1ec0df9a2411 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 29 Mar 2012 15:11:21 -0700 Subject: [PATCH 16/33] hello world test for a tcp server in libuv .. im now going to refactor the tcp request and server tests to utilize each other, so no more external network ugliness --- src/libstd/uv.rs | 215 ++++++++++++++++++++++++++++++++++++++++--- src/rt/rust_uv.cpp | 73 ++++++++++----- src/rt/rustrt.def.in | 8 +- 3 files changed, 257 insertions(+), 39 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 6f9e5a5186a66..6c56871a771d1 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -218,7 +218,6 @@ fn gen_stub_uv_connect_t() -> uv_connect_t { }; } -// ref #1402 .. don't use this, like sockaddr_in // unix size: 16 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] @@ -310,8 +309,9 @@ native mod rustrt { fn rust_uv_stop_op_cb(handle: *libc::c_void); fn rust_uv_run(loop_handle: *libc::c_void); fn rust_uv_close(handle: *libc::c_void, cb: *u8); - fn rust_uv_close_async(handle: *libc::c_void); - fn rust_uv_close_timer(handle: *libc::c_void); + fn rust_uv_hilvl_close(handle: *libc::c_void, cb: *u8); + fn rust_uv_hilvl_close_async(handle: *libc::c_void); + fn rust_uv_hilvl_close_timer(handle: *libc::c_void); fn rust_uv_async_send(handle: *libc::c_void); fn rust_uv_async_init( loop_handle: *libc::c_void, @@ -338,10 +338,18 @@ native mod rustrt { -> bool; fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) -> sockaddr_in; + // 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) -> libc::c_int; + // FIXME ref 2064 + fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, + ++addr: *sockaddr_in) -> libc::c_int; + fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int, + cb: *u8) -> libc::c_int; + fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) + -> libc::c_int; 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; @@ -403,6 +411,7 @@ mod direct { -> libc::c_int { ret rustrt::rust_uv_tcp_init(loop_handle, handle); } + // FIXME ref #2064 unsafe fn tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in, @@ -414,10 +423,23 @@ mod direct { ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr); } + // FIXME ref #2064 + unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in) -> libc::c_int { + ret rustrt::rust_uv_tcp_bind(tcp_server_ptr, + addr_ptr); + } + + unsafe fn listen(stream: *libc::c_void, backlog: libc::c_int, + cb: *u8) -> libc::c_int { + ret rustrt::rust_uv_listen(stream, backlog, cb); + } + + unsafe fn accept(server: *libc::c_void, client: *libc::c_void) + -> libc::c_int { + ret rustrt::rust_uv_accept(server, client); + } - // TODO github #1402 -- the buf_in is a vector of pointers - // to malloc'd buffers .. these will have to be translated - // back into their value types in c. sigh. unsafe fn write(req: *libc::c_void, stream: *libc::c_void, buf_in: *[uv_buf_t], cb: *u8) -> libc::c_int { let buf_ptr = vec::unsafe::to_ptr(*buf_in); @@ -944,12 +966,12 @@ fn handle_op_close(handle: uv_handle, handle_ptr: *libc::c_void) { alt handle { uv_async(id, lp) { let cb = process_close_async; - rustrt::rust_uv_close( + rustrt::rust_uv_hilvl_close( handle_ptr, cb); } uv_timer(id, lp) { let cb = process_close_timer; - rustrt::rust_uv_close( + rustrt::rust_uv_hilvl_close( handle_ptr, cb); } _ { @@ -988,7 +1010,7 @@ crust fn process_close_async( data: *uv_loop_data) unsafe { let id = get_handle_id_from(id_buf); - rustrt::rust_uv_close_async(handle_ptr); + rustrt::rust_uv_hilvl_close_async(handle_ptr); // at this point, the handle and its data has been // released. notify the rust loop to remove the // handle and its data and call the user-supplied @@ -1002,7 +1024,7 @@ crust fn process_close_timer( data: *uv_loop_data) unsafe { let id = get_handle_id_from(id_buf); - rustrt::rust_uv_close_timer(handle_ptr); + rustrt::rust_uv_hilvl_close_timer(handle_ptr); process_close_common(id, data); } @@ -1187,11 +1209,10 @@ fn impl_uv_tcp_request() unsafe { io::println("building addr..."); let addr = direct::ip4_addr("74.125.227.16", 80); + // FIXME ref #2064 let addr_ptr = ptr::addr_of(addr); io::println(#fmt("after build addr in rust. port: %u", addr.sin_port as uint)); - //let addr: *libc::c_void = ptr::addr_of(addr_val) as - // *libc::c_void; // this should set up the connection request.. io::println(#fmt("before calling tcp_connect .. connect cb ptr: %u ", @@ -1265,6 +1286,176 @@ fn test_uv_tcp_request() unsafe { } // END TCP REQUEST TEST SUITE +crust fn server_after_close_cb(handle: *libc::c_void) unsafe { + io::println("server stream closed, should exit loop..."); +} + +crust fn client_stream_after_close_cb(handle: *libc::c_void) + unsafe { + io::println("closed client stream, now server.."); + let client_data = direct::get_data_for_uv_handle( + handle) as + *tcp_server_data; + direct::close((*client_data).server as *libc::c_void, + server_after_close_cb); +} + +crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, + nread: libc::ssize_t, + ++buf: uv_buf_t) unsafe { + if (nread > 0) { + // we have data + io::println(#fmt("read: data! nread: %d", nread)); + + // pull out the contents of the write from the client + let buf_base = direct::get_base_from_buf(buf); + let buf_len = direct::get_len_from_buf(buf); + let bytes = vec::unsafe::from_buf(buf_base, buf_len); + let request_str = str::from_bytes(bytes); + io::println("client req to follow"); + io::println(request_str); + io::println("end of client read"); + + if (str::contains(request_str, ">>EOF<<")) { + let client_data = direct::get_data_for_uv_handle( + client_stream_ptr as *libc::c_void) as + *tcp_server_data; + direct::read_stop(client_stream_ptr); + direct::close(client_stream_ptr as *libc::c_void, + client_stream_after_close_cb) + } + } + else if (nread == -1) { + // err .. possibly EOF + io::println("read: eof!"); + } + else { + // nread == 0 .. do nothing, just free buf as below + io::println("read: do nothing!"); + } + // when we're done + direct::free_base_of_buf(buf); + io::println("exiting on_read_cb"); +} + +crust fn server_connection_cb(server_stream_ptr: *uv_stream_t, + status: libc::c_int) unsafe { + io::println("client connecting!"); + let test_loop = direct::get_loop_for_uv_handle( + server_stream_ptr as *libc::c_void); + let server_data = direct::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 = direct::tcp_init(test_loop, + client_stream_ptr); + direct::set_data_for_uv_handle( + client_stream_ptr as *libc::c_void, + server_data as *libc::c_void); + if (client_init_result == 0i32) { + io::println("successfully initialized client stream"); + let accept_result = direct::accept(server_stream_ptr as + *libc::c_void, + client_stream_ptr as + *libc::c_void); + if (accept_result == 0i32) { + // start reading + let read_result = direct::read_start(client_stream_ptr + as *uv_stream_t, + on_alloc_cb, + on_server_read_cb); + if (read_result == 0i32) { + io::println("successful server read start"); + } + else { + io::println(#fmt("server_connection_cb: bad read:%d", + read_result as int)); + assert false; + } + } + else { + io::println(#fmt("server_connection_cb: bad accept: %d", + accept_result as int)); + assert false; + } + } + else { + io::println(#fmt("server_connection_cb: bad client init: %d", + client_init_result as int)); + assert false; + } +} + +type tcp_server_data = { + client: *uv_tcp_t, + server: *uv_tcp_t +}; + +fn impl_uv_tcp_server(server_ip: str, server_port: int) unsafe { + let test_loop = direct::loop_new(); + let tcp_server = direct::tcp_t(); + let tcp_server_ptr = ptr::addr_of(tcp_server); + + let tcp_client = direct::tcp_t(); + let tcp_client_ptr = ptr::addr_of(tcp_client); + + let server_data: tcp_server_data = { + client: tcp_client_ptr, + server: tcp_server_ptr + }; + let server_data_ptr = ptr::addr_of(server_data); + direct::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 = direct::tcp_init( + test_loop as *libc::c_void, tcp_server_ptr); + if (tcp_init_result == 0i32) { + let server_addr = direct::ip4_addr(server_ip, server_port); + // FIXME ref #2064 + let server_addr_ptr = ptr::addr_of(server_addr); + + // uv_tcp_bind() + let bind_result = direct::tcp_bind(tcp_server_ptr, + server_addr_ptr); + if (bind_result == 0i32) { + io::println("successful uv_tcp_bind, listening"); + + // uv_listen() + let listen_result = direct::listen(tcp_server_ptr as + *libc::c_void, + 128i32, + server_connection_cb); + if (listen_result == 0i32) { + // uv_run() + direct::run(test_loop); + } + else { + io::println(#fmt("non-zero result on uv_listen: %d", + listen_result as int)); + assert false; + } + + direct::loop_delete(test_loop); + } + else { + io::println(#fmt("non-zero result on uv_tcp_bind: %d", + bind_result as int)); + assert false; + } + } + else { + io::println(#fmt("non-zero result on uv_tcp_init: %d", + tcp_init_result as int)); + assert false; + } +} + +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_tcp_server() unsafe { + impl_uv_tcp_server("0.0.0.0", 8888); +} + // struct size tests #[test] #[ignore(cfg(target_os = "freebsd"))] diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 7ed4124a690e1..7a6a79ce17bff 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -139,20 +139,25 @@ rust_uv_run(uv_loop_t* loop) { } extern "C" void -rust_uv_close(uv_handle_t* handle, crust_close_cb cb) { - handle_data* data = (handle_data*)handle->data; - data->close_cb = cb; - uv_close(handle, native_close_cb); +rust_uv_close(uv_handle_t* handle, uv_close_cb cb) { + uv_close(handle, cb); +} + +extern "C" void +rust_uv_hilvl_close(uv_handle_t* handle, crust_close_cb cb) { + handle_data* data = (handle_data*)handle->data; + data->close_cb = cb; + uv_close(handle, native_close_cb); } extern "C" void -rust_uv_close_async(uv_async_t* handle) { +rust_uv_hilvl_close_async(uv_async_t* handle) { current_kernel_free(handle->data); current_kernel_free(handle); } extern "C" void -rust_uv_close_timer(uv_async_t* handle) { +rust_uv_hilvl_close_timer(uv_async_t* handle) { current_kernel_free(handle->data); current_kernel_free(handle); } @@ -204,6 +209,43 @@ rust_uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { return uv_tcp_init(loop, handle); } +extern "C" int +rust_uv_tcp_connect(uv_connect_t* connect_ptr, + uv_tcp_t* tcp_ptr, + uv_connect_cb cb, + sockaddr_in* addr_ptr) { + printf("inside rust_uv_tcp_connect\n"); + // FIXME ref #2064 + sockaddr_in addr = *addr_ptr; + printf("before tcp_connect .. port: %d\n", addr.sin_port); + printf("before tcp_connect.. tcp stream: %lu cb ptr: %lu\n", + (unsigned long int)tcp_ptr, (unsigned long int)cb); + int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); + printf ("leaving rust_uv_tcp_connect.. and result: %d\n", + result); + return result; +} + +extern "C" int +rust_uv_tcp_bind(uv_tcp_t* tcp_server, sockaddr_in* addr_ptr) { + // FIXME ref #2064 + sockaddr_in addr = *addr_ptr; + printf("before uv_tcp_bind .. tcp_server: %lu port: %d\n", + (unsigned long int)tcp_server, addr.sin_port); + return uv_tcp_bind(tcp_server, addr); +} + +extern "C" int +rust_uv_listen(uv_stream_t* stream, int backlog, + uv_connection_cb cb) { + return uv_listen(stream, backlog, cb); +} + +extern "C" int +rust_uv_accept(uv_stream_t* server, uv_stream_t* client) { + return uv_accept(server, client); +} + extern "C" size_t rust_uv_helper_uv_tcp_t_size() { return sizeof(uv_tcp_t); @@ -247,7 +289,6 @@ current_kernel_malloc_alloc_cb(uv_handle_t* handle, return uv_buf_init(base_ptr, suggested_size); } -// FIXME see issue #1402 extern "C" uv_buf_t rust_uv_buf_init(char* base, size_t len) { return uv_buf_init(base, len); @@ -293,24 +334,6 @@ extern "C" uv_err_t rust_uv_last_error(uv_loop_t* loop) { return uv_last_error(loop); } -extern "C" int -rust_uv_tcp_connect(uv_connect_t* connect_ptr, - uv_tcp_t* tcp_ptr, - uv_connect_cb cb, - sockaddr_in* addr_ptr) { - //return uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); - printf("inside rust_uv_tcp_connect\n"); - //sockaddr_in addr_tmp = *((sockaddr_in*)addr_ptr); - //sockaddr_in addr = addr_tmp; - sockaddr_in addr = *addr_ptr; - printf("before tcp_connect .. port: %d\n", addr.sin_port); - //int result = uv_tcp_connect(connect_ptr, tcp_ptr, loc_addr, cb); - printf("before tcp_connect.. tcp stream: %lu cb ptr: %lu\n", (unsigned long int)tcp_ptr, (unsigned long int)cb); - int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); - printf ("leaving rust_uv_tcp_connect.. and result: %d\n", - result); - return result; -} extern "C" int rust_uv_write(uv_write_t* req, uv_stream_t* handle, diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 744f4999d8605..3369f6a3048e2 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -87,8 +87,9 @@ rust_uv_bind_op_cb rust_uv_stop_op_cb rust_uv_run rust_uv_close -rust_uv_close_async -rust_uv_close_timer +rust_uv_hilvl_close +rust_uv_hilvl_close_async +rust_uv_hilvl_close_timer rust_uv_async_send rust_uv_async_init rust_uv_timer_init @@ -101,6 +102,9 @@ rust_uv_last_error rust_uv_ip4_test_verify_port_val rust_uv_ip4_addr rust_uv_tcp_connect +rust_uv_tcp_bind +rust_uv_listen +rust_uv_accept rust_uv_write rust_uv_read_start rust_uv_read_stop From 0361de9b8595db76c9ce7e7bd175475d9d3c58dc Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 29 Mar 2012 23:11:41 -0700 Subject: [PATCH 17/33] refactored the tcp request and server tests into 1 test using loopback ..plus whitespace cleanup for make check --- src/libstd/uv.rs | 179 ++++++++++++++++++++++++++++------------------- 1 file changed, 106 insertions(+), 73 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 6c56871a771d1..5fab90330638a 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -211,7 +211,7 @@ fn gen_stub_uv_connect_t() -> uv_connect_t { } #[cfg(target_os = "win32")] fn gen_stub_uv_connect_t() -> uv_connect_t { - ret { + ret { 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 @@ -1076,8 +1076,6 @@ fn test_uv_timer() { uv::loop_delete(test_loop); } -// BEGIN TCP REQUEST TEST SUITE - enum tcp_read_data { tcp_read_eof, tcp_read_more([u8]), @@ -1087,7 +1085,7 @@ enum tcp_read_data { type request_wrapper = { write_req: *uv_write_t, req_buf: *[uv_buf_t], - read_chan: comm::chan + read_chan: *comm::chan }; crust fn after_close_cb(handle: *libc::c_void) { @@ -1114,9 +1112,9 @@ crust fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, let buf_base = direct::get_base_from_buf(buf); let buf_len = direct::get_len_from_buf(buf); let bytes = vec::unsafe::from_buf(buf_base, buf_len); - let read_chan = (*client_data).read_chan; - comm::send(read_chan, tcp_read_more(bytes)); - comm::send(read_chan, tcp_read_eof); + let read_chan = *((*client_data).read_chan); + let msg_from_server = str::from_bytes(bytes); + comm::send(read_chan, msg_from_server); direct::close(stream as *libc::c_void, after_close_cb) } else if (nread == -1) { @@ -1171,7 +1169,8 @@ crust fn on_connect_cb(connect_req_ptr: *uv_connect_t, io::println("finishing on_connect_cb"); } -fn impl_uv_tcp_request() unsafe { +fn impl_uv_tcp_request(ip: str, port: int, req_str: str, + client_chan: *comm::chan) unsafe { let test_loop = direct::loop_new(); let tcp_handle = direct::tcp_t(); let tcp_handle_ptr = ptr::addr_of(tcp_handle); @@ -1183,11 +1182,10 @@ fn impl_uv_tcp_request() unsafe { // 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 = str::bytes("GET / HTTP/1.1\r\nHost: google.com" - + "\r\n\r\n\r\n"); - let req_msg_ptr: *u8 = vec::unsafe::to_ptr(req_str); + let req_str_bytes = str::bytes(req_str); + let req_msg_ptr: *u8 = vec::unsafe::to_ptr(req_str_bytes); let req_msg = [ - direct::buf_init(req_msg_ptr, vec::len(req_str)) + direct::buf_init(req_msg_ptr, vec::len(req_str_bytes)) ]; // this is the enclosing record, we'll pass a ptr to // this to C.. @@ -1196,11 +1194,9 @@ fn impl_uv_tcp_request() unsafe { io::println(#fmt("tcp req: tcp stream: %d write_handle: %d", tcp_handle_ptr as int, write_handle_ptr as int)); - let read_port = comm::port::(); - let read_chan = comm::chan::(read_port); let client_data = { writer_handle: write_handle_ptr, req_buf: ptr::addr_of(req_msg), - read_chan: read_chan }; + read_chan: client_chan }; let tcp_init_result = direct::tcp_init( test_loop as *libc::c_void, tcp_handle_ptr); @@ -1208,7 +1204,7 @@ fn impl_uv_tcp_request() unsafe { io::println("sucessful tcp_init_result"); io::println("building addr..."); - let addr = direct::ip4_addr("74.125.227.16", 80); + let addr = direct::ip4_addr(ip, port); // FIXME ref #2064 let addr_ptr = ptr::addr_of(addr); io::println(#fmt("after build addr in rust. port: %u", @@ -1232,40 +1228,6 @@ fn impl_uv_tcp_request() unsafe { io::println("before run tcp req loop"); direct::run(test_loop); io::println("after run tcp req loop"); - - // now we read from the port to get data - let mut read_bytes: [u8] = [0u8]; - let mut more_data = true; - while(more_data) { - alt comm::recv(read_port) { - tcp_read_eof { - more_data = false; - } - tcp_read_more(new_bytes) { - if (vec::len(read_bytes) == 1u && - read_bytes[0] == 0u8) { - // the "first" read.. replace - // the stubbed out vec above - // with our initial set of read - // data - read_bytes = new_bytes; - } - else { - // otherwise append - read_bytes += new_bytes; - } - } - _ { - assert false; - } - } - } - io::println("finished reading data, output to follow:"); - let read_str = str::from_bytes(read_bytes); - - io::println(read_str); - io::println(">>>>EOF<<<<"); - direct::loop_delete(test_loop); } else { io::println("direct::tcp_connect() failure"); @@ -1276,15 +1238,9 @@ fn impl_uv_tcp_request() unsafe { io::println("direct::tcp_init() failure"); assert false; } + direct::loop_delete(test_loop); } -// START HERE AND WORK YOUR WAY UP VIA CALLBACKS -#[test] -#[ignore(cfg(target_os = "freebsd"))] -fn test_uv_tcp_request() unsafe { - impl_uv_tcp_request(); -} -// END TCP REQUEST TEST SUITE crust fn server_after_close_cb(handle: *libc::c_void) unsafe { io::println("server stream closed, should exit loop..."); @@ -1300,13 +1256,24 @@ crust fn client_stream_after_close_cb(handle: *libc::c_void) server_after_close_cb); } +crust fn after_server_resp_write(req: *uv_write_t) unsafe { + let client_stream_ptr = + direct::get_stream_handle_from_write_req(req); + let client_data = direct::get_data_for_uv_handle( + client_stream_ptr as *libc::c_void) as + *tcp_server_data; + direct::read_stop(client_stream_ptr); + direct::close(client_stream_ptr as *libc::c_void, + client_stream_after_close_cb) +} + crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, nread: libc::ssize_t, ++buf: uv_buf_t) unsafe { if (nread > 0) { // we have data io::println(#fmt("read: data! nread: %d", nread)); - + // pull out the contents of the write from the client let buf_base = direct::get_base_from_buf(buf); let buf_len = direct::get_len_from_buf(buf); @@ -1315,14 +1282,20 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, io::println("client req to follow"); io::println(request_str); io::println("end of client read"); - - if (str::contains(request_str, ">>EOF<<")) { - let client_data = direct::get_data_for_uv_handle( - client_stream_ptr as *libc::c_void) as - *tcp_server_data; - direct::read_stop(client_stream_ptr); - direct::close(client_stream_ptr as *libc::c_void, - client_stream_after_close_cb) + + let client_data = direct::get_data_for_uv_handle( + client_stream_ptr as *libc::c_void) as *tcp_server_data; + + let server_kill_msg = (*client_data).server_kill_msg; + let write_req = (*client_data).server_write_req; + if (str::contains(request_str, server_kill_msg)) { + let server_chan = *((*client_data).server_chan); + comm::send(server_chan, request_str); + let write_result = direct::write( + write_req as *libc::c_void, + client_stream_ptr as *libc::c_void, + (*client_data).server_resp_buf, + after_server_resp_write); } } else if (nread == -1) { @@ -1387,10 +1360,19 @@ crust fn server_connection_cb(server_stream_ptr: *uv_stream_t, type tcp_server_data = { client: *uv_tcp_t, - server: *uv_tcp_t + server: *uv_tcp_t, + server_kill_msg: str, + server_resp_buf: *[uv_buf_t], + server_chan: *comm::chan, + server_write_req: *uv_write_t }; -fn impl_uv_tcp_server(server_ip: str, server_port: int) unsafe { +fn impl_uv_tcp_server(server_ip: str, + server_port: int, + kill_server_msg: str, + server_resp_msg: str, + server_chan: *comm::chan, + continue_chan: comm::chan) unsafe { let test_loop = direct::loop_new(); let tcp_server = direct::tcp_t(); let tcp_server_ptr = ptr::addr_of(tcp_server); @@ -1398,9 +1380,22 @@ fn impl_uv_tcp_server(server_ip: str, server_port: int) unsafe { let tcp_client = direct::tcp_t(); let tcp_client_ptr = ptr::addr_of(tcp_client); + let server_write_req = direct::write_t(); + let server_write_req_ptr = ptr::addr_of(server_write_req); + + let resp_str_bytes = str::bytes(server_resp_msg); + let resp_msg_ptr: *u8 = vec::unsafe::to_ptr(resp_str_bytes); + let resp_msg = [ + direct::buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) + ]; + let server_data: tcp_server_data = { client: tcp_client_ptr, - server: tcp_server_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); direct::set_data_for_uv_handle(tcp_server_ptr as *libc::c_void, @@ -1426,6 +1421,10 @@ fn impl_uv_tcp_server(server_ip: str, server_port: int) unsafe { 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.. + comm::send(continue_chan, true); + // uv_run() direct::run(test_loop); } @@ -1434,8 +1433,6 @@ fn impl_uv_tcp_server(server_ip: str, server_port: int) unsafe { listen_result as int)); assert false; } - - direct::loop_delete(test_loop); } else { io::println(#fmt("non-zero result on uv_tcp_bind: %d", @@ -1448,12 +1445,48 @@ fn impl_uv_tcp_server(server_ip: str, server_port: int) unsafe { tcp_init_result as int)); assert false; } + direct::loop_delete(test_loop); } #[test] #[ignore(cfg(target_os = "freebsd"))] -fn test_uv_tcp_server() unsafe { - impl_uv_tcp_server("0.0.0.0", 8888); +fn test_uv_tcp_server_and_request() unsafe { + let ip = "0.0.0.0"; + let port = 8888; + let kill_server_msg = "does a dog have buddha nature?"; + let server_resp_msg = "mu!"; + let client_port = comm::port::(); + let client_chan = comm::chan::(client_port); + let server_port = comm::port::(); + let server_chan = comm::chan::(server_port); + + let continue_port = comm::port::(); + let continue_chan = comm::chan::(continue_port); + + task::spawn_sched(task::manual_threads(1u)) {|| + impl_uv_tcp_server(ip, port, + kill_server_msg, + server_resp_msg, + ptr::addr_of(server_chan), + continue_chan); + }; + + // block until the server up is.. possibly a race? + io::println("before receiving on server continue_port"); + comm::recv(continue_port); + io::println("received on continue port, set up tcp client"); + + task::spawn_sched(task::manual_threads(1u)) {|| + impl_uv_tcp_request(ip, port, + kill_server_msg, + ptr::addr_of(client_chan)); + }; + + let msg_from_client = comm::recv(server_port); + let msg_from_server = comm::recv(client_port); + + assert str::contains(msg_from_client, kill_server_msg); + assert str::contains(msg_from_server, server_resp_msg); } // struct size tests From db69531d389d2664ef82761dce187e983754b533 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 30 Mar 2012 07:19:45 -0700 Subject: [PATCH 18/33] add low-level uv_async bindings for use in tcp test --- src/libstd/uv.rs | 112 +++++++++++++++++++++++++++++++++++++++---- src/rt/rust_uv.cpp | 27 +++++++---- src/rt/rustrt.def.in | 2 + 3 files changed, 123 insertions(+), 18 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 5fab90330638a..0e21d1d5da6c3 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -274,6 +274,30 @@ fn gen_stub_uv_write_t() -> uv_write_t { a12: 0 as *u8 }; } +// unix size: 120 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +type 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 +}; +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +fn gen_stub_uv_async_t() -> uv_async_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 + }; +} // unix size: 16 #[cfg(target_os = "linux")] @@ -312,8 +336,11 @@ native mod rustrt { fn rust_uv_hilvl_close(handle: *libc::c_void, cb: *u8); fn rust_uv_hilvl_close_async(handle: *libc::c_void); fn rust_uv_hilvl_close_timer(handle: *libc::c_void); - fn rust_uv_async_send(handle: *libc::c_void); - fn rust_uv_async_init( + fn rust_uv_async_send(handle: *uv_async_t); + fn rust_uv_async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int; + fn rust_uv_hilvl_async_init( loop_handle: *libc::c_void, cb: *u8, id: *u8) -> *libc::c_void; @@ -366,6 +393,7 @@ native mod rustrt { fn rust_uv_helper_uv_write_t_size() -> libc::c_uint; fn rust_uv_helper_uv_err_t_size() -> libc::c_uint; fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; + fn rust_uv_helper_uv_async_t_size() -> libc::c_uint; // data accessors for rust-mapped uv structs fn rust_uv_get_stream_handle_from_connect_req( @@ -460,6 +488,18 @@ mod direct { ret rustrt::rust_uv_last_error(loop_handle); } + unsafe fn async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int { + ret rustrt::rust_uv_async_init(loop_handle, + async_handle, + cb); + } + + unsafe fn async_send(async_handle: *uv_async_t) { + ret rustrt::rust_uv_async_send(async_handle); + } + // libuv struct initializers unsafe fn tcp_t() -> uv_tcp_t { ret gen_stub_uv_tcp_t(); @@ -470,6 +510,9 @@ mod direct { unsafe fn write_t() -> uv_write_t { ret gen_stub_uv_write_t(); } + unsafe fn async_t() -> uv_async_t { + ret gen_stub_uv_async_t(); + } unsafe fn get_loop_for_uv_handle(handle: *libc::c_void) -> *libc::c_void { ret rustrt::rust_uv_get_loop_for_uv_handle(handle); @@ -855,7 +898,7 @@ fn pass_to_libuv( do_send(op_handle); } fn do_send(h: *libc::c_void) { - rustrt::rust_uv_async_send(h); + rustrt::rust_uv_async_send(h as *uv_async_t); } fn gen_handle_id() -> [u8] { ret rand::rng().gen_bytes(16u); @@ -920,7 +963,7 @@ crust fn process_operation( alt comm::recv(op_port) { op_async_init(id) { let id_ptr = vec::unsafe::to_ptr(id); - let async_handle = rustrt::rust_uv_async_init( + let async_handle = rustrt::rust_uv_hilvl_async_init( lp, process_async_send, id_ptr); @@ -1367,12 +1410,29 @@ type tcp_server_data = { server_write_req: *uv_write_t }; +type async_handle_data = { + continue_chan: *comm::chan +}; + +crust 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 = direct::get_data_for_uv_handle( + async_handle as *libc::c_void) as *async_handle_data; + let continue_chan = *((*data).continue_chan); + comm::send(continue_chan, true); + direct::close(async_handle as *libc::c_void, 0 as *u8); +} + fn impl_uv_tcp_server(server_ip: str, server_port: int, kill_server_msg: str, server_resp_msg: str, server_chan: *comm::chan, - continue_chan: comm::chan) unsafe { + continue_chan: *comm::chan) unsafe { let test_loop = direct::loop_new(); let tcp_server = direct::tcp_t(); let tcp_server_ptr = ptr::addr_of(tcp_server); @@ -1389,6 +1449,13 @@ fn impl_uv_tcp_server(server_ip: str, direct::buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) ]; + let continue_async_handle = direct::async_t(); + let continue_async_handle_ptr = + ptr::addr_of(continue_async_handle); + let async_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, @@ -1423,10 +1490,22 @@ fn impl_uv_tcp_server(server_ip: str, if (listen_result == 0i32) { // let the test know it can set up the tcp server, // now.. this may still present a race, not sure.. - comm::send(continue_chan, true); - - // uv_run() - direct::run(test_loop); + let async_result = direct::async_init(test_loop, + continue_async_handle_ptr, + continue_async_cb); + if (async_result == 0i32) { + direct::set_data_for_uv_handle( + continue_async_handle_ptr as *libc::c_void, + async_data_ptr as *libc::c_void); + direct::async_send(continue_async_handle_ptr); + // uv_run() + direct::run(test_loop); + } + else { + io::println(#fmt("uv_async_init failure: %d", + async_result as int)); + assert false; + } } else { io::println(#fmt("non-zero result on uv_listen: %d", @@ -1462,13 +1541,14 @@ fn test_uv_tcp_server_and_request() unsafe { let continue_port = comm::port::(); let continue_chan = comm::chan::(continue_port); + let continue_chan_ptr = ptr::addr_of(continue_chan); task::spawn_sched(task::manual_threads(1u)) {|| impl_uv_tcp_server(ip, port, kill_server_msg, server_resp_msg, ptr::addr_of(server_chan), - continue_chan); + continue_chan_ptr); }; // block until the server up is.. possibly a race? @@ -1546,6 +1626,18 @@ fn test_uv_struct_size_sockaddr_in() { assert native_handle_size as uint == rust_handle_size; } +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_struct_size_uv_async_t() { + let native_handle_size = + rustrt::rust_uv_helper_uv_async_t_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("uv_async_t -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + io::println(output); + assert native_handle_size as uint == rust_handle_size; +} + fn impl_uv_byval_test() unsafe { let addr = direct::ip4_addr("173.194.33.111", 80); io::println(#fmt("after build addr in rust. port: %u", diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 7a6a79ce17bff..6303bd700a6b6 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -167,15 +167,22 @@ rust_uv_async_send(uv_async_t* handle) { uv_async_send(handle); } +extern "C" int +rust_uv_async_init(uv_loop_t* loop_handle, + uv_async_t* async_handle, + uv_async_cb cb) { + return uv_async_init(loop_handle, async_handle, cb); +} + extern "C" void* -rust_uv_async_init(uv_loop_t* loop, crust_simple_cb cb, - uint8_t* buf) { - uv_async_t* async = (uv_async_t*)current_kernel_malloc( - sizeof(uv_async_t), - "uv_async_t"); - uv_async_init(loop, async, native_async_cb); - handle_data* data = new_handle_data_from(buf, cb); - async->data = data; +rust_uv_hilvl_async_init(uv_loop_t* loop, crust_simple_cb cb, + uint8_t* buf) { + uv_async_t* async = (uv_async_t*)current_kernel_malloc( + sizeof(uv_async_t), + "uv_async_t"); + uv_async_init(loop, async, native_async_cb); + handle_data* data = new_handle_data_from(buf, cb); + async->data = data; return async; } @@ -270,6 +277,10 @@ extern "C" size_t rust_uv_helper_sockaddr_in_size() { return sizeof(sockaddr_in); } +extern "C" size_t +rust_uv_helper_uv_async_t_size() { + return sizeof(uv_async_t); +} extern "C" uv_stream_t* rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 3369f6a3048e2..38d97f0c3ed25 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -92,6 +92,7 @@ rust_uv_hilvl_close_async rust_uv_hilvl_close_timer rust_uv_async_send rust_uv_async_init +rust_uv_hilvl_async_init rust_uv_timer_init rust_uv_timer_start rust_uv_timer_stop @@ -116,6 +117,7 @@ rust_uv_helper_uv_buf_t_size rust_uv_helper_uv_write_t_size rust_uv_helper_uv_err_t_size rust_uv_helper_sockaddr_in_size +rust_uv_helper_uv_async_t_size rust_uv_get_stream_handle_from_connect_req rust_uv_get_stream_handle_from_write_req rust_uv_get_loop_for_uv_handle From 1b4df79919c5489096be93ae644923536349ad6c Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 1 Apr 2012 13:13:18 -0700 Subject: [PATCH 19/33] add libuv error msg helpers.. flushing out windows tcp issue. --- src/libstd/uv.rs | 79 +++++++++++++++++++++++++++++++++----------- src/rt/rust_uv.cpp | 12 +++++++ src/rt/rustrt.def.in | 2 ++ 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 0e21d1d5da6c3..4c4415437bcec 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -360,6 +360,10 @@ native mod rustrt { fn rust_uv_buf_init(base: *u8, len: libc::size_t) -> uv_buf_t; fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; + // FIXME ref #2064 + fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char; + // FIXME ref #2064 + fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char; fn rust_uv_ip4_test_verify_port_val(++addr: sockaddr_in, expected: libc::c_uint) -> bool; @@ -484,10 +488,17 @@ mod direct { ret rustrt::rust_uv_read_stop(stream as *libc::c_void); } - unsafe fn uv_last_error(loop_handle: *libc::c_void) -> uv_err_t { + unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t { ret rustrt::rust_uv_last_error(loop_handle); } + unsafe fn strerror(err: *uv_err_t) -> *libc::c_char { + ret rustrt::rust_uv_strerror(err); + } + unsafe fn err_name(err: *uv_err_t) -> *libc::c_char { + ret rustrt::rust_uv_err_name(err); + } + unsafe fn async_init(loop_handle: *libc::c_void, async_handle: *uv_async_t, cb: *u8) -> libc::c_int { @@ -570,6 +581,15 @@ mod direct { unsafe fn free_base_of_buf(buf: uv_buf_t) { rustrt::rust_uv_free_base_of_buf(buf); } + + unsafe fn print_last_err_info(uv_loop: *libc::c_void) { + let err = direct::last_error(uv_loop); + let err_ptr = ptr::addr_of(err); + let err_name = str::unsafe::from_c_str(direct::err_name(err_ptr)); + let err_msg = str::unsafe::from_c_str(direct::strerror(err_ptr)); + io::println(#fmt("LIBUV ERROR: name: %s msg: %s", + err_name, err_msg)); + } } // public functions @@ -1145,9 +1165,10 @@ crust fn on_alloc_cb(handle: *libc::c_void, crust fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, ++buf: uv_buf_t) unsafe { + io::println(#fmt("CLIENT entering on_read_cb nred: %d", nread)); if (nread > 0) { // we have data - io::println(#fmt("read: data! nread: %d", nread)); + io::println(#fmt("CLIENT read: data! nread: %d", nread)); direct::read_stop(stream); let client_data = direct:: get_data_for_uv_handle(stream as *libc::c_void) @@ -1170,18 +1191,18 @@ crust fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, } // when we're done direct::free_base_of_buf(buf); - io::println("exiting on_read_cb"); + io::println("CLIENT exiting on_read_cb"); } crust fn on_write_complete_cb(write_req: *uv_write_t, status: libc::c_int) unsafe { - io::println(#fmt("beginning on_write_complete_cb status: %d", + io::println(#fmt("CLIENT beginning on_write_complete_cb status: %d", status as int)); let stream = direct::get_stream_handle_from_write_req(write_req); - io::println(#fmt("on_write_complete_cb: tcp:%d write_handle:%d", + io::println(#fmt("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", stream as int, write_req as int)); let result = direct::read_start(stream, on_alloc_cb, on_read_cb); - io::println(#fmt("ending on_write_complete_cb .. status: %d", + io::println(#fmt("CLIENT ending on_write_complete_cb .. status: %d", result as int)); } @@ -1207,7 +1228,9 @@ crust fn on_connect_cb(connect_req_ptr: *uv_connect_t, write_result as int)); } else { - io::println("non-zero status for on_connect_cb.."); + let test_loop = direct::get_loop_for_uv_handle(stream as *libc::c_void); + direct::print_last_err_info(test_loop); + assert false; } io::println("finishing on_connect_cb"); } @@ -1286,12 +1309,12 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, } crust fn server_after_close_cb(handle: *libc::c_void) unsafe { - io::println("server stream closed, should exit loop..."); + io::println("SERVER server stream closed, should exit loop..."); } crust fn client_stream_after_close_cb(handle: *libc::c_void) unsafe { - io::println("closed client stream, now server.."); + io::println("SERVER: closed client stream, now closing server stream"); let client_data = direct::get_data_for_uv_handle( handle) as *tcp_server_data; @@ -1305,7 +1328,7 @@ crust fn after_server_resp_write(req: *uv_write_t) unsafe { let client_data = direct::get_data_for_uv_handle( client_stream_ptr as *libc::c_void) as *tcp_server_data; - direct::read_stop(client_stream_ptr); + io::println("SERVER: resp sent... closing client stream"); direct::close(client_stream_ptr as *libc::c_void, client_stream_after_close_cb) } @@ -1315,16 +1338,13 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, ++buf: uv_buf_t) unsafe { if (nread > 0) { // we have data - io::println(#fmt("read: data! nread: %d", nread)); + io::println(#fmt("SERVER read: data! nread: %d", nread)); // pull out the contents of the write from the client let buf_base = direct::get_base_from_buf(buf); let buf_len = direct::get_len_from_buf(buf); let bytes = vec::unsafe::from_buf(buf_base, buf_len); let request_str = str::from_bytes(bytes); - io::println("client req to follow"); - io::println(request_str); - io::println("end of client read"); let client_data = direct::get_data_for_uv_handle( client_stream_ptr as *libc::c_void) as *tcp_server_data; @@ -1332,6 +1352,9 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, let server_kill_msg = (*client_data).server_kill_msg; let write_req = (*client_data).server_write_req; if (str::contains(request_str, server_kill_msg)) { + io::println("SERVER: client request contains server_kill_msg!"); + io::println("SERVER: sending response to client"); + direct::read_stop(client_stream_ptr); let server_chan = *((*client_data).server_chan); comm::send(server_chan, request_str); let write_result = direct::write( @@ -1339,6 +1362,18 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, client_stream_ptr as *libc::c_void, (*client_data).server_resp_buf, after_server_resp_write); + io::println(#fmt("SERVER: resp write result: %d", + write_result as int)); + if (write_result != 0i32) { + io::println("non-zero result for server resp direct::write()"); + direct::print_last_err_info( + direct::get_loop_for_uv_handle(client_stream_ptr + as *libc::c_void)); + assert false; + } + } + else { + io::println("SERVER: client req DOESNT contain server_kill_msg!"); } } else if (nread == -1) { @@ -1351,7 +1386,7 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, } // when we're done direct::free_base_of_buf(buf); - io::println("exiting on_read_cb"); + io::println("SERVER exiting on_read_cb"); } crust fn server_connection_cb(server_stream_ptr: *uv_stream_t, @@ -1414,6 +1449,10 @@ type async_handle_data = { continue_chan: *comm::chan }; +crust fn async_close_cb(handle: *libc::c_void) { + io::println("SERVER: closing async cb..."); +} + crust fn continue_async_cb(async_handle: *uv_async_t, status: libc::c_int) unsafe { // once we're in the body of this callback, @@ -1424,7 +1463,7 @@ crust fn continue_async_cb(async_handle: *uv_async_t, async_handle as *libc::c_void) as *async_handle_data; let continue_chan = *((*data).continue_chan); comm::send(continue_chan, true); - direct::close(async_handle as *libc::c_void, 0 as *u8); + direct::close(async_handle as *libc::c_void, async_close_cb); } fn impl_uv_tcp_server(server_ip: str, @@ -1500,6 +1539,7 @@ fn impl_uv_tcp_server(server_ip: str, direct::async_send(continue_async_handle_ptr); // uv_run() direct::run(test_loop); + io::println("server uv::run() has returned"); } else { io::println(#fmt("uv_async_init failure: %d", @@ -1530,7 +1570,8 @@ fn impl_uv_tcp_server(server_ip: str, #[test] #[ignore(cfg(target_os = "freebsd"))] fn test_uv_tcp_server_and_request() unsafe { - let ip = "0.0.0.0"; + let bind_ip = "0.0.0.0"; + let request_ip = "127.0.0.1"; let port = 8888; let kill_server_msg = "does a dog have buddha nature?"; let server_resp_msg = "mu!"; @@ -1544,7 +1585,7 @@ fn test_uv_tcp_server_and_request() unsafe { let continue_chan_ptr = ptr::addr_of(continue_chan); task::spawn_sched(task::manual_threads(1u)) {|| - impl_uv_tcp_server(ip, port, + impl_uv_tcp_server(bind_ip, port, kill_server_msg, server_resp_msg, ptr::addr_of(server_chan), @@ -1557,7 +1598,7 @@ fn test_uv_tcp_server_and_request() unsafe { io::println("received on continue port, set up tcp client"); task::spawn_sched(task::manual_threads(1u)) {|| - impl_uv_tcp_request(ip, port, + impl_uv_tcp_request(request_ip, port, kill_server_msg, ptr::addr_of(client_chan)); }; diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 6303bd700a6b6..9d2bb5e826030 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -346,6 +346,18 @@ rust_uv_last_error(uv_loop_t* loop) { return uv_last_error(loop); } +extern "C" const char* +rust_uv_strerror(uv_err_t* err_ptr) { + uv_err_t err = *err_ptr; + return uv_strerror(err); +} + +extern "C" const char* +rust_uv_err_name(uv_err_t* err_ptr) { + uv_err_t err = *err_ptr; + return uv_err_name(err); +} + extern "C" int rust_uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t* bufs, int buf_cnt, diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 38d97f0c3ed25..bf51d67cd41cf 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -100,6 +100,8 @@ rust_uv_free rust_uv_tcp_init rust_uv_buf_init rust_uv_last_error +rust_uv_strerror +rust_uv_err_name rust_uv_ip4_test_verify_port_val rust_uv_ip4_addr rust_uv_tcp_connect From e82a70d453f327180e56ed7392396597b2791668 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 1 Apr 2012 13:47:08 -0700 Subject: [PATCH 20/33] fix size of uv_async_t on windows. is this the cause of the libuv segfault? --- src/libstd/uv.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 4c4415437bcec..c346862a07ac3 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -278,17 +278,24 @@ fn gen_stub_uv_write_t() -> uv_write_t { #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] type 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 }; +// win32 size 132 (68) +#[cfg(target_os = "win32")] +type 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 +}; #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] fn gen_stub_uv_async_t() -> uv_async_t { ret { fields: { loop_handle: ptr::null(), type_: 0u32, close_cb: ptr::null(), @@ -298,6 +305,17 @@ fn gen_stub_uv_async_t() -> uv_async_t { a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8 }; } +#[cfg(target_os = "win32")] +fn gen_stub_uv_async_t() -> uv_async_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 + }; +} // unix size: 16 #[cfg(target_os = "linux")] From 2e8faf22179d7ff94d30aa8005ae85ebacf1fb39 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 1 Apr 2012 13:47:47 -0700 Subject: [PATCH 21/33] docs tweak for uv module --- src/libstd/uv.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index c346862a07ac3..4cd29261ed7b5 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -1,5 +1,5 @@ #[doc = " -Rust mappings to libuv (http://github.com/joyent/libuv) +Rust bindings to libuv This crate provides a low-level mapping to libuv, a library for running an asynchronous event loop, with extensive IO operations. @@ -10,7 +10,8 @@ should not be inferred from its current form. The base module contains a set of safe functions for creating an event loop that runs within a single task, but allows operations against it from other tasks, but funneling it through a uv_async -request which reads from a port that users write to. +request which reads from a port that users write to. This API should +not be considered stable and may go away in the near future. The 'll' module contains low-level, bare-metal mappings to the libuv C-api. All functions within this module are marked unsafe and should From cc823801485c15457013783e30c6258ab1c1628b Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 1 Apr 2012 21:16:50 -0700 Subject: [PATCH 22/33] line length fixes for make check --- src/libstd/uv.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 4cd29261ed7b5..5038b35d29c86 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -1247,7 +1247,8 @@ crust fn on_connect_cb(connect_req_ptr: *uv_connect_t, write_result as int)); } else { - let test_loop = direct::get_loop_for_uv_handle(stream as *libc::c_void); + let test_loop = direct::get_loop_for_uv_handle( + stream as *libc::c_void); direct::print_last_err_info(test_loop); assert false; } @@ -1384,7 +1385,7 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, io::println(#fmt("SERVER: resp write result: %d", write_result as int)); if (write_result != 0i32) { - io::println("non-zero result for server resp direct::write()"); + io::println("bad result for server resp direct::write()"); direct::print_last_err_info( direct::get_loop_for_uv_handle(client_stream_ptr as *libc::c_void)); From 565a092f52d730a4fc8a691110898ab2cbd4626c Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 1 Apr 2012 21:43:39 -0700 Subject: [PATCH 23/33] whitespace cleanup after rebase --- src/rt/rust_uv.cpp | 261 ++++++++++++++++++++++----------------------- 1 file changed, 127 insertions(+), 134 deletions(-) diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 9d2bb5e826030..c13b43a660d4b 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -9,18 +9,18 @@ // crust fn pointers typedef void (*crust_async_op_cb)(uv_loop_t* loop, void* data, - uv_async_t* op_handle); + uv_async_t* op_handle); typedef void (*crust_simple_cb)(uint8_t* id_buf, void* loop_data); typedef void (*crust_close_cb)(uint8_t* id_buf, void* handle, - void* data); + void* data); // data types #define RUST_UV_HANDLE_LEN 16 struct handle_data { - uint8_t id_buf[RUST_UV_HANDLE_LEN]; - crust_simple_cb cb; - crust_close_cb close_cb; + uint8_t id_buf[RUST_UV_HANDLE_LEN]; + crust_simple_cb cb; + crust_close_cb close_cb; }; // helpers @@ -37,52 +37,52 @@ current_kernel_free(void* ptr) { static handle_data* new_handle_data_from(uint8_t* buf, crust_simple_cb cb) { - handle_data* data = (handle_data*)current_kernel_malloc( - sizeof(handle_data), - "handle_data"); - memcpy(data->id_buf, buf, RUST_UV_HANDLE_LEN); - data->cb = cb; - return data; + handle_data* data = (handle_data*)current_kernel_malloc( + sizeof(handle_data), + "handle_data"); + memcpy(data->id_buf, buf, RUST_UV_HANDLE_LEN); + data->cb = cb; + return data; } // libuv callback impls static void native_crust_async_op_cb(uv_async_t* handle, int status) { crust_async_op_cb cb = (crust_async_op_cb)handle->data; - void* loop_data = handle->loop->data; - cb(handle->loop, loop_data, handle); + void* loop_data = handle->loop->data; + cb(handle->loop, loop_data, handle); } static void native_async_cb(uv_async_t* handle, int status) { - handle_data* handle_d = (handle_data*)handle->data; - void* loop_data = handle->loop->data; - handle_d->cb(handle_d->id_buf, loop_data); + handle_data* handle_d = (handle_data*)handle->data; + void* loop_data = handle->loop->data; + handle_d->cb(handle_d->id_buf, loop_data); } static void native_timer_cb(uv_timer_t* handle, int status) { - handle_data* handle_d = (handle_data*)handle->data; - void* loop_data = handle->loop->data; - handle_d->cb(handle_d->id_buf, loop_data); + handle_data* handle_d = (handle_data*)handle->data; + void* loop_data = handle->loop->data; + handle_d->cb(handle_d->id_buf, loop_data); } static void native_close_cb(uv_handle_t* handle) { - handle_data* data = (handle_data*)handle->data; - data->close_cb(data->id_buf, handle, handle->loop->data); + handle_data* data = (handle_data*)handle->data; + data->close_cb(data->id_buf, handle, handle->loop->data); } static void native_close_op_cb(uv_handle_t* op_handle) { - current_kernel_free(op_handle); - // uv_run() should return after this.. + current_kernel_free(op_handle); + // uv_run() should return after this.. } // native fns bound in rust extern "C" void rust_uv_free(void* ptr) { - current_kernel_free(ptr); + current_kernel_free(ptr); } extern "C" void* rust_uv_loop_new() { @@ -117,49 +117,49 @@ rust_uv_loop_set_data(uv_loop_t* loop, void* data) { extern "C" void* rust_uv_bind_op_cb(uv_loop_t* loop, crust_async_op_cb cb) { - uv_async_t* async = (uv_async_t*)current_kernel_malloc( - sizeof(uv_async_t), - "uv_async_t"); - uv_async_init(loop, async, native_crust_async_op_cb); - async->data = (void*)cb; - // decrement the ref count, so that our async bind - // doesn't count towards keeping the loop alive - //uv_unref(loop); - return async; + uv_async_t* async = (uv_async_t*)current_kernel_malloc( + sizeof(uv_async_t), + "uv_async_t"); + uv_async_init(loop, async, native_crust_async_op_cb); + async->data = (void*)cb; + // decrement the ref count, so that our async bind + // doesn't count towards keeping the loop alive + //uv_unref(loop); + return async; } extern "C" void rust_uv_stop_op_cb(uv_handle_t* op_handle) { - uv_close(op_handle, native_close_op_cb); + uv_close(op_handle, native_close_op_cb); } extern "C" void rust_uv_run(uv_loop_t* loop) { - uv_run(loop); + uv_run(loop); } extern "C" void rust_uv_close(uv_handle_t* handle, uv_close_cb cb) { - uv_close(handle, cb); + uv_close(handle, cb); } extern "C" void rust_uv_hilvl_close(uv_handle_t* handle, crust_close_cb cb) { - handle_data* data = (handle_data*)handle->data; - data->close_cb = cb; - uv_close(handle, native_close_cb); + handle_data* data = (handle_data*)handle->data; + data->close_cb = cb; + uv_close(handle, native_close_cb); } extern "C" void rust_uv_hilvl_close_async(uv_async_t* handle) { - current_kernel_free(handle->data); - current_kernel_free(handle); + current_kernel_free(handle->data); + current_kernel_free(handle); } extern "C" void rust_uv_hilvl_close_timer(uv_async_t* handle) { - current_kernel_free(handle->data); - current_kernel_free(handle); + current_kernel_free(handle->data); + current_kernel_free(handle); } extern "C" void @@ -169,233 +169,226 @@ rust_uv_async_send(uv_async_t* handle) { extern "C" int rust_uv_async_init(uv_loop_t* loop_handle, - uv_async_t* async_handle, - uv_async_cb cb) { - return uv_async_init(loop_handle, async_handle, cb); + uv_async_t* async_handle, + uv_async_cb cb) { + return uv_async_init(loop_handle, async_handle, cb); } extern "C" void* rust_uv_hilvl_async_init(uv_loop_t* loop, crust_simple_cb cb, - uint8_t* buf) { - uv_async_t* async = (uv_async_t*)current_kernel_malloc( - sizeof(uv_async_t), - "uv_async_t"); - uv_async_init(loop, async, native_async_cb); - handle_data* data = new_handle_data_from(buf, cb); - async->data = data; + uint8_t* buf) { + uv_async_t* async = (uv_async_t*)current_kernel_malloc( + sizeof(uv_async_t), + "uv_async_t"); + uv_async_init(loop, async, native_async_cb); + handle_data* data = new_handle_data_from(buf, cb); + async->data = data; - return async; + return async; } extern "C" void* rust_uv_timer_init(uv_loop_t* loop, crust_simple_cb cb, - uint8_t* buf) { - uv_timer_t* new_timer = (uv_timer_t*)current_kernel_malloc( - sizeof(uv_timer_t), - "uv_timer_t"); - uv_timer_init(loop, new_timer); - handle_data* data = new_handle_data_from(buf, cb); - new_timer->data = data; + uint8_t* buf) { + uv_timer_t* new_timer = (uv_timer_t*)current_kernel_malloc( + sizeof(uv_timer_t), + "uv_timer_t"); + uv_timer_init(loop, new_timer); + handle_data* data = new_handle_data_from(buf, cb); + new_timer->data = data; - return new_timer; + return new_timer; } extern "C" void rust_uv_timer_start(uv_timer_t* the_timer, uint32_t timeout, - uint32_t repeat) { - uv_timer_start(the_timer, native_timer_cb, timeout, repeat); + uint32_t repeat) { + uv_timer_start(the_timer, native_timer_cb, timeout, repeat); } extern "C" void rust_uv_timer_stop(uv_timer_t* the_timer) { - uv_timer_stop(the_timer); + uv_timer_stop(the_timer); } extern "C" int rust_uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { - return uv_tcp_init(loop, handle); + return uv_tcp_init(loop, handle); } extern "C" int rust_uv_tcp_connect(uv_connect_t* connect_ptr, - uv_tcp_t* tcp_ptr, - uv_connect_cb cb, - sockaddr_in* addr_ptr) { - printf("inside rust_uv_tcp_connect\n"); - // FIXME ref #2064 - sockaddr_in addr = *addr_ptr; - printf("before tcp_connect .. port: %d\n", addr.sin_port); - printf("before tcp_connect.. tcp stream: %lu cb ptr: %lu\n", - (unsigned long int)tcp_ptr, (unsigned long int)cb); - int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); - printf ("leaving rust_uv_tcp_connect.. and result: %d\n", - result); - return result; + uv_tcp_t* tcp_ptr, + uv_connect_cb cb, + sockaddr_in* addr_ptr) { + printf("inside rust_uv_tcp_connect\n"); + // FIXME ref #2064 + sockaddr_in addr = *addr_ptr; + printf("before tcp_connect .. port: %d\n", addr.sin_port); + printf("before tcp_connect.. tcp stream: %lu cb ptr: %lu\n", + (unsigned long int)tcp_ptr, (unsigned long int)cb); + int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); + printf ("leaving rust_uv_tcp_connect.. and result: %d\n", + result); + return result; } extern "C" int rust_uv_tcp_bind(uv_tcp_t* tcp_server, sockaddr_in* addr_ptr) { - // FIXME ref #2064 - sockaddr_in addr = *addr_ptr; - printf("before uv_tcp_bind .. tcp_server: %lu port: %d\n", - (unsigned long int)tcp_server, addr.sin_port); - return uv_tcp_bind(tcp_server, addr); + // FIXME ref #2064 + sockaddr_in addr = *addr_ptr; + printf("before uv_tcp_bind .. tcp_server: %lu port: %d\n", + (unsigned long int)tcp_server, addr.sin_port); + return uv_tcp_bind(tcp_server, addr); } extern "C" int rust_uv_listen(uv_stream_t* stream, int backlog, - uv_connection_cb cb) { - return uv_listen(stream, backlog, cb); + uv_connection_cb cb) { + return uv_listen(stream, backlog, cb); } extern "C" int rust_uv_accept(uv_stream_t* server, uv_stream_t* client) { - return uv_accept(server, client); + return uv_accept(server, client); } extern "C" size_t rust_uv_helper_uv_tcp_t_size() { - return sizeof(uv_tcp_t); + return sizeof(uv_tcp_t); } extern "C" size_t rust_uv_helper_uv_connect_t_size() { - return sizeof(uv_connect_t); + return sizeof(uv_connect_t); } extern "C" size_t rust_uv_helper_uv_buf_t_size() { - return sizeof(uv_buf_t); + return sizeof(uv_buf_t); } extern "C" size_t rust_uv_helper_uv_write_t_size() { - return sizeof(uv_write_t); + return sizeof(uv_write_t); } extern "C" size_t rust_uv_helper_uv_err_t_size() { - return sizeof(uv_err_t); + return sizeof(uv_err_t); } extern "C" size_t rust_uv_helper_sockaddr_in_size() { - return sizeof(sockaddr_in); + return sizeof(sockaddr_in); } extern "C" size_t rust_uv_helper_uv_async_t_size() { - return sizeof(uv_async_t); + return sizeof(uv_async_t); } extern "C" uv_stream_t* rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) { - return connect->handle; + return connect->handle; } extern "C" uv_stream_t* rust_uv_get_stream_handle_from_write_req(uv_write_t* write_req) { - return write_req->handle; + return write_req->handle; } extern "C" uv_buf_t current_kernel_malloc_alloc_cb(uv_handle_t* handle, - size_t suggested_size) { - char* base_ptr = (char*)current_kernel_malloc(sizeof(char) - * suggested_size, - "uv_buf_t_base_val"); - return uv_buf_init(base_ptr, suggested_size); + size_t suggested_size) { + char* base_ptr = (char*)current_kernel_malloc(sizeof(char) + * suggested_size, + "uv_buf_t_base_val"); + return uv_buf_init(base_ptr, suggested_size); } extern "C" uv_buf_t rust_uv_buf_init(char* base, size_t len) { - return uv_buf_init(base, len); + return uv_buf_init(base, len); } extern "C" uv_loop_t* rust_uv_get_loop_for_uv_handle(uv_handle_t* handle) { - return handle->loop; + return handle->loop; } extern "C" void* rust_uv_get_data_for_uv_handle(uv_handle_t* handle) { - return handle->data; + return handle->data; } extern "C" void rust_uv_set_data_for_uv_handle(uv_handle_t* handle, - void* data) { - handle->data = data; + void* data) { + handle->data = data; } extern "C" void* rust_uv_get_data_for_req(uv_req_t* req) { - return req->data; + return req->data; } extern "C" void rust_uv_set_data_for_req(uv_req_t* req, void* data) { - req->data = data; + req->data = data; } extern "C" char* rust_uv_get_base_from_buf(uv_buf_t buf) { - return buf.base; + return buf.base; } extern "C" size_t rust_uv_get_len_from_buf(uv_buf_t buf) { - return buf.len; + return buf.len; } extern "C" uv_err_t rust_uv_last_error(uv_loop_t* loop) { - return uv_last_error(loop); + return uv_last_error(loop); } extern "C" const char* rust_uv_strerror(uv_err_t* err_ptr) { - uv_err_t err = *err_ptr; - return uv_strerror(err); + uv_err_t err = *err_ptr; + return uv_strerror(err); } extern "C" const char* rust_uv_err_name(uv_err_t* err_ptr) { - uv_err_t err = *err_ptr; - return uv_err_name(err); + uv_err_t err = *err_ptr; + return uv_err_name(err); } extern "C" int rust_uv_write(uv_write_t* req, uv_stream_t* handle, - uv_buf_t* bufs, int buf_cnt, - uv_write_cb cb) { - return uv_write(req, handle, bufs, buf_cnt, cb); + uv_buf_t* bufs, int buf_cnt, + uv_write_cb cb) { + return uv_write(req, handle, bufs, buf_cnt, cb); } extern "C" int rust_uv_read_start(uv_stream_t* stream, uv_alloc_cb on_alloc, - uv_read_cb on_read) { + uv_read_cb on_read) { return uv_read_start(stream, on_alloc, on_read); } extern "C" int rust_uv_read_stop(uv_stream_t* stream) { - return uv_read_stop(stream); + return uv_read_stop(stream); } extern "C" char* rust_uv_malloc_buf_base_of(size_t suggested_size) { - return (char*) current_kernel_malloc(sizeof(char)*suggested_size, - "uv_buf_t base"); + return (char*) current_kernel_malloc(sizeof(char)*suggested_size, + "uv_buf_t base"); } extern "C" void rust_uv_free_base_of_buf(uv_buf_t buf) { - current_kernel_free(buf.base); + current_kernel_free(buf.base); } extern "C" struct sockaddr_in rust_uv_ip4_addr(const char* ip, int port) { - printf("before creating addr_ptr.. ip %s port %d\n", ip, port); - struct sockaddr_in addr = uv_ip4_addr(ip, port); - printf("after creating .. port: %d\n", addr.sin_port); - return addr; -} - -extern "C" bool -rust_uv_ip4_test_verify_port_val(struct sockaddr_in addr, - unsigned int expected) { - printf("inside c++ ip4_test .. port: %u\n", addr.sin_port); - return addr.sin_port == expected; + printf("before creating addr_ptr.. ip %s port %d\n", ip, port); + struct sockaddr_in addr = uv_ip4_addr(ip, port); + printf("after creating .. port: %d\n", addr.sin_port); + return addr; } From 076e58674286591d928393fea0838579c7bd4003 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 2 Apr 2012 11:46:15 -0700 Subject: [PATCH 24/33] getting rid of ip4 port byval test... 2064 workarounds in place, for now --- src/libstd/uv.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 5038b35d29c86..6f89f607bc072 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -383,9 +383,6 @@ native mod rustrt { fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char; // FIXME ref #2064 fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char; - fn rust_uv_ip4_test_verify_port_val(++addr: sockaddr_in, - expected: libc::c_uint) - -> bool; fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) -> sockaddr_in; // FIXME ref #2064 @@ -1698,18 +1695,3 @@ fn test_uv_struct_size_uv_async_t() { io::println(output); assert native_handle_size as uint == rust_handle_size; } - -fn impl_uv_byval_test() unsafe { - let addr = direct::ip4_addr("173.194.33.111", 80); - io::println(#fmt("after build addr in rust. port: %u", - addr.sin_port as uint)); - assert rustrt::rust_uv_ip4_test_verify_port_val(addr, - addr.sin_port as libc::c_uint); - io::println(#fmt("after build addr in rust. port: %u", - addr.sin_port as uint)); -} -#[test] -#[ignore(cfg(target_os = "freebsd"))] -fn test_uv_ip4_byval_passing_test() { - impl_uv_byval_test(); -} From bd797858fb06ba7d8d78b1155a83fd8552d3e9be Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 2 Apr 2012 09:12:43 -0700 Subject: [PATCH 25/33] rename uv::direct:: to uv::ll:: and put into its own crate --- src/libstd/std.rc | 3 + src/libstd/uv.rs | 737 +++++++++----------------------------------- src/libstd/uv_ll.rs | 526 +++++++++++++++++++++++++++++++ 3 files changed, 669 insertions(+), 597 deletions(-) create mode 100644 src/libstd/uv_ll.rs diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 43b61e195e2a1..998c31115cac2 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -19,7 +19,10 @@ export test, tempfile, serialization; // General io and system-services modules mod net; + +// libuv modules mod uv; +mod uv_ll; // Utility modules diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 6f89f607bc072..f5ee758a368bc 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -24,321 +24,9 @@ import map::hashmap; export loop_new, loop_delete, run, close, run_in_bg; export async_init, async_send; export timer_init, timer_start, timer_stop; -export uv_ip4_addr, uv_ip6_addr; -export direct; -// these are processed solely in the -// process_operation() crust fn below -enum uv_operation { - op_async_init([u8]), - op_close(uv_handle, *libc::c_void), - op_timer_init([u8]), - op_timer_start([u8], *libc::c_void, u32, u32), - op_timer_stop([u8], *libc::c_void, fn~(uv_handle)), - op_teardown(*libc::c_void) -} - -enum uv_handle { - uv_async([u8], uv_loop), - uv_timer([u8], uv_loop), -} - -enum uv_msg { - // requests from library users - msg_run(comm::chan), - msg_run_in_bg(), - msg_async_init(fn~(uv_handle), fn~(uv_handle)), - msg_async_send([u8]), - msg_close(uv_handle, fn~()), - msg_timer_init(fn~(uv_handle)), - msg_timer_start([u8], u32, u32, fn~(uv_handle)), - msg_timer_stop([u8], fn~(uv_handle)), - - // dispatches from libuv - uv_async_init([u8], *libc::c_void), - uv_async_send([u8]), - uv_close([u8]), - uv_timer_init([u8], *libc::c_void), - uv_timer_call([u8]), - uv_timer_stop([u8], fn~(uv_handle)), - uv_end(), - uv_teardown_check() -} - -type uv_loop_data = { - operation_port: comm::port, - rust_loop_chan: comm::chan -}; - -enum uv_loop { - uv_loop_new(comm::chan, *libc::c_void) -} - -// libuv struct mappings -type uv_ip4_addr = { - ip: [u8], - port: int -}; -type uv_ip6_addr = uv_ip4_addr; - -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 -} - -type handle_type = libc::c_uint; - -type uv_handle_fields = { - loop_handle: *libc::c_void, - type_: handle_type, - close_cb: *u8, - mut data: *libc::c_void, -}; - -// unix size: 8 -type 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..) -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] -type uv_stream_t = { - fields: uv_handle_fields -}; - -// unix size: 272 -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -type 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, a26: *u8, a27: *u8, - a28: *u8, a29: *u8 -}; -// win32 size: 240 (120) -#[cfg(target_os = "win32")] -type 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 -}; -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -fn gen_stub_uv_tcp_t() -> uv_tcp_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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, a26: 0 as *u8, a27: 0 as *u8, - a28: 0 as *u8, a29: 0 as *u8 - }; -} -#[cfg(target_os = "win32")] -fn gen_stub_uv_tcp_t() -> uv_tcp_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; -} - -// unix size: 48 -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -type uv_connect_t = { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8 -}; -// win32 size: 88 (44) -#[cfg(target_os = "win32")] -type 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 -}; -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -fn gen_stub_uv_connect_t() -> uv_connect_t { - ret { - a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, - a04: 0 as *u8, a05: 0 as *u8 - }; -} -#[cfg(target_os = "win32")] -fn gen_stub_uv_connect_t() -> uv_connect_t { - ret { - 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 - }; -} - -// unix size: 16 -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] -type uv_buf_t = { - base: *u8, - len: libc::size_t -}; -// no gen stub method.. should create -// it via uv::direct::buf_init() - -// unix size: 144 -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -type 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, a13: *u8 -}; -// win32 size: 136 (68) -#[cfg(target_os = "win32")] -type 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 -}; -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -fn gen_stub_uv_write_t() -> uv_write_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; -} -#[cfg(target_os = "win32")] -fn gen_stub_uv_write_t() -> uv_write_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; -} -// unix size: 120 -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -type 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 -}; -// win32 size 132 (68) -#[cfg(target_os = "win32")] -type 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 -}; -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -fn gen_stub_uv_async_t() -> uv_async_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; -} -#[cfg(target_os = "win32")] -fn gen_stub_uv_async_t() -> uv_async_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; -} - -// unix size: 16 -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] -type sockaddr_in = { - mut sin_family: u16, - mut sin_port: u16, - mut sin_addr: u32, // in_addr: this is an opaque, per-platform struct - mut sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8) -}; - -// unix size: 28 .. make due w/ 32 -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] -#[cfg(target_os = "win32")] -type sockaddr_in6 = { - a0: *u8, a1: *u8, - a2: *u8, a3: *u8 -}; +import ll = uv_ll; +export ll; #[nolink] native mod rustrt { @@ -351,14 +39,10 @@ native mod rustrt { -> *libc::c_void; fn rust_uv_stop_op_cb(handle: *libc::c_void); fn rust_uv_run(loop_handle: *libc::c_void); - fn rust_uv_close(handle: *libc::c_void, cb: *u8); fn rust_uv_hilvl_close(handle: *libc::c_void, cb: *u8); fn rust_uv_hilvl_close_async(handle: *libc::c_void); fn rust_uv_hilvl_close_timer(handle: *libc::c_void); - fn rust_uv_async_send(handle: *uv_async_t); - fn rust_uv_async_init(loop_handle: *libc::c_void, - async_handle: *uv_async_t, - cb: *u8) -> libc::c_int; + fn rust_uv_async_send(handle: *ll::uv_async_t); fn rust_uv_hilvl_async_init( loop_handle: *libc::c_void, cb: *u8, @@ -414,198 +98,54 @@ native mod rustrt { fn rust_uv_helper_uv_err_t_size() -> libc::c_uint; fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; fn rust_uv_helper_uv_async_t_size() -> libc::c_uint; - - // data accessors for rust-mapped uv structs - 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: *libc::c_void) - -> *libc::c_void; - fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void) - -> *libc::c_void; - fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void, - data: *libc::c_void); - fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void; - fn rust_uv_set_data_for_req(req: *libc::c_void, - data: *libc::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) -> libc::size_t; } -// this module is structured around functions that directly -// expose libuv functionality and data structures. for use -// in higher level mappings -mod direct { - unsafe fn loop_new() -> *libc::c_void { - ret rustrt::rust_uv_loop_new(); - } - - unsafe fn loop_delete(loop_handle: *libc::c_void) { - rustrt::rust_uv_loop_delete(loop_handle); - } - - unsafe fn run(loop_handle: *libc::c_void) { - rustrt::rust_uv_run(loop_handle); - } - - unsafe fn close(handle: *libc::c_void, cb: *u8) { - rustrt::rust_uv_close(handle, cb); - } - unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t) - -> libc::c_int { - ret rustrt::rust_uv_tcp_init(loop_handle, handle); - } - // FIXME ref #2064 - 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 { - let address = *addr_ptr; - io::println(#fmt("b4 native tcp_connect--addr port: %u cb: %u", - address.sin_port as uint, after_connect_cb as uint)); - ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, - after_connect_cb, addr_ptr); - } - // FIXME ref #2064 - unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, - addr_ptr: *sockaddr_in) -> libc::c_int { - ret rustrt::rust_uv_tcp_bind(tcp_server_ptr, - addr_ptr); - } - - unsafe fn listen(stream: *libc::c_void, backlog: libc::c_int, - cb: *u8) -> libc::c_int { - ret rustrt::rust_uv_listen(stream, backlog, cb); - } - - unsafe fn accept(server: *libc::c_void, client: *libc::c_void) - -> libc::c_int { - ret rustrt::rust_uv_accept(server, client); - } - - unsafe fn write(req: *libc::c_void, stream: *libc::c_void, - buf_in: *[uv_buf_t], cb: *u8) -> libc::c_int { - let buf_ptr = vec::unsafe::to_ptr(*buf_in); - let buf_cnt = vec::len(*buf_in) as i32; - ret rustrt::rust_uv_write(req, stream, buf_ptr, buf_cnt, cb); - } - unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, - on_read: *u8) -> libc::c_int { - ret rustrt::rust_uv_read_start(stream as *libc::c_void, - on_alloc, on_read); - } - - unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int { - ret rustrt::rust_uv_read_stop(stream as *libc::c_void); - } - - unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t { - ret rustrt::rust_uv_last_error(loop_handle); - } - - unsafe fn strerror(err: *uv_err_t) -> *libc::c_char { - ret rustrt::rust_uv_strerror(err); - } - unsafe fn err_name(err: *uv_err_t) -> *libc::c_char { - ret rustrt::rust_uv_err_name(err); - } +// these are processed solely in the +// process_operation() crust fn below +enum uv_operation { + op_async_init([u8]), + op_close(uv_handle, *libc::c_void), + op_timer_init([u8]), + op_timer_start([u8], *libc::c_void, u32, u32), + op_timer_stop([u8], *libc::c_void, fn~(uv_handle)), + op_teardown(*libc::c_void) +} - unsafe fn async_init(loop_handle: *libc::c_void, - async_handle: *uv_async_t, - cb: *u8) -> libc::c_int { - ret rustrt::rust_uv_async_init(loop_handle, - async_handle, - cb); - } +enum uv_handle { + uv_async([u8], uv_loop), + uv_timer([u8], uv_loop), +} - unsafe fn async_send(async_handle: *uv_async_t) { - ret rustrt::rust_uv_async_send(async_handle); - } +enum uv_msg { + // requests from library users + msg_run(comm::chan), + msg_run_in_bg(), + msg_async_init(fn~(uv_handle), fn~(uv_handle)), + msg_async_send([u8]), + msg_close(uv_handle, fn~()), + msg_timer_init(fn~(uv_handle)), + msg_timer_start([u8], u32, u32, fn~(uv_handle)), + msg_timer_stop([u8], fn~(uv_handle)), - // libuv struct initializers - unsafe fn tcp_t() -> uv_tcp_t { - ret gen_stub_uv_tcp_t(); - } - unsafe fn connect_t() -> uv_connect_t { - ret gen_stub_uv_connect_t(); - } - unsafe fn write_t() -> uv_write_t { - ret gen_stub_uv_write_t(); - } - unsafe fn async_t() -> uv_async_t { - ret gen_stub_uv_async_t(); - } - unsafe fn get_loop_for_uv_handle(handle: *libc::c_void) - -> *libc::c_void { - ret rustrt::rust_uv_get_loop_for_uv_handle(handle); - } - unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) - -> *uv_stream_t { - ret rustrt::rust_uv_get_stream_handle_from_connect_req( - connect); - } - unsafe fn get_stream_handle_from_write_req( - write_req: *uv_write_t) - -> *uv_stream_t { - ret rustrt::rust_uv_get_stream_handle_from_write_req( - write_req); - } + // dispatches from libuv + uv_async_init([u8], *libc::c_void), + uv_async_send([u8]), + uv_close([u8]), + uv_timer_init([u8], *libc::c_void), + uv_timer_call([u8]), + uv_timer_stop([u8], fn~(uv_handle)), + uv_end(), + uv_teardown_check() +} - unsafe fn get_data_for_uv_handle(handle: *libc::c_void) -> *libc::c_void { - ret rustrt::rust_uv_get_data_for_uv_handle(handle); - } - unsafe fn set_data_for_uv_handle(handle: *libc::c_void, - data: *libc::c_void) { - rustrt::rust_uv_set_data_for_uv_handle(handle, data); - } - unsafe fn get_data_for_req(req: *libc::c_void) -> *libc::c_void { - ret rustrt::rust_uv_get_data_for_req(req); - } - unsafe fn set_data_for_req(req: *libc::c_void, - data: *libc::c_void) { - rustrt::rust_uv_set_data_for_req(req, data); - } - unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { - ret rustrt::rust_uv_get_base_from_buf(buf); - } - unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t { - ret rustrt::rust_uv_get_len_from_buf(buf); - } - unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { - ret rustrt::rust_uv_buf_init(input, len); - } - unsafe fn ip4_addr(ip: str, port: int) - -> sockaddr_in { - let mut addr_vec = str::bytes(ip); - addr_vec += [0u8]; // add null terminator - let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); - let ip_back = str::from_bytes(addr_vec); - io::println(#fmt("vec val: '%s' length: %u", - ip_back, vec::len(addr_vec))); - ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, - port as libc::c_int); - } - unsafe fn malloc_buf_base_of(suggested_size: libc::size_t) - -> *u8 { - ret rustrt::rust_uv_malloc_buf_base_of(suggested_size); - } - unsafe fn free_base_of_buf(buf: uv_buf_t) { - rustrt::rust_uv_free_base_of_buf(buf); - } +type uv_loop_data = { + operation_port: comm::port, + rust_loop_chan: comm::chan +}; - unsafe fn print_last_err_info(uv_loop: *libc::c_void) { - let err = direct::last_error(uv_loop); - let err_ptr = ptr::addr_of(err); - let err_name = str::unsafe::from_c_str(direct::err_name(err_ptr)); - let err_msg = str::unsafe::from_c_str(direct::strerror(err_ptr)); - io::println(#fmt("LIBUV ERROR: name: %s msg: %s", - err_name, err_msg)); - } +enum uv_loop { + uv_loop_new(comm::chan, *libc::c_void) } // public functions @@ -934,7 +474,7 @@ fn pass_to_libuv( do_send(op_handle); } fn do_send(h: *libc::c_void) { - rustrt::rust_uv_async_send(h as *uv_async_t); + rustrt::rust_uv_async_send(h as *ll::uv_async_t); } fn gen_handle_id() -> [u8] { ret rand::rng().gen_bytes(16u); @@ -1162,8 +702,8 @@ enum tcp_read_data { } type request_wrapper = { - write_req: *uv_write_t, - req_buf: *[uv_buf_t], + write_req: *ll::uv_write_t, + req_buf: *[ll::uv_buf_t], read_chan: *comm::chan }; @@ -1172,30 +712,31 @@ crust fn after_close_cb(handle: *libc::c_void) { } crust fn on_alloc_cb(handle: *libc::c_void, - suggested_size: libc::size_t) -> uv_buf_t - unsafe { + suggested_size: libc::size_t) + -> ll::uv_buf_t unsafe { io::println("on_alloc_cb!"); - let char_ptr = direct::malloc_buf_base_of(suggested_size); - ret direct::buf_init(char_ptr, suggested_size); + let char_ptr = ll::malloc_buf_base_of(suggested_size); + ret ll::buf_init(char_ptr, suggested_size); } -crust fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, - ++buf: uv_buf_t) unsafe { +crust fn on_read_cb(stream: *ll::uv_stream_t, + nread: libc::ssize_t, + ++buf: ll::uv_buf_t) unsafe { io::println(#fmt("CLIENT entering on_read_cb nred: %d", nread)); if (nread > 0) { // we have data io::println(#fmt("CLIENT read: data! nread: %d", nread)); - direct::read_stop(stream); - let client_data = direct:: + ll::read_stop(stream); + let client_data = ll:: get_data_for_uv_handle(stream as *libc::c_void) as *request_wrapper; - let buf_base = direct::get_base_from_buf(buf); - let buf_len = direct::get_len_from_buf(buf); + let buf_base = ll::get_base_from_buf(buf); + let buf_len = ll::get_len_from_buf(buf); let bytes = vec::unsafe::from_buf(buf_base, buf_len); let read_chan = *((*client_data).read_chan); let msg_from_server = str::from_bytes(bytes); comm::send(read_chan, msg_from_server); - direct::close(stream as *libc::c_void, after_close_cb) + ll::close(stream as *libc::c_void, after_close_cb) } else if (nread == -1) { // err .. possibly EOF @@ -1206,47 +747,48 @@ crust fn on_read_cb(stream: *uv_stream_t, nread: libc::ssize_t, io::println("read: do nothing!"); } // when we're done - direct::free_base_of_buf(buf); + ll::free_base_of_buf(buf); io::println("CLIENT exiting on_read_cb"); } -crust fn on_write_complete_cb(write_req: *uv_write_t, +crust fn on_write_complete_cb(write_req: *ll::uv_write_t, status: libc::c_int) unsafe { io::println(#fmt("CLIENT beginning on_write_complete_cb status: %d", status as int)); - let stream = direct::get_stream_handle_from_write_req(write_req); + let stream = ll::get_stream_handle_from_write_req(write_req); io::println(#fmt("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", stream as int, write_req as int)); - let result = direct::read_start(stream, on_alloc_cb, on_read_cb); + let result = ll::read_start(stream, on_alloc_cb, on_read_cb); io::println(#fmt("CLIENT ending on_write_complete_cb .. status: %d", result as int)); } -crust fn on_connect_cb(connect_req_ptr: *uv_connect_t, +crust fn on_connect_cb(connect_req_ptr: *ll::uv_connect_t, status: libc::c_int) unsafe { io::println(#fmt("beginning on_connect_cb .. status: %d", status as int)); let stream = - direct::get_stream_handle_from_connect_req(connect_req_ptr); + ll::get_stream_handle_from_connect_req(connect_req_ptr); if (status == 0i32) { io::println("on_connect_cb: in status=0 if.."); - let client_data = direct::get_data_for_req( + let client_data = ll::get_data_for_req( connect_req_ptr as *libc::c_void) as *request_wrapper; let write_handle = (*client_data).write_req as *libc::c_void; io::println(#fmt("on_connect_cb: tcp stream: %d write_handle addr %d", stream as int, write_handle as int)); - let write_result = direct::write(write_handle, + let write_result = ll::write(write_handle, stream as *libc::c_void, (*client_data).req_buf, on_write_complete_cb); - io::println(#fmt("on_connect_cb: direct::write() status: %d", + io::println(#fmt("on_connect_cb: ll::write() status: %d", write_result as int)); } else { - let test_loop = direct::get_loop_for_uv_handle( + let test_loop = ll::get_loop_for_uv_handle( stream as *libc::c_void); - direct::print_last_err_info(test_loop); + let err_msg = ll::get_last_err_info(test_loop); + io::println(err_msg); assert false; } io::println("finishing on_connect_cb"); @@ -1254,10 +796,10 @@ crust fn on_connect_cb(connect_req_ptr: *uv_connect_t, fn impl_uv_tcp_request(ip: str, port: int, req_str: str, client_chan: *comm::chan) unsafe { - let test_loop = direct::loop_new(); - let tcp_handle = direct::tcp_t(); + let test_loop = ll::loop_new(); + let tcp_handle = ll::tcp_t(); let tcp_handle_ptr = ptr::addr_of(tcp_handle); - let connect_handle = direct::connect_t(); + let connect_handle = ll::connect_t(); let connect_req_ptr = ptr::addr_of(connect_handle); // this is the persistent payload of data that we @@ -1268,11 +810,11 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, let req_str_bytes = str::bytes(req_str); let req_msg_ptr: *u8 = vec::unsafe::to_ptr(req_str_bytes); let req_msg = [ - direct::buf_init(req_msg_ptr, vec::len(req_str_bytes)) + ll::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 = direct::write_t(); + let write_handle = ll::write_t(); let write_handle_ptr = ptr::addr_of(write_handle); io::println(#fmt("tcp req: tcp stream: %d write_handle: %d", tcp_handle_ptr as int, @@ -1281,13 +823,13 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, req_buf: ptr::addr_of(req_msg), read_chan: client_chan }; - let tcp_init_result = direct::tcp_init( + let tcp_init_result = ll::tcp_init( test_loop as *libc::c_void, tcp_handle_ptr); if (tcp_init_result == 0i32) { io::println("sucessful tcp_init_result"); io::println("building addr..."); - let addr = direct::ip4_addr(ip, port); + let addr = ll::ip4_addr(ip, port); // FIXME ref #2064 let addr_ptr = ptr::addr_of(addr); io::println(#fmt("after build addr in rust. port: %u", @@ -1296,32 +838,32 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, // this should set up the connection request.. io::println(#fmt("before calling tcp_connect .. connect cb ptr: %u ", on_connect_cb as uint)); - let tcp_connect_result = direct::tcp_connect( + let tcp_connect_result = ll::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 - direct::set_data_for_req( + ll::set_data_for_req( connect_req_ptr as *libc::c_void, ptr::addr_of(client_data) as *libc::c_void); - direct::set_data_for_uv_handle( + ll::set_data_for_uv_handle( tcp_handle_ptr as *libc::c_void, ptr::addr_of(client_data) as *libc::c_void); io::println("before run tcp req loop"); - direct::run(test_loop); + ll::run(test_loop); io::println("after run tcp req loop"); } else { - io::println("direct::tcp_connect() failure"); + io::println("ll::tcp_connect() failure"); assert false; } } else { - io::println("direct::tcp_init() failure"); + io::println("ll::tcp_init() failure"); assert false; } - direct::loop_delete(test_loop); + ll::loop_delete(test_loop); } @@ -1332,38 +874,38 @@ crust fn server_after_close_cb(handle: *libc::c_void) unsafe { crust fn client_stream_after_close_cb(handle: *libc::c_void) unsafe { io::println("SERVER: closed client stream, now closing server stream"); - let client_data = direct::get_data_for_uv_handle( + let client_data = ll::get_data_for_uv_handle( handle) as *tcp_server_data; - direct::close((*client_data).server as *libc::c_void, + ll::close((*client_data).server as *libc::c_void, server_after_close_cb); } -crust fn after_server_resp_write(req: *uv_write_t) unsafe { +crust fn after_server_resp_write(req: *ll::uv_write_t) unsafe { let client_stream_ptr = - direct::get_stream_handle_from_write_req(req); - let client_data = direct::get_data_for_uv_handle( + ll::get_stream_handle_from_write_req(req); + let client_data = ll::get_data_for_uv_handle( client_stream_ptr as *libc::c_void) as *tcp_server_data; io::println("SERVER: resp sent... closing client stream"); - direct::close(client_stream_ptr as *libc::c_void, + ll::close(client_stream_ptr as *libc::c_void, client_stream_after_close_cb) } -crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, +crust fn on_server_read_cb(client_stream_ptr: *ll::uv_stream_t, nread: libc::ssize_t, - ++buf: uv_buf_t) unsafe { + ++buf: ll::uv_buf_t) unsafe { if (nread > 0) { // we have data io::println(#fmt("SERVER read: data! nread: %d", nread)); // pull out the contents of the write from the client - let buf_base = direct::get_base_from_buf(buf); - let buf_len = direct::get_len_from_buf(buf); + let buf_base = ll::get_base_from_buf(buf); + let buf_len = ll::get_len_from_buf(buf); let bytes = vec::unsafe::from_buf(buf_base, buf_len); let request_str = str::from_bytes(bytes); - let client_data = direct::get_data_for_uv_handle( + let client_data = ll::get_data_for_uv_handle( client_stream_ptr as *libc::c_void) as *tcp_server_data; let server_kill_msg = (*client_data).server_kill_msg; @@ -1371,10 +913,10 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, if (str::contains(request_str, server_kill_msg)) { io::println("SERVER: client request contains server_kill_msg!"); io::println("SERVER: sending response to client"); - direct::read_stop(client_stream_ptr); + ll::read_stop(client_stream_ptr); let server_chan = *((*client_data).server_chan); comm::send(server_chan, request_str); - let write_result = direct::write( + let write_result = ll::write( write_req as *libc::c_void, client_stream_ptr as *libc::c_void, (*client_data).server_resp_buf, @@ -1382,10 +924,10 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, io::println(#fmt("SERVER: resp write result: %d", write_result as int)); if (write_result != 0i32) { - io::println("bad result for server resp direct::write()"); - direct::print_last_err_info( - direct::get_loop_for_uv_handle(client_stream_ptr - as *libc::c_void)); + io::println("bad result for server resp ll::write()"); + io::println(ll::get_last_err_info( + ll::get_loop_for_uv_handle(client_stream_ptr + as *libc::c_void))); assert false; } } @@ -1402,33 +944,34 @@ crust fn on_server_read_cb(client_stream_ptr: *uv_stream_t, io::println("read: do nothing!"); } // when we're done - direct::free_base_of_buf(buf); + ll::free_base_of_buf(buf); io::println("SERVER exiting on_read_cb"); } -crust fn server_connection_cb(server_stream_ptr: *uv_stream_t, +crust fn server_connection_cb(server_stream_ptr: + *ll::uv_stream_t, status: libc::c_int) unsafe { io::println("client connecting!"); - let test_loop = direct::get_loop_for_uv_handle( + let test_loop = ll::get_loop_for_uv_handle( server_stream_ptr as *libc::c_void); - let server_data = direct::get_data_for_uv_handle( + let server_data = ll::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 = direct::tcp_init(test_loop, + let client_init_result = ll::tcp_init(test_loop, client_stream_ptr); - direct::set_data_for_uv_handle( + ll::set_data_for_uv_handle( client_stream_ptr as *libc::c_void, server_data as *libc::c_void); if (client_init_result == 0i32) { io::println("successfully initialized client stream"); - let accept_result = direct::accept(server_stream_ptr as + let accept_result = ll::accept(server_stream_ptr as *libc::c_void, client_stream_ptr as *libc::c_void); if (accept_result == 0i32) { // start reading - let read_result = direct::read_start(client_stream_ptr - as *uv_stream_t, + let read_result = ll::read_start( + client_stream_ptr as *ll::uv_stream_t, on_alloc_cb, on_server_read_cb); if (read_result == 0i32) { @@ -1454,12 +997,12 @@ crust fn server_connection_cb(server_stream_ptr: *uv_stream_t, } type tcp_server_data = { - client: *uv_tcp_t, - server: *uv_tcp_t, + client: *ll::uv_tcp_t, + server: *ll::uv_tcp_t, server_kill_msg: str, - server_resp_buf: *[uv_buf_t], + server_resp_buf: *[ll::uv_buf_t], server_chan: *comm::chan, - server_write_req: *uv_write_t + server_write_req: *ll::uv_write_t }; type async_handle_data = { @@ -1470,17 +1013,17 @@ crust fn async_close_cb(handle: *libc::c_void) { io::println("SERVER: closing async cb..."); } -crust fn continue_async_cb(async_handle: *uv_async_t, +crust fn continue_async_cb(async_handle: *ll::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 = direct::get_data_for_uv_handle( + let data = ll::get_data_for_uv_handle( async_handle as *libc::c_void) as *async_handle_data; let continue_chan = *((*data).continue_chan); comm::send(continue_chan, true); - direct::close(async_handle as *libc::c_void, async_close_cb); + ll::close(async_handle as *libc::c_void, async_close_cb); } fn impl_uv_tcp_server(server_ip: str, @@ -1489,23 +1032,23 @@ fn impl_uv_tcp_server(server_ip: str, server_resp_msg: str, server_chan: *comm::chan, continue_chan: *comm::chan) unsafe { - let test_loop = direct::loop_new(); - let tcp_server = direct::tcp_t(); + let test_loop = ll::loop_new(); + let tcp_server = ll::tcp_t(); let tcp_server_ptr = ptr::addr_of(tcp_server); - let tcp_client = direct::tcp_t(); + let tcp_client = ll::tcp_t(); let tcp_client_ptr = ptr::addr_of(tcp_client); - let server_write_req = direct::write_t(); + let server_write_req = ll::write_t(); let server_write_req_ptr = ptr::addr_of(server_write_req); let resp_str_bytes = str::bytes(server_resp_msg); let resp_msg_ptr: *u8 = vec::unsafe::to_ptr(resp_str_bytes); let resp_msg = [ - direct::buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) + ll::buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) ]; - let continue_async_handle = direct::async_t(); + let continue_async_handle = ll::async_t(); let continue_async_handle_ptr = ptr::addr_of(continue_async_handle); let async_data = @@ -1521,41 +1064,41 @@ fn impl_uv_tcp_server(server_ip: str, server_write_req: server_write_req_ptr }; let server_data_ptr = ptr::addr_of(server_data); - direct::set_data_for_uv_handle(tcp_server_ptr as *libc::c_void, + ll::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 = direct::tcp_init( + let tcp_init_result = ll::tcp_init( test_loop as *libc::c_void, tcp_server_ptr); if (tcp_init_result == 0i32) { - let server_addr = direct::ip4_addr(server_ip, server_port); + let server_addr = ll::ip4_addr(server_ip, server_port); // FIXME ref #2064 let server_addr_ptr = ptr::addr_of(server_addr); // uv_tcp_bind() - let bind_result = direct::tcp_bind(tcp_server_ptr, + let bind_result = ll::tcp_bind(tcp_server_ptr, server_addr_ptr); if (bind_result == 0i32) { io::println("successful uv_tcp_bind, listening"); // uv_listen() - let listen_result = direct::listen(tcp_server_ptr as + let listen_result = ll::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 = direct::async_init(test_loop, + let async_result = ll::async_init(test_loop, continue_async_handle_ptr, continue_async_cb); if (async_result == 0i32) { - direct::set_data_for_uv_handle( + ll::set_data_for_uv_handle( continue_async_handle_ptr as *libc::c_void, async_data_ptr as *libc::c_void); - direct::async_send(continue_async_handle_ptr); + ll::async_send(continue_async_handle_ptr); // uv_run() - direct::run(test_loop); + ll::run(test_loop); io::println("server uv::run() has returned"); } else { @@ -1581,7 +1124,7 @@ fn impl_uv_tcp_server(server_ip: str, tcp_init_result as int)); assert false; } - direct::loop_delete(test_loop); + ll::loop_delete(test_loop); } #[test] @@ -1632,7 +1175,7 @@ fn test_uv_tcp_server_and_request() unsafe { #[ignore(cfg(target_os = "freebsd"))] fn test_uv_struct_size_uv_tcp_t() { let native_handle_size = rustrt::rust_uv_helper_uv_tcp_t_size(); - let rust_handle_size = sys::size_of::(); + let rust_handle_size = sys::size_of::(); let output = #fmt("uv_tcp_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); io::println(output); @@ -1643,7 +1186,7 @@ fn test_uv_struct_size_uv_tcp_t() { fn test_uv_struct_size_uv_connect_t() { let native_handle_size = rustrt::rust_uv_helper_uv_connect_t_size(); - let rust_handle_size = sys::size_of::(); + let rust_handle_size = sys::size_of::(); let output = #fmt("uv_connect_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); io::println(output); @@ -1654,7 +1197,7 @@ fn test_uv_struct_size_uv_connect_t() { fn test_uv_struct_size_uv_buf_t() { let native_handle_size = rustrt::rust_uv_helper_uv_buf_t_size(); - let rust_handle_size = sys::size_of::(); + let rust_handle_size = sys::size_of::(); let output = #fmt("uv_buf_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); io::println(output); @@ -1665,7 +1208,7 @@ fn test_uv_struct_size_uv_buf_t() { fn test_uv_struct_size_uv_write_t() { let native_handle_size = rustrt::rust_uv_helper_uv_write_t_size(); - let rust_handle_size = sys::size_of::(); + let rust_handle_size = sys::size_of::(); let output = #fmt("uv_write_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); io::println(output); @@ -1677,7 +1220,7 @@ fn test_uv_struct_size_uv_write_t() { fn test_uv_struct_size_sockaddr_in() { let native_handle_size = rustrt::rust_uv_helper_sockaddr_in_size(); - let rust_handle_size = sys::size_of::(); + let rust_handle_size = sys::size_of::(); let output = #fmt("sockaddr_in -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); io::println(output); @@ -1689,7 +1232,7 @@ fn test_uv_struct_size_sockaddr_in() { fn test_uv_struct_size_uv_async_t() { let native_handle_size = rustrt::rust_uv_helper_uv_async_t_size(); - let rust_handle_size = sys::size_of::(); + let rust_handle_size = sys::size_of::(); let output = #fmt("uv_async_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); io::println(output); diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs new file mode 100644 index 0000000000000..520298ca5c0d2 --- /dev/null +++ b/src/libstd/uv_ll.rs @@ -0,0 +1,526 @@ +// libuv struct mappings +type uv_ip4_addr = { + ip: [u8], + port: int +}; +type uv_ip6_addr = uv_ip4_addr; + +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 +} + +type handle_type = libc::c_uint; + +type uv_handle_fields = { + loop_handle: *libc::c_void, + type_: handle_type, + close_cb: *u8, + mut data: *libc::c_void, +}; + +// unix size: 8 +type 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..) +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +type uv_stream_t = { + fields: uv_handle_fields +}; + +// unix size: 272 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type 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, a26: *u8, a27: *u8, + a28: *u8, a29: *u8 +}; +// win32 size: 240 (120) +#[cfg(target_os = "win32")] +type 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: 48 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type uv_connect_t = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8 +}; +// win32 size: 88 (44) +#[cfg(target_os = "win32")] +type 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 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +type uv_buf_t = { + base: *u8, + len: libc::size_t +}; +// no gen stub method.. should create +// it via uv::direct::buf_init() + +// unix size: 144 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type 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, a13: *u8 +}; +// win32 size: 136 (68) +#[cfg(target_os = "win32")] +type 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 +}; +// unix size: 120 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +type 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 +}; +// win32 size 132 (68) +#[cfg(target_os = "win32")] +type 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 +}; + +// unix size: 16 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +type sockaddr_in = { + mut sin_family: u16, + mut sin_port: u16, + mut sin_addr: u32, // in_addr: this is an opaque, per-platform struct + mut sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8) +}; + +// unix size: 28 .. make due w/ 32 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +type sockaddr_in6 = { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8 +}; + +mod uv_ll_struct_stubgen { + #[cfg(target_os = "linux")] + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + fn gen_stub_uv_tcp_t() -> uv_tcp_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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, a26: 0 as *u8, + a27: 0 as *u8, + a28: 0 as *u8, a29: 0 as *u8 + }; + } + #[cfg(target_os = "win32")] + fn gen_stub_uv_tcp_t() -> uv_tcp_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 = "linux")] + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + fn gen_stub_uv_connect_t() -> uv_connect_t { + ret { + a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, + a03: 0 as *u8, + a04: 0 as *u8, a05: 0 as *u8 + }; + } + #[cfg(target_os = "win32")] + fn gen_stub_uv_connect_t() -> uv_connect_t { + ret { + 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(target_os = "linux")] + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + fn gen_stub_uv_async_t() -> uv_async_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 + }; + } + #[cfg(target_os = "win32")] + fn gen_stub_uv_async_t() -> uv_async_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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(target_os = "linux")] + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + fn gen_stub_uv_write_t() -> uv_write_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 + }; + } + #[cfg(target_os = "win32")] + fn gen_stub_uv_write_t() -> uv_write_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 + }; + } +} + +#[nolink] +native mod rustrt { + fn rust_uv_loop_new() -> *libc::c_void; + fn rust_uv_loop_delete(lp: *libc::c_void); + fn rust_uv_run(loop_handle: *libc::c_void); + fn rust_uv_close(handle: *libc::c_void, cb: *u8); + fn rust_uv_async_send(handle: *uv_async_t); + fn rust_uv_async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int; + fn rust_uv_tcp_init( + loop_handle: *libc::c_void, + handle_ptr: *uv_tcp_t) -> libc::c_int; + fn rust_uv_buf_init(base: *u8, len: libc::size_t) + -> uv_buf_t; + fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; + // FIXME ref #2064 + fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char; + // FIXME ref #2064 + fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char; + fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) + -> sockaddr_in; + // 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) -> libc::c_int; + // FIXME ref 2064 + fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, + ++addr: *sockaddr_in) -> libc::c_int; + fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int, + cb: *u8) -> libc::c_int; + fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) + -> libc::c_int; + 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; + fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8, + on_read: *u8) -> libc::c_int; + fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int; + fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; + fn rust_uv_free_base_of_buf(++buf: uv_buf_t); + + // data accessors for rust-mapped uv structs + 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: *libc::c_void) + -> *libc::c_void; + fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void) + -> *libc::c_void; + fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void, + data: *libc::c_void); + fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void; + fn rust_uv_set_data_for_req(req: *libc::c_void, + data: *libc::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) -> libc::size_t; +} + +unsafe fn loop_new() -> *libc::c_void { + ret rustrt::rust_uv_loop_new(); +} + +unsafe fn loop_delete(loop_handle: *libc::c_void) { + rustrt::rust_uv_loop_delete(loop_handle); +} + +unsafe fn run(loop_handle: *libc::c_void) { + rustrt::rust_uv_run(loop_handle); +} + +unsafe fn close(handle: *libc::c_void, cb: *u8) { + rustrt::rust_uv_close(handle, cb); +} + +unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t) + -> libc::c_int { + ret rustrt::rust_uv_tcp_init(loop_handle, handle); +} +// FIXME ref #2064 +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 { + let address = *addr_ptr; + io::println(#fmt("b4 native tcp_connect--addr port: %u cb: %u", + address.sin_port as uint, after_connect_cb as uint)); + ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); +} +// FIXME ref #2064 +unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in) -> libc::c_int { + ret rustrt::rust_uv_tcp_bind(tcp_server_ptr, + addr_ptr); +} + +unsafe fn listen(stream: *libc::c_void, backlog: libc::c_int, + cb: *u8) -> libc::c_int { + ret rustrt::rust_uv_listen(stream, backlog, cb); +} + +unsafe fn accept(server: *libc::c_void, client: *libc::c_void) + -> libc::c_int { + ret rustrt::rust_uv_accept(server, client); +} + +unsafe fn write(req: *libc::c_void, stream: *libc::c_void, + buf_in: *[uv_buf_t], cb: *u8) -> libc::c_int { + let buf_ptr = vec::unsafe::to_ptr(*buf_in); + let buf_cnt = vec::len(*buf_in) as i32; + ret rustrt::rust_uv_write(req, stream, buf_ptr, buf_cnt, cb); +} +unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, + on_read: *u8) -> libc::c_int { + ret rustrt::rust_uv_read_start(stream as *libc::c_void, + on_alloc, on_read); +} + +unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int { + ret rustrt::rust_uv_read_stop(stream as *libc::c_void); +} + +unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t { + ret rustrt::rust_uv_last_error(loop_handle); +} + +unsafe fn strerror(err: *uv_err_t) -> *libc::c_char { + ret rustrt::rust_uv_strerror(err); +} +unsafe fn err_name(err: *uv_err_t) -> *libc::c_char { + ret rustrt::rust_uv_err_name(err); +} + +unsafe fn async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int { + ret rustrt::rust_uv_async_init(loop_handle, + async_handle, + cb); +} + +unsafe fn async_send(async_handle: *uv_async_t) { + ret rustrt::rust_uv_async_send(async_handle); +} + +// libuv struct initializers +unsafe fn tcp_t() -> uv_tcp_t { + ret uv_ll_struct_stubgen::gen_stub_uv_tcp_t(); +} +unsafe fn connect_t() -> uv_connect_t { + ret uv_ll_struct_stubgen::gen_stub_uv_connect_t(); +} +unsafe fn write_t() -> uv_write_t { + ret uv_ll_struct_stubgen::gen_stub_uv_write_t(); +} +unsafe fn async_t() -> uv_async_t { + ret uv_ll_struct_stubgen::gen_stub_uv_async_t(); +} +unsafe fn get_loop_for_uv_handle(handle: *libc::c_void) + -> *libc::c_void { + ret rustrt::rust_uv_get_loop_for_uv_handle(handle); +} +unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) + -> *uv_stream_t { + ret rustrt::rust_uv_get_stream_handle_from_connect_req( + connect); +} +unsafe fn get_stream_handle_from_write_req( + write_req: *uv_write_t) + -> *uv_stream_t { + ret rustrt::rust_uv_get_stream_handle_from_write_req( + write_req); +} + +unsafe fn get_data_for_uv_handle(handle: *libc::c_void) -> *libc::c_void { + ret rustrt::rust_uv_get_data_for_uv_handle(handle); +} +unsafe fn set_data_for_uv_handle(handle: *libc::c_void, + data: *libc::c_void) { + rustrt::rust_uv_set_data_for_uv_handle(handle, data); +} +unsafe fn get_data_for_req(req: *libc::c_void) -> *libc::c_void { + ret rustrt::rust_uv_get_data_for_req(req); +} +unsafe fn set_data_for_req(req: *libc::c_void, + data: *libc::c_void) { + rustrt::rust_uv_set_data_for_req(req, data); +} +unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { + ret rustrt::rust_uv_get_base_from_buf(buf); +} +unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t { + ret rustrt::rust_uv_get_len_from_buf(buf); +} +unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { + ret rustrt::rust_uv_buf_init(input, len); +} +unsafe fn ip4_addr(ip: str, port: int) +-> sockaddr_in { + let mut addr_vec = str::bytes(ip); + addr_vec += [0u8]; // add null terminator + let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); + let ip_back = str::from_bytes(addr_vec); + io::println(#fmt("vec val: '%s' length: %u", + ip_back, vec::len(addr_vec))); + ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, + port as libc::c_int); +} +unsafe fn malloc_buf_base_of(suggested_size: libc::size_t) + -> *u8 { + ret rustrt::rust_uv_malloc_buf_base_of(suggested_size); +} +unsafe fn free_base_of_buf(buf: uv_buf_t) { + rustrt::rust_uv_free_base_of_buf(buf); +} + +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::unsafe::from_c_str(err_name(err_ptr)); + let err_msg = str::unsafe::from_c_str(strerror(err_ptr)); + ret #fmt("LIBUV ERROR: name: %s msg: %s", + err_name, err_msg); +} \ No newline at end of file From 1755e2babae317e4f2801f8e8a3104a42e52c55f Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 2 Apr 2012 11:03:45 -0700 Subject: [PATCH 26/33] adding uv_hl module and some doc work --- src/libstd/std.rc | 1 + src/libstd/uv.rs | 40 +++++++++++-------- src/libstd/uv_hl.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++ src/libstd/uv_ll.rs | 22 +++++++++++ 4 files changed, 141 insertions(+), 17 deletions(-) create mode 100644 src/libstd/uv_hl.rs diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 998c31115cac2..5756f07fd4014 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -23,6 +23,7 @@ mod net; // libuv modules mod uv; mod uv_ll; +mod uv_hl; // Utility modules diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index f5ee758a368bc..5099ef0749103 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -1,23 +1,26 @@ #[doc = " Rust bindings to libuv -This crate provides a low-level mapping to libuv, a library for -running an asynchronous event loop, with extensive IO operations. - -This crate is seeing heavy work, currently, and the final API layout -should not be inferred from its current form. - -The base module contains a set of safe functions for creating -an event loop that runs within a single task, but allows operations -against it from other tasks, but funneling it through a uv_async -request which reads from a port that users write to. This API should -not be considered stable and may go away in the near future. - -The 'll' module contains low-level, bare-metal mappings to the libuv -C-api. All functions within this module are marked unsafe and should -be used, primarily, for composing rust-idiomatic abstractions. In -lieu of satisfactory documention for the 'll' module, itself, libuv's -uv.h should be consulted. +This is the base-module for various levels of bindings to +the libuv library. + +These modules are seeing heavy work, currently, and the final +API layout should not be inferred from its current form. + +This base module currently contains a historical, rust-based +implementation of a few libuv operations that hews closely to +the patterns of the libuv C-API. It was used, mostly, to explore +some implementation details and will most likely be deprecated +in the near future. + +The `ll` module contains low-level mappings for working directly +with the libuv C-API. + +The `hl` module contains a set of tools library developers can +use for interacting with an active libuv loop. This modules's +API is meant to be used to write high-level, +rust-idiomatic abstractions for utilizes libuv's asynchronous IO +facilities. "]; import map::hashmap; @@ -28,6 +31,9 @@ export timer_init, timer_start, timer_stop; import ll = uv_ll; export ll; +import hl = uv_hl; +export hl; + #[nolink] native mod rustrt { fn rust_uv_loop_new() -> *libc::c_void; diff --git a/src/libstd/uv_hl.rs b/src/libstd/uv_hl.rs new file mode 100644 index 0000000000000..753af6f090b01 --- /dev/null +++ b/src/libstd/uv_hl.rs @@ -0,0 +1,95 @@ +#[doc = " +High-level bindings to work with the libuv library. + +This module is geared towards library developers who want to +provide a high-level, abstracted interface to some set of +libuv functionality. +"]; + +import ll = uv_ll; + +export high_level_loop; +export interact, prepare_loop; + +#[doc = " +Used to abstract-away direct interaction with a libuv loop. + +# Fields + +* async_handle - a pointer to a uv_async_t struct used to 'poke' +the C uv loop to process any pending callbacks + +* op_chan - a channel used to send function callbacks to be processed +by the C uv loop +"] +type high_level_loop = { + async_handle: *ll::uv_async_t, + op_chan: comm::chan +}; + +#[doc = " +Pass in a callback to be processed on the running libuv loop's thread + +# Fields + +* a_loop - a high_level_loop record that represents a channel of +communication with an active libuv loop running on a thread +somwhere in the current process + +* cb - a function callback to be processed on the running loop's +thread. The only parameter is an opaque pointer to the running +uv_loop_t. You can use this pointer to initiate or continue any +operations against the loop +"] +unsafe fn interact(a_loop: high_level_loop, + -cb: fn~(*libc::c_void)) { + comm::send(a_loop.op_chan, cb); + ll::async_send(a_loop.async_handle); +} + +#[doc = " +Prepares a clean, inactive uv_loop_t* to be used with any of the +functions in the `uv::hl` module. + +Library developers can use this function to prepare a given +`uv_loop_t*`, whose lifecycle they manage, to be used, ran +and controlled with the tools in this module. + +After this is ran against a loop, a library developer can run +the loop in its own thread and then use the returned +`high_level_loop` to interact with it. + +# Fields + +* loop_ptr - a pointer to a newly created `uv_loop_t*` with no +handles registered (this will interfere with the internal lifecycle +management this module provides). Ideally, this should be called +immediately after using `uv::ll::loop_new()` + +# Returns + +A `high_level_loop` record that can be used to interact with the +loop (after you use `uv::ll::run()` on the `uv_loop_t*`, of course +"] +unsafe fn prepare_loop(loop_ptr: *libc::c_void) + -> high_level_loop { + // will probably need to stake out a data record + // here, as well, to keep whatever state we want to + // use with the loop + + // move this into a malloc + let async = ll::async_t(); + let async_ptr = ptr::addr_of(async); + let async_result = ll::async_init(loop_ptr, + async_ptr, + interact_ptr); + if (async_result != 0i32) { + fail ll::get_last_err_info(loop_ptr); + } +} + +// this will be invoked by a called to uv::hl::interact(), so +// we'll drain the port of pending callbacks, processing each +crust fn interact_poke(async_handle: *libc::c_void) { + // nothing here, yet. +} \ No newline at end of file diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 520298ca5c0d2..a3e934e1ee8ef 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1,3 +1,25 @@ +#[doc = " +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. +"]; + // libuv struct mappings type uv_ip4_addr = { ip: [u8], From 15a8547575a5ed9d8e17cd9fecabbc4324a9a819 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 2 Apr 2012 16:17:10 -0700 Subject: [PATCH 27/33] fixing some libuv stuff that leaked through the rebase --- src/libstd/uv.rs | 27 ++++++++++++++------------- src/libstd/uv_hl.rs | 9 ++++++++- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 5099ef0749103..542ade068f2a3 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -65,36 +65,37 @@ native mod rustrt { fn rust_uv_free(ptr: *libc::c_void); fn rust_uv_tcp_init( loop_handle: *libc::c_void, - handle_ptr: *uv_tcp_t) -> libc::c_int; + handle_ptr: *ll::uv_tcp_t) -> libc::c_int; fn rust_uv_buf_init(base: *u8, len: libc::size_t) - -> uv_buf_t; - fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; + -> ll::uv_buf_t; + fn rust_uv_last_error(loop_handle: *libc::c_void) -> + ll::uv_err_t; // FIXME ref #2064 - fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char; + fn rust_uv_strerror(err: *ll::uv_err_t) -> *libc::c_char; // FIXME ref #2064 - fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char; + fn rust_uv_err_name(err: *ll::uv_err_t) -> *libc::c_char; fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) - -> sockaddr_in; + -> ll::sockaddr_in; // FIXME ref #2064 - fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, - tcp_handle_ptr: *uv_tcp_t, + fn rust_uv_tcp_connect(connect_ptr: *ll::uv_connect_t, + tcp_handle_ptr: *ll::uv_tcp_t, ++after_cb: *u8, - ++addr: *sockaddr_in) -> libc::c_int; + ++addr: *ll::sockaddr_in) -> libc::c_int; // FIXME ref 2064 - fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, - ++addr: *sockaddr_in) -> libc::c_int; + fn rust_uv_tcp_bind(tcp_server: *ll::uv_tcp_t, + ++addr: *ll::sockaddr_in) -> libc::c_int; fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int, cb: *u8) -> libc::c_int; fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) -> libc::c_int; fn rust_uv_write(req: *libc::c_void, stream: *libc::c_void, - ++buf_in: *uv_buf_t, buf_cnt: libc::c_int, + ++buf_in: *ll::uv_buf_t, buf_cnt: libc::c_int, cb: *u8) -> libc::c_int; fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8, on_read: *u8) -> libc::c_int; fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int; fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; - fn rust_uv_free_base_of_buf(++buf: uv_buf_t); + fn rust_uv_free_base_of_buf(++buf: ll::uv_buf_t); // sizeof testing helpers fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint; diff --git a/src/libstd/uv_hl.rs b/src/libstd/uv_hl.rs index 753af6f090b01..910ad9d7e8120 100644 --- a/src/libstd/uv_hl.rs +++ b/src/libstd/uv_hl.rs @@ -71,6 +71,7 @@ immediately after using `uv::ll::loop_new()` A `high_level_loop` record that can be used to interact with the loop (after you use `uv::ll::run()` on the `uv_loop_t*`, of course "] +#[cfg(target_archsdfsdf="bleh")] unsafe fn prepare_loop(loop_ptr: *libc::c_void) -> high_level_loop { // will probably need to stake out a data record @@ -80,12 +81,18 @@ unsafe fn prepare_loop(loop_ptr: *libc::c_void) // move this into a malloc let async = ll::async_t(); let async_ptr = ptr::addr_of(async); + let op_port = comm::port::(); let async_result = ll::async_init(loop_ptr, async_ptr, - interact_ptr); + interact_poke); if (async_result != 0i32) { fail ll::get_last_err_info(loop_ptr); } + // need to store the port and async_ptr in the top-level + // of the provided loop .. + ret { async_handle: async_ptr, + op_chan: comm::chan::(op_port) + }; } // this will be invoked by a called to uv::hl::interact(), so From 855aa3e813f0774a6cadcb40b8a0fcca74e3d450 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 3 Apr 2012 04:20:29 -0700 Subject: [PATCH 28/33] adding 32bit-unix struct struct size differences --- src/libstd/uv_ll.rs | 246 ++++++++++++++++++++++++++++++++------------ 1 file changed, 178 insertions(+), 68 deletions(-) diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index a3e934e1ee8ef..ff1f2b0e12617 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -73,7 +73,7 @@ type uv_stream_t = { fields: uv_handle_fields }; -// unix size: 272 +// 64bit unix size: 272 #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] @@ -86,9 +86,22 @@ type uv_tcp_t = { a16: *u8, a17: *u8, a18: *u8, a19: *u8, a20: *u8, a21: *u8, a22: *u8, a23: *u8, a24: *u8, a25: *u8, a26: *u8, a27: *u8, - a28: *u8, a29: *u8 + a28: *u8, + a30: uv_tcp_t_32bit_unix_riders }; -// win32 size: 240 (120) +// 32bit unix size: 328 (164) +#[cfg(target_arch="x86_64")] +type uv_tcp_t_32bit_unix_riders = { + a29: *u8 +}; +#[cfg(target_arch="x86")] +type uv_tcp_t_32bit_unix_riders = { + a29: *u8, a30: *u8, a31: *u8, + a32: *u8, a33: *u8, a34: *u8, + a35: *u8, a36: *u8 +}; + +// 32bit win32 size: 240 (120) #[cfg(target_os = "win32")] type uv_tcp_t = { fields: uv_handle_fields, @@ -138,7 +151,16 @@ type uv_write_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 + a12: *u8, + a14: uv_write_t_32bit_unix_riders +}; +#[cfg(target_arch="x86_64")] +type uv_write_t_32bit_unix_riders = { + a13: *u8 +}; +#[cfg(target_arch="x86")] +type uv_write_t_32bit_unix_riders = { + a13: *u8, a14: *u8 }; // win32 size: 136 (68) #[cfg(target_os = "win32")] @@ -149,7 +171,8 @@ type uv_write_t = { a08: *u8, a09: *u8, a10: *u8, a11: *u8, a12: *u8 }; -// unix size: 120 +// 64bit unix size: 120 +// 32bit unix size: 152 (76) #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] @@ -157,7 +180,16 @@ type 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 + a08: *u8, a09: *u8, + a11: uv_async_t_32bit_unix_riders +}; +#[cfg(target_arch="x86_64")] +type uv_async_t_32bit_unix_riders = { + a10: *u8 +}; +#[cfg(target_arch="x86")] +type uv_async_t_32bit_unix_riders = { + a10: *u8, a11: *u8, a12: *u8, a13: *u8 }; // win32 size 132 (68) #[cfg(target_os = "win32")] @@ -192,49 +224,86 @@ type sockaddr_in6 = { }; mod uv_ll_struct_stubgen { - #[cfg(target_os = "linux")] - #[cfg(target_os = "macos")] - #[cfg(target_os = "freebsd")] fn gen_stub_uv_tcp_t() -> uv_tcp_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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, a26: 0 as *u8, - a27: 0 as *u8, - a28: 0 as *u8, a29: 0 as *u8 - }; - } - #[cfg(target_os = "win32")] - fn gen_stub_uv_tcp_t() -> uv_tcp_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; + ret gen_stub_os(); + #[cfg(target_os = "linux")] + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + fn gen_stub_os() -> uv_tcp_t { + ret gen_stub_arch(); + #[cfg(target_arch="x86_64")] + fn gen_stub_arch() -> uv_tcp_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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, a26: 0 as *u8, + a27: 0 as *u8, + a28: 0 as *u8, + a30: { + a29: 0 as *u8 + } + }; + } + #[cfg(target_arch="x86")] + fn gen_stub_arch() -> uv_tcp_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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, a26: 0 as *u8, + a27: 0 as *u8, + a28: 0 as *u8, + a30: { + a29: 0 as *u8, a30: 0 as *u8, a31: 0 as *u8, + a32: 0 as *u8, a33: 0 as *u8, a34: 0 as *u8, + a35: 0 as *u8, a36: 0 as *u8 + } + }; + } + } + #[cfg(target_os = "win32")] + fn gen_stub_os() -> uv_tcp_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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 = "linux")] #[cfg(target_os = "macos")] @@ -260,15 +329,38 @@ mod uv_ll_struct_stubgen { #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] fn gen_stub_uv_async_t() -> uv_async_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; + ret gen_stub_arch(); + #[cfg(target_arch = "x86_64")] + fn gen_stub_arch() -> uv_async_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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: { + a10: 0 as *u8 + } + }; + } + #[cfg(target_arch = "x86")] + fn gen_stub_arch() -> uv_async_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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: { + a10: 0 as *u8, a11: 0 as *u8, + a12: 0 as *u8, a13: 0 as *u8 + } + }; + } } #[cfg(target_os = "win32")] fn gen_stub_uv_async_t() -> uv_async_t { @@ -288,17 +380,35 @@ mod uv_ll_struct_stubgen { #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] fn gen_stub_uv_write_t() -> uv_write_t { - ret { fields: { loop_handle: ptr::null(), type_: 0u32, - close_cb: ptr::null(), - mut 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 - }; + ret gen_stub_arch(); + #[cfg(target_arch="x86_64")] + fn gen_stub_arch() -> uv_write_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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: { a13: 0 as *u8 } + }; + } + #[cfg(target_arch="x86")] + fn gen_stub_arch() -> uv_write_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut 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: { a13: 0 as *u8, a14: 0 as *u8 } + }; + } } #[cfg(target_os = "win32")] fn gen_stub_uv_write_t() -> uv_write_t { From 725df1a861e80190ac1c70f04a658822392f21a5 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 3 Apr 2012 09:25:13 -0700 Subject: [PATCH 29/33] whitespace cleanup in uv_* --- src/libstd/uv_hl.rs | 2 +- src/libstd/uv_ll.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/uv_hl.rs b/src/libstd/uv_hl.rs index 910ad9d7e8120..c12cbfd9202d9 100644 --- a/src/libstd/uv_hl.rs +++ b/src/libstd/uv_hl.rs @@ -77,7 +77,7 @@ unsafe fn prepare_loop(loop_ptr: *libc::c_void) // will probably need to stake out a data record // here, as well, to keep whatever state we want to // use with the loop - + // move this into a malloc let async = ll::async_t(); let async_ptr = ptr::addr_of(async); diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index ff1f2b0e12617..541a6d0bd3019 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -180,7 +180,7 @@ type 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, + a08: *u8, a09: *u8, a11: uv_async_t_32bit_unix_riders }; #[cfg(target_arch="x86_64")] From 3bb9d8d794844893e96191f9cdde8017bbb5c6c5 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 3 Apr 2012 09:42:22 -0700 Subject: [PATCH 30/33] removed this binding a few commits back. missed it in rustrt.def.in --- src/rt/rustrt.def.in | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index bf51d67cd41cf..e21edfbdd805c 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -102,7 +102,6 @@ rust_uv_buf_init rust_uv_last_error rust_uv_strerror rust_uv_err_name -rust_uv_ip4_test_verify_port_val rust_uv_ip4_addr rust_uv_tcp_connect rust_uv_tcp_bind From 749644d961ae8751262bea03a7cc8ae469d5c709 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 4 Apr 2012 00:17:19 -0700 Subject: [PATCH 31/33] experimenting with a different uv_buf_init impl to placate 32bit linux --- src/libstd/uv.rs | 9 +++++---- src/libstd/uv_ll.rs | 26 +++++++++++++++++++++++--- src/rt/rust_uv.cpp | 19 +++++++++++++++++-- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 542ade068f2a3..a76f2afe1bf6d 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -66,10 +66,6 @@ native mod rustrt { fn rust_uv_tcp_init( loop_handle: *libc::c_void, handle_ptr: *ll::uv_tcp_t) -> libc::c_int; - fn rust_uv_buf_init(base: *u8, len: libc::size_t) - -> ll::uv_buf_t; - fn rust_uv_last_error(loop_handle: *libc::c_void) -> - ll::uv_err_t; // FIXME ref #2064 fn rust_uv_strerror(err: *ll::uv_err_t) -> *libc::c_char; // FIXME ref #2064 @@ -723,6 +719,9 @@ crust fn on_alloc_cb(handle: *libc::c_void, -> ll::uv_buf_t unsafe { io::println("on_alloc_cb!"); let char_ptr = ll::malloc_buf_base_of(suggested_size); + io::println(#fmt("on_alloc_cb char_ptr: %u sug. size: %u", + char_ptr as uint, + suggested_size as uint)); ret ll::buf_init(char_ptr, suggested_size); } @@ -816,6 +815,7 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, // data field in our uv_connect_t struct let req_str_bytes = str::bytes(req_str); let req_msg_ptr: *u8 = vec::unsafe::to_ptr(req_str_bytes); + io::println(#fmt("req_msg ptr: %u", req_msg_ptr as uint)); let req_msg = [ ll::buf_init(req_msg_ptr, vec::len(req_str_bytes)) ]; @@ -1051,6 +1051,7 @@ fn impl_uv_tcp_server(server_ip: str, let resp_str_bytes = str::bytes(server_resp_msg); let resp_msg_ptr: *u8 = vec::unsafe::to_ptr(resp_str_bytes); + io::println(#fmt("resp_msg ptr: %u", resp_msg_ptr as uint)); let resp_msg = [ ll::buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) ]; diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 541a6d0bd3019..059792b8da549 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -439,7 +439,10 @@ native mod rustrt { fn rust_uv_tcp_init( loop_handle: *libc::c_void, handle_ptr: *uv_tcp_t) -> libc::c_int; - fn rust_uv_buf_init(base: *u8, len: libc::size_t) + // FIXME ref #2604 .. ? + fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, + len: libc::size_t); + fn rust_uv_buf_init_2(++base: *u8, len: libc::size_t) -> uv_buf_t; fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; // FIXME ref #2064 @@ -626,8 +629,25 @@ unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t { ret rustrt::rust_uv_get_len_from_buf(buf); } -unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { - ret rustrt::rust_uv_buf_init(input, len); +unsafe fn buf_init(++input: *u8, len: uint) -> uv_buf_t { + let out_buf = { base: ptr::null(), len: 0 as libc::size_t }; + let out_buf_ptr = ptr::addr_of(out_buf); + io::println(#fmt("ll::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); + //let result = rustrt::rust_uv_buf_init_2(input, len); + io::println("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); + io::println(#fmt("ll::buf_init - result %u len %u", + res_base as uint, + res_len as uint)); + ret out_buf; + //ret result; } unsafe fn ip4_addr(ip: str, port: int) -> sockaddr_in { diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index c13b43a660d4b..316a44cc5d80c 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -300,9 +300,24 @@ current_kernel_malloc_alloc_cb(uv_handle_t* handle, return uv_buf_init(base_ptr, suggested_size); } +extern "C" void +rust_uv_buf_init(uv_buf_t* out_buf, char* base, size_t len) { + printf("rust_uv_buf_init: base: %lu len: %lu\n", + (long unsigned int)base, + (long unsigned int)len); + *out_buf = uv_buf_init(base, len); + printf("rust_uv_buf_init: after: result->base: %lu len: %lu\n", + (unsigned long int)(*out_buf).base, + (unsigned long int)(*out_buf).len); +} extern "C" uv_buf_t -rust_uv_buf_init(char* base, size_t len) { - return uv_buf_init(base, len); +rust_uv_buf_init_2(char* base, size_t len) { + printf("uv_buf_init: base ptr %p\n len: %lu", base, + (long unsigned int)len); + uv_buf_t result = uv_buf_init(base, len); + printf("after uv_buf_init: result->base %p\n", + result.base); + return result; } extern "C" uv_loop_t* From c897728148a841b9c6223611992943707855028c Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 4 Apr 2012 09:28:26 -0700 Subject: [PATCH 32/33] removing some unneeded native fn mappingsin uv.rs and misc clean .. 32bit linux issues persist. --- src/libstd/uv.rs | 37 ++++++------------------------------- src/libstd/uv_hl.rs | 1 - src/libstd/uv_ll.rs | 2 -- src/rt/rust_uv.cpp | 19 +++++-------------- 4 files changed, 11 insertions(+), 48 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index a76f2afe1bf6d..914ebfc811dd7 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -63,36 +63,6 @@ native mod rustrt { repeat: libc::c_uint); fn rust_uv_timer_stop(handle: *libc::c_void); fn rust_uv_free(ptr: *libc::c_void); - fn rust_uv_tcp_init( - loop_handle: *libc::c_void, - handle_ptr: *ll::uv_tcp_t) -> libc::c_int; - // FIXME ref #2064 - fn rust_uv_strerror(err: *ll::uv_err_t) -> *libc::c_char; - // FIXME ref #2064 - fn rust_uv_err_name(err: *ll::uv_err_t) -> *libc::c_char; - fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) - -> ll::sockaddr_in; - // FIXME ref #2064 - fn rust_uv_tcp_connect(connect_ptr: *ll::uv_connect_t, - tcp_handle_ptr: *ll::uv_tcp_t, - ++after_cb: *u8, - ++addr: *ll::sockaddr_in) -> libc::c_int; - // FIXME ref 2064 - fn rust_uv_tcp_bind(tcp_server: *ll::uv_tcp_t, - ++addr: *ll::sockaddr_in) -> libc::c_int; - fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int, - cb: *u8) -> libc::c_int; - fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) - -> libc::c_int; - fn rust_uv_write(req: *libc::c_void, stream: *libc::c_void, - ++buf_in: *ll::uv_buf_t, buf_cnt: libc::c_int, - cb: *u8) -> libc::c_int; - fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8, - on_read: *u8) -> libc::c_int; - fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int; - fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; - fn rust_uv_free_base_of_buf(++buf: ll::uv_buf_t); - // sizeof testing helpers fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint; fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint; @@ -715,7 +685,7 @@ crust fn after_close_cb(handle: *libc::c_void) { } crust fn on_alloc_cb(handle: *libc::c_void, - suggested_size: libc::size_t) + ++suggested_size: libc::size_t) -> ll::uv_buf_t unsafe { io::println("on_alloc_cb!"); let char_ptr = ll::malloc_buf_base_of(suggested_size); @@ -909,6 +879,10 @@ crust fn on_server_read_cb(client_stream_ptr: *ll::uv_stream_t, // pull out the contents of the write from the client let buf_base = ll::get_base_from_buf(buf); let buf_len = ll::get_len_from_buf(buf); + io::println(#fmt("SERVER buf base: %u, len: %u, nread: %d", + buf_base as uint, + buf_len as uint, + nread)); let bytes = vec::unsafe::from_buf(buf_base, buf_len); let request_str = str::from_bytes(bytes); @@ -1246,3 +1220,4 @@ fn test_uv_struct_size_uv_async_t() { io::println(output); assert native_handle_size as uint == rust_handle_size; } + diff --git a/src/libstd/uv_hl.rs b/src/libstd/uv_hl.rs index c12cbfd9202d9..24fceadd9fbd2 100644 --- a/src/libstd/uv_hl.rs +++ b/src/libstd/uv_hl.rs @@ -71,7 +71,6 @@ immediately after using `uv::ll::loop_new()` A `high_level_loop` record that can be used to interact with the loop (after you use `uv::ll::run()` on the `uv_loop_t*`, of course "] -#[cfg(target_archsdfsdf="bleh")] unsafe fn prepare_loop(loop_ptr: *libc::c_void) -> high_level_loop { // will probably need to stake out a data record diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 059792b8da549..1b36b96d0f270 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -442,8 +442,6 @@ native mod rustrt { // FIXME ref #2604 .. ? fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, len: libc::size_t); - fn rust_uv_buf_init_2(++base: *u8, len: libc::size_t) - -> uv_buf_t; fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t; // FIXME ref #2064 fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char; diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 316a44cc5d80c..2b1e5d1ca3c57 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -302,22 +302,13 @@ current_kernel_malloc_alloc_cb(uv_handle_t* handle, extern "C" void rust_uv_buf_init(uv_buf_t* out_buf, char* base, size_t len) { - printf("rust_uv_buf_init: base: %lu len: %lu\n", - (long unsigned int)base, - (long unsigned int)len); + printf("rust_uv_buf_init: base: %lu len: %lu\n", + (long unsigned int)base, + (long unsigned int)len); *out_buf = uv_buf_init(base, len); printf("rust_uv_buf_init: after: result->base: %lu len: %lu\n", - (unsigned long int)(*out_buf).base, - (unsigned long int)(*out_buf).len); -} -extern "C" uv_buf_t -rust_uv_buf_init_2(char* base, size_t len) { - printf("uv_buf_init: base ptr %p\n len: %lu", base, - (long unsigned int)len); - uv_buf_t result = uv_buf_init(base, len); - printf("after uv_buf_init: result->base %p\n", - result.base); - return result; + (unsigned long int)(*out_buf).base, + (unsigned long int)(*out_buf).len); } extern "C" uv_loop_t* From 971400f1fe34262e185dc1860854845776e7b839 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 5 Apr 2012 07:38:25 -0700 Subject: [PATCH 33/33] ignore tcp server/client test on linux 32bit, pending #2064 also println->log(debug,) and assorted cleanup ahead of merge to master --- src/libstd/uv.rs | 170 ++++++++++++++++++++++++++------------------ src/libstd/uv_hl.rs | 2 + src/libstd/uv_ll.rs | 10 +-- 3 files changed, 107 insertions(+), 75 deletions(-) diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 914ebfc811dd7..d0e8c66d4b08e 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -681,15 +681,17 @@ type request_wrapper = { }; crust fn after_close_cb(handle: *libc::c_void) { - io::println("after uv_close!"); + log(debug, #fmt("after uv_close! handle ptr: %?", + handle)); } crust fn on_alloc_cb(handle: *libc::c_void, ++suggested_size: libc::size_t) -> ll::uv_buf_t unsafe { - io::println("on_alloc_cb!"); + log(debug, "on_alloc_cb!"); let char_ptr = ll::malloc_buf_base_of(suggested_size); - io::println(#fmt("on_alloc_cb char_ptr: %u sug. size: %u", + log(debug, #fmt("on_alloc_cb h: %? char_ptr: %u sugsize: %u", + handle, char_ptr as uint, suggested_size as uint)); ret ll::buf_init(char_ptr, suggested_size); @@ -698,10 +700,10 @@ crust fn on_alloc_cb(handle: *libc::c_void, crust fn on_read_cb(stream: *ll::uv_stream_t, nread: libc::ssize_t, ++buf: ll::uv_buf_t) unsafe { - io::println(#fmt("CLIENT entering on_read_cb nred: %d", nread)); + log(debug, #fmt("CLIENT entering on_read_cb nred: %d", nread)); if (nread > 0) { // we have data - io::println(#fmt("CLIENT read: data! nread: %d", nread)); + log(debug, #fmt("CLIENT read: data! nread: %d", nread)); ll::read_stop(stream); let client_data = ll:: get_data_for_uv_handle(stream as *libc::c_void) @@ -716,58 +718,58 @@ crust fn on_read_cb(stream: *ll::uv_stream_t, } else if (nread == -1) { // err .. possibly EOF - io::println("read: eof!"); + log(debug, "read: eof!"); } else { // nread == 0 .. do nothing, just free buf as below - io::println("read: do nothing!"); + log(debug, "read: do nothing!"); } // when we're done ll::free_base_of_buf(buf); - io::println("CLIENT exiting on_read_cb"); + log(debug, "CLIENT exiting on_read_cb"); } crust fn on_write_complete_cb(write_req: *ll::uv_write_t, status: libc::c_int) unsafe { - io::println(#fmt("CLIENT beginning on_write_complete_cb status: %d", + log(debug, #fmt("CLIENT beginning on_write_complete_cb status: %d", status as int)); let stream = ll::get_stream_handle_from_write_req(write_req); - io::println(#fmt("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", + log(debug, #fmt("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", stream as int, write_req as int)); let result = ll::read_start(stream, on_alloc_cb, on_read_cb); - io::println(#fmt("CLIENT ending on_write_complete_cb .. status: %d", + log(debug, #fmt("CLIENT ending on_write_complete_cb .. status: %d", result as int)); } crust fn on_connect_cb(connect_req_ptr: *ll::uv_connect_t, status: libc::c_int) unsafe { - io::println(#fmt("beginning on_connect_cb .. status: %d", + log(debug, #fmt("beginning on_connect_cb .. status: %d", status as int)); let stream = ll::get_stream_handle_from_connect_req(connect_req_ptr); if (status == 0i32) { - io::println("on_connect_cb: in status=0 if.."); + log(debug, "on_connect_cb: in status=0 if.."); let client_data = ll::get_data_for_req( connect_req_ptr as *libc::c_void) as *request_wrapper; let write_handle = (*client_data).write_req as *libc::c_void; - io::println(#fmt("on_connect_cb: tcp stream: %d write_handle addr %d", + log(debug, #fmt("on_connect_cb: tcp stream: %d write_handle addr %d", stream as int, write_handle as int)); let write_result = ll::write(write_handle, stream as *libc::c_void, (*client_data).req_buf, on_write_complete_cb); - io::println(#fmt("on_connect_cb: ll::write() status: %d", + log(debug, #fmt("on_connect_cb: ll::write() status: %d", write_result as int)); } else { let test_loop = ll::get_loop_for_uv_handle( stream as *libc::c_void); let err_msg = ll::get_last_err_info(test_loop); - io::println(err_msg); + log(debug, err_msg); assert false; } - io::println("finishing on_connect_cb"); + log(debug, "finishing on_connect_cb"); } fn impl_uv_tcp_request(ip: str, port: int, req_str: str, @@ -785,7 +787,7 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, // data field in our uv_connect_t struct let req_str_bytes = str::bytes(req_str); let req_msg_ptr: *u8 = vec::unsafe::to_ptr(req_str_bytes); - io::println(#fmt("req_msg ptr: %u", req_msg_ptr as uint)); + log(debug, #fmt("req_msg ptr: %u", req_msg_ptr as uint)); let req_msg = [ ll::buf_init(req_msg_ptr, vec::len(req_str_bytes)) ]; @@ -793,7 +795,7 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, // this to C.. let write_handle = ll::write_t(); let write_handle_ptr = ptr::addr_of(write_handle); - io::println(#fmt("tcp req: tcp stream: %d write_handle: %d", + log(debug, #fmt("tcp req: tcp stream: %d write_handle: %d", tcp_handle_ptr as int, write_handle_ptr as int)); let client_data = { writer_handle: write_handle_ptr, @@ -803,17 +805,17 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, let tcp_init_result = ll::tcp_init( test_loop as *libc::c_void, tcp_handle_ptr); if (tcp_init_result == 0i32) { - io::println("sucessful tcp_init_result"); + log(debug, "sucessful tcp_init_result"); - io::println("building addr..."); + log(debug, "building addr..."); let addr = ll::ip4_addr(ip, port); // FIXME ref #2064 let addr_ptr = ptr::addr_of(addr); - io::println(#fmt("after build addr in rust. port: %u", + log(debug, #fmt("after build addr in rust. port: %u", addr.sin_port as uint)); // this should set up the connection request.. - io::println(#fmt("before calling tcp_connect .. connect cb ptr: %u ", + log(debug, #fmt("before calling tcp_connect .. connect cb ptr: %u ", on_connect_cb as uint)); let tcp_connect_result = ll::tcp_connect( connect_req_ptr, tcp_handle_ptr, @@ -827,17 +829,17 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, ll::set_data_for_uv_handle( tcp_handle_ptr as *libc::c_void, ptr::addr_of(client_data) as *libc::c_void); - io::println("before run tcp req loop"); + log(debug, "before run tcp req loop"); ll::run(test_loop); - io::println("after run tcp req loop"); + log(debug, "after run tcp req loop"); } else { - io::println("ll::tcp_connect() failure"); + log(debug, "ll::tcp_connect() failure"); assert false; } } else { - io::println("ll::tcp_init() failure"); + log(debug, "ll::tcp_init() failure"); assert false; } ll::loop_delete(test_loop); @@ -845,12 +847,13 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, } crust fn server_after_close_cb(handle: *libc::c_void) unsafe { - io::println("SERVER server stream closed, should exit loop..."); + log(debug, #fmt("SERVER server stream closed, should exit.. h: %?", + handle)); } crust fn client_stream_after_close_cb(handle: *libc::c_void) unsafe { - io::println("SERVER: closed client stream, now closing server stream"); + log(debug, "SERVER: closed client stream, now closing server stream"); let client_data = ll::get_data_for_uv_handle( handle) as *tcp_server_data; @@ -861,10 +864,7 @@ crust fn client_stream_after_close_cb(handle: *libc::c_void) crust fn after_server_resp_write(req: *ll::uv_write_t) unsafe { let client_stream_ptr = ll::get_stream_handle_from_write_req(req); - let client_data = ll::get_data_for_uv_handle( - client_stream_ptr as *libc::c_void) as - *tcp_server_data; - io::println("SERVER: resp sent... closing client stream"); + log(debug, "SERVER: resp sent... closing client stream"); ll::close(client_stream_ptr as *libc::c_void, client_stream_after_close_cb) } @@ -874,12 +874,12 @@ crust fn on_server_read_cb(client_stream_ptr: *ll::uv_stream_t, ++buf: ll::uv_buf_t) unsafe { if (nread > 0) { // we have data - io::println(#fmt("SERVER read: data! nread: %d", nread)); + log(debug, #fmt("SERVER read: data! nread: %d", nread)); // pull out the contents of the write from the client let buf_base = ll::get_base_from_buf(buf); let buf_len = ll::get_len_from_buf(buf); - io::println(#fmt("SERVER buf base: %u, len: %u, nread: %d", + log(debug, #fmt("SERVER buf base: %u, len: %u, nread: %d", buf_base as uint, buf_len as uint, nread)); @@ -892,8 +892,8 @@ crust fn on_server_read_cb(client_stream_ptr: *ll::uv_stream_t, let server_kill_msg = (*client_data).server_kill_msg; let write_req = (*client_data).server_write_req; if (str::contains(request_str, server_kill_msg)) { - io::println("SERVER: client request contains server_kill_msg!"); - io::println("SERVER: sending response to client"); + log(debug, "SERVER: client request contains server_kill_msg!"); + log(debug, "SERVER: sending response to client"); ll::read_stop(client_stream_ptr); let server_chan = *((*client_data).server_chan); comm::send(server_chan, request_str); @@ -902,39 +902,45 @@ crust fn on_server_read_cb(client_stream_ptr: *ll::uv_stream_t, client_stream_ptr as *libc::c_void, (*client_data).server_resp_buf, after_server_resp_write); - io::println(#fmt("SERVER: resp write result: %d", + log(debug, #fmt("SERVER: resp write result: %d", write_result as int)); if (write_result != 0i32) { - io::println("bad result for server resp ll::write()"); - io::println(ll::get_last_err_info( + log(debug, "bad result for server resp ll::write()"); + log(debug, ll::get_last_err_info( ll::get_loop_for_uv_handle(client_stream_ptr as *libc::c_void))); assert false; } } else { - io::println("SERVER: client req DOESNT contain server_kill_msg!"); + log(debug, "SERVER: client req DOESNT contain server_kill_msg!"); } } else if (nread == -1) { // err .. possibly EOF - io::println("read: eof!"); + log(debug, "read: eof!"); } else { // nread == 0 .. do nothing, just free buf as below - io::println("read: do nothing!"); + log(debug, "read: do nothing!"); } // when we're done ll::free_base_of_buf(buf); - io::println("SERVER exiting on_read_cb"); + log(debug, "SERVER exiting on_read_cb"); } crust fn server_connection_cb(server_stream_ptr: *ll::uv_stream_t, status: libc::c_int) unsafe { - io::println("client connecting!"); + log(debug, "client connecting!"); let test_loop = ll::get_loop_for_uv_handle( server_stream_ptr as *libc::c_void); + if status != 0i32 { + let err_msg = ll::get_last_err_info(test_loop); + log(debug, #fmt("server_connect_cb: non-zero status: %?", + err_msg)); + ret; + } let server_data = ll::get_data_for_uv_handle( server_stream_ptr as *libc::c_void) as *tcp_server_data; let client_stream_ptr = (*server_data).client; @@ -944,7 +950,7 @@ crust fn server_connection_cb(server_stream_ptr: client_stream_ptr as *libc::c_void, server_data as *libc::c_void); if (client_init_result == 0i32) { - io::println("successfully initialized client stream"); + log(debug, "successfully initialized client stream"); let accept_result = ll::accept(server_stream_ptr as *libc::c_void, client_stream_ptr as @@ -956,22 +962,22 @@ crust fn server_connection_cb(server_stream_ptr: on_alloc_cb, on_server_read_cb); if (read_result == 0i32) { - io::println("successful server read start"); + log(debug, "successful server read start"); } else { - io::println(#fmt("server_connection_cb: bad read:%d", + log(debug, #fmt("server_connection_cb: bad read:%d", read_result as int)); assert false; } } else { - io::println(#fmt("server_connection_cb: bad accept: %d", + log(debug, #fmt("server_connection_cb: bad accept: %d", accept_result as int)); assert false; } } else { - io::println(#fmt("server_connection_cb: bad client init: %d", + log(debug, #fmt("server_connection_cb: bad client init: %d", client_init_result as int)); assert false; } @@ -991,7 +997,8 @@ type async_handle_data = { }; crust fn async_close_cb(handle: *libc::c_void) { - io::println("SERVER: closing async cb..."); + log(debug, #fmt("SERVER: closing async cb... h: %?", + handle)); } crust fn continue_async_cb(async_handle: *ll::uv_async_t, @@ -1003,7 +1010,8 @@ crust fn continue_async_cb(async_handle: *ll::uv_async_t, let data = ll::get_data_for_uv_handle( async_handle as *libc::c_void) as *async_handle_data; let continue_chan = *((*data).continue_chan); - comm::send(continue_chan, true); + let should_continue = status == 0i32; + comm::send(continue_chan, should_continue); ll::close(async_handle as *libc::c_void, async_close_cb); } @@ -1025,7 +1033,7 @@ fn impl_uv_tcp_server(server_ip: str, let resp_str_bytes = str::bytes(server_resp_msg); let resp_msg_ptr: *u8 = vec::unsafe::to_ptr(resp_str_bytes); - io::println(#fmt("resp_msg ptr: %u", resp_msg_ptr as uint)); + log(debug, #fmt("resp_msg ptr: %u", resp_msg_ptr as uint)); let resp_msg = [ ll::buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) ]; @@ -1061,7 +1069,7 @@ fn impl_uv_tcp_server(server_ip: str, let bind_result = ll::tcp_bind(tcp_server_ptr, server_addr_ptr); if (bind_result == 0i32) { - io::println("successful uv_tcp_bind, listening"); + log(debug, "successful uv_tcp_bind, listening"); // uv_listen() let listen_result = ll::listen(tcp_server_ptr as @@ -1081,37 +1089,37 @@ fn impl_uv_tcp_server(server_ip: str, ll::async_send(continue_async_handle_ptr); // uv_run() ll::run(test_loop); - io::println("server uv::run() has returned"); + log(debug, "server uv::run() has returned"); } else { - io::println(#fmt("uv_async_init failure: %d", + log(debug, #fmt("uv_async_init failure: %d", async_result as int)); assert false; } } else { - io::println(#fmt("non-zero result on uv_listen: %d", + log(debug, #fmt("non-zero result on uv_listen: %d", listen_result as int)); assert false; } } else { - io::println(#fmt("non-zero result on uv_tcp_bind: %d", + log(debug, #fmt("non-zero result on uv_tcp_bind: %d", bind_result as int)); assert false; } } else { - io::println(#fmt("non-zero result on uv_tcp_init: %d", + log(debug, #fmt("non-zero result on uv_tcp_init: %d", tcp_init_result as int)); assert false; } ll::loop_delete(test_loop); } -#[test] -#[ignore(cfg(target_os = "freebsd"))] -fn test_uv_tcp_server_and_request() unsafe { +// this is the impl for a test that is (maybe) ran on a +// per-platform/arch basis below +fn impl_uv_tcp_server_and_request() unsafe { let bind_ip = "0.0.0.0"; let request_ip = "127.0.0.1"; let port = 8888; @@ -1135,9 +1143,9 @@ fn test_uv_tcp_server_and_request() unsafe { }; // block until the server up is.. possibly a race? - io::println("before receiving on server continue_port"); + log(debug, "before receiving on server continue_port"); comm::recv(continue_port); - io::println("received on continue port, set up tcp client"); + log(debug, "received on continue port, set up tcp client"); task::spawn_sched(task::manual_threads(1u)) {|| impl_uv_tcp_request(request_ip, port, @@ -1152,6 +1160,28 @@ fn test_uv_tcp_server_and_request() unsafe { assert str::contains(msg_from_server, server_resp_msg); } +// don't run this test on fbsd or 32bit linux +#[cfg(target_os="win32")] +#[cfg(target_os="darwin")] +#[cfg(target_os="linux")] +mod tcp_and_server_client_test { + #[cfg(target_arch="x86_64")] + mod impl64 { + #[test] + fn test_uv_tcp_server_and_request() unsafe { + impl_uv_tcp_server_and_request(); + } + } + #[cfg(target_arch="x86")] + mod impl32 { + #[test] + #[ignore(cfg(target_os = "linux"))] + fn test_uv_tcp_server_and_request() unsafe { + impl_uv_tcp_server_and_request(); + } + } +} + // struct size tests #[test] #[ignore(cfg(target_os = "freebsd"))] @@ -1160,7 +1190,7 @@ fn test_uv_struct_size_uv_tcp_t() { let rust_handle_size = sys::size_of::(); let output = #fmt("uv_tcp_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); - io::println(output); + log(debug, output); assert native_handle_size as uint == rust_handle_size; } #[test] @@ -1171,7 +1201,7 @@ fn test_uv_struct_size_uv_connect_t() { let rust_handle_size = sys::size_of::(); let output = #fmt("uv_connect_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); - io::println(output); + log(debug, output); assert native_handle_size as uint == rust_handle_size; } #[test] @@ -1182,7 +1212,7 @@ fn test_uv_struct_size_uv_buf_t() { let rust_handle_size = sys::size_of::(); let output = #fmt("uv_buf_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); - io::println(output); + log(debug, output); assert native_handle_size as uint == rust_handle_size; } #[test] @@ -1193,7 +1223,7 @@ fn test_uv_struct_size_uv_write_t() { let rust_handle_size = sys::size_of::(); let output = #fmt("uv_write_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); - io::println(output); + log(debug, output); assert native_handle_size as uint == rust_handle_size; } @@ -1205,7 +1235,7 @@ fn test_uv_struct_size_sockaddr_in() { let rust_handle_size = sys::size_of::(); let output = #fmt("sockaddr_in -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); - io::println(output); + log(debug, output); assert native_handle_size as uint == rust_handle_size; } @@ -1217,7 +1247,7 @@ fn test_uv_struct_size_uv_async_t() { let rust_handle_size = sys::size_of::(); let output = #fmt("uv_async_t -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); - io::println(output); + log(debug, output); assert native_handle_size as uint == rust_handle_size; } diff --git a/src/libstd/uv_hl.rs b/src/libstd/uv_hl.rs index 24fceadd9fbd2..c716f7a306af4 100644 --- a/src/libstd/uv_hl.rs +++ b/src/libstd/uv_hl.rs @@ -98,4 +98,6 @@ unsafe fn prepare_loop(loop_ptr: *libc::c_void) // we'll drain the port of pending callbacks, processing each crust fn interact_poke(async_handle: *libc::c_void) { // nothing here, yet. + log(debug, #fmt("interact_poke crust.. handle: %?", + async_handle)); } \ No newline at end of file diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 1b36b96d0f270..85da16823c0ef 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -517,7 +517,7 @@ unsafe fn tcp_connect(connect_ptr: *uv_connect_t, ++after_connect_cb: *u8) -> libc::c_int { let address = *addr_ptr; - io::println(#fmt("b4 native tcp_connect--addr port: %u cb: %u", + log(debug, #fmt("b4 native tcp_connect--addr port: %u cb: %u", address.sin_port as uint, after_connect_cb as uint)); ret rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr); @@ -630,18 +630,18 @@ unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t { unsafe fn buf_init(++input: *u8, len: uint) -> uv_buf_t { let out_buf = { base: ptr::null(), len: 0 as libc::size_t }; let out_buf_ptr = ptr::addr_of(out_buf); - io::println(#fmt("ll::buf_init - input %u len %u out_buf: %u", + log(debug, #fmt("ll::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); //let result = rustrt::rust_uv_buf_init_2(input, len); - io::println("after rust_uv_buf_init"); + 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); - io::println(#fmt("ll::buf_init - result %u len %u", + log(debug, #fmt("ll::buf_init - result %u len %u", res_base as uint, res_len as uint)); ret out_buf; @@ -653,7 +653,7 @@ unsafe fn ip4_addr(ip: str, port: int) addr_vec += [0u8]; // add null terminator let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); let ip_back = str::from_bytes(addr_vec); - io::println(#fmt("vec val: '%s' length: %u", + log(debug, #fmt("vec val: '%s' length: %u", ip_back, vec::len(addr_vec))); ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port as libc::c_int);