-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refine select nodelay #211
Changes from 61 commits
372784e
53fd0b0
7f8f1a4
3d3c720
c28e122
66434dd
af7760a
f752848
dfe4f91
e377010
12f2375
968604e
15af3b6
1b382b5
654abcc
c88e28e
2b57dac
6739514
276be6a
6886660
668a92d
4b89ca3
0706eb3
04b8c43
768e909
3c157e8
e618bc1
c6e23c3
6d13964
f7d8695
98c19c8
5d44346
c9042f6
f4d4e71
6a49aaf
b308497
71f8cd5
18541b0
f012a49
1068027
f8fcab7
36edf84
3359aea
ab57640
3c49f1f
fc52610
75050b5
667b15a
fbc3f15
4a1fa40
f4ecd78
5cb8ded
20d3176
a47f167
77d3004
cca05f9
1642070
bc32d01
720ece9
7e3764a
eebbd66
6496168
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,10 +2,13 @@ | |
// // | ||
// // | ||
|
||
use crate::interface; | ||
use std::mem::size_of; | ||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; | ||
use std::fs::read_to_string; | ||
use std::str::from_utf8; | ||
use std::os::unix::io::{AsRawFd, RawFd}; | ||
use std::mem; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also we import mem:size_of above, maybe combine and just import what you need? |
||
|
||
extern crate libc; | ||
|
||
|
@@ -206,7 +209,7 @@ pub struct SockaddrV6 { | |
#[derive(Debug)] | ||
pub struct Socket { | ||
pub refcnt: i32, | ||
raw_sys_fd: i32 | ||
pub raw_sys_fd: i32 | ||
} | ||
|
||
impl Socket { | ||
|
@@ -340,8 +343,8 @@ impl Socket { | |
|
||
pub fn setsockopt(&self, level: i32, optname: i32, optval: i32) -> i32 { | ||
let valbuf = optval; | ||
let sor = unsafe{libc::setsockopt(self.raw_sys_fd, level, optname, (&valbuf as *const i32).cast::<libc::c_void>(), size_of::<i32>() as u32)}; | ||
sor | ||
let ret = unsafe{libc::setsockopt(self.raw_sys_fd, level, optname, (&valbuf as *const i32).cast::<libc::c_void>(), size_of::<i32>() as u32)}; | ||
ret | ||
} | ||
|
||
pub fn shutdown(&self, how: i32) -> i32 { | ||
|
@@ -366,3 +369,95 @@ impl Drop for Socket { | |
pub fn getifaddrs_from_file() -> String { | ||
read_to_string(NET_DEV_FILENAME).expect("No net_devices file present!").to_owned() | ||
} | ||
|
||
// Implementations of select related FD_SET structure | ||
pub struct FdSet(libc::fd_set); | ||
|
||
impl FdSet { | ||
pub fn new() -> FdSet { | ||
unsafe { | ||
let mut raw_fd_set = std::mem::MaybeUninit::<libc::fd_set>::uninit(); | ||
libc::FD_ZERO(raw_fd_set.as_mut_ptr()); | ||
FdSet(raw_fd_set.assume_init()) | ||
} | ||
} | ||
|
||
pub fn new_from_ptr(raw_fdset_ptr: *const libc::fd_set) -> &'static mut FdSet { | ||
unsafe { | ||
&mut *(raw_fdset_ptr as *mut FdSet) | ||
} | ||
} | ||
|
||
// copy the src FdSet into self | ||
pub fn copy_from(&mut self, src_fds: &FdSet) { | ||
unsafe { | ||
std::ptr::copy_nonoverlapping(&src_fds.0 as *const libc::fd_set, &mut self.0 as *mut libc::fd_set, 1); | ||
} | ||
} | ||
|
||
// turn off the fd bit in fd_set (currently only used by the tests) | ||
#[allow(dead_code)] | ||
pub fn clear(&mut self, fd: RawFd) { | ||
unsafe { libc::FD_CLR(fd, &mut self.0) } | ||
} | ||
|
||
// turn on the fd bit in fd_set | ||
pub fn set(&mut self, fd: RawFd) { | ||
unsafe { libc::FD_SET(fd, &mut self.0) } | ||
} | ||
|
||
// return true if the bit for fd is set, false otherwise | ||
pub fn is_set(&self, fd: RawFd) -> bool { | ||
unsafe { libc::FD_ISSET(fd, &self.0) } | ||
} | ||
|
||
pub fn is_empty(&self) -> bool { | ||
let fd_array: &[u8] = unsafe { | ||
std::slice::from_raw_parts(&self.0 as *const _ as *const u8, mem::size_of::<libc::fd_set>()) | ||
}; | ||
fd_array.iter().all(|&byte| byte == 0) | ||
} | ||
|
||
// for each fd, if kernel_fds turned it on, then self will turn the corresponding tranlated fd on | ||
pub fn set_from_kernelfds_and_translate(&mut self, kernel_fds: &FdSet, nfds: i32, rawfd_lindfd_tuples: &Vec<(i32, i32)>) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. theres a lot of nesting here, maybe condense some of this to one liners for readability There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Following Nick's suggestion, the nested loop can be modified as something like this:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is probably not a great idea because I believe creating a hashmap is slow, so even though the algorithmic complexity may be better N should never be large enough where it surpasses that allocation cost. |
||
for fd in 0..nfds { | ||
if !kernel_fds.is_set(fd) { | ||
continue; | ||
} | ||
// translate and set | ||
if let Some((_, lindfd)) = rawfd_lindfd_tuples.iter().find(|(rawfd, _)| *rawfd == fd) { | ||
self.set(*lindfd); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// for unwrapping in kernel_select | ||
fn to_fdset_ptr(opt: Option<&mut FdSet>) -> *mut libc::fd_set { | ||
match opt { | ||
None => std::ptr::null_mut(), | ||
Some(&mut FdSet(ref mut raw_fd_set)) => raw_fd_set, | ||
} | ||
} | ||
|
||
pub fn kernel_select(nfds: libc::c_int, readfds: Option<&mut FdSet>, writefds: Option<&mut FdSet>, errorfds: Option<&mut FdSet>) -> i32 { | ||
// Call libc::select and store the result | ||
let result = unsafe { | ||
// Create a timeval struct with zero timeout | ||
|
||
let mut kselect_timeout = libc::timeval { | ||
tv_sec: 0, // 0 seconds | ||
tv_usec: 0, // 0 microseconds | ||
}; | ||
|
||
libc::select( | ||
nfds, | ||
to_fdset_ptr(readfds), | ||
to_fdset_ptr(writefds), | ||
to_fdset_ptr(errorfds), | ||
&mut kselect_timeout as *mut libc::timeval, | ||
) | ||
}; | ||
|
||
return result; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't actually need to import this. Can't we just use ints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice catch