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}