fix for php. include incomplete code for UnixSocket
This commit is contained in:
parent
f846ba11f2
commit
9106bd46f2
@ -3,7 +3,7 @@
|
||||
<ProdID>0</ProdID>
|
||||
<ISVSVN>0</ISVSVN>
|
||||
<StackMaxSize>0x100000</StackMaxSize>
|
||||
<HeapMaxSize>0x1000000</HeapMaxSize>
|
||||
<HeapMaxSize>0x2000000</HeapMaxSize>
|
||||
<TCSNum>8</TCSNum>
|
||||
<TCSPolicy>1</TCSPolicy>
|
||||
<DisableDebug>0</DisableDebug>
|
||||
|
@ -373,7 +373,7 @@ impl File for StdoutFile {
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
ctime: Timespec { sec: 0, nsec: 0 },
|
||||
type_: FileType::File,
|
||||
type_: FileType::CharDevice,
|
||||
mode: 0,
|
||||
nlinks: 0,
|
||||
uid: 0,
|
||||
@ -489,7 +489,7 @@ impl File for StdinFile {
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
ctime: Timespec { sec: 0, nsec: 0 },
|
||||
type_: FileType::File,
|
||||
type_: FileType::CharDevice,
|
||||
mode: 0,
|
||||
nlinks: 0,
|
||||
uid: 0,
|
||||
|
@ -1,5 +1,4 @@
|
||||
use super::*;
|
||||
use crate::syscall::AsSocket;
|
||||
use std::any::Any;
|
||||
use std::collections::btree_map::BTreeMap;
|
||||
use std::fmt;
|
||||
|
@ -9,7 +9,8 @@ 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;
|
||||
pub use self::socket_file::{SocketFile, AsSocket};
|
||||
pub use self::unix_socket::{UnixSocketFile, AsUnixSocket};
|
||||
use self::inode_file::OpenOptions;
|
||||
pub use self::pipe::Pipe;
|
||||
pub use self::io_multiplexing::*;
|
||||
@ -27,6 +28,7 @@ mod sgx_impl;
|
||||
mod io_multiplexing;
|
||||
mod access;
|
||||
mod null;
|
||||
mod unix_socket;
|
||||
|
||||
|
||||
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
@ -363,7 +365,7 @@ pub fn do_sendfile(
|
||||
|
||||
let in_file = file_table.get(in_fd)?;
|
||||
let out_file = file_table.get(out_fd)?;
|
||||
let mut buffer: [u8; 1024] = unsafe { uninitialized() };
|
||||
let mut buffer: [u8; 1024 * 11] = unsafe { uninitialized() };
|
||||
|
||||
let mut read_offset = match offset {
|
||||
Some(offset) => offset,
|
||||
|
@ -90,7 +90,21 @@ impl File for SocketFile {
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
unimplemented!()
|
||||
Ok(Metadata {
|
||||
dev: 0,
|
||||
inode: 0,
|
||||
size: 0,
|
||||
blk_size: 0,
|
||||
blocks: 0,
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
ctime: Timespec { sec: 0, nsec: 0 },
|
||||
type_: FileType::Socket,
|
||||
mode: 0,
|
||||
nlinks: 0,
|
||||
uid: 0,
|
||||
gid: 0
|
||||
})
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
@ -113,3 +127,15 @@ impl File for SocketFile {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub 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"))
|
||||
}
|
||||
}
|
||||
|
310
src/libos/src/fs/unix_socket.rs
Normal file
310
src/libos/src/fs/unix_socket.rs
Normal file
@ -0,0 +1,310 @@
|
||||
use super::*;
|
||||
use std::collections::btree_map::BTreeMap;
|
||||
use util::ring_buf::{RingBufReader, RingBufWriter, RingBuf};
|
||||
use std::sync::SgxMutex as Mutex;
|
||||
use alloc::prelude::ToString;
|
||||
use std::fmt;
|
||||
|
||||
pub struct UnixSocketFile {
|
||||
inner: Mutex<UnixSocket>
|
||||
}
|
||||
|
||||
impl File for UnixSocketFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.read(buf)
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.write(buf)
|
||||
}
|
||||
|
||||
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
self.read(buf)
|
||||
}
|
||||
|
||||
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||
self.write(buf)
|
||||
}
|
||||
|
||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let mut total_len = 0;
|
||||
for buf in bufs {
|
||||
match inner.read(buf) {
|
||||
Ok(len) => {
|
||||
total_len += len;
|
||||
}
|
||||
Err(_) if total_len != 0 => break,
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let mut total_len = 0;
|
||||
for buf in bufs {
|
||||
match inner.write(buf) {
|
||||
Ok(len) => {
|
||||
total_len += len;
|
||||
}
|
||||
Err(_) if total_len != 0 => break,
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
errno!(ESPIPE, "UnixSocket does not support seek")
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
Ok(Metadata {
|
||||
dev: 0,
|
||||
inode: 0,
|
||||
size: 0,
|
||||
blk_size: 0,
|
||||
blocks: 0,
|
||||
atime: Timespec { sec: 0, nsec: 0 },
|
||||
mtime: Timespec { sec: 0, nsec: 0 },
|
||||
ctime: Timespec { sec: 0, nsec: 0 },
|
||||
type_: FileType::Socket,
|
||||
mode: 0,
|
||||
nlinks: 0,
|
||||
uid: 0,
|
||||
gid: 0
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl UnixSocketFile {
|
||||
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||
let inner = UnixSocket::new(socket_type, protocol)?;
|
||||
Ok(UnixSocketFile { inner: Mutex::new(inner) })
|
||||
}
|
||||
|
||||
pub fn bind(&self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.bind(path)
|
||||
}
|
||||
|
||||
pub fn listen(&self) -> Result<(), Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.listen()
|
||||
}
|
||||
|
||||
pub fn accept(&self) -> Result<UnixSocketFile, Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let new_socket = inner.accept()?;
|
||||
Ok(UnixSocketFile { inner: Mutex::new(new_socket) })
|
||||
}
|
||||
|
||||
pub fn connect(&self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.connect(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for UnixSocketFile {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "UnixSocketFile {{ ... }}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait AsUnixSocket {
|
||||
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error>;
|
||||
}
|
||||
|
||||
impl AsUnixSocket for FileRef {
|
||||
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error> {
|
||||
self.as_any()
|
||||
.downcast_ref::<UnixSocketFile>()
|
||||
.ok_or(Error::new(Errno::EBADF, "not a unix socket"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct UnixSocket {
|
||||
obj: Option<Arc<UnixSocketObject>>,
|
||||
status: Status,
|
||||
}
|
||||
|
||||
enum Status {
|
||||
None,
|
||||
Listening,
|
||||
Connected(Channel),
|
||||
}
|
||||
|
||||
impl UnixSocket {
|
||||
/// C/S 1: Create a new unix socket
|
||||
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||
if socket_type == libc::SOCK_STREAM && protocol == 0 {
|
||||
Ok(UnixSocket {
|
||||
obj: None,
|
||||
status: Status::None
|
||||
})
|
||||
} else {
|
||||
errno!(ENOSYS, "unimplemented unix socket type")
|
||||
}
|
||||
}
|
||||
|
||||
/// Server 2: Bind the socket to a file system path
|
||||
pub fn bind(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
// TODO: check permission
|
||||
if self.obj.is_some() {
|
||||
return errno!(EINVAL, "The socket is already bound to an address.");
|
||||
}
|
||||
self.obj = Some(UnixSocketObject::create(path)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Server 3: Listen to a socket
|
||||
pub fn listen(&mut self) -> Result<(), Error> {
|
||||
self.status = Status::Listening;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Server 4: Accept a connection on listening. Non-blocking.
|
||||
pub fn accept(&mut self) -> Result<UnixSocket, Error> {
|
||||
match self.status {
|
||||
Status::Listening => {}
|
||||
_ => return errno!(EINVAL, "unix socket is not listening"),
|
||||
};
|
||||
let socket = self.obj.as_mut().unwrap().pop()
|
||||
.ok_or(Error::new(EAGAIN, "no connections are present to be accepted"))?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
/// Client 2: Connect to a path
|
||||
pub fn connect(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||
if let Status::Listening = self.status {
|
||||
return errno!(EINVAL, "unix socket is listening?");
|
||||
}
|
||||
let obj = UnixSocketObject::get(path)
|
||||
.ok_or(Error::new(EINVAL, "unix socket path not found"))?;
|
||||
let (channel1, channel2) = Channel::new_pair();
|
||||
self.status = Status::Connected(channel1);
|
||||
obj.push(UnixSocket {
|
||||
obj: Some(obj.clone()),
|
||||
status: Status::Connected(channel2),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
if let Status::Connected(channel) = &self.status {
|
||||
channel.reader.read(buf)
|
||||
} else {
|
||||
errno!(EBADF, "UnixSocket is not connected")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
if let Status::Connected(channel) = &self.status {
|
||||
channel.writer.write(buf)
|
||||
} else {
|
||||
errno!(EBADF, "UnixSocket is not connected")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for UnixSocket {
|
||||
fn drop(&mut self) {
|
||||
if let Status::Listening = self.status {
|
||||
let path = &self.obj.as_ref().unwrap().path;
|
||||
UnixSocketObject::remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UnixSocketObject {
|
||||
path: String,
|
||||
accepted_sockets: Mutex<VecDeque<UnixSocket>>,
|
||||
}
|
||||
|
||||
impl UnixSocketObject {
|
||||
fn push(&self, unix_socket: UnixSocket) {
|
||||
let mut queue = self.accepted_sockets.lock().unwrap();
|
||||
queue.push_back(unix_socket);
|
||||
}
|
||||
fn pop(&self) -> Option<UnixSocket> {
|
||||
let mut queue = self.accepted_sockets.lock().unwrap();
|
||||
queue.pop_front()
|
||||
}
|
||||
fn get(path: impl AsRef<str>) -> Option<Arc<Self>> {
|
||||
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||
paths.get(path.as_ref()).map(|obj| obj.clone())
|
||||
}
|
||||
fn create(path: impl AsRef<str>) -> Result<Arc<Self>, Error> {
|
||||
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||
if paths.contains_key(path.as_ref()) {
|
||||
return errno!(EADDRINUSE, "unix socket path already exists");
|
||||
}
|
||||
let obj = Arc::new(UnixSocketObject {
|
||||
path: path.as_ref().to_string(),
|
||||
accepted_sockets: Mutex::new(VecDeque::new())
|
||||
});
|
||||
paths.insert(path.as_ref().to_string(), obj.clone());
|
||||
Ok(obj)
|
||||
}
|
||||
fn remove(path: impl AsRef<str>) {
|
||||
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||
paths.remove(path.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
struct Channel {
|
||||
reader: RingBufReader,
|
||||
writer: RingBufWriter
|
||||
}
|
||||
|
||||
unsafe impl Send for Channel {}
|
||||
unsafe impl Sync for Channel {}
|
||||
|
||||
impl Channel {
|
||||
fn new_pair() -> (Channel, Channel) {
|
||||
let buf1 = RingBuf::new(DEFAULT_BUF_SIZE);
|
||||
let buf2 = RingBuf::new(DEFAULT_BUF_SIZE);
|
||||
let channel1 = Channel {
|
||||
reader: buf1.reader,
|
||||
writer: buf2.writer,
|
||||
};
|
||||
let channel2 = Channel {
|
||||
reader: buf2.reader,
|
||||
writer: buf1.writer,
|
||||
};
|
||||
(channel1, channel2)
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_BUF_SIZE: usize = 1 * 1024 * 1024;
|
||||
|
||||
lazy_static! {
|
||||
static ref UNIX_SOCKET_OBJS: Mutex<BTreeMap<String, Arc<UnixSocketObject>>>
|
||||
= Mutex::new(BTreeMap::new());
|
||||
}
|
@ -36,7 +36,7 @@ macro_rules! debug_trace {
|
||||
|
||||
macro_rules! errno {
|
||||
($errno: ident, $msg: expr) => {{
|
||||
println!(
|
||||
error!(
|
||||
"ERROR: {} ({}, line {} in file {})",
|
||||
$errno,
|
||||
$msg,
|
||||
@ -54,7 +54,7 @@ macro_rules! try_libc {
|
||||
if ret == -1 {
|
||||
let errno = unsafe { libc::errno() };
|
||||
// println will cause libc ocall and overwrite errno
|
||||
println!(
|
||||
error!(
|
||||
"ERROR from libc: {} (line {} in file {})",
|
||||
errno,
|
||||
line!(),
|
||||
|
@ -101,7 +101,7 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Res
|
||||
waiter
|
||||
};
|
||||
|
||||
let child_pid = Waiter::sleep_until_woken_with_result(waiter);
|
||||
let child_pid = waiter.sleep_until_woken_with_result();
|
||||
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
let child_i = {
|
||||
|
@ -4,8 +4,8 @@ use std::ptr;
|
||||
use xmas_elf::{header, program, sections, ElfFile};
|
||||
|
||||
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
|
||||
pub const DEFAULT_HEAP_SIZE: usize = 2 * 1024 * 1024;
|
||||
pub const DEFAULT_MMAP_SIZE: usize = 8 * 1024 * 1024;
|
||||
pub const DEFAULT_HEAP_SIZE: usize = 10 * 1024 * 1024;
|
||||
pub const DEFAULT_MMAP_SIZE: usize = 40 * 1024 * 1024;
|
||||
|
||||
pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
|
||||
let mut code_seg = get_code_segment(elf_file)?;
|
||||
|
@ -113,7 +113,8 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<Fi
|
||||
}
|
||||
}
|
||||
&FileAction::Close(fd) => {
|
||||
cloned_file_table.del(fd)?;
|
||||
// ignore error
|
||||
cloned_file_table.del(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,14 +48,14 @@ where
|
||||
self.inner.lock().unwrap().data
|
||||
}
|
||||
|
||||
pub fn sleep_until_woken_with_result(waiter: Waiter<D, R>) -> R {
|
||||
while !waiter.inner.lock().unwrap().is_woken {
|
||||
pub fn sleep_until_woken_with_result(self) -> R {
|
||||
while !self.inner.lock().unwrap().is_woken {
|
||||
unsafe {
|
||||
wait_event(waiter.thread);
|
||||
wait_event(self.thread);
|
||||
}
|
||||
}
|
||||
|
||||
waiter.inner.lock().unwrap().result.unwrap()
|
||||
self.inner.lock().unwrap().result.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +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::{AccessFlags, AccessModes, FcntlCmd, File, FileDesc, FileRef, SocketFile, AT_FDCWD};
|
||||
use fs::*;
|
||||
use misc::{resource_t, rlimit_t, utsname_t};
|
||||
use prelude::*;
|
||||
use process::{pid_t, ChildProcessFilter, CloneFlags, FileAction, FutexFlags, FutexOp};
|
||||
@ -48,10 +48,15 @@ pub extern "C" fn dispatch_syscall(
|
||||
);
|
||||
#[cfg(feature = "syscall_timing")]
|
||||
let time_start = {
|
||||
if crate::process::current_pid() == 1 && num == SYS_EXIT {
|
||||
print_syscall_timing();
|
||||
static mut LAST_PRINT: usize = 0;
|
||||
let time = crate::time::do_gettimeofday().as_usec();
|
||||
unsafe {
|
||||
if time / 1000000 / 5 > LAST_PRINT {
|
||||
LAST_PRINT = time / 1000000 / 5;
|
||||
print_syscall_timing();
|
||||
}
|
||||
}
|
||||
crate::time::do_gettimeofday().as_usec()
|
||||
time
|
||||
};
|
||||
|
||||
let ret = match num {
|
||||
@ -248,6 +253,11 @@ pub extern "C" fn dispatch_syscall(
|
||||
arg3 as *mut c_void,
|
||||
arg4 as *mut libc::socklen_t,
|
||||
),
|
||||
SYS_GETPEERNAME => do_getpeername(
|
||||
arg0 as c_int,
|
||||
arg1 as *mut libc::sockaddr,
|
||||
arg2 as *mut libc::socklen_t,
|
||||
),
|
||||
SYS_SENDTO => do_sendto(
|
||||
arg0 as c_int,
|
||||
arg1 as *const c_void,
|
||||
@ -295,6 +305,9 @@ fn print_syscall_timing() {
|
||||
}
|
||||
println!("{:>3}: {:>6} us", i, time);
|
||||
}
|
||||
for x in unsafe { SYSCALL_TIMING.iter_mut() } {
|
||||
*x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -936,8 +949,16 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize
|
||||
domain, socket_type, protocol
|
||||
);
|
||||
|
||||
let socket = SocketFile::new(domain, socket_type, protocol)?;
|
||||
let file_ref: Arc<Box<File>> = Arc::new(Box::new(socket));
|
||||
let file_ref: Arc<Box<File>> = match domain {
|
||||
// libc::AF_LOCAL => {
|
||||
// let unix_socket = UnixSocketFile::new(socket_type, protocol)?;
|
||||
// Arc::new(Box::new(unix_socket))
|
||||
// }
|
||||
_ => {
|
||||
let socket = SocketFile::new(domain, socket_type, protocol)?;
|
||||
Arc::new(Box::new(socket))
|
||||
}
|
||||
};
|
||||
|
||||
let current_ref = process::get_current();
|
||||
let mut proc = current_ref.lock().unwrap();
|
||||
@ -958,10 +979,18 @@ fn do_connect(
|
||||
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 = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len));
|
||||
Ok(ret as isize)
|
||||
if let Ok(socket) = file_ref.as_socket() {
|
||||
let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len));
|
||||
Ok(ret as isize)
|
||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||
let addr = addr as *const libc::sockaddr_un;
|
||||
check_ptr(addr)?; // TODO: check addr_len
|
||||
let path = clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })?.to_string_lossy().into_owned();
|
||||
unix_socket.connect(path)?;
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_accept4(
|
||||
@ -977,13 +1006,26 @@ fn do_accept4(
|
||||
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()?;
|
||||
if let Ok(socket) = file_ref.as_socket() {
|
||||
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);
|
||||
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)
|
||||
Ok(new_fd as isize)
|
||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||
let addr = addr as *mut libc::sockaddr_un;
|
||||
check_mut_ptr(addr)?; // TODO: check addr_len
|
||||
|
||||
let new_socket = unix_socket.accept()?;
|
||||
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(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
||||
@ -991,10 +1033,12 @@ fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
||||
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 = try_libc!(libc::ocall::shutdown(socket.fd(), how));
|
||||
Ok(ret as isize)
|
||||
if let Ok(socket) = file_ref.as_socket() {
|
||||
let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how));
|
||||
Ok(ret as isize)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_bind(
|
||||
@ -1006,10 +1050,19 @@ fn do_bind(
|
||||
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 = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len));
|
||||
Ok(ret as isize)
|
||||
if let Ok(socket) = file_ref.as_socket() {
|
||||
check_ptr(addr)?; // TODO: check addr_len
|
||||
let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len));
|
||||
Ok(ret as isize)
|
||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||
let addr = addr as *const libc::sockaddr_un;
|
||||
check_ptr(addr)?; // TODO: check addr_len
|
||||
let path = clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })?.to_string_lossy().into_owned();
|
||||
unix_socket.bind(path)?;
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
||||
@ -1017,10 +1070,15 @@ fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
||||
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 = try_libc!(libc::ocall::listen(socket.fd(), backlog));
|
||||
Ok(ret as isize)
|
||||
if let Ok(socket) = file_ref.as_socket() {
|
||||
let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog));
|
||||
Ok(ret as isize)
|
||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||
unix_socket.listen()?;
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_setsockopt(
|
||||
@ -1037,16 +1095,21 @@ fn do_setsockopt(
|
||||
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 = try_libc!(libc::ocall::setsockopt(
|
||||
socket.fd(),
|
||||
level,
|
||||
optname,
|
||||
optval,
|
||||
optlen
|
||||
));
|
||||
Ok(ret as isize)
|
||||
if let Ok(socket) = file_ref.as_socket() {
|
||||
let ret = try_libc!(libc::ocall::setsockopt(
|
||||
socket.fd(),
|
||||
level,
|
||||
optname,
|
||||
optval,
|
||||
optlen
|
||||
));
|
||||
Ok(ret as isize)
|
||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||
warn!("setsockopt for unix socket is unimplemented");
|
||||
Ok(0)
|
||||
} else {
|
||||
errno!(EBADF, "not a socket")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_getsockopt(
|
||||
@ -1075,6 +1138,25 @@ fn do_getsockopt(
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_getpeername(
|
||||
fd: c_int,
|
||||
addr: *mut libc::sockaddr,
|
||||
addr_len: *mut libc::socklen_t,
|
||||
) -> Result<isize, Error> {
|
||||
info!("getpeername: fd: {}, addr: {:?}, addr_len: {:?}", 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 = try_libc!(libc::ocall::getpeername(
|
||||
socket.fd(),
|
||||
addr,
|
||||
addr_len
|
||||
));
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_sendto(
|
||||
fd: c_int,
|
||||
base: *const c_void,
|
||||
@ -1230,18 +1312,6 @@ fn do_epoll_wait(
|
||||
Ok(count as isize)
|
||||
}
|
||||
|
||||
pub 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"))
|
||||
}
|
||||
}
|
||||
|
||||
fn do_uname(name: *mut utsname_t) -> Result<isize, Error> {
|
||||
check_mut_ptr(name)?;
|
||||
let name = unsafe { &mut *name };
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#define DATA_SPACE_SIZE (96*1024*1024)
|
||||
#define DATA_SPACE_SIZE (128*1024*1024)
|
||||
|
||||
static char __prealloced_data_space[DATA_SPACE_SIZE]
|
||||
__attribute__ ((
|
||||
|
Loading…
Reference in New Issue
Block a user