Skip to content

Commit

Permalink
Merge pull request tokio-rs#3 from fortanix/raoul/sgx-port-0.8.11
Browse files Browse the repository at this point in the history
SGX support for v0.8.11
  • Loading branch information
raoulstrackx authored Mar 27, 2024
2 parents 0328bde + dacd623 commit 8f20ee7
Show file tree
Hide file tree
Showing 25 changed files with 1,582 additions and 52 deletions.
14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,20 @@ features = [
wasi = "0.11.0"
libc = "0.2.149"

[target.x86_64-fortanix-unknown-sgx.dependencies]
async-usercalls = "0.5"
crossbeam-channel = "0.5"

[patch.crates-io]
async-usercalls = { git = "https://github.com/fortanix/rust-sgx.git", branch = "master" }

[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 +107,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");
}
}
17 changes: 17 additions & 0 deletions ct.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash -ex
export RUST_BACKTRACE=1

toolchains=("nightly-2023-05-07-x86_64-unknown-linux-gnu" "nightly-2024-02-20-x86_64-unknown-linux-gnu")
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
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 @@ -70,6 +71,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

0 comments on commit 8f20ee7

Please sign in to comment.