Skip to main content

ntex_io/
buf.rs

1use std::{cell::Cell, fmt, io, task::Poll};
2
3use ntex_bytes::{BytePageSize, BytePages, BytesMut};
4
5use crate::{IoConfig, IoRef};
6
7pub(crate) struct Stack {
8    buffers: Vec<Buffer>,
9}
10
11#[derive(Default)]
12struct Buffer {
13    read: Cell<Option<BytesMut>>,
14    write: Cell<Option<BytePages>>,
15}
16
17impl fmt::Debug for Stack {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        f.debug_struct("Stack")
20            .field("len", &self.buffers.len())
21            .finish()
22    }
23}
24
25impl Stack {
26    pub(crate) fn new(size: BytePageSize) -> Self {
27        Self {
28            buffers: vec![
29                Buffer {
30                    read: Cell::new(None),
31                    write: Cell::new(Some(BytePages::new(size))),
32                },
33                Buffer {
34                    read: Cell::new(None),
35                    write: Cell::new(Some(BytePages::new(size))),
36                },
37            ],
38        }
39    }
40
41    pub(crate) fn set_page_size(&self, size: BytePageSize) {
42        for b in &self.buffers {
43            b.with_write(|b| b.set_page_size(size));
44        }
45    }
46
47    pub(crate) fn add_layer(&mut self, page_size: BytePageSize) {
48        self.buffers.insert(
49            0,
50            Buffer {
51                read: Cell::new(None),
52                write: Cell::new(Some(BytePages::new(page_size))),
53            },
54        );
55    }
56
57    fn with_last<F, R>(&self, f: F) -> R
58    where
59        F: FnOnce(&Buffer) -> R,
60    {
61        f(&self.buffers[self.buffers.len() - 2])
62    }
63
64    pub(crate) fn with_read_src<F, R>(&self, io: &IoRef, f: F) -> R
65    where
66        F: FnOnce(&mut BytesMut) -> R,
67    {
68        self.with_last(|buf| buf.with_read(io, f))
69    }
70
71    pub(crate) fn with_read_dst<F, R>(&self, io: &IoRef, f: F) -> R
72    where
73        F: FnOnce(&mut BytesMut) -> R,
74    {
75        self.buffers[0].with_read(io, f)
76    }
77
78    pub(crate) fn write_buf_size(&self) -> usize {
79        // check size for first level because delayed filter processing
80        if self.buffers.len() == 2 {
81            self.buffers[0].write_len()
82        } else {
83            self.buffers[0].write_len() + self.buffers[self.buffers.len() - 2].write_len()
84        }
85    }
86
87    pub(crate) fn with_write_src<F, R>(&self, f: F) -> R
88    where
89        F: FnOnce(&mut BytePages) -> R,
90    {
91        self.buffers[0].with_write(f)
92    }
93
94    pub(crate) fn with_write_dst<F, R>(&self, f: F) -> R
95    where
96        F: FnOnce(&mut BytePages) -> R,
97    {
98        self.buffers[self.buffers.len() - 2].with_write(f)
99    }
100
101    pub(crate) fn read_dst_size(&self) -> usize {
102        self.buffers[0].read_len()
103    }
104
105    pub(crate) fn with_filter<F, R>(&self, io: &IoRef, f: F) -> R
106    where
107        F: FnOnce(&mut FilterCtx<'_>) -> R,
108    {
109        let mut ctx = FilterCtx {
110            io,
111            idx: 0,
112            nbytes: 0,
113            stack: self,
114            st: FilterUpdates {
115                wants_write: false,
116                notify: false,
117            },
118        };
119        f(&mut ctx)
120    }
121
122    pub(crate) fn get_read_buf(&self) -> Option<BytesMut> {
123        self.with_last(|buffer| buffer.read.take())
124    }
125
126    pub(crate) fn set_read_buf(&self, buf: BytesMut, cfg: &IoConfig) {
127        self.with_last(move |buffer| {
128            if let Some(mut first_buf) = buffer.read.take() {
129                first_buf.extend_from_slice(&buf);
130                cfg.read_buf().release(buf);
131                buffer.read.set(Some(first_buf));
132            } else if !buf.is_empty() {
133                buffer.read.set(Some(buf));
134            } else {
135                cfg.read_buf().release(buf);
136            }
137        });
138    }
139
140    pub(crate) fn process_read_buf(
141        &self,
142        io: &IoRef,
143        nbytes: usize,
144    ) -> io::Result<FilterUpdates> {
145        let mut ctx = FilterCtx {
146            io,
147            nbytes,
148            idx: 0,
149            stack: self,
150            st: FilterUpdates {
151                wants_write: false,
152                notify: false,
153            },
154        };
155        io.with_callbacks(|cb| cb.before_processing(io));
156        let result = io.filter().process_read_buf(&mut ctx);
157        io.with_callbacks(|cb| cb.after_processing(io));
158
159        result.map(|()| ctx.st)
160    }
161
162    pub(crate) fn process_read_buf_no_cb(
163        &self,
164        io: &IoRef,
165        nbytes: usize,
166    ) -> io::Result<FilterUpdates> {
167        let mut ctx = FilterCtx {
168            io,
169            nbytes,
170            idx: 0,
171            stack: self,
172            st: FilterUpdates {
173                wants_write: false,
174                notify: false,
175            },
176        };
177        io.filter().process_read_buf(&mut ctx).map(|()| ctx.st)
178    }
179
180    pub(crate) fn process_write_buf(&self, io: &IoRef) -> io::Result<()> {
181        if self.buffers[0].is_write_empty() {
182            Ok(())
183        } else {
184            let mut ctx = FilterCtx {
185                io,
186                idx: 0,
187                nbytes: 0,
188                stack: self,
189                st: FilterUpdates {
190                    wants_write: true,
191                    notify: false,
192                },
193            };
194            io.with_callbacks(|cb| cb.before_processing(io));
195            let res = io.filter().process_write_buf(&mut ctx);
196            io.with_callbacks(|cb| cb.after_processing(io));
197
198            res
199        }
200    }
201
202    pub(crate) fn process_write_buf_no_cb(&self, io: &IoRef) -> io::Result<()> {
203        if self.buffers[0].is_write_empty() {
204            Ok(())
205        } else {
206            let mut ctx = FilterCtx {
207                io,
208                idx: 0,
209                nbytes: 0,
210                stack: self,
211                st: FilterUpdates {
212                    wants_write: true,
213                    notify: false,
214                },
215            };
216            io.filter().process_write_buf(&mut ctx)
217        }
218    }
219
220    pub(crate) fn process_write_buf_force(&self, io: &IoRef) -> io::Result<()> {
221        let mut ctx = FilterCtx {
222            io,
223            idx: 0,
224            nbytes: 0,
225            stack: self,
226            st: FilterUpdates {
227                wants_write: true,
228                notify: false,
229            },
230        };
231        io.with_callbacks(|cb| cb.before_processing(io));
232        let res = io.filter().process_write_buf(&mut ctx);
233        io.with_callbacks(|cb| cb.after_processing(io));
234
235        res
236    }
237
238    pub(crate) fn process_shutdown(&self, io: &IoRef) -> io::Result<Poll<()>> {
239        self.process_write_buf(io)?;
240        io.with_callbacks(|cb| cb.before_processing(io));
241        let res = self.with_filter(io, |ctx| io.filter().shutdown(ctx));
242        io.with_callbacks(|cb| cb.after_processing(io));
243
244        res
245    }
246}
247
248impl Buffer {
249    fn is_write_empty(&self) -> bool {
250        self.with_write(|b| b.is_empty())
251    }
252
253    fn read_len(&self) -> usize {
254        if let Some(rb) = self.read.take() {
255            let l = rb.len();
256            self.read.set(Some(rb));
257            l
258        } else {
259            0
260        }
261    }
262
263    fn write_len(&self) -> usize {
264        self.with_write(|b| b.len())
265    }
266
267    fn with_read<F, R>(&self, io: &IoRef, f: F) -> R
268    where
269        F: FnOnce(&mut BytesMut) -> R,
270    {
271        let mut rb = self
272            .read
273            .take()
274            .unwrap_or_else(|| io.cfg().read_buf().get());
275        let result = f(&mut rb);
276
277        // check nested updates
278        if self.read.take().is_some() {
279            log::error!("Nested read io operation is detected");
280            io.terminate();
281        }
282
283        if rb.is_empty() {
284            io.cfg().read_buf().release(rb);
285        } else {
286            self.read.set(Some(rb));
287        }
288        result
289    }
290
291    fn with_write<F, R>(&self, f: F) -> R
292    where
293        F: FnOnce(&mut BytePages) -> R,
294    {
295        let mut wb = self.write.take().unwrap();
296        let result = f(&mut wb);
297        self.write.set(Some(wb));
298        result
299    }
300}
301
302#[derive(Copy, Clone, Debug)]
303pub(crate) struct FilterUpdates {
304    pub(crate) wants_write: bool,
305    pub(crate) notify: bool,
306}
307
308#[derive(Debug)]
309pub struct FilterCtx<'a> {
310    io: &'a IoRef,
311    idx: usize,
312    nbytes: usize,
313    stack: &'a Stack,
314    st: FilterUpdates,
315}
316
317impl FilterCtx<'_> {
318    #[inline]
319    /// Gets a reference to the I/O object.
320    pub fn io(&self) -> &IoRef {
321        self.io
322    }
323
324    #[inline]
325    /// Gets the I/O tag.
326    pub fn tag(&self) -> &'static str {
327        self.io.tag()
328    }
329
330    #[inline]
331    /// Gets new bytes count for read buffer.
332    pub fn new_read_bytes(&self) -> usize {
333        self.nbytes
334    }
335
336    #[inline]
337    /// Notifies about readiness changes.
338    pub fn notify(&mut self) {
339        self.st.notify = true;
340    }
341
342    #[inline]
343    /// Returns the filter context for the next filter in the chain.
344    pub fn with_next<F, R>(&mut self, f: F) -> R
345    where
346        F: FnOnce(&mut Self) -> R,
347    {
348        self.idx += 1;
349        let res = f(self);
350        self.idx -= 1;
351        res
352    }
353
354    #[inline]
355    /// Returns the filter buffer.
356    pub fn with_buffer<F, R>(&mut self, f: F) -> R
357    where
358        F: FnOnce(&mut FilterBuf<'_>) -> R,
359    {
360        let mut buf = FilterBuf {
361            io: self.io,
362            curr: &self.stack.buffers[self.idx],
363            next: &self.stack.buffers[self.idx + 1],
364            wants_write: Cell::new(self.st.wants_write),
365        };
366        let result = f(&mut buf);
367        if buf.wants_write.get() {
368            self.st.wants_write = true;
369        }
370        result
371    }
372
373    #[inline]
374    /// Returns the size of the last read buffer in the chain.
375    pub fn read_dst_size(&self) -> usize {
376        self.stack.buffers[0].read_len()
377    }
378
379    #[inline]
380    /// Returns the size of the last write buffer in the chain.
381    pub fn write_dst_size(&mut self) -> usize {
382        self.stack.buffers[self.stack.buffers.len() - 2].write_len()
383    }
384
385    pub(crate) fn clear_write_buf(&mut self) {
386        self.stack.buffers[self.idx].with_write(BytePages::clear);
387    }
388}
389
390#[derive(Debug)]
391pub struct FilterBuf<'a> {
392    io: &'a IoRef,
393    curr: &'a Buffer,
394    next: &'a Buffer,
395    wants_write: Cell<bool>,
396}
397
398impl FilterBuf<'_> {
399    #[inline]
400    /// Gets a reference to the I/O object.
401    pub fn io(&self) -> &IoRef {
402        self.io
403    }
404
405    #[inline]
406    /// Gets the I/O tag.
407    pub fn tag(&self) -> &'static str {
408        self.io.tag()
409    }
410
411    /// Returns references to the source read buffer.
412    pub fn with_read_src<F, R>(&self, f: F) -> R
413    where
414        F: FnOnce(&mut Option<BytesMut>) -> R,
415    {
416        let mut read_src = self.next.read.take();
417        let result = f(&mut read_src);
418
419        if let Some(b) = read_src {
420            if b.is_empty() {
421                self.io.cfg().read_buf().release(b);
422            } else {
423                self.next.read.set(Some(b));
424            }
425        }
426        result
427    }
428
429    /// Returns references to the source and destination read buffers.
430    pub fn with_read_buffers<F, R>(&self, f: F) -> R
431    where
432        F: FnOnce(&mut Option<BytesMut>, &mut BytesMut) -> R,
433    {
434        let mut read_src = self.next.read.take();
435        let mut read_dst = self
436            .curr
437            .read
438            .take()
439            .unwrap_or_else(|| self.io.cfg().read_buf().get());
440
441        let result = f(&mut read_src, &mut read_dst);
442
443        if let Some(b) = read_src {
444            if b.is_empty() {
445                self.io.cfg().read_buf().release(b);
446            } else {
447                self.next.read.set(Some(b));
448            }
449        }
450        if read_dst.is_empty() {
451            self.io.cfg().read_buf().release(read_dst);
452        } else {
453            self.curr.read.set(Some(read_dst));
454        }
455
456        result
457    }
458
459    #[inline]
460    /// Returns references to the source and destination write buffers.
461    pub fn with_write_buffers<F, R>(&self, f: F) -> R
462    where
463        F: FnOnce(&mut BytePages, &mut BytePages) -> R,
464    {
465        let mut write_curr = self.curr.write.take().unwrap();
466        let mut write_next = self.next.write.take().unwrap();
467        let write_len = if self.wants_write.get() {
468            0
469        } else {
470            write_next.len()
471        };
472
473        let result = f(&mut write_curr, &mut write_next);
474
475        if !self.wants_write.get() && write_next.len() > write_len {
476            self.wants_write.set(true);
477        }
478
479        self.curr.write.set(Some(write_curr));
480        self.next.write.set(Some(write_next));
481        result
482    }
483}
484
485impl fmt::Debug for Buffer {
486    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487        let read = self.read.take();
488        let write = self.write.take();
489
490        let result = f
491            .debug_struct("Buffer")
492            .field("read", &read)
493            .field("write", &write)
494            .finish();
495        self.read.set(read);
496        self.write.set(write);
497        result
498    }
499}