Created
November 22, 2020 22:02
-
-
Save pjambet/5992351aa6b16a6cfb126cbb67db785b to your computer and use it in GitHub Desktop.
select/pselect in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate libc; | |
use std::{io,mem,ptr,time}; | |
use std::os::unix::io::RawFd; | |
use std::net::TcpStream; | |
use std::os::unix::io::AsRawFd; | |
// use std::io::Read; | |
pub struct FdSet(libc::fd_set); | |
impl FdSet { | |
pub fn new() -> FdSet { | |
unsafe { | |
let mut raw_fd_set = mem::uninitialized::<libc::fd_set>(); | |
// let mut raw_fd_set = mem::MaybeUninit::<libc::fd_set>::uninit().assume_init(); | |
libc::FD_ZERO(&mut raw_fd_set); | |
FdSet(raw_fd_set) | |
} | |
} | |
pub fn clear(&mut self, fd: RawFd) { | |
unsafe { | |
libc::FD_CLR(fd, &mut self.0); | |
} | |
} | |
pub fn set(&mut self, fd: RawFd) { | |
unsafe { | |
libc::FD_SET(fd, &mut self.0); | |
} | |
} | |
pub fn is_set(&mut self, fd: RawFd) -> bool { | |
unsafe { | |
libc::FD_ISSET(fd, &mut self.0) | |
} | |
} | |
} | |
pub fn pselect (nfds: libc::c_int, | |
readfds: Option<&mut FdSet>, | |
writefds: Option<&mut FdSet>, | |
errorfds: Option<&mut FdSet>, | |
// timeout: Option<&libc::timeval>, | |
timeout: Option<&libc::timespec>, | |
sigmask: Option<&libc::sigset_t>) -> io::Result<usize> { | |
fn to_fdset_ptr (opt: Option<&mut FdSet>) -> *mut libc::fd_set { | |
match opt { | |
None => ptr::null_mut(), | |
Some(&mut FdSet(ref mut raw_fd_set)) => raw_fd_set, | |
} | |
} | |
fn to_ptr<T> (opt: Option<&T>) -> *const T { | |
match opt { | |
None => ptr::null::<T>(), | |
Some(p) => p, | |
} | |
} | |
match unsafe { | |
libc::pselect(nfds, | |
to_fdset_ptr(readfds), | |
to_fdset_ptr(writefds), | |
to_fdset_ptr(errorfds), | |
to_ptr(timeout), | |
to_ptr(sigmask)) | |
// libc::select(nfds, to_fdset_ptr(readfds), to_fdset_ptr(None), to_fdset_ptr(None), to_ptr::<libc::timeval>(timeout) as *mut libc::timeval) | |
} { | |
-1 => Err(io::Error::last_os_error()), | |
res => Ok(res as usize), | |
} | |
} | |
pub fn make_timeval(duration: time::Duration) -> libc::timeval { | |
libc::timeval { | |
tv_sec: duration.as_secs() as i64, | |
tv_usec: duration.subsec_micros() as i32, | |
} | |
} | |
pub fn make_timespec(duration: time::Duration) -> libc::timespec { | |
libc::timespec { | |
tv_sec: duration.as_secs() as i64, | |
tv_nsec: duration.subsec_nanos() as i64, | |
} | |
} | |
fn main() { | |
let five_seconds = time::Duration::new(60, 0); | |
let mut buffer = [0; 2]; | |
let mut fd_set = FdSet::new(); | |
if let Ok(stream) = TcpStream::connect("localhost:2000") { | |
// let mut fd_set = FdSet::new(); | |
// println!("{}", stream.read(&mut buffer).unwrap()); | |
println!("Connected to the server!, {}", stream.as_raw_fd()); | |
fd_set.clear(stream.as_raw_fd()); | |
let raw_fd = stream.as_raw_fd(); | |
fd_set.set(raw_fd); | |
println!("isset: {}", fd_set.is_set(stream.as_raw_fd())); | |
// if let Ok(res) = pselect(stream.as_raw_fd() + 1, Some(&mut fd_set), None, None, Some(&make_timeval(five_seconds)), None) { | |
if let Ok(res) = pselect(stream.as_raw_fd() + 1, Some(&mut fd_set), None, None, Some(&make_timespec(five_seconds)), None) { | |
println!("Got result back! {}", res); | |
} else { | |
println!("Failed to pselect"); | |
} | |
} else { | |
println!("Couldn't connect to server..."); | |
} | |
println!("Hello, world!"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment