From e5bcfebd794fdfe89a37dfe7f001e8cec1156b71 Mon Sep 17 00:00:00 2001 From: Robert Clipsham Date: Thu, 17 Jul 2014 11:32:42 +0100 Subject: [PATCH 1/5] Support using custom sockets within the runtime. This is akin to supporting custom file descriptors, but for sockets. This allows for the implementation of raw sockets in an external library, as well as integration with other libraries that use sockets such as zeromq. --- src/liblibc/lib.rs | 152 ++++++++++++++++++++++- src/libnative/io/mod.rs | 28 +++-- src/libnative/io/net.rs | 78 ++++++++++++ src/librustrt/rtio.rs | 10 ++ src/librustuv/net.rs | 260 ++++++++++++++++++++++++++++++++++++++++ src/librustuv/uvio.rs | 12 +- src/libstd/io/mod.rs | 5 +- 7 files changed, 529 insertions(+), 16 deletions(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 949dd08eaa343..29689d913cd2c 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -116,13 +116,14 @@ pub use consts::os::posix88::{S_IFDIR, S_IFIFO, S_IFMT, S_IFREG, S_IFLNK}; pub use consts::os::posix88::{S_IREAD, S_IRUSR, S_IRWXU, S_IWUSR}; pub use consts::os::posix88::{STDERR_FILENO, STDIN_FILENO, S_IXUSR}; pub use consts::os::posix88::{STDOUT_FILENO, W_OK, X_OK}; -pub use consts::os::bsd44::{AF_INET, AF_INET6, SOCK_STREAM, SOCK_DGRAM}; +pub use consts::os::bsd44::{AF_INET, AF_INET6, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW}; pub use consts::os::bsd44::{IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, TCP_NODELAY}; pub use consts::os::bsd44::{SOL_SOCKET, SO_KEEPALIVE, SO_ERROR}; pub use consts::os::bsd44::{SO_REUSEADDR, SO_BROADCAST, SHUT_WR, IP_MULTICAST_LOOP}; pub use consts::os::bsd44::{IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP}; pub use consts::os::bsd44::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP}; -pub use consts::os::bsd44::{IP_MULTICAST_TTL, IP_TTL, SHUT_RD}; +pub use consts::os::bsd44::{IP_MULTICAST_TTL, IP_TTL, IP_HDRINCL, SHUT_RD}; +pub use consts::os::extra::{IPPROTO_RAW}; pub use funcs::c95::ctype::{isalnum, isalpha, iscntrl, isdigit}; pub use funcs::c95::ctype::{islower, isprint, ispunct, isspace}; @@ -178,14 +179,16 @@ pub use funcs::bsd43::{shutdown}; #[cfg(unix)] pub use consts::os::posix88::{ECANCELED, SIGINT, EINPROGRESS}; #[cfg(unix)] pub use consts::os::posix88::{ENOSYS, ENOTTY, ETIMEDOUT, EMFILE}; #[cfg(unix)] pub use consts::os::posix88::{SIGTERM, SIGKILL, SIGPIPE, PROT_NONE}; -#[cfg(unix)] pub use consts::os::posix01::{SIG_IGN}; +#[cfg(unix)] pub use consts::os::posix01::{SIG_IGN, F_GETFL, F_SETFL}; #[cfg(unix)] pub use consts::os::bsd44::{AF_UNIX}; +#[cfg(unix)] pub use consts::os::extra::{O_NONBLOCK}; #[cfg(unix)] pub use types::os::common::posix01::{pthread_t, timespec, timezone}; #[cfg(unix)] pub use types::os::arch::posix88::{uid_t, gid_t}; #[cfg(unix)] pub use types::os::arch::posix01::{pthread_attr_t}; #[cfg(unix)] pub use types::os::arch::posix01::{stat, utimbuf}; +#[cfg(unix)] pub use types::os::common::bsd44::{ifaddrs}; #[cfg(unix)] pub use funcs::posix88::unistd::{sysconf, setgid, setsid, setuid, pread, pwrite}; #[cfg(unix)] pub use funcs::posix88::unistd::{getgid, getuid}; #[cfg(unix)] pub use funcs::posix88::unistd::{_PC_NAME_MAX, utime, nanosleep, pathconf, link}; @@ -193,9 +196,11 @@ pub use funcs::bsd43::{shutdown}; #[cfg(unix)] pub use funcs::posix88::mman::{mmap, munmap, mprotect}; #[cfg(unix)] pub use funcs::posix88::dirent::{opendir, readdir_r, closedir}; #[cfg(unix)] pub use funcs::posix88::fcntl::{fcntl}; +#[cfg(unix)] pub use funcs::posix88::net::{if_nametoindex}; #[cfg(unix)] pub use funcs::posix01::stat_::{lstat}; #[cfg(unix)] pub use funcs::posix01::unistd::{fsync, ftruncate}; #[cfg(unix)] pub use funcs::posix01::unistd::{readlink, symlink}; +#[cfg(unix)] pub use funcs::bsd43::{getifaddrs, freeifaddrs}; #[cfg(windows)] pub use consts::os::c95::{WSAECONNREFUSED, WSAECONNRESET, WSAEACCES}; #[cfg(windows)] pub use consts::os::c95::{WSAEWOULDBLOCK, WSAENOTCONN, WSAECONNABORTED}; @@ -236,6 +241,7 @@ pub use funcs::bsd43::{shutdown}; #[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_CONNECTED, WAIT_OBJECT_0}; #[cfg(windows)] pub use consts::os::extra::{ERROR_NOT_FOUND}; #[cfg(windows)] pub use consts::os::extra::{ERROR_OPERATION_ABORTED}; +#[cfg(windows)] pub use consts::os::extra::{FIONBIO}; #[cfg(windows)] pub use types::os::common::bsd44::{SOCKET}; #[cfg(windows)] pub use types::os::common::posix01::{stat, utimbuf}; #[cfg(windows)] pub use types::os::arch::extra::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES}; @@ -268,6 +274,7 @@ pub use funcs::bsd43::{shutdown}; #[cfg(windows)] pub use funcs::extra::kernel32::{DisconnectNamedPipe, OpenProcess}; #[cfg(windows)] pub use funcs::extra::kernel32::{MoveFileExW, VirtualProtect}; #[cfg(windows)] pub use funcs::extra::msvcrt::{get_osfhandle, open_osfhandle}; +#[cfg(windows)] pub use funcs::extra::winsock::{ioctlsocket}; #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] #[cfg(target_os = "dragonfly")] @@ -275,6 +282,10 @@ pub use consts::os::posix01::{CLOCK_REALTIME, CLOCK_MONOTONIC}; #[cfg(target_os = "linux")] #[cfg(target_os = "android")] pub use funcs::posix01::unistd::{fdatasync}; +#[cfg(target_os = "linux")] #[cfg(target_os = "android")] +pub use types::os::arch::extra::{sockaddr_ll}; +#[cfg(target_os = "linux")] #[cfg(target_os = "android")] +pub use consts::os::extra::{AF_PACKET}; #[cfg(unix, not(target_os = "freebsd"))] pub use consts::os::extra::{MAP_STACK}; @@ -400,6 +411,7 @@ pub mod types { pub type sighandler_t = size_t; } pub mod bsd44 { + use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_int, c_uint}; pub type socklen_t = u32; @@ -477,6 +489,17 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char, ..108] } + + pub struct ifaddrs { + pub ifa_next: *mut ifaddrs, + pub ifa_name: *mut c_char, + pub ifa_flags: c_uint, + pub ifa_addr: *mut sockaddr, + pub ifa_netmask: *mut sockaddr, + pub ifa_ifu: *mut sockaddr, // FIXME This should be a union + pub ifa_data: *mut c_void + } + } } @@ -675,7 +698,19 @@ pub mod types { } pub mod posix08 {} pub mod bsd44 {} - pub mod extra {} + pub mod extra { + use types::os::arch::c95::{c_ushort, c_int, c_uchar}; + pub struct sockaddr_ll { + pub sll_family: c_ushort, + pub sll_protocol: c_ushort, + pub sll_ifindex: c_int, + pub sll_hatype: c_ushort, + pub sll_pkttype: c_uchar, + pub sll_halen: c_uchar, + pub sll_addr: [c_uchar, ..8] + } + } + } #[cfg(target_arch = "x86_64")] @@ -763,6 +798,17 @@ pub mod types { pub mod bsd44 { } pub mod extra { + use types::os::arch::c95::{c_ushort, c_int, c_uchar}; + pub struct sockaddr_ll { + pub sll_family: c_ushort, + pub sll_protocol: c_ushort, + pub sll_ifindex: c_int, + pub sll_hatype: c_ushort, + pub sll_pkttype: c_uchar, + pub sll_halen: c_uchar, + pub sll_addr: [c_uchar, ..8] + } + } } } @@ -812,6 +858,7 @@ pub mod types { pub type sighandler_t = size_t; } pub mod bsd44 { + use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_int, c_uint}; pub type socklen_t = u32; @@ -884,6 +931,17 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char, ..104] } + pub struct ifaddrs { + pub ifa_next: *mut ifaddrs, + pub ifa_name: *mut c_char, + pub ifa_flags: c_uint, + pub ifa_addr: *mut sockaddr, + pub ifa_netmask: *mut sockaddr, + pub ifa_dstaddr: *mut sockaddr, + pub ifa_data: *mut c_void + } + + } } @@ -1628,6 +1686,7 @@ pub mod types { } pub mod bsd44 { + use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_int, c_uint}; pub type socklen_t = c_int; @@ -1700,6 +1759,15 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char, ..104] } + pub struct ifaddrs { + pub ifa_next: *mut ifaddrs, + pub ifa_name: *mut c_char, + pub ifa_flags: c_uint, + pub ifa_addr: *mut sockaddr, + pub ifa_netmask: *mut sockaddr, + pub ifa_dstaddr: *mut sockaddr, + pub ifa_data: *mut c_void + } } } @@ -2032,6 +2100,7 @@ pub mod consts { pub static AF_INET6: c_int = 23; pub static SOCK_STREAM: c_int = 1; pub static SOCK_DGRAM: c_int = 2; + pub static SOCK_RAW: c_int = 3; pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_IP: c_int = 0; pub static IPPROTO_IPV6: c_int = 41; @@ -2042,6 +2111,7 @@ pub mod consts { pub static IPV6_ADD_MEMBERSHIP: c_int = 5; pub static IPV6_DROP_MEMBERSHIP: c_int = 6; pub static IP_TTL: c_int = 4; + pub static IP_HDRINCL: c_int = 2; pub static TCP_NODELAY: c_int = 0x0001; pub static SOL_SOCKET: c_int = 0xffff; @@ -2050,12 +2120,14 @@ pub mod consts { pub static SO_REUSEADDR: c_int = 4; pub static SO_ERROR: c_int = 0x1007; + pub static IFF_LOOPBACK: c_int = 4; + pub static SHUT_RD: c_int = 0; pub static SHUT_WR: c_int = 1; pub static SHUT_RDWR: c_int = 2; } pub mod extra { - use types::os::arch::c95::c_int; + use types::os::arch::c95::{c_int, c_long}; use types::os::arch::extra::{WORD, DWORD, BOOL, HANDLE}; pub static TRUE : BOOL = 1; @@ -2279,6 +2351,10 @@ pub mod consts { pub static PIPE_ACCEPT_REMOTE_CLIENTS: DWORD = 0x00000000; pub static PIPE_REJECT_REMOTE_CLIENTS: DWORD = 0x00000008; pub static PIPE_UNLIMITED_INSTANCES: DWORD = 255; + + pub static IPPROTO_RAW: c_int = 255; + + pub static FIONBIO: c_long = -0x7FFB9982; } pub mod sysconf { } @@ -2737,6 +2813,12 @@ pub mod consts { pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; + pub static F_DUPFD : c_int = 0; + pub static F_GETFD : c_int = 1; + pub static F_SETFD : c_int = 2; + pub static F_GETFL : c_int = 3; + pub static F_SETFL : c_int = 4; + pub static SIGTRAP : c_int = 5; pub static SIGPIPE: c_int = 13; pub static SIG_IGN: size_t = 1; @@ -2826,17 +2908,21 @@ pub mod consts { pub static MADV_UNMERGEABLE : c_int = 13; pub static MADV_HWPOISON : c_int = 100; + pub static IFF_LOOPBACK: c_int = 0x8; + pub static AF_UNIX: c_int = 1; pub static AF_INET: c_int = 2; pub static AF_INET6: c_int = 10; pub static SOCK_STREAM: c_int = 1; pub static SOCK_DGRAM: c_int = 2; + pub static SOCK_RAW: c_int = 3; pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_IP: c_int = 0; pub static IPPROTO_IPV6: c_int = 41; pub static IP_MULTICAST_TTL: c_int = 33; pub static IP_MULTICAST_LOOP: c_int = 34; pub static IP_TTL: c_int = 2; + pub static IP_HDRINCL: c_int = 3; pub static IP_ADD_MEMBERSHIP: c_int = 35; pub static IP_DROP_MEMBERSHIP: c_int = 36; pub static IPV6_ADD_MEMBERSHIP: c_int = 20; @@ -2903,8 +2989,12 @@ pub mod consts { pub mod extra { use types::os::arch::c95::c_int; + pub static AF_PACKET : c_int = 17; + pub static IPPROTO_RAW : c_int = 255; + pub static O_RSYNC : c_int = 1052672; pub static O_DSYNC : c_int = 4096; + pub static O_NONBLOCK : c_int = 2048; pub static O_SYNC : c_int = 1052672; pub static PROT_GROWSDOWN : c_int = 0x010000000; @@ -3240,6 +3330,12 @@ pub mod consts { pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; + pub static F_DUPFD : c_int = 0; + pub static F_GETFD : c_int = 1; + pub static F_SETFD : c_int = 2; + pub static F_GETFL : c_int = 3; + pub static F_SETFL : c_int = 4; + pub static SIGTRAP : c_int = 5; pub static SIGPIPE: c_int = 13; pub static SIG_IGN: size_t = 1; @@ -3338,12 +3434,14 @@ pub mod consts { pub static AF_UNIX: c_int = 1; pub static SOCK_STREAM: c_int = 1; pub static SOCK_DGRAM: c_int = 2; + pub static SOCK_RAW: c_int = 3; pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_IP: c_int = 0; pub static IPPROTO_IPV6: c_int = 41; pub static IP_MULTICAST_TTL: c_int = 10; pub static IP_MULTICAST_LOOP: c_int = 11; pub static IP_TTL: c_int = 4; + pub static IP_HDRINCL: c_int = 2; pub static IP_ADD_MEMBERSHIP: c_int = 12; pub static IP_DROP_MEMBERSHIP: c_int = 13; pub static IPV6_ADD_MEMBERSHIP: c_int = 12; @@ -3357,6 +3455,8 @@ pub mod consts { pub static SO_REUSEADDR: c_int = 0x0004; pub static SO_ERROR: c_int = 0x1007; + pub static IFF_LOOPBACK: c_int = 0x8; + pub static SHUT_RD: c_int = 0; pub static SHUT_WR: c_int = 1; pub static SHUT_RDWR: c_int = 2; @@ -3365,6 +3465,7 @@ pub mod consts { use types::os::arch::c95::c_int; pub static O_SYNC : c_int = 128; + pub static O_NONBLOCK : c_int = 4; pub static CTL_KERN: c_int = 1; pub static KERN_PROC: c_int = 14; #[cfg(target_os = "freebsd")] @@ -3379,6 +3480,8 @@ pub mod consts { pub static MAP_STACK : c_int = 0x0400; pub static MAP_NOSYNC : c_int = 0x0800; pub static MAP_NOCORE : c_int = 0x020000; + + pub static IPPROTO_RAW : c_int = 255; } pub mod sysconf { use types::os::arch::c95::c_int; @@ -3646,6 +3749,12 @@ pub mod consts { pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; + pub static F_DUPFD : c_int = 0; + pub static F_GETFD : c_int = 1; + pub static F_SETFD : c_int = 2; + pub static F_GETFL : c_int = 3; + pub static F_SETFL : c_int = 4; + pub static SIGTRAP : c_int = 5; pub static SIGPIPE: c_int = 13; pub static SIG_IGN: size_t = 1; @@ -3728,12 +3837,14 @@ pub mod consts { pub static AF_INET6: c_int = 30; pub static SOCK_STREAM: c_int = 1; pub static SOCK_DGRAM: c_int = 2; + pub static SOCK_RAW: c_int = 3; pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_IP: c_int = 0; pub static IPPROTO_IPV6: c_int = 41; pub static IP_MULTICAST_TTL: c_int = 10; pub static IP_MULTICAST_LOOP: c_int = 11; pub static IP_TTL: c_int = 4; + pub static IP_HDRINCL: c_int = 2; pub static IP_ADD_MEMBERSHIP: c_int = 12; pub static IP_DROP_MEMBERSHIP: c_int = 13; pub static IPV6_ADD_MEMBERSHIP: c_int = 12; @@ -3747,6 +3858,8 @@ pub mod consts { pub static SO_REUSEADDR: c_int = 0x0004; pub static SO_ERROR: c_int = 0x1007; + pub static IFF_LOOPBACK: c_int = 0x8; + pub static SHUT_RD: c_int = 0; pub static SHUT_WR: c_int = 1; pub static SHUT_RDWR: c_int = 2; @@ -3756,6 +3869,7 @@ pub mod consts { pub static O_DSYNC : c_int = 4194304; pub static O_SYNC : c_int = 128; + pub static O_NONBLOCK : c_int = 4; pub static F_FULLFSYNC : c_int = 51; pub static MAP_COPY : c_int = 0x0002; @@ -3766,6 +3880,8 @@ pub mod consts { pub static MAP_NOCACHE : c_int = 0x0400; pub static MAP_JIT : c_int = 0x0800; pub static MAP_STACK : c_int = 0; + + pub static IPPROTO_RAW : c_int = 255; } pub mod sysconf { use types::os::arch::c95::c_int; @@ -4326,6 +4442,15 @@ pub mod funcs { pub fn shm_unlink(name: *const c_char) -> c_int; } } + + pub mod net { + use types::os::arch::c95::{c_char, c_uint}; + + extern { + pub fn if_nametoindex(ifname: *const c_char) -> c_uint; + } + } + } #[cfg(target_os = "linux")] @@ -4439,6 +4564,9 @@ pub mod funcs { pub mod mman { } + + pub mod net { + } } @@ -4457,7 +4585,7 @@ pub mod funcs { #[cfg(not(windows))] pub mod bsd43 { use types::common::c95::{c_void}; - use types::os::common::bsd44::{socklen_t, sockaddr}; + use types::os::common::bsd44::{socklen_t, sockaddr, ifaddrs}; use types::os::arch::c95::{c_int, size_t}; use types::os::arch::posix88::ssize_t; @@ -4487,6 +4615,8 @@ pub mod funcs { pub fn sendto(socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t; + pub fn getifaddrs(ifap: *mut *mut ifaddrs) -> c_int; + pub fn freeifaddrs(ifa: *mut ifaddrs); pub fn shutdown(socket: c_int, how: c_int) -> c_int; } } @@ -4572,6 +4702,7 @@ pub mod funcs { extern { pub fn getdtablesize() -> c_int; + pub fn ioctl(d: c_int, request: c_int, ...) -> c_int; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) @@ -4815,6 +4946,15 @@ pub mod funcs { flags: c_int) -> c_int; } } + + pub mod winsock { + use types::os::arch::c95::{c_int, c_long, c_ulong}; + use types::os::common::bsd44::SOCKET; + + extern "system" { + pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int; + } + } } } diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 2dc6539b17806..fac767a42b20f 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -26,6 +26,7 @@ use libc::c_int; use libc; use std::c_str::CString; +use std::num::from_i32; use std::os; use std::rt::rtio; use std::rt::rtio::{IoResult, IoError}; @@ -117,22 +118,24 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> { #[cfg(windows)] #[inline] -fn retry(f: || -> libc::c_int) -> libc::c_int { +fn retry(f: || -> T) -> T { loop { - match f() { - -1 if os::errno() as int == libc::WSAEINTR as int => {} - n => return n, + let minus1: T = from_i32(-1).unwrap(); + let ret = f(); + if ret != minus1 || os::errno() as int != libc::WSAEINTR as int { + return ret } } } #[cfg(unix)] #[inline] -fn retry(f: || -> libc::c_int) -> libc::c_int { +fn retry(f: || -> T) -> T { loop { - match f() { - -1 if os::errno() as int == libc::EINTR as int => {} - n => return n, + let minus1: T = from_i32(-1).unwrap(); + let ret = f(); + if ret != minus1 || os::errno() as int != libc::EINTR as int { + return ret } } } @@ -208,6 +211,15 @@ impl rtio::IoFactory for IoFactory { { addrinfo::GetAddrInfoRequest::run(host, servname, hint) } + fn socket_from_raw_fd(&mut self, fd: net::sock_t, close: rtio::CloseBehavior) + -> IoResult> { + let close = match close { + rtio::CloseSynchronously | rtio::CloseAsynchronously => true, + rtio::DontClose => false + }; + + net::Socket::new(fd, close).map(|s| box s as Box) + } // filesystem operations fn fs_from_raw_fd(&mut self, fd: c_int, close: rtio::CloseBehavior) diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 368b5914444ac..d21b6d01ca986 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -10,6 +10,7 @@ use alloc::arc::Arc; use libc; +use std::intrinsics; use std::mem; use std::ptr; use std::rt::mutex; @@ -877,6 +878,83 @@ impl rtio::RtioUdpSocket for UdpSocket { } } +//////////////////////////////////////////////////////////////////////////////// +/// Arbitrary sockets +//////////////////////////////////////////////////////////////////////////////// + +#[cfg(windows)] +pub fn net_buflen(buf: &[u8]) -> i32 { + buf.len() as i32 +} + +#[cfg(not(windows))] +pub fn net_buflen(buf: &[u8]) -> u64 { + buf.len() as u64 +} + +pub struct Socket { + fd: sock_t, + close_on_drop: bool +} + +impl Socket { + pub fn new(sock: sock_t, close_on_drop: bool) -> IoResult + { + let socket = Socket { fd: sock, close_on_drop: close_on_drop }; + return Ok(socket); + } +} + +impl rtio::RtioCustomSocket for Socket { + fn recv_from(&mut self, buf: &mut [u8], addr: *mut libc::sockaddr_storage) + -> IoResult + { + let mut caddrlen = unsafe { + intrinsics::size_of::() + } as libc::socklen_t; + let len = unsafe { + retry( || libc::recvfrom(self.fd, + buf.as_ptr() as *mut libc::c_void, + net_buflen(buf), + 0, + addr as *mut libc::sockaddr, + &mut caddrlen)) + }; + if len == -1 { + return Err(last_error()); + } + + return Ok(len as uint); + } + + fn send_to(&mut self, buf: &[u8], addr: *const libc::sockaddr, slen: uint) + -> IoResult + { + let len = unsafe { + retry( || libc::sendto(self.fd, + buf.as_ptr() as *const libc::c_void, + net_buflen(buf), + 0, + addr, + slen as libc::socklen_t)) + }; + + return if len < 0 { + Err(last_error()) + } else { + Ok(len as uint) + }; + } +} + +impl Drop for Socket { + fn drop(&mut self) { + if self.close_on_drop { + unsafe { close(self.fd) } + } + } +} + //////////////////////////////////////////////////////////////////////////////// // Timeout helpers // diff --git a/src/librustrt/rtio.rs b/src/librustrt/rtio.rs index 261d544a24149..b2ba2269338ea 100644 --- a/src/librustrt/rtio.rs +++ b/src/librustrt/rtio.rs @@ -23,6 +23,9 @@ use c_str::CString; use local::Local; use task::Task; +#[cfg(windows)] pub type CSocketT = libc::SOCKET; +#[cfg(unix)] pub type CSocketT = libc::c_int; + pub trait EventLoop { fn run(&mut self); fn callback(&mut self, arg: proc(): Send); @@ -201,6 +204,8 @@ pub trait IoFactory { fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>, hint: Option) -> IoResult>; + fn socket_from_raw_fd(&mut self, fd: CSocketT, close: CloseBehavior) + -> IoResult>; // filesystem operations fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) @@ -292,6 +297,11 @@ pub trait RtioUdpSocket : RtioSocket { fn set_write_timeout(&mut self, timeout_ms: Option); } +pub trait RtioCustomSocket { + fn recv_from(&mut self, buf: &mut [u8], *mut libc::sockaddr_storage) -> IoResult; + fn send_to(&mut self, buf: &[u8], dst: *const libc::sockaddr, len: uint) -> IoResult; +} + pub trait RtioTimer { fn sleep(&mut self, msecs: u64); fn oneshot(&mut self, msecs: u64, cb: Box); diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 84ef9deaf922f..fc21a44bfa1cb 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -10,6 +10,7 @@ use libc::{size_t, ssize_t, c_int, c_void, c_uint}; use libc; +use std::intrinsics; use std::mem; use std::ptr; use std::rt::rtio; @@ -840,6 +841,265 @@ impl Drop for UdpWatcher { } } +//////////////////////////////////////////////////////////////////////////////// +/// Raw socket implementation +//////////////////////////////////////////////////////////////////////////////// + +pub struct SocketWatcher { + handle: *mut uvll::uv_poll_t, + socket: uvll::uv_os_socket_t, + home: HomeHandle, + close_on_drop: bool, +} + +#[cfg(windows)] +pub fn net_buflen(buf: &[u8]) -> i32 { + buf.len() as i32 +} + +#[cfg(not(windows))] +pub fn net_buflen(buf: &[u8]) -> u64 { + buf.len() as u64 +} + +#[cfg(windows)] +fn last_error() -> IoError { + use std::os; + let code = unsafe { libc::GetLastError() as uint }; + IoError { + code: code, + extra: 0, + detail: Some(os::error_string(code)), + } +} + +#[cfg(not(windows))] +fn last_error() -> IoError { + use std::os; + + let errno = os::errno() as uint; + IoError { + code: os::errno() as uint, + extra: 0, + detail: Some(os::error_string(errno)), + } +} + + +#[cfg(windows)] +fn make_nonblocking(socket: libc::SOCKET) -> Option { + let mut one: libc::c_ulong = 1; + if unsafe { libc::ioctlsocket(socket, libc::FIONBIO, &mut one as *mut libc::c_ulong) } != 0 { + Some(last_error()) + } else { + None + } +} + +#[cfg(not(windows))] +fn make_nonblocking(socket: c_int) -> Option { + let flags = unsafe { libc::fcntl(socket, libc::F_GETFL, 0i) }; + if flags == -1 { + return Some(last_error()); + } + if unsafe { libc::fcntl(socket, libc::F_SETFL, flags | libc::O_NONBLOCK) } == -1 { + return Some(last_error()); + } + return None; +} + +impl SocketWatcher { + pub fn new(io: &mut UvIoFactory, socket: uvll::uv_os_socket_t, close_on_drop: bool) + -> Result + { + let handle = unsafe { uvll::malloc_handle(uvll::UV_POLL) }; + + let raw = SocketWatcher { + handle: handle, + home: io.make_handle(), + socket: socket, + close_on_drop: close_on_drop + }; + + // Make socket non-blocking - required for libuv + match make_nonblocking(raw.socket) { + Some(e) => return Err(e), + None => () + } + + assert_eq!(unsafe { + uvll::uv_poll_init_socket(io.uv_loop(), raw.handle, raw.socket) + }, 0); + return Ok(raw); + } +} + +impl UvHandle for SocketWatcher { + fn uv_handle(&self) -> *mut uvll::uv_poll_t { self.handle } +} + +impl Drop for SocketWatcher { + fn drop(&mut self) { + let _m = self.fire_homing_missile(); + if self.close_on_drop { + self.close(); + } + } +} + +impl HomingIO for SocketWatcher { + fn home<'r>(&'r mut self) -> &'r mut HomeHandle { &mut self.home } +} + +impl rtio::RtioCustomSocket for SocketWatcher { + fn recv_from(&mut self, buf: &mut [u8], addr: *mut libc::sockaddr_storage) + -> Result + { + struct Ctx<'b> { + task: Option, + buf: &'b [u8], + result: Option>, + socket: Option, + addr: *mut libc::sockaddr_storage + } + let _m = self.fire_homing_missile(); + let a = match unsafe { + uvll::uv_poll_start(self.handle, uvll::UV_READABLE as c_int, recv_cb) + } { + 0 => { + let mut cx = Ctx { + task: None, + buf: buf, + result: None, + socket: Some(self.socket), + addr: addr, + }; + wait_until_woken_after(&mut cx.task, &self.uv_loop(), || { + unsafe { uvll::set_data_for_uv_handle(self.handle, &mut cx) } + }); + cx.result.unwrap().map(|n| n as uint) + } + n => Err(uv_error_to_io_error(UvError(n))) + }; + return a; + + extern fn recv_cb(handle: *mut uvll::uv_poll_t, status: c_int, events: c_int) { + assert!((events & (uvll::UV_READABLE as c_int)) != 0); + let cx: &mut Ctx = unsafe { + intrinsics::transmute(uvll::get_data_for_uv_handle(handle)) + }; + + if status < 0 { + cx.result = Some(Err(uv_error_to_io_error(UvError(status)))); + wakeup(&mut cx.task); + return; + } + + unsafe { + assert_eq!(uvll::uv_poll_stop(handle), 0) + } + + let mut caddrlen = unsafe { + intrinsics::size_of::() + } as libc::socklen_t; + let len = match cx.socket { + Some(sock) => unsafe { + libc::recvfrom(sock, + cx.buf.as_ptr() as *mut c_void, + net_buflen(cx.buf), + 0, + cx.addr as *mut libc::sockaddr, + &mut caddrlen) + }, + _ => -1 + }; + if len == -1 { + cx.result = Some(Err(last_error())); + wakeup(&mut cx.task); + return; + } + + cx.result = Some(Ok(len as ssize_t)); + + wakeup(&mut cx.task); + } + } + + fn send_to(&mut self, buf: &[u8], dst: *const libc::sockaddr, slen: uint) + -> Result + { + struct Ctx<'b> { + task: Option, + buf: &'b [u8], + result: Option>, + socket: Option, + addr: *const libc::sockaddr, + len: uint + } + let _m = self.fire_homing_missile(); + + let a = match unsafe { + uvll::uv_poll_start(self.handle, uvll::UV_WRITABLE as c_int, send_cb) + } { + 0 => { + let mut cx = Ctx { + task: None, + buf: buf, + result: None, + socket: Some(self.socket), + addr: dst, + len: slen + }; + wait_until_woken_after(&mut cx.task, &self.uv_loop(), || { + unsafe { uvll::set_data_for_uv_handle(self.handle, &mut cx) } + }); + cx.result.unwrap() + } + n => Err(uv_error_to_io_error(UvError(n))) + }; + return a; + + extern fn send_cb(handle: *mut uvll::uv_poll_t, status: c_int, events: c_int) { + assert!((events & (uvll::UV_WRITABLE as c_int)) != 0); + let cx: &mut Ctx = unsafe { + intrinsics::transmute(uvll::get_data_for_uv_handle(handle)) + }; + if status < 0 { + cx.result = Some(Err(uv_error_to_io_error(UvError(status)))); + wakeup(&mut cx.task); + return; + } + + unsafe { + assert_eq!(uvll::uv_poll_stop(handle), 0) + } + + let len = match cx.socket { + Some(sock) => { + unsafe { + libc::sendto(sock, + cx.buf.as_ptr() as *const c_void, + net_buflen(cx.buf), + 0, + cx.addr, + cx.len as libc::socklen_t) + } + }, + _ => -1 + }; + + cx.result = if len < 0 { + Some(Err(last_error())) + } else { + Some(Ok(len as uint)) + }; + + wakeup(&mut cx.task); + } + } +} + + //////////////////////////////////////////////////////////////////////////////// // Shutdown helper //////////////////////////////////////////////////////////////////////////////// diff --git a/src/librustuv/uvio.rs b/src/librustuv/uvio.rs index 61e52a3abd19c..797fba9259266 100644 --- a/src/librustuv/uvio.rs +++ b/src/librustuv/uvio.rs @@ -29,7 +29,7 @@ use file::{FsRequest, FileWatcher}; use queue::QueuePool; use homing::HomeHandle; use idle::IdleWatcher; -use net::{TcpWatcher, TcpListener, UdpWatcher}; +use net::{SocketWatcher, TcpWatcher, TcpListener, UdpWatcher}; use pipe::{PipeWatcher, PipeListener}; use process::Process; use signal::SignalWatcher; @@ -176,6 +176,16 @@ impl IoFactory for UvIoFactory { r.map_err(uv_error_to_io_error) } + fn socket_from_raw_fd(&mut self, fd: uvll::uv_os_socket_t, close_on_drop: rtio::CloseBehavior) + -> IoResult> { + let close = match close_on_drop { + rtio::CloseSynchronously | rtio::CloseAsynchronously => true, + rtio::DontClose => false + }; + + SocketWatcher::new(self, fd, close).map(|sw| box sw as Box) + } + fn fs_from_raw_fd(&mut self, fd: c_int, close: rtio::CloseBehavior) -> Box { box FileWatcher::new(self, fd, close) as diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index dc6478df3605d..b21af143f2282 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -412,7 +412,10 @@ impl IoError { IoError::from_errno(os::errno() as uint, true) } - fn from_rtio_error(err: rtio::IoError) -> IoError { + /// Convert a from a runtime I/O error to a IoError + /// + /// Primarily useful when using `IoFactory::socket_from_raw_fd()`. + pub fn from_rtio_error(err: rtio::IoError) -> IoError { let rtio::IoError { code, extra, detail } = err; let mut ioerr = IoError::from_errno(code, false); ioerr.detail = detail; From bbf24b2fb4fa72ef14142ab0a6d9c909eb316a30 Mon Sep 17 00:00:00 2001 From: Robert Clipsham Date: Thu, 31 Jul 2014 12:17:07 +0100 Subject: [PATCH 2/5] Code clean-ups for custom socket support. This fixes a number of issues discussed in the pull request. --- src/libnative/io/mod.rs | 9 +-- src/libnative/io/net.rs | 47 ++++++------- src/librustrt/rtio.rs | 3 +- src/librustuv/net.rs | 147 +++++++++++++++++++++------------------- src/librustuv/uvio.rs | 9 +-- 5 files changed, 104 insertions(+), 111 deletions(-) diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index fac767a42b20f..43257c1697098 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -211,14 +211,9 @@ impl rtio::IoFactory for IoFactory { { addrinfo::GetAddrInfoRequest::run(host, servname, hint) } - fn socket_from_raw_fd(&mut self, fd: net::sock_t, close: rtio::CloseBehavior) + fn socket_from_raw_fd(&mut self, fd: net::sock_t) -> IoResult> { - let close = match close { - rtio::CloseSynchronously | rtio::CloseAsynchronously => true, - rtio::DontClose => false - }; - - net::Socket::new(fd, close).map(|s| box s as Box) + net::Socket::new(fd).map(|s| box s as Box) } // filesystem operations diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index d21b6d01ca986..72f509f7c3cb9 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -10,7 +10,6 @@ use alloc::arc::Arc; use libc; -use std::intrinsics; use std::mem; use std::ptr; use std::rt::mutex; @@ -883,24 +882,18 @@ impl rtio::RtioUdpSocket for UdpSocket { //////////////////////////////////////////////////////////////////////////////// #[cfg(windows)] -pub fn net_buflen(buf: &[u8]) -> i32 { - buf.len() as i32 -} - +type Buflen = i32; #[cfg(not(windows))] -pub fn net_buflen(buf: &[u8]) -> u64 { - buf.len() as u64 -} +type Buflen = u64; pub struct Socket { fd: sock_t, - close_on_drop: bool } impl Socket { - pub fn new(sock: sock_t, close_on_drop: bool) -> IoResult + pub fn new(sock: sock_t) -> IoResult { - let socket = Socket { fd: sock, close_on_drop: close_on_drop }; + let socket = Socket { fd: sock }; return Ok(socket); } } @@ -909,16 +902,11 @@ impl rtio::RtioCustomSocket for Socket { fn recv_from(&mut self, buf: &mut [u8], addr: *mut libc::sockaddr_storage) -> IoResult { - let mut caddrlen = unsafe { - intrinsics::size_of::() - } as libc::socklen_t; + let mut caddrlen = mem::size_of::() as libc::socklen_t; let len = unsafe { - retry( || libc::recvfrom(self.fd, - buf.as_ptr() as *mut libc::c_void, - net_buflen(buf), - 0, - addr as *mut libc::sockaddr, - &mut caddrlen)) + retry( || libc::recvfrom(self.fd, buf.as_ptr() as *mut libc::c_void, + buf.len() as Buflen, 0, addr as *mut libc::sockaddr, + &mut caddrlen)) }; if len == -1 { return Err(last_error()); @@ -931,12 +919,8 @@ impl rtio::RtioCustomSocket for Socket { -> IoResult { let len = unsafe { - retry( || libc::sendto(self.fd, - buf.as_ptr() as *const libc::c_void, - net_buflen(buf), - 0, - addr, - slen as libc::socklen_t)) + retry( || libc::sendto(self.fd, buf.as_ptr() as *const libc::c_void, + buf.len() as Buflen, 0, addr, slen as libc::socklen_t)) }; return if len < 0 { @@ -945,12 +929,19 @@ impl rtio::RtioCustomSocket for Socket { Ok(len as uint) }; } + + fn clone(&self) -> Box { + box Socket { + fd: self.fd + } as Box + } + } impl Drop for Socket { fn drop(&mut self) { - if self.close_on_drop { - unsafe { close(self.fd) } + unsafe { + close(self.fd) } } } diff --git a/src/librustrt/rtio.rs b/src/librustrt/rtio.rs index b2ba2269338ea..8151153170ac4 100644 --- a/src/librustrt/rtio.rs +++ b/src/librustrt/rtio.rs @@ -204,7 +204,7 @@ pub trait IoFactory { fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>, hint: Option) -> IoResult>; - fn socket_from_raw_fd(&mut self, fd: CSocketT, close: CloseBehavior) + fn socket_from_raw_fd(&mut self, fd: CSocketT) -> IoResult>; // filesystem operations @@ -300,6 +300,7 @@ pub trait RtioUdpSocket : RtioSocket { pub trait RtioCustomSocket { fn recv_from(&mut self, buf: &mut [u8], *mut libc::sockaddr_storage) -> IoResult; fn send_to(&mut self, buf: &[u8], dst: *const libc::sockaddr, len: uint) -> IoResult; + fn clone(&self) -> Box; } pub trait RtioTimer { diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index fc21a44bfa1cb..6fc75727f902e 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -10,7 +10,6 @@ use libc::{size_t, ssize_t, c_int, c_void, c_uint}; use libc; -use std::intrinsics; use std::mem; use std::ptr; use std::rt::rtio; @@ -849,18 +848,18 @@ pub struct SocketWatcher { handle: *mut uvll::uv_poll_t, socket: uvll::uv_os_socket_t, home: HomeHandle, - close_on_drop: bool, -} -#[cfg(windows)] -pub fn net_buflen(buf: &[u8]) -> i32 { - buf.len() as i32 + // See above for what these are + refcount: Refcount, + read_access: AccessTimeout, + write_access: AccessTimeout, + } +#[cfg(windows)] +type Buflen = i32; #[cfg(not(windows))] -pub fn net_buflen(buf: &[u8]) -> u64 { - buf.len() as u64 -} +type Buflen = u64; #[cfg(windows)] fn last_error() -> IoError { @@ -909,7 +908,9 @@ fn make_nonblocking(socket: c_int) -> Option { } impl SocketWatcher { - pub fn new(io: &mut UvIoFactory, socket: uvll::uv_os_socket_t, close_on_drop: bool) + // NOTE It is an error to have multiple SocketWatchers for the same socket, + // see documentation for uv_poll_s in uv.h. + pub fn new(io: &mut UvIoFactory, socket: uvll::uv_os_socket_t) -> Result { let handle = unsafe { uvll::malloc_handle(uvll::UV_POLL) }; @@ -918,7 +919,9 @@ impl SocketWatcher { handle: handle, home: io.make_handle(), socket: socket, - close_on_drop: close_on_drop + refcount: Refcount::new(), + read_access: AccessTimeout::new(), + write_access: AccessTimeout::new(), }; // Make socket non-blocking - required for libuv @@ -941,7 +944,7 @@ impl UvHandle for SocketWatcher { impl Drop for SocketWatcher { fn drop(&mut self) { let _m = self.fire_homing_missile(); - if self.close_on_drop { + if self.refcount.decrement() { self.close(); } } @@ -959,10 +962,12 @@ impl rtio::RtioCustomSocket for SocketWatcher { task: Option, buf: &'b [u8], result: Option>, - socket: Option, + socket: uvll::uv_os_socket_t, addr: *mut libc::sockaddr_storage } - let _m = self.fire_homing_missile(); + let loop_ = self.uv_loop(); + let m = self.fire_homing_missile(); + let _guard = try!(self.read_access.grant(m)); let a = match unsafe { uvll::uv_poll_start(self.handle, uvll::UV_READABLE as c_int, recv_cb) } { @@ -971,11 +976,12 @@ impl rtio::RtioCustomSocket for SocketWatcher { task: None, buf: buf, result: None, - socket: Some(self.socket), + socket: self.socket, addr: addr, }; - wait_until_woken_after(&mut cx.task, &self.uv_loop(), || { - unsafe { uvll::set_data_for_uv_handle(self.handle, &mut cx) } + let handle = self.handle; + wait_until_woken_after(&mut cx.task, &loop_, || { + unsafe { uvll::set_data_for_uv_handle(handle, &mut cx) } }); cx.result.unwrap().map(|n| n as uint) } @@ -985,13 +991,15 @@ impl rtio::RtioCustomSocket for SocketWatcher { extern fn recv_cb(handle: *mut uvll::uv_poll_t, status: c_int, events: c_int) { assert!((events & (uvll::UV_READABLE as c_int)) != 0); - let cx: &mut Ctx = unsafe { - intrinsics::transmute(uvll::get_data_for_uv_handle(handle)) + let cx = unsafe { + uvll::get_data_for_uv_handle(handle) as *mut Ctx }; if status < 0 { - cx.result = Some(Err(uv_error_to_io_error(UvError(status)))); - wakeup(&mut cx.task); + unsafe { + (*cx).result = Some(Err(uv_error_to_io_error(UvError(status)))); + wakeup(&mut (*cx).task); + } return; } @@ -999,29 +1007,22 @@ impl rtio::RtioCustomSocket for SocketWatcher { assert_eq!(uvll::uv_poll_stop(handle), 0) } - let mut caddrlen = unsafe { - intrinsics::size_of::() - } as libc::socklen_t; - let len = match cx.socket { - Some(sock) => unsafe { - libc::recvfrom(sock, - cx.buf.as_ptr() as *mut c_void, - net_buflen(cx.buf), - 0, - cx.addr as *mut libc::sockaddr, - &mut caddrlen) - }, - _ => -1 + let mut caddrlen = mem::size_of::() as libc::socklen_t; + let len = unsafe { + libc::recvfrom((*cx).socket, (*cx).buf.as_ptr() as *mut c_void, + (*cx).buf.len() as Buflen, 0, + (*cx).addr as *mut libc::sockaddr, &mut caddrlen) }; - if len == -1 { - cx.result = Some(Err(last_error())); - wakeup(&mut cx.task); - return; - } - cx.result = Some(Ok(len as ssize_t)); + unsafe { + (*cx).result = if len == -1 { + Some(Err(last_error())) + } else { + Some(Ok(len as ssize_t)) + }; - wakeup(&mut cx.task); + wakeup(&mut (*cx).task); + } } } @@ -1032,11 +1033,13 @@ impl rtio::RtioCustomSocket for SocketWatcher { task: Option, buf: &'b [u8], result: Option>, - socket: Option, + socket: uvll::uv_os_socket_t, addr: *const libc::sockaddr, len: uint } - let _m = self.fire_homing_missile(); + let loop_ = self.uv_loop(); + let m = self.fire_homing_missile(); + let _guard = try!(self.write_access.grant(m)); let a = match unsafe { uvll::uv_poll_start(self.handle, uvll::UV_WRITABLE as c_int, send_cb) @@ -1046,12 +1049,13 @@ impl rtio::RtioCustomSocket for SocketWatcher { task: None, buf: buf, result: None, - socket: Some(self.socket), + socket: self.socket, addr: dst, len: slen }; - wait_until_woken_after(&mut cx.task, &self.uv_loop(), || { - unsafe { uvll::set_data_for_uv_handle(self.handle, &mut cx) } + let handle = self.handle; + wait_until_woken_after(&mut cx.task, &loop_, || { + unsafe { uvll::set_data_for_uv_handle(handle, &mut cx) } }); cx.result.unwrap() } @@ -1061,12 +1065,14 @@ impl rtio::RtioCustomSocket for SocketWatcher { extern fn send_cb(handle: *mut uvll::uv_poll_t, status: c_int, events: c_int) { assert!((events & (uvll::UV_WRITABLE as c_int)) != 0); - let cx: &mut Ctx = unsafe { - intrinsics::transmute(uvll::get_data_for_uv_handle(handle)) + let cx = unsafe { + uvll::get_data_for_uv_handle(handle) as *mut Ctx }; if status < 0 { - cx.result = Some(Err(uv_error_to_io_error(UvError(status)))); - wakeup(&mut cx.task); + unsafe { + (*cx).result = Some(Err(uv_error_to_io_error(UvError(status)))); + wakeup(&mut (*cx).task); + } return; } @@ -1074,29 +1080,34 @@ impl rtio::RtioCustomSocket for SocketWatcher { assert_eq!(uvll::uv_poll_stop(handle), 0) } - let len = match cx.socket { - Some(sock) => { - unsafe { - libc::sendto(sock, - cx.buf.as_ptr() as *const c_void, - net_buflen(cx.buf), - 0, - cx.addr, - cx.len as libc::socklen_t) - } - }, - _ => -1 + let len = unsafe { + libc::sendto((*cx).socket, (*cx).buf.as_ptr() as *const c_void, + (*cx).buf.len() as Buflen, 0, + (*cx).addr, (*cx).len as libc::socklen_t) }; - cx.result = if len < 0 { - Some(Err(last_error())) - } else { - Some(Ok(len as uint)) - }; + unsafe { + (*cx).result = if len < 0 { + Some(Err(last_error())) + } else { + Some(Ok(len as uint)) + }; - wakeup(&mut cx.task); + wakeup(&mut (*cx).task); + } } } + + fn clone(&self) -> Box { + box SocketWatcher { + handle: self.handle, + socket: self.socket, + home: self.home.clone(), + refcount: self.refcount.clone(), + write_access: self.write_access.clone(), + read_access: self.read_access.clone(), + } as Box + } } diff --git a/src/librustuv/uvio.rs b/src/librustuv/uvio.rs index 797fba9259266..f420d5fb01c02 100644 --- a/src/librustuv/uvio.rs +++ b/src/librustuv/uvio.rs @@ -176,14 +176,9 @@ impl IoFactory for UvIoFactory { r.map_err(uv_error_to_io_error) } - fn socket_from_raw_fd(&mut self, fd: uvll::uv_os_socket_t, close_on_drop: rtio::CloseBehavior) + fn socket_from_raw_fd(&mut self, fd: uvll::uv_os_socket_t) -> IoResult> { - let close = match close_on_drop { - rtio::CloseSynchronously | rtio::CloseAsynchronously => true, - rtio::DontClose => false - }; - - SocketWatcher::new(self, fd, close).map(|sw| box sw as Box) + SocketWatcher::new(self, fd).map(|sw| box sw as Box) } fn fs_from_raw_fd(&mut self, fd: c_int, close: rtio::CloseBehavior) From 2b7981f028e1ced9aa4393910847f013e303c15e Mon Sep 17 00:00:00 2001 From: Robert Clipsham Date: Mon, 25 Aug 2014 18:46:03 +0100 Subject: [PATCH 3/5] Fix for latest changes. --- src/libnative/io/net.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 72f509f7c3cb9..dadcbeec70d4a 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -941,7 +941,7 @@ impl rtio::RtioCustomSocket for Socket { impl Drop for Socket { fn drop(&mut self) { unsafe { - close(self.fd) + os::close(self.fd) } } } From 914efa100e56e91ec529bba37d89e946f89866e7 Mon Sep 17 00:00:00 2001 From: Robert Clipsham Date: Mon, 25 Aug 2014 19:02:23 +0100 Subject: [PATCH 4/5] More fixes for latest Rust changes. --- src/liblibc/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 29689d913cd2c..ae643c0c03bd3 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -490,6 +490,7 @@ pub mod types { pub sun_path: [c_char, ..108] } + #[repr(C)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, @@ -700,6 +701,7 @@ pub mod types { pub mod bsd44 {} pub mod extra { use types::os::arch::c95::{c_ushort, c_int, c_uchar}; + #[repr(C)] pub struct sockaddr_ll { pub sll_family: c_ushort, pub sll_protocol: c_ushort, @@ -931,6 +933,7 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char, ..104] } + #[repr(C)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, @@ -1759,6 +1762,7 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char, ..104] } + #[repr(C)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, From 9bbc3665b4c2b269c28028d62276343989b374e8 Mon Sep 17 00:00:00 2001 From: Robert Clipsham Date: Tue, 26 Aug 2014 13:15:56 +0100 Subject: [PATCH 5/5] More build fixes. --- src/librustuv/net.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 6fc75727f902e..35bce92f2240f 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -851,8 +851,8 @@ pub struct SocketWatcher { // See above for what these are refcount: Refcount, - read_access: AccessTimeout, - write_access: AccessTimeout, + read_access: AccessTimeout<()>, + write_access: AccessTimeout<()>, } @@ -920,8 +920,8 @@ impl SocketWatcher { home: io.make_handle(), socket: socket, refcount: Refcount::new(), - read_access: AccessTimeout::new(), - write_access: AccessTimeout::new(), + read_access: AccessTimeout::new(()), + write_access: AccessTimeout::new(()), }; // Make socket non-blocking - required for libuv