Compare commits
2 Commits
e88c28c15c
...
fdf388436a
| Author | SHA1 | Date | |
|---|---|---|---|
| fdf388436a | |||
| 0f7f1be3c3 |
@@ -26,9 +26,35 @@ const RECV_BUF: usize = MAX_DATAGRAM_BYTES + 1;
|
|||||||
/// so erroring out here kills a stream that the very next packet would resume. If the peer is
|
/// so erroring out here kills a stream that the very next packet would resume. If the peer is
|
||||||
/// genuinely gone, the QUIC control plane times out and ends the session cleanly instead. (This is
|
/// genuinely gone, the QUIC control plane times out and ends the session cleanly instead. (This is
|
||||||
/// the classic connected-UDP "ICMP errors are advisory" rule, doubly true with hole-punching.)
|
/// the classic connected-UDP "ICMP errors are advisory" rule, doubly true with hole-punching.)
|
||||||
|
/// - `ENOBUFS`: a WiFi/wlan driver (e.g. `ath11k` on the Steam Deck) returns this — NOT `EAGAIN`/
|
||||||
|
/// `WouldBlock` — when its tx queue is momentarily full. Rust maps `ENOBUFS` to
|
||||||
|
/// `ErrorKind::Uncategorized`, so the `WouldBlock` arm misses it; without this a transient
|
||||||
|
/// tx-queue burst tears the whole stream down (observed live: the host streamed flawlessly on
|
||||||
|
/// loopback / under a debugger — anything slow enough not to fill the small wlan0 buffer — but
|
||||||
|
/// died at full rate over WiFi). Same lossy-drop contract as `WouldBlock`; FEC + the next frame
|
||||||
|
/// recover. Asynchronous network-path blips (`ENETUNREACH`/`EHOSTUNREACH`/`ENETDOWN`/`EHOSTDOWN`)
|
||||||
|
/// are droppable for the same reason a stale ICMP is.
|
||||||
fn is_transient_io(e: &std::io::Error) -> bool {
|
fn is_transient_io(e: &std::io::Error) -> bool {
|
||||||
use std::io::ErrorKind::{ConnectionRefused, ConnectionReset, WouldBlock};
|
use std::io::ErrorKind::{ConnectionRefused, ConnectionReset, WouldBlock};
|
||||||
matches!(e.kind(), WouldBlock | ConnectionRefused | ConnectionReset)
|
if matches!(e.kind(), WouldBlock | ConnectionRefused | ConnectionReset) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// `ENOBUFS` & friends have no stable `ErrorKind`, so match the raw errno (unix only).
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
matches!(
|
||||||
|
e.raw_os_error(),
|
||||||
|
Some(libc::ENOBUFS)
|
||||||
|
| Some(libc::ENETUNREACH)
|
||||||
|
| Some(libc::EHOSTUNREACH)
|
||||||
|
| Some(libc::ENETDOWN)
|
||||||
|
| Some(libc::EHOSTDOWN)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
{
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build one `mmsghdr` per `iovec` (each a single-buffer message) for `sendmmsg`/`recvmmsg`. Shared
|
/// Build one `mmsghdr` per `iovec` (each a single-buffer message) for `sendmmsg`/`recvmmsg`. Shared
|
||||||
|
|||||||
@@ -837,12 +837,19 @@ async fn serve_session(
|
|||||||
// can be on different subnets; control + side planes ride the client-initiated QUIC, but
|
// can be on different subnets; control + side planes ride the client-initiated QUIC, but
|
||||||
// the raw video UDP needs the client to open the path first). Falls back to the
|
// the raw video UDP needs the client to open the path first). Falls back to the
|
||||||
// client-reported address for clients that don't punch (flat-LAN, unchanged).
|
// client-reported address for clients that don't punch (flat-LAN, unchanged).
|
||||||
let (transport, punched) = UdpTransport::connect_via_punch(
|
let (transport, punched) = match UdpTransport::connect_via_punch(
|
||||||
&format!("0.0.0.0:{udp_port}"),
|
&format!("0.0.0.0:{udp_port}"),
|
||||||
&client_udp.to_string(),
|
&client_udp.to_string(),
|
||||||
std::time::Duration::from_millis(2500),
|
std::time::Duration::from_millis(2500),
|
||||||
)
|
) {
|
||||||
.context("bind data plane")?;
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
// Surface the failure here directly: a data-plane bind error would otherwise be
|
||||||
|
// reported only after teardown (and a teardown stall could swallow it entirely).
|
||||||
|
tracing::error!(error = %e, %client_udp, udp_port, "data-plane socket bind/hole-punch failed");
|
||||||
|
return Err(anyhow::Error::new(e)).context("bind data plane");
|
||||||
|
}
|
||||||
|
};
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
%client_udp,
|
%client_udp,
|
||||||
punched,
|
punched,
|
||||||
|
|||||||
Reference in New Issue
Block a user