Skip to main content

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.
14///
15/// [`ecn`]: SendItem::ecn
16/// [`segment_size`]: SendItem::segment_size
17#[derive(Clone, Copy)]
18pub struct SendItem<'a> {
19    pub(crate) data: &'a [u8],
20    pub(crate) destination: SocketAddr,
21    pub(crate) ecn: Option<Ecn>,
22    pub(crate) segment_size: Option<u16>,
23}
24
25impl<'a> SendItem<'a> {
26    /// Create a datagram targeting `destination` with the given `data` payload.
27    /// Address comes first, then data.
28    pub fn new(destination: SocketAddr, data: &'a [u8]) -> Self {
29        SendItem {
30            data,
31            destination,
32            ecn: None,
33            segment_size: None,
34        }
35    }
36
37    /// Attach an ECN codepoint to the outgoing datagram.
38    pub fn ecn(mut self, ecn: Ecn) -> Self {
39        self.ecn = Some(ecn);
40        self
41    }
42
43    /// Enable UDP segmentation offload (GSO on Linux). The kernel will split
44    /// `data` into consecutive chunks of `segment_size` bytes and send each as
45    /// a separate UDP datagram to the same `destination`.
46    ///
47    /// `data.len()` must be a multiple of `segment_size`, except for the final
48    /// segment which may be shorter.
49    pub fn segment_size(mut self, segment_size: u16) -> Self {
50        self.segment_size = Some(segment_size);
51        self
52    }
53}
54
55/// A single inbound UDP datagram slot.
56///
57/// Create with [`ReceiveItem::new`] passing a buffer, then call
58/// [`FastUdpSocket::receive_many`] to fill it. After a successful receive,
59/// [`data`] / [`source`] / [`ecn`] / [`len`] return the received datagram's
60/// metadata.
61///
62/// [`data`]: ReceiveItem::data
63/// [`source`]: ReceiveItem::source
64/// [`ecn`]: ReceiveItem::ecn
65/// [`len`]: ReceiveItem::len
66/// [`FastUdpSocket::receive_many`]: crate::FastUdpSocket::receive_many
67pub struct ReceiveItem<'a> {
68    pub(crate) buf: &'a mut [u8],
69    pub(crate) source: SocketAddr,
70    pub(crate) ecn: Option<Ecn>,
71    pub(crate) len: usize,
72}
73
74impl<'a> ReceiveItem<'a> {
75    /// Create an empty receive slot backed by `buf`.
76    pub fn new(buf: &'a mut [u8]) -> Self {
77        ReceiveItem {
78            buf,
79            source: SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED), 0),
80            ecn: None,
81            len: 0,
82        }
83    }
84
85    /// The received payload (first `len` bytes of the internal buffer).
86    pub fn data(&self) -> &[u8] {
87        &self.buf[..self.len]
88    }
89
90    /// The source address of the received datagram.
91    pub fn source(&self) -> SocketAddr {
92        self.source
93    }
94
95    /// The ECN codepoint received with the datagram, if any.
96    pub fn ecn(&self) -> Option<Ecn> {
97        self.ecn
98    }
99
100    /// Number of bytes received.
101    pub fn len(&self) -> usize {
102        self.len
103    }
104
105    /// Whether zero bytes were received.
106    pub fn is_empty(&self) -> bool {
107        self.len == 0
108    }
109}