diff --git a/open-coroutine-core/src/syscall/facade.rs b/open-coroutine-core/src/syscall/facade.rs index def70952..e6cf6f83 100644 --- a/open-coroutine-core/src/syscall/facade.rs +++ b/open-coroutine-core/src/syscall/facade.rs @@ -51,17 +51,6 @@ pub extern "C" fn select( /// read -#[must_use] -pub extern "C" fn recv( - fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, - socket: c_int, - buf: *mut c_void, - len: size_t, - flags: c_int, -) -> ssize_t { - CHAIN.recv(fn_ptr, socket, buf, len, flags) -} - #[must_use] pub extern "C" fn recvfrom( fn_ptr: Option< diff --git a/open-coroutine-core/src/syscall/io_uring.rs b/open-coroutine-core/src/syscall/io_uring.rs index e650a23a..fda70988 100644 --- a/open-coroutine-core/src/syscall/io_uring.rs +++ b/open-coroutine-core/src/syscall/io_uring.rs @@ -51,17 +51,6 @@ impl UnixSyscall for IoUringLinuxSyscall { unsupported!(self, select, fn_ptr, nfds, readfds, writefds, errorfds, timeout) } - extern "C" fn recv( - &self, - fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, - socket: c_int, - buf: *mut c_void, - len: size_t, - flags: c_int, - ) -> ssize_t { - impl_io_uring!(self, recv, fn_ptr, socket, buf, len, flags) - } - extern "C" fn recvfrom( &self, fn_ptr: Option< diff --git a/open-coroutine-core/src/syscall/mod.rs b/open-coroutine-core/src/syscall/mod.rs index 3ab748fc..d2f2f73f 100644 --- a/open-coroutine-core/src/syscall/mod.rs +++ b/open-coroutine-core/src/syscall/mod.rs @@ -54,15 +54,6 @@ pub trait UnixSyscall { /// read - extern "C" fn recv( - &self, - fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, - fd: c_int, - buf: *mut c_void, - len: size_t, - flags: c_int, - ) -> ssize_t; - extern "C" fn recvfrom( &self, fn_ptr: Option< diff --git a/open-coroutine-core/src/syscall/nio.rs b/open-coroutine-core/src/syscall/nio.rs index a54eb8eb..67032e6e 100644 --- a/open-coroutine-core/src/syscall/nio.rs +++ b/open-coroutine-core/src/syscall/nio.rs @@ -352,17 +352,6 @@ impl UnixSyscall for NioLinuxSyscall { r } - extern "C" fn recv( - &self, - fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, - socket: c_int, - buf: *mut c_void, - len: size_t, - flags: c_int, - ) -> ssize_t { - impl_expected_read_hook!(self.inner, recv, fn_ptr, socket, buf, len, flags) - } - extern "C" fn recvfrom( &self, fn_ptr: Option< diff --git a/open-coroutine-core/src/syscall/raw.rs b/open-coroutine-core/src/syscall/raw.rs index 8efae2a7..980ddec1 100644 --- a/open-coroutine-core/src/syscall/raw.rs +++ b/open-coroutine-core/src/syscall/raw.rs @@ -48,21 +48,6 @@ impl UnixSyscall for RawLinuxSyscall { /// read - extern "C" fn recv( - &self, - fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, - socket: c_int, - buf: *mut c_void, - len: size_t, - flags: c_int, - ) -> ssize_t { - if let Some(f) = fn_ptr { - (f)(socket, buf, len, flags) - } else { - unsafe { libc::send(socket, buf, len, flags) } - } - } - extern "C" fn recvfrom( &self, fn_ptr: Option< diff --git a/open-coroutine-core/src/syscall/state.rs b/open-coroutine-core/src/syscall/state.rs index 981c53da..e5e0d958 100644 --- a/open-coroutine-core/src/syscall/state.rs +++ b/open-coroutine-core/src/syscall/state.rs @@ -61,17 +61,6 @@ impl UnixSyscall for StateLinuxSyscall { syscall_state!(self, select, fn_ptr, nfds, readfds, writefds, errorfds, timeout) } - extern "C" fn recv( - &self, - fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, - socket: c_int, - buf: *mut c_void, - len: size_t, - flags: c_int, - ) -> ssize_t { - syscall_state!(self, recv, fn_ptr, socket, buf, len, flags) - } - extern "C" fn recvfrom( &self, fn_ptr: Option< diff --git a/open-coroutine-core/src/syscall/unix/mod.rs b/open-coroutine-core/src/syscall/unix/mod.rs index 1ce0ba79..04489f80 100644 --- a/open-coroutine-core/src/syscall/unix/mod.rs +++ b/open-coroutine-core/src/syscall/unix/mod.rs @@ -5,6 +5,7 @@ pub use close::close; pub use connect::connect; pub use listen::listen; pub use nanosleep::nanosleep; +pub use recv::recv; pub use send::send; pub use shutdown::shutdown; pub use sleep::sleep; @@ -118,6 +119,69 @@ macro_rules! impl_nio_read { } } +macro_rules! impl_nio_expected_read { + ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, + $buf: ident : $buf_type: ty, $len: ident : $len_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + #[derive(Debug, Default)] + struct $struct_name { + inner: I, + } + + impl $trait_name for $struct_name { + extern "C" fn $syscall( + &self, + fn_ptr: Option<&extern "C" fn($fd_type, $buf_type, $len_type, $($arg_type),*) -> $result>, + $fd: $fd_type, + $buf: $buf_type, + $len: $len_type, + $($arg: $arg_type),* + ) -> $result { + let blocking = $crate::syscall::common::is_blocking($fd); + if blocking { + $crate::syscall::common::set_non_blocking($fd); + } + let mut received = 0; + let mut r = 0; + while received < $len { + r = self.inner.$syscall( + fn_ptr, + $fd, + ($buf as usize + received) as *mut c_void, + $len - received, + $($arg, )* + ); + if r != -1 { + $crate::syscall::common::reset_errno(); + received += r as size_t; + if received >= $len || r == 0 { + r = received as ssize_t; + break; + } + } + let error_kind = std::io::Error::last_os_error().kind(); + if error_kind == std::io::ErrorKind::WouldBlock { + //wait read event + if $crate::net::event_loop::EventLoops::wait_read_event( + $fd, + Some(std::time::Duration::from_millis(10)), + ) + .is_err() + { + break; + } + } else if error_kind != std::io::ErrorKind::Interrupted { + break; + } + } + if blocking { + $crate::syscall::common::set_blocking($fd); + } + r + } + } + } +} + macro_rules! impl_nio_expected_write { ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, $buf: ident : $buf_type: ty, $len: ident : $len_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { @@ -209,6 +273,7 @@ mod close; mod connect; mod listen; mod nanosleep; +mod recv; mod send; mod shutdown; mod sleep; diff --git a/open-coroutine-core/src/syscall/unix/recv.rs b/open-coroutine-core/src/syscall/unix/recv.rs new file mode 100644 index 00000000..f0cd1931 --- /dev/null +++ b/open-coroutine-core/src/syscall/unix/recv.rs @@ -0,0 +1,51 @@ +use libc::{size_t, ssize_t}; +use once_cell::sync::Lazy; +use std::ffi::{c_int, c_void}; + +#[must_use] +pub extern "C" fn recv( + fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, + socket: c_int, + buf: *mut c_void, + len: size_t, + flags: c_int, +) -> ssize_t { + cfg_if::cfg_if! { + if #[cfg(all(target_os = "linux", feature = "io_uring"))] { + static CHAIN: Lazy< + RecvSyscallFacade>> + > = Lazy::new(Default::default); + } else { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + } + } + CHAIN.recv(fn_ptr, socket, buf, len, flags) +} + +trait RecvSyscall { + extern "C" fn recv( + &self, + fn_ptr: Option<&extern "C" fn(c_int, *mut c_void, size_t, c_int) -> ssize_t>, + fd: c_int, + buf: *mut c_void, + len: size_t, + flags: c_int, + ) -> ssize_t; +} + +impl_facade!(RecvSyscallFacade, RecvSyscall, + recv(fd: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t +); + +impl_io_uring!(IoUringRecvSyscall, RecvSyscall, + recv(fd: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t +); + +impl_nio_expected_read!(NioRecvSyscall, RecvSyscall, + recv(fd: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t +); + +impl_raw!(RawRecvSyscall, RecvSyscall, + recv(fd: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t +);