Skip to content

Commit 83b48b5

Browse files
larseggertdjc
authored andcommitted
feat: Allow changing the UDP send/receive buffer sizes
Also includes getters for the current sizes and a test. Bump version to 0.5.11.
1 parent 1c27b02 commit 83b48b5

File tree

7 files changed

+162
-10
lines changed

7 files changed

+162
-10
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

perf/src/lib.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::net::SocketAddr;
22

33
use anyhow::{Context, Result};
4+
use quinn::udp::UdpSocketState;
45
use rustls::crypto::ring::cipher_suite;
56
use socket2::{Domain, Protocol, Socket, Type};
67
use tracing::warn;
@@ -25,22 +26,28 @@ pub fn bind_socket(
2526
socket
2627
.bind(&socket2::SockAddr::from(addr))
2728
.context("binding endpoint")?;
28-
socket
29-
.set_send_buffer_size(send_buffer_size)
29+
30+
let socket_state = UdpSocketState::new((&socket).into())?;
31+
socket_state
32+
.set_send_buffer_size((&socket).into(), send_buffer_size)
3033
.context("send buffer size")?;
31-
socket
32-
.set_recv_buffer_size(recv_buffer_size)
34+
socket_state
35+
.set_recv_buffer_size((&socket).into(), recv_buffer_size)
3336
.context("recv buffer size")?;
3437

35-
let buf_size = socket.send_buffer_size().context("send buffer size")?;
38+
let buf_size = socket_state
39+
.send_buffer_size((&socket).into())
40+
.context("send buffer size")?;
3641
if buf_size < send_buffer_size {
3742
warn!(
3843
"Unable to set desired send buffer size. Desired: {}, Actual: {}",
3944
send_buffer_size, buf_size
4045
);
4146
}
4247

43-
let buf_size = socket.recv_buffer_size().context("recv buffer size")?;
48+
let buf_size = socket_state
49+
.recv_buffer_size((&socket).into())
50+
.context("recv buffer size")?;
4451
if buf_size < recv_buffer_size {
4552
warn!(
4653
"Unable to set desired recv buffer size. Desired: {}, Actual: {}",

quinn-udp/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "quinn-udp"
3-
version = "0.5.10"
3+
version = "0.5.11"
44
edition.workspace = true
55
rust-version.workspace = true
66
license.workspace = true

quinn-udp/src/fallback.rs

+24
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ impl UdpSocketState {
8686
1
8787
}
8888

89+
/// Resize the send buffer of `socket` to `bytes`
90+
#[inline]
91+
pub fn set_send_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> {
92+
socket.0.set_send_buffer_size(bytes)
93+
}
94+
95+
/// Resize the receive buffer of `socket` to `bytes`
96+
#[inline]
97+
pub fn set_recv_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> {
98+
socket.0.set_recv_buffer_size(bytes)
99+
}
100+
101+
/// Get the size of the `socket` send buffer
102+
#[inline]
103+
pub fn send_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> {
104+
socket.0.send_buffer_size()
105+
}
106+
107+
/// Get the size of the `socket` receive buffer
108+
#[inline]
109+
pub fn recv_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> {
110+
socket.0.recv_buffer_size()
111+
}
112+
89113
#[inline]
90114
pub fn may_fragment(&self) -> bool {
91115
true

quinn-udp/src/unix.rs

+24
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,30 @@ impl UdpSocketState {
249249
self.gro_segments
250250
}
251251

252+
/// Resize the send buffer of `socket` to `bytes`
253+
#[inline]
254+
pub fn set_send_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> {
255+
socket.0.set_send_buffer_size(bytes)
256+
}
257+
258+
/// Resize the receive buffer of `socket` to `bytes`
259+
#[inline]
260+
pub fn set_recv_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> {
261+
socket.0.set_recv_buffer_size(bytes)
262+
}
263+
264+
/// Get the size of the `socket` send buffer
265+
#[inline]
266+
pub fn send_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> {
267+
socket.0.send_buffer_size()
268+
}
269+
270+
/// Get the size of the `socket` receive buffer
271+
#[inline]
272+
pub fn recv_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> {
273+
socket.0.recv_buffer_size()
274+
}
275+
252276
/// Whether transmitted datagrams might get fragmented by the IP layer
253277
///
254278
/// Returns `false` on targets which employ e.g. the `IPV6_DONTFRAG` socket option.

quinn-udp/src/windows.rs

+24
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,30 @@ impl UdpSocketState {
292292
64
293293
}
294294

295+
/// Resize the send buffer of `socket` to `bytes`
296+
#[inline]
297+
pub fn set_send_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> {
298+
socket.0.set_send_buffer_size(bytes)
299+
}
300+
301+
/// Resize the receive buffer of `socket` to `bytes`
302+
#[inline]
303+
pub fn set_recv_buffer_size(&self, socket: UdpSockRef<'_>, bytes: usize) -> io::Result<()> {
304+
socket.0.set_recv_buffer_size(bytes)
305+
}
306+
307+
/// Get the size of the `socket` send buffer
308+
#[inline]
309+
pub fn send_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> {
310+
socket.0.send_buffer_size()
311+
}
312+
313+
/// Get the size of the `socket` receive buffer
314+
#[inline]
315+
pub fn recv_buffer_size(&self, socket: UdpSockRef<'_>) -> io::Result<usize> {
316+
socket.0.recv_buffer_size()
317+
}
318+
295319
#[inline]
296320
pub fn may_fragment(&self) -> bool {
297321
false

quinn-udp/tests/tests.rs

+75-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#[cfg(not(any(target_os = "openbsd", target_os = "netbsd", solarish)))]
2-
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
2+
use std::net::{SocketAddr, SocketAddrV6};
33
use std::{
44
io::IoSliceMut,
5-
net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket},
5+
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, UdpSocket},
66
slice,
77
};
88

@@ -186,6 +186,79 @@ fn gso() {
186186
);
187187
}
188188

189+
#[test]
190+
fn socket_buffers() {
191+
const BUFFER_SIZE: usize = 123456;
192+
const FACTOR: usize = if cfg!(any(target_os = "linux", target_os = "android")) {
193+
2 // Linux and Android set the buffer to double the requested size
194+
} else {
195+
1 // Everyone else is sane.
196+
};
197+
198+
let send = socket2::Socket::new(
199+
socket2::Domain::IPV4,
200+
socket2::Type::DGRAM,
201+
Some(socket2::Protocol::UDP),
202+
)
203+
.unwrap();
204+
let recv = socket2::Socket::new(
205+
socket2::Domain::IPV4,
206+
socket2::Type::DGRAM,
207+
Some(socket2::Protocol::UDP),
208+
)
209+
.unwrap();
210+
for sock in [&send, &recv] {
211+
sock.bind(&socket2::SockAddr::from(SocketAddrV4::new(
212+
Ipv4Addr::LOCALHOST,
213+
0,
214+
)))
215+
.unwrap();
216+
217+
let socket_state = UdpSocketState::new(sock.into()).expect("created socket state");
218+
219+
// Change the send buffer size.
220+
let buffer_before = socket_state.send_buffer_size(sock.into()).unwrap();
221+
assert_ne!(
222+
buffer_before,
223+
BUFFER_SIZE * FACTOR,
224+
"make sure buffer is not already desired size"
225+
);
226+
socket_state
227+
.set_send_buffer_size(sock.into(), BUFFER_SIZE)
228+
.expect("set send buffer size {buffer_before} -> {BUFFER_SIZE}");
229+
let buffer_after = socket_state.send_buffer_size(sock.into()).unwrap();
230+
assert_eq!(
231+
buffer_after,
232+
BUFFER_SIZE * FACTOR,
233+
"setting send buffer size to {BUFFER_SIZE} resulted in {buffer_before} -> {buffer_after}",
234+
);
235+
236+
// Change the receive buffer size.
237+
let buffer_before = socket_state.recv_buffer_size(sock.into()).unwrap();
238+
socket_state
239+
.set_recv_buffer_size(sock.into(), BUFFER_SIZE)
240+
.expect("set recv buffer size {buffer_before} -> {BUFFER_SIZE}");
241+
let buffer_after = socket_state.recv_buffer_size(sock.into()).unwrap();
242+
assert_eq!(
243+
buffer_after,
244+
BUFFER_SIZE * FACTOR,
245+
"setting recv buffer size to {BUFFER_SIZE} resulted in {buffer_before} -> {buffer_after}",
246+
);
247+
}
248+
249+
test_send_recv(
250+
&send,
251+
&recv,
252+
Transmit {
253+
destination: recv.local_addr().unwrap().as_socket().unwrap(),
254+
ecn: None,
255+
contents: b"hello",
256+
segment_size: None,
257+
src_ip: None,
258+
},
259+
);
260+
}
261+
189262
fn test_send_recv(send: &Socket, recv: &Socket, transmit: Transmit) {
190263
let send_state = UdpSocketState::new(send.into()).unwrap();
191264
let recv_state = UdpSocketState::new(recv.into()).unwrap();

0 commit comments

Comments
 (0)