Skip to content

Commit 59b79f7

Browse files
author
Jethro Beekman
committed
SGX target: implement networking
1 parent 1a894f1 commit 59b79f7

File tree

2 files changed

+167
-53
lines changed

2 files changed

+167
-53
lines changed

src/libstd/sys/sgx/abi/usercalls/mod.rs

+55
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,61 @@ pub fn close(fd: Fd) {
5555
unsafe { raw::close(fd) }
5656
}
5757

58+
fn string_from_bytebuffer(buf: &alloc::UserRef<ByteBuffer>, usercall: &str, arg: &str) -> String {
59+
String::from_utf8(copy_user_buffer(buf))
60+
.unwrap_or_else(|_| panic!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
61+
}
62+
63+
pub fn bind_stream(addr: &str) -> IoResult<(Fd, String)> {
64+
unsafe {
65+
let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
66+
let mut local = alloc::User::<ByteBuffer>::uninitialized();
67+
let fd = raw::bind_stream(
68+
addr_user.as_ptr(),
69+
addr_user.len(),
70+
local.as_raw_mut_ptr()
71+
).from_sgx_result()?;
72+
let local = string_from_bytebuffer(&local, "bind_stream", "local_addr");
73+
Ok((fd, local))
74+
}
75+
}
76+
77+
pub fn accept_stream(fd: Fd) -> IoResult<(Fd, String, String)> {
78+
unsafe {
79+
let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
80+
let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
81+
// without forcing coercion?
82+
let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
83+
let fd = raw::accept_stream(
84+
fd,
85+
local.as_raw_mut_ptr(),
86+
peer.as_raw_mut_ptr()
87+
).from_sgx_result()?;
88+
let local = string_from_bytebuffer(&local, "accept_stream", "local_addr");
89+
let peer = string_from_bytebuffer(&peer, "accept_stream", "peer_addr");
90+
Ok((fd, local, peer))
91+
}
92+
}
93+
94+
pub fn connect_stream(addr: &str) -> IoResult<(Fd, String, String)> {
95+
unsafe {
96+
let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
97+
let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
98+
let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
99+
// without forcing coercion?
100+
let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
101+
let fd = raw::connect_stream(
102+
addr_user.as_ptr(),
103+
addr_user.len(),
104+
local.as_raw_mut_ptr(),
105+
peer.as_raw_mut_ptr()
106+
).from_sgx_result()?;
107+
let local = string_from_bytebuffer(&local, "connect_stream", "local_addr");
108+
let peer = string_from_bytebuffer(&peer, "connect_stream", "peer_addr");
109+
Ok((fd, local, peer))
110+
}
111+
}
112+
58113
pub fn launch_thread() -> IoResult<()> {
59114
unsafe { raw::launch_thread().from_sgx_result() }
60115
}

src/libstd/sys/sgx/net.rs

+112-53
Original file line numberDiff line numberDiff line change
@@ -10,144 +10,182 @@
1010

1111
use fmt;
1212
use io;
13-
use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
13+
use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr, ToSocketAddrs};
1414
use time::Duration;
15-
use sys::{unsupported, Void};
15+
use sys::{unsupported, Void, sgx_ineffective};
16+
use sys::fd::FileDesc;
1617
use convert::TryFrom;
18+
use error;
19+
use sync::Arc;
1720

18-
pub struct TcpStream(Void);
21+
use super::abi::usercalls;
22+
23+
const DEFAULT_FAKE_TTL: u32 = 64;
24+
25+
#[derive(Debug, Clone)]
26+
struct Socket {
27+
inner: Arc<FileDesc>,
28+
local_addr: String,
29+
}
30+
31+
impl Socket {
32+
fn new(fd: usercalls::Fd, local_addr: String) -> Socket {
33+
Socket { inner: Arc::new(FileDesc::new(fd)), local_addr }
34+
}
35+
}
36+
37+
#[derive(Debug, Clone)]
38+
pub struct TcpStream {
39+
inner: Socket,
40+
peer_addr: String,
41+
}
42+
43+
fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
44+
match result {
45+
Ok(saddr) => Ok(saddr.to_string()),
46+
// need to downcast twice because io::Error::into_inner doesn't return the original
47+
// value if the conversion fails
48+
Err(e) => if e.get_ref().and_then(|e| e.downcast_ref::<NonIpSockAddr>()).is_some() {
49+
Ok(e.into_inner().unwrap().downcast::<NonIpSockAddr>().unwrap().host)
50+
} else {
51+
Err(e)
52+
}
53+
}
54+
}
55+
56+
fn addr_to_sockaddr(addr: &str) -> io::Result<SocketAddr> {
57+
// unwrap OK: if an iterator is returned, we're guaranteed to get exactly one entry
58+
addr.to_socket_addrs().map(|mut it| it.next().unwrap())
59+
}
1960

2061
impl TcpStream {
21-
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
22-
unsupported()
62+
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
63+
let addr = io_err_to_addr(addr)?;
64+
let (fd, local_addr, peer_addr) = usercalls::connect_stream(&addr)?;
65+
Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr })
2366
}
2467

25-
pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
26-
unsupported()
68+
pub fn connect_timeout(addr: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
69+
Self::connect(Ok(addr)) // FIXME: ignoring timeout
2770
}
2871

2972
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
30-
match self.0 {}
73+
sgx_ineffective(())
3174
}
3275

3376
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
34-
match self.0 {}
77+
sgx_ineffective(())
3578
}
3679

3780
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
38-
match self.0 {}
81+
sgx_ineffective(None)
3982
}
4083

4184
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
42-
match self.0 {}
85+
sgx_ineffective(None)
4386
}
4487

4588
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
46-
match self.0 {}
89+
Ok(0)
4790
}
4891

49-
pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
50-
match self.0 {}
92+
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
93+
self.inner.inner.read(buf)
5194
}
5295

53-
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
54-
match self.0 {}
96+
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
97+
self.inner.inner.write(buf)
5598
}
5699

57100
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
58-
match self.0 {}
101+
addr_to_sockaddr(&self.peer_addr)
59102
}
60103

61104
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
62-
match self.0 {}
105+
addr_to_sockaddr(&self.inner.local_addr)
63106
}
64107

65108
pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
66-
match self.0 {}
109+
sgx_ineffective(())
67110
}
68111

69112
pub fn duplicate(&self) -> io::Result<TcpStream> {
70-
match self.0 {}
113+
Ok(self.clone())
71114
}
72115

73116
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
74-
match self.0 {}
117+
sgx_ineffective(())
75118
}
76119

77120
pub fn nodelay(&self) -> io::Result<bool> {
78-
match self.0 {}
121+
sgx_ineffective(false)
79122
}
80123

81124
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
82-
match self.0 {}
125+
sgx_ineffective(())
83126
}
84127

85128
pub fn ttl(&self) -> io::Result<u32> {
86-
match self.0 {}
129+
sgx_ineffective(DEFAULT_FAKE_TTL)
87130
}
88131

89132
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
90-
match self.0 {}
133+
Ok(None)
91134
}
92135

93136
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
94-
match self.0 {}
137+
sgx_ineffective(())
95138
}
96139
}
97140

98-
impl fmt::Debug for TcpStream {
99-
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
100-
match self.0 {}
101-
}
141+
#[derive(Debug, Clone)]
142+
pub struct TcpListener {
143+
inner: Socket,
102144
}
103145

104-
pub struct TcpListener(Void);
105-
106146
impl TcpListener {
107-
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
108-
unsupported()
147+
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
148+
let addr = io_err_to_addr(addr)?;
149+
let (fd, local_addr) = usercalls::bind_stream(&addr)?;
150+
Ok(TcpListener { inner: Socket::new(fd, local_addr) })
109151
}
110152

111153
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
112-
match self.0 {}
154+
addr_to_sockaddr(&self.inner.local_addr)
113155
}
114156

115157
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
116-
match self.0 {}
158+
let (fd, local_addr, peer_addr) = usercalls::accept_stream(self.inner.inner.raw())?;
159+
let ret_peer = addr_to_sockaddr(&peer_addr).unwrap_or_else(|_| ([0; 4], 0).into());
160+
Ok((TcpStream { inner: Socket::new(fd, local_addr), peer_addr }, ret_peer))
117161
}
118162

119163
pub fn duplicate(&self) -> io::Result<TcpListener> {
120-
match self.0 {}
164+
Ok(self.clone())
121165
}
122166

123167
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
124-
match self.0 {}
168+
sgx_ineffective(())
125169
}
126170

127171
pub fn ttl(&self) -> io::Result<u32> {
128-
match self.0 {}
172+
sgx_ineffective(DEFAULT_FAKE_TTL)
129173
}
130174

131175
pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
132-
match self.0 {}
176+
sgx_ineffective(())
133177
}
134178

135179
pub fn only_v6(&self) -> io::Result<bool> {
136-
match self.0 {}
180+
sgx_ineffective(false)
137181
}
138182

139183
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
140-
match self.0 {}
184+
Ok(None)
141185
}
142186

143187
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
144-
match self.0 {}
145-
}
146-
}
147-
148-
impl fmt::Debug for TcpListener {
149-
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
150-
match self.0 {}
188+
sgx_ineffective(())
151189
}
152190
}
153191

@@ -285,9 +323,30 @@ impl fmt::Debug for UdpSocket {
285323
}
286324
}
287325

326+
#[derive(Debug)]
327+
pub struct NonIpSockAddr {
328+
host: String
329+
}
330+
331+
impl error::Error for NonIpSockAddr {
332+
fn description(&self) -> &str {
333+
"Failed to convert address to SocketAddr"
334+
}
335+
}
336+
337+
impl fmt::Display for NonIpSockAddr {
338+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339+
write!(f, "Failed to convert address to SocketAddr: {}", self.host)
340+
}
341+
}
342+
288343
pub struct LookupHost(Void);
289344

290345
impl LookupHost {
346+
fn new(host: String) -> io::Result<LookupHost> {
347+
Err(io::Error::new(io::ErrorKind::Other, NonIpSockAddr { host }))
348+
}
349+
291350
pub fn port(&self) -> u16 {
292351
match self.0 {}
293352
}
@@ -303,16 +362,16 @@ impl Iterator for LookupHost {
303362
impl<'a> TryFrom<&'a str> for LookupHost {
304363
type Error = io::Error;
305364

306-
fn try_from(_v: &'a str) -> io::Result<LookupHost> {
307-
unsupported()
365+
fn try_from(v: &'a str) -> io::Result<LookupHost> {
366+
LookupHost::new(v.to_owned())
308367
}
309368
}
310369

311370
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
312371
type Error = io::Error;
313372

314-
fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
315-
unsupported()
373+
fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
374+
LookupHost::new(format!("{}:{}", host, port))
316375
}
317376
}
318377

0 commit comments

Comments
 (0)