noq/
connection.rs

1use std::{
2    any::Any,
3    fmt,
4    future::Future,
5    io,
6    net::{IpAddr, SocketAddr},
7    num::NonZeroUsize,
8    pin::Pin,
9    sync::{
10        Arc, Weak,
11        atomic::{AtomicUsize, Ordering},
12    },
13    task::{Context, Poll, Waker, ready},
14};
15
16use bytes::Bytes;
17use pin_project_lite::pin_project;
18use rustc_hash::FxHashMap;
19use thiserror::Error;
20use tokio::sync::{Notify, futures::Notified, mpsc, oneshot, watch};
21use tracing::{Instrument, Span, debug_span};
22
23use crate::{
24    ConnectionEvent, Duration, Instant, Path, VarInt,
25    endpoint::ensure_ipv6,
26    mutex::{Mutex, MutexGuard},
27    path::{OpenPath, PathRef, PathRefOwner},
28    recv_stream::RecvStream,
29    runtime::{AsyncTimer, Runtime, UdpSender},
30    send_stream::SendStream,
31    udp_transmit,
32};
33use proto::{
34    ConnectionError, ConnectionHandle, ConnectionStats, Dir, EndpointEvent, FourTuple, PathError,
35    PathEvent, PathId, PathStats, PathStatus, Side, StreamEvent, StreamId, TransportError,
36    TransportErrorCode, congestion::Controller, n0_nat_traversal,
37};
38
39/// In-progress connection attempt future
40#[derive(Debug)]
41pub struct Connecting {
42    conn: Option<ConnectionRef>,
43    connected: oneshot::Receiver<bool>,
44    handshake_data_ready: Option<oneshot::Receiver<()>>,
45}
46
47impl Connecting {
48    pub(crate) fn new(
49        handle: ConnectionHandle,
50        conn: proto::Connection,
51        endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>,
52        conn_events: mpsc::UnboundedReceiver<ConnectionEvent>,
53        sender: Pin<Box<dyn UdpSender>>,
54        runtime: Arc<dyn Runtime>,
55    ) -> Self {
56        let (on_handshake_data_send, on_handshake_data_recv) = oneshot::channel();
57        let (on_connected_send, on_connected_recv) = oneshot::channel();
58
59        let conn = ConnectionRef(Arc::new(Arc::new(ConnectionInner {
60            state: Mutex::new(State::new(
61                conn,
62                handle,
63                endpoint_events,
64                conn_events,
65                on_handshake_data_send,
66                on_connected_send,
67                sender,
68                runtime.clone(),
69            )),
70            shared: Shared::default(),
71        })));
72
73        let driver = ConnectionDriver(conn.clone());
74        runtime.spawn(Box::pin(
75            async {
76                if let Err(e) = driver.await {
77                    tracing::error!("I/O error: {e}");
78                }
79            }
80            .instrument(Span::current()),
81        ));
82
83        Self {
84            conn: Some(conn),
85            connected: on_connected_recv,
86            handshake_data_ready: Some(on_handshake_data_recv),
87        }
88    }
89
90    /// Convert into a 0-RTT or 0.5-RTT connection at the cost of weakened security
91    ///
92    /// Returns `Ok` immediately if the local endpoint is able to attempt sending 0/0.5-RTT data.
93    /// If so, the returned [`Connection`] can be used to send application data without waiting for
94    /// the rest of the handshake to complete, at the cost of weakened cryptographic security
95    /// guarantees. The returned [`ZeroRttAccepted`] future resolves when the handshake does
96    /// complete, at which point subsequently opened streams and written data will have full
97    /// cryptographic protection.
98    ///
99    /// ## Outgoing
100    ///
101    /// For outgoing connections, the initial attempt to convert to a [`Connection`] which sends
102    /// 0-RTT data will proceed if the [`crypto::ClientConfig`][crate::crypto::ClientConfig]
103    /// attempts to resume a previous TLS session. However, **the remote endpoint may not actually
104    /// _accept_ the 0-RTT data**--yet still accept the connection attempt in general. This
105    /// possibility is conveyed through the [`ZeroRttAccepted`] future--when the handshake
106    /// completes, it resolves to true if the 0-RTT data was accepted and false if it was rejected.
107    /// If it was rejected, the existence of streams opened and other application data sent prior
108    /// to the handshake completing will not be conveyed to the remote application, and local
109    /// operations on them will return `ZeroRttRejected` errors.
110    ///
111    /// A server may reject 0-RTT data at its discretion, but accepting 0-RTT data requires the
112    /// relevant resumption state to be stored in the server, which servers may limit or lose for
113    /// various reasons including not persisting resumption state across server restarts.
114    ///
115    /// If manually providing a [`crypto::ClientConfig`][crate::crypto::ClientConfig], check your
116    /// implementation's docs for 0-RTT pitfalls.
117    ///
118    /// ## Incoming
119    ///
120    /// For incoming connections, conversion to 0.5-RTT will always fully succeed. `into_0rtt` will
121    /// always return `Ok` and the [`ZeroRttAccepted`] will always resolve to true.
122    ///
123    /// If manually providing a [`crypto::ServerConfig`][crate::crypto::ServerConfig], check your
124    /// implementation's docs for 0-RTT pitfalls.
125    ///
126    /// ## Security
127    ///
128    /// On outgoing connections, this enables transmission of 0-RTT data, which is vulnerable to
129    /// replay attacks, and should therefore never invoke non-idempotent operations.
130    ///
131    /// On incoming connections, this enables transmission of 0.5-RTT data, which may be sent
132    /// before TLS client authentication has occurred, and should therefore not be used to send
133    /// data for which client authentication is being used.
134    pub fn into_0rtt(mut self) -> Result<(Connection, ZeroRttAccepted), Self> {
135        // This lock borrows `self` and would normally be dropped at the end of this scope, so we'll
136        // have to release it explicitly before returning `self` by value.
137        let conn = (self.conn.as_mut().unwrap()).lock_without_waking("into_0rtt");
138
139        let is_ok = conn.inner.has_0rtt() || conn.inner.side().is_server();
140        drop(conn);
141
142        if is_ok {
143            let conn = self.conn.take().unwrap();
144            Ok((Connection(conn), ZeroRttAccepted(self.connected)))
145        } else {
146            Err(self)
147        }
148    }
149
150    /// Parameters negotiated during the handshake
151    ///
152    /// The dynamic type returned is determined by the configured
153    /// [`Session`](proto::crypto::Session). For the default `rustls` session, the return value can
154    /// be [`downcast`](Box::downcast) to a
155    /// [`crypto::rustls::HandshakeData`](crate::crypto::rustls::HandshakeData).
156    pub async fn handshake_data(&mut self) -> Result<Box<dyn Any>, ConnectionError> {
157        // Taking &mut self allows us to use a single oneshot channel rather than dealing with
158        // potentially many tasks waiting on the same event. It's a bit of a hack, but keeps things
159        // simple.
160        if let Some(x) = self.handshake_data_ready.take() {
161            let _ = x.await;
162        }
163        let conn = self.conn.as_ref().unwrap();
164        let inner = conn.lock_without_waking("handshake");
165        inner
166            .inner
167            .crypto_session()
168            .handshake_data()
169            .ok_or_else(|| {
170                inner
171                    .error
172                    .clone()
173                    .expect("spurious handshake data ready notification")
174            })
175    }
176
177    /// The local IP address which was used when the peer established
178    /// the connection
179    ///
180    /// This can be different from the address the endpoint is bound to, in case
181    /// the endpoint is bound to a wildcard address like `0.0.0.0` or `::`.
182    ///
183    /// This will return `None` for clients, or when the platform does not expose this
184    /// information. See [`noq_udp::RecvMeta::dst_ip`](udp::RecvMeta::dst_ip) for a list of
185    /// supported platforms when using [`noq_udp`](udp) for I/O, which is the default.
186    ///
187    /// Will panic if called after `poll` has returned `Ready`.
188    pub fn local_ip(&self) -> Option<IpAddr> {
189        let conn = self.conn.as_ref().expect("used after yielding Ready");
190        let inner = conn.lock_without_waking("local_ip");
191
192        inner
193            .inner
194            .network_path(PathId::ZERO)
195            .expect("PathId::ZERO is the only path during the handshake")
196            .local_ip()
197    }
198
199    /// The peer's UDP addresses
200    ///
201    /// Will panic if called after `poll` has returned `Ready`.
202    pub fn remote_address(&self) -> SocketAddr {
203        let conn_ref: &ConnectionRef = self.conn.as_ref().expect("used after yielding Ready");
204        conn_ref
205            .lock_without_waking("remote_address")
206            .inner
207            .network_path(PathId::ZERO)
208            .expect("PathId::ZERO is the only path during the handshake")
209            .remote()
210    }
211}
212
213impl Future for Connecting {
214    type Output = Result<Connection, ConnectionError>;
215    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
216        Pin::new(&mut self.connected).poll(cx).map(|_| {
217            let conn = self.conn.take().unwrap();
218            let inner = conn.lock_without_waking("connecting");
219            if inner.connected {
220                drop(inner);
221                Ok(Connection(conn))
222            } else {
223                Err(inner
224                    .error
225                    .clone()
226                    .expect("connected signaled without connection success or error"))
227            }
228        })
229    }
230}
231
232/// Future that completes when a connection is fully established
233///
234/// For clients, the resulting value indicates if 0-RTT was accepted. For servers, the resulting
235/// value is meaningless.
236pub struct ZeroRttAccepted(oneshot::Receiver<bool>);
237
238impl Future for ZeroRttAccepted {
239    type Output = bool;
240    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
241        Pin::new(&mut self.0).poll(cx).map(|x| x.unwrap_or(false))
242    }
243}
244
245/// A future that drives protocol logic for a connection
246///
247/// This future handles the protocol logic for a single connection, routing events from the
248/// `Connection` API object to the `Endpoint` task and the related stream-related interfaces.
249/// It also keeps track of outstanding timeouts for the `Connection`.
250///
251/// If the connection encounters an error condition, this future will yield an error. It will
252/// terminate (yielding `Ok(())`) if the connection was closed without error. Unlike other
253/// connection-related futures, this waits for the draining period to complete to ensure that
254/// packets still in flight from the peer are handled gracefully.
255#[must_use = "connection drivers must be spawned for their connections to function"]
256#[derive(Debug)]
257struct ConnectionDriver(ConnectionRef);
258
259impl Future for ConnectionDriver {
260    type Output = Result<(), io::Error>;
261
262    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
263        let conn = &mut *self.0.lock_without_waking("poll");
264
265        let span = debug_span!("drive", id = conn.handle.0);
266        let _guard = span.enter();
267
268        if let Err(e) = conn.process_conn_events(&self.0.shared, cx) {
269            conn.terminate(e, &self.0.shared);
270            return Poll::Ready(Ok(()));
271        }
272        let mut keep_going = conn.drive_transmit(cx)?;
273        // If a timer expires, there might be more to transmit. When we transmit something, we
274        // might need to reset a timer. Hence, we must loop until neither happens.
275        keep_going |= conn.drive_timer(cx);
276        conn.forward_endpoint_events();
277        conn.forward_app_events(&self.0.shared);
278
279        if !conn.inner.is_drained() {
280            if keep_going {
281                // If the connection hasn't processed all tasks, schedule it again
282                cx.waker().wake_by_ref();
283            } else {
284                conn.driver = Some(cx.waker().clone());
285            }
286            return Poll::Pending;
287        }
288        if conn.error.is_none() {
289            unreachable!("drained connections always have an error");
290        }
291        Poll::Ready(Ok(()))
292    }
293}
294
295/// A QUIC connection.
296///
297/// If all references to a connection (including every clone of the `Connection` handle, streams of
298/// incoming streams, and the various stream types) have been dropped, then the connection will be
299/// automatically closed with an `error_code` of 0 and an empty `reason`. You can also close the
300/// connection explicitly by calling [`Connection::close()`].
301///
302/// Closing the connection immediately abandons efforts to deliver data to the peer.  Upon
303/// receiving CONNECTION_CLOSE the peer *may* drop any stream data not yet delivered to the
304/// application. [`Connection::close()`] describes in more detail how to gracefully close a
305/// connection without losing application data.
306///
307/// May be cloned to obtain another handle to the same connection.
308///
309/// [`Connection::close()`]: Connection::close
310#[derive(Debug, Clone)]
311pub struct Connection(ConnectionRef);
312
313impl Connection {
314    /// Returns a weak reference to the inner connection struct.
315    pub fn weak_handle(&self) -> WeakConnectionHandle {
316        self.0.weak_handle()
317    }
318
319    /// Initiate a new outgoing unidirectional stream.
320    ///
321    /// Streams are cheap and instantaneous to open unless blocked by flow control. As a
322    /// consequence, the peer won't be notified that a stream has been opened until the stream is
323    /// actually used.
324    pub fn open_uni(&self) -> OpenUni<'_> {
325        OpenUni {
326            conn: &self.0,
327            notify: self.0.shared.stream_budget_available[Dir::Uni as usize].notified(),
328        }
329    }
330
331    /// Initiate a new outgoing bidirectional stream.
332    ///
333    /// Streams are cheap and instantaneous to open unless blocked by flow control. As a
334    /// consequence, the peer won't be notified that a stream has been opened until the stream is
335    /// actually used. Calling [`open_bi()`] then waiting on the [`RecvStream`] without writing
336    /// anything to [`SendStream`] will never succeed.
337    ///
338    /// [`open_bi()`]: crate::Connection::open_bi
339    /// [`SendStream`]: crate::SendStream
340    /// [`RecvStream`]: crate::RecvStream
341    pub fn open_bi(&self) -> OpenBi<'_> {
342        OpenBi {
343            conn: &self.0,
344            notify: self.0.shared.stream_budget_available[Dir::Bi as usize].notified(),
345        }
346    }
347
348    /// Accept the next incoming uni-directional stream
349    pub fn accept_uni(&self) -> AcceptUni<'_> {
350        AcceptUni {
351            conn: &self.0,
352            notify: self.0.shared.stream_incoming[Dir::Uni as usize].notified(),
353        }
354    }
355
356    /// Accept the next incoming bidirectional stream
357    ///
358    /// **Important Note**: The `Connection` that calls [`open_bi()`] must write to its
359    /// [`SendStream`] before the other `Connection` is able to `accept_bi()`. Calling
360    /// [`open_bi()`] then waiting on the [`RecvStream`] without writing anything to
361    /// [`SendStream`] will never succeed.
362    ///
363    /// [`accept_bi()`]: crate::Connection::accept_bi
364    /// [`open_bi()`]: crate::Connection::open_bi
365    /// [`SendStream`]: crate::SendStream
366    /// [`RecvStream`]: crate::RecvStream
367    pub fn accept_bi(&self) -> AcceptBi<'_> {
368        AcceptBi {
369            conn: &self.0,
370            notify: self.0.shared.stream_incoming[Dir::Bi as usize].notified(),
371        }
372    }
373
374    /// Receive an application datagram
375    pub fn read_datagram(&self) -> ReadDatagram<'_> {
376        ReadDatagram {
377            conn: &self.0,
378            notify: self.0.shared.datagram_received.notified(),
379        }
380    }
381
382    /// Opens a new path if no path exists yet for `network_path`.
383    ///
384    /// If `network_path` has no local IP set, then this will open a new path
385    /// if no path exists for this remote address, independent of the existing
386    /// path's local IP. If a local IP is set, it will match against the full
387    /// four-tuple of existing paths.
388    ///
389    /// Otherwise behaves exactly as [`open_path`].
390    ///
391    /// [`open_path`]: Self::open_path
392    pub fn open_path_ensure(
393        &self,
394        network_path: impl Into<FourTuple>,
395        initial_status: PathStatus,
396    ) -> OpenPath {
397        let network_path = network_path.into();
398        let mut state = self.0.lock_and_wake("open_path");
399
400        let network_path = match normalize_network_path(network_path, &state.inner) {
401            Ok(network_path) => network_path,
402            Err(err) => return OpenPath::rejected(err),
403        };
404
405        let now = state.runtime.now();
406        let open_res = state
407            .inner
408            .open_path_ensure(network_path, initial_status, now);
409        match open_res {
410            Ok((path_id, existed)) if existed => {
411                let recv = state.open_path.get(&path_id).map(|tx| tx.subscribe());
412                drop(state);
413                match recv {
414                    Some(recv) => OpenPath::new(path_id, recv, self.0.clone()),
415                    None => OpenPath::ready(path_id, self.0.clone()),
416                }
417            }
418            Ok((path_id, _)) => {
419                let (tx, rx) = watch::channel(Ok(()));
420                state.open_path.insert(path_id, tx);
421                drop(state);
422                OpenPath::new(path_id, rx, self.0.clone())
423            }
424            Err(err) => OpenPath::rejected(err),
425        }
426    }
427
428    /// Opens an additional path if the multipath extension is negotiated.
429    ///
430    /// This function takes a [`FourTuple`], which contains the remote address and an optional
431    /// local IP. If the local IP is set, the path will be opened with this source address,
432    /// and the endpoint must support sending from that IP address. You can also pass a
433    /// [`SocketAddr`] to only set the remote address and leave the local IP interface unspecified.
434    ///
435    /// The returned future completes once the path is either fully opened and ready to
436    /// carry application data, or if there was an error.
437    ///
438    /// Dropping the returned future does not cancel the opening of the path, the
439    /// [`PathEvent::Established`] event will still be emitted from [`Self::path_events`] if
440    /// the path opens.  The [`PathId`] for the events can be extracted from
441    /// [`OpenPath::path_id`].
442    ///
443    /// Failure to open a path can either occur immediately, before polling the returned
444    /// future, or at a later time.  If the failure is immediate [`OpenPath::path_id`] will
445    /// return `None` and the future will be ready immediately.  If the failure happens
446    /// later, a [`PathEvent`] will be emitted.
447    pub fn open_path(
448        &self,
449        network_path: impl Into<FourTuple>,
450        initial_status: PathStatus,
451    ) -> OpenPath {
452        let network_path = network_path.into();
453        let mut state = self.0.lock_and_wake("open_path");
454
455        let network_path = match normalize_network_path(network_path, &state.inner) {
456            Ok(network_path) => network_path,
457            Err(err) => return OpenPath::rejected(err),
458        };
459
460        let (on_open_path_send, on_open_path_recv) = watch::channel(Ok(()));
461        let now = state.runtime.now();
462        let open_res = state.inner.open_path(network_path, initial_status, now);
463        match open_res {
464            Ok(path_id) => {
465                state.open_path.insert(path_id, on_open_path_send);
466                drop(state);
467                OpenPath::new(path_id, on_open_path_recv, self.0.clone())
468            }
469            Err(err) => OpenPath::rejected(err),
470        }
471    }
472
473    /// Returns the [`Path`] structure of an open path
474    pub fn path(&self, id: PathId) -> Option<Path> {
475        Path::new(&self.0, id)
476    }
477
478    /// A stream of [`PathEvent`]s for all paths in this connection.
479    ///
480    /// The stream will yield a [`PathEvent`] whenever there is a change in the state of any path in
481    /// this connection. The events need to be processed immediately, since there isn't an
482    /// unbounded buffer for them.
483    ///
484    /// If processing of events lags behind too much, you will get an error of type
485    /// [`crate::Lagged`] indicating how many events were lost. The stream continues after a
486    /// lag, delivering the oldest retained message next.
487    pub fn path_events(&self) -> crate::PathEvents {
488        crate::PathEvents::new(
489            self.0
490                .lock_without_waking("path_events")
491                .path_events
492                .subscribe(),
493        )
494    }
495
496    /// A stream of NAT traversal updates for this connection.
497    ///
498    /// The events need to be processed immediately, since there isn't an unbounded buffer for them.
499    ///
500    /// If processing of events lags behind too much, you will get an error of type
501    /// [`crate::Lagged`] indicating how many events were lost. The stream continues after a
502    /// lag, delivering the oldest retained message next.
503    pub fn nat_traversal_updates(&self) -> crate::NatTraversalUpdates {
504        crate::NatTraversalUpdates::new(
505            self.0
506                .lock_without_waking("nat_traversal_updates")
507                .nat_traversal_updates
508                .subscribe(),
509        )
510    }
511
512    /// Wait for the connection to be closed for any reason
513    ///
514    /// Despite the return type's name, closed connections are often not an error condition at the
515    /// application layer. Cases that might be routine include [`ConnectionError::LocallyClosed`]
516    /// and [`ConnectionError::ApplicationClosed`].
517    pub async fn closed(&self) -> ConnectionError {
518        {
519            let conn = self.0.lock_without_waking("closed");
520            if let Some(error) = conn.error.as_ref() {
521                return error.clone();
522            }
523            // Construct the future while the lock is held to ensure we can't miss a wakeup if
524            // the `Notify` is signaled immediately after we release the lock. `await` it after
525            // the lock guard is out of scope.
526            self.0.shared.closed.notified()
527        }
528        .await;
529        self.0
530            .lock_without_waking("closed")
531            .error
532            .as_ref()
533            .expect("closed without an error")
534            .clone()
535    }
536
537    /// Wait for the connection to be closed without keeping a strong reference to the connection
538    ///
539    /// Returns a future that resolves, once the connection is closed, to a [`Closed`] struct
540    /// describing the close reason and final connection and per-path statistics.
541    ///
542    /// Calling [`Self::closed`] keeps the connection alive until it is either closed locally via
543    /// [`Connection::close`] or closed by the remote peer. This function instead does not keep
544    /// the connection itself alive, so if all *other* clones of the connection are dropped, the
545    /// connection will be closed implicitly even if there are futures returned from this
546    /// function still being awaited.
547    pub fn on_closed(&self) -> OnClosed {
548        let (tx, rx) = oneshot::channel();
549        let mut state = self.0.lock_without_waking("on_closed");
550        if let Some(reason) = state.error.clone() {
551            // Connection already closed, send immediately
552            let _ = tx.send(Closed::new(&mut state, reason));
553        } else {
554            state.on_closed.push(tx);
555        }
556        drop(state);
557        OnClosed {
558            conn: self.weak_handle(),
559            rx,
560        }
561    }
562
563    /// Whether the connection is closed, and why.
564    ///
565    /// The close_reason is always set to `Some(ConnectionError)` when a socket is
566    /// closed; whether it was closed manually by calling [`Connection::close()`] or due to
567    /// an internal error (such as an idle timeout or the peer closing the
568    /// connection).
569    ///
570    /// Note: when the connection is closed, `connection.close_reason().is_some()` will always be
571    /// true.
572    pub fn close_reason(&self) -> Option<ConnectionError> {
573        self.0.lock_without_waking("close_reason").error.clone()
574    }
575
576    /// Close the connection immediately.
577    ///
578    /// Pending operations will fail immediately with [`ConnectionError::LocallyClosed`]. No
579    /// more data is sent to the peer and the peer may drop buffered data upon receiving
580    /// the CONNECTION_CLOSE frame.
581    ///
582    /// `error_code` and `reason` are not interpreted, and are provided directly to the peer.
583    ///
584    /// `reason` will be truncated to fit in a single packet with overhead; to improve odds that it
585    /// is preserved in full, it should be kept under 1KiB.
586    ///
587    /// # Gracefully closing a connection
588    ///
589    /// Only the peer last receiving application data can be certain that all data is
590    /// delivered. The only reliable action it can then take is to close the connection,
591    /// potentially with a custom error code. The delivery of the final CONNECTION_CLOSE
592    /// frame is very likely if both endpoints stay online long enough, and
593    /// [`Endpoint::wait_idle()`] can be used to provide sufficient time. Otherwise, the
594    /// remote peer will time out the connection, provided that the idle timeout is not
595    /// disabled.
596    ///
597    /// The sending side can not guarantee all stream data is delivered to the remote
598    /// application. It only knows the data is delivered to the QUIC stack of the remote
599    /// endpoint. Once the local side sends a CONNECTION_CLOSE frame in response to calling
600    /// [`close()`] the remote endpoint may drop any data it received but is as yet
601    /// undelivered to the application, including data that was acknowledged as received to
602    /// the local endpoint.
603    ///
604    /// [`ConnectionError::LocallyClosed`]: crate::ConnectionError::LocallyClosed
605    /// [`Endpoint::wait_idle()`]: crate::Endpoint::wait_idle
606    /// [`close()`]: Connection::close
607    pub fn close(&self, error_code: VarInt, reason: &[u8]) {
608        let conn = &mut *self.0.lock_without_waking("close"); // conn.close self-wakes
609        conn.close(error_code, Bytes::copy_from_slice(reason), &self.0.shared);
610    }
611
612    /// Wait for the handshake to be confirmed.
613    ///
614    /// As a server, who must be authenticated by clients,
615    /// this happens when the handshake completes
616    /// upon receiving a TLS Finished message from the client.
617    /// In return, the server send a HANDSHAKE_DONE frame.
618    ///
619    /// As a client, this happens when receiving a HANDSHAKE_DONE frame.
620    /// At this point, the server has either accepted our authentication,
621    /// or, if client authentication is not required, accepted our lack of authentication.
622    pub async fn handshake_confirmed(&self) -> Result<(), ConnectionError> {
623        {
624            let conn = self.0.lock_without_waking("handshake_confirmed");
625            if let Some(error) = conn.error.as_ref() {
626                return Err(error.clone());
627            }
628            if conn.handshake_confirmed {
629                return Ok(());
630            }
631            // Construct the future while the lock is held to ensure we can't miss a wakeup if
632            // the `Notify` is signaled immediately after we release the lock. `await` it after
633            // the lock guard is out of scope.
634            self.0.shared.handshake_confirmed.notified()
635        }
636        .await;
637        if let Some(error) = self
638            .0
639            .lock_without_waking("handshake_confirmed")
640            .error
641            .as_ref()
642        {
643            Err(error.clone())
644        } else {
645            Ok(())
646        }
647    }
648
649    /// Transmit `data` as an unreliable, unordered application datagram
650    ///
651    /// Application datagrams are a low-level primitive. They may be lost or delivered out of order,
652    /// and `data` must both fit inside a single QUIC packet and be smaller than the maximum
653    /// dictated by the peer.
654    ///
655    /// Previously queued datagrams which are still unsent may be discarded to make space for this
656    /// datagram, in order of oldest to newest.
657    pub fn send_datagram(&self, data: Bytes) -> Result<(), SendDatagramError> {
658        let conn = &mut *self.0.lock_and_wake("send_datagram");
659        if let Some(ref x) = conn.error {
660            return Err(SendDatagramError::ConnectionLost(x.clone()));
661        }
662        use proto::SendDatagramError::*;
663        match conn.inner.datagrams().send(data, true) {
664            Ok(()) => Ok(()),
665            Err(e) => Err(match e {
666                Blocked(..) => unreachable!(),
667                UnsupportedByPeer => SendDatagramError::UnsupportedByPeer,
668                Disabled => SendDatagramError::Disabled,
669                TooLarge => SendDatagramError::TooLarge,
670            }),
671        }
672    }
673
674    /// Transmit `data` as an unreliable, unordered application datagram
675    ///
676    /// Unlike [`send_datagram()`], this method will wait for buffer space during congestion
677    /// conditions, which effectively prioritizes old datagrams over new datagrams.
678    ///
679    /// See [`send_datagram()`] for details.
680    ///
681    /// [`send_datagram()`]: Connection::send_datagram
682    pub fn send_datagram_wait(&self, data: Bytes) -> SendDatagram<'_> {
683        SendDatagram {
684            conn: &self.0,
685            data: Some(data),
686            notify: self.0.shared.datagrams_unblocked.notified(),
687        }
688    }
689
690    /// Compute the maximum size of datagrams that may be passed to [`send_datagram()`].
691    ///
692    /// Returns `None` if datagrams are unsupported by the peer or disabled locally.
693    ///
694    /// This may change over the lifetime of a connection according to variation in the path MTU
695    /// estimate. The peer can also enforce an arbitrarily small fixed limit, but if the peer's
696    /// limit is large this is guaranteed to be a little over a kilobyte at minimum.
697    ///
698    /// Not necessarily the maximum size of received datagrams.
699    ///
700    /// [`send_datagram()`]: Connection::send_datagram
701    pub fn max_datagram_size(&self) -> Option<usize> {
702        self.0
703            .lock_without_waking("max_datagram_size")
704            .inner
705            .datagrams()
706            .max_size()
707    }
708
709    /// Bytes available in the outgoing datagram buffer
710    ///
711    /// When greater than zero, calling [`send_datagram()`](Self::send_datagram) with a datagram of
712    /// at most this size is guaranteed not to cause older datagrams to be dropped.
713    pub fn datagram_send_buffer_space(&self) -> usize {
714        self.0
715            .lock_without_waking("datagram_send_buffer_space")
716            .inner
717            .datagrams()
718            .send_buffer_space()
719    }
720
721    /// The side of the connection (client or server)
722    pub fn side(&self) -> Side {
723        self.0.lock_without_waking("side").inner.side()
724    }
725
726    /// Current best estimate of this connection's latency (round-trip-time)
727    pub fn rtt(&self, path_id: PathId) -> Option<Duration> {
728        self.0.lock_without_waking("rtt").inner.rtt(path_id)
729    }
730
731    /// Returns connection statistics
732    pub fn stats(&self) -> ConnectionStats {
733        self.0.lock_without_waking("stats").inner.stats()
734    }
735
736    /// Returns path statistics
737    pub fn path_stats(&self, path_id: PathId) -> Option<PathStats> {
738        self.0.lock_without_waking("path_stats").path_stats(path_id)
739    }
740
741    /// Current state of the congestion control algorithm, for debugging purposes
742    pub fn congestion_state(&self, path_id: PathId) -> Option<Box<dyn Controller>> {
743        self.0
744            .lock_without_waking("congestion_state")
745            .inner
746            .congestion_state(path_id)
747            .map(|c| c.clone_box())
748    }
749
750    /// Succeeds when an incoming connection is proven not to be a replay attack.
751    ///
752    /// Only interesting for `Connection`s obtained from [`Connecting::into_0rtt`]. On 1-RTT
753    /// connections, always completes immediately. Contrast
754    /// [`handshake_confirmed`](Self::handshake_confirmed), which waits longer on clients e.g. to
755    /// confirm client authentication.
756    ///
757    /// For incoming connections, reads from [`RecvStream`]s are guaranteed not to arise from replay
758    /// attacks after this succeeds, even for streams accepted or read during 0-RTT. For outgoing
759    /// connections, streams opened after this succeeds will never be discarded by the server due to
760    /// 0-RTT rejection.
761    pub async fn authenticated(&self) -> Result<(), ConnectionError> {
762        let notified = {
763            let conn = self.0.state.lock("connected");
764            if let Some(e) = &conn.error {
765                return Err(e.clone());
766            }
767            if conn.connected {
768                return Ok(());
769            }
770            self.0.shared.connected.notified()
771        };
772        notified.await;
773        let conn = self.0.state.lock("connected");
774        conn.error.clone().map_or(Ok(()), Err)
775    }
776
777    /// Parameters negotiated during the handshake
778    ///
779    /// Guaranteed to return `Some` on fully established connections or after
780    /// [`Connecting::handshake_data()`] succeeds. See that method's documentations for details on
781    /// the returned value.
782    ///
783    /// [`Connection::handshake_data()`]: crate::Connecting::handshake_data
784    pub fn handshake_data(&self) -> Option<Box<dyn Any>> {
785        self.0
786            .lock_without_waking("handshake_data")
787            .inner
788            .crypto_session()
789            .handshake_data()
790    }
791
792    /// Cryptographic identity of the peer
793    ///
794    /// The dynamic type returned is determined by the configured
795    /// [`Session`](proto::crypto::Session). For the default `rustls` session, the return value can
796    /// be [`downcast`](Box::downcast) to a <code>Vec<[rustls::pki_types::CertificateDer]></code>
797    pub fn peer_identity(&self) -> Option<Box<dyn Any>> {
798        self.0
799            .lock_without_waking("peer_identity")
800            .inner
801            .crypto_session()
802            .peer_identity()
803    }
804
805    /// A stable identifier for this connection
806    ///
807    /// Peer addresses and connection IDs can change, but this value will remain
808    /// fixed for the lifetime of the connection.
809    pub fn stable_id(&self) -> usize {
810        self.0.stable_id()
811    }
812
813    /// Update traffic keys spontaneously
814    ///
815    /// This primarily exists for testing purposes.
816    pub fn force_key_update(&self) {
817        self.0
818            .lock_and_wake("force_key_update")
819            .inner
820            .force_key_update()
821    }
822
823    /// Derive keying material from this connection's TLS session secrets.
824    ///
825    /// When both peers call this method with the same `label` and `context`
826    /// arguments and `output` buffers of equal length, they will get the
827    /// same sequence of bytes in `output`. These bytes are cryptographically
828    /// strong and pseudorandom, and are suitable for use as keying material.
829    ///
830    /// See [RFC5705](https://tools.ietf.org/html/rfc5705) for more information.
831    pub fn export_keying_material(
832        &self,
833        output: &mut [u8],
834        label: &[u8],
835        context: &[u8],
836    ) -> Result<(), proto::crypto::ExportKeyingMaterialError> {
837        self.0
838            .lock_without_waking("export_keying_material")
839            .inner
840            .crypto_session()
841            .export_keying_material(output, label, context)
842    }
843
844    /// Modify the number of remotely initiated unidirectional streams that may be concurrently open
845    ///
846    /// No streams may be opened by the peer unless fewer than `count` are already open. Large
847    /// `count`s increase both minimum and worst-case memory consumption.
848    pub fn set_max_concurrent_uni_streams(&self, count: VarInt) {
849        let mut conn = self.0.lock_and_wake("set_max_concurrent_uni_streams");
850        conn.inner.set_max_concurrent_streams(Dir::Uni, count);
851    }
852
853    /// See [`proto::TransportConfig::send_window()`]
854    pub fn set_send_window(&self, send_window: u64) {
855        let mut conn = self.0.lock_and_wake("set_send_window");
856        conn.inner.set_send_window(send_window);
857    }
858
859    /// See [`proto::TransportConfig::receive_window()`]
860    pub fn set_receive_window(&self, receive_window: VarInt) {
861        let mut conn = self.0.lock_and_wake("set_receive_window");
862        conn.inner.set_receive_window(receive_window);
863    }
864
865    /// Modify the number of remotely initiated bidirectional streams that may be concurrently open
866    ///
867    /// No streams may be opened by the peer unless fewer than `count` are already open. Large
868    /// `count`s increase both minimum and worst-case memory consumption.
869    pub fn set_max_concurrent_bi_streams(&self, count: VarInt) {
870        let mut conn = self.0.lock_and_wake("set_max_concurrent_bi_streams");
871        conn.inner.set_max_concurrent_streams(Dir::Bi, count);
872    }
873
874    /// Track changes on our external address as reported by the peer.
875    pub fn observed_external_addr(&self) -> crate::ObservedExternalAddr {
876        let conn = self.0.lock_without_waking("external_addr");
877        crate::ObservedExternalAddr::new(conn.observed_external_addr.subscribe())
878    }
879
880    /// Is multipath enabled?
881    // TODO(flub): not a useful API, once we do real things with multipath we can remove
882    // this again.
883    pub fn is_multipath_enabled(&self) -> bool {
884        let conn = self.0.lock_without_waking("is_multipath_enabled");
885        conn.inner.is_multipath_negotiated()
886    }
887
888    /// Registers one address at which this endpoint might be reachable
889    ///
890    /// When the NAT traversal extension is negotiated, servers send these addresses to clients in
891    /// `ADD_ADDRESS` frames. This allows clients to obtain server address candidates to initiate
892    /// NAT traversal attempts. Clients provide their own reachable addresses in `REACH_OUT` frames
893    /// when [`Self::initiate_nat_traversal_round`] is called.
894    pub fn add_nat_traversal_address(
895        &self,
896        address: SocketAddr,
897    ) -> Result<(), n0_nat_traversal::Error> {
898        let mut conn = self.0.lock_and_wake("add_nat_traversal_addresses");
899        conn.inner.add_nat_traversal_address(address)
900    }
901
902    /// Removes one or more addresses from the set of addresses at which this endpoint is reachable
903    ///
904    /// When the NAT traversal extension is negotiated, servers send address removals to
905    /// clients in `REMOVE_ADDRESS` frames. This allows clients to stop using outdated
906    /// server address candidates that are no longer valid for NAT traversal.
907    ///
908    /// For clients, removed addresses will no longer be advertised in `REACH_OUT` frames.
909    ///
910    /// Addresses not present in the set will be silently ignored.
911    pub fn remove_nat_traversal_address(
912        &self,
913        address: SocketAddr,
914    ) -> Result<(), n0_nat_traversal::Error> {
915        let mut conn = self.0.lock_and_wake("remove_nat_traversal_addresses");
916        conn.inner.remove_nat_traversal_address(address)
917    }
918
919    /// Get the current local nat traversal addresses
920    pub fn get_local_nat_traversal_addresses(
921        &self,
922    ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
923        let conn = self
924            .0
925            .lock_without_waking("get_local_nat_traversal_addresses");
926        conn.inner.get_local_nat_traversal_addresses()
927    }
928
929    /// Get the currently advertised nat traversal addresses by the server
930    pub fn get_remote_nat_traversal_addresses(
931        &self,
932    ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
933        let conn = self
934            .0
935            .lock_without_waking("get_remote_nat_traversal_addresses");
936        conn.inner.get_remote_nat_traversal_addresses()
937    }
938
939    /// Initiates a new nat traversal round
940    ///
941    /// A nat traversal round involves advertising the client's local addresses in `REACH_OUT`
942    /// frames, and initiating probing of the known remote addresses. When a new round is
943    /// initiated, the previous one is cancelled, and paths that have not been opened are closed.
944    ///
945    /// Returns the server addresses that are now being probed.
946    pub fn initiate_nat_traversal_round(&self) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
947        let mut conn = self.0.lock_and_wake("initiate_nat_traversal_round");
948        let now = conn.runtime.now();
949        conn.inner.initiate_nat_traversal_round(now)
950    }
951}
952
953/// Normalizes a [`FourTuple`] against the connection's address family.
954///
955/// If the connection already uses IPv6 paths, the remote is canonicalised via
956/// [`ensure_ipv6`]. If it uses IPv4 and the requested remote is IPv6, this returns
957/// [`PathError::InvalidRemoteAddress`].
958fn normalize_network_path(
959    network_path: FourTuple,
960    conn: &proto::Connection,
961) -> Result<FourTuple, PathError> {
962    // If endpoint::State::ipv6 is true we want to keep all our IP addresses as IPv6.
963    // If not, we do not support IPv6.  We can not access endpoint::State from here
964    // however, but either all our paths use an IPv6 address, or all our paths use an
965    // IPv4 address.  So we can use that information.
966    let ipv6 = conn
967        .paths()
968        .iter()
969        .filter_map(|id| {
970            conn.network_path(*id)
971                .map(|addrs| addrs.remote().is_ipv6())
972                .ok()
973        })
974        .next()
975        .unwrap_or_default();
976    let remote = network_path.remote();
977    if remote.is_ipv6() && !ipv6 {
978        Err(PathError::InvalidRemoteAddress(remote))
979    } else if ipv6 {
980        let remote = SocketAddr::V6(ensure_ipv6(remote));
981        Ok(FourTuple::new(remote, network_path.local_ip()))
982    } else {
983        Ok(network_path)
984    }
985}
986
987pin_project! {
988    /// Future produced by [`Connection::open_uni`]
989    pub struct OpenUni<'a> {
990        conn: &'a ConnectionRef,
991        #[pin]
992        notify: Notified<'a>,
993    }
994}
995
996impl Future for OpenUni<'_> {
997    type Output = Result<SendStream, ConnectionError>;
998    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
999        let this = self.project();
1000        let (conn, id, is_0rtt) = ready!(poll_open(ctx, this.conn, this.notify, Dir::Uni))?;
1001        Poll::Ready(Ok(SendStream::new(conn, id, is_0rtt)))
1002    }
1003}
1004
1005pin_project! {
1006    /// Future produced by [`Connection::open_bi`]
1007    pub struct OpenBi<'a> {
1008        conn: &'a ConnectionRef,
1009        #[pin]
1010        notify: Notified<'a>,
1011    }
1012}
1013
1014impl Future for OpenBi<'_> {
1015    type Output = Result<(SendStream, RecvStream), ConnectionError>;
1016    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
1017        let this = self.project();
1018        let (conn, id, is_0rtt) = ready!(poll_open(ctx, this.conn, this.notify, Dir::Bi))?;
1019
1020        Poll::Ready(Ok((
1021            SendStream::new(conn.clone(), id, is_0rtt),
1022            RecvStream::new(conn, id, is_0rtt),
1023        )))
1024    }
1025}
1026
1027fn poll_open<'a>(
1028    ctx: &mut Context<'_>,
1029    conn: &'a ConnectionRef,
1030    mut notify: Pin<&mut Notified<'a>>,
1031    dir: Dir,
1032) -> Poll<Result<(ConnectionRef, StreamId, bool), ConnectionError>> {
1033    let mut state = conn.lock_without_waking("poll_open");
1034    if let Some(ref e) = state.error {
1035        return Poll::Ready(Err(e.clone()));
1036    } else if let Some(id) = state.inner.streams().open(dir) {
1037        let is_0rtt = state.inner.side().is_client() && state.inner.is_handshaking();
1038        drop(state); // Release the lock so clone can take it
1039        return Poll::Ready(Ok((conn.clone(), id, is_0rtt)));
1040    }
1041    loop {
1042        match notify.as_mut().poll(ctx) {
1043            // `state` lock ensures we didn't race with readiness
1044            Poll::Pending => return Poll::Pending,
1045            // Spurious wakeup, get a new future
1046            Poll::Ready(()) => {
1047                notify.set(conn.shared.stream_budget_available[dir as usize].notified())
1048            }
1049        }
1050    }
1051}
1052
1053pin_project! {
1054    /// Future produced by [`Connection::accept_uni`]
1055    pub struct AcceptUni<'a> {
1056        conn: &'a ConnectionRef,
1057        #[pin]
1058        notify: Notified<'a>,
1059    }
1060}
1061
1062impl Future for AcceptUni<'_> {
1063    type Output = Result<RecvStream, ConnectionError>;
1064
1065    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
1066        let this = self.project();
1067        let (conn, id, is_0rtt) = ready!(poll_accept(ctx, this.conn, this.notify, Dir::Uni))?;
1068        Poll::Ready(Ok(RecvStream::new(conn, id, is_0rtt)))
1069    }
1070}
1071
1072pin_project! {
1073    /// Future produced by [`Connection::accept_bi`]
1074    pub struct AcceptBi<'a> {
1075        conn: &'a ConnectionRef,
1076        #[pin]
1077        notify: Notified<'a>,
1078    }
1079}
1080
1081impl Future for AcceptBi<'_> {
1082    type Output = Result<(SendStream, RecvStream), ConnectionError>;
1083
1084    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
1085        let this = self.project();
1086        let (conn, id, is_0rtt) = ready!(poll_accept(ctx, this.conn, this.notify, Dir::Bi))?;
1087        Poll::Ready(Ok((
1088            SendStream::new(conn.clone(), id, is_0rtt),
1089            RecvStream::new(conn, id, is_0rtt),
1090        )))
1091    }
1092}
1093
1094fn poll_accept<'a>(
1095    ctx: &mut Context<'_>,
1096    conn: &'a ConnectionRef,
1097    mut notify: Pin<&mut Notified<'a>>,
1098    dir: Dir,
1099) -> Poll<Result<(ConnectionRef, StreamId, bool), ConnectionError>> {
1100    let mut state = conn.lock_and_wake("poll_accept");
1101    // Check for incoming streams before checking `state.error` so that already-received streams,
1102    // which are necessarily finite, can be drained from a closed connection.
1103    if let Some(id) = state.inner.streams().accept(dir) {
1104        let is_0rtt = state.inner.is_handshaking();
1105        drop(state); // Release the lock (wake on drop) so clone can take it
1106        return Poll::Ready(Ok((conn.clone(), id, is_0rtt)));
1107    } else if let Some(ref e) = state.error {
1108        return Poll::Ready(Err(e.clone()));
1109    }
1110    loop {
1111        match notify.as_mut().poll(ctx) {
1112            // `state` lock ensures we didn't race with readiness
1113            Poll::Pending => return Poll::Pending,
1114            // Spurious wakeup, get a new future
1115            Poll::Ready(()) => notify.set(conn.shared.stream_incoming[dir as usize].notified()),
1116        }
1117    }
1118}
1119
1120pin_project! {
1121    /// Future produced by [`Connection::read_datagram`]
1122    pub struct ReadDatagram<'a> {
1123        conn: &'a ConnectionRef,
1124        #[pin]
1125        notify: Notified<'a>,
1126    }
1127}
1128
1129impl Future for ReadDatagram<'_> {
1130    type Output = Result<Bytes, ConnectionError>;
1131    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
1132        let mut this = self.project();
1133        let mut state = this.conn.lock_without_waking("ReadDatagram::poll");
1134        // Check for buffered datagrams before checking `state.error` so that already-received
1135        // datagrams, which are necessarily finite, can be drained from a closed connection.
1136        if let Some(x) = state.inner.datagrams().recv() {
1137            return Poll::Ready(Ok(x));
1138        } else if let Some(ref e) = state.error {
1139            return Poll::Ready(Err(e.clone()));
1140        }
1141        loop {
1142            match this.notify.as_mut().poll(ctx) {
1143                // `state` lock ensures we didn't race with readiness
1144                Poll::Pending => return Poll::Pending,
1145                // Spurious wakeup, get a new future
1146                Poll::Ready(()) => this
1147                    .notify
1148                    .set(this.conn.shared.datagram_received.notified()),
1149            }
1150        }
1151    }
1152}
1153
1154pin_project! {
1155    /// Future produced by [`Connection::send_datagram_wait`]
1156    pub struct SendDatagram<'a> {
1157        conn: &'a ConnectionRef,
1158        data: Option<Bytes>,
1159        #[pin]
1160        notify: Notified<'a>,
1161    }
1162}
1163
1164impl Future for SendDatagram<'_> {
1165    type Output = Result<(), SendDatagramError>;
1166    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
1167        let mut this = self.project();
1168        let mut state = this.conn.lock_and_wake("SendDatagram::poll");
1169        if let Some(ref e) = state.error {
1170            return Poll::Ready(Err(SendDatagramError::ConnectionLost(e.clone())));
1171        }
1172        use proto::SendDatagramError::*;
1173        match state
1174            .inner
1175            .datagrams()
1176            .send(this.data.take().unwrap(), false)
1177        {
1178            Ok(()) => Poll::Ready(Ok(())),
1179            Err(e) => Poll::Ready(Err(match e {
1180                Blocked(data) => {
1181                    this.data.replace(data);
1182                    loop {
1183                        match this.notify.as_mut().poll(ctx) {
1184                            Poll::Pending => return Poll::Pending,
1185                            // Spurious wakeup, get a new future
1186                            Poll::Ready(()) => this
1187                                .notify
1188                                .set(this.conn.shared.datagrams_unblocked.notified()),
1189                        }
1190                    }
1191                }
1192                UnsupportedByPeer => SendDatagramError::UnsupportedByPeer,
1193                Disabled => SendDatagramError::Disabled,
1194                TooLarge => SendDatagramError::TooLarge,
1195            })),
1196        }
1197    }
1198}
1199
1200/// State of a [`Connection`] at the moment it was closed.
1201///
1202/// Returned by the [`OnClosed`] future from [`Connection::on_closed`].
1203#[derive(Debug, Clone)]
1204#[non_exhaustive]
1205pub struct Closed {
1206    /// The reason the connection was closed.
1207    pub reason: ConnectionError,
1208    /// Aggregate connection statistics at the moment of close.
1209    pub stats: ConnectionStats,
1210    /// Per-path statistics for every path the connection knew about at close time.
1211    ///
1212    /// This includes paths that haven't been discarded at close time, plus any
1213    /// already-discarded paths whose final stats had been retained because a [`Path`]
1214    /// or [`WeakPathHandle`] handle was kept alive.
1215    ///
1216    /// [`WeakPathHandle`]: crate::WeakPathHandle
1217    pub path_stats: Vec<(PathId, PathStats)>,
1218}
1219
1220impl Closed {
1221    /// Snapshot the current connection state into a [`Closed`] value.
1222    ///
1223    /// Must only be called once `state.error` has been set.
1224    pub(crate) fn new(state: &mut State, reason: ConnectionError) -> Self {
1225        let stats = state.inner.stats();
1226
1227        let non_discarded_paths = state.inner.paths();
1228        let mut path_stats =
1229            Vec::with_capacity(non_discarded_paths.len() + state.final_path_stats.len());
1230
1231        // Non-discarded paths are tracked by proto::Connection.
1232        path_stats.extend(
1233            non_discarded_paths
1234                .into_iter()
1235                .filter_map(|id| state.inner.path_stats(id).map(|stats| (id, stats))),
1236        );
1237        // Already-discarded paths whose final stats we kept around.
1238        path_stats.extend(
1239            state
1240                .final_path_stats
1241                .iter()
1242                .map(|(id, stats)| (*id, *stats)),
1243        );
1244        Self {
1245            reason,
1246            stats,
1247            path_stats,
1248        }
1249    }
1250}
1251
1252/// Future returned by [`Connection::on_closed`]
1253///
1254/// Resolves to [`Closed`].
1255pub struct OnClosed {
1256    rx: oneshot::Receiver<Closed>,
1257    conn: WeakConnectionHandle,
1258}
1259
1260impl Drop for OnClosed {
1261    fn drop(&mut self) {
1262        if self.rx.is_terminated() {
1263            return;
1264        };
1265        if let Some(conn) = self.conn.upgrade() {
1266            self.rx.close();
1267            conn.0
1268                .lock_without_waking("OnClosed::drop")
1269                .on_closed
1270                .retain(|tx| !tx.is_closed());
1271        }
1272    }
1273}
1274
1275impl Future for OnClosed {
1276    type Output = Closed;
1277
1278    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1279        let this = self.get_mut();
1280        // The `expect` is safe because `State::drop` ensures that all senders are triggered
1281        // before being dropped.
1282        Pin::new(&mut this.rx)
1283            .poll(cx)
1284            .map(|x| x.expect("on_close sender is never dropped before sending"))
1285    }
1286}
1287
1288#[derive(Debug)]
1289#[allow(clippy::redundant_allocation)]
1290pub(crate) struct ConnectionRef(Arc<Arc<ConnectionInner>>);
1291
1292impl ConnectionRef {
1293    #[allow(clippy::redundant_allocation)]
1294    fn from_arc(inner: Arc<Arc<ConnectionInner>>) -> Self {
1295        inner.shared.ref_count.fetch_add(1, Ordering::Relaxed);
1296        Self(inner)
1297    }
1298
1299    pub(crate) fn stable_id(&self) -> usize {
1300        &*self.0 as *const _ as usize
1301    }
1302
1303    pub(crate) fn weak_handle(&self) -> WeakConnectionHandle {
1304        WeakConnectionHandle(Arc::downgrade(&self.0))
1305    }
1306}
1307
1308impl Clone for ConnectionRef {
1309    fn clone(&self) -> Self {
1310        Self::from_arc(Arc::clone(&self.0))
1311    }
1312}
1313
1314impl Drop for ConnectionRef {
1315    fn drop(&mut self) {
1316        if self.shared.ref_count.fetch_sub(1, Ordering::Relaxed) > 1 {
1317            return;
1318        }
1319
1320        let conn = &mut *self.lock_without_waking("drop");
1321
1322        if !conn.inner.is_closed() {
1323            // If the driver is alive, it's just it and us, so we'd better shut it down. If it's
1324            // not, we can't do any harm. If there were any streams being opened, then either
1325            // the connection will be closed for an unrelated reason or a fresh reference will
1326            // be constructed for the newly opened stream.
1327            conn.implicit_close(&self.shared);
1328        }
1329    }
1330}
1331
1332impl std::ops::Deref for ConnectionRef {
1333    type Target = ConnectionInner;
1334    fn deref(&self) -> &Self::Target {
1335        &self.0
1336    }
1337}
1338
1339#[derive(Debug)]
1340pub(crate) struct ConnectionInner {
1341    /// Kept private intentionally, use [`Self::lock_and_wake`].
1342    state: Mutex<State>,
1343    pub(crate) shared: Shared,
1344}
1345
1346impl ConnectionInner {
1347    /// Lock the state and return a guard that wakes the connection driver on drop.
1348    ///
1349    /// Use this for operations that may queue frames. The wake ensures the driver sends queued
1350    /// frames. If that's not needed, use [`Self::lock_without_waking`].
1351    pub(crate) fn lock_and_wake(&self, purpose: &'static str) -> WakeGuard<'_> {
1352        WakeGuard {
1353            guard: self.state.lock(purpose),
1354            wake: true,
1355        }
1356    }
1357
1358    /// Lock the state and return a guard that unlocks once dropped.
1359    ///
1360    /// Use this for operations that don't require any action from the connection driver.
1361    /// Otherwise, use [`Self::lock_and_wake`] instead.
1362    pub(crate) fn lock_without_waking(&self, purpose: &'static str) -> WakeGuard<'_> {
1363        WakeGuard {
1364            guard: self.state.lock(purpose),
1365            wake: false,
1366        }
1367    }
1368}
1369
1370/// [`MutexGuard`] wrapper that calls [`State::wake`] on drop.
1371#[derive(derive_more::Deref, derive_more::DerefMut)]
1372pub(crate) struct WakeGuard<'a> {
1373    #[deref]
1374    #[deref_mut]
1375    guard: MutexGuard<'a, State>,
1376    wake: bool,
1377}
1378
1379impl WakeGuard<'_> {
1380    pub(crate) fn skip_waking(&mut self) {
1381        self.wake = false;
1382    }
1383}
1384
1385impl Drop for WakeGuard<'_> {
1386    fn drop(&mut self) {
1387        if self.wake {
1388            self.guard.wake();
1389        }
1390    }
1391}
1392
1393/// A handle to some connection internals, use with care.
1394///
1395/// This contains a weak reference to the connection so will not itself keep the connection
1396/// alive.
1397#[derive(Debug, Clone)]
1398pub struct WeakConnectionHandle(Weak<Arc<ConnectionInner>>);
1399
1400impl WeakConnectionHandle {
1401    /// Returns `true` if the [`Connection`] associated with this handle is still alive.
1402    pub fn is_alive(&self) -> bool {
1403        self.0.upgrade().is_some()
1404    }
1405
1406    /// Upgrade the handle to a full `Connection`
1407    pub fn upgrade(&self) -> Option<Connection> {
1408        self.upgrade_to_ref().map(Connection)
1409    }
1410
1411    pub(crate) fn upgrade_to_ref(&self) -> Option<ConnectionRef> {
1412        self.0.upgrade().map(ConnectionRef::from_arc)
1413    }
1414
1415    /// Returns `true` if the two [`WeakConnectionHandle`] point at the same connection.
1416    pub fn is_same_connection(&self, other: &Self) -> bool {
1417        self.0.ptr_eq(&other.0)
1418    }
1419}
1420
1421#[derive(Debug, Default)]
1422pub(crate) struct Shared {
1423    handshake_confirmed: Notify,
1424    /// Notified when new streams may be locally initiated due to an increase in stream ID flow
1425    /// control budget
1426    stream_budget_available: [Notify; 2],
1427    /// Notified when the peer has initiated a new stream
1428    stream_incoming: [Notify; 2],
1429    datagram_received: Notify,
1430    datagrams_unblocked: Notify,
1431    closed: Notify,
1432    connected: Notify,
1433    /// Number of live handles that can be used to initiate or handle I/O; excludes the driver
1434    ref_count: AtomicUsize,
1435}
1436
1437pub(crate) struct State {
1438    pub(crate) inner: proto::Connection,
1439    driver: Option<Waker>,
1440    handle: ConnectionHandle,
1441    on_handshake_data: Option<oneshot::Sender<()>>,
1442    on_connected: Option<oneshot::Sender<bool>>,
1443    connected: bool,
1444    handshake_confirmed: bool,
1445    timer: Option<Pin<Box<dyn AsyncTimer>>>,
1446    timer_deadline: Option<Instant>,
1447    conn_events: mpsc::UnboundedReceiver<ConnectionEvent>,
1448    endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>,
1449    pub(crate) blocked_writers: FxHashMap<StreamId, Waker>,
1450    pub(crate) blocked_readers: FxHashMap<StreamId, Waker>,
1451    pub(crate) stopped: FxHashMap<StreamId, Arc<Notify>>,
1452    /// Always set to Some before the connection becomes drained
1453    pub(crate) error: Option<ConnectionError>,
1454    /// Tracks paths being opened
1455    open_path: FxHashMap<PathId, watch::Sender<Result<(), PathError>>>,
1456    /// Tracks reference counts for paths.
1457    ///
1458    /// I.e. how many [`Path`] and [`WeakPathHandle`] structs are alive for a path.
1459    /// Each entry's [`PathRefOwner`] holds an [`AtomicUsize`] so that cloning or
1460    /// dropping a [`PathRef`] (held by [`Path`] or [`WeakPathHandle`]) does not need
1461    /// to lock this state.
1462    ///
1463    /// [`WeakPathHandle`]: crate::path::WeakPathHandle
1464    pub(crate) path_refs: FxHashMap<PathId, PathRefOwner>,
1465    /// Final path stats for discarded paths.
1466    ///
1467    /// We only insert entries if the discarded path has a non-zero reference count in
1468    /// [`Self::path_refs`]. When the last reference to a path is dropped its entry is removed
1469    /// from both maps.
1470    pub(crate) final_path_stats: FxHashMap<PathId, PathStats>,
1471    pub(crate) path_events: tokio::sync::broadcast::Sender<PathEvent>,
1472    sender: Pin<Box<dyn UdpSender>>,
1473    pub(crate) runtime: Arc<dyn Runtime>,
1474    send_buffer: Vec<u8>,
1475    /// We buffer a transmit when the underlying I/O would block
1476    buffered_transmit: Option<proto::Transmit>,
1477    /// Our last external address reported by the peer. When multipath is enabled, this will be the
1478    /// last report across all paths.
1479    pub(crate) observed_external_addr: watch::Sender<Option<SocketAddr>>,
1480    pub(crate) nat_traversal_updates: tokio::sync::broadcast::Sender<n0_nat_traversal::Event>,
1481    on_closed: Vec<oneshot::Sender<Closed>>,
1482}
1483
1484impl State {
1485    #[allow(clippy::too_many_arguments)]
1486    fn new(
1487        inner: proto::Connection,
1488        handle: ConnectionHandle,
1489        endpoint_events: mpsc::UnboundedSender<(ConnectionHandle, EndpointEvent)>,
1490        conn_events: mpsc::UnboundedReceiver<ConnectionEvent>,
1491        on_handshake_data: oneshot::Sender<()>,
1492        on_connected: oneshot::Sender<bool>,
1493        sender: Pin<Box<dyn UdpSender>>,
1494        runtime: Arc<dyn Runtime>,
1495    ) -> Self {
1496        Self {
1497            inner,
1498            driver: None,
1499            handle,
1500            on_handshake_data: Some(on_handshake_data),
1501            on_connected: Some(on_connected),
1502            connected: false,
1503            handshake_confirmed: false,
1504            timer: None,
1505            timer_deadline: None,
1506            conn_events,
1507            endpoint_events,
1508            blocked_writers: FxHashMap::default(),
1509            blocked_readers: FxHashMap::default(),
1510            stopped: FxHashMap::default(),
1511            open_path: FxHashMap::default(),
1512            error: None,
1513            sender,
1514            runtime,
1515            send_buffer: Vec::new(),
1516            buffered_transmit: None,
1517            path_events: tokio::sync::broadcast::channel(32).0,
1518            observed_external_addr: watch::Sender::new(None),
1519            nat_traversal_updates: tokio::sync::broadcast::channel(32).0,
1520            on_closed: Vec::new(),
1521            final_path_stats: Default::default(),
1522            path_refs: Default::default(),
1523        }
1524    }
1525
1526    fn drive_transmit(&mut self, cx: &mut Context<'_>) -> io::Result<bool> {
1527        let now = self.runtime.now();
1528        let mut transmits = 0;
1529
1530        let max_datagrams = self
1531            .sender
1532            .max_transmit_segments()
1533            .min(MAX_TRANSMIT_SEGMENTS);
1534
1535        loop {
1536            // Retry the last transmit, or get a new one.
1537            let t = match self.buffered_transmit.take() {
1538                Some(t) => t,
1539                None => {
1540                    self.send_buffer.clear();
1541                    match self
1542                        .inner
1543                        .poll_transmit(now, max_datagrams, &mut self.send_buffer)
1544                    {
1545                        Some(t) => {
1546                            transmits += match t.segment_size {
1547                                None => 1,
1548                                Some(s) => t.size.div_ceil(s), // round up
1549                            };
1550                            t
1551                        }
1552                        None => break,
1553                    }
1554                }
1555            };
1556
1557            let len = t.size;
1558            match self
1559                .sender
1560                .as_mut()
1561                .poll_send(&udp_transmit(&t, &self.send_buffer[..len]), cx)
1562            {
1563                Poll::Pending => {
1564                    self.buffered_transmit = Some(t);
1565                    return Ok(false);
1566                }
1567                Poll::Ready(Err(e)) => return Err(e),
1568                Poll::Ready(Ok(())) => {}
1569            }
1570
1571            if transmits >= MAX_TRANSMIT_DATAGRAMS {
1572                // TODO: What isn't ideal here yet is that if we don't poll all
1573                // datagrams that could be sent we don't go into the `app_limited`
1574                // state and CWND continues to grow until we get here the next time.
1575                // See https://github.com/quinn-rs/quinn/issues/1126
1576                return Ok(true);
1577            }
1578        }
1579
1580        Ok(false)
1581    }
1582
1583    fn forward_endpoint_events(&mut self) {
1584        while let Some(event) = self.inner.poll_endpoint_events() {
1585            // If the endpoint driver is gone, noop.
1586            let _ = self.endpoint_events.send((self.handle, event));
1587        }
1588    }
1589
1590    /// If this returns `Err`, the endpoint is dead, so the driver should exit immediately.
1591    fn process_conn_events(
1592        &mut self,
1593        shared: &Shared,
1594        cx: &mut Context<'_>,
1595    ) -> Result<(), ConnectionError> {
1596        loop {
1597            match self.conn_events.poll_recv(cx) {
1598                Poll::Ready(Some(ConnectionEvent::Rebind(sender))) => {
1599                    self.sender = sender;
1600                    self.inner.handle_network_change(None, self.runtime.now());
1601                }
1602                Poll::Ready(Some(ConnectionEvent::LocalAddressChanged(hint))) => {
1603                    self.inner
1604                        .handle_network_change(hint.as_deref().map(|x| x as _), self.runtime.now());
1605                }
1606                Poll::Ready(Some(ConnectionEvent::Proto(event))) => {
1607                    self.inner.handle_event(event);
1608                }
1609                Poll::Ready(Some(ConnectionEvent::Close { reason, error_code })) => {
1610                    self.close(error_code, reason, shared);
1611                }
1612                Poll::Ready(None) => {
1613                    return Err(ConnectionError::TransportError(TransportError::new(
1614                        TransportErrorCode::INTERNAL_ERROR,
1615                        "endpoint driver future was dropped".to_string(),
1616                    )));
1617                }
1618                Poll::Pending => {
1619                    return Ok(());
1620                }
1621            }
1622        }
1623    }
1624
1625    fn forward_app_events(&mut self, shared: &Shared) {
1626        while let Some(event) = self.inner.poll() {
1627            use proto::Event::*;
1628            match event {
1629                HandshakeDataReady => {
1630                    if let Some(x) = self.on_handshake_data.take() {
1631                        let _ = x.send(());
1632                    }
1633                }
1634                Connected => {
1635                    self.connected = true;
1636                    shared.connected.notify_waiters();
1637                    if let Some(x) = self.on_connected.take() {
1638                        // We don't care if the on-connected future was dropped
1639                        let _ = x.send(self.inner.accepted_0rtt());
1640                    }
1641                    if self.inner.side().is_client() && !self.inner.accepted_0rtt() {
1642                        // Wake up rejected 0-RTT streams so they can fail immediately with
1643                        // `ZeroRttRejected` errors.
1644                        wake_all(&mut self.blocked_writers);
1645                        wake_all(&mut self.blocked_readers);
1646                        wake_all_notify(&mut self.stopped);
1647                    }
1648                }
1649                HandshakeConfirmed => {
1650                    self.handshake_confirmed = true;
1651                    shared.handshake_confirmed.notify_waiters();
1652                }
1653                ConnectionLost { reason } => {
1654                    self.terminate(reason, shared);
1655                }
1656                Stream(StreamEvent::Writable { id }) => wake_stream(id, &mut self.blocked_writers),
1657                Stream(StreamEvent::Opened { dir: Dir::Uni }) => {
1658                    shared.stream_incoming[Dir::Uni as usize].notify_waiters();
1659                }
1660                Stream(StreamEvent::Opened { dir: Dir::Bi }) => {
1661                    shared.stream_incoming[Dir::Bi as usize].notify_waiters();
1662                }
1663                DatagramReceived => {
1664                    shared.datagram_received.notify_waiters();
1665                }
1666                DatagramsUnblocked => {
1667                    shared.datagrams_unblocked.notify_waiters();
1668                }
1669                Stream(StreamEvent::Readable { id }) => wake_stream(id, &mut self.blocked_readers),
1670                Stream(StreamEvent::Available { dir }) => {
1671                    // Might mean any number of streams are ready, so we wake up everyone
1672                    shared.stream_budget_available[dir as usize].notify_waiters();
1673                }
1674                Stream(StreamEvent::Finished { id }) => wake_stream_notify(id, &mut self.stopped),
1675                Stream(StreamEvent::Stopped { id, .. }) => {
1676                    wake_stream_notify(id, &mut self.stopped);
1677                    wake_stream(id, &mut self.blocked_writers);
1678                }
1679                Path(ref evt @ PathEvent::ObservedAddr { addr: observed, .. }) => {
1680                    self.path_events.send(evt.clone()).ok();
1681                    self.observed_external_addr.send_if_modified(|addr| {
1682                        let old = addr.replace(observed);
1683                        old != *addr
1684                    });
1685                }
1686                Path(ref evt @ PathEvent::Established { id, .. }) => {
1687                    self.path_events.send(evt.clone()).ok();
1688                    if let Some(sender) = self.open_path.remove(&id) {
1689                        sender.send_modify(|value| *value = Ok(()));
1690                    }
1691                }
1692                Path(
1693                    ref evt @ PathEvent::Discarded {
1694                        id, ref path_stats, ..
1695                    },
1696                ) => {
1697                    if self.path_refs.contains_key(&id) {
1698                        self.final_path_stats.insert(id, *path_stats.clone());
1699                    }
1700                    self.path_events.send(evt.clone()).ok();
1701                }
1702                Path(ref evt @ PathEvent::Abandoned { id, .. }) => {
1703                    if let Some(sender) = self.open_path.remove(&id) {
1704                        // We don't care for the reason why this path was closed here, because
1705                        // semantically all close reasons for a path that
1706                        // has not yet been opened equals to `ValidationFailed`.
1707                        // With the noq API, there is no way to application-close a not-yet-opened
1708                        // path, so `ApplicationClosed` cannot occur. And
1709                        // all other variants will only occur for paths that
1710                        // have already been opened. The previous iteration
1711                        // of this code had another event `PathEvent::LocallyClosed` which
1712                        // contained a `PathError`, but that was only ever set to
1713                        // `ValidationFailed`.
1714                        let error = PathError::ValidationFailed;
1715                        sender.send_modify(|value| *value = Err(error));
1716                    }
1717                    // this will happen also for already opened paths
1718                    self.path_events.send(evt.clone()).ok();
1719                }
1720                Path(evt @ PathEvent::RemoteStatus { .. }) => {
1721                    self.path_events.send(evt).ok();
1722                }
1723                NatTraversal(update) => {
1724                    self.nat_traversal_updates.send(update).ok();
1725                }
1726                _ => {
1727                    // PathEvent is #[non_exhaustive].
1728                    // It's possible that noq is built against a newer noq-proto version.
1729                    // In that case, we need to ignore path events we can't handle yet.
1730                    // But for tests, we expect noq and noq-proto to be in sync, so we
1731                    // should panic in case we don't actually handle new cases.
1732                    #[cfg(test)]
1733                    panic!("Unhandled PathEvent variant: {event:?}");
1734                }
1735            }
1736        }
1737    }
1738
1739    fn drive_timer(&mut self, cx: &mut Context<'_>) -> bool {
1740        let Some(deadline) = self.inner.poll_timeout() else {
1741            self.timer_deadline = None;
1742            return false;
1743        };
1744
1745        // Use the clock rather than the async timer to detect expiry: Sleep::poll
1746        // respects Tokio's cooperative budget and can return Pending for elapsed
1747        // deadlines.
1748        let now = self.runtime.now();
1749        if now >= deadline {
1750            self.inner.handle_timeout(now);
1751            self.timer_deadline = None;
1752            return true;
1753        }
1754
1755        match &mut self.timer {
1756            // Avoid resetting the timer when the deadline is unchanged.
1757            Some(delay) if self.timer_deadline != Some(deadline) => {
1758                delay.as_mut().reset(deadline);
1759            }
1760            None => {
1761                self.timer = Some(self.runtime.new_timer(deadline));
1762            }
1763            _ => {}
1764        }
1765        self.timer_deadline = Some(deadline);
1766
1767        let delay = self
1768            .timer
1769            .as_mut()
1770            .expect("timer must exist in this state")
1771            .as_mut();
1772        if delay.poll(cx).is_pending() {
1773            return false;
1774        }
1775
1776        // The deadline elapsed in the window between the clock check and poll.
1777        self.inner.handle_timeout(self.runtime.now());
1778        self.timer_deadline = None;
1779        true
1780    }
1781
1782    /// Wake up a blocked `Driver` task to process I/O
1783    pub(crate) fn wake(&mut self) {
1784        if let Some(x) = self.driver.take() {
1785            x.wake();
1786        }
1787    }
1788
1789    /// Used to wake up all blocked futures when the connection becomes closed for any reason
1790    fn terminate(&mut self, reason: ConnectionError, shared: &Shared) {
1791        self.error = Some(reason.clone());
1792        if let Some(x) = self.on_handshake_data.take() {
1793            let _ = x.send(());
1794        }
1795        wake_all(&mut self.blocked_writers);
1796        wake_all(&mut self.blocked_readers);
1797        shared.stream_budget_available[Dir::Uni as usize].notify_waiters();
1798        shared.stream_budget_available[Dir::Bi as usize].notify_waiters();
1799        shared.stream_incoming[Dir::Uni as usize].notify_waiters();
1800        shared.stream_incoming[Dir::Bi as usize].notify_waiters();
1801        shared.datagram_received.notify_waiters();
1802        shared.datagrams_unblocked.notify_waiters();
1803        if let Some(x) = self.on_connected.take() {
1804            let _ = x.send(false);
1805        }
1806        shared.handshake_confirmed.notify_waiters();
1807        wake_all_notify(&mut self.stopped);
1808        shared.closed.notify_waiters();
1809        // Send to the registered on_closed futures.
1810        if !self.on_closed.is_empty() {
1811            let closed = Closed::new(self, reason);
1812            for tx in self.on_closed.drain(..) {
1813                tx.send(closed.clone()).ok();
1814            }
1815        }
1816        shared.connected.notify_waiters();
1817    }
1818
1819    fn close(&mut self, error_code: VarInt, reason: Bytes, shared: &Shared) {
1820        self.inner.close(self.runtime.now(), error_code, reason);
1821        self.terminate(ConnectionError::LocallyClosed, shared);
1822        self.wake();
1823    }
1824
1825    /// Close for a reason other than the application's explicit request
1826    pub(crate) fn implicit_close(&mut self, shared: &Shared) {
1827        self.close(0u32.into(), Bytes::new(), shared);
1828    }
1829
1830    pub(crate) fn check_0rtt(&self) -> Result<(), ()> {
1831        if self.inner.is_handshaking()
1832            || self.inner.accepted_0rtt()
1833            || self.inner.side().is_server()
1834        {
1835            Ok(())
1836        } else {
1837            Err(())
1838        }
1839    }
1840
1841    /// Returns [`PathStats`] for a path, if available.
1842    ///
1843    /// This gets the stats from [`proto::Connection`]. If that returns `None`
1844    /// it gets them from `Self::final_path_stats` instead.
1845    pub(crate) fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> {
1846        self.inner
1847            .path_stats(path_id)
1848            .or_else(|| self.final_path_stats.get(&path_id).copied())
1849    }
1850
1851    /// Acquire a new [`PathRef`] for a path id, bumping its reference counter by 1.
1852    ///
1853    /// The returned [`PathRef`] is intended to be stored on a [`Path`] or [`WeakPathHandle`].
1854    /// Its reference count is automatically increased when cloned. When its owner is dropped,
1855    /// [`PathRef::on_drop`] must be called to decrement the refcount.
1856    ///
1857    /// [`WeakPathHandle`]: crate::path::WeakPathHandle
1858    pub(crate) fn acquire_path_ref(&mut self, path_id: PathId) -> PathRef {
1859        self.path_refs.entry(path_id).or_default().acquire(path_id)
1860    }
1861}
1862
1863impl Drop for State {
1864    fn drop(&mut self) {
1865        if !self.inner.is_drained() {
1866            // Ensure the endpoint can tidy up
1867            let _ = self
1868                .endpoint_events
1869                .send((self.handle, EndpointEvent::drained()));
1870        }
1871
1872        if !self.on_closed.is_empty()
1873            && let Some(reason) = self.error.clone()
1874        {
1875            // Ensure that all on_closed oneshot senders are triggered before dropping.
1876            let closed = Closed::new(self, reason);
1877            for tx in self.on_closed.drain(..) {
1878                tx.send(closed.clone()).ok();
1879            }
1880        }
1881    }
1882}
1883
1884impl fmt::Debug for State {
1885    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1886        f.debug_struct("State").field("inner", &self.inner).finish()
1887    }
1888}
1889
1890fn wake_stream(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Waker>) {
1891    if let Some(waker) = wakers.remove(&stream_id) {
1892        waker.wake();
1893    }
1894}
1895
1896fn wake_all(wakers: &mut FxHashMap<StreamId, Waker>) {
1897    wakers.drain().for_each(|(_, waker)| waker.wake())
1898}
1899
1900fn wake_stream_notify(stream_id: StreamId, wakers: &mut FxHashMap<StreamId, Arc<Notify>>) {
1901    if let Some(notify) = wakers.remove(&stream_id) {
1902        notify.notify_waiters()
1903    }
1904}
1905
1906fn wake_all_notify(wakers: &mut FxHashMap<StreamId, Arc<Notify>>) {
1907    wakers
1908        .drain()
1909        .for_each(|(_, notify)| notify.notify_waiters())
1910}
1911
1912/// Errors that can arise when sending a datagram
1913#[derive(Debug, Error, Clone, Eq, PartialEq)]
1914pub enum SendDatagramError {
1915    /// The peer does not support receiving datagram frames
1916    #[error("datagrams not supported by peer")]
1917    UnsupportedByPeer,
1918    /// Datagram support is disabled locally
1919    #[error("datagram support disabled")]
1920    Disabled,
1921    /// The datagram is larger than the connection can currently accommodate
1922    ///
1923    /// Indicates that the path MTU minus overhead or the limit advertised by the peer has been
1924    /// exceeded.
1925    #[error("datagram too large")]
1926    TooLarge,
1927    /// The connection was lost
1928    #[error("connection lost")]
1929    ConnectionLost(#[from] ConnectionError),
1930}
1931
1932/// The maximum amount of datagrams which will be produced in a single `drive_transmit` call
1933///
1934/// This limits the amount of CPU resources consumed by datagram generation,
1935/// and allows other tasks (like receiving ACKs) to run in between.
1936const MAX_TRANSMIT_DATAGRAMS: usize = 20;
1937
1938/// The maximum amount of datagrams that are sent in a single transmit
1939///
1940/// This can be lower than the maximum platform capabilities, to avoid excessive
1941/// memory allocations when calling `poll_transmit()`. Benchmarks have shown
1942/// that numbers around 10 are a good compromise.
1943const MAX_TRANSMIT_SEGMENTS: NonZeroUsize = NonZeroUsize::new(10).expect("known");