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