Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extend network support for HermitCore #73331

Merged
merged 11 commits into from
Jun 15, 2020
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1434,9 +1434,9 @@ dependencies = [

[[package]]
name = "hermit-abi"
version = "0.1.13"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
dependencies = [
"compiler_builtins",
"libc",
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }

[target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies]
hermit-abi = { version = "0.1.13", features = ['rustc-dep-of-std'] }
hermit-abi = { version = "0.1.14", features = ['rustc-dep-of-std'] }

[target.wasm32-wasi.dependencies]
wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }
Expand Down
151 changes: 105 additions & 46 deletions src/libstd/sys/hermit/net.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::convert::TryFrom;
use crate::fmt;
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::str;
use crate::sync::Arc;
use crate::sys::hermit::abi;
use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6};
use crate::sys::{unsupported, Void};
use crate::sys_common::AsInner;
use crate::time::Duration;

/// Checks whether the HermitCore's socket interface has been started already, and
Expand All @@ -17,14 +20,31 @@ pub fn init() -> io::Result<()> {
Ok(())
}

pub struct TcpStream(abi::Handle);
#[derive(Debug, Clone)]
pub struct Socket(abi::Handle);

impl AsInner<abi::Handle> for Socket {
fn as_inner(&self) -> &abi::Handle {
&self.0
}
}

impl Drop for Socket {
fn drop(&mut self) {
let _ = abi::tcpstream::close(self.0);
}
}


#[derive(Clone)]
pub struct TcpStream(Arc<Socket>);
kennytm marked this conversation as resolved.
Show resolved Hide resolved

impl TcpStream {
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
let addr = addr?;

match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
Ok(handle) => Ok(TcpStream(handle)),
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => {
Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
}
Expand All @@ -37,39 +57,42 @@ impl TcpStream {
saddr.port(),
Some(duration.as_millis() as u64),
) {
Ok(handle) => Ok(TcpStream(handle)),
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => {
Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
}
}
}

pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
abi::tcpstream::set_read_timeout(self.0, duration.map(|d| d.as_millis() as u64))
abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
}

pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
abi::tcpstream::set_write_timeout(self.0, duration.map(|d| d.as_millis() as u64))
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
abi::tcpstream::set_write_timeout(
*self.0.as_inner(),
duration.map(|d| d.as_millis() as u64),
)
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
}

pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
let duration = abi::tcpstream::get_read_timeout(self.0)
let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;

Ok(duration.map(|d| Duration::from_millis(d)))
}

pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
let duration = abi::tcpstream::get_write_timeout(self.0)
let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;

Ok(duration.map(|d| Duration::from_millis(d)))
}

pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
abi::tcpstream::peek(self.0, buf)
abi::tcpstream::peek(*self.0.as_inner(), buf)
.map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
}

Expand All @@ -81,18 +104,11 @@ impl TcpStream {
let mut size: usize = 0;

for i in ioslice.iter_mut() {
let mut pos: usize = 0;

while pos < i.len() {
let ret = abi::tcpstream::read(self.0, &mut i[pos..])
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;

if ret == 0 {
return Ok(size);
} else {
size += ret;
pos += ret;
}
let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..])
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;

if ret != 0 {
size += ret;
}
}

Expand All @@ -112,7 +128,7 @@ impl TcpStream {
let mut size: usize = 0;

for i in ioslice.iter() {
size += abi::tcpstream::write(self.0, i)
size += abi::tcpstream::write(*self.0.as_inner(), i)
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?;
}

Expand All @@ -125,42 +141,64 @@ impl TcpStream {
}

pub fn peer_addr(&self) -> io::Result<SocketAddr> {
Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported"))
let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?;

let saddr = match ipaddr {
Ipv4(ref addr) => SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
IpAddr::V4(Ipv4Addr::from(addr.0)),

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolving in #73389 .

port,
),
Ipv6(ref addr) => SocketAddr::new(
IpAddr::V6(Ipv6Addr::new(
((addr.0[0] as u16) << 8) | addr.0[1] as u16,
((addr.0[2] as u16) << 8) | addr.0[3] as u16,
((addr.0[4] as u16) << 8) | addr.0[5] as u16,
((addr.0[6] as u16) << 8) | addr.0[7] as u16,
((addr.0[8] as u16) << 8) | addr.0[9] as u16,
((addr.0[10] as u16) << 8) | addr.0[11] as u16,
((addr.0[12] as u16) << 8) | addr.0[13] as u16,
((addr.0[14] as u16) << 8) | addr.0[15] as u16)),
kennytm marked this conversation as resolved.
Show resolved Hide resolved
port,
),
_ => {
return Err(io::Error::new(ErrorKind::Other, "peer_addr failed"));
},
};

Ok(saddr)
}

pub fn socket_addr(&self) -> io::Result<SocketAddr> {
Err(io::Error::new(ErrorKind::Other, "socket_addr isn't supported"))
}

pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
abi::tcpstream::shutdown(self.0, how as i32)
abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket"))
}

pub fn duplicate(&self) -> io::Result<TcpStream> {
let handle = abi::tcpstream::duplicate(self.0)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to duplicate stream"))?;

Ok(TcpStream(handle))
Ok(self.clone())
}

pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nodelay(self.0, mode)
abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
.map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
}

pub fn nodelay(&self) -> io::Result<bool> {
abi::tcpstream::nodelay(self.0)
abi::tcpstream::nodelay(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed"))
}

pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
abi::tcpstream::set_tll(self.0, tll)
abi::tcpstream::set_tll(*self.0.as_inner(), tll)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL"))
}

pub fn ttl(&self) -> io::Result<u32> {
abi::tcpstream::get_tll(self.0)
abi::tcpstream::get_tll(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL"))
}

Expand All @@ -169,40 +207,61 @@ impl TcpStream {
}

pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nonblocking(self.0, mode)
abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode"))
}
}

impl Drop for TcpStream {
fn drop(&mut self) {
let _ = abi::tcpstream::close(self.0);
}
}

impl fmt::Debug for TcpStream {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}

pub struct TcpListener(abi::Handle);
#[derive(Clone)]
pub struct TcpListener(SocketAddr);

impl TcpListener {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
let addr = addr?;

Ok(TcpListener(*addr))
}

pub fn socket_addr(&self) -> io::Result<SocketAddr> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
Ok(self.0)
}

pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
.map_err(|_| io::Error::new(ErrorKind::Other, "accept failed"))?;
let saddr = match ipaddr {
Ipv4(ref addr) => SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
IpAddr::V4(Ipv4Addr::from(addr.0)),

port,
),
Ipv6(ref addr) => SocketAddr::new(
IpAddr::V6(Ipv6Addr::new(
((addr.0[0] as u16) << 8) | addr.0[1] as u16,
kennytm marked this conversation as resolved.
Show resolved Hide resolved
((addr.0[2] as u16) << 8) | addr.0[3] as u16,
((addr.0[4] as u16) << 8) | addr.0[5] as u16,
((addr.0[6] as u16) << 8) | addr.0[7] as u16,
((addr.0[8] as u16) << 8) | addr.0[9] as u16,
((addr.0[10] as u16) << 8) | addr.0[11] as u16,
((addr.0[12] as u16) << 8) | addr.0[13] as u16,
((addr.0[14] as u16) << 8) | addr.0[15] as u16)),
port,
),
_ => {
return Err(io::Error::new(ErrorKind::Other, "accept failed"));
},
};

Ok((TcpStream(Arc::new(Socket(handle))), saddr))
}

pub fn duplicate(&self) -> io::Result<TcpListener> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
Ok(self.clone())
}

pub fn set_ttl(&self, _: u32) -> io::Result<()> {
Expand Down