Skip to content

Commit 37ad090

Browse files
feat: provide access to connection Waker to datagram Endpoint (#1598)
* Remove Default for datagram (Pre)ConnectionInfo structs It doesn't make much sense for there to be default values for these, and as more fields are added a Default may become awkward or impossible. This removes the ability to construct these outside of s2n-quic, but doing so is awkward if there's no reasonable default value for some of the fields. (The next commit adds such a value for ConnectionInfo). * Add Waker to datagram ConnectionInfo This waker allows datagram receiver/senders to wake up the connection, which will re-poll the connection for interest in sending. When implementing a custom datagram Receiver which wants to schedule a reply datagram, this Waker or something like it is necessary to indirect the wakeup of the connection and subsequent call to the Sender's on_transmit. This is a waker and not a connection handle for two reasons: * The Waker does not directly extend the lifetime of the connection, which avoids keeping the connection data indefinitely alive for cases where the Waker is stored within the Sender or Receiver. * s2n-quic calling datagram Endpoint::new_connection doesn't have easy access to an application handle to the connection. Note that applications still must retain the Connection or a Handle to it: when the last application handle closes, the connection is also closed, even if there are Wakers for that connection still around. In practice this seems useful as it allows bounding the number of active connections with an Endpoint and the extra waste of connection handles is unlikely to be significant.
1 parent 406fc82 commit 37ad090

File tree

3 files changed

+24
-21
lines changed

3 files changed

+24
-21
lines changed

quic/s2n-quic-core/src/datagram/default.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -554,12 +554,13 @@ mod tests {
554554
use super::*;
555555
use crate::datagram::WriteError;
556556
use core::task::{Context, Poll};
557-
use futures_test::task::new_count_waker;
557+
use futures_test::task::{new_count_waker, noop_waker};
558558

559559
#[test]
560560
fn send_datagram_forced() {
561561
let conn_info = ConnectionInfo {
562562
max_datagram_payload: 100,
563+
waker: noop_waker(),
563564
};
564565
// Create a default sender queue that only holds two elements
565566
let mut default_sender = Sender::builder()
@@ -598,6 +599,7 @@ mod tests {
598599
fn send_datagram() {
599600
let conn_info = ConnectionInfo {
600601
max_datagram_payload: 100,
602+
waker: noop_waker(),
601603
};
602604
// Create a default sender queue that only holds two elements
603605
let mut default_sender = Sender::builder()
@@ -636,7 +638,7 @@ mod tests {
636638

637639
#[test]
638640
fn poll_send_datagram() {
639-
let conn_info = ConnectionInfo::new(100);
641+
let conn_info = ConnectionInfo::new(100, noop_waker());
640642
let mut default_sender = Sender::builder()
641643
.with_capacity(2)
642644
.with_connection_info(&conn_info)
@@ -708,6 +710,7 @@ mod tests {
708710
fn retain_datagrams() {
709711
let conn_info = ConnectionInfo {
710712
max_datagram_payload: 100,
713+
waker: noop_waker(),
711714
};
712715
let mut default_sender = Sender::builder()
713716
.with_capacity(3)
@@ -752,7 +755,7 @@ mod tests {
752755
// Check that our default on_transmit function doesn't continue to pop datagrams
753756
// off the send queue if the remaining packet space is too small to send datagrams.
754757
fn has_written_test() {
755-
let conn_info = ConnectionInfo::new(100);
758+
let conn_info = ConnectionInfo::new(100, noop_waker());
756759
let mut default_sender = Sender::builder()
757760
.with_connection_info(&conn_info)
758761
.build()

quic/s2n-quic-core/src/datagram/traits.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use core::task::Waker;
5+
46
use crate::connection;
57

68
/// The datagram endpoint trait provides a way to implement custom unreliable datagram
@@ -17,49 +19,46 @@ pub trait Endpoint: 'static + Send {
1719
fn max_datagram_frame_size(&self, info: &PreConnectionInfo) -> u64;
1820
}
1921

20-
/// ConnectionInfo contains the peer's limit on the size of datagrams
21-
/// they accept
22-
///
23-
/// Sending a datagram larger than this will result in an error
22+
/// Information about the accepted connection for which the Sender/Receiver are being created.
2423
#[non_exhaustive]
2524
#[derive(Debug)]
2625
pub struct ConnectionInfo {
26+
/// The peer's limit on the size of datagrams they will accept. Datagrams larger than this will
27+
/// result in an error.
2728
pub max_datagram_payload: u64,
29+
30+
/// The `waker` associated with this connection. When woken, the connection will check the
31+
/// interest in sending ([`Sender::has_transmission_interest`]), and send packets if necessary.
32+
///
33+
/// This is useful for applications that wish to enqueue packets with `Sender` without calling
34+
/// `datagram_mut`, perhaps because they don't have an available handle to the connection when
35+
/// enqueuing packets, or wish to avoid incurring the lock/unlock required by `datagram_mut`.
36+
pub waker: Waker,
2837
}
2938

3039
impl ConnectionInfo {
3140
#[doc(hidden)]
32-
pub fn new(max_datagram_payload: u64) -> Self {
41+
pub fn new(max_datagram_payload: u64, waker: Waker) -> Self {
3342
ConnectionInfo {
3443
max_datagram_payload,
44+
waker,
3545
}
3646
}
3747
}
3848

39-
impl Default for ConnectionInfo {
40-
fn default() -> Self {
41-
ConnectionInfo::new(0)
42-
}
43-
}
44-
4549
/// PreConnectionInfo will contain information needed to determine whether
4650
/// or not a provider will accept datagrams.
4751
#[non_exhaustive]
4852
pub struct PreConnectionInfo(());
4953

5054
impl PreConnectionInfo {
5155
#[doc(hidden)]
56+
#[allow(clippy::new_without_default)]
5257
pub fn new() -> Self {
5358
PreConnectionInfo(())
5459
}
5560
}
5661

57-
impl Default for PreConnectionInfo {
58-
fn default() -> Self {
59-
Self::new()
60-
}
61-
}
62-
6362
/// ReceiveContext contains information about the connection.
6463
#[non_exhaustive]
6564
#[derive(Debug)]

quic/s2n-quic-transport/src/space/session_context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,8 @@ impl<'a, Config: endpoint::Config, Pub: event::ConnectionPublisher>
399399
self.limits.max_keep_alive_period(),
400400
);
401401

402-
let conn_info = ConnectionInfo::new(datagram_limits.max_datagram_payload);
402+
let conn_info =
403+
ConnectionInfo::new(datagram_limits.max_datagram_payload, self.waker.clone());
403404
let (datagram_sender, datagram_receiver) = self.datagram.create_connection(&conn_info);
404405
let datagram_manager = datagram::Manager::new(
405406
datagram_sender,

0 commit comments

Comments
 (0)