s2n_quic_platform/io/tokio/
builder.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use super::*;
5
6#[derive(Debug, Default)]
7pub struct Builder {
8    pub(super) handle: Option<Handle>,
9    pub(super) rx_socket: Option<socket2::Socket>,
10    pub(super) tx_socket: Option<socket2::Socket>,
11    pub(super) recv_addr: Option<std::net::SocketAddr>,
12    pub(super) send_addr: Option<std::net::SocketAddr>,
13    pub(super) socket_recv_buffer_size: Option<usize>,
14    pub(super) socket_send_buffer_size: Option<usize>,
15    pub(super) queue_recv_buffer_size: Option<u32>,
16    pub(super) queue_send_buffer_size: Option<u32>,
17    pub(super) mtu_config_builder: mtu::Builder,
18    pub(super) max_segments: gso::MaxSegments,
19    pub(super) gro_enabled: Option<bool>,
20    pub(super) reuse_address: bool,
21    pub(super) reuse_port: bool,
22    pub(super) only_v6: bool,
23}
24
25impl Builder {
26    #[must_use]
27    pub fn with_handle(mut self, handle: Handle) -> Self {
28        self.handle = Some(handle);
29        self
30    }
31
32    /// Sets the local address for the runtime to listen on. If no send address
33    /// or tx socket is specified, this address will also be used for transmitting from.
34    ///
35    /// NOTE: this method is mutually exclusive with `with_rx_socket`
36    pub fn with_receive_address(mut self, addr: std::net::SocketAddr) -> io::Result<Self> {
37        debug_assert!(self.rx_socket.is_none(), "rx socket has already been set");
38        self.recv_addr = Some(addr);
39        Ok(self)
40    }
41
42    /// Sets the local address for the runtime to transmit from. If no send address
43    /// or tx socket is specified, the receive_address will be used for transmitting.
44    ///
45    /// NOTE: this method is mutually exclusive with `with_tx_socket`
46    pub fn with_send_address(mut self, addr: std::net::SocketAddr) -> io::Result<Self> {
47        debug_assert!(self.tx_socket.is_none(), "tx socket has already been set");
48        self.send_addr = Some(addr);
49        Ok(self)
50    }
51
52    /// Sets the socket used for receiving for the runtime. If no tx_socket or send address is
53    /// specified, this socket will be used for transmitting.
54    ///
55    /// NOTE: this method is mutually exclusive with `with_receive_address`
56    pub fn with_rx_socket(mut self, socket: std::net::UdpSocket) -> io::Result<Self> {
57        debug_assert!(
58            self.recv_addr.is_none(),
59            "recv address has already been set"
60        );
61        self.rx_socket = Some(socket.into());
62        Ok(self)
63    }
64
65    /// Sets the socket used for transmitting on for the runtime. If no tx_socket or send address is
66    /// specified, the rx_socket will be used for transmitting.
67    ///
68    /// NOTE: this method is mutually exclusive with `with_send_address`
69    pub fn with_tx_socket(mut self, socket: std::net::UdpSocket) -> io::Result<Self> {
70        debug_assert!(
71            self.send_addr.is_none(),
72            "send address has already been set"
73        );
74        self.tx_socket = Some(socket.into());
75        Ok(self)
76    }
77
78    /// Sets the size of the operating system’s send buffer associated with the tx socket
79    pub fn with_send_buffer_size(mut self, send_buffer_size: usize) -> io::Result<Self> {
80        self.socket_send_buffer_size = Some(send_buffer_size);
81        Ok(self)
82    }
83
84    /// Sets the size of the operating system’s receive buffer associated with the rx socket
85    pub fn with_recv_buffer_size(mut self, recv_buffer_size: usize) -> io::Result<Self> {
86        self.socket_recv_buffer_size = Some(recv_buffer_size);
87        Ok(self)
88    }
89
90    /// Sets the size of the send buffer associated with the transmit side (internal to s2n-quic)
91    pub fn with_internal_send_buffer_size(mut self, send_buffer_size: usize) -> io::Result<Self> {
92        self.queue_send_buffer_size = Some(
93            send_buffer_size
94                .try_into()
95                .map_err(|err| io::Error::new(ErrorKind::InvalidInput, format!("{err}")))?,
96        );
97        Ok(self)
98    }
99
100    /// Sets the size of the send buffer associated with the receive side (internal to s2n-quic)
101    pub fn with_internal_recv_buffer_size(mut self, recv_buffer_size: usize) -> io::Result<Self> {
102        self.queue_recv_buffer_size = Some(
103            recv_buffer_size
104                .try_into()
105                .map_err(|err| io::Error::new(ErrorKind::InvalidInput, format!("{err}")))?,
106        );
107        Ok(self)
108    }
109
110    /// Sets the largest maximum transmission unit (MTU) that can be sent on a path (default: 1500)
111    ///
112    /// MTU is the size of the largest IP packet that can be transmitted on a path. This includes the
113    /// size of the IP header, the size of the UDP header, and the size of the UDP payload containing
114    /// the QUIC packet(s).
115    ///
116    /// Most networks can support the Ethernet II framing MTU of 1500 bytes. If your network supports
117    /// Ethernet jumbo frames, you can set `max_mtu` to a higher value (~9000). This will enable
118    /// s2n-quic to send probe packets at larger sizes to validate the MTU the network can support, giving a
119    /// significant throughput improvement if a large MTU is confirmed.
120    ///
121    /// Note: `max_mtu` must be >= `initial_mtu` and `base_mtu`
122    pub fn with_max_mtu(mut self, max_mtu: u16) -> io::Result<Self> {
123        self.mtu_config_builder = self
124            .mtu_config_builder
125            .with_max_mtu(max_mtu)
126            .map_err(|err| io::Error::new(ErrorKind::InvalidInput, format!("{err}")))?;
127        Ok(self)
128    }
129
130    /// Sets the maximum transmission unit (MTU) to use when initiating a connection (default: 1228)
131    ///
132    /// MTU is the size of the largest IP packet that can be transmitted on a path. This includes the
133    /// size of the IP header, the size of the UDP header, and the size of the UDP payload containing
134    /// the QUIC packet(s).
135    ///
136    /// By default, s2n-quic will complete the QUIC handshake using packets limited to the `base_mtu`
137    /// (default: 1228). Following the handshake, s2n-quic will send probe packets at larger sizes
138    /// to validate the MTU the network can support, up to the `max_mtu` (default: 1500).
139    ///
140    /// If you have high confidence your network can support an MTU larger than the default
141    /// `initial_mtu`, you can set this to a higher value and immediately start using a larger MTU
142    /// before the handshake completes. Any packet loss during the handshake suspected of being
143    /// caused by this `initial_mtu` setting will cause the MTU to drop back to the `base_mtu` to
144    /// allow the handshake to complete. MTU probing will then begin as usual when the handshake
145    /// completes.
146    ///
147    /// Note: `initial_mtu` must be >= `base_mtu` and <= `max_mtu`
148    pub fn with_initial_mtu(mut self, initial_mtu: u16) -> io::Result<Self> {
149        self.mtu_config_builder = self
150            .mtu_config_builder
151            .with_initial_mtu(initial_mtu)
152            .map_err(|err| io::Error::new(ErrorKind::InvalidInput, format!("{err}")))?;
153        Ok(self)
154    }
155
156    /// Sets the smallest maximum transmission unit (MTU) to use when transmitting (default: 1228)
157    ///
158    /// MTU is the size of the largest IP packet that can be transmitted on a path. This includes the
159    /// size of the IP header, the size of the UDP header, and the size of the UDP payload containing
160    /// the QUIC packet(s).
161    ///
162    /// QUIC requires that a network path support at least a 1200 byte datagram size, which translates
163    /// to 1228 bytes including the minimum IP header size (20 bytes) + UDP header size (8 bytes).
164    ///
165    /// If you have high confidence your network can support an MTU larger than the default `base_mtu`,
166    /// you can set this to a higher value. This will allow every packet s2n-quic transmits to reach
167    /// this MTU, even if packet loss results in MTU probing failing. Only configure this value if
168    /// it is certain the network path and peer can support the given `base_mtu`, as if it cannot
169    /// support the `base_mtu`, connections will not be able to opened to or from the endpoint.
170    ///
171    /// Note: `base_mtu` must be >= 1228 and <= `initial_mtu` and `max_mtu`
172    pub fn with_base_mtu(mut self, base_mtu: u16) -> io::Result<Self> {
173        self.mtu_config_builder = self
174            .mtu_config_builder
175            .with_base_mtu(base_mtu)
176            .map_err(|err| io::Error::new(ErrorKind::InvalidInput, format!("{err}")))?;
177        Ok(self)
178    }
179
180    /// Disables Generic Segmentation Offload (GSO)
181    ///
182    /// By default, GSO will be used unless the platform does not support it or an attempt to use
183    /// GSO fails. If it is known that GSO is not available, set this option to explicitly disable it.
184    pub fn with_gso_disabled(mut self) -> io::Result<Self> {
185        self.max_segments = 1.try_into().expect("1 is always a valid MaxSegments value");
186        Ok(self)
187    }
188
189    /// Configures Generic Segmentation Offload (GSO)
190    ///
191    /// By default, GSO will be used unless the platform does not support it or an attempt to use
192    /// GSO fails. If it is known that GSO is not available, set this option to explicitly disable it.
193    pub fn with_gso(self, enabled: bool) -> io::Result<Self> {
194        if enabled {
195            Ok(self)
196        } else {
197            self.with_gso_disabled()
198        }
199    }
200
201    /// Disables Generic Receive Offload (GRO)
202    ///
203    /// By default, GRO will be used unless the platform does not support it. If it is known that
204    /// GRO is not available, set this option to explicitly disable it.
205    pub fn with_gro_disabled(mut self) -> io::Result<Self> {
206        self.gro_enabled = Some(false);
207        Ok(self)
208    }
209
210    /// Configures Generic Receive Offload (GRO)
211    ///
212    /// By default, GRO will be used unless the platform does not support it. If it is known that
213    /// GRO is not available, set this option to explicitly disable it.
214    pub fn with_gro(self, enabled: bool) -> io::Result<Self> {
215        if enabled {
216            Ok(self)
217        } else {
218            self.with_gro_disabled()
219        }
220    }
221
222    /// Enables the address reuse (SO_REUSEADDR) socket option
223    pub fn with_reuse_address(mut self, enabled: bool) -> io::Result<Self> {
224        self.reuse_address = enabled;
225        Ok(self)
226    }
227
228    /// Enables the port reuse (SO_REUSEPORT) socket option
229    pub fn with_reuse_port(mut self) -> io::Result<Self> {
230        if !cfg!(unix) {
231            return Err(io::Error::new(
232                io::ErrorKind::InvalidInput,
233                "reuse_port is not supported on the current platform",
234            ));
235        }
236        self.reuse_port = true;
237        Ok(self)
238    }
239
240    /// Set the value for the IPV6_V6ONLY socket option.
241    ///
242    /// If this is set to `true` then the socket is restricted to sending and
243    /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
244    /// can bind the same port at the same time.
245    ///
246    /// If this is set to `false` then the socket can be used to send and
247    /// receive packets from an IPv4-mapped IPv6 address.
248    pub fn with_only_v6(mut self, only_v6: bool) -> io::Result<Self> {
249        self.only_v6 = only_v6;
250        Ok(self)
251    }
252
253    pub fn build(self) -> io::Result<Io> {
254        Ok(Io { builder: self })
255    }
256}