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 { | ||||
|         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 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)?; | ||||
|     let file_ref: Arc<Box<File>> = Arc::new(Box::new(socket)); | ||||
|             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()?; | ||||
| 
 | ||||
|     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,6 +1006,7 @@ 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)?; | ||||
|     if let Ok(socket) = file_ref.as_socket() { | ||||
|         let socket = file_ref.as_socket()?; | ||||
| 
 | ||||
|         let new_socket = socket.accept(addr, addr_len, flags)?; | ||||
| @ -984,6 +1014,18 @@ fn do_accept4( | ||||
|         let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false); | ||||
| 
 | ||||
|         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()?; | ||||
| 
 | ||||
|     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()?; | ||||
| 
 | ||||
|     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()?; | ||||
| 
 | ||||
|     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,8 +1095,7 @@ 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()?; | ||||
| 
 | ||||
|     if let Ok(socket) = file_ref.as_socket() { | ||||
|         let ret = try_libc!(libc::ocall::setsockopt( | ||||
|             socket.fd(), | ||||
|             level, | ||||
| @ -1047,6 +1104,12 @@ fn do_setsockopt( | ||||
|             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