Skip to content
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

Fix: replace is_connect_failed with is_err #189

Merged
merged 56 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
04ea01e
Fix, HUP will sometimes happen in write
irvingoujAtDevolution Feb 5, 2024
2cf58cf
Fix,TCP fail must happend with both err and hub
irvingoujAtDevolution Feb 5, 2024
cff8983
a hack
irvingoujAtDevolution Feb 5, 2024
1f3502a
fix:replace check connect failed with is_err
irvingoujAtDevolution Feb 7, 2024
e88773f
Merge branch 'master' into fix-detect-connection-fail
irvingoujAtDevolution Feb 7, 2024
ec5d954
update example
irvingoujAtDevolution Feb 7, 2024
90a9675
CI
irvingoujAtDevolution Feb 7, 2024
040f52d
updating example to pass ci
irvingoujAtDevolution Feb 7, 2024
f9e6d0c
ci fix
irvingoujAtDevolution Feb 7, 2024
f33f93a
CI
irvingoujAtDevolution Feb 7, 2024
b11a2bf
ci
irvingoujAtDevolution Feb 7, 2024
80578fd
ci
irvingoujAtDevolution Feb 7, 2024
82a4d5d
fix doctest
irvingoujAtDevolution Feb 7, 2024
aaef907
CI
irvingoujAtDevolution Feb 7, 2024
5270211
doc test
irvingoujAtDevolution Feb 7, 2024
27f4d52
fix macos
irvingoujAtDevolution Feb 7, 2024
aa248fb
add andriod
irvingoujAtDevolution Feb 7, 2024
9f8f960
fix test
irvingoujAtDevolution Feb 7, 2024
5a0fd36
fix test
irvingoujAtDevolution Feb 7, 2024
c04e8ee
fmt
irvingoujAtDevolution Feb 7, 2024
a94a66b
add is_connection_fail back, mark depercated
irvingoujAtDevolution Feb 13, 2024
93dc77c
Merge branch 'fix-detect-connection-fail' of github.com:irvingoujAtDe…
irvingoujAtDevolution Feb 13, 2024
0953927
update comment
irvingoujAtDevolution Feb 13, 2024
c135cc2
Fix, HUP will sometimes happen in write
irvingoujAtDevolution Feb 5, 2024
0ccf400
Fix,TCP fail must happend with both err and hub
irvingoujAtDevolution Feb 5, 2024
153e281
a hack
irvingoujAtDevolution Feb 5, 2024
154f38f
fix:replace check connect failed with is_err
irvingoujAtDevolution Feb 7, 2024
b2031a8
update example
irvingoujAtDevolution Feb 7, 2024
5a70011
CI
irvingoujAtDevolution Feb 7, 2024
678ec62
updating example to pass ci
irvingoujAtDevolution Feb 7, 2024
e2e7222
ci fix
irvingoujAtDevolution Feb 7, 2024
39a5dc3
CI
irvingoujAtDevolution Feb 7, 2024
d130e9b
ci
irvingoujAtDevolution Feb 7, 2024
4a5d5fc
ci
irvingoujAtDevolution Feb 7, 2024
bcfe7a2
add is_connection_fail back, mark depercated
irvingoujAtDevolution Feb 13, 2024
061100a
fix doctest
irvingoujAtDevolution Feb 7, 2024
51d7ea0
CI
irvingoujAtDevolution Feb 7, 2024
b9ff086
doc test
irvingoujAtDevolution Feb 7, 2024
e20ad7e
fix macos
irvingoujAtDevolution Feb 7, 2024
23e37f9
add andriod
irvingoujAtDevolution Feb 7, 2024
117ef10
fix test
irvingoujAtDevolution Feb 7, 2024
7d09e02
fix test
irvingoujAtDevolution Feb 7, 2024
4e5a342
fmt
irvingoujAtDevolution Feb 7, 2024
1ec8199
update comment
irvingoujAtDevolution Feb 13, 2024
d0f8206
Merge branch 'fix-detect-connection-fail' of github.com:irvingoujAtDe…
irvingoujAtDevolution Feb 13, 2024
d4a2ee3
Merge branch 'smol-rs:master' into fix-detect-connection-fail
irvingoujAtDevolution Feb 13, 2024
7fa4cfc
review fix
irvingoujAtDevolution Feb 22, 2024
2c84391
ci
irvingoujAtDevolution Feb 22, 2024
83c2b6c
ci
irvingoujAtDevolution Feb 22, 2024
d84b6ec
Merge branch 'master' into fix-detect-connection-fail
irvingoujAtDevolution Feb 29, 2024
2241584
Update src/lib.rs
irvingoujAtDevolution Mar 5, 2024
23f611e
Update src/lib.rs
irvingoujAtDevolution Mar 5, 2024
8edf0cf
review fix
irvingoujAtDevolution Mar 15, 2024
ddc920a
review fix
irvingoujAtDevolution Mar 15, 2024
20996c2
Update src/lib.rs
irvingoujAtDevolution Mar 20, 2024
bf30796
Merge branch 'master' into fix-detect-connection-fail
irvingoujAtDevolution Mar 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 136 additions & 17 deletions examples/tcp_client.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,155 @@
use std::{io, net};
#[cfg(target_os = "linux")]
fn main() -> std::io::Result<()> {
use std::net;
use std::{io::Write, time::Duration};

use polling::Event;
use socket2::Type;
use polling::Event;
use socket2::Type;

fn main() -> io::Result<()> {
std::thread::spawn(|| {
let listener = net::TcpListener::bind("0.0.0.0:8080").unwrap();
println!("Listening on {}", listener.local_addr().unwrap());
for stream in listener.incoming() {
let mut stream = stream.unwrap();
stream.write_all(b"Hello, world!\n").unwrap();
}
});
std::thread::sleep(Duration::from_millis(100));
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();
poller.wait(&mut events, Some(Duration::from_secs(3)))?;

let event = events.iter().next().expect("no event");

assert!(event.is_interrupt());

let addr = net::SocketAddr::new("127.0.0.1".parse().unwrap(), 8080);
let err = socket.connect(&addr.into()).unwrap_err();

// EINPROGRESS
assert_eq!(115, err.raw_os_error().expect("No OS error"));

poller
.modify(&socket, Event::writable(0))
.expect("modify failed");
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(());
poller.wait(&mut events, Some(Duration::from_secs(3)))?;

let event = events.iter().next().expect("no event");

assert!(event.writable);
assert!(!event.is_interrupt());
assert!(!event.is_err().unwrap());

println!("event: {:?}", event);
println!("socket is now writable");
// ========================================================================
// the below is example of a bad socket
println!("testing bad socket");
let bad_socket = socket2::Socket::new(socket2::Domain::IPV4, Type::STREAM, None)?;
irvingoujAtDevolution marked this conversation as resolved.
Show resolved Hide resolved
let addr = net::SocketAddr::new("127.0.0.1".parse().unwrap(), 12345);
bad_socket.set_nonblocking(true)?;

unsafe {
poller.add(&bad_socket, Event::writable(0))?;
}

events.clear();
poller.wait(&mut events, Some(Duration::from_secs(3)))?;

let err = bad_socket.connect(&addr.into()).unwrap_err();
assert_eq!(115, err.raw_os_error().expect("No OS error"));

poller
.modify(&bad_socket, Event::writable(0))
.expect("modify failed");

events.clear();
poller.wait(&mut events, Some(Duration::from_secs(3)))?;

let event = events.iter().next().expect("no event");

assert!(event.is_err().unwrap());
println!("bad socket is now in error state");

Ok(())
}

#[cfg(target_os = "windows")]
fn main() -> std::io::Result<()> {
use polling::Event;
use std::io;
use std::{io::Write, time::Duration};

std::thread::spawn(|| {
let listener = std::net::TcpListener::bind("0.0.0.0:8080").unwrap();
println!("Listening on {}", listener.local_addr().unwrap());
for stream in listener.incoming() {
let mut stream = match stream {
Ok(stream) => stream,
Err(_) => {
continue;
}
};
stream.write_all(b"Hello, world!\n").unwrap();
}
};
});
std::thread::sleep(Duration::from_millis(100));
let socket = socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, None)?;
let poller = polling::Poller::new()?;
unsafe {
poller.add(&socket, Event::new(0, true, true))?;
}

socket.set_nonblocking(true)?;

let addr = std::net::SocketAddr::new("127.0.0.1".parse().unwrap(), 8080);
let err = socket.connect(&addr.into()).unwrap_err();

assert_eq!(err.kind(), io::ErrorKind::WouldBlock);

let mut events = polling::Events::new();
poller.wait(&mut events, Some(Duration::from_secs(3)))?;

let event = events.iter().next().expect("no event");

assert!(event.writable);
assert!(!event.is_interrupt());
assert!(!event.is_err().unwrap());

println!("event: {:?}", event);
if event.is_connect_failed().unwrap_or_default() {
println!("connect failed");
println!("socket is now writable");
// // ========================================================================
// // the below is example of a bad socket
println!("testing bad socket");
let bad_socket = socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, None)?;
let addr = std::net::SocketAddr::new("127.0.0.1".parse().unwrap(), 12345);
bad_socket.set_nonblocking(true)?;
bad_socket.connect(&addr.into()).unwrap_err();

unsafe {
poller.add(&bad_socket, Event::writable(0))?;
}

events.clear();
poller.wait(&mut events, Some(Duration::from_secs(3)))?;

let event = events.iter().next().expect("no event");

assert!(event.is_err().unwrap());
println!("bad socket is now in error state");

Ok(())
}

#[cfg(not(any(target_os = "linux", target_os = "windows")))]
fn main() {
println!("This example is not yet supported on this platform.");
}
7 changes: 6 additions & 1 deletion src/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,9 +386,14 @@ impl EventExtra {
pub fn is_connect_failed(&self) -> Option<bool> {
Some(
self.flags.contains(epoll::EventFlags::ERR)
|| self.flags.contains(epoll::EventFlags::HUP),
&& self.flags.contains(epoll::EventFlags::HUP),
)
}

#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.contains(epoll::EventFlags::ERR))
}
}

/// The notifier for Linux.
Expand Down
8 changes: 7 additions & 1 deletion src/iocp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,11 +682,17 @@ impl EventExtra {
self.flags.set(AfdPollMask::RECEIVE_EXPEDITED, active);
}

/// Check if TCP connect failed.
/// Check if TCP connect failed. Deprecated.
#[inline]
pub fn is_connect_failed(&self) -> Option<bool> {
Some(self.flags.intersects(AfdPollMask::CONNECT_FAIL))
}

/// Check if TCP connect failed.
#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.intersects(AfdPollMask::CONNECT_FAIL))
}
}

/// A packet used to wake up the poller with an event.
Expand Down
5 changes: 5 additions & 0 deletions src/kqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,11 @@ impl EventExtra {
pub fn is_connect_failed(&self) -> Option<bool> {
None
}

#[inline]
pub fn is_err(&self) -> Option<bool> {
None
}
}

pub(crate) fn mode_to_flags(mode: PollMode) -> kqueue::EventFlags {
Expand Down
53 changes: 53 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,10 +391,63 @@ impl Event {
/// 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]
#[deprecated]
irvingoujAtDevolution marked this conversation as resolved.
Show resolved Hide resolved
pub fn is_connect_failed(&self) -> Option<bool> {
self.extra.is_connect_failed()
}

/// Tells if this event is the result of a connection failure.
///
/// This function checks if an error exist,particularlly useful in detecting if TCP connection failed. It corresponds to the `EPOLLERR` event in Linux
/// and `CONNECT_FAILED` event in Windows IOCP.
///
/// note: in epoll, a tcp connection failure is indicated by EPOLLERR + EPOLLHUP, though just EPOLLERR is enough to indicate a connection failure.
irvingoujAtDevolution marked this conversation as resolved.
Show resolved Hide resolved
/// EPOLLHUP may happen when we haven't event called `connect` on the socket, but it is still a valid event to check for.
///
/// # Examples
///
/// ```
/// fn main() -> std::io::Result<()> {
/// use std::net;
/// use std::time::Duration;
///
/// use polling::Event;
/// use socket2::Type;
/// let poller = polling::Poller::new()?;
/// let bad_socket = socket2::Socket::new(socket2::Domain::IPV4, Type::STREAM, None)?;
/// let addr = net::SocketAddr::new("127.0.0.1".parse().unwrap(), 12345);
/// bad_socket.set_nonblocking(true)?;
/// let mut events = polling::Events::new();
///
/// let _ = bad_socket.connect(&addr.into()).unwrap_err();
///
/// unsafe {
/// poller.add(&bad_socket, Event::writable(0))?;
/// }
///
/// poller.wait(&mut events, Some(Duration::from_secs(3)))?;
///
/// let event = events.iter().next().expect("no event");
/// let is_err = match event.is_err() {
/// Some(is_err) => is_err,
/// None => {
/// println!("not supported in this platform");
/// return Ok(());
/// },
/// };
/// assert!(is_err);
/// println!("bad socket is now in error state");
///
/// Ok(())
/// }
irvingoujAtDevolution marked this conversation as resolved.
Show resolved Hide resolved
/// ```
/// Returns `Some(true)` if the connection has failed, `Some(false)` if there is an error,
irvingoujAtDevolution marked this conversation as resolved.
Show resolved Hide resolved
/// or `None` if the platform does not support detecting this condition.
#[inline]
pub fn is_err(&self) -> Option<bool> {
self.extra.is_err()
}

/// Remove any extra information from this event.
#[inline]
pub fn clear_extra(&mut self) {
Expand Down
5 changes: 5 additions & 0 deletions src/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,11 @@ impl EventExtra {
pub fn is_connect_failed(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR) || self.flags.contains(PollFlags::HUP))
}

#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR))
}
}

fn cvt_mode_as_remove(mode: PollMode) -> io::Result<bool> {
Expand Down
7 changes: 6 additions & 1 deletion src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ impl EventExtra {

#[inline]
pub fn is_connect_failed(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR) || self.flags.contains(PollFlags::HUP))
Some(self.flags.contains(PollFlags::ERR) && self.flags.contains(PollFlags::HUP))
}

#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR))
}
}
Loading