diff --git a/.travis.yml b/.travis.yml index b21f272..7296fbf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: rust -sudo: false +sudo: required matrix: include: @@ -10,7 +10,7 @@ matrix: - rust: nightly script: - cargo test - - cargo test --feature snightly + - cargo test --features nightly - rust: nightly before_script: @@ -20,6 +20,13 @@ matrix: after_success: - travis-cargo doc-upload +before_script: + # Add an IPv6 config - see the corresponding Travis issue + # https://github.com/travis-ci/travis-ci/issues/8361 + - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then + sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'; + fi + script: - cargo test diff --git a/Cargo.toml b/Cargo.toml index a806e64..9049c74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,11 @@ Extensions to the standard library's networking types as proposed in RFC 1158. [target."cfg(windows)".dependencies] winapi = { version = "0.3", features = ["handleapi", "winsock2", "ws2def", "ws2ipdef", "ws2tcpip"] } -[target.'cfg(any(target_os="redox", unix))'.dependencies] -libc = "0.2.42" +[target.'cfg(any(target_os="redox", unix, target_os="wasi"))'.dependencies] +libc = "0.2.54" [dependencies] -cfg-if = "0.1" +cfg-if = "<0.1.10" [features] nightly = [] diff --git a/src/ext.rs b/src/ext.rs index 74783e4..60a920e 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -38,13 +38,15 @@ cfg_if! { use std::time::Duration; -#[cfg(any(unix, target_os = "redox"))] use libc::*; +#[cfg(any(unix, target_os = "redox", target_os = "wasi"))] use libc::*; #[cfg(any(unix, target_os = "redox"))] use std::os::unix::prelude::*; +#[cfg(target_os = "wasi")] use std::os::wasi::prelude::*; #[cfg(target_os = "redox")] pub type Socket = usize; #[cfg(unix)] pub type Socket = c_int; +#[cfg(target_os = "wasi")] pub type Socket = std::os::wasi::io::RawFd; #[cfg(windows)] pub type Socket = SOCKET; #[cfg(windows)] use std::os::windows::prelude::*; -#[cfg(windows)] use sys::c::*; +#[cfg(any(windows, target_os = "wasi"))] use sys::c::*; #[cfg(windows)] const SIO_KEEPALIVE_VALS: DWORD = 0x98000004; #[cfg(windows)] @@ -55,31 +57,42 @@ struct tcp_keepalive { keepaliveinterval: c_ulong, } -#[cfg(target_os = "redox")] fn v(opt: c_int) -> c_int { opt } -#[cfg(unix)] fn v(opt: c_int) -> c_int { opt } +#[cfg(any(unix, target_os = "redox", target_os = "wasi"))] fn v(opt: c_int) -> c_int { opt } #[cfg(windows)] fn v(opt: IPPROTO) -> c_int { opt as c_int } +#[cfg(target_os = "wasi")] +pub fn set_opt(_sock: Socket, _opt: c_int, _val: c_int, + _payload: T) -> io::Result<()> { + Ok(()) +} + +#[cfg(not(target_os = "wasi"))] pub fn set_opt(sock: Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> { unsafe { let payload = &payload as *const T as *const c_void; #[cfg(target_os = "redox")] let sock = sock as c_int; - try!(::cvt(setsockopt(sock, opt, val, payload as *const _, - mem::size_of::() as socklen_t))); - Ok(()) + ::cvt(setsockopt(sock, opt, val, payload as *const _, + mem::size_of::() as socklen_t))?; } + Ok(()) } +#[cfg(target_os = "wasi")] +pub fn get_opt(_sock: Socket, _opt: c_int, _val: c_int) -> io::Result { + unimplemented!() +} +#[cfg(not(target_os = "wasi"))] pub fn get_opt(sock: Socket, opt: c_int, val: c_int) -> io::Result { unsafe { let mut slot: T = mem::zeroed(); let mut len = mem::size_of::() as socklen_t; #[cfg(target_os = "redox")] let sock = sock as c_int; - try!(::cvt(getsockopt(sock, opt, val, + ::cvt(getsockopt(sock, opt, val, &mut slot as *mut _ as *mut _, - &mut len))); + &mut len))?; assert_eq!(len as usize, mem::size_of::()); Ok(slot) } @@ -641,11 +654,7 @@ pub trait AsSock { fn as_sock(&self) -> Socket; } -#[cfg(target_os = "redox")] -impl AsSock for T { - fn as_sock(&self) -> Socket { self.as_raw_fd() } -} -#[cfg(unix)] +#[cfg(any(unix, target_os = "redox", target_os = "wasi"))] impl AsSock for T { fn as_sock(&self) -> Socket { self.as_raw_fd() } } @@ -707,58 +716,76 @@ impl TcpStreamExt for TcpStream { #[cfg(target_os = "redox")] fn set_keepalive_ms(&self, keepalive: Option) -> io::Result<()> { - try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE, - keepalive.is_some() as c_int)); + set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE, + keepalive.is_some() as c_int)?; if let Some(dur) = keepalive { - try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION, - (dur / 1000) as c_int)); + set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION, + (dur / 1000) as c_int)?; } Ok(()) } #[cfg(target_os = "redox")] fn keepalive_ms(&self) -> io::Result> { - let keepalive = try!(get_opt::(self.as_sock(), SOL_SOCKET, - SO_KEEPALIVE)); + let keepalive = get_opt::(self.as_sock(), SOL_SOCKET, + SO_KEEPALIVE)?; if keepalive == 0 { return Ok(None) } - let secs = try!(get_opt::(self.as_sock(), v(IPPROTO_TCP), - KEEPALIVE_OPTION)); + let secs = get_opt::(self.as_sock(), v(IPPROTO_TCP), + KEEPALIVE_OPTION)?; Ok(Some((secs as u32) * 1000)) } - #[cfg(unix)] + #[cfg(target_os = "openbsd")] fn set_keepalive_ms(&self, keepalive: Option) -> io::Result<()> { - try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE, - keepalive.is_some() as c_int)); - cfg_if! { - if #[cfg(not(target_os = "openbsd"))] { - if let Some(dur) = keepalive { - try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION, - (dur / 1000) as c_int)); - } - } - } + set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE, + keepalive.is_some() as c_int)?; Ok(()) } - #[cfg(unix)] + #[cfg(target_os = "openbsd")] fn keepalive_ms(&self) -> io::Result> { - let keepalive = try!(get_opt::(self.as_sock(), SOL_SOCKET, - SO_KEEPALIVE)); + let keepalive = get_opt::(self.as_sock(), SOL_SOCKET, + SO_KEEPALIVE)?; if keepalive == 0 { return Ok(None) + } else { + return Ok(Some(1u32)) } - cfg_if! { - if #[cfg(target_os = "openbsd")] { - Ok(None) - } else { - let secs = try!(get_opt::(self.as_sock(), v(IPPROTO_TCP), - KEEPALIVE_OPTION)); - Ok(Some((secs as u32) * 1000)) - } + } + + #[cfg(all(unix, not(target_os = "openbsd")))] + fn set_keepalive_ms(&self, keepalive: Option) -> io::Result<()> { + set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE, + keepalive.is_some() as c_int)?; + if let Some(dur) = keepalive { + set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION, + (dur / 1000) as c_int)?; + } + Ok(()) + } + + #[cfg(all(unix, not(target_os = "openbsd")))] + fn keepalive_ms(&self) -> io::Result> { + let keepalive = get_opt::(self.as_sock(), SOL_SOCKET, + SO_KEEPALIVE)?; + if keepalive == 0 { + return Ok(None) } + let secs = get_opt::(self.as_sock(), v(IPPROTO_TCP), + KEEPALIVE_OPTION)?; + Ok(Some((secs as u32) * 1000)) + } + + #[cfg(target_os = "wasi")] + fn set_keepalive_ms(&self, _keepalive: Option) -> io::Result<()> { + unimplemented!() + } + + #[cfg(target_os = "wasi")] + fn keepalive_ms(&self) -> io::Result> { + unimplemented!() } #[cfg(windows)] @@ -790,7 +817,7 @@ impl TcpStreamExt for TcpStream { keepaliveinterval: 0, }; unsafe { - try!(::cvt_win(WSAIoctl(self.as_sock(), + ::cvt_win(WSAIoctl(self.as_sock(), SIO_KEEPALIVE_VALS, 0 as *mut _, 0, @@ -798,7 +825,7 @@ impl TcpStreamExt for TcpStream { mem::size_of_val(&ka) as DWORD, 0 as *mut _, 0 as *mut _, - None))); + None))?; } Ok({ if ka.onoff == 0 { @@ -883,7 +910,7 @@ impl TcpStreamExt for TcpStream { } } -#[cfg(any(target_os = "redox", unix))] +#[cfg(any(target_os = "redox", unix, target_os = "wasi"))] fn ms2timeout(dur: Option) -> timeval { // TODO: be more rigorous match dur { @@ -895,7 +922,7 @@ fn ms2timeout(dur: Option) -> timeval { } } -#[cfg(any(target_os = "redox", unix))] +#[cfg(any(target_os = "redox", unix, target_os = "wasi"))] fn timeout2ms(dur: timeval) -> Option { if dur.tv_sec == 0 && dur.tv_usec == 0 { None @@ -940,7 +967,7 @@ fn dur2linger(dur: Option) -> linger { } } -#[cfg(any(target_os = "redox", unix))] +#[cfg(any(target_os = "redox", unix, target_os = "wasi"))] fn dur2linger(dur: Option) -> linger { match dur { Some(d) => { @@ -1204,6 +1231,22 @@ impl UdpSocketExt for UdpSocket { } } + #[cfg(target_os = "wasi")] + fn send(&self, buf: &[u8]) -> io::Result { + let _so_datalen: *mut sys::c::size_t = &mut 0; + unsafe { + let _errno = libc::__wasi_sock_send( + self.as_sock() as libc::__wasi_fd_t, + buf.as_ptr() as *const _, + buf.len(), + 0, + _so_datalen, + ); + // TODO: handle errno + Ok((*_so_datalen) as usize) + } + } + #[cfg(windows)] fn send(&self, buf: &[u8]) -> io::Result { let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize); @@ -1230,6 +1273,24 @@ impl UdpSocketExt for UdpSocket { } } + #[cfg(target_os = "wasi")] + fn recv(&self, buf: &mut [u8]) -> io::Result { + let _ro_datalen: *mut sys::c::size_t = &mut 0; + let _ro_flags: *mut sys::c::__wasi_roflags_t = &mut 0; + unsafe { + let _errno = __wasi_sock_recv( + self.as_sock(), + buf.as_mut_ptr() as *mut _, + buf.len(), + 0, + _ro_datalen, + _ro_flags, + ); + // TODO: handle errno + Ok((*_ro_datalen) as usize) + } + } + #[cfg(windows)] fn recv(&self, buf: &mut [u8]) -> io::Result { let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize); @@ -1248,7 +1309,7 @@ impl UdpSocketExt for UdpSocket { fn do_connect(sock: Socket, addr: A) -> io::Result<()> { let err = io::Error::new(io::ErrorKind::Other, "no socket addresses resolved"); - let addrs = try!(addr.to_socket_addrs()); + let addrs = addr.to_socket_addrs()?; let sys = sys::Socket::from_inner(sock); let sock = socket::Socket::from_inner(sys); let ret = addrs.fold(Err(err), |prev, addr| { @@ -1281,6 +1342,11 @@ fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> { }).map(|_| ()) } +#[cfg(target_os = "wasi")] +fn set_nonblocking(_sock: Socket, _nonblocking: bool) -> io::Result<()> { + Ok(()) +} + #[cfg(windows)] fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_ulong; @@ -1300,7 +1366,7 @@ fn ip2in_addr(ip: &Ipv4Addr) -> in_addr { } } -#[cfg(unix)] +#[cfg(any(unix, target_os = "wasi"))] fn ip2in_addr(ip: &Ipv4Addr) -> in_addr { let oct = ip.octets(); in_addr { @@ -1432,7 +1498,7 @@ impl TcpBuilder { /// Set value for the `SO_REUSEADDR` option on this socket. /// - /// This indicates that futher calls to `bind` may allow reuse of local + /// This indicates that further calls to `bind` may allow reuse of local /// addresses. For IPv4 sockets this means that a socket may bind even when /// there's a socket already listening on this port. pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> { diff --git a/src/lib.rs b/src/lib.rs index d5a3378..c93fd2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,8 +41,9 @@ html_root_url = "https://doc.rust-lang.org/net2-rs")] #![deny(missing_docs, warnings)] +#![cfg_attr(target_os = "wasi", feature(wasi_ext))] -#[cfg(any(target_os="redox", unix))] extern crate libc; +#[cfg(any(target_os = "redox", target_os = "wasi", unix))] extern crate libc; #[cfg(windows)] extern crate winapi; @@ -63,6 +64,7 @@ mod utils; #[cfg(target_os="redox")] #[path = "sys/redox/mod.rs"] mod sys; #[cfg(unix)] #[path = "sys/unix/mod.rs"] mod sys; #[cfg(windows)] #[path = "sys/windows/mod.rs"] mod sys; +#[cfg(target_os = "wasi")] #[path = "sys/wasi/mod.rs"] mod sys; #[cfg(all(unix, not(any(target_os = "solaris"))))] pub mod unix; pub use tcp::TcpBuilder; @@ -70,7 +72,7 @@ pub use udp::UdpBuilder; pub use ext::{TcpStreamExt, TcpListenerExt, UdpSocketExt}; fn one_addr(tsa: T) -> io::Result { - let mut addrs = try!(tsa.to_socket_addrs()); + let mut addrs = tsa.to_socket_addrs()?; let addr = match addrs.next() { Some(addr) => addr, None => return Err(io::Error::new(io::ErrorKind::Other, diff --git a/src/socket.rs b/src/socket.rs index 385ed2d..b3d0a73 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -12,9 +12,7 @@ use std::fmt; use std::io; use std::mem; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; -#[cfg(target_os = "redox")] -use libc::c_int; -#[cfg(unix)] +#[cfg(any(unix, target_os = "redox", target_os = "wasi"))] use libc::c_int; #[cfg(windows)] use winapi::ctypes::c_int; @@ -28,7 +26,7 @@ pub struct Socket { impl Socket { pub fn new(family: c_int, ty: c_int) -> io::Result { - Ok(Socket { inner: try!(sys::Socket::new(family, ty)) }) + Ok(Socket { inner: sys::Socket::new(family, ty)? }) } pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> { @@ -55,9 +53,9 @@ impl Socket { unsafe { let mut storage: c::sockaddr_storage = mem::zeroed(); let mut len = mem::size_of_val(&storage) as c::socklen_t; - try!(::cvt(c::getsockname(self.inner.raw(), + ::cvt(c::getsockname(self.inner.raw(), &mut storage as *mut _ as *mut _, - &mut len))); + &mut len))?; raw2addr(&storage, len) } } diff --git a/src/sys/unix/mod.rs b/src/sys/unix/mod.rs index e13f97c..0583b91 100644 --- a/src/sys/unix/mod.rs +++ b/src/sys/unix/mod.rs @@ -50,7 +50,7 @@ impl Socket { Err(e) => return Err(e), } - let fd = try!(::cvt(libc::socket(family, ty, 0))); + let fd = ::cvt(libc::socket(family, ty, 0))?; ioctl(fd, FIOCLEX); Ok(Socket { fd: fd }) } @@ -61,7 +61,7 @@ impl Socket { #[cfg(any(target_os = "solaris", target_os = "emscripten"))] pub fn new(family: c_int, ty: c_int) -> io::Result { unsafe { - let fd = try!(::cvt(libc::socket(family, ty, 0))); + let fd = ::cvt(libc::socket(family, ty, 0))?; libc::fcntl(fd, libc::FD_CLOEXEC); Ok(Socket { fd: fd }) } diff --git a/src/sys/wasi/impls.rs b/src/sys/wasi/impls.rs new file mode 100644 index 0000000..eef8094 --- /dev/null +++ b/src/sys/wasi/impls.rs @@ -0,0 +1,33 @@ +use std::os::wasi::io::{FromRawFd, AsRawFd}; + +use {TcpBuilder, UdpBuilder, FromInner, AsInner}; +use socket::Socket; +use sys::{self, c::__wasi_fd_t}; + +impl FromRawFd for TcpBuilder { + unsafe fn from_raw_fd(fd: __wasi_fd_t) -> TcpBuilder { + let sock = sys::Socket::from_inner(fd); + TcpBuilder::from_inner(Socket::from_inner(sock)) + } +} + +impl AsRawFd for TcpBuilder { + fn as_raw_fd(&self) -> __wasi_fd_t { + // TODO: this unwrap() is very bad + self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as __wasi_fd_t + } +} + +impl FromRawFd for UdpBuilder { + unsafe fn from_raw_fd(fd: __wasi_fd_t) -> UdpBuilder { + let sock = sys::Socket::from_inner(fd); + UdpBuilder::from_inner(Socket::from_inner(sock)) + } +} + +impl AsRawFd for UdpBuilder { + fn as_raw_fd(&self) -> __wasi_fd_t { + // TODO: this unwrap() is very bad + self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as __wasi_fd_t + } +} diff --git a/src/sys/wasi/mod.rs b/src/sys/wasi/mod.rs new file mode 100644 index 0000000..bbc507e --- /dev/null +++ b/src/sys/wasi/mod.rs @@ -0,0 +1,185 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_camel_case_types)] +use libc::{self, c_int, __wasi_fd_t}; +use std::io; +use std::mem; +use std::net::{TcpListener, TcpStream, UdpSocket}; +use std::os::wasi::io::FromRawFd; + +mod impls; + +pub mod c { + pub use libc::*; + + pub type sa_family_t = u16; + pub type socklen_t = u32; + pub type in_port_t = u16; + + pub const SOCK_DGRAM: c_int = 0x00; + pub const SOL_SOCKET: c_int = 0x00; + pub const SO_RCVBUF: c_int = 0x00; + pub const SO_SNDBUF: c_int = 0x00; + pub const TCP_NODELAY: c_int = 0x00; + pub const IPPROTO_TCP: c_int = 0x00; + pub const SO_RCVTIMEO: c_int = 0x00; + pub const SO_SNDTIMEO: c_int = 0x00; + pub const IPPROTO_IP: c_int = 0x00; + pub const IP_TTL: c_int = 0x00; + pub const IPPROTO_IPV6: c_int = 0x00; + pub const IPV6_V6ONLY: c_int = 0x00; + pub const SO_ERROR: c_int = 0x00; + pub const SO_LINGER: c_int = 0x00; + pub const SO_BROADCAST: c_int = 0x00; + pub const IP_MULTICAST_LOOP: c_int = 0x00; + pub const IP_MULTICAST_TTL: c_int = 0x00; + pub const IPV6_MULTICAST_HOPS: c_int = 0x00; + pub const IPV6_MULTICAST_LOOP: c_int = 0x00; + pub const IP_MULTICAST_IF: c_int = 0x00; + pub const IPV6_MULTICAST_IF: c_int = 0x00; + pub const IPV6_UNICAST_HOPS: c_int = 0x00; + pub const IP_ADD_MEMBERSHIP: c_int = 0x00; + pub const IPV6_ADD_MEMBERSHIP: c_int = 0x00; + pub const IP_DROP_MEMBERSHIP: c_int = 0x00; + pub const IPV6_DROP_MEMBERSHIP: c_int = 0x00; + pub const SO_REUSEADDR: c_int = 0x00; + pub const SOCK_STREAM: c_int = 0x00; + pub const AF_INET: c_int = 0x00; + pub const AF_INET6: c_int = 0x01; + + #[repr(C)] + pub struct sockaddr_storage { + pub ss_family: sa_family_t, + } + #[repr(C)] + pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [c_char; 14], + } + + #[repr(C)] + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: in6_addr, + pub sin6_scope_id: u32, + } + + #[repr(C)] + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: in_port_t, + pub sin_addr: in_addr, + pub sin_zero: [u8; 8], + } + + #[repr(align(4))] + #[derive(Copy, Clone)] + pub struct in6_addr { + pub s6_addr: [u8; 16], + } + + #[derive(Copy, Clone)] + pub struct ipv6_mreq { + pub ipv6mr_multiaddr: in6_addr, + pub ipv6mr_interface: c_uint, + } + + pub type in_addr_t = u32; + #[derive(Copy, Clone)] + pub struct in_addr { + pub s_addr: in_addr_t, + } + + #[derive(Copy, Clone)] + pub struct linger { + pub l_onoff: c_int, + pub l_linger: c_int, + } + + #[derive(Copy, Clone)] + pub struct ip_mreq { + pub imr_multiaddr: in_addr, + pub imr_interface: in_addr, + } + + pub unsafe fn getsockname(_socket: __wasi_fd_t, _address: *mut sockaddr, + _address_len: *mut socklen_t) -> c_int { + unimplemented!() + } + pub unsafe fn connect(_socket: __wasi_fd_t, _address: *const sockaddr, + _len: socklen_t) -> c_int { + unimplemented!() + } + pub unsafe fn listen(_socket: __wasi_fd_t, _backlog: c_int) -> c_int { + unimplemented!() + } + pub unsafe fn bind(_socket: __wasi_fd_t, _address: *const sockaddr, + _address_len: socklen_t) -> c_int { + unimplemented!() + } + + pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 { + ::ntoh((*sa).sin_addr.s_addr) + } + + pub fn in_addr_to_u32(addr: &in_addr) -> u32 { + ::ntoh(addr.s_addr) + } +} + +pub struct Socket { + fd: __wasi_fd_t, +} + +impl Socket { + pub fn new(_family: c_int, _ty: c_int) -> io::Result { + unimplemented!() + } + + pub fn raw(&self) -> libc::__wasi_fd_t { + self.fd + } + + fn into_fd(self) -> libc::__wasi_fd_t { + let fd = self.fd; + mem::forget(self); + fd + } + + pub fn into_tcp_listener(self) -> TcpListener { + unsafe { TcpListener::from_raw_fd(self.into_fd()) } + } + + pub fn into_tcp_stream(self) -> TcpStream { + unsafe { TcpStream::from_raw_fd(self.into_fd()) } + } + + pub fn into_udp_socket(self) -> UdpSocket { + unsafe { UdpSocket::from_raw_fd(self.into_fd()) } + } +} + +impl ::FromInner for Socket { + type Inner = libc::__wasi_fd_t; + fn from_inner(fd: libc::__wasi_fd_t) -> Socket { + Socket { fd: fd } + } +} + +impl Drop for Socket { + fn drop(&mut self) { + // unsafe { + // let _ = libc::close(self.fd); + // } + } +} \ No newline at end of file diff --git a/src/sys/windows/mod.rs b/src/sys/windows/mod.rs index b2da96d..4b983d1 100644 --- a/src/sys/windows/mod.rs +++ b/src/sys/windows/mod.rs @@ -14,7 +14,7 @@ use std::io; use std::mem; use std::net::{TcpListener, TcpStream, UdpSocket}; use std::os::windows::io::{RawSocket, FromRawSocket}; -use std::sync::{Once, ONCE_INIT}; +use std::sync::Once; const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; @@ -53,7 +53,7 @@ use self::c::*; mod impls; fn init() { - static INIT: Once = ONCE_INIT; + static INIT: Once = Once::new(); INIT.call_once(|| { // Initialize winsock through the standard library by just creating a @@ -70,14 +70,14 @@ pub struct Socket { impl Socket { pub fn new(family: c_int, ty: c_int) -> io::Result { init(); - let socket = try!(unsafe { + let socket = unsafe { match WSASocketW(family, ty, 0, 0 as *mut _, 0, WSA_FLAG_OVERLAPPED) { INVALID_SOCKET => Err(io::Error::last_os_error()), n => Ok(Socket { socket: n }), } - }); - try!(socket.set_no_inherit()); + }?; + socket.set_no_inherit()?; Ok(socket) } diff --git a/src/tcp.rs b/src/tcp.rs index 5a535db..e00da65 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -51,7 +51,7 @@ impl TcpBuilder { where T: ToSocketAddrs { self.with_socket(|sock| { - let addr = try!(::one_addr(addr)); + let addr = ::one_addr(addr)?; sock.bind(&addr) }).map(|()| self) } @@ -85,7 +85,7 @@ impl TcpBuilder { self.with_socket(|sock| { let err = io::Error::new(io::ErrorKind::Other, "no socket addresses resolved"); - try!(addr.to_socket_addrs()).fold(Err(err), |prev, addr| { + addr.to_socket_addrs()?.fold(Err(err), |prev, addr| { prev.or_else(|_| sock.connect(&addr)) }) }).and_then(|()| { diff --git a/src/udp.rs b/src/udp.rs index d061ab5..031e600 100644 --- a/src/udp.rs +++ b/src/udp.rs @@ -50,10 +50,10 @@ impl UdpBuilder { pub fn bind(&self, addr: T) -> io::Result where T: ToSocketAddrs { - try!(self.with_socket(|sock| { - let addr = try!(::one_addr(addr)); + self.with_socket(|sock| { + let addr = ::one_addr(addr)?; sock.bind(&addr) - })); + })?; Ok(self.socket.borrow_mut().take().unwrap().into_inner().into_udp_socket()) } diff --git a/src/unix.rs b/src/unix.rs index 21dcb2a..a1e1c6f 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -10,7 +10,7 @@ use ext::{self, AsSock}; pub trait UnixTcpBuilderExt { /// Set value for the `SO_REUSEPORT` option on this socket. /// - /// This indicates that futher calls to `bind` may allow reuse of local + /// This indicates that further calls to `bind` may allow reuse of local /// addresses. For IPv4 sockets this means that a socket may bind even when /// there's a socket already listening on this port. fn reuse_port(&self, reuse: bool) -> io::Result<&Self>; @@ -35,7 +35,7 @@ impl UnixTcpBuilderExt for TcpBuilder { pub trait UnixUdpBuilderExt { /// Set value for the `SO_REUSEPORT` option on this socket. /// - /// This indicates that futher calls to `bind` may allow reuse of local + /// This indicates that further calls to `bind` may allow reuse of local /// addresses. For IPv4 sockets this means that a socket may bind even when /// there's a socket already listening on this port. fn reuse_port(&self, reuse: bool) -> io::Result<&Self>;