tcplistener_accept_timeout/
lib.rs1#[cfg(not(target_os = "windows"))]
7extern crate libc;
8#[cfg(not(target_os = "windows"))]
9use libc::{time_t, c_long, POLLIN, timespec, pollfd, ppoll};
10#[cfg(not(target_os = "windows"))]
11use std::os::fd::AsRawFd;
12#[cfg(not(target_os = "windows"))]
13use std::ptr;
14
15#[cfg(target_os = "windows")]
16extern crate windows_sys;
17#[cfg(target_os = "windows")]
18use windows_sys::Win32::Networking::WinSock::{POLLIN, WSAPOLLFD as pollfd, WSAPoll as poll};
19#[cfg(target_os = "windows")]
20use std::os::windows::io::AsRawSocket;
21
22use std::net::{TcpListener, TcpStream, SocketAddr};
23use std::io::Result as IoResult;
24use std::time::Duration;
25
26
27pub trait TcpListenerAcceptTimeout {
29 fn accept_timeout(&self, timeout: Option<Duration>) -> Option<IoResult<(TcpStream, SocketAddr)>>;
38
39 fn connection_pending(&self, timeout: Option<Duration>) -> bool;
46}
47
48impl TcpListenerAcceptTimeout for TcpListener {
49 fn accept_timeout(&self, timeout: Option<Duration>) -> Option<IoResult<(TcpStream, SocketAddr)>> {
50 if !self.connection_pending(timeout) {
51 return None;
52 }
53 Some(self.accept())
54 }
55
56 #[cfg(not(target_os = "windows"))]
57 fn connection_pending(&self, timeout: Option<Duration>) -> bool {
58 let mut fd = pollfd {
59 fd: self.as_raw_fd(),
60 events: POLLIN,
61 revents: 0,
62 };
63 unsafe {
64 ppoll(&mut fd,
65 1,
66 timeout.map(|timeout| {
67 timespec {
68 tv_sec: timeout.as_secs() as time_t,
69 tv_nsec: timeout.subsec_nanos() as c_long,
70 }
71 })
72 .as_ref()
73 .map(|timeout| timeout as *const _)
74 .unwrap_or(ptr::null()),
75 ptr::null()) == 1 && (fd.revents & POLLIN) != 0
76 }
77 }
78
79 #[cfg(target_os = "windows")]
80 fn connection_pending(&self, timeout: Option<Duration>) -> bool {
81 let mut fd = pollfd {
82 fd: self.as_raw_socket() as usize,
83 events: POLLIN,
84 revents: 0,
85 };
86 unsafe {
87 match timeout {
88 None => poll(&mut fd, 1, -1) == 1 && (fd.revents & POLLIN) != 0,
89 Some(timeout) => {
90 let mut ms = timeout.as_millis();
91 while ms > i32::MAX as u128 {
92 let ret = poll(&mut fd, 1, i32::MAX);
93 if ret != 0 {
94 return ret == 1 && (fd.revents & POLLIN) != 0;
95 }
96 ms -= i32::MAX as u128;
97 }
98 poll(&mut fd, 1, ms as i32) == 1 && (fd.revents & POLLIN) != 0
99 }
100 }
101 }
102 }
103}