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

SGX port v0.8.9 #1

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,17 @@ features = [
wasi = "0.11.0"
libc = "0.2.149"

[target.x86_64-fortanix-unknown-sgx.dependencies]
async-usercalls = { git = "https://github.com/fortanix/rust-sgx.git", branch = "master" } # FIXME: use published version once available
crossbeam-channel = "0.5"

[dev-dependencies]
env_logger = { version = "0.9.3", default-features = false }
rand = "0.8"

[build-dependencies]
rustc_version = "0.2"

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]
Expand Down Expand Up @@ -97,3 +104,7 @@ required-features = ["os-poll", "net"]
[[example]]
name = "udp_server"
required-features = ["os-poll", "net"]

# set number of threads so tests can run properly
[package.metadata.fortanix-sgx]
threads = 100
7 changes: 7 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use rustc_version::Version;

fn main() {
if Version::parse("1.78.0").unwrap() <= rustc_version::version().unwrap() {
println!("cargo:rustc-cfg=compiler_has_send_sgx_types");
}
}
18 changes: 18 additions & 0 deletions ct.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash -ex
export RUST_BACKTRACE=1
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is part of the "local CI" commit and may be removed before upstreaming


toolchains=("my_sgx_build" "nightly")
platforms=("x86_64-fortanix-unknown-sgx" "x86_64-unknown-linux-gnu")

for toolchain in "${toolchains[@]}"; do
for platform in "${platforms[@]}"; do
echo "toolchain: $toolchain"
echo "platform: $platform"
echo ""
cargo +${toolchain} test --target ${platform}
cargo +${toolchain} test --features "net,os-poll" --target ${platform}
cargo +${toolchain} test --features "net,os-ext" --target ${platform}
cargo +${toolchain} test --features "net,os-poll,os-ext" --target ${platform}
done
done
exit 0
7 changes: 7 additions & 0 deletions examples/tcp_listenfd_server.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg_attr(target_env = "sgx", feature(sgx_platform))]

// You can run this example from the root of the mio repo:
// cargo run --example tcp_listenfd_server --features="os-poll net"
// or with wasi:
Expand All @@ -23,7 +25,12 @@ fn get_first_listen_fd_listener() -> Option<std::net::TcpListener> {
use std::os::unix::io::FromRawFd;
#[cfg(target_os = "wasi")]
use std::os::wasi::io::FromRawFd;
#[cfg(target_env = "sgx")]
use std::os::fortanix_sgx::io::FromRawFd;

#[cfg(target_env = "sgx")]
let stdlistener = unsafe { std::net::TcpListener::from_raw_fd(3, Default::default()) };
#[cfg(not(target_env = "sgx"))]
let stdlistener = unsafe { std::net::TcpListener::from_raw_fd(3) };
stdlistener.set_nonblocking(true).unwrap();
Some(stdlistener)
Expand Down
17 changes: 13 additions & 4 deletions examples/udp_server.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
// You can run this example from the root of the mio repo:
// cargo run --example udp_server --features="os-poll net"
use log::warn;
use mio::{Events, Interest, Poll, Token};
use std::io;
#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
use {
log::warn,
mio::{Events, Interest, Poll, Token},
std::io,
};

// A token to allow us to identify which event is for the `UdpSocket`.
#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
const UDP_SOCKET: Token = Token(0);

#[cfg(not(target_os = "wasi"))]
#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
fn main() -> io::Result<()> {
use mio::net::UdpSocket;

Expand Down Expand Up @@ -84,6 +88,11 @@ fn main() -> io::Result<()> {
}
}

#[cfg(target_env = "sgx")]
fn main() {
println!("SGX does not support UDP yet");
}

#[cfg(target_os = "wasi")]
fn main() {
panic!("can't bind to an address with wasi")
Expand Down
5 changes: 4 additions & 1 deletion src/io_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::ops::{Deref, DerefMut};
use std::os::unix::io::AsRawFd;
#[cfg(target_os = "wasi")]
use std::os::wasi::io::AsRawFd;
#[cfg(target_env = "sgx")]
use std::os::fortanix_sgx::io::AsRawFd;
#[cfg(windows)]
use std::os::windows::io::AsRawSocket;
#[cfg(debug_assertions)]
Expand Down Expand Up @@ -102,6 +104,7 @@ impl<T> IoSource<T> {
/// [`deregister`] it.
///
/// [`deregister`]: Registry::deregister
#[cfg(not(target_env = "sgx"))]
pub fn into_inner(self) -> T {
self.inner
}
Expand Down Expand Up @@ -129,7 +132,7 @@ impl<T> DerefMut for IoSource<T> {
}
}

#[cfg(unix)]
#[cfg(any(unix, target_env = "sgx"))]
impl<T> event::Source for IoSource<T>
where
T: AsRawFd,
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg_attr(compiler_has_send_sgx_types, feature(stmt_expr_attributes))]
#![cfg_attr(not(compiler_has_send_sgx_types), allow(suspicious_auto_trait_impls))]
#![deny(
missing_docs,
missing_debug_implementations,
Expand All @@ -10,6 +12,7 @@
#![cfg_attr(test, deny(warnings))]
// Disallow warnings in examples.
#![doc(test(attr(deny(warnings))))]
#![cfg_attr(target_env = "sgx", feature(sgx_platform))]

//! Mio is a fast, low-level I/O library for Rust focusing on non-blocking APIs
//! and event notification for building high performance I/O apps with as little
Expand Down
4 changes: 2 additions & 2 deletions src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
mod tcp;
pub use self::tcp::{TcpListener, TcpStream};

#[cfg(not(target_os = "wasi"))]
#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
mod udp;
#[cfg(not(target_os = "wasi"))]
#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
pub use self::udp::UdpSocket;

#[cfg(unix)]
Expand Down
72 changes: 49 additions & 23 deletions src/net/tcp/listener.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#[cfg(target_env = "sgx")]
use crate::sys::tcp::net::{self, SocketAddr};
#[cfg(not(target_env = "sgx"))]
use std::net::{self, SocketAddr};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
Expand All @@ -11,7 +14,7 @@ use crate::io_source::IoSource;
use crate::net::TcpStream;
#[cfg(unix)]
use crate::sys::tcp::set_reuseaddr;
#[cfg(not(target_os = "wasi"))]
#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
use crate::sys::tcp::{bind, listen, new_for_addr};
use crate::{event, sys, Interest, Registry, Token};

Expand Down Expand Up @@ -57,25 +60,42 @@ impl TcpListener {
/// 4. Calls `listen` on the socket to prepare it to receive new connections.
#[cfg(not(target_os = "wasi"))]
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
let listener = unsafe { TcpListener::from_raw_fd(socket) };
#[cfg(windows)]
let listener = unsafe { TcpListener::from_raw_socket(socket as _) };

// On platforms with Berkeley-derived sockets, this allows to quickly
// rebind a socket, without needing to wait for the OS to clean up the
// previous one.
//
// On Windows, this allows rebinding sockets which are actively in use,
// which allows “socket hijacking”, so we explicitly don't set it here.
// https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
#[cfg(not(windows))]
set_reuseaddr(&listener.inner, true)?;

bind(&listener.inner, addr)?;
listen(&listener.inner, 1024)?;
Ok(listener)
#[cfg(not(target_env = "sgx"))] {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
let listener = unsafe { TcpListener::from_raw_fd(socket) };
#[cfg(windows)]
let listener = unsafe { TcpListener::from_raw_socket(socket as _) };

// On platforms with Berkeley-derived sockets, this allows to quickly
// rebind a socket, without needing to wait for the OS to clean up the
// previous one.
//
// On Windows, this allows rebinding sockets which are actively in use,
// which allows “socket hijacking”, so we explicitly don't set it here.
// https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
#[cfg(not(windows))]
set_reuseaddr(&listener.inner, true)?;

bind(&listener.inner, addr)?;
listen(&listener.inner, 1024)?;
Ok(listener)
}

#[cfg(target_env = "sgx")] {
Ok(TcpListener {
inner: IoSource::new(sys::tcp::bind(addr)?),
})
}
}

/// Convenience method to bind a new TCP listener to the specified address
/// to receive new connections.
#[cfg(target_env = "sgx")]
pub fn bind_str(addr: &str) -> io::Result<TcpListener> {
Ok(TcpListener {
inner: IoSource::new(sys::tcp::bind_str(addr)?),
})
}

/// Creates a new `TcpListener` from a standard `net::TcpListener`.
Expand All @@ -84,9 +104,9 @@ impl TcpListener {
/// standard library in the Mio equivalent. The conversion assumes nothing
/// about the underlying listener; ; it is left up to the user to set it
/// in non-blocking mode.
pub fn from_std(listener: net::TcpListener) -> TcpListener {
pub fn from_std(listener: std::net::TcpListener) -> TcpListener {
TcpListener {
inner: IoSource::new(listener),
inner: IoSource::new(listener.into()),
}
}

Expand All @@ -100,7 +120,13 @@ impl TcpListener {
/// returned along with it.
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
self.inner.do_io(|inner| {
sys::tcp::accept(inner).map(|(stream, addr)| (TcpStream::from_std(stream), addr))
sys::tcp::accept(inner).map(|(stream, addr)| {
#[cfg(target_env = "sgx")]
let stream = TcpStream::internal_new(stream);
#[cfg(not(target_env = "sgx"))]
let stream = TcpStream::from_std(stream);
(stream, addr)
})
})
}

Expand Down
46 changes: 37 additions & 9 deletions src/net/tcp/stream.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::fmt;
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
#[cfg(target_env = "sgx")]
use crate::sys::tcp::net::{self, Shutdown, SocketAddr};
#[cfg(not(target_env = "sgx"))]
use std::net::{self, Shutdown, SocketAddr};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
Expand All @@ -9,9 +12,11 @@ use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};

use crate::io_source::IoSource;
#[cfg(not(target_os = "wasi"))]
#[cfg(not(any(target_os = "wasi", target_env = "sgx")))]
use crate::sys::tcp::{connect, new_for_addr};
use crate::{event, Interest, Registry, Token};
#[cfg(target_env = "sgx")]
use crate::sys;

/// A non-blocking TCP stream between a local socket and a remote socket.
///
Expand Down Expand Up @@ -50,6 +55,13 @@ pub struct TcpStream {
}

impl TcpStream {
#[cfg(target_env = "sgx")]
pub(crate) fn internal_new(stream: sys::tcp::TcpStream) -> TcpStream {
TcpStream {
inner: IoSource::new(stream),
}
}

/// Create a new TCP stream and issue a non-blocking connect to the
/// specified address.
///
Expand Down Expand Up @@ -82,13 +94,26 @@ impl TcpStream {
/// [write interest]: Interest::WRITABLE
#[cfg(not(target_os = "wasi"))]
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
let stream = unsafe { TcpStream::from_raw_fd(socket) };
#[cfg(windows)]
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
connect(&stream.inner, addr)?;
Ok(stream)
#[cfg(not(target_env = "sgx"))] {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
let stream = unsafe { TcpStream::from_raw_fd(socket) };
#[cfg(windows)]
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
connect(&stream.inner, addr)?;
Ok(stream)
}

#[cfg(target_env = "sgx")] {
sys::tcp::connect(addr).map(TcpStream::internal_new)
}
}

/// Create a new TCP stream and issue a non-blocking connect to the
/// specified address.
#[cfg(target_env = "sgx")]
pub fn connect_str(addr: &str) -> io::Result<TcpStream> {
sys::tcp::connect_str(addr).map(TcpStream::internal_new)
}

/// Creates a new `TcpStream` from a standard `net::TcpStream`.
Expand All @@ -103,7 +128,10 @@ impl TcpStream {
/// The TCP stream here will not have `connect` called on it, so it
/// should already be connected via some other means (be it manually, or
/// the standard library).
pub fn from_std(stream: net::TcpStream) -> TcpStream {
pub fn from_std(stream: std::net::TcpStream) -> TcpStream {
#[cfg(target_env = "sgx")]
let stream: sys::tcp::TcpStream = stream.into();

TcpStream {
inner: IoSource::new(stream),
}
Expand Down
7 changes: 7 additions & 0 deletions src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//! * `tcp` and `udp` modules: see the [`crate::net`] module.
//! * `Waker`: see [`crate::Waker`].

#[cfg(not(target_env = "sgx"))]
cfg_os_poll! {
macro_rules! debug_detail {
(
Expand Down Expand Up @@ -69,6 +70,12 @@ cfg_os_poll! {
pub(crate) use self::wasi::*;
}

#[cfg(target_env = "sgx")]
cfg_os_poll! {
mod sgx;
pub(crate) use self::sgx::*;
}

cfg_not_os_poll! {
mod shell;
pub(crate) use self::shell::*;
Expand Down
Loading