[catnap] Bug Fix: Set Async Opts in New Socket
@@ -15,6 +15,7 @@ use ::runtime::{
};
use ::std::{
future::Future,
+ mem::size_of_val,
os::unix::prelude::RawFd,
pin::Pin,
task::{
@@ -22,6 +23,10 @@ use ::std::{
Poll,
},
};
+use libc::{
+ c_void,
+ socklen_t,
+};
//==============================================================================
// Structures
@@ -74,6 +79,17 @@ impl Future for AcceptFuture {
// Operation completed.
Ok(new_fd) => {
trace!("connection accepted ({:?})", new_fd);
+
+ // Set async options in socket.
+ unsafe {
+ if set_tcp_nodelay(new_fd) != 0 {
+ warn!("cannot set TCP_NONDELAY option");
+ }
+ if set_nonblock(new_fd) != 0 {
+ warn!("cannot set NONBLOCK option");
+ }
+ }
+
Poll::Ready(Ok(new_fd))
},
// Operation in progress.
@@ -90,3 +106,35 @@ impl Future for AcceptFuture {
}
}
}
+
+//==============================================================================
+// Standalone Functions
+//==============================================================================
+
+/// Sets TCP_NODELAY option in a socket.
+unsafe fn set_tcp_nodelay(fd: RawFd) -> i32 {
+ let value: u32 = 1;
+ let value_ptr: *const u32 = &value as *const u32;
+ let option_len: socklen_t = size_of_val(&value) as socklen_t;
+ libc::setsockopt(
+ fd,
+ libc::IPPROTO_TCP,
+ libc::TCP_NODELAY,
+ value_ptr as *const c_void,
+ option_len,
+ )
+}
+
+/// Sets NONBLOCK option in a socket.
+unsafe fn set_nonblock(fd: RawFd) -> i32 {
+ // Get file flags.
+ let mut flags: i32 = libc::fcntl(fd, libc::F_GETFL);
+ if flags == -1 {
+ warn!("failed to get flags for new socket");
+ return -1;
+ }
+
+ // Set file flags.
+ flags |= libc::O_NONBLOCK;
+ libc::fcntl(fd, libc::F_SETFL, flags, 1)
+}
