[Libos] Refactor io_uring and related module implementions
This commit is contained in:
		
							parent
							
								
									b80450ef96
								
							
						
					
					
						commit
						070a024c0d
					
				| @ -26,7 +26,11 @@ impl Synchronizer for EdgeSync { | ||||
|             return Ok(()); | ||||
|         } | ||||
|         loop { | ||||
|             self.host_eventfd.poll(timeout)?; | ||||
|             if let Err(error) = self.host_eventfd.poll(timeout) { | ||||
|                 self.state.store(INIT, Ordering::Relaxed); | ||||
|                 return Err(error); | ||||
|             } | ||||
| 
 | ||||
|             if self | ||||
|                 .state | ||||
|                 .compare_exchange(NOTIFIED, INIT, Ordering::Acquire, Ordering::Acquire) | ||||
| @ -47,8 +51,7 @@ impl Synchronizer for EdgeSync { | ||||
|         // Need to change timeout from `Option<&mut Duration>` to `&mut Option<Duration>`
 | ||||
|         // so that the Rust compiler is happy about using the variable in a loop.
 | ||||
|         let ret = self.host_eventfd.poll_mut(remain.as_mut()); | ||||
|         // Wait for something to happen, assuming it's still set to PARKED.
 | ||||
|         // futex_wait(&self.state, PARKED, Some(timeout));
 | ||||
|         // Wait for something to happen, assuming it's still set to NOTIFIED.
 | ||||
|         // This is not just a store, because we need to establish a
 | ||||
|         // release-acquire ordering with unpark().
 | ||||
|         if self.state.swap(INIT, Ordering::Acquire) == NOTIFIED { | ||||
|  | ||||
| @ -27,7 +27,7 @@ use crate::prelude::*; | ||||
| /// Although it is safer to use AcqRel,here using `Release` would be enough.
 | ||||
| pub struct WaiterQueue<Sync: Synchronizer = LevelSync> { | ||||
|     count: AtomicUsize, | ||||
|     wakers: SgxMutex<VecDeque<Waker<Sync>>>, | ||||
|     wakers: Mutex<VecDeque<Waker<Sync>>>, | ||||
| } | ||||
| 
 | ||||
| impl<Sync: Synchronizer> WaiterQueue<Sync> { | ||||
| @ -35,7 +35,7 @@ impl<Sync: Synchronizer> WaiterQueue<Sync> { | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             count: AtomicUsize::new(0), | ||||
|             wakers: SgxMutex::new(VecDeque::new()), | ||||
|             wakers: Mutex::new(VecDeque::new()), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -54,7 +54,7 @@ impl<Sync: Synchronizer> WaiterQueue<Sync> { | ||||
|     pub fn reset_and_enqueue(&self, waiter: &Waiter<Sync>) { | ||||
|         waiter.reset(); | ||||
| 
 | ||||
|         let mut wakers = self.wakers.lock().unwrap(); | ||||
|         let mut wakers = self.wakers.lock(); | ||||
|         self.count.fetch_add(1, Ordering::Release); | ||||
|         wakers.push_back(waiter.waker()); | ||||
|     } | ||||
| @ -78,7 +78,7 @@ impl<Sync: Synchronizer> WaiterQueue<Sync> { | ||||
| 
 | ||||
|         // Dequeue wakers
 | ||||
|         let to_wake = { | ||||
|             let mut wakers = self.wakers.lock().unwrap(); | ||||
|             let mut wakers = self.wakers.lock(); | ||||
|             let max_count = max_count.min(wakers.len()); | ||||
|             let to_wake: Vec<Waker<Sync>> = wakers.drain(..max_count).collect(); | ||||
|             self.count.fetch_sub(to_wake.len(), Ordering::Release); | ||||
|  | ||||
| @ -36,7 +36,8 @@ impl GetIfConf { | ||||
|         } | ||||
| 
 | ||||
|         let mut if_conf = self.to_raw_ifconf(); | ||||
|         get_ifconf_by_host(fd, &mut if_conf)?; | ||||
|         GetIfConf::get_ifconf_by_host(fd, &mut if_conf)?; | ||||
| 
 | ||||
|         self.set_len(if_conf.ifc_len as usize); | ||||
|         Ok(()) | ||||
|     } | ||||
| @ -78,59 +79,59 @@ impl GetIfConf { | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_ifconf_by_host(fd: FileDesc, if_conf: &mut IfConf) -> Result<()> { | ||||
|         const SIOCGIFCONF: u32 = 0x8912; | ||||
| 
 | ||||
|         extern "C" { | ||||
|             // Used to ioctl arguments with pointer members.
 | ||||
|             //
 | ||||
|             // Before the call the area the pointers points to should be assembled into
 | ||||
|             // one continuous memory block. Then the block is repacked to ioctl arguments
 | ||||
|             // in the ocall implementation in host.
 | ||||
|             //
 | ||||
|             // ret: holds the return value of ioctl in host
 | ||||
|             // fd: the host fd for the device
 | ||||
|             // cmd_num: request number of the ioctl
 | ||||
|             // buf: the data to exchange with host
 | ||||
|             // len: the size of the buf
 | ||||
|             // recv_len: accepts transferred data length when buf is used to get data from host
 | ||||
|             //
 | ||||
|             fn occlum_ocall_ioctl_repack( | ||||
|                 ret: *mut i32, | ||||
|                 fd: i32, | ||||
|                 cmd_num: i32, | ||||
|                 buf: *const u8, | ||||
|                 len: i32, | ||||
|                 recv_len: *mut i32, | ||||
|             ) -> sgx_types::sgx_status_t; | ||||
|         } | ||||
| 
 | ||||
|         try_libc!({ | ||||
|             let mut recv_len: i32 = 0; | ||||
|             let mut retval: i32 = 0; | ||||
|             let status = occlum_ocall_ioctl_repack( | ||||
|                 &mut retval as *mut i32, | ||||
|                 fd as _, | ||||
|                 SIOCGIFCONF as _, | ||||
|                 if_conf.ifc_buf, | ||||
|                 if_conf.ifc_len, | ||||
|                 &mut recv_len as *mut i32, | ||||
|             ); | ||||
|             assert!(status == sgx_types::sgx_status_t::SGX_SUCCESS); | ||||
| 
 | ||||
|             // If ifc_req is NULL, SIOCGIFCONF returns the necessary buffer
 | ||||
|             // size in bytes for receiving all available addresses in ifc_len
 | ||||
|             // which is irrelevant to the orginal ifc_len.
 | ||||
|             if !if_conf.ifc_buf.is_null() { | ||||
|                 assert!(if_conf.ifc_len >= recv_len); | ||||
|             } | ||||
|             if_conf.ifc_len = recv_len; | ||||
|             retval | ||||
|         }); | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl IoctlCmd for GetIfConf {} | ||||
| 
 | ||||
| const SIOCGIFCONF: u32 = 0x8912; | ||||
| 
 | ||||
| fn get_ifconf_by_host(fd: FileDesc, if_conf: &mut IfConf) -> Result<()> { | ||||
|     extern "C" { | ||||
|         // Used to ioctl arguments with pointer members.
 | ||||
|         //
 | ||||
|         // Before the call the area the pointers points to should be assembled into
 | ||||
|         // one continuous memory block. Then the block is repacked to ioctl arguments
 | ||||
|         // in the ocall implementation in host.
 | ||||
|         //
 | ||||
|         // ret: holds the return value of ioctl in host
 | ||||
|         // fd: the host fd for the device
 | ||||
|         // cmd_num: request number of the ioctl
 | ||||
|         // buf: the data to exchange with host
 | ||||
|         // len: the size of the buf
 | ||||
|         // recv_len: accepts transferred data length when buf is used to get data from host
 | ||||
|         //
 | ||||
|         fn occlum_ocall_ioctl_repack( | ||||
|             ret: *mut i32, | ||||
|             fd: i32, | ||||
|             cmd_num: i32, | ||||
|             buf: *const u8, | ||||
|             len: i32, | ||||
|             recv_len: *mut i32, | ||||
|         ) -> sgx_types::sgx_status_t; | ||||
|     } | ||||
| 
 | ||||
|     try_libc!({ | ||||
|         let mut recv_len: i32 = 0; | ||||
|         let mut retval: i32 = 0; | ||||
|         let status = occlum_ocall_ioctl_repack( | ||||
|             &mut retval as *mut i32, | ||||
|             fd as _, | ||||
|             SIOCGIFCONF as _, | ||||
|             if_conf.ifc_buf, | ||||
|             if_conf.ifc_len, | ||||
|             &mut recv_len as *mut i32, | ||||
|         ); | ||||
|         assert!(status == sgx_types::sgx_status_t::SGX_SUCCESS); | ||||
| 
 | ||||
|         // If ifc_req is NULL, SIOCGIFCONF returns the necessary buffer
 | ||||
|         // size in bytes for receiving all available addresses in ifc_len
 | ||||
|         // which is irrelevant to the orginal ifc_len.
 | ||||
|         if !if_conf.ifc_buf.is_null() { | ||||
|             assert!(if_conf.ifc_len >= recv_len); | ||||
|         } | ||||
|         if_conf.ifc_len = recv_len; | ||||
|         retval | ||||
|     }); | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| @ -34,40 +34,40 @@ impl GetIfReqWithRawCmd { | ||||
| 
 | ||||
|     pub fn execute(&mut self, fd: FileDesc) -> Result<()> { | ||||
|         let input_if_req = self.inner.input(); | ||||
|         let output_if_req = get_ifreq_by_host(fd, self.raw_cmd, input_if_req)?; | ||||
|         let output_if_req = GetIfReqWithRawCmd::get_ifreq_by_host(fd, self.raw_cmd, input_if_req)?; | ||||
|         self.inner.set_output(output_if_req); | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_ifreq_by_host(fd: FileDesc, cmd: u32, req: &IfReq) -> Result<IfReq> { | ||||
|     let mut if_req: IfReq = req.clone(); | ||||
|     try_libc!({ | ||||
|         let mut retval: i32 = 0; | ||||
|         extern "C" { | ||||
|             pub fn occlum_ocall_ioctl( | ||||
|                 ret: *mut i32, | ||||
|                 fd: c_int, | ||||
|                 request: c_int, | ||||
|                 arg: *mut c_void, | ||||
|                 len: size_t, | ||||
|             ) -> sgx_types::sgx_status_t; | ||||
|         } | ||||
|     fn get_ifreq_by_host(fd: FileDesc, cmd: u32, req: &IfReq) -> Result<IfReq> { | ||||
|         let mut if_req: IfReq = req.clone(); | ||||
|         try_libc!({ | ||||
|             let mut retval: i32 = 0; | ||||
|             extern "C" { | ||||
|                 pub fn occlum_ocall_ioctl( | ||||
|                     ret: *mut i32, | ||||
|                     fd: c_int, | ||||
|                     request: c_int, | ||||
|                     arg: *mut c_void, | ||||
|                     len: size_t, | ||||
|                 ) -> sgx_types::sgx_status_t; | ||||
|             } | ||||
| 
 | ||||
|         use libc::{c_int, c_void, size_t}; | ||||
|         use occlum_ocall_ioctl as do_ioctl; | ||||
|             use libc::{c_int, c_void, size_t}; | ||||
|             use occlum_ocall_ioctl as do_ioctl; | ||||
| 
 | ||||
|         let status = do_ioctl( | ||||
|             &mut retval as *mut i32, | ||||
|             fd as i32, | ||||
|             cmd as i32, | ||||
|             &mut if_req as *mut IfReq as *mut c_void, | ||||
|             std::mem::size_of::<IfReq>(), | ||||
|         ); | ||||
|         assert!(status == sgx_types::sgx_status_t::SGX_SUCCESS); | ||||
|         retval | ||||
|     }); | ||||
|     Ok(if_req) | ||||
|             let status = do_ioctl( | ||||
|                 &mut retval as *mut i32, | ||||
|                 fd as i32, | ||||
|                 cmd as i32, | ||||
|                 &mut if_req as *mut IfReq as *mut c_void, | ||||
|                 std::mem::size_of::<IfReq>(), | ||||
|             ); | ||||
|             assert!(status == sgx_types::sgx_status_t::SGX_SUCCESS); | ||||
|             retval | ||||
|         }); | ||||
|         Ok(if_req) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl IoctlCmd for GetIfReqWithRawCmd {} | ||||
|  | ||||
| @ -214,7 +214,6 @@ pub use self::set_close_on_exec::*; | ||||
| pub use self::set_nonblocking::SetNonBlocking; | ||||
| pub use self::termios::*; | ||||
| pub use self::winsize::*; | ||||
| pub use net::socket::sockopt::SetSockOptRawCmd; | ||||
| 
 | ||||
| mod get_ifconf; | ||||
| mod get_ifreq; | ||||
|  | ||||
| @ -112,7 +112,7 @@ impl File for PipeReader { | ||||
|     fn ioctl(&self, cmd: &mut dyn IoctlCmd) -> Result<()> { | ||||
|         match_ioctl_cmd_auto_error!(cmd, { | ||||
|             cmd : GetReadBufLen => { | ||||
|                 let read_buf_len = self.consumer.ready_len(); | ||||
|                 let read_buf_len = self.get_ready_len().min(std::i32::MAX as usize) as i32; | ||||
|                 cmd.set_output(read_buf_len as _); | ||||
|             }, | ||||
|         }); | ||||
|  | ||||
| @ -104,13 +104,11 @@ impl UringSet { | ||||
|                 // Sum registered socket
 | ||||
|                 let total_socket_num = map | ||||
|                     .values() | ||||
|                     .fold(0, |acc, state| acc + state.registered_num) | ||||
|                     + 1; | ||||
|                     .fold(0, |acc, state| acc + state.registered_num); | ||||
|                 // Determine the number of available io_uring
 | ||||
|                 let uring_num = (total_socket_num / SOCKET_THRESHOLD_PER_URING) + 1; | ||||
|                 let existed_uring_num = self.running_uring_num.load(Ordering::Relaxed); | ||||
|                 assert!(existed_uring_num <= uring_num); | ||||
|                 existed_uring_num < uring_num | ||||
| 
 | ||||
|                 running_uring_num < uring_num | ||||
|             }; | ||||
| 
 | ||||
|             if should_build_uring { | ||||
| @ -134,7 +132,7 @@ impl UringSet { | ||||
|         // Link the file to the io_uring instance with the least load.
 | ||||
|         let (mut uring, mut state) = map | ||||
|             .iter_mut() | ||||
|             .min_by_key(|(_, &mut state)| state.registered_num) | ||||
|             .min_by_key(|(_, state)| state.registered_num) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|         // Re-select io_uring instance with least task load
 | ||||
|  | ||||
| @ -7,13 +7,17 @@ pub use self::io_multiplexing::{ | ||||
|     PollEventFlags, PollFd, THREAD_NOTIFIERS, | ||||
| }; | ||||
| pub use self::socket::{ | ||||
|     socketpair, unix_socket, AsUnixSocket, Domain, HostSocket, HostSocketType, Iovs, IovsMut, | ||||
|     RawAddr, SliceAsLibcIovec, UnixAddr, | ||||
|     mmsghdr, socketpair, unix_socket, Addr, AnyAddr, AsUnixSocket, Domain, GetAcceptConnCmd, | ||||
|     GetDomainCmd, GetErrorCmd, GetOutputAsBytes, GetPeerNameCmd, GetRecvBufSizeCmd, | ||||
|     GetRecvTimeoutCmd, GetSendBufSizeCmd, GetSendTimeoutCmd, GetSockOptRawCmd, GetTypeCmd, | ||||
|     HostSocket, HostSocketType, Iovs, IovsMut, RecvFlags, SendFlags, SetRecvBufSizeCmd, | ||||
|     SetRecvTimeoutCmd, SetSendBufSizeCmd, SetSendTimeoutCmd, SetSockOptRawCmd, Shutdown, | ||||
|     SliceAsLibcIovec, SockAddr, SockOptName, SocketFile, SocketType, UnixAddr, UringSocketType, | ||||
| }; | ||||
| pub use self::syscalls::*; | ||||
| 
 | ||||
| mod io_multiplexing; | ||||
| pub(crate) mod socket; | ||||
| mod socket; | ||||
| mod syscalls; | ||||
| 
 | ||||
| pub use self::syscalls::*; | ||||
|  | ||||
| @ -26,7 +26,7 @@ pub struct HostSocket { | ||||
| impl HostSocket { | ||||
|     pub fn new( | ||||
|         domain: Domain, | ||||
|         socket_type: Type, | ||||
|         socket_type: SocketType, | ||||
|         socket_flags: SocketFlags, | ||||
|         protocol: i32, | ||||
|     ) -> Result<Self> { | ||||
| @ -49,7 +49,7 @@ impl HostSocket { | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn bind(&self, addr: &RawAddr) -> Result<()> { | ||||
|     pub fn bind(&self, addr: &SockAddr) -> Result<()> { | ||||
|         let (addr_ptr, addr_len) = addr.as_ptr_and_len(); | ||||
| 
 | ||||
|         let ret = try_libc!(libc::ocall::bind( | ||||
| @ -65,8 +65,8 @@ impl HostSocket { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub fn accept(&self, flags: SocketFlags) -> Result<(Self, Option<RawAddr>)> { | ||||
|         let mut sockaddr = RawAddr::default(); | ||||
|     pub fn accept(&self, flags: SocketFlags) -> Result<(Self, Option<SockAddr>)> { | ||||
|         let mut sockaddr = SockAddr::default(); | ||||
|         let mut addr_len = sockaddr.len(); | ||||
| 
 | ||||
|         let raw_host_fd = try_libc!(libc::ocall::accept4( | ||||
| @ -86,8 +86,8 @@ impl HostSocket { | ||||
|         Ok((HostSocket::from_host_fd(host_fd)?, addr_option)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn addr(&self) -> Result<RawAddr> { | ||||
|         let mut sockaddr = RawAddr::default(); | ||||
|     pub fn addr(&self) -> Result<SockAddr> { | ||||
|         let mut sockaddr = SockAddr::default(); | ||||
|         let mut addr_len = sockaddr.len(); | ||||
|         try_libc!(libc::ocall::getsockname( | ||||
|             self.raw_host_fd() as i32, | ||||
| @ -99,8 +99,8 @@ impl HostSocket { | ||||
|         Ok(sockaddr) | ||||
|     } | ||||
| 
 | ||||
|     pub fn peer_addr(&self) -> Result<RawAddr> { | ||||
|         let mut sockaddr = RawAddr::default(); | ||||
|     pub fn peer_addr(&self) -> Result<SockAddr> { | ||||
|         let mut sockaddr = SockAddr::default(); | ||||
|         let mut addr_len = sockaddr.len(); | ||||
|         try_libc!(libc::ocall::getpeername( | ||||
|             self.raw_host_fd() as i32, | ||||
| @ -112,7 +112,7 @@ impl HostSocket { | ||||
|         Ok(sockaddr) | ||||
|     } | ||||
| 
 | ||||
|     pub fn connect(&self, addr: &Option<RawAddr>) -> Result<()> { | ||||
|     pub fn connect(&self, addr: Option<&SockAddr>) -> Result<()> { | ||||
|         debug!("connect: host_fd: {}, addr {:?}", self.raw_host_fd(), addr); | ||||
| 
 | ||||
|         let (addr_ptr, addr_len) = if let Some(sock_addr) = addr { | ||||
| @ -133,14 +133,13 @@ impl HostSocket { | ||||
|         &self, | ||||
|         buf: &[u8], | ||||
|         flags: SendFlags, | ||||
|         addr_option: &Option<RawAddr>, | ||||
|         addr_option: Option<AnyAddr>, | ||||
|     ) -> Result<usize> { | ||||
|         let bufs = vec![buf]; | ||||
|         self.sendmsg(&bufs, flags, addr_option, None) | ||||
|     } | ||||
| 
 | ||||
|     pub fn recvfrom(&self, buf: &mut [u8], flags: RecvFlags) -> Result<(usize, Option<RawAddr>)> { | ||||
|         let mut sockaddr = RawAddr::default(); | ||||
|     pub fn recvfrom(&self, buf: &mut [u8], flags: RecvFlags) -> Result<(usize, Option<AnyAddr>)> { | ||||
|         let mut bufs = vec![buf]; | ||||
|         let (bytes_recv, recv_addr, _, _) = self.recvmsg(&mut bufs, flags, None)?; | ||||
| 
 | ||||
|  | ||||
| @ -12,7 +12,7 @@ impl HostSocket { | ||||
|         data: &mut [&mut [u8]], | ||||
|         flags: RecvFlags, | ||||
|         control: Option<&mut [u8]>, | ||||
|     ) -> Result<(usize, Option<RawAddr>, MsgFlags, usize)> { | ||||
|     ) -> Result<(usize, Option<AnyAddr>, MsgFlags, usize)> { | ||||
|         let current = current!(); | ||||
|         let data_length = data.iter().map(|s| s.len()).sum(); | ||||
|         let mut ocall_alloc; | ||||
| @ -54,10 +54,10 @@ impl HostSocket { | ||||
|         data: &mut [UntrustedSlice], | ||||
|         flags: RecvFlags, | ||||
|         mut control: Option<&mut [u8]>, | ||||
|     ) -> Result<(usize, Option<RawAddr>, MsgFlags, usize)> { | ||||
|     ) -> Result<(usize, Option<AnyAddr>, MsgFlags, usize)> { | ||||
|         // Prepare the arguments for OCall
 | ||||
|         let host_fd = self.raw_host_fd() as i32; | ||||
|         let mut addr = RawAddr::default(); | ||||
|         let mut addr = SockAddr::default(); | ||||
|         let mut msg_name = addr.as_mut_ptr(); | ||||
|         let mut msg_namelen = addr.len(); | ||||
|         let mut msg_namelen_recvd = 0_u32; | ||||
| @ -122,16 +122,16 @@ impl HostSocket { | ||||
|         }; | ||||
|         let msg_namelen_recvd = msg_namelen_recvd as usize; | ||||
| 
 | ||||
|         let raw_addr = if msg_namelen_recvd == 0 { | ||||
|             None | ||||
|         } else { | ||||
|             addr.set_len(msg_namelen_recvd)?; | ||||
|             Some(addr) | ||||
|         }; | ||||
|         let raw_addr = (msg_namelen_recvd != 0).then(|| { | ||||
|             addr.set_len(msg_namelen_recvd); | ||||
|             addr | ||||
|         }); | ||||
| 
 | ||||
|         let addr = raw_addr.map(|addr| AnyAddr::Raw(addr)); | ||||
| 
 | ||||
|         assert!(msg_namelen_recvd <= msg_namelen); | ||||
|         assert!(msg_controllen_recvd <= msg_controllen); | ||||
|         Ok((bytes_recvd, raw_addr, flags_recvd, msg_controllen_recvd)) | ||||
|         Ok((bytes_recvd, addr, flags_recvd, msg_controllen_recvd)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -2,14 +2,14 @@ use super::*; | ||||
| 
 | ||||
| impl HostSocket { | ||||
|     pub fn send(&self, buf: &[u8], flags: SendFlags) -> Result<usize> { | ||||
|         self.sendto(buf, flags, &None) | ||||
|         self.sendto(buf, flags, None) | ||||
|     } | ||||
| 
 | ||||
|     pub fn sendmsg( | ||||
|         &self, | ||||
|         data: &[&[u8]], | ||||
|         flags: SendFlags, | ||||
|         addr: &Option<RawAddr>, | ||||
|         addr: Option<AnyAddr>, | ||||
|         control: Option<&[u8]>, | ||||
|     ) -> Result<usize> { | ||||
|         let current = current!(); | ||||
| @ -34,8 +34,14 @@ impl HostSocket { | ||||
|             bufs | ||||
|         }; | ||||
| 
 | ||||
|         let name = addr.as_ref().map(|raw_addr| raw_addr.as_slice()); | ||||
|         self.do_sendmsg_untrusted_data(&u_data, flags, name, control) | ||||
|         let raw_addr = addr.map(|addr| addr.to_raw()); | ||||
| 
 | ||||
|         self.do_sendmsg_untrusted_data( | ||||
|             &u_data, | ||||
|             flags, | ||||
|             raw_addr.as_ref().map(|addr| addr.as_slice()), | ||||
|             control, | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fn do_sendmsg_untrusted_data( | ||||
|  | ||||
| @ -41,7 +41,7 @@ impl File for HostSocket { | ||||
|     } | ||||
| 
 | ||||
|     fn writev(&self, bufs: &[&[u8]]) -> Result<usize> { | ||||
|         self.sendmsg(bufs, SendFlags::empty(), &None, None) | ||||
|         self.sendmsg(bufs, SendFlags::empty(), None, None) | ||||
|     } | ||||
| 
 | ||||
|     fn seek(&self, pos: SeekFrom) -> Result<off_t> { | ||||
|  | ||||
| @ -1,15 +1,22 @@ | ||||
| use super::*; | ||||
| 
 | ||||
| mod host; | ||||
| pub(crate) mod sockopt; | ||||
| mod sockopt; | ||||
| mod unix; | ||||
| pub(crate) mod uring; | ||||
| pub(crate) mod util; | ||||
| mod uring; | ||||
| mod util; | ||||
| 
 | ||||
| pub use self::host::{HostSocket, HostSocketType}; | ||||
| pub use self::unix::{socketpair, unix_socket, AsUnixSocket}; | ||||
| pub use self::util::{ | ||||
|     Addr, AnyAddr, CMessages, CSockAddr, CmsgData, Domain, Iovs, IovsMut, Ipv4Addr, Ipv4SocketAddr, | ||||
|     Ipv6SocketAddr, MsgFlags, RawAddr, RecvFlags, SendFlags, Shutdown, SliceAsLibcIovec, | ||||
|     SocketProtocol, Type, UnixAddr, | ||||
|     mmsghdr, Addr, AnyAddr, CMessages, CSockAddr, CmsgData, Domain, Iovs, IovsMut, Ipv4Addr, | ||||
|     Ipv4SocketAddr, Ipv6SocketAddr, MsgFlags, RecvFlags, SendFlags, Shutdown, SliceAsLibcIovec, | ||||
|     SockAddr, SocketFlags, SocketProtocol, SocketType, UnixAddr, | ||||
| }; | ||||
| pub use sockopt::{ | ||||
|     GetAcceptConnCmd, GetDomainCmd, GetErrorCmd, GetOutputAsBytes, GetPeerNameCmd, | ||||
|     GetRecvBufSizeCmd, GetRecvTimeoutCmd, GetSendBufSizeCmd, GetSendTimeoutCmd, GetSockOptRawCmd, | ||||
|     GetTypeCmd, SetRecvBufSizeCmd, SetRecvTimeoutCmd, SetSendBufSizeCmd, SetSendTimeoutCmd, | ||||
|     SetSockOptRawCmd, SockOptName, | ||||
| }; | ||||
| pub use uring::{socket_file::SocketFile, UringSocketType}; | ||||
|  | ||||
| @ -1,12 +1,11 @@ | ||||
| use super::{GetRecvTimeoutCmd, GetSendTimeoutCmd}; | ||||
| 
 | ||||
| use super::{ | ||||
|     GetAcceptConnCmd, GetDomainCmd, GetErrorCmd, GetPeerNameCmd, GetRcvBufSizeCmd, | ||||
|     GetSndBufSizeCmd, GetSockOptRawCmd, GetTypeCmd, | ||||
|     GetAcceptConnCmd, GetDomainCmd, GetErrorCmd, GetPeerNameCmd, GetRecvBufSizeCmd, | ||||
|     GetSendBufSizeCmd, GetSockOptRawCmd, GetTypeCmd, | ||||
| }; | ||||
| 
 | ||||
| use libc::timeval; | ||||
| use std::time::Duration; | ||||
| 
 | ||||
| use crate::prelude::*; | ||||
| 
 | ||||
| @ -60,7 +59,7 @@ impl GetOutputAsBytes for GetTypeCmd { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl GetOutputAsBytes for GetSndBufSizeCmd { | ||||
| impl GetOutputAsBytes for GetSendBufSizeCmd { | ||||
|     fn get_output_as_bytes(&self) -> Option<&[u8]> { | ||||
|         self.output().map(|val_ref| unsafe { | ||||
|             std::slice::from_raw_parts( | ||||
| @ -71,7 +70,7 @@ impl GetOutputAsBytes for GetSndBufSizeCmd { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl GetOutputAsBytes for GetRcvBufSizeCmd { | ||||
| impl GetOutputAsBytes for GetRecvBufSizeCmd { | ||||
|     fn get_output_as_bytes(&self) -> Option<&[u8]> { | ||||
|         self.output().map(|val_ref| unsafe { | ||||
|             std::slice::from_raw_parts( | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| crate::impl_ioctl_cmd! { | ||||
|     pub struct GetSndBufSizeCmd<Input=(), Output=usize> {} | ||||
|     pub struct GetSendBufSizeCmd<Input=(), Output=usize> {} | ||||
| } | ||||
| 
 | ||||
| crate::impl_ioctl_cmd! { | ||||
|     pub struct GetRcvBufSizeCmd<Input=(), Output=usize> {} | ||||
|     pub struct GetRecvBufSizeCmd<Input=(), Output=usize> {} | ||||
| } | ||||
|  | ||||
| @ -16,10 +16,10 @@ pub use get_domain::GetDomainCmd; | ||||
| pub use get_error::GetErrorCmd; | ||||
| pub use get_output::*; | ||||
| pub use get_peername::{AddrStorage, GetPeerNameCmd}; | ||||
| pub use get_sockbuf::{GetRcvBufSizeCmd, GetSndBufSizeCmd}; | ||||
| pub use get_sockbuf::{GetRecvBufSizeCmd, GetSendBufSizeCmd}; | ||||
| pub use get_type::GetTypeCmd; | ||||
| pub use set::{setsockopt_by_host, SetSockOptRawCmd}; | ||||
| pub use set_sockbuf::{SetRcvBufSizeCmd, SetSndBufSizeCmd}; | ||||
| pub use set_sockbuf::{SetRecvBufSizeCmd, SetSendBufSizeCmd}; | ||||
| pub use timeout::{ | ||||
|     timeout_to_timeval, GetRecvTimeoutCmd, GetSendTimeoutCmd, SetRecvTimeoutCmd, SetSendTimeoutCmd, | ||||
| }; | ||||
|  | ||||
| @ -2,14 +2,16 @@ use crate::{fs::IoctlCmd, prelude::*}; | ||||
| use libc::ocall::setsockopt as do_setsockopt; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SetSockOptRawCmd { | ||||
| pub struct SetSockOptRawCmd<'a> { | ||||
|     level: i32, | ||||
|     optname: i32, | ||||
|     optval: &'static [u8], | ||||
|     optval: &'a [u8], | ||||
| } | ||||
| 
 | ||||
| impl SetSockOptRawCmd { | ||||
|     pub fn new(level: i32, optname: i32, optval: &'static [u8]) -> Self { | ||||
| impl IoctlCmd for SetSockOptRawCmd<'static> {} | ||||
| 
 | ||||
| impl<'a> SetSockOptRawCmd<'a> { | ||||
|     pub fn new(level: i32, optname: i32, optval: &'a [u8]) -> SetSockOptRawCmd<'a> { | ||||
|         Self { | ||||
|             level, | ||||
|             optname, | ||||
| @ -23,8 +25,6 @@ impl SetSockOptRawCmd { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl IoctlCmd for SetSockOptRawCmd {} | ||||
| 
 | ||||
| pub fn setsockopt_by_host(fd: FileDesc, level: i32, optname: i32, optval: &[u8]) -> Result<()> { | ||||
|     try_libc!(do_setsockopt( | ||||
|         fd as _, | ||||
|  | ||||
| @ -1,23 +1,18 @@ | ||||
| use super::set::setsockopt_by_host; | ||||
| use crate::{fs::IoctlCmd, prelude::*}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SetSndBufSizeCmd { | ||||
|     buf_size: usize, | ||||
| crate::impl_ioctl_cmd! { | ||||
|     pub struct SetSendBufSizeCmd<Input=usize, Output=()> {} | ||||
| } | ||||
| 
 | ||||
| impl SetSndBufSizeCmd { | ||||
|     pub fn new(buf_size: usize) -> Self { | ||||
|         Self { buf_size } | ||||
|     } | ||||
| 
 | ||||
|     pub fn buf_size(&self) -> usize { | ||||
|         self.buf_size | ||||
|     } | ||||
| crate::impl_ioctl_cmd! { | ||||
|     pub struct SetRecvBufSizeCmd<Input=usize, Output=()> {} | ||||
| } | ||||
| 
 | ||||
| impl SetSendBufSizeCmd { | ||||
|     pub fn update_host(&self, fd: FileDesc) -> Result<()> { | ||||
|         // The buf size for host call should be divided by 2 because the value will be doubled by host kernel.
 | ||||
|         let host_call_buf_size = (self.buf_size / 2).to_ne_bytes(); | ||||
|         let host_call_buf_size = (self.input / 2).to_ne_bytes(); | ||||
| 
 | ||||
|         // Setting SO_SNDBUF for host socket needs to respect /proc/sys/net/core/wmem_max. Thus, the value might be different on host, but it is fine.
 | ||||
|         setsockopt_by_host( | ||||
| @ -29,25 +24,10 @@ impl SetSndBufSizeCmd { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl IoctlCmd for SetSndBufSizeCmd {} | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SetRcvBufSizeCmd { | ||||
|     buf_size: usize, | ||||
| } | ||||
| 
 | ||||
| impl SetRcvBufSizeCmd { | ||||
|     pub fn new(buf_size: usize) -> Self { | ||||
|         Self { buf_size } | ||||
|     } | ||||
| 
 | ||||
|     pub fn buf_size(&self) -> usize { | ||||
|         self.buf_size | ||||
|     } | ||||
| 
 | ||||
| impl SetRecvBufSizeCmd { | ||||
|     pub fn update_host(&self, fd: FileDesc) -> Result<()> { | ||||
|         // The buf size for host call should be divided by 2 because the value will be doubled by host kernel.
 | ||||
|         let host_call_buf_size = (self.buf_size / 2).to_ne_bytes(); | ||||
|         let host_call_buf_size = (self.input / 2).to_ne_bytes(); | ||||
| 
 | ||||
|         // Setting SO_RCVBUF for host socket needs to respect /proc/sys/net/core/rmem_max. Thus, the value might be different on host, but it is fine.
 | ||||
|         setsockopt_by_host( | ||||
| @ -58,5 +38,3 @@ impl SetRcvBufSizeCmd { | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl IoctlCmd for SetRcvBufSizeCmd {} | ||||
|  | ||||
| @ -3,34 +3,12 @@ use crate::prelude::*; | ||||
| use libc::{suseconds_t, time_t}; | ||||
| use std::time::Duration; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SetSendTimeoutCmd(Duration); | ||||
| 
 | ||||
| impl IoctlCmd for SetSendTimeoutCmd {} | ||||
| 
 | ||||
| impl SetSendTimeoutCmd { | ||||
|     pub fn new(timeout: Duration) -> Self { | ||||
|         Self(timeout) | ||||
|     } | ||||
| 
 | ||||
|     pub fn timeout(&self) -> &Duration { | ||||
|         &self.0 | ||||
|     } | ||||
| crate::impl_ioctl_cmd! { | ||||
|     pub struct SetSendTimeoutCmd<Input=Duration, Output=()> {} | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct SetRecvTimeoutCmd(Duration); | ||||
| 
 | ||||
| impl IoctlCmd for SetRecvTimeoutCmd {} | ||||
| 
 | ||||
| impl SetRecvTimeoutCmd { | ||||
|     pub fn new(timeout: Duration) -> Self { | ||||
|         Self(timeout) | ||||
|     } | ||||
| 
 | ||||
|     pub fn timeout(&self) -> &Duration { | ||||
|         &self.0 | ||||
|     } | ||||
| crate::impl_ioctl_cmd! { | ||||
|     pub struct SetRecvTimeoutCmd<Input=Duration, Output=()> {} | ||||
| } | ||||
| 
 | ||||
| crate::impl_ioctl_cmd! { | ||||
|  | ||||
| @ -5,12 +5,12 @@ mod stream; | ||||
| pub use self::stream::Stream; | ||||
| 
 | ||||
| //TODO: rewrite this file when a new kind of uds is added
 | ||||
| pub fn unix_socket(socket_type: Type, flags: SocketFlags, protocol: i32) -> Result<Stream> { | ||||
| pub fn unix_socket(socket_type: SocketType, flags: SocketFlags, protocol: i32) -> Result<Stream> { | ||||
|     if protocol != 0 && protocol != Domain::LOCAL as i32 { | ||||
|         return_errno!(EPROTONOSUPPORT, "protocol is not supported"); | ||||
|     } | ||||
| 
 | ||||
|     if socket_type == Type::STREAM { | ||||
|     if socket_type == SocketType::STREAM { | ||||
|         Ok(Stream::new(flags)) | ||||
|     } else { | ||||
|         return_errno!(ESOCKTNOSUPPORT, "only stream type is supported"); | ||||
| @ -18,7 +18,7 @@ pub fn unix_socket(socket_type: Type, flags: SocketFlags, protocol: i32) -> Resu | ||||
| } | ||||
| 
 | ||||
| pub fn socketpair( | ||||
|     socket_type: Type, | ||||
|     socket_type: SocketType, | ||||
|     flags: SocketFlags, | ||||
|     protocol: i32, | ||||
| ) -> Result<(Stream, Stream)> { | ||||
| @ -26,7 +26,7 @@ pub fn socketpair( | ||||
|         return_errno!(EPROTONOSUPPORT, "protocol is not supported"); | ||||
|     } | ||||
| 
 | ||||
|     if socket_type == Type::STREAM { | ||||
|     if socket_type == SocketType::STREAM { | ||||
|         Stream::socketpair(flags) | ||||
|     } else { | ||||
|         return_errno!(ESOCKTNOSUPPORT, "only stream type is supported"); | ||||
|  | ||||
| @ -72,7 +72,10 @@ impl Stream { | ||||
|         return_errno!(ENOTCONN, "the socket is not connected"); | ||||
|     } | ||||
| 
 | ||||
|     pub fn bind(&self, addr: &mut UnixAddr) -> Result<()> { | ||||
|     pub fn bind(&self, addr: &UnixAddr) -> Result<()> { | ||||
|         let mut unix_addr = addr.clone(); | ||||
|         let addr = &mut unix_addr; | ||||
| 
 | ||||
|         if let UnixAddr::File(inode_num, path) = addr { | ||||
|             // create the corresponding file in the fs and fill Addr with its inode
 | ||||
|             let corresponding_inode_num = { | ||||
| @ -218,7 +221,7 @@ impl Stream { | ||||
|     } | ||||
| 
 | ||||
|     // TODO: handle flags
 | ||||
|     pub fn sendto(&self, buf: &[u8], flags: SendFlags, addr: &Option<UnixAddr>) -> Result<usize> { | ||||
|     pub fn sendto(&self, buf: &[u8], flags: SendFlags, addr: Option<&UnixAddr>) -> Result<usize> { | ||||
|         self.write(buf) | ||||
|     } | ||||
| 
 | ||||
| @ -255,7 +258,7 @@ impl Stream { | ||||
|         bufs: &mut [&mut [u8]], | ||||
|         flags: RecvFlags, | ||||
|         control: Option<&mut [u8]>, | ||||
|     ) -> Result<(usize, usize)> { | ||||
|     ) -> Result<(usize, Option<AnyAddr>, MsgFlags, usize)> { | ||||
|         if !flags.is_empty() { | ||||
|             warn!("unsupported flags: {:?}", flags); | ||||
|         } | ||||
| @ -288,7 +291,7 @@ impl Stream { | ||||
|             0 | ||||
|         }; | ||||
| 
 | ||||
|         Ok((data_len, control_len)) | ||||
|         Ok((data_len, None, MsgFlags::empty(), control_len)) | ||||
|     } | ||||
| 
 | ||||
|     /// perform shutdown on the socket.
 | ||||
|  | ||||
| @ -18,7 +18,7 @@ use crate::prelude::*; | ||||
| /// The common parts of all stream sockets.
 | ||||
| pub struct Common<A: Addr + 'static, R: Runtime> { | ||||
|     host_fd: FileDesc, | ||||
|     type_: Type, | ||||
|     type_: SocketType, | ||||
|     nonblocking: AtomicBool, | ||||
|     is_closed: AtomicBool, | ||||
|     pollee: Pollee, | ||||
| @ -30,7 +30,7 @@ pub struct Common<A: Addr + 'static, R: Runtime> { | ||||
| } | ||||
| 
 | ||||
| impl<A: Addr + 'static, R: Runtime> Common<A, R> { | ||||
|     pub fn new(type_: Type, nonblocking: bool, protocol: Option<i32>) -> Result<Self> { | ||||
|     pub fn new(type_: SocketType, nonblocking: bool, protocol: Option<i32>) -> Result<Self> { | ||||
|         let domain_c = A::domain() as libc::c_int; | ||||
|         let type_c = type_ as libc::c_int; | ||||
|         let protocol = protocol.unwrap_or(0) as libc::c_int; | ||||
| @ -56,11 +56,11 @@ impl<A: Addr + 'static, R: Runtime> Common<A, R> { | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn new_pair(sock_type: Type, nonblocking: bool) -> Result<(Self, Self)> { | ||||
|     pub fn new_pair(sock_type: SocketType, nonblocking: bool) -> Result<(Self, Self)> { | ||||
|         return_errno!(EINVAL, "Unix is unsupported"); | ||||
|     } | ||||
| 
 | ||||
|     pub fn with_host_fd(host_fd: FileDesc, type_: Type, nonblocking: bool) -> Self { | ||||
|     pub fn with_host_fd(host_fd: FileDesc, type_: SocketType, nonblocking: bool) -> Self { | ||||
|         let nonblocking = AtomicBool::new(nonblocking); | ||||
|         let is_closed = AtomicBool::new(false); | ||||
|         let pollee = Pollee::new(IoEvents::empty()); | ||||
| @ -90,7 +90,7 @@ impl<A: Addr + 'static, R: Runtime> Common<A, R> { | ||||
|         self.host_fd | ||||
|     } | ||||
| 
 | ||||
|     pub fn type_(&self) -> Type { | ||||
|     pub fn type_(&self) -> SocketType { | ||||
|         self.type_ | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -20,7 +20,7 @@ pub struct DatagramSocket<A: Addr + 'static, R: Runtime> { | ||||
| 
 | ||||
| impl<A: Addr, R: Runtime> DatagramSocket<A, R> { | ||||
|     pub fn new(nonblocking: bool) -> Result<Self> { | ||||
|         let common = Arc::new(Common::new(Type::DGRAM, nonblocking, None)?); | ||||
|         let common = Arc::new(Common::new(SocketType::DGRAM, nonblocking, None)?); | ||||
|         let state = RwLock::new(State::new()); | ||||
|         let sender = Sender::new(common.clone()); | ||||
|         let receiver = Receiver::new(common.clone()); | ||||
| @ -33,7 +33,7 @@ impl<A: Addr, R: Runtime> DatagramSocket<A, R> { | ||||
|     } | ||||
| 
 | ||||
|     pub fn new_pair(nonblocking: bool) -> Result<(Self, Self)> { | ||||
|         let (common1, common2) = Common::new_pair(Type::DGRAM, nonblocking)?; | ||||
|         let (common1, common2) = Common::new_pair(SocketType::DGRAM, nonblocking)?; | ||||
|         let socket1 = Self::new_connected(common1); | ||||
|         let socket2 = Self::new_connected(common2); | ||||
|         Ok((socket1, socket2)) | ||||
| @ -321,10 +321,10 @@ impl<A: Addr, R: Runtime> DatagramSocket<A, R> { | ||||
|                 cmd.execute(self.host_fd())?; | ||||
|             }, | ||||
|             cmd: SetRecvTimeoutCmd => { | ||||
|                 self.set_recv_timeout(*cmd.timeout()); | ||||
|                 self.set_recv_timeout(*cmd.input()); | ||||
|             }, | ||||
|             cmd: SetSendTimeoutCmd => { | ||||
|                 self.set_send_timeout(*cmd.timeout()); | ||||
|                 self.set_send_timeout(*cmd.input()); | ||||
|             }, | ||||
|             cmd: GetRecvTimeoutCmd => { | ||||
|                 let timeval = timeout_to_timeval(self.recv_timeout()); | ||||
|  | ||||
| @ -102,10 +102,10 @@ impl SocketFile { | ||||
|         apply_fn_on_any_socket!(&self.socket, |socket| { socket.ioctl(cmd) }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_type(&self) -> Type { | ||||
|     pub fn get_type(&self) -> SocketType { | ||||
|         match self.socket { | ||||
|             AnySocket::Ipv4Stream(_) | AnySocket::Ipv6Stream(_) => Type::STREAM, | ||||
|             AnySocket::Ipv4Datagram(_) | AnySocket::Ipv6Datagram(_) => Type::DGRAM, | ||||
|             AnySocket::Ipv4Stream(_) | AnySocket::Ipv6Stream(_) => SocketType::STREAM, | ||||
|             AnySocket::Ipv4Datagram(_) | AnySocket::Ipv6Datagram(_) => SocketType::DGRAM, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -115,11 +115,11 @@ impl SocketFile { | ||||
|     pub fn new( | ||||
|         domain: Domain, | ||||
|         protocol: SocketProtocol, | ||||
|         socket_type: Type, | ||||
|         socket_type: SocketType, | ||||
|         nonblocking: bool, | ||||
|     ) -> Result<Self> { | ||||
|         match socket_type { | ||||
|             Type::STREAM => { | ||||
|             SocketType::STREAM => { | ||||
|                 if protocol != SocketProtocol::IPPROTO_IP && protocol != SocketProtocol::IPPROTO_TCP | ||||
|                 { | ||||
|                     return_errno!(EPROTONOSUPPORT, "Protocol not supported"); | ||||
| @ -140,7 +140,7 @@ impl SocketFile { | ||||
|                 let new_self = Self { socket: any_socket }; | ||||
|                 Ok(new_self) | ||||
|             } | ||||
|             Type::DGRAM => { | ||||
|             SocketType::DGRAM => { | ||||
|                 if protocol != SocketProtocol::IPPROTO_IP && protocol != SocketProtocol::IPPROTO_UDP | ||||
|                 { | ||||
|                     return_errno!(EPROTONOSUPPORT, "Protocol not supported"); | ||||
| @ -161,7 +161,7 @@ impl SocketFile { | ||||
|                 let new_self = Self { socket: any_socket }; | ||||
|                 Ok(new_self) | ||||
|             } | ||||
|             Type::RAW => { | ||||
|             SocketType::RAW => { | ||||
|                 return_errno!(EINVAL, "RAW socket not supported"); | ||||
|             } | ||||
|             _ => { | ||||
| @ -210,7 +210,7 @@ impl SocketFile { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn bind(&self, addr: &mut AnyAddr) -> Result<()> { | ||||
|     pub fn bind(&self, addr: &AnyAddr) -> Result<()> { | ||||
|         match &self.socket { | ||||
|             AnySocket::Ipv4Stream(ipv4_stream) => { | ||||
|                 let ip_addr = addr.to_ipv4()?; | ||||
|  | ||||
| @ -57,7 +57,7 @@ impl<A: Addr, R: Runtime> StreamSocket<A, R> { | ||||
|     } | ||||
| 
 | ||||
|     pub fn new_pair(nonblocking: bool) -> Result<(Self, Self)> { | ||||
|         let (common1, common2) = Common::new_pair(Type::STREAM, nonblocking)?; | ||||
|         let (common1, common2) = Common::new_pair(SocketType::STREAM, nonblocking)?; | ||||
|         let connected1 = ConnectedStream::new(Arc::new(common1)); | ||||
|         let connected2 = ConnectedStream::new(Arc::new(common2)); | ||||
|         let socket1 = Self::new_connected(connected1); | ||||
| @ -373,10 +373,10 @@ impl<A: Addr, R: Runtime> StreamSocket<A, R> { | ||||
|                 cmd.execute(self.host_fd())?; | ||||
|             }, | ||||
|             cmd: SetRecvTimeoutCmd => { | ||||
|                 self.set_recv_timeout(*cmd.timeout()); | ||||
|                 self.set_recv_timeout(*cmd.input()); | ||||
|             }, | ||||
|             cmd: SetSendTimeoutCmd => { | ||||
|                 self.set_send_timeout(*cmd.timeout()); | ||||
|                 self.set_send_timeout(*cmd.input()); | ||||
|             }, | ||||
|             cmd: GetRecvTimeoutCmd => { | ||||
|                 let timeval = timeout_to_timeval(self.recv_timeout()); | ||||
| @ -386,21 +386,21 @@ impl<A: Addr, R: Runtime> StreamSocket<A, R> { | ||||
|                 let timeval = timeout_to_timeval(self.send_timeout()); | ||||
|                 cmd.set_output(timeval); | ||||
|             }, | ||||
|             cmd: SetSndBufSizeCmd => { | ||||
|             cmd: SetSendBufSizeCmd => { | ||||
|                 cmd.update_host(self.host_fd())?; | ||||
|                 let buf_size = cmd.buf_size(); | ||||
|                 let buf_size = *cmd.input(); | ||||
|                 self.set_kernel_send_buf_size(buf_size); | ||||
|             }, | ||||
|             cmd: SetRcvBufSizeCmd => { | ||||
|             cmd: SetRecvBufSizeCmd => { | ||||
|                 cmd.update_host(self.host_fd())?; | ||||
|                 let buf_size = cmd.buf_size(); | ||||
|                 let buf_size = *cmd.input(); | ||||
|                 self.set_kernel_recv_buf_size(buf_size); | ||||
|             }, | ||||
|             cmd: GetSndBufSizeCmd => { | ||||
|             cmd: GetSendBufSizeCmd => { | ||||
|                 let buf_size = SEND_BUF_SIZE.load(Ordering::Relaxed); | ||||
|                 cmd.set_output(buf_size); | ||||
|             }, | ||||
|             cmd: GetRcvBufSizeCmd => { | ||||
|             cmd: GetRecvBufSizeCmd => { | ||||
|                 let buf_size = RECV_BUF_SIZE.load(Ordering::Relaxed); | ||||
|                 cmd.set_output(buf_size); | ||||
|             }, | ||||
| @ -454,6 +454,8 @@ impl<A: Addr, R: Runtime> StreamSocket<A, R> { | ||||
|     } | ||||
| 
 | ||||
|     fn set_kernel_send_buf_size(&self, buf_size: usize) { | ||||
|         // Setting the minimal buf_size to 128 Kbytes
 | ||||
|         let buf_size = (128 * 1024 + 1).max(buf_size); | ||||
|         let state = self.state.read().unwrap(); | ||||
|         match &*state { | ||||
|             State::Init(_) | State::Listen(_) | State::Connect(_) => { | ||||
| @ -467,6 +469,8 @@ impl<A: Addr, R: Runtime> StreamSocket<A, R> { | ||||
|     } | ||||
| 
 | ||||
|     fn set_kernel_recv_buf_size(&self, buf_size: usize) { | ||||
|         // Setting the minimal buf_size to 128 Kbytes
 | ||||
|         let buf_size = (128 * 1024 + 1).max(buf_size); | ||||
|         let state = self.state.read().unwrap(); | ||||
|         match &*state { | ||||
|             State::Init(_) | State::Listen(_) | State::Connect(_) => { | ||||
|  | ||||
| @ -191,7 +191,6 @@ impl<A: Addr + 'static, R: Runtime> ConnectedStream<A, R> { | ||||
|         // Init the callback invoked upon the completion of the async recv
 | ||||
|         let stream = self.clone(); | ||||
|         let complete_fn = move |retval: i32| { | ||||
|             // let mut inner = stream.receiver.inner.lock().unwrap();
 | ||||
|             let mut inner = stream.receiver.inner.lock(); | ||||
|             trace!("recv request complete with retval: {:?}", retval); | ||||
| 
 | ||||
| @ -232,7 +231,9 @@ impl<A: Addr + 'static, R: Runtime> ConnectedStream<A, R> { | ||||
|             // ready to read.
 | ||||
|             stream.common.pollee().add_events(Events::IN); | ||||
| 
 | ||||
|             stream.do_recv(&mut inner); | ||||
|             if !stream.receiver.need_update() { | ||||
|                 stream.do_recv(&mut inner); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         // Generate the async recv request
 | ||||
|  | ||||
| @ -183,7 +183,14 @@ impl<A: Addr + 'static, R: Runtime> ConnectedStream<A, R> { | ||||
| 
 | ||||
|                 inner.fatal = Some(errno); | ||||
|                 stream.common.set_errno(errno); | ||||
|                 stream.common.pollee().add_events(Events::ERR); | ||||
| 
 | ||||
|                 let events = if errno == ENOTCONN || errno == ECONNRESET || errno == ECONNREFUSED { | ||||
|                     Events::HUP | Events::OUT | Events::ERR | ||||
|                 } else { | ||||
|                     Events::ERR | ||||
|                 }; | ||||
| 
 | ||||
|                 stream.common.pollee().add_events(events); | ||||
|                 return; | ||||
|             } | ||||
|             assert!(retval != 0); | ||||
|  | ||||
| @ -15,7 +15,7 @@ struct Inner { | ||||
| 
 | ||||
| impl<A: Addr + 'static, R: Runtime> InitStream<A, R> { | ||||
|     pub fn new(nonblocking: bool) -> Result<Arc<Self>> { | ||||
|         let common = Arc::new(Common::new(Type::STREAM, nonblocking, None)?); | ||||
|         let common = Arc::new(Common::new(SocketType::STREAM, nonblocking, None)?); | ||||
|         common.pollee().add_events(IoEvents::HUP | IoEvents::OUT); | ||||
|         let inner = Mutex::new(Inner::new()); | ||||
|         let new_self = Self { common, inner }; | ||||
|  | ||||
| @ -121,7 +121,11 @@ impl<A: Addr + 'static, R: Runtime> ListenerStream<A, R> { | ||||
|         self.initiate_async_accepts(inner); | ||||
| 
 | ||||
|         let common = { | ||||
|             let common = Arc::new(Common::with_host_fd(accepted_fd, Type::STREAM, nonblocking)); | ||||
|             let common = Arc::new(Common::with_host_fd( | ||||
|                 accepted_fd, | ||||
|                 SocketType::STREAM, | ||||
|                 nonblocking, | ||||
|             )); | ||||
|             common.set_peer_addr(&accepted_addr); | ||||
|             common | ||||
|         }; | ||||
|  | ||||
| @ -1,7 +1,8 @@ | ||||
| use crate::net::{Addr, Domain}; | ||||
| use std::any::Any; | ||||
| use std::fmt::{self, Debug}; | ||||
| 
 | ||||
| use super::{Addr, CSockAddr, Domain, RawAddr}; | ||||
| use super::{CSockAddr, SockAddr}; | ||||
| use crate::prelude::*; | ||||
| 
 | ||||
| /// An IPv4 socket address, consisting of an IPv4 address and a port.
 | ||||
| @ -70,9 +71,9 @@ impl Ipv4SocketAddr { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_raw(&self) -> RawAddr { | ||||
|     pub fn to_raw(&self) -> SockAddr { | ||||
|         let (storage, len) = self.to_c_storage(); | ||||
|         RawAddr::from_c_storage(&storage, len) | ||||
|         SockAddr::from_c_storage(&storage, len) | ||||
|     } | ||||
| 
 | ||||
|     pub fn ip(&self) -> &Ipv4Addr { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use std::any::Any; | ||||
| use std::fmt::Debug; | ||||
| 
 | ||||
| use super::RawAddr; | ||||
| use super::SockAddr; | ||||
| use super::{Addr, CSockAddr, Domain}; | ||||
| use crate::prelude::*; | ||||
| use libc::in6_addr; | ||||
| @ -85,9 +85,9 @@ impl Ipv6SocketAddr { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_raw(&self) -> RawAddr { | ||||
|     pub fn to_raw(&self) -> SockAddr { | ||||
|         let (storage, len) = self.to_c_storage(); | ||||
|         RawAddr::from_c_storage(&storage, len) | ||||
|         SockAddr::from_c_storage(&storage, len) | ||||
|     } | ||||
| 
 | ||||
|     pub fn ip(&self) -> &Ipv6Addr { | ||||
|  | ||||
| @ -38,7 +38,7 @@ pub trait Addr: Clone + Debug + Default + PartialEq + Send + Sync { | ||||
| pub use self::c_sock_addr::CSockAddr; | ||||
| pub use self::ipv4::{Ipv4Addr, Ipv4SocketAddr}; | ||||
| pub use self::ipv6::{Ipv6Addr, Ipv6SocketAddr}; | ||||
| pub use self::raw_addr::RawAddr; | ||||
| pub use self::raw_addr::SockAddr; | ||||
| pub use self::unix_addr::UnixAddr; | ||||
| 
 | ||||
| #[cfg(test)] | ||||
|  | ||||
| @ -2,22 +2,22 @@ use super::*; | ||||
| use std::*; | ||||
| 
 | ||||
| #[derive(Copy, Clone)] | ||||
| pub struct RawAddr { | ||||
| pub struct SockAddr { | ||||
|     storage: libc::sockaddr_storage, | ||||
|     len: usize, | ||||
| } | ||||
| 
 | ||||
| // TODO: add more fields
 | ||||
| impl fmt::Debug for RawAddr { | ||||
| impl fmt::Debug for SockAddr { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         f.debug_struct("RawAddr") | ||||
|         f.debug_struct("SockAddr") | ||||
|             .field("family", &Domain::try_from(self.storage.ss_family).unwrap()) | ||||
|             .field("len", &self.len) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl RawAddr { | ||||
| impl SockAddr { | ||||
|     pub fn from_c_storage(c_addr: &libc::sockaddr_storage, c_addr_len: usize) -> Self { | ||||
|         Self { | ||||
|             storage: *c_addr, | ||||
| @ -118,7 +118,7 @@ impl RawAddr { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Default for RawAddr { | ||||
| impl Default for SockAddr { | ||||
|     fn default() -> Self { | ||||
|         let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; | ||||
|         Self { | ||||
|  | ||||
| @ -106,7 +106,7 @@ impl UnixAddr { | ||||
|         /// The '/0' at the end of Self::File counts
 | ||||
|         match self.path_str() { | ||||
|             Ok(str) => str.len() + 1 + *SUN_PATH_OFFSET, | ||||
|             Err(_) => 0, | ||||
|             Err(_) => std::mem::size_of::<libc::sa_family_t>(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -123,9 +123,9 @@ impl UnixAddr { | ||||
|         c_un_addr.to_c_storage() | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_raw(&self) -> RawAddr { | ||||
|     pub fn to_raw(&self) -> SockAddr { | ||||
|         let (storage, addr_len) = self.to_c_storage(); | ||||
|         RawAddr::from_c_storage(&storage, addr_len) | ||||
|         SockAddr::from_c_storage(&storage, addr_len) | ||||
|     } | ||||
| 
 | ||||
|     fn to_c(&self) -> (libc::sockaddr_un, usize) { | ||||
|  | ||||
| @ -3,7 +3,7 @@ use std::mem::{self, MaybeUninit}; | ||||
| use crate::net::socket::Domain; | ||||
| use crate::prelude::*; | ||||
| 
 | ||||
| use super::{Addr, CSockAddr, Ipv4Addr, Ipv4SocketAddr, Ipv6SocketAddr, RawAddr, UnixAddr}; | ||||
| use super::{Addr, CSockAddr, Ipv4Addr, Ipv4SocketAddr, Ipv6SocketAddr, SockAddr, UnixAddr}; | ||||
| use num_enum::IntoPrimitive; | ||||
| use std::path::Path; | ||||
| 
 | ||||
| @ -12,7 +12,7 @@ pub enum AnyAddr { | ||||
|     Ipv4(Ipv4SocketAddr), | ||||
|     Ipv6(Ipv6SocketAddr), | ||||
|     Unix(UnixAddr), | ||||
|     Raw(RawAddr), | ||||
|     Raw(SockAddr), | ||||
|     Unspec, | ||||
| } | ||||
| 
 | ||||
| @ -33,7 +33,7 @@ impl AnyAddr { | ||||
|                 Self::Unix(unix_addr) | ||||
|             } | ||||
|             _ => { | ||||
|                 let raw_addr = RawAddr::from_c_storage(c_addr, c_addr_len); | ||||
|                 let raw_addr = SockAddr::from_c_storage(c_addr, c_addr_len); | ||||
|                 Self::Raw(raw_addr) | ||||
|             } | ||||
|         }; | ||||
| @ -55,7 +55,7 @@ impl AnyAddr { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_raw(&self) -> RawAddr { | ||||
|     pub fn to_raw(&self) -> SockAddr { | ||||
|         match self { | ||||
|             Self::Ipv4(ipv4_addr) => ipv4_addr.to_raw(), | ||||
|             Self::Ipv6(ipv6_addr) => ipv6_addr.to_raw(), | ||||
| @ -65,7 +65,7 @@ impl AnyAddr { | ||||
|                 let mut sockaddr_storage = | ||||
|                     unsafe { MaybeUninit::<libc::sockaddr_storage>::uninit().assume_init() }; | ||||
|                 sockaddr_storage.ss_family = libc::AF_UNSPEC as _; | ||||
|                 RawAddr::from_c_storage(&sockaddr_storage, mem::size_of::<libc::sa_family_t>()) | ||||
|                 SockAddr::from_c_storage(&sockaddr_storage, mem::size_of::<libc::sa_family_t>()) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -77,13 +77,6 @@ impl AnyAddr { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn as_ipv4(&self) -> Option<&Ipv4SocketAddr> { | ||||
|         match self { | ||||
|             Self::Ipv4(ipv4_addr) => Some(ipv4_addr), | ||||
|             _ => None, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_ipv4(&self) -> Result<&Ipv4SocketAddr> { | ||||
|         match self { | ||||
|             Self::Ipv4(ipv4_addr) => Ok(ipv4_addr), | ||||
|  | ||||
| @ -1,4 +1,6 @@ | ||||
| use bitflags::bitflags; | ||||
| use sgx_trts::libc; | ||||
| use std::ffi::c_uint; | ||||
| 
 | ||||
| // Flags to use when sending data through a socket
 | ||||
| bitflags! { | ||||
| @ -37,3 +39,18 @@ bitflags! { | ||||
|         const MSG_NOTIFICATION = 0x8000;     // Only applicable to SCTP socket
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Flags to use when creating a new socket
 | ||||
| bitflags! { | ||||
|     pub struct SocketFlags: i32 { | ||||
|         const SOCK_NONBLOCK = 0x800; | ||||
|         const SOCK_CLOEXEC  = 0x80000; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[repr(C)] | ||||
| #[derive(Copy, Clone)] | ||||
| pub struct mmsghdr { | ||||
|     pub msg_hdr: libc::msghdr, | ||||
|     pub msg_len: c_uint, | ||||
| } | ||||
|  | ||||
| @ -15,13 +15,13 @@ mod shutdown; | ||||
| mod r#type; | ||||
| 
 | ||||
| pub use self::addr::{ | ||||
|     Addr, CSockAddr, Ipv4Addr, Ipv4SocketAddr, Ipv6SocketAddr, RawAddr, UnixAddr, | ||||
|     Addr, CSockAddr, Ipv4Addr, Ipv4SocketAddr, Ipv6SocketAddr, SockAddr, UnixAddr, | ||||
| }; | ||||
| pub use self::any_addr::AnyAddr; | ||||
| pub use self::domain::Domain; | ||||
| pub use self::flags::{MsgFlags, RecvFlags, SendFlags}; | ||||
| pub use self::flags::{mmsghdr, MsgFlags, RecvFlags, SendFlags, SocketFlags}; | ||||
| pub use self::iovs::{Iovs, IovsMut, SliceAsLibcIovec}; | ||||
| pub use self::msg::{CMessages, CmsgData}; | ||||
| pub use self::protocol::SocketProtocol; | ||||
| pub use self::r#type::Type; | ||||
| pub use self::r#type::SocketType; | ||||
| pub use self::shutdown::Shutdown; | ||||
|  | ||||
| @ -4,7 +4,7 @@ use num_enum::{IntoPrimitive, TryFromPrimitive}; | ||||
| /// A network type.
 | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)] | ||||
| #[repr(i32)] | ||||
| pub enum Type { | ||||
| pub enum SocketType { | ||||
|     STREAM = libc::SOCK_STREAM, | ||||
|     DGRAM = libc::SOCK_DGRAM, | ||||
|     RAW = libc::SOCK_RAW, | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| use super::socket::{MsgFlags, SocketProtocol}; | ||||
| use super::{socket::uring::socket_file::SocketFile, *}; | ||||
| use super::socket::{mmsghdr, MsgFlags, SocketFlags, SocketProtocol}; | ||||
| 
 | ||||
| use atomic::Ordering; | ||||
| use core::f32::consts::E; | ||||
| @ -17,15 +16,6 @@ use std::convert::TryFrom; | ||||
| use time::{timespec_t, timeval_t}; | ||||
| use util::mem_util::from_user; | ||||
| 
 | ||||
| use super::socket::sockopt::{ | ||||
|     GetAcceptConnCmd, GetDomainCmd, GetErrorCmd, GetOutputAsBytes, GetPeerNameCmd, | ||||
|     GetRcvBufSizeCmd, GetRecvTimeoutCmd, GetSendTimeoutCmd, GetSndBufSizeCmd, GetSockOptRawCmd, | ||||
|     GetTypeCmd, SetRcvBufSizeCmd, SetRecvTimeoutCmd, SetSendTimeoutCmd, SetSndBufSizeCmd, | ||||
|     SetSockOptRawCmd, SockOptName, | ||||
| }; | ||||
| use super::socket::uring::UringSocketType; | ||||
| use super::socket::AnyAddr; | ||||
| 
 | ||||
| use super::*; | ||||
| 
 | ||||
| use crate::fs::StatusFlags; | ||||
| @ -36,20 +26,13 @@ use crate::prelude::*; | ||||
| const SOMAXCONN: u32 = 4096; | ||||
| const SOCONN_DEFAULT: u32 = 16; | ||||
| 
 | ||||
| #[repr(C)] | ||||
| #[derive(Copy, Clone)] | ||||
| pub struct mmsghdr { | ||||
|     pub msg_hdr: libc::msghdr, | ||||
|     pub msg_len: c_uint, | ||||
| } | ||||
| 
 | ||||
| pub fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize> { | ||||
|     let domain = Domain::try_from(domain as u16)?; | ||||
|     let flags = SocketFlags::from_bits_truncate(socket_type); | ||||
| 
 | ||||
|     let type_bits = socket_type & !flags.bits(); | ||||
|     let socket_type = | ||||
|         Type::try_from(type_bits).map_err(|_| errno!(EINVAL, "invalid socket type"))?; | ||||
|         SocketType::try_from(type_bits).map_err(|_| errno!(EINVAL, "invalid socket type"))?; | ||||
| 
 | ||||
|     debug!( | ||||
|         "socket domain: {:?}, type: {:?}, protocol: {:?}", | ||||
| @ -64,7 +47,8 @@ pub fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<i | ||||
| 
 | ||||
|         // Determine if type and domain match uring supported socket
 | ||||
|         let match_uring = move || { | ||||
|             let is_uring_type = (socket_type == Type::DGRAM || socket_type == Type::STREAM); | ||||
|             let is_uring_type = | ||||
|                 (socket_type == SocketType::DGRAM || socket_type == SocketType::STREAM); | ||||
|             let is_uring_protocol = (protocol == SocketProtocol::IPPROTO_IP | ||||
|                 || protocol == SocketProtocol::IPPROTO_TCP | ||||
|                 || protocol == SocketProtocol::IPPROTO_UDP); | ||||
| @ -100,20 +84,24 @@ pub fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<i | ||||
| } | ||||
| 
 | ||||
| pub fn do_bind(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result<isize> { | ||||
|     let addr_len = addr_len as usize; | ||||
|     let sockaddr_storage = copy_sock_addr_from_user(addr, addr_len)?; | ||||
|     let mut addr = AnyAddr::from_c_storage(&sockaddr_storage, addr_len)?; | ||||
|     let addr = { | ||||
|         let addr_len = addr_len as usize; | ||||
|         let sockaddr_storage = copy_sock_addr_from_user(addr, addr_len)?; | ||||
|         let addr = AnyAddr::from_c_storage(&sockaddr_storage, addr_len)?; | ||||
|         addr | ||||
|     }; | ||||
| 
 | ||||
|     trace!("bind to addr: {:?}", addr); | ||||
| 
 | ||||
|     let file_ref = current!().file(fd as FileDesc)?; | ||||
|     if let Ok(socket) = file_ref.as_host_socket() { | ||||
|         let mut raw_addr = addr.to_raw(); | ||||
|         socket.bind(&mut raw_addr)?; | ||||
|         let raw_addr = addr.to_raw(); | ||||
|         socket.bind(&raw_addr)?; | ||||
|     } else if let Ok(unix_socket) = file_ref.as_unix_socket() { | ||||
|         let mut unix_addr = (addr.to_unix()?).clone(); | ||||
|         unix_socket.bind(&mut unix_addr)?; | ||||
|         let unix_addr = addr.to_unix()?; | ||||
|         unix_socket.bind(unix_addr)?; | ||||
|     } else if let Ok(uring_socket) = file_ref.as_uring_socket() { | ||||
|         uring_socket.bind(&mut addr)?; | ||||
|         uring_socket.bind(&addr)?; | ||||
|     } else { | ||||
|         return_errno!(ENOTSOCK, "not a socket"); | ||||
|     } | ||||
| @ -159,18 +147,21 @@ pub fn do_connect( | ||||
|     let file_ref = current!().file(fd as FileDesc)?; | ||||
|     if let Ok(socket) = file_ref.as_host_socket() { | ||||
|         let addr_option = if addr_set { | ||||
|             Some(unsafe { RawAddr::try_from_raw(addr, addr_len as u32)? }) | ||||
|             Some(unsafe { SockAddr::try_from_raw(addr, addr_len as u32)? }) | ||||
|         } else { | ||||
|             None | ||||
|         }; | ||||
| 
 | ||||
|         socket.connect(&addr_option)?; | ||||
|         socket.connect(addr_option.as_ref())?; | ||||
|         return Ok(0); | ||||
|     }; | ||||
| 
 | ||||
|     let addr_len = addr_len as usize; | ||||
|     let sockaddr_storage = copy_sock_addr_from_user(addr, addr_len)?; | ||||
|     let addr = AnyAddr::from_c_storage(&sockaddr_storage, addr_len)?; | ||||
|     let addr = { | ||||
|         let addr_len = addr_len as usize; | ||||
|         let sockaddr_storage = copy_sock_addr_from_user(addr, addr_len)?; | ||||
|         let addr = AnyAddr::from_c_storage(&sockaddr_storage, addr_len)?; | ||||
|         addr | ||||
|     }; | ||||
| 
 | ||||
|     if let Ok(unix_socket) = file_ref.as_unix_socket() { | ||||
|         // TODO: support AF_UNSPEC address for datagram socket use
 | ||||
| @ -415,19 +406,17 @@ pub fn do_sendto( | ||||
| 
 | ||||
|     let file_ref = current!().file(fd as FileDesc)?; | ||||
|     if let Ok(host_socket) = file_ref.as_host_socket() { | ||||
|         let addr = addr.map(|any_addr| any_addr.to_raw()); | ||||
| 
 | ||||
|         host_socket | ||||
|             .sendto(buf, send_flags, &addr) | ||||
|             .sendto(buf, send_flags, addr) | ||||
|             .map(|u| u as isize) | ||||
|     } else if let Ok(unix_socket) = file_ref.as_unix_socket() { | ||||
|         let addr = match addr { | ||||
|             Some(any_addr) => Some(any_addr.to_unix()?.clone()), | ||||
|             Some(ref any_addr) => Some(any_addr.to_unix()?), | ||||
|             None => None, | ||||
|         }; | ||||
| 
 | ||||
|         unix_socket | ||||
|             .sendto(buf, send_flags, &addr) | ||||
|             .sendto(buf, send_flags, addr) | ||||
|             .map(|u| u as isize) | ||||
|     } else if let Ok(uring_socket) = file_ref.as_uring_socket() { | ||||
|         uring_socket | ||||
| @ -458,9 +447,7 @@ pub fn do_recvfrom( | ||||
| 
 | ||||
|     let file_ref = current!().file(fd as FileDesc)?; | ||||
|     let (data_len, addr_recv) = if let Ok(socket) = file_ref.as_host_socket() { | ||||
|         socket | ||||
|             .recvfrom(buf, recv_flags) | ||||
|             .map(|(len, addr_recv)| (len, addr_recv.map(|raw_addr| AnyAddr::Raw(raw_addr))))? | ||||
|         socket.recvfrom(buf, recv_flags)? | ||||
|     } else if let Ok(unix_socket) = file_ref.as_unix_socket() { | ||||
|         unix_socket | ||||
|             .recvfrom(buf, recv_flags) | ||||
| @ -496,7 +483,7 @@ pub fn do_socketpair( | ||||
| 
 | ||||
|     let file_flags = SocketFlags::from_bits_truncate(socket_type); | ||||
|     let close_on_spawn = file_flags.contains(SocketFlags::SOCK_CLOEXEC); | ||||
|     let sock_type = Type::try_from(socket_type & (!file_flags.bits())) | ||||
|     let sock_type = SocketType::try_from(socket_type & (!file_flags.bits())) | ||||
|         .map_err(|_| errno!(EINVAL, "invalid socket type"))?; | ||||
| 
 | ||||
|     let domain = Domain::try_from(domain as u16)?; | ||||
| @ -526,9 +513,8 @@ pub fn do_sendmsg(fd: c_int, msg_ptr: *const libc::msghdr, flags_c: c_int) -> Re | ||||
| 
 | ||||
|     let file_ref = current!().file(fd as FileDesc)?; | ||||
|     if let Ok(host_socket) = file_ref.as_host_socket() { | ||||
|         let raw_addr = addr.map(|addr| addr.to_raw()); | ||||
|         host_socket | ||||
|             .sendmsg(&bufs[..], flags, &raw_addr, control) | ||||
|             .sendmsg(&bufs[..], flags, addr, control) | ||||
|             .map(|bytes_send| bytes_send as isize) | ||||
|     } else if let Ok(socket) = file_ref.as_unix_socket() { | ||||
|         socket | ||||
| @ -554,20 +540,9 @@ pub fn do_recvmsg(fd: c_int, msg_mut_ptr: *mut libc::msghdr, flags_c: c_int) -> | ||||
|     let file_ref = current!().file(fd as FileDesc)?; | ||||
|     let (bytes_recv, recv_addr, msg_flags, msg_controllen) = | ||||
|         if let Ok(host_socket) = file_ref.as_host_socket() { | ||||
|             host_socket.recvmsg(&mut bufs[..], flags, control).map( | ||||
|                 |(bytes, addr, msg, controllen)| { | ||||
|                     ( | ||||
|                         bytes, | ||||
|                         addr.map(|raw_addr| AnyAddr::Raw(raw_addr)), | ||||
|                         msg, | ||||
|                         controllen, | ||||
|                     ) | ||||
|                 }, | ||||
|             )? | ||||
|             host_socket.recvmsg(&mut bufs[..], flags, control)? | ||||
|         } else if let Ok(unix_socket) = file_ref.as_unix_socket() { | ||||
|             unix_socket.recvmsg(&mut bufs[..], flags, control).map( | ||||
|                 |(bytes_recvd, control_len)| (bytes_recvd, None, MsgFlags::empty(), control_len), | ||||
|             )? | ||||
|             unix_socket.recvmsg(&mut bufs[..], flags, control)? | ||||
|         } else if let Ok(uring_socket) = file_ref.as_uring_socket() { | ||||
|             uring_socket.recvmsg(&mut bufs[..], flags, control)? | ||||
|         } else { | ||||
| @ -610,13 +585,12 @@ pub fn do_sendmmsg( | ||||
| 
 | ||||
|     if let Ok(host_socket) = file_ref.as_host_socket() { | ||||
|         for mmsg in (msgvec) { | ||||
|             let (any_addr, bufs, control) = extract_msghdr_from_user(&mmsg.msg_hdr)?; | ||||
|             let raw_addr = any_addr.map(|any_addr| any_addr.to_raw()); | ||||
|             let (addr, bufs, control) = extract_msghdr_from_user(&mmsg.msg_hdr)?; | ||||
| 
 | ||||
|             if host_socket | ||||
|                 .sendmsg(&bufs[..], flags, &raw_addr, control) | ||||
|                 .sendmsg(&bufs[..], flags, addr, control) | ||||
|                 .map(|bytes_send| { | ||||
|                     mmsg.msg_len += bytes_send as c_uint; | ||||
|                     mmsg.msg_len = bytes_send as c_uint; | ||||
|                     bytes_send as isize | ||||
|                 }) | ||||
|                 .is_ok() | ||||
| @ -635,7 +609,7 @@ pub fn do_sendmmsg( | ||||
|             if uring_socket | ||||
|                 .sendmsg(&bufs[..], addr, flags, control) | ||||
|                 .map(|bytes_send| { | ||||
|                     mmsg.msg_len += bytes_send as c_uint; | ||||
|                     mmsg.msg_len = bytes_send as c_uint; | ||||
|                     bytes_send as isize | ||||
|                 }) | ||||
|                 .is_ok() | ||||
| @ -1021,18 +995,17 @@ fn copy_sock_addr_from_user( | ||||
|     let sockaddr_src_buf = from_user::make_slice(addr as *const u8, addr_len)?; | ||||
| 
 | ||||
|     let sockaddr_storage = { | ||||
|         // Safety. The content will be initialized before function returns.
 | ||||
|         let mut sockaddr_storage = | ||||
|             unsafe { MaybeUninit::<libc::sockaddr_storage>::uninit().assume_init() }; | ||||
|         let mut sockaddr_storage = MaybeUninit::<libc::sockaddr_storage>::uninit(); | ||||
|         // Safety. The dst slice is the only mutable reference to the sockaddr_storage
 | ||||
|         let sockaddr_dst_buf = unsafe { | ||||
|             let ptr = &mut sockaddr_storage as *mut _ as *mut u8; | ||||
|             let ptr = sockaddr_storage.as_mut_ptr() as *mut u8; | ||||
|             let len = addr_len; | ||||
|             std::slice::from_raw_parts_mut(ptr, len) | ||||
|         }; | ||||
|         sockaddr_dst_buf.copy_from_slice(sockaddr_src_buf); | ||||
|         sockaddr_storage | ||||
|         unsafe { sockaddr_storage.assume_init() } | ||||
|     }; | ||||
| 
 | ||||
|     Ok(sockaddr_storage) | ||||
| } | ||||
| 
 | ||||
| @ -1088,7 +1061,7 @@ fn new_uring_getsockopt_cmd( | ||||
|     level: i32, | ||||
|     optname: i32, | ||||
|     optlen: u32, | ||||
|     socket_type: Type, | ||||
|     socket_type: SocketType, | ||||
| ) -> Result<Box<dyn IoctlCmd>> { | ||||
|     if level != libc::SOL_SOCKET { | ||||
|         return Ok(Box::new(GetSockOptRawCmd::new(level, optname, optlen))); | ||||
| @ -1106,17 +1079,17 @@ fn new_uring_getsockopt_cmd( | ||||
|         SockOptName::SO_RCVTIMEO_OLD => Box::new(GetRecvTimeoutCmd::new(())), | ||||
|         SockOptName::SO_SNDTIMEO_OLD => Box::new(GetSendTimeoutCmd::new(())), | ||||
|         SockOptName::SO_SNDBUF => { | ||||
|             if socket_type == Type::STREAM { | ||||
|             if socket_type == SocketType::STREAM { | ||||
|                 // Implement dynamic buf size for stream socket only.
 | ||||
|                 Box::new(GetSndBufSizeCmd::new(())) | ||||
|                 Box::new(GetSendBufSizeCmd::new(())) | ||||
|             } else { | ||||
|                 Box::new(GetSockOptRawCmd::new(level, optname, optlen)) | ||||
|             } | ||||
|         } | ||||
|         SockOptName::SO_RCVBUF => { | ||||
|             if socket_type == Type::STREAM { | ||||
|             if socket_type == SocketType::STREAM { | ||||
|                 // Implement dynamic buf size for stream socket only.
 | ||||
|                 Box::new(GetRcvBufSizeCmd::new(())) | ||||
|                 Box::new(GetRecvBufSizeCmd::new(())) | ||||
|             } else { | ||||
|                 Box::new(GetSockOptRawCmd::new(level, optname, optlen)) | ||||
|             } | ||||
| @ -1163,161 +1136,153 @@ fn new_uring_setsockopt_cmd( | ||||
|     level: i32, | ||||
|     optname: i32, | ||||
|     optval: &'static [u8], | ||||
|     socket_type: Type, | ||||
|     socket_type: SocketType, | ||||
| ) -> Result<Box<dyn IoctlCmd>> { | ||||
|     if level != libc::SOL_SOCKET { | ||||
|         return Ok(Box::new(SetSockOptRawCmd::new(level, optname, optval))); | ||||
|     } | ||||
| 
 | ||||
|     if optval.len() == 0 { | ||||
|         return_errno!(EINVAL, "Not a valid optval length"); | ||||
|     } | ||||
| 
 | ||||
|     let opt = | ||||
|         SockOptName::try_from(optname).map_err(|_| errno!(ENOPROTOOPT, "Not a valid optname"))?; | ||||
| 
 | ||||
|     let enable_uring = ENABLE_URING.load(Ordering::Relaxed); | ||||
|     if !enable_uring { | ||||
|         Ok(match opt { | ||||
|             SockOptName::SO_ACCEPTCONN | ||||
|             | SockOptName::SO_DOMAIN | ||||
|             | SockOptName::SO_PEERNAME | ||||
|             | SockOptName::SO_TYPE | ||||
|             | SockOptName::SO_ERROR | ||||
|             | SockOptName::SO_PEERCRED | ||||
|             | SockOptName::SO_SNDLOWAT | ||||
|             | SockOptName::SO_PEERSEC | ||||
|             | SockOptName::SO_PROTOCOL | ||||
|             | SockOptName::SO_MEMINFO | ||||
|             | SockOptName::SO_INCOMING_NAPI_ID | ||||
|             | SockOptName::SO_COOKIE | ||||
|             | SockOptName::SO_PEERGROUPS => return_errno!(ENOPROTOOPT, "it's a read-only option"), | ||||
|             _ => Box::new(SetSockOptRawCmd::new(level, optname, optval)), | ||||
|         }) | ||||
|     } else { | ||||
|         Ok(match opt { | ||||
|             SockOptName::SO_ACCEPTCONN | ||||
|             | SockOptName::SO_DOMAIN | ||||
|             | SockOptName::SO_PEERNAME | ||||
|             | SockOptName::SO_TYPE | ||||
|             | SockOptName::SO_ERROR | ||||
|             | SockOptName::SO_PEERCRED | ||||
|             | SockOptName::SO_SNDLOWAT | ||||
|             | SockOptName::SO_PEERSEC | ||||
|             | SockOptName::SO_PROTOCOL | ||||
|             | SockOptName::SO_MEMINFO | ||||
|             | SockOptName::SO_INCOMING_NAPI_ID | ||||
|             | SockOptName::SO_COOKIE | ||||
|             | SockOptName::SO_PEERGROUPS => return_errno!(ENOPROTOOPT, "it's a read-only option"), | ||||
|             SockOptName::SO_RCVTIMEO_OLD => { | ||||
|                 let mut timeout: *const libc::timeval = std::ptr::null(); | ||||
|                 if optval.len() >= std::mem::size_of::<libc::timeval>() { | ||||
|                     timeout = optval as *const _ as *const libc::timeval; | ||||
|                 } else { | ||||
|                     return_errno!(EINVAL, "invalid timeout option"); | ||||
|                 } | ||||
|                 let timeout = unsafe { | ||||
|                     let secs = if (*timeout).tv_sec < 0 { | ||||
|                         0 | ||||
|                     } else { | ||||
|                         (*timeout).tv_sec | ||||
|                     }; | ||||
| 
 | ||||
|                     let usec = (*timeout).tv_usec; | ||||
|                     if usec < 0 || usec > 1000000 || (usec as u32).checked_mul(1000).is_none() { | ||||
|                         return_errno!(EDOM, "time struct value is invalid"); | ||||
|                     } | ||||
|                     Duration::new(secs as u64, (*timeout).tv_usec as u32 * 1000) | ||||
|                 }; | ||||
|                 trace!("recv timeout = {:?}", timeout); | ||||
|                 Box::new(SetRecvTimeoutCmd::new(timeout)) | ||||
|     Ok(match opt { | ||||
|         SockOptName::SO_ACCEPTCONN | ||||
|         | SockOptName::SO_DOMAIN | ||||
|         | SockOptName::SO_PEERNAME | ||||
|         | SockOptName::SO_TYPE | ||||
|         | SockOptName::SO_ERROR | ||||
|         | SockOptName::SO_PEERCRED | ||||
|         | SockOptName::SO_SNDLOWAT | ||||
|         | SockOptName::SO_PEERSEC | ||||
|         | SockOptName::SO_PROTOCOL | ||||
|         | SockOptName::SO_MEMINFO | ||||
|         | SockOptName::SO_INCOMING_NAPI_ID | ||||
|         | SockOptName::SO_COOKIE | ||||
|         | SockOptName::SO_PEERGROUPS => return_errno!(ENOPROTOOPT, "it's a read-only option"), | ||||
|         SockOptName::SO_RCVTIMEO_OLD => { | ||||
|             let mut timeout: *const libc::timeval = std::ptr::null(); | ||||
|             if optval.len() >= std::mem::size_of::<libc::timeval>() { | ||||
|                 timeout = optval as *const _ as *const libc::timeval; | ||||
|             } else { | ||||
|                 return_errno!(EINVAL, "invalid timeout option"); | ||||
|             } | ||||
|             SockOptName::SO_SNDTIMEO_OLD => { | ||||
|                 let mut timeout: *const libc::timeval = std::ptr::null(); | ||||
|                 if optval.len() >= std::mem::size_of::<libc::timeval>() { | ||||
|                     timeout = optval as *const _ as *const libc::timeval; | ||||
|             let timeout = unsafe { | ||||
|                 let secs = if (*timeout).tv_sec < 0 { | ||||
|                     0 | ||||
|                 } else { | ||||
|                     return_errno!(EINVAL, "invalid timeout option"); | ||||
|                 } | ||||
|                 let timeout = unsafe { | ||||
|                     let secs = if (*timeout).tv_sec < 0 { | ||||
|                         0 | ||||
|                     } else { | ||||
|                         (*timeout).tv_sec | ||||
|                     }; | ||||
| 
 | ||||
|                     let usec = (*timeout).tv_usec; | ||||
|                     if usec < 0 || usec > 1000000 || (usec as u32).checked_mul(1000).is_none() { | ||||
|                         return_errno!(EDOM, "time struct value is invalid"); | ||||
|                     } | ||||
|                     Duration::new(secs as u64, usec as u32 * 1000) | ||||
|                     (*timeout).tv_sec | ||||
|                 }; | ||||
|                 trace!("send timeout = {:?}", timeout); | ||||
|                 Box::new(SetSendTimeoutCmd::new(timeout)) | ||||
| 
 | ||||
|                 let usec = (*timeout).tv_usec; | ||||
|                 if usec < 0 || usec > 1000000 || (usec as u32).checked_mul(1000).is_none() { | ||||
|                     return_errno!(EDOM, "time struct value is invalid"); | ||||
|                 } | ||||
|                 Duration::new(secs as u64, (*timeout).tv_usec as u32 * 1000) | ||||
|             }; | ||||
|             trace!("recv timeout = {:?}", timeout); | ||||
|             Box::new(SetRecvTimeoutCmd::new(timeout)) | ||||
|         } | ||||
|         SockOptName::SO_SNDTIMEO_OLD => { | ||||
|             let mut timeout: *const libc::timeval = std::ptr::null(); | ||||
|             if optval.len() >= std::mem::size_of::<libc::timeval>() { | ||||
|                 timeout = optval as *const _ as *const libc::timeval; | ||||
|             } else { | ||||
|                 return_errno!(EINVAL, "invalid timeout option"); | ||||
|             } | ||||
|             SockOptName::SO_SNDBUF => { | ||||
|             let timeout = unsafe { | ||||
|                 let secs = if (*timeout).tv_sec < 0 { | ||||
|                     0 | ||||
|                 } else { | ||||
|                     (*timeout).tv_sec | ||||
|                 }; | ||||
| 
 | ||||
|                 let usec = (*timeout).tv_usec; | ||||
|                 if usec < 0 || usec > 1000000 || (usec as u32).checked_mul(1000).is_none() { | ||||
|                     return_errno!(EDOM, "time struct value is invalid"); | ||||
|                 } | ||||
|                 Duration::new(secs as u64, usec as u32 * 1000) | ||||
|             }; | ||||
|             trace!("send timeout = {:?}", timeout); | ||||
|             Box::new(SetSendTimeoutCmd::new(timeout)) | ||||
|         } | ||||
|         SockOptName::SO_SNDBUF => { | ||||
|             // Implement dynamic buf size for stream socket only.
 | ||||
|             if socket_type != SocketType::STREAM { | ||||
|                 Box::new(SetSockOptRawCmd::new(level, optname, optval)) | ||||
|             } else { | ||||
|                 // Based on the man page: The minimum (doubled) value for this option is 2048.
 | ||||
|                 // However, the test on Linux shows the minimum value (doubled) is 4608. Here, we just
 | ||||
|                 // use the same value as Linux.
 | ||||
|                 let min_size = 128 * 1024; | ||||
|                 // For the max value, we choose 4MB (doubled) to assure the libos kernel buf won't be the bottleneck.
 | ||||
|                 let max_size = 2 * 1024 * 1024; | ||||
| 
 | ||||
|                 if optval.len() > 8 { | ||||
|                     return_errno!(EINVAL, "optval size is invalid"); | ||||
|                 } | ||||
| 
 | ||||
|                 let mut send_buf_size = { | ||||
|                     let mut size = [0 as u8; std::mem::size_of::<usize>()]; | ||||
|                     let start_offset = size.len() - optval.len(); | ||||
|                     size[start_offset..].copy_from_slice(optval); | ||||
|                     usize::from_ne_bytes(size) | ||||
|                 }; | ||||
|                 trace!("set SO_SNDBUF size = {:?}", send_buf_size); | ||||
|                 if send_buf_size < min_size { | ||||
|                     send_buf_size = min_size; | ||||
|                 } | ||||
|                 if send_buf_size > max_size { | ||||
|                     send_buf_size = max_size; | ||||
|                 } | ||||
|                 // Based on man page: The kernel doubles this value (to allow space for bookkeeping overhead)
 | ||||
|                 // when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2).
 | ||||
|                 send_buf_size *= 2; | ||||
|                 Box::new(SetSendBufSizeCmd::new(send_buf_size)) | ||||
|             } | ||||
|         } | ||||
|         SockOptName::SO_RCVBUF => { | ||||
|             if socket_type != SocketType::STREAM { | ||||
|                 Box::new(SetSockOptRawCmd::new(level, optname, optval)) | ||||
|             } else { | ||||
|                 // Implement dynamic buf size for stream socket only.
 | ||||
|                 if socket_type != Type::STREAM { | ||||
|                     Box::new(SetSockOptRawCmd::new(level, optname, optval)) | ||||
|                 } else { | ||||
|                     // Based on the man page: The minimum (doubled) value for this option is 2048.
 | ||||
|                     // However, the test on Linux shows the minimum value (doubled) is 4608. Here, we just
 | ||||
|                     // use the same value as Linux.
 | ||||
|                     let min_size = 1152; | ||||
|                     // For the max value, we choose 4MB (doubled) to assure the libos kernel buf won't be the bottleneck.
 | ||||
|                     let max_size = 2 * 1024 * 1024; | ||||
|                 info!("optval = {:?}", optval); | ||||
|                 // Based on the man page: The minimum (doubled) value for this option is 256.
 | ||||
|                 // However, the test on Linux shows the minimum value (doubled) is 2304. Here, we just
 | ||||
|                 // use the same value as Linux.
 | ||||
|                 let min_size = 128 * 1024; | ||||
|                 // For the max value, we choose 4MB (doubled) to assure the libos kernel buf won't be the bottleneck.
 | ||||
|                 let max_size = 2 * 1024 * 1024; | ||||
| 
 | ||||
|                     let mut send_buf_size = { | ||||
|                         let mut size = [0 as u8; std::mem::size_of::<usize>()]; | ||||
|                         let start_offset = size.len() - optval.len(); | ||||
|                         size[start_offset..].copy_from_slice(optval); | ||||
|                         usize::from_ne_bytes(size) | ||||
|                     }; | ||||
|                     trace!("set SO_SNDBUF size = {:?}", send_buf_size); | ||||
|                     if send_buf_size < min_size { | ||||
|                         send_buf_size = min_size; | ||||
|                     } | ||||
|                     if send_buf_size > max_size { | ||||
|                         send_buf_size = max_size; | ||||
|                     } | ||||
|                     // Based on man page: The kernel doubles this value (to allow space for bookkeeping overhead)
 | ||||
|                     // when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2).
 | ||||
|                     send_buf_size *= 2; | ||||
|                     Box::new(SetSndBufSizeCmd::new(send_buf_size)) | ||||
|                 if optval.len() > 8 { | ||||
|                     return_errno!(EINVAL, "optval size is invalid"); | ||||
|                 } | ||||
|             } | ||||
|             SockOptName::SO_RCVBUF => { | ||||
|                 if socket_type != Type::STREAM { | ||||
|                     Box::new(SetSockOptRawCmd::new(level, optname, optval)) | ||||
|                 } else { | ||||
|                     // Implement dynamic buf size for stream socket only.
 | ||||
|                     info!("optval = {:?}", optval); | ||||
|                     // Based on the man page: The minimum (doubled) value for this option is 256.
 | ||||
|                     // However, the test on Linux shows the minimum value (doubled) is 2304. Here, we just
 | ||||
|                     // use the same value as Linux.
 | ||||
|                     let min_size = 1152; | ||||
|                     // For the max value, we choose 4MB (doubled) to assure the libos kernel buf won't be the bottleneck.
 | ||||
|                     let max_size = 2 * 1024 * 1024; | ||||
| 
 | ||||
|                     let mut recv_buf_size = { | ||||
|                         let mut size = [0 as u8; std::mem::size_of::<usize>()]; | ||||
|                         let start_offset = size.len() - optval.len(); | ||||
|                         size[start_offset..].copy_from_slice(optval); | ||||
|                         usize::from_ne_bytes(size) | ||||
|                     }; | ||||
|                     trace!("set SO_RCVBUF size = {:?}", recv_buf_size); | ||||
|                     if recv_buf_size < min_size { | ||||
|                         recv_buf_size = min_size; | ||||
|                     } | ||||
| 
 | ||||
|                     if recv_buf_size > max_size { | ||||
|                         recv_buf_size = max_size | ||||
|                     } | ||||
|                     // Based on man page: The kernel doubles this value (to allow space for bookkeeping overhead)
 | ||||
|                     // when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2).
 | ||||
|                     recv_buf_size *= 2; | ||||
|                     Box::new(SetRcvBufSizeCmd::new(recv_buf_size)) | ||||
|                 let mut recv_buf_size = { | ||||
|                     let mut size = [0 as u8; std::mem::size_of::<usize>()]; | ||||
|                     let start_offset = size.len() - optval.len(); | ||||
|                     size[start_offset..].copy_from_slice(optval); | ||||
|                     usize::from_ne_bytes(size) | ||||
|                 }; | ||||
|                 trace!("set SO_RCVBUF size = {:?}", recv_buf_size); | ||||
|                 if recv_buf_size < min_size { | ||||
|                     recv_buf_size = min_size; | ||||
|                 } | ||||
| 
 | ||||
|                 if recv_buf_size > max_size { | ||||
|                     recv_buf_size = max_size | ||||
|                 } | ||||
|                 // Based on man page: The kernel doubles this value (to allow space for bookkeeping overhead)
 | ||||
|                 // when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2).
 | ||||
|                 recv_buf_size *= 2; | ||||
|                 Box::new(SetRecvBufSizeCmd::new(recv_buf_size)) | ||||
|             } | ||||
|             _ => Box::new(SetSockOptRawCmd::new(level, optname, optval)), | ||||
|         }) | ||||
|     } | ||||
|         } | ||||
|         _ => Box::new(SetSockOptRawCmd::new(level, optname, optval)), | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| fn get_optval(cmd: &dyn IoctlCmd) -> Result<&[u8]> { | ||||
| @ -1346,10 +1311,10 @@ fn get_optval(cmd: &dyn IoctlCmd) -> Result<&[u8]> { | ||||
|         cmd : GetSendTimeoutCmd => { | ||||
|             cmd.get_output_as_bytes() | ||||
|         }, | ||||
|         cmd : GetSndBufSizeCmd => { | ||||
|         cmd : GetSendBufSizeCmd => { | ||||
|             cmd.get_output_as_bytes() | ||||
|         }, | ||||
|         cmd : GetRcvBufSizeCmd => { | ||||
|         cmd : GetRecvBufSizeCmd => { | ||||
|             cmd.get_output_as_bytes() | ||||
|         }, | ||||
|         _ => { | ||||
| @ -1491,11 +1456,3 @@ fn extract_msghdr_mut_from_user<'a>( | ||||
| 
 | ||||
|     Ok((msg_mut, name, control, bufs)) | ||||
| } | ||||
| 
 | ||||
| // Flags to use when creating a new socket
 | ||||
| bitflags! { | ||||
|     pub struct SocketFlags: i32 { | ||||
|         const SOCK_NONBLOCK = 0x800; | ||||
|         const SOCK_CLOEXEC  = 0x80000; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -17,8 +17,7 @@ pub use std::sync::{ | ||||
| pub use crate::error::Result; | ||||
| pub use crate::error::*; | ||||
| pub use crate::fs::{File, FileDesc, FileRef}; | ||||
| pub use crate::net::socket::util::Addr; | ||||
| pub use crate::net::socket::{Domain, RecvFlags, SendFlags, Shutdown, Type}; | ||||
| pub use crate::net::{Addr, Domain, RecvFlags, SendFlags, Shutdown, SocketType}; | ||||
| pub use crate::process::{pid_t, uid_t}; | ||||
| pub use crate::util::sync::RwLock; | ||||
| pub use crate::util::sync::{Mutex, MutexGuard}; | ||||
|  | ||||
| @ -14,7 +14,6 @@ use crate::misc::ResourceLimits; | ||||
| use crate::prelude::*; | ||||
| use crate::sched::{NiceValue, SchedAgent}; | ||||
| use crate::signal::{SigDispositions, SigQueues}; | ||||
| use crate::util::sync::Mutex; | ||||
| use crate::vm::ProcessVM; | ||||
| 
 | ||||
| use self::pgrp::ProcessGrp; | ||||
|  | ||||
| @ -11,20 +11,20 @@ use atomic::Ordering; | ||||
| use crate::process::{futex_wait, futex_wake}; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct Mutex<T> { | ||||
|     value: UnsafeCell<T>, | ||||
| pub struct Mutex<T: ?Sized> { | ||||
|     inner: Box<MutexInner>, | ||||
|     value: UnsafeCell<T>, | ||||
| } | ||||
| 
 | ||||
| unsafe impl<T: Send> Sync for Mutex<T> {} | ||||
| unsafe impl<T: Send> Send for Mutex<T> {} | ||||
| unsafe impl<T: Send + ?Sized> Sync for Mutex<T> {} | ||||
| unsafe impl<T: Send + ?Sized> Send for Mutex<T> {} | ||||
| 
 | ||||
| pub struct MutexGuard<'a, T: 'a> { | ||||
| pub struct MutexGuard<'a, T: ?Sized + 'a> { | ||||
|     inner: &'a Mutex<T>, | ||||
| } | ||||
| 
 | ||||
| impl<T> !Send for MutexGuard<'_, T> {} | ||||
| unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {} | ||||
| impl<T: ?Sized> !Send for MutexGuard<'_, T> {} | ||||
| unsafe impl<T: Sync + ?Sized> Sync for MutexGuard<'_, T> {} | ||||
| 
 | ||||
| impl<T> Mutex<T> { | ||||
|     #[inline] | ||||
| @ -34,14 +34,9 @@ impl<T> Mutex<T> { | ||||
|             inner: Box::new(MutexInner::new()), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub fn into_inner(self) -> T { | ||||
|         self.value.into_inner() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> Mutex<T> { | ||||
| impl<T: ?Sized> Mutex<T> { | ||||
|     #[inline] | ||||
|     pub fn lock(&self) -> MutexGuard<'_, T> { | ||||
|         self.inner.lock(); | ||||
| @ -50,7 +45,7 @@ impl<T> Mutex<T> { | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> { | ||||
|         self.inner.try_lock().map(|_| MutexGuard { inner: self }) | ||||
|         self.inner.try_lock().then(|| MutexGuard { inner: self }) | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
| @ -67,9 +62,17 @@ impl<T> Mutex<T> { | ||||
|     pub fn get_mut(&mut self) -> &mut T { | ||||
|         self.value.get_mut() | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub fn into_inner(self) -> T | ||||
|     where | ||||
|         T: Sized, | ||||
|     { | ||||
|         self.value.into_inner() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> Deref for MutexGuard<'_, T> { | ||||
| impl<T: ?Sized> Deref for MutexGuard<'_, T> { | ||||
|     type Target = T; | ||||
| 
 | ||||
|     fn deref(&self) -> &Self::Target { | ||||
| @ -77,13 +80,13 @@ impl<T> Deref for MutexGuard<'_, T> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> DerefMut for MutexGuard<'_, T> { | ||||
| impl<T: ?Sized> DerefMut for MutexGuard<'_, T> { | ||||
|     fn deref_mut(&mut self) -> &mut Self::Target { | ||||
|         unsafe { &mut *self.inner.value.get() } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> Drop for MutexGuard<'_, T> { | ||||
| impl<T: ?Sized> Drop for MutexGuard<'_, T> { | ||||
|     fn drop(&mut self) { | ||||
|         unsafe { | ||||
|             self.inner.force_unlock(); | ||||
| @ -91,13 +94,13 @@ impl<T> Drop for MutexGuard<'_, T> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T: fmt::Debug> fmt::Debug for MutexGuard<'_, T> { | ||||
| impl<T: fmt::Debug + ?Sized> fmt::Debug for MutexGuard<'_, T> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Debug::fmt(&**self, f) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T: fmt::Debug> fmt::Debug for Mutex<T> { | ||||
| impl<T: fmt::Debug + ?Sized> fmt::Debug for Mutex<T> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         match self.try_lock() { | ||||
|             Some(guard) => write!(f, "Mutex {{ value: ") | ||||
| @ -138,10 +141,10 @@ impl MutexInner { | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub fn try_lock(&self) -> Option<u32> { | ||||
|     pub fn try_lock(&self) -> bool { | ||||
|         self.lock | ||||
|             .compare_exchange(0, 1, Ordering::Acquire, Ordering::Relaxed) | ||||
|             .ok() | ||||
|             .is_ok() | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user