implement SocketFile. pass socket test
This commit is contained in:
parent
0dda84d7f2
commit
5b90d90643
@ -64,7 +64,7 @@ fn parse_arguments(
|
||||
|
||||
// TODO: make sure do_boot can only be called once
|
||||
fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> {
|
||||
info!("boot: path: {:?}, argv: {:?}", path_str, argv);
|
||||
// info!("boot: path: {:?}, argv: {:?}", path_str, argv);
|
||||
util::mpx_util::mpx_enable()?;
|
||||
|
||||
let envp = std::vec::Vec::new();
|
||||
|
@ -39,6 +39,7 @@ impl fmt::Display for Error {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum Errno {
|
||||
EUNDEF = 0,
|
||||
EPERM = 1,
|
||||
@ -86,6 +87,14 @@ impl Errno {
|
||||
pub fn as_retval(&self) -> i32 {
|
||||
-(*self as i32)
|
||||
}
|
||||
pub fn from_retval(ret: i32) -> Self {
|
||||
let ret = if ret <= 0 && ret >= -39 {
|
||||
(-ret) as u8
|
||||
} else {
|
||||
0
|
||||
};
|
||||
unsafe { core::mem::transmute(ret) }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Errno {
|
||||
|
@ -3,8 +3,9 @@ use std;
|
||||
use std::borrow::BorrowMut;
|
||||
use std::fmt;
|
||||
use std::io::SeekFrom;
|
||||
use std::any::Any;
|
||||
|
||||
pub trait File: Debug + Sync + Send {
|
||||
pub trait File: Debug + Sync + Send + Any {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error>;
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error>;
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error>;
|
||||
@ -17,6 +18,7 @@ pub trait File: Debug + Sync + Send {
|
||||
fn sync_all(&self) -> Result<(), Error>;
|
||||
fn sync_data(&self) -> Result<(), Error>;
|
||||
fn read_entry(&self) -> Result<String, Error>;
|
||||
fn as_any(&self) -> &Any { unimplemented!() }
|
||||
}
|
||||
|
||||
pub type FileRef = Arc<Box<File>>;
|
||||
|
@ -9,12 +9,14 @@ use super::*;
|
||||
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
|
||||
pub use self::file_table::{FileDesc, FileTable};
|
||||
pub use self::inode_file::{INodeExt, INodeFile, ROOT_INODE};
|
||||
pub use self::socket_file::SocketFile;
|
||||
use self::inode_file::OpenOptions;
|
||||
pub use self::pipe::Pipe;
|
||||
|
||||
mod file;
|
||||
mod file_table;
|
||||
mod inode_file;
|
||||
mod socket_file;
|
||||
mod pipe;
|
||||
mod sgx_impl;
|
||||
|
||||
@ -206,6 +208,7 @@ pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
}
|
||||
|
||||
pub fn do_close(fd: FileDesc) -> Result<(), Error> {
|
||||
info!("close: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_table_ref = current_process.get_files();
|
||||
|
110
src/libos/src/fs/socket_file.rs
Normal file
110
src/libos/src/fs/socket_file.rs
Normal file
@ -0,0 +1,110 @@
|
||||
use super::*;
|
||||
use std::any::Any;
|
||||
|
||||
/// Native Linux socket
|
||||
#[derive(Debug)]
|
||||
pub struct SocketFile {
|
||||
fd: c_int,
|
||||
}
|
||||
|
||||
impl SocketFile {
|
||||
pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||
let ret = unsafe { libc::ocall::socket(domain, socket_type, protocol) };
|
||||
if ret < 0 {
|
||||
Err(Error::new(Errno::from_retval(ret as i32), ""))
|
||||
} else {
|
||||
Ok(SocketFile { fd: ret })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn accept(
|
||||
&self,
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
flags: c_int,
|
||||
) -> Result<Self, Error> {
|
||||
let ret = unsafe { libc::ocall::accept4(self.fd, addr, addr_len, flags) };
|
||||
if ret < 0 {
|
||||
Err(Error::new(Errno::from_retval(ret as i32), ""))
|
||||
} else {
|
||||
Ok(SocketFile { fd: ret })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> c_int {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SocketFile {
|
||||
fn drop(&mut self) {
|
||||
let ret = unsafe { libc::ocall::close(self.fd) };
|
||||
if ret < 0 {
|
||||
warn!("socket (host fd: {}) close failed", self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl File for SocketFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let ret = unsafe { libc::ocall::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len()) };
|
||||
if ret < 0 {
|
||||
Err(Error::new(Errno::from_retval(ret as i32), ""))
|
||||
} else {
|
||||
Ok(ret as usize)
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
let ret = unsafe { libc::ocall::write(self.fd, buf.as_ptr() as *const c_void, buf.len()) };
|
||||
if ret < 0 {
|
||||
Err(Error::new(Errno::from_retval(ret as i32), ""))
|
||||
} else {
|
||||
Ok(ret as usize)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
Err(Error::new(Errno::ESPIPE, "Socket does not support seek"))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &Any {
|
||||
self
|
||||
}
|
||||
}
|
@ -7,8 +7,7 @@
|
||||
//! 3. Dispatch the syscall to `do_*` (at this file)
|
||||
//! 4. Do some memory checks then call `mod::do_*` (at each module)
|
||||
|
||||
use fs::File;
|
||||
use fs::{off_t, FileDesc};
|
||||
use fs::{File, SocketFile, off_t, FileDesc, FileRef};
|
||||
use prelude::*;
|
||||
use process::{ChildProcessFilter, FileAction, pid_t, CloneFlags, FutexFlags, FutexOp};
|
||||
use std::ffi::{CStr, CString};
|
||||
@ -21,6 +20,7 @@ use {fs, process, std, vm};
|
||||
use super::*;
|
||||
|
||||
use self::consts::*;
|
||||
use std::any::Any;
|
||||
|
||||
// Use the internal syscall wrappers from sgx_tstd
|
||||
//use std::libc_fs as fs;
|
||||
@ -177,6 +177,22 @@ pub extern "C" fn dispatch_syscall(
|
||||
arg3 as *mut c_void,
|
||||
arg4 as *mut libc::socklen_t,
|
||||
),
|
||||
SYS_SENDTO => do_sendto(
|
||||
arg0 as c_int,
|
||||
arg1 as *const c_void,
|
||||
arg2 as size_t,
|
||||
arg3 as c_int,
|
||||
arg4 as *const libc::sockaddr,
|
||||
arg5 as libc::socklen_t,
|
||||
),
|
||||
SYS_RECVFROM => do_recvfrom(
|
||||
arg0 as c_int,
|
||||
arg1 as *mut c_void,
|
||||
arg2 as size_t,
|
||||
arg3 as c_int,
|
||||
arg4 as *mut libc::sockaddr,
|
||||
arg5 as *mut libc::socklen_t,
|
||||
),
|
||||
|
||||
_ => do_unknown(num, arg0, arg1, arg2, arg3, arg4, arg5),
|
||||
};
|
||||
@ -654,6 +670,7 @@ fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<isize, Error> {
|
||||
const MAP_FAILED: *const c_void = ((-1) as i64) as *const c_void;
|
||||
|
||||
fn do_exit(status: i32) -> ! {
|
||||
info!("exit: {}", status);
|
||||
extern "C" {
|
||||
fn do_exit_task() -> !;
|
||||
}
|
||||
@ -749,8 +766,15 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize
|
||||
"socket: domain: {}, socket_type: {}, protocol: {}",
|
||||
domain, socket_type, protocol
|
||||
);
|
||||
let ret = unsafe { libc::ocall::socket(domain, socket_type, protocol) };
|
||||
Ok(ret as isize)
|
||||
|
||||
let socket = SocketFile::new(domain, socket_type, protocol)?;
|
||||
let file_ref: Arc<Box<File>> = Arc::new(Box::new(socket));
|
||||
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
|
||||
let fd = proc.get_files().lock().unwrap().put(file_ref, false);
|
||||
Ok(fd as isize)
|
||||
}
|
||||
|
||||
fn do_connect(
|
||||
@ -762,7 +786,12 @@ fn do_connect(
|
||||
"connect: fd: {}, addr: {:?}, addr_len: {}",
|
||||
fd, addr, addr_len
|
||||
);
|
||||
let ret = unsafe { libc::ocall::connect(fd, addr, addr_len) };
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::connect(socket.fd(), addr, addr_len) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
@ -776,13 +805,26 @@ fn do_accept(
|
||||
"accept: fd: {}, addr: {:?}, addr_len: {:?}, flags: {:#x}",
|
||||
fd, addr, addr_len, flags
|
||||
);
|
||||
let ret = unsafe { libc::ocall::accept4(fd, addr, addr_len, flags) };
|
||||
Ok(ret as isize)
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let new_socket = socket.accept(addr, addr_len, flags)?;
|
||||
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
|
||||
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
|
||||
|
||||
Ok(new_fd as isize)
|
||||
}
|
||||
|
||||
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
||||
info!("shutdown: fd: {}, how: {}", fd, how);
|
||||
let ret = unsafe { libc::ocall::shutdown(fd, how) };
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::shutdown(socket.fd(), how) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
@ -792,13 +834,23 @@ fn do_bind(
|
||||
addr_len: libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
info!("bind: fd: {}, addr: {:?}, addr_len: {}", fd, addr, addr_len);
|
||||
let ret = unsafe { libc::ocall::bind(fd, addr, addr_len) };
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::bind(socket.fd(), addr, addr_len) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
||||
info!("listen: fd: {}, backlog: {}", fd, backlog);
|
||||
let ret = unsafe { libc::ocall::listen(fd, backlog) };
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::listen(socket.fd(), backlog) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
@ -813,7 +865,12 @@ fn do_setsockopt(
|
||||
"setsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
||||
fd, level, optname, optval, optlen
|
||||
);
|
||||
let ret = unsafe { libc::ocall::setsockopt(fd, level, optname, optval, optlen) };
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::setsockopt(socket.fd(), level, optname, optval, optlen) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
@ -828,6 +885,65 @@ fn do_getsockopt(
|
||||
"getsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
||||
fd, level, optname, optval, optlen
|
||||
);
|
||||
let ret = unsafe { libc::ocall::getsockopt(fd, level, optname, optval, optlen) };
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::getsockopt(socket.fd(), level, optname, optval, optlen) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_sendto(
|
||||
fd: c_int,
|
||||
base: *const c_void,
|
||||
len: size_t,
|
||||
flags: c_int,
|
||||
addr: *const libc::sockaddr,
|
||||
addr_len: libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
info!(
|
||||
"sendto: fd: {}, base: {:?}, len: {}, addr: {:?}, addr_len: {}",
|
||||
fd, base, len, addr, addr_len
|
||||
);
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::sendto(socket.fd(), base, len, flags, addr, addr_len) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_recvfrom(
|
||||
fd: c_int,
|
||||
base: *mut c_void,
|
||||
len: size_t,
|
||||
flags: c_int,
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
info!(
|
||||
"recvfrom: fd: {}, base: {:?}, len: {}, flags: {}, addr: {:?}, addr_len: {:?}",
|
||||
fd, base, len, flags, addr, addr_len
|
||||
);
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||
let socket = file_ref.as_socket()?;
|
||||
|
||||
let ret = unsafe { libc::ocall::recvfrom(socket.fd(), base, len, flags, addr, addr_len) };
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
trait AsSocket {
|
||||
fn as_socket(&self) -> Result<&SocketFile, Error>;
|
||||
}
|
||||
|
||||
impl AsSocket for FileRef {
|
||||
fn as_socket(&self) -> Result<&SocketFile, Error> {
|
||||
self.as_any()
|
||||
.downcast_ref::<SocketFile>()
|
||||
.ok_or(Error::new(Errno::EBADF, "not a socket"))
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,10 @@ impl Log for SimpleLogger {
|
||||
if self.enabled(record.metadata()) {
|
||||
let color = Color::from(record.level());
|
||||
println!(
|
||||
"\u{1B}[{}m[{:>5}] {}\u{1B}[0m",
|
||||
"\u{1B}[{}m[{:>5}][{}] {}\u{1B}[0m",
|
||||
color as u8,
|
||||
record.level(),
|
||||
crate::process::do_getpid(),
|
||||
record.args()
|
||||
);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../)
|
||||
# Dependencies: need to be compiled but not to run by any Makefile target
|
||||
TEST_DEPS := dev_null
|
||||
# Tests: need to be compiled and run by test-% target
|
||||
TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread clone server
|
||||
TESTS := empty argv hello_world malloc file getpid spawn pipe time truncate readdir mkdir link tls pthread client server
|
||||
# Benchmarks: need to be compiled and run by bench-% target
|
||||
BENCHES := spawn_and_exit_latency pipe_throughput
|
||||
|
||||
|
@ -14,7 +14,7 @@ int main(int argc, const char *argv[]) {
|
||||
|
||||
if (argc != 2) {
|
||||
printf("usage: ./client <ipaddress>\n");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user