1use super::{BodyError, BodyFrame, ReadableBody, WritableBody};
5use crate::future::cancellable;
6use base_scheduler::Cancellation;
7use event_listener::Event;
8use std::{
9 collections::VecDeque,
10 sync::{Arc, Mutex, MutexGuard, PoisonError},
11};
12
13struct State<D> {
14 frames: VecDeque<(BodyFrame<D>, usize)>,
15 bytes: usize,
16 read_closed: bool,
17 write_closed: bool,
18 headers: bool,
19 error: Option<BodyError>,
20}
21
22pub(crate) struct Shared<D> {
23 state: Mutex<State<D>>,
24 readable: Event,
25 writable: Event,
26 max_bytes: usize,
27 max_chunks: usize,
28 length: Option<u64>,
29}
30
31impl<D> Shared<D> {
32 fn lock(&self) -> MutexGuard<'_, State<D>> {
33 self.state.lock().unwrap_or_else(PoisonError::into_inner)
34 }
35
36 pub(crate) fn finish(&self, mut error: Option<BodyError>) {
38 let discarded = {
39 let mut state = self.lock();
40 let discarded = if error.is_some() {
41 if state.error.is_none() {
42 state.error = error.take();
43 }
44 state.bytes = 0;
45 std::mem::take(&mut state.frames)
46 } else {
47 VecDeque::new()
48 };
49 state.write_closed = true;
50 discarded
51 };
52 self.readable.notify(usize::MAX);
53 self.writable.notify(usize::MAX);
54 drop(discarded);
55 }
56}
57
58pub struct BodyReader<D = Vec<u8>> {
66 shared: Arc<Shared<D>>,
67}
68
69pub struct BodyWriter<D = Vec<u8>> {
76 shared: Arc<Shared<D>>,
77 closed: bool,
78}
79
80impl<D: AsRef<[u8]> + Send> BodyReader<D> {
81 pub fn bounded(max_bytes: usize, max_chunks: usize) -> (Self, BodyWriter<D>) {
83 Self::pair(max_bytes, max_chunks, None)
84 }
85
86 pub fn with_length(max_bytes: usize, max_chunks: usize, length: u64) -> (Self, BodyWriter<D>) {
88 Self::pair(max_bytes, max_chunks, Some(length))
89 }
90
91 fn pair(max_bytes: usize, max_chunks: usize, length: Option<u64>) -> (Self, BodyWriter<D>) {
92 assert!(max_bytes > 0, "body byte limit must be positive");
93 assert!(max_chunks > 0, "body chunk limit must be positive");
94 let shared = Arc::new(Shared {
95 state: Mutex::new(State {
96 frames: VecDeque::new(),
97 bytes: 0,
98 read_closed: false,
99 write_closed: false,
100 headers: false,
101 error: None,
102 }),
103 readable: Event::new(),
104 writable: Event::new(),
105 max_bytes,
106 max_chunks,
107 length,
108 });
109 (
110 Self {
111 shared: Arc::clone(&shared),
112 },
113 BodyWriter {
114 shared,
115 closed: false,
116 },
117 )
118 }
119}
120
121impl<D: AsRef<[u8]> + Send> ReadableBody for BodyReader<D> {
122 type Data = D;
123 type Error = BodyError;
124
125 fn is_ready(&self) -> bool {
126 let state = self.shared.lock();
127 !state.frames.is_empty() || state.read_closed || state.write_closed
128 }
129 fn is_empty(&self) -> bool {
130 let state = self.shared.lock();
131 state.frames.is_empty() && (state.read_closed || state.write_closed)
132 }
133 fn length(&self) -> Option<u64> {
134 self.shared.length
135 }
136 fn close(&mut self, error: Option<BodyError>) {
137 let discarded = {
138 let mut state = self.shared.lock();
139 state.read_closed = true;
140 state.bytes = 0;
141 if state.error.is_none() {
142 state.error = error;
143 }
144 std::mem::take(&mut state.frames)
145 };
146 self.shared.readable.notify(usize::MAX);
147 self.shared.writable.notify(usize::MAX);
148 drop(discarded);
149 }
150
151 async fn read(&mut self, cancellation: &Cancellation) -> Result<BodyFrame<D>, BodyError> {
152 loop {
153 cancellation.check()?;
154 event_listener::listener!(self.shared.readable => listener);
156 let chunk = {
157 let mut state = self.shared.lock();
158 if let Some(error) = &state.error {
159 return Err(error.clone());
160 }
161 if let Some((mut frame, length)) = state.frames.pop_front() {
162 state.bytes -= length;
163 if state.write_closed && state.frames.is_empty() {
164 match &mut frame {
165 BodyFrame::Data { end, .. } | BodyFrame::Headers { end, .. } => {
166 *end = true
167 }
168 BodyFrame::End => {}
169 }
170 }
171 Some(frame)
172 } else if state.write_closed || state.read_closed {
173 return Ok(BodyFrame::End);
174 } else {
175 None
176 }
177 };
178 if let Some(chunk) = chunk {
179 self.shared.writable.notify(usize::MAX);
180 return Ok(chunk);
181 }
182 cancellable(listener, cancellation).await?;
183 }
184 }
185}
186
187impl<D: AsRef<[u8]> + Send> BodyWriter<D> {
188 pub async fn write(&mut self, data: D, cancellation: &Cancellation) -> Result<(), BodyError> {
189 self.write_frame(BodyFrame::Data { data, end: false }, cancellation)
190 .await
191 }
192
193 pub async fn write_frame(
198 &mut self,
199 frame: BodyFrame<D>,
200 cancellation: &Cancellation,
201 ) -> Result<(), BodyError> {
202 cancellation.check()?;
203 let length = match &frame {
204 BodyFrame::Data { data, .. } => data.as_ref().len(),
205 BodyFrame::Headers { fields, .. } => {
206 fields.pairs().iter().fold(0usize, |sum, field| {
207 sum.saturating_add(field.name().len())
208 .saturating_add(field.value().len())
209 })
210 }
211 BodyFrame::End => 0,
212 };
213 if length > self.shared.max_bytes {
214 return Err(BodyError::ChunkTooLarge {
215 length,
216 limit: self.shared.max_bytes,
217 });
218 }
219 loop {
220 event_listener::listener!(self.shared.writable => listener);
221 {
222 let mut state = self.shared.lock();
223 if let Some(error) = &state.error {
224 return Err(error.clone());
225 }
226 if state.read_closed {
227 return Err(BodyError::Abandoned);
228 }
229 if state.write_closed {
230 return Err(BodyError::Closed);
231 }
232 if state.headers && !matches!(&frame, BodyFrame::End) {
233 return Err(BodyError::InvalidFrame);
234 }
235 if state.frames.len() < self.shared.max_chunks
236 && state.bytes <= self.shared.max_bytes - length
237 {
238 state.headers |= matches!(&frame, BodyFrame::Headers { .. });
239 let end = frame.is_end();
240 state.bytes += length;
241 state.frames.push_back((frame, length));
242 if end {
243 state.write_closed = true;
244 self.closed = true;
245 }
246 drop(state);
247 self.shared.readable.notify(usize::MAX);
248 return Ok(());
249 }
250 }
251 cancellable(listener, cancellation).await?;
252 }
253 }
254
255 pub async fn flush(&mut self, cancellation: &Cancellation) -> Result<(), BodyError> {
256 cancellation.check()?;
257 let state = self.shared.lock();
258 if let Some(error) = &state.error {
259 return Err(error.clone());
260 }
261 if state.read_closed {
262 return Err(BodyError::Abandoned);
263 }
264 Ok(())
267 }
268
269 pub fn close_write(&mut self, error: Option<BodyError>) {
270 if !self.closed {
271 self.closed = true;
272 self.shared.finish(error);
273 }
274 }
275
276 pub fn abort(&mut self) {
277 self.close_write(Some(BodyError::Abandoned));
278 }
279}
280
281impl<D> Drop for BodyReader<D> {
282 fn drop(&mut self) {
283 let discarded = {
284 let mut state = self.shared.lock();
285 state.read_closed = true;
286 state.bytes = 0;
287 std::mem::take(&mut state.frames)
288 };
289 self.shared.writable.notify(usize::MAX);
290 drop(discarded);
291 }
292}
293
294impl<D> Drop for BodyWriter<D> {
295 fn drop(&mut self) {
296 if !self.closed {
297 self.shared.finish(Some(BodyError::Abandoned));
298 }
299 }
300}
301
302impl<D: AsRef<[u8]> + Send> WritableBody for BodyWriter<D> {
303 type Data = D;
304 type Error = BodyError;
305 async fn write_frame(
306 &mut self,
307 frame: BodyFrame<D>,
308 cancellation: &Cancellation,
309 ) -> Result<(), BodyError> {
310 BodyWriter::write_frame(self, frame, cancellation).await
311 }
312 async fn write(&mut self, data: D, cancellation: &Cancellation) -> Result<(), BodyError> {
313 BodyWriter::write(self, data, cancellation).await
314 }
315 async fn flush(&mut self, cancellation: &Cancellation) -> Result<(), BodyError> {
316 BodyWriter::flush(self, cancellation).await
317 }
318 fn close_write(&mut self, error: Option<BodyError>) {
319 BodyWriter::close_write(self, error)
320 }
321 fn abort(&mut self) {
322 BodyWriter::abort(self)
323 }
324}