Skip to content

Commit

Permalink
Merge pull request #84 from rylev/wasi-scaffold
Browse files Browse the repository at this point in the history
Scaffold wasi support
  • Loading branch information
alexcrichton committed May 9, 2019
2 parents a3d51b3 + 60cb366 commit eda403f
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 20 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ 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"
Expand Down
86 changes: 72 additions & 14 deletions src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -55,10 +57,16 @@ 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<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int,
_payload: T) -> io::Result<()> {
Ok(())
}

#[cfg(not(target_os = "wasi"))]
pub fn set_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int,
payload: T) -> io::Result<()> {
unsafe {
Expand All @@ -67,10 +75,15 @@ pub fn set_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int,
let sock = sock as c_int;
try!(::cvt(setsockopt(sock, opt, val, payload as *const _,
mem::size_of::<T>() as socklen_t)));
Ok(())
}
Ok(())
}

#[cfg(target_os = "wasi")]
pub fn get_opt<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int) -> io::Result<T> {
unimplemented!()
}
#[cfg(not(target_os = "wasi"))]
pub fn get_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int) -> io::Result<T> {
unsafe {
let mut slot: T = mem::zeroed();
Expand Down Expand Up @@ -641,11 +654,7 @@ pub trait AsSock {
fn as_sock(&self) -> Socket;
}

#[cfg(target_os = "redox")]
impl<T: AsRawFd> AsSock for T {
fn as_sock(&self) -> Socket { self.as_raw_fd() }
}
#[cfg(unix)]
#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
impl<T: AsRawFd> AsSock for T {
fn as_sock(&self) -> Socket { self.as_raw_fd() }
}
Expand Down Expand Up @@ -750,6 +759,16 @@ impl TcpStreamExt for TcpStream {
Ok(Some((secs as u32) * 1000))
}

#[cfg(target_os = "wasi")]
fn set_keepalive_ms(&self, _keepalive: Option<u32>) -> io::Result<()> {
unimplemented!()
}

#[cfg(target_os = "wasi")]
fn keepalive_ms(&self) -> io::Result<Option<u32>> {
unimplemented!()
}

#[cfg(windows)]
fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
let ms = keepalive.unwrap_or(INFINITE);
Expand Down Expand Up @@ -872,7 +891,7 @@ impl TcpStreamExt for TcpStream {
}
}

#[cfg(any(target_os = "redox", unix))]
#[cfg(any(target_os = "redox", unix, target_os = "wasi"))]
fn ms2timeout(dur: Option<u32>) -> timeval {
// TODO: be more rigorous
match dur {
Expand All @@ -884,7 +903,7 @@ fn ms2timeout(dur: Option<u32>) -> timeval {
}
}

#[cfg(any(target_os = "redox", unix))]
#[cfg(any(target_os = "redox", unix, target_os = "wasi"))]
fn timeout2ms(dur: timeval) -> Option<u32> {
if dur.tv_sec == 0 && dur.tv_usec == 0 {
None
Expand Down Expand Up @@ -929,7 +948,7 @@ fn dur2linger(dur: Option<Duration>) -> linger {
}
}

#[cfg(any(target_os = "redox", unix))]
#[cfg(any(target_os = "redox", unix, target_os = "wasi"))]
fn dur2linger(dur: Option<Duration>) -> linger {
match dur {
Some(d) => {
Expand Down Expand Up @@ -1193,6 +1212,22 @@ impl UdpSocketExt for UdpSocket {
}
}

#[cfg(target_os = "wasi")]
fn send(&self, buf: &[u8]) -> io::Result<usize> {
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<usize> {
let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
Expand All @@ -1219,6 +1254,24 @@ impl UdpSocketExt for UdpSocket {
}
}

#[cfg(target_os = "wasi")]
fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
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<usize> {
let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
Expand Down Expand Up @@ -1270,6 +1323,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;
Expand All @@ -1289,7 +1347,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 {
Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions src/sys/wasi/impls.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
Loading

0 comments on commit eda403f

Please sign in to comment.