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(&self, io: &IoRef, nbytes: usize) -> io::Result<FilterUpdates> {
141        let mut ctx = FilterCtx {
142            io,
143            nbytes,
144            idx: 0,
145            stack: self,
146            st: FilterUpdates {
147                wants_write: false,
148                notify: false,
149            },
150        };
151        io.with_callbacks(|cb| cb.before_processing(io));
152        let result = io.filter().process_read_buf(&mut ctx);
153        io.with_callbacks(|cb| cb.after_processing(io));
154
155        result.map(|()| ctx.st)
156    }
157
158    pub(crate) fn process_read_buf_no_cb(
159        &self,
160        io: &IoRef,
161        nbytes: usize,
162    ) -> io::Result<FilterUpdates> {
163        let mut ctx = FilterCtx {
164            io,
165            nbytes,
166            idx: 0,
167            stack: self,
168            st: FilterUpdates {
169                wants_write: false,
170                notify: false,
171            },
172        };
173        io.filter().process_read_buf(&mut ctx).map(|()| ctx.st)
174    }
175
176    pub(crate) fn process_write_buf(&self, io: &IoRef) -> io::Result<()> {
177        if self.buffers[0].is_write_empty() {
178            Ok(())
179        } else {
180            let mut ctx = FilterCtx {
181                io,
182                idx: 0,
183                nbytes: 0,
184                stack: self,
185                st: FilterUpdates {
186                    wants_write: true,
187                    notify: false,
188                },
189            };
190            io.with_callbacks(|cb| cb.before_processing(io));
191            let res = io.filter().process_write_buf(&mut ctx);
192            io.with_callbacks(|cb| cb.after_processing(io));
193
194            res
195        }
196    }
197
198    pub(crate) fn process_write_buf_no_cb(&self, io: &IoRef) -> io::Result<()> {
199        if self.buffers[0].is_write_empty() {
200            Ok(())
201        } else {
202            let mut ctx = FilterCtx {
203                io,
204                idx: 0,
205                nbytes: 0,
206                stack: self,
207                st: FilterUpdates {
208                    wants_write: true,
209                    notify: false,
210                },
211            };
212            io.filter().process_write_buf(&mut ctx)
213        }
214    }
215
216    pub(crate) fn process_write_buf_force(&self, io: &IoRef) -> io::Result<()> {
217        let mut ctx = FilterCtx {
218            io,
219            idx: 0,
220            nbytes: 0,
221            stack: self,
222            st: FilterUpdates {
223                wants_write: true,
224                notify: false,
225            },
226        };
227        io.with_callbacks(|cb| cb.before_processing(io));
228        let res = io.filter().process_write_buf(&mut ctx);
229        io.with_callbacks(|cb| cb.after_processing(io));
230
231        res
232    }
233
234    pub(crate) fn process_shutdown(&self, io: &IoRef) -> io::Result<Poll<()>> {
235        self.process_write_buf(io)?;
236        io.with_callbacks(|cb| cb.before_processing(io));
237        let res = self.with_filter(io, |ctx| io.filter().shutdown(ctx));
238        io.with_callbacks(|cb| cb.after_processing(io));
239
240        res
241    }
242}
243
244impl Buffer {
245    fn is_write_empty(&self) -> bool {
246        self.with_write(|b| b.is_empty())
247    }
248
249    fn read_len(&self) -> usize {
250        if let Some(rb) = self.read.take() {
251            let l = rb.len();
252            self.read.set(Some(rb));
253            l
254        } else {
255            0
256        }
257    }
258
259    fn write_len(&self) -> usize {
260        self.with_write(|b| b.len())
261    }
262
263    fn with_read<F, R>(&self, io: &IoRef, f: F) -> R
264    where
265        F: FnOnce(&mut BytesMut) -> R,
266    {
267        let mut rb = self
268            .read
269            .take()
270            .unwrap_or_else(|| io.cfg().read_buf().get());
271        let result = f(&mut rb);
272
273        // check nested updates
274        if self.read.take().is_some() {
275            log::error!("Nested read io operation is detected");
276            io.terminate();
277        }
278
279        if rb.is_empty() {
280            io.cfg().read_buf().release(rb);
281        } else {
282            self.read.set(Some(rb));
283        }
284        result
285    }
286
287    fn with_write<F, R>(&self, f: F) -> R
288    where
289        F: FnOnce(&mut BytePages) -> R,
290    {
291        let mut wb = self.write.take().unwrap();
292        let result = f(&mut wb);
293        self.write.set(Some(wb));
294        result
295    }
296}
297
298#[derive(Copy, Clone, Debug)]
299pub(crate) struct FilterUpdates {
300    pub(crate) wants_write: bool,
301    pub(crate) notify: bool,
302}
303
304#[derive(Debug)]
305pub struct FilterCtx<'a> {
306    io: &'a IoRef,
307    idx: usize,
308    nbytes: usize,
309    stack: &'a Stack,
310    st: FilterUpdates,
311}
312
313impl FilterCtx<'_> {
314    #[inline]
315    /// Gets a reference to the I/O object.
316    pub fn io(&self) -> &IoRef {
317        self.io
318    }
319
320    #[inline]
321    /// Gets the I/O tag.
322    pub fn tag(&self) -> &'static str {
323        self.io.tag()
324    }
325
326    #[inline]
327    /// Gets new bytes count for read buffer.
328    pub fn new_read_bytes(&self) -> usize {
329        self.nbytes
330    }
331
332    #[inline]
333    /// Notifies about readiness changes.
334    pub fn notify(&mut self) {
335        self.st.notify = true;
336    }
337
338    #[inline]
339    /// Returns the filter context for the next filter in the chain.
340    pub fn with_next<F, R>(&mut self, f: F) -> R
341    where
342        F: FnOnce(&mut Self) -> R,
343    {
344        self.idx += 1;
345        let res = f(self);
346        self.idx -= 1;
347        res
348    }
349
350    #[inline]
351    /// Returns the filter buffer.
352    pub fn with_buffer<F, R>(&mut self, f: F) -> R
353    where
354        F: FnOnce(&mut FilterBuf<'_>) -> R,
355    {
356        let mut buf = FilterBuf {
357            io: self.io,
358            curr: &self.stack.buffers[self.idx],
359            next: &self.stack.buffers[self.idx + 1],
360            wants_write: Cell::new(self.st.wants_write),
361        };
362        let result = f(&mut buf);
363        if buf.wants_write.get() {
364            self.st.wants_write = true;
365        }
366        result
367    }
368
369    #[inline]
370    /// Returns the size of the last read buffer in the chain.
371    pub fn read_dst_size(&self) -> usize {
372        self.stack.buffers[0].read_len()
373    }
374
375    #[inline]
376    /// Returns the size of the last write buffer in the chain.
377    pub fn write_dst_size(&mut self) -> usize {
378        self.stack.buffers[self.stack.buffers.len() - 2].write_len()
379    }
380
381    pub(crate) fn clear_write_buf(&mut self) {
382        self.stack.buffers[self.idx].with_write(BytePages::clear);
383    }
384}
385
386#[derive(Debug)]
387pub struct FilterBuf<'a> {
388    io: &'a IoRef,
389    curr: &'a Buffer,
390    next: &'a Buffer,
391    wants_write: Cell<bool>,
392}
393
394impl FilterBuf<'_> {
395    #[inline]
396    /// Gets a reference to the I/O object.
397    pub fn io(&self) -> &IoRef {
398        self.io
399    }
400
401    #[inline]
402    /// Gets the I/O tag.
403    pub fn tag(&self) -> &'static str {
404        self.io.tag()
405    }
406
407    /// Returns references to the source read buffer.
408    pub fn with_read_src<F, R>(&self, f: F) -> R
409    where
410        F: FnOnce(&mut Option<BytesMut>) -> R,
411    {
412        let mut read_src = self.next.read.take();
413        let result = f(&mut read_src);
414
415        if let Some(b) = read_src {
416            if b.is_empty() {
417                self.io.cfg().read_buf().release(b);
418            } else {
419                self.next.read.set(Some(b));
420            }
421        }
422        result
423    }
424
425    /// Returns references to the source and destination read buffers.
426    pub fn with_read_buffers<F, R>(&self, f: F) -> R
427    where
428        F: FnOnce(&mut Option<BytesMut>, &mut BytesMut) -> R,
429    {
430        let mut read_src = self.next.read.take();
431        let mut read_dst = self
432            .curr
433            .read
434            .take()
435            .unwrap_or_else(|| self.io.cfg().read_buf().get());
436
437        let result = f(&mut read_src, &mut read_dst);
438
439        if let Some(b) = read_src {
440            if b.is_empty() {
441                self.io.cfg().read_buf().release(b);
442            } else {
443                self.next.read.set(Some(b));
444            }
445        }
446        if read_dst.is_empty() {
447            self.io.cfg().read_buf().release(read_dst);
448        } else {
449            self.curr.read.set(Some(read_dst));
450        }
451
452        result
453    }
454
455    #[inline]
456    /// Returns references to the source and destination write buffers.
457    pub fn with_write_buffers<F, R>(&self, f: F) -> R
458    where
459        F: FnOnce(&mut BytePages, &mut BytePages) -> R,
460    {
461        let mut write_curr = self.curr.write.take().unwrap();
462        let mut write_next = self.next.write.take().unwrap();
463        let write_len = if self.wants_write.get() {
464            0
465        } else {
466            write_next.len()
467        };
468
469        let result = f(&mut write_curr, &mut write_next);
470
471        if !self.wants_write.get() && write_next.len() > write_len {
472            self.wants_write.set(true);
473        }
474
475        self.curr.write.set(Some(write_curr));
476        self.next.write.set(Some(write_next));
477        result
478    }
479}
480
481impl fmt::Debug for Buffer {
482    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483        let read = self.read.take();
484        let write = self.write.take();
485
486        let result = f
487            .debug_struct("Buffer")
488            .field("read", &read)
489            .field("write", &write)
490            .finish();
491        self.read.set(read);
492        self.write.set(write);
493        result
494    }
495}