tokio_fast_udp/item.rs
1use std::net::SocketAddr;
2
3use crate::Ecn;
4
5/// A single outbound UDP datagram.
6///
7/// Build with [`SendItem::new`] and optionally chain [`ecn`] / [`segment_size`]
8/// to attach ancillary data.
9///
10/// When [`segment_size`] is set and the platform supports it (Linux GSO), the
11/// kernel will segment `data` into multiple datagrams of `segment_size` bytes
12/// each (the final segment may be shorter). This allows sending N packets in
13/// a single syscall. On platforms without GSO the same datagrams are produced
14/// by splitting `data` in user space.
15///
16/// [`ecn`]: SendItem::ecn
17/// [`segment_size`]: SendItem::segment_size
18#[derive(Clone, Copy)]
19pub struct SendItem<'a> {
20 pub(crate) data: &'a [u8],
21 pub(crate) destination: SocketAddr,
22 pub(crate) ecn: Option<Ecn>,
23 pub(crate) segment_size: Option<u16>,
24}
25
26impl<'a> SendItem<'a> {
27 /// Create a datagram targeting `destination` with the given `data` payload.
28 /// Address comes first, then data.
29 pub fn new(destination: SocketAddr, data: &'a [u8]) -> Self {
30 SendItem {
31 data,
32 destination,
33 ecn: None,
34 segment_size: None,
35 }
36 }
37
38 /// Attach an ECN codepoint to the outgoing datagram.
39 pub fn ecn(mut self, ecn: Ecn) -> Self {
40 self.ecn = Some(ecn);
41 self
42 }
43
44 /// Enable UDP segmentation offload (GSO on Linux). `data` is split into
45 /// consecutive chunks of `segment_size` bytes and each chunk is sent as a
46 /// separate UDP datagram to the same `destination` (the final chunk may be
47 /// shorter).
48 ///
49 /// On Linux with GSO available the kernel performs the segmentation from a
50 /// single `sendmsg`; everywhere else the chunks are emitted as individual
51 /// datagrams in user space.
52 ///
53 /// `segment_size` must be greater than zero: a zero value makes the next
54 /// send fail with [`io::ErrorKind::InvalidInput`].
55 ///
56 /// [`io::ErrorKind::InvalidInput`]: std::io::ErrorKind::InvalidInput
57 pub fn segment_size(mut self, segment_size: u16) -> Self {
58 self.segment_size = Some(segment_size);
59 self
60 }
61}
62
63/// A single inbound UDP datagram slot.
64///
65/// Create with [`ReceiveItem::new`] passing a buffer, then call
66/// [`FastUdpSocket::receive_many`] to fill it. After a successful receive,
67/// [`data`] / [`source`] / [`ecn`] / [`len`] return the received datagram's
68/// metadata.
69///
70/// [`data`]: ReceiveItem::data
71/// [`source`]: ReceiveItem::source
72/// [`ecn`]: ReceiveItem::ecn
73/// [`len`]: ReceiveItem::len
74/// [`FastUdpSocket::receive_many`]: crate::FastUdpSocket::receive_many
75pub struct ReceiveItem<'a> {
76 pub(crate) buf: &'a mut [u8],
77 pub(crate) source: SocketAddr,
78 pub(crate) ecn: Option<Ecn>,
79 pub(crate) len: usize,
80}
81
82impl<'a> ReceiveItem<'a> {
83 /// Create an empty receive slot backed by `buf`.
84 pub fn new(buf: &'a mut [u8]) -> Self {
85 ReceiveItem {
86 buf,
87 source: SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED), 0),
88 ecn: None,
89 len: 0,
90 }
91 }
92
93 /// The received payload (first `len` bytes of the internal buffer).
94 pub fn data(&self) -> &[u8] {
95 &self.buf[..self.len]
96 }
97
98 /// The source address of the received datagram.
99 pub fn source(&self) -> SocketAddr {
100 self.source
101 }
102
103 /// The ECN codepoint received with the datagram, if any.
104 pub fn ecn(&self) -> Option<Ecn> {
105 self.ecn
106 }
107
108 /// Number of bytes received.
109 pub fn len(&self) -> usize {
110 self.len
111 }
112
113 /// Whether zero bytes were received.
114 pub fn is_empty(&self) -> bool {
115 self.len == 0
116 }
117}