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