noq_proto/connection/
datagrams.rs1use std::collections::VecDeque;
2
3use bytes::Bytes;
4use thiserror::Error;
5use tracing::{debug, trace};
6
7use super::Connection;
8use crate::{
9 FrameStats, TransportError,
10 connection::PacketBuilder,
11 frame::{Datagram, FrameStruct},
12};
13
14pub struct Datagrams<'a> {
16 pub(super) conn: &'a mut Connection,
17}
18
19impl Datagrams<'_> {
20 pub fn send(&mut self, data: Bytes, drop: bool) -> Result<(), SendDatagramError> {
30 if self.conn.config.datagram_receive_buffer_size.is_none() {
31 return Err(SendDatagramError::Disabled);
32 }
33 let max = self
34 .max_size()
35 .ok_or(SendDatagramError::UnsupportedByPeer)?;
36 if data.len() > max {
37 return Err(SendDatagramError::TooLarge);
38 }
39 if drop {
40 while self.conn.datagrams.outgoing_total > self.conn.config.datagram_send_buffer_size {
41 let prev = self
42 .conn
43 .datagrams
44 .outgoing
45 .pop_front()
46 .expect("datagrams.outgoing_total desynchronized");
47 trace!(len = prev.data.len(), "dropping outgoing datagram");
48 self.conn.datagrams.outgoing_total -= prev.data.len();
49 }
50 } else if self.conn.datagrams.outgoing_total + data.len()
51 > self.conn.config.datagram_send_buffer_size
52 {
53 self.conn.datagrams.send_blocked = true;
54 return Err(SendDatagramError::Blocked(data));
55 }
56 self.conn.datagrams.outgoing_total += data.len();
57 self.conn.datagrams.outgoing.push_back(Datagram { data });
58 Ok(())
59 }
60
61 pub fn max_size(&self) -> Option<usize> {
74 let max_size = self.conn.current_mtu() as usize
78 - self.conn.predict_1rtt_overhead_no_pn()
79 - Datagram::SIZE_BOUND;
80 let limit = self
81 .conn
82 .peer_params
83 .max_datagram_frame_size?
84 .into_inner()
85 .saturating_sub(Datagram::SIZE_BOUND as u64);
86 Some(limit.min(max_size as u64) as usize)
87 }
88
89 pub fn recv(&mut self) -> Option<Bytes> {
91 self.conn.datagrams.recv()
92 }
93
94 pub fn send_buffer_space(&self) -> usize {
99 self.conn
100 .config
101 .datagram_send_buffer_size
102 .saturating_sub(self.conn.datagrams.outgoing_total)
103 }
104}
105
106#[derive(Default)]
107pub(super) struct DatagramState {
108 pub(super) recv_buffered: usize,
111 pub(super) incoming: VecDeque<Datagram>,
112 pub(super) outgoing: VecDeque<Datagram>,
113 pub(super) outgoing_total: usize,
114 pub(super) send_blocked: bool,
115}
116
117impl DatagramState {
118 pub(super) fn received(
119 &mut self,
120 datagram: Datagram,
121 window: &Option<usize>,
122 ) -> Result<bool, TransportError> {
123 let window = match window {
124 None => {
125 return Err(TransportError::PROTOCOL_VIOLATION(
126 "unexpected DATAGRAM frame",
127 ));
128 }
129 Some(x) => *x,
130 };
131
132 if datagram.data.len() > window {
133 return Err(TransportError::PROTOCOL_VIOLATION("oversized datagram"));
134 }
135
136 let was_empty = self.recv_buffered == 0;
137 while datagram.data.len() + self.recv_buffered > window {
138 debug!("dropping stale datagram");
139 self.recv();
140 }
141
142 self.recv_buffered += datagram.data.len();
143 self.incoming.push_back(datagram);
144 Ok(was_empty)
145 }
146
147 pub(super) fn drop_oversized(&mut self, max_payload: usize) -> bool {
154 let mut dropped_any = false;
155 self.outgoing.retain(|datagram| {
156 let result = datagram.data.len() < max_payload;
157 if !result {
158 trace!(
159 "dropping {} byte datagram violating {} byte limit",
160 datagram.data.len(),
161 max_payload
162 );
163 self.outgoing_total -= datagram.data.len();
164 dropped_any = true;
165 }
166 result
167 });
168 dropped_any
169 }
170
171 pub(super) fn write<'a, 'b>(
176 &mut self,
177 buf: &mut PacketBuilder<'a, 'b>,
178 stat: &mut FrameStats,
179 ) -> bool {
180 let Some(datagram) = self.outgoing.pop_front() else {
181 return false;
182 };
183
184 if buf.frame_space_remaining() < datagram.size(true) {
185 self.outgoing.push_front(datagram);
188 return false;
189 }
190
191 self.outgoing_total -= datagram.data.len();
192 buf.write_frame(datagram, stat);
193 true
194 }
195
196 pub(super) fn recv(&mut self) -> Option<Bytes> {
197 let x = self.incoming.pop_front()?.data;
198 self.recv_buffered -= x.len();
199 Some(x)
200 }
201}
202
203#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
205pub enum SendDatagramError {
206 #[error("datagrams not supported by peer")]
208 UnsupportedByPeer,
209 #[error("datagram support disabled")]
211 Disabled,
212 #[error("datagram too large")]
217 TooLarge,
218 #[error("datagram send blocked")]
220 Blocked(Bytes),
221}