rust/src/libstd/uv_ll.rs
Alex Crichton 2df07ddc25 Fix implicit leaks of imports throughout libraries
Also touch up use of 'pub' and move some tests around so the tested functions
don't have to be 'pub'
2013-02-28 18:00:34 -05:00

1899 lines
68 KiB
Rust

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
* Low-level bindings to the libuv library.
*
* This module contains a set of direct, 'bare-metal' wrappers around
* the libuv C-API.
*
* Also contained herein are a set of rust records that map, in
* approximate memory-size, to the libuv data structures. The record
* implementations are adjusted, per-platform, to match their respective
* representations.
*
* There are also a collection of helper functions to ease interacting
* with the low-level API (such as a function to return the latest
* libuv error as a rust-formatted string).
*
* As new functionality, existant in uv.h, is added to the rust stdlib,
* the mappings should be added in this module.
*
* This module's implementation will hopefully be, eventually, replaced
* with per-platform, generated source files from rust-bindgen.
*/
#[allow(non_camel_case_types)]; // C types
use core::libc::size_t;
use core::libc;
use core::prelude::*;
use core::ptr::to_unsafe_ptr;
use core::ptr;
use core::str;
use core::vec;
use core::comm::{stream, Chan, SharedChan, Port};
// libuv struct mappings
pub struct uv_ip4_addr {
ip: ~[u8],
port: int,
}
pub type uv_ip6_addr = uv_ip4_addr;
pub enum uv_handle_type {
UNKNOWN_HANDLE = 0,
UV_TCP,
UV_UDP,
UV_NAMED_PIPE,
UV_TTY,
UV_FILE,
UV_TIMER,
UV_PREPARE,
UV_CHECK,
UV_IDLE,
UV_ASYNC,
UV_ARES_TASK,
UV_ARES_EVENT,
UV_PROCESS,
UV_FS_EVENT
}
pub type handle_type = libc::c_uint;
pub struct uv_handle_fields {
loop_handle: *libc::c_void,
type_: handle_type,
close_cb: *u8,
data: *libc::c_void,
}
// unix size: 8
pub struct uv_err_t {
code: libc::c_int,
sys_errno_: libc::c_int
}
// don't create one of these directly. instead,
// count on it appearing in libuv callbacks or embedded
// in other types as a pointer to be used in other
// operations (so mostly treat it as opaque, once you
// have it in this form..)
pub struct uv_stream_t {
fields: uv_handle_fields,
}
// 64bit unix size: 216
#[cfg(target_os="macos")]
pub struct uv_tcp_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8, a11: *u8,
a12: *u8, a13: *u8, a14: *u8, a15: *u8,
a16: *u8, a17: *u8, a18: *u8, a19: *u8,
a20: *u8, a21: *u8, a22: *u8,
a23: uv_tcp_t_osx_riders
}
#[cfg(target_arch="x86_64")]
pub struct uv_tcp_t_osx_riders {
a23: *u8,
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct uv_tcp_t_osx_riders {
a23: *u8,
a24: *u8, a25: *u8,
}
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
#[cfg(target_os="android")]
pub struct uv_tcp_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8, a11: *u8,
a12: *u8, a13: *u8, a14: *u8, a15: *u8,
a16: *u8, a17: *u8, a18: *u8, a19: *u8,
a20: *u8, a21: *u8,
a22: uv_tcp_t_32bit_unix_riders,
}
// 32bit unix size: 328 (164)
#[cfg(target_arch="x86_64")]
pub struct uv_tcp_t_32bit_unix_riders {
a29: *u8,
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct uv_tcp_t_32bit_unix_riders {
a29: *u8, a30: *u8, a31: *u8,
}
// 32bit win32 size: 240 (120)
#[cfg(windows)]
pub struct uv_tcp_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8, a11: *u8,
a12: *u8, a13: *u8, a14: *u8, a15: *u8,
a16: *u8, a17: *u8, a18: *u8, a19: *u8,
a20: *u8, a21: *u8, a22: *u8, a23: *u8,
a24: *u8, a25: *u8,
}
// unix size: 64
#[cfg(unix)]
pub struct uv_connect_t {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8
}
// win32 size: 88 (44)
#[cfg(windows)]
pub struct uv_connect_t {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8,
}
// unix size: 16
pub struct uv_buf_t {
base: *u8,
len: libc::size_t,
}
// no gen stub method.. should create
// it via uv::direct::buf_init()
// unix size: 160
#[cfg(unix)]
pub struct uv_write_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8, a11: *u8,
a12: *u8,
a14: uv_write_t_32bit_unix_riders,
}
#[cfg(target_arch="x86_64")]
pub struct uv_write_t_32bit_unix_riders {
a13: *u8, a14: *u8, a15: *u8
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct uv_write_t_32bit_unix_riders {
a13: *u8, a14: *u8, a15: *u8,
a16: *u8,
}
// win32 size: 136 (68)
#[cfg(windows)]
pub struct uv_write_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8, a11: *u8,
a12: *u8,
}
// 64bit unix size: 96
// 32bit unix size: 152 (76)
#[cfg(unix)]
pub struct uv_async_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8,
a07: uv_async_t_32bit_unix_riders,
}
#[cfg(target_arch="x86_64")]
pub struct uv_async_t_32bit_unix_riders {
a10: *u8,
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct uv_async_t_32bit_unix_riders {
a10: *u8,
}
// win32 size 132 (68)
#[cfg(windows)]
pub struct uv_async_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8, a11: *u8,
a12: *u8,
}
// 64bit unix size: 120
// 32bit unix size: 84
#[cfg(unix)]
pub struct uv_timer_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8,
a11: uv_timer_t_32bit_unix_riders,
}
#[cfg(target_arch="x86_64")]
pub struct uv_timer_t_32bit_unix_riders {
a10: *u8,
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct uv_timer_t_32bit_unix_riders {
a10: *u8, a11: *u8, a12: *u8
}
// win32 size: 64
#[cfg(windows)]
pub struct uv_timer_t {
fields: uv_handle_fields,
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
a08: *u8, a09: *u8, a10: *u8, a11: *u8,
}
// unix size: 16
pub struct sockaddr_in {
sin_family: u16,
sin_port: u16,
sin_addr: u32, // in_addr: this is an opaque, per-platform struct
sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8),
}
// unix size: 28 .. FIXME #1645
// stuck with 32 becuse of rust padding structs?
#[cfg(target_arch="x86_64")]
pub struct sockaddr_in6 {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct sockaddr_in6 {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
a4: *u8, a5: *u8,
a6: *u8, a7: *u8,
}
// unix size: 28 .. FIXME #1645
// stuck with 32 becuse of rust padding structs?
pub type addr_in = addr_in_impl::addr_in;
#[cfg(unix)]
pub mod addr_in_impl {
#[cfg(target_arch="x86_64")]
pub struct addr_in {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct addr_in {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
a4: *u8, a5: *u8,
a6: *u8, a7: *u8,
}
}
#[cfg(windows)]
pub mod addr_in_impl {
pub struct addr_in {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
}
}
// unix size: 48, 32bit: 32
pub type addrinfo = addrinfo_impl::addrinfo;
#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub mod addrinfo_impl {
#[cfg(target_arch="x86_64")]
pub struct addrinfo {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8,
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub struct addrinfo {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8,
}
}
#[cfg(target_os="macos")]
#[cfg(target_os="freebsd")]
pub mod addrinfo_impl {
pub struct addrinfo {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8,
}
}
#[cfg(windows)]
pub mod addrinfo_impl {
pub struct addrinfo {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8,
}
}
// unix size: 72
pub struct uv_getaddrinfo_t {
a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8,
a06: *u8, a07: *u8, a08: *u8, a09: *u8,
a10: *u8, a11: *u8, a12: *u8, a13: *u8, a14: *u8, a15: *u8
}
pub mod uv_ll_struct_stubgen {
use uv_ll::{
uv_async_t,
uv_connect_t,
uv_getaddrinfo_t,
uv_handle_fields,
uv_tcp_t,
uv_timer_t,
uv_write_t,
};
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
use uv_ll::{
uv_async_t_32bit_unix_riders,
uv_tcp_t_32bit_unix_riders,
uv_timer_t_32bit_unix_riders,
uv_write_t_32bit_unix_riders,
};
use core::ptr;
pub fn gen_stub_uv_tcp_t() -> uv_tcp_t {
return gen_stub_os();
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
pub fn gen_stub_os() -> uv_tcp_t {
return gen_stub_arch();
#[cfg(target_arch="x86_64")]
pub fn gen_stub_arch() -> uv_tcp_t {
uv_tcp_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
a15: 0 as *u8,
a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
a19: 0 as *u8,
a20: 0 as *u8, a21: 0 as *u8,
a22: uv_tcp_t_32bit_unix_riders { a29: 0 as *u8 },
}
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_tcp_t {
uv_tcp_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
a15: 0 as *u8,
a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
a19: 0 as *u8,
a20: 0 as *u8, a21: 0 as *u8,
a22: uv_tcp_t_32bit_unix_riders {
a29: 0 as *u8, a30: 0 as *u8, a31: 0 as *u8,
},
}
}
}
#[cfg(windows)]
pub fn gen_stub_os() -> uv_tcp_t {
uv_tcp_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
a15: 0 as *u8,
a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
a19: 0 as *u8,
a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
a23: 0 as *u8,
a24: 0 as *u8, a25: 0 as *u8,
}
}
#[cfg(target_os = "macos")]
pub fn gen_stub_os() -> uv_tcp_t {
use super::uv_tcp_t_osx_riders;
return gen_stub_arch();
#[cfg(target_arch = "x86_64")]
fn gen_stub_arch() -> uv_tcp_t {
uv_tcp_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
a15: 0 as *u8,
a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
a19: 0 as *u8,
a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
a23: uv_tcp_t_osx_riders {
a23: 0 as *u8,
}
}
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "arm")]
fn gen_stub_arch() -> uv_tcp_t {
uv_tcp_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
a15: 0 as *u8,
a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
a19: 0 as *u8,
a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
a23: uv_tcp_t_osx_riders {
a23: 0 as *u8,
a24: 0 as *u8, a25: 0 as *u8,
}
}
}
}
}
#[cfg(unix)]
pub fn gen_stub_uv_connect_t() -> uv_connect_t {
uv_connect_t {
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8
}
}
#[cfg(windows)]
pub fn gen_stub_uv_connect_t() -> uv_connect_t {
uv_connect_t {
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
}
}
#[cfg(unix)]
pub fn gen_stub_uv_async_t() -> uv_async_t {
return gen_stub_arch();
#[cfg(target_arch = "x86_64")]
pub fn gen_stub_arch() -> uv_async_t {
uv_async_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: uv_async_t_32bit_unix_riders { a10: 0 as *u8 },
}
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_async_t {
uv_async_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: uv_async_t_32bit_unix_riders {
a10: 0 as *u8,
}
}
}
}
#[cfg(windows)]
pub fn gen_stub_uv_async_t() -> uv_async_t {
uv_async_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8,
}
}
#[cfg(unix)]
pub fn gen_stub_uv_timer_t() -> uv_timer_t {
return gen_stub_arch();
#[cfg(target_arch = "x86_64")]
pub fn gen_stub_arch() -> uv_timer_t {
uv_timer_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8,
a11: uv_timer_t_32bit_unix_riders {
a10: 0 as *u8
},
}
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_timer_t {
uv_timer_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8,
a11: uv_timer_t_32bit_unix_riders {
a10: 0 as *u8, a11: 0 as *u8,
a12: 0 as *u8,
},
}
}
}
#[cfg(windows)]
pub fn gen_stub_uv_timer_t() -> uv_timer_t {
uv_timer_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
}
}
#[cfg(unix)]
pub fn gen_stub_uv_write_t() -> uv_write_t {
return gen_stub_arch();
#[cfg(target_arch="x86_64")]
pub fn gen_stub_arch() -> uv_write_t {
uv_write_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8,
a14: uv_write_t_32bit_unix_riders { a13: 0 as *u8,
a14: 0 as *u8,
a15: 0 as *u8},
}
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_write_t {
uv_write_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8,
a14: uv_write_t_32bit_unix_riders {
a13: 0 as *u8,
a14: 0 as *u8,
a15: 0 as *u8,
a16: 0 as *u8,
}
}
}
}
#[cfg(windows)]
pub fn gen_stub_uv_write_t() -> uv_write_t {
uv_write_t {
fields: uv_handle_fields {
loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
data: ptr::null(),
},
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
a11: 0 as *u8,
a12: 0 as *u8
}
}
pub fn gen_stub_uv_getaddrinfo_t() -> uv_getaddrinfo_t {
uv_getaddrinfo_t {
a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8,
a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8, a07: 0 as *u8,
a08: 0 as *u8, a09: 0 as *u8,
a10: 1 as *u8, a11: 1 as *u8, a12: 1 as *u8, a13: 1 as *u8,
a14: 1 as *u8, a15: 1 as *u8
}
}
}
#[nolink]
extern mod rustrt {
// libuv public API
unsafe fn rust_uv_loop_new() -> *libc::c_void;
unsafe fn rust_uv_loop_delete(lp: *libc::c_void);
unsafe fn rust_uv_run(loop_handle: *libc::c_void);
unsafe fn rust_uv_close(handle: *libc::c_void, cb: *u8);
unsafe fn rust_uv_walk(loop_handle: *libc::c_void, cb: *u8,
arg: *libc::c_void);
unsafe fn rust_uv_async_send(handle: *uv_async_t);
unsafe fn rust_uv_async_init(loop_handle: *libc::c_void,
async_handle: *uv_async_t,
cb: *u8) -> libc::c_int;
unsafe fn rust_uv_tcp_init(
loop_handle: *libc::c_void,
handle_ptr: *uv_tcp_t) -> libc::c_int;
// FIXME ref #2604 .. ?
unsafe fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8,
len: libc::size_t);
unsafe fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t;
// FIXME ref #2064
unsafe fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char;
// FIXME ref #2064
unsafe fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char;
unsafe fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int)
-> sockaddr_in;
unsafe fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int)
-> sockaddr_in6;
unsafe fn rust_uv_ip4_name(src: *sockaddr_in,
dst: *u8,
size: libc::size_t)
-> libc::c_int;
unsafe fn rust_uv_ip6_name(src: *sockaddr_in6,
dst: *u8,
size: libc::size_t)
-> libc::c_int;
unsafe fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint;
unsafe fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint;
// FIXME ref #2064
unsafe fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
++after_cb: *u8,
++addr: *sockaddr_in) -> libc::c_int;
// FIXME ref #2064
unsafe fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t,
++addr: *sockaddr_in) -> libc::c_int;
// FIXME ref #2064
unsafe fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
++after_cb: *u8,
++addr: *sockaddr_in6) -> libc::c_int;
// FIXME ref #2064
unsafe fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t,
++addr: *sockaddr_in6) -> libc::c_int;
unsafe fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
++name: *sockaddr_in) -> libc::c_int;
unsafe fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
++name: *sockaddr_in6) ->libc::c_int;
unsafe fn rust_uv_listen(stream: *libc::c_void,
backlog: libc::c_int,
cb: *u8) -> libc::c_int;
unsafe fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void)
-> libc::c_int;
unsafe fn rust_uv_write(req: *libc::c_void,
stream: *libc::c_void,
++buf_in: *uv_buf_t,
buf_cnt: libc::c_int,
cb: *u8)
-> libc::c_int;
unsafe fn rust_uv_read_start(stream: *libc::c_void,
on_alloc: *u8,
on_read: *u8)
-> libc::c_int;
unsafe fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int;
unsafe fn rust_uv_timer_init(loop_handle: *libc::c_void,
timer_handle: *uv_timer_t)
-> libc::c_int;
unsafe fn rust_uv_timer_start(
timer_handle: *uv_timer_t,
cb: *u8,
timeout: libc::c_uint,
repeat: libc::c_uint) -> libc::c_int;
unsafe fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int;
unsafe fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void,
handle: *uv_getaddrinfo_t,
cb: *u8,
node_name_ptr: *u8,
service_name_ptr: *u8,
// should probably only pass ptr::null()
hints: *addrinfo)
-> libc::c_int;
unsafe fn rust_uv_freeaddrinfo(res: *addrinfo);
// data accessors/helpers for rust-mapped uv structs
unsafe fn rust_uv_helper_get_INADDR_NONE() -> u32;
unsafe fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool;
unsafe fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool;
unsafe fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo;
unsafe fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo)
-> *sockaddr_in;
unsafe fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo)
-> *sockaddr_in6;
unsafe fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8;
unsafe fn rust_uv_free_base_of_buf(++buf: uv_buf_t);
unsafe fn rust_uv_get_stream_handle_from_connect_req(
connect_req: *uv_connect_t)
-> *uv_stream_t;
unsafe fn rust_uv_get_stream_handle_from_write_req(
write_req: *uv_write_t)
-> *uv_stream_t;
unsafe fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void)
-> *libc::c_void;
unsafe fn rust_uv_get_data_for_uv_loop(loop_ptr: *libc::c_void)
-> *libc::c_void;
unsafe fn rust_uv_set_data_for_uv_loop(loop_ptr: *libc::c_void,
data: *libc::c_void);
unsafe fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void)
-> *libc::c_void;
unsafe fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void,
data: *libc::c_void);
unsafe fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void;
unsafe fn rust_uv_set_data_for_req(req: *libc::c_void,
data: *libc::c_void);
unsafe fn rust_uv_get_base_from_buf(++buf: uv_buf_t) -> *u8;
unsafe fn rust_uv_get_len_from_buf(++buf: uv_buf_t) -> libc::size_t;
// sizeof testing helpers
unsafe fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_uv_write_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_uv_err_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint;
unsafe fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint;
unsafe fn rust_uv_helper_uv_async_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint;
unsafe fn rust_uv_helper_addrinfo_size() -> libc::c_uint;
unsafe fn rust_uv_helper_addr_in_size() -> libc::c_uint;
}
pub unsafe fn loop_new() -> *libc::c_void {
return rustrt::rust_uv_loop_new();
}
pub unsafe fn loop_delete(loop_handle: *libc::c_void) {
rustrt::rust_uv_loop_delete(loop_handle);
}
pub unsafe fn run(loop_handle: *libc::c_void) {
rustrt::rust_uv_run(loop_handle);
}
pub unsafe fn close<T>(handle: *T, cb: *u8) {
rustrt::rust_uv_close(handle as *libc::c_void, cb);
}
pub unsafe fn walk(loop_handle: *libc::c_void, cb: *u8, arg: *libc::c_void) {
rustrt::rust_uv_walk(loop_handle, cb, arg);
}
pub unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t)
-> libc::c_int {
return rustrt::rust_uv_tcp_init(loop_handle, handle);
}
// FIXME ref #2064
pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in,
after_connect_cb: *u8)
-> libc::c_int {
log(debug, fmt!("b4 foreign tcp_connect--addr port: %u cb: %u",
(*addr_ptr).sin_port as uint, after_connect_cb as uint));
return rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr,
after_connect_cb, addr_ptr);
}
// FIXME ref #2064
pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in6,
after_connect_cb: *u8)
-> libc::c_int {
return rustrt::rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr,
after_connect_cb, addr_ptr);
}
// FIXME ref #2064
pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in) -> libc::c_int {
return rustrt::rust_uv_tcp_bind(tcp_server_ptr,
addr_ptr);
}
// FIXME ref #2064
pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t,
addr_ptr: *sockaddr_in6) -> libc::c_int {
return rustrt::rust_uv_tcp_bind6(tcp_server_ptr,
addr_ptr);
}
pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
name: *sockaddr_in) -> libc::c_int {
return rustrt::rust_uv_tcp_getpeername(tcp_handle_ptr, name);
}
pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
name: *sockaddr_in6) ->libc::c_int {
return rustrt::rust_uv_tcp_getpeername6(tcp_handle_ptr, name);
}
pub unsafe fn listen<T>(stream: *T, backlog: libc::c_int,
cb: *u8) -> libc::c_int {
return rustrt::rust_uv_listen(stream as *libc::c_void, backlog, cb);
}
pub unsafe fn accept(server: *libc::c_void, client: *libc::c_void)
-> libc::c_int {
return rustrt::rust_uv_accept(server as *libc::c_void,
client as *libc::c_void);
}
pub unsafe fn write<T>(req: *uv_write_t, stream: *T,
buf_in: *~[uv_buf_t], cb: *u8) -> libc::c_int {
let buf_ptr = vec::raw::to_ptr(*buf_in);
let buf_cnt = vec::len(*buf_in) as i32;
return rustrt::rust_uv_write(req as *libc::c_void,
stream as *libc::c_void,
buf_ptr, buf_cnt, cb);
}
pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8,
on_read: *u8) -> libc::c_int {
return rustrt::rust_uv_read_start(stream as *libc::c_void,
on_alloc, on_read);
}
pub unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int {
return rustrt::rust_uv_read_stop(stream as *libc::c_void);
}
pub unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t {
return rustrt::rust_uv_last_error(loop_handle);
}
pub unsafe fn strerror(err: *uv_err_t) -> *libc::c_char {
return rustrt::rust_uv_strerror(err);
}
pub unsafe fn err_name(err: *uv_err_t) -> *libc::c_char {
return rustrt::rust_uv_err_name(err);
}
pub unsafe fn async_init(loop_handle: *libc::c_void,
async_handle: *uv_async_t,
cb: *u8) -> libc::c_int {
return rustrt::rust_uv_async_init(loop_handle,
async_handle,
cb);
}
pub unsafe fn async_send(async_handle: *uv_async_t) {
return rustrt::rust_uv_async_send(async_handle);
}
pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
let out_buf = uv_buf_t { base: ptr::null(), len: 0 as libc::size_t };
let out_buf_ptr = ptr::addr_of(&out_buf);
log(debug, fmt!("buf_init - input %u len %u out_buf: %u",
input as uint,
len as uint,
out_buf_ptr as uint));
// yuck :/
rustrt::rust_uv_buf_init(out_buf_ptr, input, len as size_t);
//let result = rustrt::rust_uv_buf_init_2(input, len as size_t);
log(debug, ~"after rust_uv_buf_init");
let res_base = get_base_from_buf(out_buf);
let res_len = get_len_from_buf(out_buf);
//let res_base = get_base_from_buf(result);
log(debug, fmt!("buf_init - result %u len %u",
res_base as uint,
res_len as uint));
return out_buf;
//return result;
}
pub unsafe fn ip4_addr(ip: &str, port: int)
-> sockaddr_in {
do str::as_c_str(ip) |ip_buf| {
rustrt::rust_uv_ip4_addr(ip_buf as *u8,
port as libc::c_int)
}
}
pub unsafe fn ip6_addr(ip: &str, port: int)
-> sockaddr_in6 {
do str::as_c_str(ip) |ip_buf| {
rustrt::rust_uv_ip6_addr(ip_buf as *u8,
port as libc::c_int)
}
}
pub unsafe fn ip4_name(src: &sockaddr_in) -> ~str {
// ipv4 addr max size: 15 + 1 trailing null byte
let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8];
do vec::as_imm_buf(dst) |dst_buf, size| {
rustrt::rust_uv_ip4_name(to_unsafe_ptr(src),
dst_buf, size as libc::size_t);
// seems that checking the result of uv_ip4_name
// doesn't work too well..
// you're stuck looking at the value of dst_buf
// to see if it is the string representation of
// INADDR_NONE (0xffffffff or 255.255.255.255 on
// many platforms)
str::raw::from_buf(dst_buf)
}
}
pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str {
// ipv6 addr max size: 45 + 1 trailing null byte
let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
0u8,0u8,0u8,0u8,0u8,0u8];
do vec::as_imm_buf(dst) |dst_buf, size| {
let src_unsafe_ptr = to_unsafe_ptr(src);
log(debug, fmt!("val of src *sockaddr_in6: %? sockaddr_in6: %?",
src_unsafe_ptr, src));
let result = rustrt::rust_uv_ip6_name(src_unsafe_ptr,
dst_buf, size as libc::size_t);
match result {
0i32 => str::raw::from_buf(dst_buf),
_ => ~""
}
}
}
pub unsafe fn ip4_port(src: &sockaddr_in) -> uint {
rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint
}
pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint {
rustrt::rust_uv_ip6_port(to_unsafe_ptr(src)) as uint
}
pub unsafe fn timer_init(loop_ptr: *libc::c_void,
timer_ptr: *uv_timer_t) -> libc::c_int {
return rustrt::rust_uv_timer_init(loop_ptr, timer_ptr);
}
pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint,
repeat: uint) -> libc::c_int {
return rustrt::rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint,
repeat as libc::c_uint);
}
pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int {
return rustrt::rust_uv_timer_stop(timer_ptr);
}
pub unsafe fn getaddrinfo(loop_ptr: *libc::c_void,
handle: *uv_getaddrinfo_t,
cb: *u8,
node_name_ptr: *u8,
service_name_ptr: *u8,
hints: *addrinfo) -> libc::c_int {
rustrt::rust_uv_getaddrinfo(loop_ptr,
handle,
cb,
node_name_ptr,
service_name_ptr,
hints)
}
pub unsafe fn freeaddrinfo(res: *addrinfo) {
rustrt::rust_uv_freeaddrinfo(res);
}
// libuv struct initializers
pub unsafe fn tcp_t() -> uv_tcp_t {
return uv_ll_struct_stubgen::gen_stub_uv_tcp_t();
}
pub unsafe fn connect_t() -> uv_connect_t {
return uv_ll_struct_stubgen::gen_stub_uv_connect_t();
}
pub unsafe fn write_t() -> uv_write_t {
return uv_ll_struct_stubgen::gen_stub_uv_write_t();
}
pub unsafe fn async_t() -> uv_async_t {
return uv_ll_struct_stubgen::gen_stub_uv_async_t();
}
pub unsafe fn timer_t() -> uv_timer_t {
return uv_ll_struct_stubgen::gen_stub_uv_timer_t();
}
pub unsafe fn getaddrinfo_t() -> uv_getaddrinfo_t {
return uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t();
}
// data access helpers
pub unsafe fn get_loop_for_uv_handle<T>(handle: *T)
-> *libc::c_void {
return rustrt::rust_uv_get_loop_for_uv_handle(handle as *libc::c_void);
}
pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t)
-> *uv_stream_t {
return rustrt::rust_uv_get_stream_handle_from_connect_req(
connect);
}
pub unsafe fn get_stream_handle_from_write_req(
write_req: *uv_write_t)
-> *uv_stream_t {
return rustrt::rust_uv_get_stream_handle_from_write_req(
write_req);
}
pub unsafe fn get_data_for_uv_loop(loop_ptr: *libc::c_void) -> *libc::c_void {
rustrt::rust_uv_get_data_for_uv_loop(loop_ptr)
}
pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void,
data: *libc::c_void) {
rustrt::rust_uv_set_data_for_uv_loop(loop_ptr, data);
}
pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *libc::c_void {
return rustrt::rust_uv_get_data_for_uv_handle(handle as *libc::c_void);
}
pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T,
data: *U) {
rustrt::rust_uv_set_data_for_uv_handle(handle as *libc::c_void,
data as *libc::c_void);
}
pub unsafe fn get_data_for_req<T>(req: *T) -> *libc::c_void {
return rustrt::rust_uv_get_data_for_req(req as *libc::c_void);
}
pub unsafe fn set_data_for_req<T, U>(req: *T,
data: *U) {
rustrt::rust_uv_set_data_for_req(req as *libc::c_void,
data as *libc::c_void);
}
pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
return rustrt::rust_uv_get_base_from_buf(buf);
}
pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t {
return rustrt::rust_uv_get_len_from_buf(buf);
}
pub unsafe fn malloc_buf_base_of(suggested_size: libc::size_t)
-> *u8 {
return rustrt::rust_uv_malloc_buf_base_of(suggested_size);
}
pub unsafe fn free_base_of_buf(buf: uv_buf_t) {
rustrt::rust_uv_free_base_of_buf(buf);
}
pub unsafe fn get_last_err_info(uv_loop: *libc::c_void) -> ~str {
let err = last_error(uv_loop);
let err_ptr = ptr::addr_of(&err);
let err_name = str::raw::from_c_str(err_name(err_ptr));
let err_msg = str::raw::from_c_str(strerror(err_ptr));
return fmt!("LIBUV ERROR: name: %s msg: %s",
err_name, err_msg);
}
pub unsafe fn get_last_err_data(uv_loop: *libc::c_void) -> uv_err_data {
let err = last_error(uv_loop);
let err_ptr = ptr::addr_of(&err);
let err_name = str::raw::from_c_str(err_name(err_ptr));
let err_msg = str::raw::from_c_str(strerror(err_ptr));
uv_err_data { err_name: err_name, err_msg: err_msg }
}
pub struct uv_err_data {
err_name: ~str,
err_msg: ~str,
}
pub unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool {
rustrt::rust_uv_is_ipv4_addrinfo(input)
}
pub unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool {
rustrt::rust_uv_is_ipv6_addrinfo(input)
}
pub unsafe fn get_INADDR_NONE() -> u32 {
rustrt::rust_uv_helper_get_INADDR_NONE()
}
pub unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo {
rustrt::rust_uv_get_next_addrinfo(input)
}
pub unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in {
rustrt::rust_uv_addrinfo_as_sockaddr_in(input)
}
pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 {
rustrt::rust_uv_addrinfo_as_sockaddr_in6(input)
}
//#[cfg(test)]
pub mod test {
use core::prelude::*;
use uv_ll::*;
use core::comm::{SharedChan, stream};
use core::libc;
use core::ptr;
use core::str;
use core::sys;
use core::task;
use core::vec;
enum tcp_read_data {
tcp_read_eof,
tcp_read_more(~[u8]),
tcp_read_error
}
struct request_wrapper {
write_req: *uv_write_t,
req_buf: *~[uv_buf_t],
read_chan: SharedChan<~str>,
}
extern fn after_close_cb(handle: *libc::c_void) {
log(debug, fmt!("after uv_close! handle ptr: %?",
handle));
}
extern fn on_alloc_cb(handle: *libc::c_void,
suggested_size: libc::size_t)
-> uv_buf_t {
unsafe {
log(debug, ~"on_alloc_cb!");
let char_ptr = malloc_buf_base_of(suggested_size);
log(debug, fmt!("on_alloc_cb h: %? char_ptr: %u sugsize: %u",
handle,
char_ptr as uint,
suggested_size as uint));
return buf_init(char_ptr, suggested_size as uint);
}
}
extern fn on_read_cb(stream: *uv_stream_t,
nread: libc::ssize_t,
++buf: uv_buf_t) {
unsafe {
let nread = nread as int;
log(debug, fmt!("CLIENT entering on_read_cb nred: %d",
nread));
if (nread > 0) {
// we have data
log(debug, fmt!("CLIENT read: data! nread: %d", nread));
read_stop(stream);
let client_data =
get_data_for_uv_handle(stream as *libc::c_void)
as *request_wrapper;
let buf_base = get_base_from_buf(buf);
let bytes = vec::from_buf(buf_base, nread as uint);
let read_chan = (*client_data).read_chan.clone();
let msg_from_server = str::from_bytes(bytes);
read_chan.send(msg_from_server);
close(stream as *libc::c_void, after_close_cb)
}
else if (nread == -1) {
// err .. possibly EOF
log(debug, ~"read: eof!");
}
else {
// nread == 0 .. do nothing, just free buf as below
log(debug, ~"read: do nothing!");
}
// when we're done
free_base_of_buf(buf);
log(debug, ~"CLIENT exiting on_read_cb");
}
}
extern fn on_write_complete_cb(write_req: *uv_write_t,
status: libc::c_int) {
unsafe {
log(debug,
fmt!("CLIENT beginning on_write_complete_cb status: %d",
status as int));
let stream = get_stream_handle_from_write_req(write_req);
log(debug,
fmt!("CLIENT on_write_complete_cb: tcp:%d write_handle:%d",
stream as int, write_req as int));
let result = read_start(stream, on_alloc_cb, on_read_cb);
log(debug,
fmt!("CLIENT ending on_write_complete_cb .. status: %d",
result as int));
}
}
extern fn on_connect_cb(connect_req_ptr: *uv_connect_t,
status: libc::c_int) {
unsafe {
log(debug, fmt!("beginning on_connect_cb .. status: %d",
status as int));
let stream =
get_stream_handle_from_connect_req(connect_req_ptr);
if (status == 0i32) {
log(debug, ~"on_connect_cb: in status=0 if..");
let client_data = get_data_for_req(
connect_req_ptr as *libc::c_void)
as *request_wrapper;
let write_handle = (*client_data).write_req;
log(debug, fmt!("on_connect_cb: tcp: %d write_hdl: %d",
stream as int, write_handle as int));
let write_result = write(write_handle,
stream as *libc::c_void,
(*client_data).req_buf,
on_write_complete_cb);
log(debug, fmt!("on_connect_cb: write() status: %d",
write_result as int));
}
else {
let test_loop = get_loop_for_uv_handle(
stream as *libc::c_void);
let err_msg = get_last_err_info(test_loop);
log(debug, err_msg);
assert false;
}
log(debug, ~"finishing on_connect_cb");
}
}
fn impl_uv_tcp_request(ip: &str, port: int, req_str: &str,
client_chan: SharedChan<~str>) {
unsafe {
let test_loop = loop_new();
let tcp_handle = tcp_t();
let tcp_handle_ptr = ptr::addr_of(&tcp_handle);
let connect_handle = connect_t();
let connect_req_ptr = ptr::addr_of(&connect_handle);
// this is the persistent payload of data that we
// need to pass around to get this example to work.
// In C, this would be a malloc'd or stack-allocated
// struct that we'd cast to a void* and store as the
// data field in our uv_connect_t struct
let req_str_bytes = str::to_bytes(req_str);
let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes);
log(debug, fmt!("req_msg ptr: %u", req_msg_ptr as uint));
let req_msg = ~[
buf_init(req_msg_ptr, vec::len(req_str_bytes))
];
// this is the enclosing record, we'll pass a ptr to
// this to C..
let write_handle = write_t();
let write_handle_ptr = ptr::addr_of(&write_handle);
log(debug, fmt!("tcp req: tcp stream: %d write_handle: %d",
tcp_handle_ptr as int,
write_handle_ptr as int));
let client_data = request_wrapper {
write_req: write_handle_ptr,
req_buf: ptr::addr_of(&req_msg),
read_chan: client_chan
};
let tcp_init_result = tcp_init(
test_loop as *libc::c_void, tcp_handle_ptr);
if (tcp_init_result == 0i32) {
log(debug, ~"sucessful tcp_init_result");
log(debug, ~"building addr...");
let addr = ip4_addr(ip, port);
// FIXME ref #2064
let addr_ptr = ptr::addr_of(&addr);
log(debug, fmt!("after build addr in rust. port: %u",
addr.sin_port as uint));
// this should set up the connection request..
log(debug, fmt!("b4 call tcp_connect connect cb: %u ",
on_connect_cb as uint));
let tcp_connect_result = tcp_connect(
connect_req_ptr, tcp_handle_ptr,
addr_ptr, on_connect_cb);
if (tcp_connect_result == 0i32) {
// not set the data on the connect_req
// until its initialized
set_data_for_req(
connect_req_ptr as *libc::c_void,
ptr::addr_of(&client_data) as *libc::c_void);
set_data_for_uv_handle(
tcp_handle_ptr as *libc::c_void,
ptr::addr_of(&client_data) as *libc::c_void);
log(debug, ~"before run tcp req loop");
run(test_loop);
log(debug, ~"after run tcp req loop");
}
else {
log(debug, ~"tcp_connect() failure");
assert false;
}
}
else {
log(debug, ~"tcp_init() failure");
assert false;
}
loop_delete(test_loop);
}
}
extern fn server_after_close_cb(handle: *libc::c_void) {
unsafe {
log(debug, fmt!("SERVER server stream closed, should exit. h: %?",
handle));
}
}
extern fn client_stream_after_close_cb(handle: *libc::c_void) {
unsafe {
log(debug,
~"SERVER: closed client stream, now closing server stream");
let client_data = get_data_for_uv_handle(
handle) as
*tcp_server_data;
close((*client_data).server as *libc::c_void,
server_after_close_cb);
}
}
extern fn after_server_resp_write(req: *uv_write_t) {
unsafe {
let client_stream_ptr =
get_stream_handle_from_write_req(req);
log(debug, ~"SERVER: resp sent... closing client stream");
close(client_stream_ptr as *libc::c_void,
client_stream_after_close_cb)
}
}
extern fn on_server_read_cb(client_stream_ptr: *uv_stream_t,
nread: libc::ssize_t,
++buf: uv_buf_t) {
unsafe {
let nread = nread as int;
if (nread > 0) {
// we have data
log(debug, fmt!("SERVER read: data! nread: %d", nread));
// pull out the contents of the write from the client
let buf_base = get_base_from_buf(buf);
let buf_len = get_len_from_buf(buf) as uint;
log(debug, fmt!("SERVER buf base: %u, len: %u, nread: %d",
buf_base as uint,
buf_len as uint,
nread));
let bytes = vec::from_buf(buf_base, nread as uint);
let request_str = str::from_bytes(bytes);
let client_data = get_data_for_uv_handle(
client_stream_ptr as *libc::c_void) as *tcp_server_data;
let server_kill_msg = (*client_data).server_kill_msg;
let write_req = (*client_data).server_write_req;
if str::contains(request_str, server_kill_msg) {
log(debug, ~"SERVER: client req contains kill_msg!");
log(debug, ~"SERVER: sending response to client");
read_stop(client_stream_ptr);
let server_chan = (*client_data).server_chan.clone();
server_chan.send(request_str);
let write_result = write(
write_req,
client_stream_ptr as *libc::c_void,
(*client_data).server_resp_buf,
after_server_resp_write);
log(debug, fmt!("SERVER: resp write result: %d",
write_result as int));
if (write_result != 0i32) {
log(debug, ~"bad result for server resp write()");
log(debug, get_last_err_info(
get_loop_for_uv_handle(client_stream_ptr
as *libc::c_void)));
assert false;
}
}
else {
log(debug, ~"SERVER: client req !contain kill_msg!");
}
}
else if (nread == -1) {
// err .. possibly EOF
log(debug, ~"read: eof!");
}
else {
// nread == 0 .. do nothing, just free buf as below
log(debug, ~"read: do nothing!");
}
// when we're done
free_base_of_buf(buf);
log(debug, ~"SERVER exiting on_read_cb");
}
}
extern fn server_connection_cb(server_stream_ptr:
*uv_stream_t,
status: libc::c_int) {
unsafe {
log(debug, ~"client connecting!");
let test_loop = get_loop_for_uv_handle(
server_stream_ptr as *libc::c_void);
if status != 0i32 {
let err_msg = get_last_err_info(test_loop);
log(debug, fmt!("server_connect_cb: non-zero status: %?",
err_msg));
return;
}
let server_data = get_data_for_uv_handle(
server_stream_ptr as *libc::c_void) as *tcp_server_data;
let client_stream_ptr = (*server_data).client;
let client_init_result = tcp_init(test_loop,
client_stream_ptr);
set_data_for_uv_handle(
client_stream_ptr as *libc::c_void,
server_data as *libc::c_void);
if (client_init_result == 0i32) {
log(debug, ~"successfully initialized client stream");
let accept_result = accept(server_stream_ptr as
*libc::c_void,
client_stream_ptr as
*libc::c_void);
if (accept_result == 0i32) {
// start reading
let read_result = read_start(
client_stream_ptr as *uv_stream_t,
on_alloc_cb,
on_server_read_cb);
if (read_result == 0i32) {
log(debug, ~"successful server read start");
}
else {
log(debug, fmt!("server_connection_cb: bad read:%d",
read_result as int));
assert false;
}
}
else {
log(debug, fmt!("server_connection_cb: bad accept: %d",
accept_result as int));
assert false;
}
}
else {
log(debug, fmt!("server_connection_cb: bad client init: %d",
client_init_result as int));
assert false;
}
}
}
struct tcp_server_data {
client: *uv_tcp_t,
server: *uv_tcp_t,
server_kill_msg: ~str,
server_resp_buf: *~[uv_buf_t],
server_chan: SharedChan<~str>,
server_write_req: *uv_write_t,
}
struct async_handle_data {
continue_chan: SharedChan<bool>,
}
extern fn async_close_cb(handle: *libc::c_void) {
log(debug, fmt!("SERVER: closing async cb... h: %?",
handle));
}
extern fn continue_async_cb(async_handle: *uv_async_t,
status: libc::c_int) {
unsafe {
// once we're in the body of this callback,
// the tcp server's loop is set up, so we
// can continue on to let the tcp client
// do its thang
let data = get_data_for_uv_handle(
async_handle as *libc::c_void) as *async_handle_data;
let continue_chan = (*data).continue_chan.clone();
let should_continue = status == 0i32;
continue_chan.send(should_continue);
close(async_handle as *libc::c_void, async_close_cb);
}
}
fn impl_uv_tcp_server(server_ip: &str,
server_port: int,
+kill_server_msg: ~str,
+server_resp_msg: ~str,
server_chan: SharedChan<~str>,
continue_chan: SharedChan<bool>) {
unsafe {
let test_loop = loop_new();
let tcp_server = tcp_t();
let tcp_server_ptr = ptr::addr_of(&tcp_server);
let tcp_client = tcp_t();
let tcp_client_ptr = ptr::addr_of(&tcp_client);
let server_write_req = write_t();
let server_write_req_ptr = ptr::addr_of(&server_write_req);
let resp_str_bytes = str::to_bytes(server_resp_msg);
let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes);
log(debug, fmt!("resp_msg ptr: %u", resp_msg_ptr as uint));
let resp_msg = ~[
buf_init(resp_msg_ptr, vec::len(resp_str_bytes))
];
let continue_async_handle = async_t();
let continue_async_handle_ptr =
ptr::addr_of(&continue_async_handle);
let async_data =
async_handle_data { continue_chan: continue_chan };
let async_data_ptr = ptr::addr_of(&async_data);
let server_data = tcp_server_data {
client: tcp_client_ptr,
server: tcp_server_ptr,
server_kill_msg: kill_server_msg,
server_resp_buf: ptr::addr_of(&resp_msg),
server_chan: server_chan,
server_write_req: server_write_req_ptr
};
let server_data_ptr = ptr::addr_of(&server_data);
set_data_for_uv_handle(tcp_server_ptr as *libc::c_void,
server_data_ptr as *libc::c_void);
// uv_tcp_init()
let tcp_init_result = tcp_init(
test_loop as *libc::c_void, tcp_server_ptr);
if (tcp_init_result == 0i32) {
let server_addr = ip4_addr(server_ip, server_port);
// FIXME ref #2064
let server_addr_ptr = ptr::addr_of(&server_addr);
// uv_tcp_bind()
let bind_result = tcp_bind(tcp_server_ptr,
server_addr_ptr);
if (bind_result == 0i32) {
log(debug, ~"successful uv_tcp_bind, listening");
// uv_listen()
let listen_result = listen(tcp_server_ptr as
*libc::c_void,
128i32,
server_connection_cb);
if (listen_result == 0i32) {
// let the test know it can set up the tcp server,
// now.. this may still present a race, not sure..
let async_result = async_init(test_loop,
continue_async_handle_ptr,
continue_async_cb);
if (async_result == 0i32) {
set_data_for_uv_handle(
continue_async_handle_ptr as *libc::c_void,
async_data_ptr as *libc::c_void);
async_send(continue_async_handle_ptr);
// uv_run()
run(test_loop);
log(debug, ~"server uv::run() has returned");
}
else {
log(debug, fmt!("uv_async_init failure: %d",
async_result as int));
assert false;
}
}
else {
log(debug, fmt!("non-zero result on uv_listen: %d",
listen_result as int));
assert false;
}
}
else {
log(debug, fmt!("non-zero result on uv_tcp_bind: %d",
bind_result as int));
assert false;
}
}
else {
log(debug, fmt!("non-zero result on uv_tcp_init: %d",
tcp_init_result as int));
assert false;
}
loop_delete(test_loop);
}
}
// this is the impl for a test that is (maybe) ran on a
// per-platform/arch basis below
pub fn impl_uv_tcp_server_and_request() {
unsafe {
let bind_ip = ~"0.0.0.0";
let request_ip = ~"127.0.0.1";
let port = 8886;
let kill_server_msg = ~"does a dog have buddha nature?";
let server_resp_msg = ~"mu!";
let (client_port, client_chan) = stream::<~str>();
let client_chan = SharedChan(client_chan);
let (server_port, server_chan) = stream::<~str>();
let server_chan = SharedChan(server_chan);
let (continue_port, continue_chan) = stream::<bool>();
let continue_chan = SharedChan(continue_chan);
do task::spawn_sched(task::ManualThreads(1)) {
impl_uv_tcp_server(bind_ip, port,
kill_server_msg,
server_resp_msg,
server_chan.clone(),
continue_chan.clone());
};
// block until the server up is.. possibly a race?
log(debug, ~"before receiving on server continue_port");
continue_port.recv();
log(debug, ~"received on continue port, set up tcp client");
do task::spawn_sched(task::ManualThreads(1u)) {
impl_uv_tcp_request(request_ip, port,
kill_server_msg,
client_chan.clone());
};
let msg_from_client = server_port.recv();
let msg_from_server = client_port.recv();
assert str::contains(msg_from_client, kill_server_msg);
assert str::contains(msg_from_server, server_resp_msg);
}
}
// FIXME don't run on fbsd or linux 32 bit(#2064)
#[cfg(target_os="win32")]
#[cfg(target_os="darwin")]
#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub mod tcp_and_server_client_test {
#[cfg(target_arch="x86_64")]
pub mod impl64 {
use uv_ll::test::*;
#[test]
pub fn test_uv_ll_tcp_server_and_request() {
unsafe {
impl_uv_tcp_server_and_request();
}
}
}
#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
pub mod impl32 {
use uv_ll::test::*;
#[test]
#[ignore(cfg(target_os = "linux"))]
pub fn test_uv_ll_tcp_server_and_request() {
unsafe {
impl_uv_tcp_server_and_request();
}
}
}
}
fn struct_size_check_common<TStruct>(t_name: ~str,
foreign_size: libc::c_uint) {
unsafe {
let rust_size = sys::size_of::<TStruct>();
let sizes_match = foreign_size as uint == rust_size;
if !sizes_match {
let output = fmt!(
"STRUCT_SIZE FAILURE: %s -- actual: %u expected: %u",
t_name, rust_size, foreign_size as uint);
log(debug, output);
}
assert sizes_match;
}
}
// struct size tests
#[test]
fn test_uv_ll_struct_size_uv_tcp_t() {
unsafe {
struct_size_check_common::<uv_tcp_t>(
~"uv_tcp_t",
::uv_ll::rustrt::rust_uv_helper_uv_tcp_t_size()
);
}
}
#[test]
fn test_uv_ll_struct_size_uv_connect_t() {
unsafe {
struct_size_check_common::<uv_connect_t>(
~"uv_connect_t",
::uv_ll::rustrt::rust_uv_helper_uv_connect_t_size()
);
}
}
#[test]
fn test_uv_ll_struct_size_uv_buf_t() {
unsafe {
struct_size_check_common::<uv_buf_t>(
~"uv_buf_t",
::uv_ll::rustrt::rust_uv_helper_uv_buf_t_size()
);
}
}
#[test]
fn test_uv_ll_struct_size_uv_write_t() {
unsafe {
struct_size_check_common::<uv_write_t>(
~"uv_write_t",
::uv_ll::rustrt::rust_uv_helper_uv_write_t_size()
);
}
}
#[test]
fn test_uv_ll_struct_size_sockaddr_in() {
unsafe {
struct_size_check_common::<sockaddr_in>(
~"sockaddr_in",
::uv_ll::rustrt::rust_uv_helper_sockaddr_in_size()
);
}
}
#[test]
fn test_uv_ll_struct_size_sockaddr_in6() {
unsafe {
let foreign_handle_size =
::uv_ll::rustrt::rust_uv_helper_sockaddr_in6_size();
let rust_handle_size = sys::size_of::<sockaddr_in6>();
let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u",
foreign_handle_size as uint, rust_handle_size);
log(debug, output);
// FIXME #1645 .. rust appears to pad structs to the nearest
// byte..?
// .. can't get the uv::ll::sockaddr_in6 to == 28 :/
// .. so the type always appears to be 32 in size.. which is
// good, i guess.. better too big than too little
assert (4u+foreign_handle_size as uint) == rust_handle_size;
}
}
#[test]
#[ignore(reason = "questionable size calculations")]
fn test_uv_ll_struct_size_addr_in() {
unsafe {
let foreign_handle_size =
::uv_ll::rustrt::rust_uv_helper_addr_in_size();
let rust_handle_size = sys::size_of::<addr_in>();
let output = fmt!("addr_in -- foreign: %u rust: %u",
foreign_handle_size as uint, rust_handle_size);
log(debug, output);
// FIXME #1645 .. see note above about struct padding
assert (4u+foreign_handle_size as uint) == rust_handle_size;
}
}
#[test]
fn test_uv_ll_struct_size_uv_async_t() {
unsafe {
struct_size_check_common::<uv_async_t>(
~"uv_async_t",
::uv_ll::rustrt::rust_uv_helper_uv_async_t_size()
);
}
}
#[test]
fn test_uv_ll_struct_size_uv_timer_t() {
unsafe {
struct_size_check_common::<uv_timer_t>(
~"uv_timer_t",
::uv_ll::rustrt::rust_uv_helper_uv_timer_t_size()
);
}
}
#[test]
#[ignore(cfg(target_os = "win32"))]
fn test_uv_ll_struct_size_uv_getaddrinfo_t() {
unsafe {
struct_size_check_common::<uv_getaddrinfo_t>(
~"uv_getaddrinfo_t",
::uv_ll::rustrt::rust_uv_helper_uv_getaddrinfo_t_size()
);
}
}
#[test]
#[ignore(cfg(target_os = "macos"))]
#[ignore(cfg(target_os = "win32"))]
fn test_uv_ll_struct_size_addrinfo() {
unsafe {
struct_size_check_common::<uv_timer_t>(
~"addrinfo",
::uv_ll::rustrt::rust_uv_helper_uv_timer_t_size()
);
}
}
}