From ec7f0819dd5aec60bfa719b2f3d5cefa134e2e04 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 16 Feb 2020 08:11:34 +0100 Subject: [PATCH 1/7] increase version number of hermit-abi/backtrace to enable network support --- Cargo.lock | 8 +++----- src/libstd/Cargo.toml | 5 +++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45a1a169be446..2d3e0bc96f428 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,9 +115,9 @@ checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" [[package]] name = "backtrace" -version = "0.3.40" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +checksum = "b4b1549d804b6c73f4817df2ba073709e96e426f12987127c48e6745568c350b" dependencies = [ "backtrace-sys", "cfg-if", @@ -1364,9 +1364,7 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b8f315b98f415780ddbe9163c7dbbc5a07225b6d102ace1d8aeef85775140" +version = "0.1.6" dependencies = [ "compiler_builtins", "libc", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index a22e162bbff48..21b13176cf201 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -27,7 +27,7 @@ hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-de [dependencies.backtrace_rs] package = "backtrace" -version = "0.3.37" +version = "0.3.42" default-features = false # without the libstd `backtrace` feature, stub out everything features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd @@ -51,7 +51,8 @@ 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", features = ['rustc-dep-of-std'] } +hermit-abi = { path = "/home/stefan/share/rusty-hermit/hermit-abi", features = ['rustc-dep-of-std'] } +#hermit-abi = { version = "0.1", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false } From d78f3775d12056e6f6ebb28e04871f7a7297dc58 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 16 Feb 2020 08:14:04 +0100 Subject: [PATCH 2/7] add helper function to initialize network stack --- src/libstd/sys/hermit/mod.rs | 6 +- src/libstd/sys/hermit/net.rs | 171 ++++++++++++++++++++--------------- 2 files changed, 100 insertions(+), 77 deletions(-) diff --git a/src/libstd/sys/hermit/mod.rs b/src/libstd/sys/hermit/mod.rs index 1e4a53abdc7bd..317818726007a 100644 --- a/src/libstd/sys/hermit/mod.rs +++ b/src/libstd/sys/hermit/mod.rs @@ -92,11 +92,7 @@ pub unsafe extern "C" fn __rust_abort() { } #[cfg(not(test))] -pub fn init() { - unsafe { - let _ = net::init(); - } -} +pub fn init() {} #[cfg(not(test))] #[no_mangle] diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 82917e71be1f8..ead873483c2ac 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -1,291 +1,316 @@ use crate::convert::TryFrom; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut, ErrorKind}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::str; +use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sys::hermit::abi; use crate::sys::{unsupported, Void}; use crate::time::Duration; -//// Iinitializes HermitCore's network stack -pub unsafe fn init() -> io::Result<()> { +/// Checks whether the HermitCore's socket interface has been started already, and +/// if not, starts it. +fn init() -> io::Result<()> { + static START: AtomicBool = AtomicBool::new(false); + + if START.swap(true, Ordering::SeqCst) == false { + if abi::network_init() < 0 { + return Err(io::Error::new(ErrorKind::Other, "Unable to initialize network interface")); + } + } + Ok(()) } -pub struct TcpStream(Void); +pub struct TcpStream(i32); impl TcpStream { - pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { - unsupported() + pub fn connect(result_addr: io::Result<&SocketAddr>) -> io::Result { + init()?; + + // unpack socker address + if result_addr.is_err() { + return Err(result_addr.unwrap_err()); + } + let _saddr = result_addr.unwrap(); + + Ok(TcpStream(0)) } pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result { - unsupported() + init()?; + + Ok(TcpStream(0)) } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn read_timeout(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn write_timeout(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peek(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn read(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn write(&self, _: &[u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peer_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn duplicate(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn nodelay(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn ttl(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn take_error(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } } impl fmt::Debug for TcpStream { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + Ok(()) } } -pub struct TcpListener(Void); +pub struct TcpListener(i32); impl TcpListener { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - unsupported() + init()?; + + Ok(TcpListener(0)) } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn duplicate(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn ttl(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn only_v6(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn take_error(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } } impl fmt::Debug for TcpListener { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + Ok(()) } } -pub struct UdpSocket(Void); +pub struct UdpSocket(i32); impl UdpSocket { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - unsupported() + init()?; + + Ok(UdpSocket(0)) } pub fn peer_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn socket_addr(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn duplicate(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn read_timeout(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn write_timeout(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn broadcast(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn multicast_loop_v4(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn multicast_ttl_v4(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn multicast_loop_v6(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn ttl(&self) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn take_error(&self) -> io::Result> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn recv(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peek(&self, _: &mut [u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn send(&self, _: &[u8]) -> io::Result { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - match self.0 {} + Err(io::Error::new(ErrorKind::Other, "not supported")) } } impl fmt::Debug for UdpSocket { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} + Ok(()) } } @@ -316,6 +341,8 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost { type Error = io::Error; fn try_from(_v: (&'a str, u16)) -> io::Result { + init()?; + unsupported() } } From 80e7d1fec367678aa3d802b5eed639ff433bfbc9 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 23 Feb 2020 19:32:56 +0100 Subject: [PATCH 3/7] add basic IP support in HermitCore - add initial version to support sockets - use TcpStream as test case - HermitCore uses smoltcp as IP stack for pure Rust applications --- Cargo.lock | 2 +- src/libstd/Cargo.toml | 3 +- src/libstd/sys/hermit/mod.rs | 4 +- src/libstd/sys/hermit/net.rs | 158 +++++++++++++++++++++-------------- 4 files changed, 102 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07196ba92fcc0..513c0c74b8892 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1369,7 +1369,7 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.6" +version = "0.1.8" dependencies = [ "compiler_builtins", "libc", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 798899fc0a874..b147aa55b2a61 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -41,8 +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 = { path = "/home/stefan/share/rusty-hermit/hermit-abi", features = ['rustc-dep-of-std'] } -#hermit-abi = { version = "0.1", features = ['rustc-dep-of-std'] } +hermit-abi = { version = "0.1", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false } diff --git a/src/libstd/sys/hermit/mod.rs b/src/libstd/sys/hermit/mod.rs index 317818726007a..958532b8fc4b2 100644 --- a/src/libstd/sys/hermit/mod.rs +++ b/src/libstd/sys/hermit/mod.rs @@ -92,7 +92,9 @@ pub unsafe extern "C" fn __rust_abort() { } #[cfg(not(test))] -pub fn init() {} +pub fn init() { + let _ = net::init(); +} #[cfg(not(test))] #[no_mangle] diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index ead873483c2ac..4755f85c565a3 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -3,120 +3,162 @@ use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut, ErrorKind}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::str; -use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::hermit::abi; use crate::sys::{unsupported, Void}; use crate::time::Duration; /// Checks whether the HermitCore's socket interface has been started already, and /// if not, starts it. -fn init() -> io::Result<()> { - static START: AtomicBool = AtomicBool::new(false); - - if START.swap(true, Ordering::SeqCst) == false { - if abi::network_init() < 0 { - return Err(io::Error::new(ErrorKind::Other, "Unable to initialize network interface")); - } +pub fn init() -> io::Result<()> { + if abi::network_init() < 0 { + return Err(io::Error::new(ErrorKind::Other, "Unable to initialize network interface")); } Ok(()) } -pub struct TcpStream(i32); +pub struct TcpStream(abi::Handle); impl TcpStream { - pub fn connect(result_addr: io::Result<&SocketAddr>) -> io::Result { - init()?; + pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { + let addr = addr?; - // unpack socker address - if result_addr.is_err() { - return Err(result_addr.unwrap_err()); + match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { + Ok(handle) => Ok(TcpStream(handle)), + _ => Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")), } - let _saddr = result_addr.unwrap(); - - Ok(TcpStream(0)) } - pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result { - init()?; - - Ok(TcpStream(0)) + pub fn connect_timeout(saddr: &SocketAddr, duration: Duration) -> io::Result { + match abi::tcpstream::connect(saddr.ip().to_string().as_bytes(), saddr.port(), Some(duration.as_millis() as u64)) { + Ok(handle) => Ok(TcpStream(handle)), + _ => Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")), + } } - pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn set_read_timeout(&self, duration: Option) -> io::Result<()> { + abi::tcpstream::set_read_timeout(self.0, 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, _: Option) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn set_write_timeout(&self, duration: Option) -> 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")) } pub fn read_timeout(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + let duration = abi::tcpstream::get_read_timeout(self.0) + .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> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + let duration = abi::tcpstream::get_write_timeout(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; + + Ok(duration.map(|d| Duration::from_millis(d))) } - pub fn peek(&self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + abi::tcpstream::peek(self.0, buf) + .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) } - pub fn read(&self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn read(&self, buffer: &mut [u8]) -> io::Result { + self.read_vectored(&mut [IoSliceMut::new(buffer)]) } - pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn read_vectored(&self, ioslice: &mut [IoSliceMut<'_>]) -> io::Result { + 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; + } + } + } + + Ok(size) } - pub fn write(&self, _: &[u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn write(&self, buffer: &[u8]) -> io::Result { + self.write_vectored(&[IoSlice::new(buffer)]) } - pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn write_vectored(&self, ioslice: &[IoSlice<'_>]) -> io::Result { + let mut size: usize = 0; + + for i in ioslice.iter() { + size += abi::tcpstream::write(self.0, i) + .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?; + } + + Ok(size) } pub fn peer_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported")) } pub fn socket_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new(ErrorKind::Other, "socket_addr isn't supported")) } - pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + abi::tcpstream::shutdown(self.0, how as i32) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket")) } pub fn duplicate(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + let handle = abi::tcpstream::duplicate(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to duplicate stream"))?; + + Ok(TcpStream(handle)) } - pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { + abi::tcpstream::set_nodelay(self.0, mode) + .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) } pub fn nodelay(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + abi::tcpstream::nodelay(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed")) } - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn set_ttl(&self, tll: u32) -> io::Result<()> { + abi::tcpstream::set_tll(self.0, tll) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL")) } pub fn ttl(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + abi::tcpstream::get_tll(self.0) + .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL")) } pub fn take_error(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new(ErrorKind::Other, "take_error isn't supported")) } - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { + abi::tcpstream::set_nonblocking(self.0, 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); } } @@ -126,13 +168,11 @@ impl fmt::Debug for TcpStream { } } -pub struct TcpListener(i32); +pub struct TcpListener(abi::Handle); impl TcpListener { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - init()?; - - Ok(TcpListener(0)) + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn socket_addr(&self) -> io::Result { @@ -178,13 +218,11 @@ impl fmt::Debug for TcpListener { } } -pub struct UdpSocket(i32); +pub struct UdpSocket(abi::Handle); impl UdpSocket { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - init()?; - - Ok(UdpSocket(0)) + Err(io::Error::new(ErrorKind::Other, "not supported")) } pub fn peer_addr(&self) -> io::Result { @@ -341,8 +379,6 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost { type Error = io::Error; fn try_from(_v: (&'a str, u16)) -> io::Result { - init()?; - unsupported() } } From 41f57dcf3e6a44600995d8ed5ce7a01391b678ae Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 23 Feb 2020 19:54:05 +0100 Subject: [PATCH 4/7] add missing update of Cargo.lock --- Cargo.lock | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index bde17ecc931c4..5ff6fce655fd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1370,6 +1370,8 @@ dependencies = [ [[package]] name = "hermit-abi" version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" dependencies = [ "compiler_builtins", "libc", From fc0f2d42dea0db1c8376aa3e5a25fd1114246bed Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 23 Feb 2020 20:12:06 +0100 Subject: [PATCH 5/7] fix coding style to pass rustfmt tests --- src/libstd/sys/hermit/net.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs index 4755f85c565a3..377c3132c5a32 100644 --- a/src/libstd/sys/hermit/net.rs +++ b/src/libstd/sys/hermit/net.rs @@ -1,6 +1,6 @@ use crate::convert::TryFrom; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut, ErrorKind}; +use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::str; use crate::sys::hermit::abi; @@ -24,15 +24,23 @@ impl TcpStream { let addr = addr?; match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { - Ok(handle) => Ok(TcpStream(handle)), - _ => Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")), + Ok(handle) => Ok(TcpStream(handle)), + _ => { + Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) + } } } pub fn connect_timeout(saddr: &SocketAddr, duration: Duration) -> io::Result { - match abi::tcpstream::connect(saddr.ip().to_string().as_bytes(), saddr.port(), Some(duration.as_millis() as u64)) { - Ok(handle) => Ok(TcpStream(handle)), - _ => Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")), + match abi::tcpstream::connect( + saddr.ip().to_string().as_bytes(), + saddr.port(), + Some(duration.as_millis() as u64), + ) { + Ok(handle) => Ok(TcpStream(handle)), + _ => { + Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) + } } } @@ -80,7 +88,7 @@ impl TcpStream { .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?; if ret == 0 { - return Ok(size) + return Ok(size); } else { size += ret; pos += ret; From 910ab5b3838b2de9f84e23095a03dffec24b0242 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 19 Mar 2020 07:43:16 +0100 Subject: [PATCH 6/7] remove unused imports --- src/libpanic_unwind/hermit.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libpanic_unwind/hermit.rs b/src/libpanic_unwind/hermit.rs index 6bded4dd499bd..69b9edb77c564 100644 --- a/src/libpanic_unwind/hermit.rs +++ b/src/libpanic_unwind/hermit.rs @@ -4,7 +4,6 @@ use alloc::boxed::Box; use core::any::Any; -use core::ptr; pub unsafe fn cleanup(_ptr: *mut u8) -> Box { extern "C" { From 3edea950511f2d43a8dc44f354694c8206c63375 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 19 Mar 2020 07:46:50 +0100 Subject: [PATCH 7/7] add basic support of OsStrExt --- src/libstd/os/mod.rs | 2 +- src/libstd/sys/hermit/ext/ffi.rs | 38 ++++++++++++++++++++++++++++++++ src/libstd/sys/hermit/ext/mod.rs | 14 ++++++++++++ src/libstd/sys/hermit/mod.rs | 1 + 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/libstd/sys/hermit/ext/ffi.rs create mode 100644 src/libstd/sys/hermit/ext/mod.rs diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 91e37ed833a4f..0fa4a1d2353ca 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -24,7 +24,7 @@ cfg_if::cfg_if! { // If we're not documenting libstd then we just expose the main modules // as we otherwise would. - #[cfg(any(target_os = "redox", unix, target_os = "vxworks"))] + #[cfg(any(target_os = "redox", unix, target_os = "vxworks", target_os = "hermit"))] #[stable(feature = "rust1", since = "1.0.0")] pub use crate::sys::ext as unix; diff --git a/src/libstd/sys/hermit/ext/ffi.rs b/src/libstd/sys/hermit/ext/ffi.rs new file mode 100644 index 0000000000000..07b59a02556d9 --- /dev/null +++ b/src/libstd/sys/hermit/ext/ffi.rs @@ -0,0 +1,38 @@ +//! HermitCore-specific extension to the primitives in the `std::ffi` module +//! +//! # Examples +//! +//! ``` +//! use std::ffi::OsString; +//! use std::os::hermit::ffi::OsStringExt; +//! +//! let bytes = b"foo".to_vec(); +//! +//! // OsStringExt::from_vec +//! let os_string = OsString::from_vec(bytes); +//! assert_eq!(os_string.to_str(), Some("foo")); +//! +//! // OsStringExt::into_vec +//! let bytes = os_string.into_vec(); +//! assert_eq!(bytes, b"foo"); +//! ``` +//! +//! ``` +//! use std::ffi::OsStr; +//! use std::os::hermit::ffi::OsStrExt; +//! +//! let bytes = b"foo"; +//! +//! // OsStrExt::from_bytes +//! let os_str = OsStr::from_bytes(bytes); +//! assert_eq!(os_str.to_str(), Some("foo")); +//! +//! // OsStrExt::as_bytes +//! let bytes = os_str.as_bytes(); +//! assert_eq!(bytes, b"foo"); +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::sys_common::os_str_bytes::*; diff --git a/src/libstd/sys/hermit/ext/mod.rs b/src/libstd/sys/hermit/ext/mod.rs new file mode 100644 index 0000000000000..ea87d0ad2c94d --- /dev/null +++ b/src/libstd/sys/hermit/ext/mod.rs @@ -0,0 +1,14 @@ +#![stable(feature = "rust1", since = "1.0.0")] +#![allow(missing_docs)] + +pub mod ffi; + +/// A prelude for conveniently writing platform-specific code. +/// +/// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod prelude { + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; +} diff --git a/src/libstd/sys/hermit/mod.rs b/src/libstd/sys/hermit/mod.rs index 958532b8fc4b2..4983b1430b3ef 100644 --- a/src/libstd/sys/hermit/mod.rs +++ b/src/libstd/sys/hermit/mod.rs @@ -21,6 +21,7 @@ pub mod args; pub mod cmath; pub mod condvar; pub mod env; +pub mod ext; pub mod fast_thread_local; pub mod fd; pub mod fs;