mirror of https://github.com/smol-rs/polling
feat: Add the ability to identify if the connection has failed
This commit is contained in:
parent
6125508c93
commit
cf25dd85f8
|
@ -46,6 +46,7 @@ features = [
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
easy-parallel = "3.1.0"
|
easy-parallel = "3.1.0"
|
||||||
fastrand = "2.0.0"
|
fastrand = "2.0.0"
|
||||||
|
socket2 = "0.5.5"
|
||||||
|
|
||||||
[target.'cfg(unix)'.dev-dependencies]
|
[target.'cfg(unix)'.dev-dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
use std::{io, net};
|
||||||
|
|
||||||
|
use polling::Event;
|
||||||
|
use socket2::Type;
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let socket = socket2::Socket::new(socket2::Domain::IPV4, Type::STREAM, None)?;
|
||||||
|
let poller = polling::Poller::new()?;
|
||||||
|
unsafe {
|
||||||
|
poller.add(&socket, Event::new(0, true, true))?;
|
||||||
|
}
|
||||||
|
let addr = net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), 8080);
|
||||||
|
socket.set_nonblocking(true)?;
|
||||||
|
let _ = socket.connect(&addr.into());
|
||||||
|
|
||||||
|
let mut events = polling::Events::new();
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
poller.wait(&mut events, None)?;
|
||||||
|
|
||||||
|
let event = events.iter().next();
|
||||||
|
let event = match event {
|
||||||
|
Some(event) => event,
|
||||||
|
None => {
|
||||||
|
println!("no event");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("event: {:?}", event);
|
||||||
|
if event.is_connect_failed().unwrap_or_default() {
|
||||||
|
println!("connect failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -365,6 +365,14 @@ impl EventExtra {
|
||||||
pub fn is_pri(&self) -> bool {
|
pub fn is_pri(&self) -> bool {
|
||||||
self.flags.contains(epoll::EventFlags::PRI)
|
self.flags.contains(epoll::EventFlags::PRI)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_connect_failed(&self) -> Option<bool> {
|
||||||
|
Some(
|
||||||
|
self.flags.contains(epoll::EventFlags::ERR)
|
||||||
|
|| self.flags.contains(epoll::EventFlags::HUP),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The notifier for Linux.
|
/// The notifier for Linux.
|
||||||
|
|
|
@ -681,6 +681,12 @@ impl EventExtra {
|
||||||
pub fn set_pri(&mut self, active: bool) {
|
pub fn set_pri(&mut self, active: bool) {
|
||||||
self.flags.set(AfdPollMask::RECEIVE_EXPEDITED, active);
|
self.flags.set(AfdPollMask::RECEIVE_EXPEDITED, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if TCP connect failed.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_connect_failed(&self) -> Option<bool> {
|
||||||
|
Some(self.flags.intersects(AfdPollMask::CONNECT_FAIL))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A packet used to wake up the poller with an event.
|
/// A packet used to wake up the poller with an event.
|
||||||
|
|
|
@ -371,6 +371,11 @@ impl EventExtra {
|
||||||
pub fn is_pri(&self) -> bool {
|
pub fn is_pri(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_connect_failed(&self) -> Option<bool> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn mode_to_flags(mode: PollMode) -> kqueue::EventFlags {
|
pub(crate) fn mode_to_flags(mode: PollMode) -> kqueue::EventFlags {
|
||||||
|
|
59
src/lib.rs
59
src/lib.rs
|
@ -332,6 +332,65 @@ impl Event {
|
||||||
self.extra.is_pri()
|
self.extra.is_pri()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tells if this event is the result of a connection failure.
|
||||||
|
///
|
||||||
|
/// This function checks if a TCP connection has failed. It corresponds to the `EPOLLERR` or `EPOLLHUP` event in Linux
|
||||||
|
/// and `CONNECT_FAILED` event in Windows IOCP.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::{io, net};
|
||||||
|
/// // Assuming polling and socket2 are included as dependencies in Cargo.toml
|
||||||
|
/// use polling::Event;
|
||||||
|
/// use socket2::Type;
|
||||||
|
///
|
||||||
|
/// fn main() -> io::Result<()> {
|
||||||
|
/// let socket = socket2::Socket::new(socket2::Domain::IPV4, Type::STREAM, None)?;
|
||||||
|
/// let poller = polling::Poller::new()?;
|
||||||
|
/// unsafe {
|
||||||
|
/// poller.add(&socket, Event::new(0, true, true))?;
|
||||||
|
/// }
|
||||||
|
/// let addr = net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), 8080);
|
||||||
|
/// socket.set_nonblocking(true)?;
|
||||||
|
/// let _ = socket.connect(&addr.into());
|
||||||
|
///
|
||||||
|
/// let mut events = polling::Events::new();
|
||||||
|
///
|
||||||
|
/// events.clear();
|
||||||
|
/// poller.wait(&mut events, None)?;
|
||||||
|
///
|
||||||
|
/// let event = events.iter().next();
|
||||||
|
///
|
||||||
|
/// let event = match event {
|
||||||
|
/// Some(event) => event,
|
||||||
|
/// None => {
|
||||||
|
/// println!("no event");
|
||||||
|
/// return Ok(());
|
||||||
|
/// },
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// println!("event: {:?}", event);
|
||||||
|
/// if event
|
||||||
|
/// .is_connect_failed()
|
||||||
|
/// .unwrap_or_default()
|
||||||
|
/// {
|
||||||
|
/// println!("connect failed");
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns `Some(true)` if the connection has failed, `Some(false)` if the connection has not failed,
|
||||||
|
/// or `None` if the platform does not support detecting this condition.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_connect_failed(&self) -> Option<bool> {
|
||||||
|
self.extra.is_connect_failed()
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove any extra information from this event.
|
/// Remove any extra information from this event.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear_extra(&mut self) {
|
pub fn clear_extra(&mut self) {
|
||||||
|
|
|
@ -426,6 +426,11 @@ impl EventExtra {
|
||||||
pub fn is_pri(&self) -> bool {
|
pub fn is_pri(&self) -> bool {
|
||||||
self.flags.contains(PollFlags::PRI)
|
self.flags.contains(PollFlags::PRI)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_connect_failed(&self) -> Option<bool> {
|
||||||
|
Some(self.flags.contains(PollFlags::ERR) || self.flags.contains(PollFlags::HUP))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cvt_mode_as_remove(mode: PollMode) -> io::Result<bool> {
|
fn cvt_mode_as_remove(mode: PollMode) -> io::Result<bool> {
|
||||||
|
|
|
@ -250,4 +250,9 @@ impl EventExtra {
|
||||||
pub fn is_pri(&self) -> bool {
|
pub fn is_pri(&self) -> bool {
|
||||||
self.flags.contains(PollFlags::PRI)
|
self.flags.contains(PollFlags::PRI)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_connect_failed(&self) -> Option<bool> {
|
||||||
|
Some(self.flags.contains(PollFlags::ERR) || self.flags.contains(PollFlags::HUP))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue