Skip to content

Commit

Permalink
refactor: Move net-dependent code in quinn-udp into submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
matheus23 committed Dec 16, 2024
1 parent 38cec54 commit 5033078
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 93 deletions.
182 changes: 93 additions & 89 deletions quinn-udp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,99 @@
#![warn(clippy::use_self)]

use std::net::{IpAddr, Ipv6Addr, SocketAddr};
#[cfg(all(feature = "net", unix))]
use std::os::unix::io::AsFd;
#[cfg(all(feature = "net", windows))]
use std::os::windows::io::AsSocket;

#[cfg(feature = "net")]
pub use net::*;

/// All UDP APIs that are behind the "net" feature.
#[cfg(feature = "net")]
use std::sync::Mutex;
// Allowing unused, otherwise the cfg condition complexity gets
// out of control only to skip an unused `Duration` import.
#[allow(unused)]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
use std::time::{Duration, Instant};
#[allow(unused)]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use web_time::{Duration, Instant};

#[cfg(all(feature = "net", any(unix, windows)))]
mod cmsg;

#[cfg(all(feature = "net", unix))]
#[path = "unix.rs"]
mod imp;

#[cfg(all(feature = "net", windows))]
#[path = "windows.rs"]
mod imp;

// No ECN support
#[cfg(all(feature = "net", not(any(unix, windows))))]
#[path = "fallback.rs"]
mod imp;
pub(crate) mod net {
#[cfg(unix)]
use std::os::unix::io::AsFd;
#[cfg(windows)]
use std::os::windows::io::AsSocket;
use std::sync::Mutex;
// Allowing unused, otherwise the cfg condition complexity gets
// out of control only to skip an unused `Duration` import.
#[allow(unused)]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
use std::time::{Duration, Instant};
#[allow(unused)]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use web_time::{Duration, Instant};

#[cfg(any(unix, windows))]
mod cmsg;

#[cfg(unix)]
#[path = "unix.rs"]
pub(crate) mod imp;

#[cfg(windows)]
#[path = "windows.rs"]
pub(crate) mod imp;

// No ECN support
#[cfg(not(any(unix, windows)))]
#[path = "fallback.rs"]
pub(crate) mod imp;

pub use imp::UdpSocketState;

/// Log at most 1 IO error per minute
const IO_ERROR_LOG_INTERVAL: Duration = std::time::Duration::from_secs(60);

/// Logs a warning message when sendmsg fails
///
/// Logging will only be performed if at least [`IO_ERROR_LOG_INTERVAL`]
/// has elapsed since the last error was logged.
#[cfg(any(feature = "tracing", feature = "direct-log"))]
fn log_sendmsg_error(
last_send_error: &Mutex<Instant>,
err: impl core::fmt::Debug,
transmit: &crate::Transmit,
) {
let now = Instant::now();
let last_send_error = &mut *last_send_error.lock().expect("poisend lock");
if now.saturating_duration_since(*last_send_error) > IO_ERROR_LOG_INTERVAL {
*last_send_error = now;
crate::log::warn!(
"sendmsg error: {:?}, Transmit: {{ destination: {:?}, src_ip: {:?}, ecn: {:?}, len: {:?}, segment_size: {:?} }}",
err, transmit.destination, transmit.src_ip, transmit.ecn, transmit.contents.len(), transmit.segment_size);
}
}

// No-op
#[cfg(not(any(feature = "tracing", feature = "direct-log")))]
fn log_sendmsg_error(_: &Mutex<Instant>, _: impl core::fmt::Debug, _: &Transmit) {}

/// A borrowed UDP socket
///
/// On Unix, constructible via `From<T: AsFd>`. On Windows, constructible via `From<T:
/// AsSocket>`.
// Wrapper around socket2 to avoid making it a public dependency and incurring stability risk
pub struct UdpSockRef<'a>(socket2::SockRef<'a>);

#[cfg(unix)]
impl<'s, S> From<&'s S> for UdpSockRef<'s>
where
S: AsFd,
{
fn from(socket: &'s S) -> Self {
Self(socket.into())
}
}

#[cfg(windows)]
impl<'s, S> From<&'s S> for UdpSockRef<'s>
where
S: AsSocket,
{
fn from(socket: &'s S) -> Self {
Self(socket.into())
}
}
}

#[allow(unused_imports, unused_macros)]
mod log {
Expand All @@ -82,12 +145,9 @@ mod log {
pub(crate) use no_op::*;
}

#[cfg(feature = "net")]
pub use imp::UdpSocketState;

/// Number of UDP packets to send/receive at a time
#[cfg(feature = "net")]
pub const BATCH_SIZE: usize = imp::BATCH_SIZE;
pub const BATCH_SIZE: usize = net::imp::BATCH_SIZE;
/// Number of UDP packets to send/receive at a time
#[cfg(not(feature = "net"))]
pub const BATCH_SIZE: usize = 1;
Expand Down Expand Up @@ -151,62 +211,6 @@ pub struct Transmit<'a> {
pub src_ip: Option<IpAddr>,
}

/// Log at most 1 IO error per minute
#[cfg(feature = "net")]
const IO_ERROR_LOG_INTERVAL: Duration = std::time::Duration::from_secs(60);

/// Logs a warning message when sendmsg fails
///
/// Logging will only be performed if at least [`IO_ERROR_LOG_INTERVAL`]
/// has elapsed since the last error was logged.
#[cfg(all(feature = "net", any(feature = "tracing", feature = "direct-log")))]
fn log_sendmsg_error(
last_send_error: &Mutex<Instant>,
err: impl core::fmt::Debug,
transmit: &Transmit,
) {
let now = Instant::now();
let last_send_error = &mut *last_send_error.lock().expect("poisend lock");
if now.saturating_duration_since(*last_send_error) > IO_ERROR_LOG_INTERVAL {
*last_send_error = now;
log::warn!(
"sendmsg error: {:?}, Transmit: {{ destination: {:?}, src_ip: {:?}, ecn: {:?}, len: {:?}, segment_size: {:?} }}",
err, transmit.destination, transmit.src_ip, transmit.ecn, transmit.contents.len(), transmit.segment_size);
}
}

// No-op
#[cfg(all(feature = "net", not(any(feature = "tracing", feature = "direct-log"))))]
fn log_sendmsg_error(_: &Mutex<Instant>, _: impl core::fmt::Debug, _: &Transmit) {}

/// A borrowed UDP socket
///
/// On Unix, constructible via `From<T: AsFd>`. On Windows, constructible via `From<T:
/// AsSocket>`.
// Wrapper around socket2 to avoid making it a public dependency and incurring stability risk
#[cfg(feature = "net")]
pub struct UdpSockRef<'a>(socket2::SockRef<'a>);

#[cfg(all(feature = "net", unix))]
impl<'s, S> From<&'s S> for UdpSockRef<'s>
where
S: AsFd,
{
fn from(socket: &'s S) -> Self {
Self(socket.into())
}
}

#[cfg(all(feature = "net", windows))]
impl<'s, S> From<&'s S> for UdpSockRef<'s>
where
S: AsSocket,
{
fn from(socket: &'s S) -> Self {
Self(socket.into())
}
}

/// Explicit congestion notification codepoint
#[repr(u8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 3 additions & 2 deletions quinn-udp/src/unix.rs → quinn-udp/src/net/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use std::{

use socket2::SockRef;

use super::{
cmsg, log_sendmsg_error, EcnCodepoint, RecvMeta, Transmit, UdpSockRef, IO_ERROR_LOG_INTERVAL,
use crate::{
net::{cmsg, log_sendmsg_error, UdpSockRef, IO_ERROR_LOG_INTERVAL},
EcnCodepoint, RecvMeta, Transmit,
};

// Adapted from https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/sys/socket_private.h
Expand Down
7 changes: 5 additions & 2 deletions quinn-udp/src/windows.rs → quinn-udp/src/net/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ use windows_sys::Win32::{
};

use crate::{
cmsg::{self, CMsgHdr},
log::debug,
log_sendmsg_error, EcnCodepoint, RecvMeta, Transmit, UdpSockRef, IO_ERROR_LOG_INTERVAL,
net::{
cmsg::{self, CMsgHdr},
log_sendmsg_error, IO_ERROR_LOG_INTERVAL,
},
EcnCodepoint, RecvMeta, Transmit, UdpSockRef,
};

/// QUIC-friendly UDP socket for Windows
Expand Down

0 comments on commit 5033078

Please sign in to comment.