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");