dbf96b68d3
ci / test (push) Has been cancelled
ci / fuzz-smoke (push) Has been cancelled
ci / windows-client (push) Has been cancelled
ci / package-release (linux-x86_64, ubuntu-latest) (push) Has been cancelled
ci / package-release (macos-aarch64, macos-14) (push) Has been cancelled
ci / package-release (macos-x86_64, macos-13) (push) Has been cancelled
ci / package-release (windows-x86_64, windows-latest) (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
105 lines
3.0 KiB
Rust
105 lines
3.0 KiB
Rust
//! UDP error classification shared by Dosh clients, servers, and embedders.
|
|
|
|
pub fn is_transient_udp_error(err: &std::io::Error) -> bool {
|
|
matches!(
|
|
err.kind(),
|
|
std::io::ErrorKind::Interrupted
|
|
| std::io::ErrorKind::TimedOut
|
|
| std::io::ErrorKind::WouldBlock
|
|
) || err.raw_os_error().is_some_and(is_transient_udp_os_error)
|
|
}
|
|
|
|
pub fn is_transient_udp_send_error(err: &std::io::Error) -> bool {
|
|
is_transient_udp_error(err)
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
fn is_transient_udp_os_error(code: i32) -> bool {
|
|
matches!(
|
|
code,
|
|
libc::EADDRNOTAVAIL
|
|
| libc::ECONNREFUSED
|
|
| libc::ECONNRESET
|
|
| libc::EHOSTDOWN
|
|
| libc::EHOSTUNREACH
|
|
| libc::ENETDOWN
|
|
| libc::ENETRESET
|
|
| libc::ENETUNREACH
|
|
| libc::ETIMEDOUT
|
|
)
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
fn is_transient_udp_os_error(code: i32) -> bool {
|
|
matches!(
|
|
code,
|
|
10049 // WSAEADDRNOTAVAIL
|
|
| 10050 // WSAENETDOWN
|
|
| 10051 // WSAENETUNREACH
|
|
| 10052 // WSAENETRESET
|
|
| 10054 // WSAECONNRESET
|
|
| 10060 // WSAETIMEDOUT
|
|
| 10061 // WSAECONNREFUSED
|
|
| 10064 // WSAEHOSTDOWN
|
|
| 10065 // WSAEHOSTUNREACH
|
|
)
|
|
}
|
|
|
|
#[cfg(not(any(unix, windows)))]
|
|
fn is_transient_udp_os_error(_code: i32) -> bool {
|
|
false
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{is_transient_udp_error, is_transient_udp_send_error};
|
|
|
|
#[test]
|
|
fn classifies_portable_transient_udp_errors() {
|
|
for kind in [
|
|
std::io::ErrorKind::Interrupted,
|
|
std::io::ErrorKind::TimedOut,
|
|
std::io::ErrorKind::WouldBlock,
|
|
] {
|
|
let err = std::io::Error::from(kind);
|
|
assert!(is_transient_udp_error(&err));
|
|
assert!(is_transient_udp_send_error(&err));
|
|
}
|
|
let fatal = std::io::Error::from(std::io::ErrorKind::PermissionDenied);
|
|
assert!(!is_transient_udp_error(&fatal));
|
|
assert!(!is_transient_udp_send_error(&fatal));
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn classifies_unix_network_churn_as_transient() {
|
|
for code in [
|
|
libc::EADDRNOTAVAIL,
|
|
libc::ECONNREFUSED,
|
|
libc::ECONNRESET,
|
|
libc::EHOSTDOWN,
|
|
libc::EHOSTUNREACH,
|
|
libc::ENETDOWN,
|
|
libc::ENETRESET,
|
|
libc::ENETUNREACH,
|
|
libc::ETIMEDOUT,
|
|
] {
|
|
let err = std::io::Error::from_raw_os_error(code);
|
|
assert!(is_transient_udp_error(&err));
|
|
assert!(is_transient_udp_send_error(&err));
|
|
}
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
#[test]
|
|
fn classifies_windows_network_churn_as_transient() {
|
|
for code in [
|
|
10049, 10050, 10051, 10052, 10054, 10060, 10061, 10064, 10065,
|
|
] {
|
|
let err = std::io::Error::from_raw_os_error(code);
|
|
assert!(is_transient_udp_error(&err));
|
|
assert!(is_transient_udp_send_error(&err));
|
|
}
|
|
}
|
|
}
|