quinn_proto/connection/streams/
send.rs1use bytes::Bytes;
2use thiserror::Error;
3
4use crate::{VarInt, connection::send_buffer::SendBuffer, frame};
5
6#[derive(Debug)]
7pub(super) struct Send {
8 pub(super) max_data: u64,
9 pub(super) state: SendState,
10 pub(super) pending: SendBuffer,
11 pub(super) priority: i32,
12 pub(super) fin_pending: bool,
14 pub(super) connection_blocked: bool,
16 pub(super) data_blocked_limit: Option<u64>,
20 pub(super) stop_reason: Option<VarInt>,
22}
23
24impl Send {
25 pub(super) fn new(max_data: VarInt) -> Box<Self> {
26 Box::new(Self {
27 max_data: max_data.into(),
28 state: SendState::Ready,
29 pending: SendBuffer::new(),
30 priority: 0,
31 fin_pending: false,
32 connection_blocked: false,
33 data_blocked_limit: None,
34 stop_reason: None,
35 })
36 }
37
38 pub(super) fn is_reset(&self) -> bool {
40 matches!(self.state, SendState::ResetSent)
41 }
42
43 pub(super) fn finish(&mut self) -> Result<(), FinishError> {
44 if let Some(error_code) = self.stop_reason {
45 Err(FinishError::Stopped(error_code))
46 } else if self.state == SendState::Ready {
47 self.state = SendState::DataSent {
48 finish_acked: false,
49 };
50 self.fin_pending = true;
51 Ok(())
52 } else {
53 Err(FinishError::ClosedStream)
54 }
55 }
56
57 pub(super) fn write<S: BytesSource>(
58 &mut self,
59 source: &mut S,
60 limit: u64,
61 ) -> Result<Written, WriteError> {
62 if !self.is_writable() {
63 return Err(WriteError::ClosedStream);
64 }
65 if let Some(error_code) = self.stop_reason {
66 return Err(WriteError::Stopped(error_code));
67 }
68 let budget = self.max_data - self.pending.offset();
69 if budget == 0 {
70 return Err(WriteError::Blocked);
71 }
72 let mut limit = limit.min(budget) as usize;
73
74 let mut result = Written::default();
75 loop {
76 let (chunk, chunks_consumed) = source.pop_chunk(limit);
77 result.chunks += chunks_consumed;
78 result.bytes += chunk.len();
79
80 if chunk.is_empty() {
81 break;
82 }
83
84 limit -= chunk.len();
85 self.pending.write(chunk);
86 }
87
88 Ok(result)
89 }
90
91 pub(super) fn reset(&mut self) {
93 use SendState::*;
94 if let DataSent { .. } | Ready = self.state {
95 self.state = ResetSent;
96 self.pending.discard();
97 self.fin_pending = false;
98 }
99 }
100
101 pub(super) fn try_stop(&mut self, error_code: VarInt) -> bool {
106 if self.stop_reason.is_none() {
107 self.stop_reason = Some(error_code);
108 true
109 } else {
110 false
111 }
112 }
113
114 pub(super) fn ack(&mut self, frame: frame::StreamMeta) -> bool {
116 self.pending.ack(frame.offsets);
117 match self.state {
118 SendState::DataSent {
119 ref mut finish_acked,
120 } => {
121 *finish_acked |= frame.fin;
122 *finish_acked && self.pending.is_fully_acked()
123 }
124 _ => false,
125 }
126 }
127
128 pub(super) fn increase_max_data(&mut self, offset: u64) -> bool {
132 if offset <= self.max_data || self.state != SendState::Ready {
133 return false;
134 }
135 let was_blocked = self.pending.offset() == self.max_data;
136 self.max_data = offset;
137 was_blocked
138 }
139
140 pub(super) fn offset(&self) -> u64 {
141 self.pending.offset()
142 }
143
144 pub(super) fn is_pending(&self) -> bool {
145 self.pending.has_unsent_data() || self.fin_pending
146 }
147
148 pub(super) fn is_writable(&self) -> bool {
149 matches!(self.state, SendState::Ready)
150 }
151}
152
153pub(crate) struct BytesArray<'a> {
158 chunks: &'a mut [Bytes],
160 consumed: usize,
162}
163
164impl<'a> BytesArray<'a> {
165 pub(crate) fn from_chunks(chunks: &'a mut [Bytes]) -> Self {
166 Self {
167 chunks,
168 consumed: 0,
169 }
170 }
171}
172
173impl BytesSource for BytesArray<'_> {
174 fn pop_chunk(&mut self, limit: usize) -> (Bytes, usize) {
175 let mut chunks_consumed = 0;
178
179 while self.consumed < self.chunks.len() {
180 let chunk = &mut self.chunks[self.consumed];
181
182 if chunk.len() <= limit {
183 let chunk = std::mem::take(chunk);
184 self.consumed += 1;
185 chunks_consumed += 1;
186 if chunk.is_empty() {
187 continue;
188 }
189 return (chunk, chunks_consumed);
190 } else if limit > 0 {
191 let chunk = chunk.split_to(limit);
192 return (chunk, chunks_consumed);
193 } else {
194 break;
195 }
196 }
197
198 (Bytes::new(), chunks_consumed)
199 }
200}
201
202pub(crate) struct ByteSlice<'a> {
208 data: &'a [u8],
210}
211
212impl<'a> ByteSlice<'a> {
213 pub(crate) fn from_slice(data: &'a [u8]) -> Self {
214 Self { data }
215 }
216}
217
218impl BytesSource for ByteSlice<'_> {
219 fn pop_chunk(&mut self, limit: usize) -> (Bytes, usize) {
220 let limit = limit.min(self.data.len());
221 if limit == 0 {
222 return (Bytes::new(), 0);
223 }
224
225 let chunk = Bytes::from(self.data[..limit].to_owned());
226 self.data = &self.data[chunk.len()..];
227
228 let chunks_consumed = usize::from(self.data.is_empty());
229 (chunk, chunks_consumed)
230 }
231}
232
233pub(super) trait BytesSource {
238 fn pop_chunk(&mut self, limit: usize) -> (Bytes, usize);
251}
252
253#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
255pub struct Written {
256 pub bytes: usize,
258 pub chunks: usize,
262}
263
264#[derive(Debug, Error, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
266pub enum WriteError {
267 #[error("unable to accept further writes")]
274 Blocked,
275 #[error("stopped by peer: code {0}")]
282 Stopped(VarInt),
283 #[error("closed stream")]
285 ClosedStream,
286}
287
288#[derive(Debug, Copy, Clone, Eq, PartialEq)]
289pub(super) enum SendState {
290 Ready,
292 DataSent { finish_acked: bool },
294 ResetSent,
296}
297
298#[derive(Debug, Error, Clone, PartialEq, Eq)]
300pub enum FinishError {
301 #[error("stopped by peer: code {0}")]
308 Stopped(VarInt),
309 #[error("closed stream")]
311 ClosedStream,
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[test]
319 fn bytes_array() {
320 let full = b"Hello World 123456789 ABCDEFGHJIJKLMNOPQRSTUVWXYZ".to_owned();
321 for limit in 0..full.len() {
322 let mut chunks = [
323 Bytes::from_static(b""),
324 Bytes::from_static(b"Hello "),
325 Bytes::from_static(b"Wo"),
326 Bytes::from_static(b""),
327 Bytes::from_static(b"r"),
328 Bytes::from_static(b"ld"),
329 Bytes::from_static(b""),
330 Bytes::from_static(b" 12345678"),
331 Bytes::from_static(b"9 ABCDE"),
332 Bytes::from_static(b"F"),
333 Bytes::from_static(b"GHJIJKLMNOPQRSTUVWXYZ"),
334 ];
335 let num_chunks = chunks.len();
336 let last_chunk_len = chunks[chunks.len() - 1].len();
337
338 let mut array = BytesArray::from_chunks(&mut chunks);
339
340 let mut buf = Vec::new();
341 let mut chunks_popped = 0;
342 let mut chunks_consumed = 0;
343 let mut remaining = limit;
344 loop {
345 let (chunk, consumed) = array.pop_chunk(remaining);
346 chunks_consumed += consumed;
347
348 if !chunk.is_empty() {
349 buf.extend_from_slice(&chunk);
350 remaining -= chunk.len();
351 chunks_popped += 1;
352 } else {
353 break;
354 }
355 }
356
357 assert_eq!(&buf[..], &full[..limit]);
358
359 if limit == full.len() {
360 assert_eq!(chunks_consumed, num_chunks);
362 assert_eq!(chunks_consumed, chunks_popped + 3);
364 } else if limit > full.len() - last_chunk_len {
365 assert_eq!(chunks_consumed, num_chunks - 1);
367 assert_eq!(chunks_consumed, chunks_popped + 2);
368 }
369 }
370 }
371
372 #[test]
373 fn byte_slice() {
374 let full = b"Hello World 123456789 ABCDEFGHJIJKLMNOPQRSTUVWXYZ".to_owned();
375 for limit in 0..full.len() {
376 let mut array = ByteSlice::from_slice(&full[..]);
377
378 let mut buf = Vec::new();
379 let mut chunks_popped = 0;
380 let mut chunks_consumed = 0;
381 let mut remaining = limit;
382 loop {
383 let (chunk, consumed) = array.pop_chunk(remaining);
384 chunks_consumed += consumed;
385
386 if !chunk.is_empty() {
387 buf.extend_from_slice(&chunk);
388 remaining -= chunk.len();
389 chunks_popped += 1;
390 } else {
391 break;
392 }
393 }
394
395 assert_eq!(&buf[..], &full[..limit]);
396 if limit != 0 {
397 assert_eq!(chunks_popped, 1);
398 } else {
399 assert_eq!(chunks_popped, 0);
400 }
401
402 if limit == full.len() {
403 assert_eq!(chunks_consumed, 1);
404 } else {
405 assert_eq!(chunks_consumed, 0);
406 }
407 }
408 }
409}