Skip to main content

ntex_io/
io.rs

1use std::cell::{Cell, UnsafeCell};
2use std::future::{Future, poll_fn};
3use std::task::{Context, Poll};
4use std::{fmt, hash, io, marker, mem, ops, pin::Pin, ptr, rc::Rc};
5
6use ntex_bytes::{BytePageSize, BytesMut};
7use ntex_codec::{Decoder, Encoder};
8use ntex_service::cfg::{Cfg, SharedCfg};
9use ntex_util::{future::Either, task::LocalWaker, time::Sleep};
10
11use crate::buf::Stack;
12use crate::cfg::IoConfig;
13use crate::ctx::IoContext;
14use crate::filter::{Base, Filter, Layer};
15use crate::filterptr::FilterPtr;
16use crate::flags::Flags;
17use crate::ops::{Id, IoManager, TimerHandle};
18use crate::seal::{IoBoxed, Sealed};
19use crate::utils::Extensions;
20use crate::{Decoded, FilterLayer, Handle, IoStatusUpdate, IoStream, RecvError};
21
22/// Buffered, filterable interface to an underlying I/O stream.
23///
24/// An `Io` value owns a shared connection state. It coordinates transport
25/// tasks, read and write buffers, backpressure, filters, and graceful shutdown.
26pub struct Io<F = Base>(UnsafeCell<IoRef>, marker::PhantomData<F>);
27
28/// Cloneable reference to an [`Io`] connection's shared state.
29#[derive(Clone)]
30pub struct IoRef(pub(super) Rc<IoState>);
31
32pub(crate) struct IoState {
33    filter: FilterPtr,
34    pub(super) id: Cell<Id>,
35    pub(super) cfg: Cfg<IoConfig>,
36    pub(super) flags: Flags,
37    pub(super) error: Cell<Option<io::Error>>,
38    pub(super) read_task: LocalWaker,
39    pub(super) write_task: LocalWaker,
40    dispatch_task: LocalWaker,
41    pub(super) buffer: Stack,
42    pub(super) handle: Cell<Option<Box<dyn Handle>>>,
43    pub(super) timeout: Cell<TimerHandle>,
44    pub(super) shutdown_timeout: Cell<Option<Sleep>>,
45    pub(super) extensions: Extensions,
46}
47
48impl IoState {
49    pub(super) fn id(&self) -> Id {
50        self.id.get()
51    }
52
53    pub(super) fn tag(&self) -> &'static str {
54        self.cfg.tag()
55    }
56
57    pub(super) fn filter(&self) -> &dyn Filter {
58        self.filter.get()
59    }
60
61    pub(super) fn notify_timeout(&self) {
62        if self.flags.check_dispatcher_timeout_unset() {
63            self.wake_dispatch_task();
64            log::trace!("{}: Timer, notify dispatcher", self.cfg.tag());
65        }
66    }
67
68    pub(super) fn notify_disconnect(&self) {
69        self.extensions.notify_disconnect();
70    }
71
72    /// Get the current I/O error.
73    pub(super) fn error(&self) -> Option<io::Error> {
74        if let Some(err) = self.error.take() {
75            self.error
76                .set(Some(io::Error::new(err.kind(), format!("{err}"))));
77            Some(err)
78        } else {
79            None
80        }
81    }
82
83    /// Returns the current I/O error, or creates a `NotConnected` error.
84    pub(super) fn error_or_disconnected(&self) -> io::Error {
85        self.error()
86            .unwrap_or_else(|| io::Error::new(io::ErrorKind::NotConnected, "Disconnected"))
87    }
88
89    pub(super) fn filters_stopped(&self) {
90        self.wake_read_task();
91        self.wake_write_task();
92        self.wake_dispatch_task();
93        self.flags.set_filters_stopped();
94    }
95
96    pub(super) fn terminate_connection(&self, err: Option<io::Error>) {
97        if !self.flags.is_terminated() {
98            log::trace!("{}: Terminate io with error {:?}", self.cfg.tag(), err);
99            if err.is_some() {
100                self.error.set(err);
101            }
102            self.flags.set_terminate();
103            self.wake_read_task();
104            self.wake_write_task();
105            self.wake_dispatch_task();
106            self.notify_disconnect();
107            self.handle.take();
108        }
109    }
110
111    /// Gracefully shuts down the read and write I/O tasks.
112    pub(super) fn start_shutdown(&self) {
113        if !self.flags.is_stopping_any() {
114            log::trace!("{}: Initiate io shutdown {:?}", self.cfg.tag(), self.flags);
115            self.flags.set_filter_stopping();
116            self.wake_read_task();
117            self.wake_write_task();
118        }
119    }
120
121    pub(super) fn get_read_buf(&self) -> BytesMut {
122        self.cfg.read_buf().get()
123    }
124
125    pub(super) fn is_rd_backpressure_needed(&self, size: usize) -> bool {
126        size >= self.cfg.read_buf().high
127    }
128
129    pub(super) fn is_wr_backpressure_needed(&self, size: usize) -> bool {
130        size >= self.cfg.write_buf().high
131    }
132
133    pub(super) fn should_disable_wr_backpressure(&self, size: usize) -> bool {
134        size <= self.cfg.write_buf().half
135    }
136
137    pub(super) fn wake_read_task(&self) {
138        self.read_task.wake();
139    }
140
141    pub(super) fn wake_write_task(&self) {
142        #[cfg(feature = "trace")]
143        log::trace!("{}: Wake write task, flags:{:?}", self.tag(), self.flags);
144        self.write_task.wake();
145    }
146
147    pub(super) fn wake_dispatch_task(&self) {
148        self.dispatch_task.wake();
149    }
150}
151
152impl Eq for IoState {}
153
154impl PartialEq for IoState {
155    #[inline]
156    fn eq(&self, other: &Self) -> bool {
157        ptr::eq(self, other)
158    }
159}
160
161impl hash::Hash for IoState {
162    #[inline]
163    fn hash<H: hash::Hasher>(&self, state: &mut H) {
164        (ptr::from_ref(self) as usize).hash(state);
165    }
166}
167
168impl fmt::Debug for IoState {
169    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170        let err = self.error.take();
171        let res = f
172            .debug_struct("IoState")
173            .field("id", &self.id)
174            .field("flags", &self.flags)
175            .field("filter", &self.filter.is_set())
176            .field("timeout", &self.timeout)
177            .field("error", &err)
178            .field("buffer", &self.buffer)
179            .field("cfg", &self.cfg)
180            .finish();
181        self.error.set(err);
182        res
183    }
184}
185
186impl Io {
187    /// Creates a new `Io` instance.
188    pub fn new<I: IoStream, T: Into<SharedCfg>>(io: I, cfg: T) -> Self {
189        let cfg = cfg.into().get::<IoConfig>();
190        let size = cfg.write_page_size();
191        let flags = Flags::new(cfg.write_buf_threshold() > 0);
192
193        let inner = Rc::new(IoState {
194            cfg,
195            flags,
196            id: Cell::new(Id::default()),
197            filter: FilterPtr::null(),
198            error: Cell::new(None),
199            dispatch_task: LocalWaker::new(),
200            read_task: LocalWaker::new(),
201            write_task: LocalWaker::new(),
202            buffer: Stack::new(size),
203            handle: Cell::new(None),
204            timeout: Cell::new(TimerHandle::default()),
205            shutdown_timeout: Cell::new(None),
206            extensions: Extensions::default(),
207        });
208        inner.filter.set(Base::new(IoRef(inner.clone())));
209
210        let ioref = IoRef(inner);
211        ioref.0.id.set(IoManager::register(&ioref));
212
213        // start io tasks
214        let hnd = io.start(IoContext::new(ioref.clone()));
215        ioref.0.handle.set(Some(hnd));
216
217        Io(UnsafeCell::new(ioref), marker::PhantomData)
218    }
219}
220
221impl<I: IoStream> From<I> for Io {
222    #[inline]
223    fn from(io: I) -> Io {
224        Io::new(io, SharedCfg::default())
225    }
226}
227
228impl IoRef {
229    fn create_empty() -> IoRef {
230        IoRef(Rc::new(IoState {
231            id: Cell::new(Id::default()),
232            cfg: SharedCfg::default().get::<IoConfig>(),
233            filter: FilterPtr::null(),
234            flags: Flags::new_stopped(),
235            error: Cell::new(None),
236            dispatch_task: LocalWaker::new(),
237            read_task: LocalWaker::new(),
238            write_task: LocalWaker::new(),
239            buffer: Stack::new(BytePageSize::Size16),
240            handle: Cell::new(None),
241            timeout: Cell::new(TimerHandle::default()),
242            shutdown_timeout: Cell::new(None),
243            extensions: Extensions::default(),
244        }))
245    }
246}
247
248impl<F> Io<F> {
249    #[inline]
250    /// Returns a cloneable reference to this connection's shared state.
251    pub fn get_ref(&self) -> IoRef {
252        self.io_ref().clone()
253    }
254
255    #[inline]
256    #[must_use]
257    /// Takes the current I/O object.
258    ///
259    /// After this call, the I/O object is no longer valid for use.
260    pub fn take(&self) -> Self {
261        Self(UnsafeCell::new(self.take_io_ref()), marker::PhantomData)
262    }
263
264    fn take_io_ref(&self) -> IoRef {
265        unsafe { mem::replace(&mut *self.0.get(), IoRef::create_empty()) }
266    }
267
268    fn st(&self) -> &IoState {
269        unsafe { &(*self.0.get()).0 }
270    }
271
272    fn io_ref(&self) -> &IoRef {
273        unsafe { &*self.0.get() }
274    }
275
276    #[inline]
277    /// Updates the shared I/O configuration.
278    pub fn set_config<T: Into<SharedCfg>>(&self, cfg: T) {
279        unsafe {
280            let cfg = cfg.into().get::<IoConfig>();
281            self.st().buffer.set_page_size(cfg.write_page_size());
282            self.st().cfg.replace(cfg);
283        }
284    }
285}
286
287impl<F: FilterLayer, T: Filter> Io<Layer<F, T>> {
288    #[inline]
289    /// Returns a reference to a filter.
290    pub fn filter(&self) -> &F {
291        &self.st().filter.filter::<Layer<F, T>>().0
292    }
293}
294
295impl<F: Filter> Io<F> {
296    #[inline]
297    /// Converts the current I/O stream into a sealed version.
298    pub fn seal(self) -> Io<Sealed> {
299        let state = self.take_io_ref();
300        state.0.filter.seal::<F>();
301
302        Io(UnsafeCell::new(state), marker::PhantomData)
303    }
304
305    #[inline]
306    /// Converts the current I/O stream into a boxed version.
307    pub fn boxed(self) -> IoBoxed {
308        self.seal().into()
309    }
310
311    #[inline]
312    /// Adds a new processing layer to the current filter chain.
313    pub fn add_filter<U>(self, nf: U) -> Io<Layer<U, F>>
314    where
315        U: FilterLayer,
316    {
317        self.with_callbacks(|cb| cb.before_processing(&self));
318
319        // Write buffer processing may be delayed,
320        // call the filter chain to process pending writes
321        if let Err(e) = self.st().buffer.process_write_buf_no_cb(&self) {
322            self.st().terminate_connection(Some(e));
323        }
324
325        let state = self.take_io_ref();
326
327        // Add the buffers layer.
328        //
329        // Safety: no references into the buffer storage are retained.
330        // All APIs first remove the buffer from storage before processing it.
331        unsafe { &mut *(Rc::as_ptr(&state.0).cast_mut()) }
332            .buffer
333            .add_layer(state.0.cfg.write_page_size());
334
335        // Replace current filter
336        state.0.filter.add_filter::<F, U>(nf);
337
338        let io = Io(UnsafeCell::new(state), marker::PhantomData);
339
340        // push read data into new filter
341        if let Err(e) = io.st().buffer.process_read_buf_no_cb(&io, 0) {
342            io.st().terminate_connection(Some(e));
343        }
344        io.with_callbacks(|cb| cb.after_processing(&io));
345
346        io
347    }
348
349    /// Wraps the current layer with a wrapper.
350    pub fn map_filter<U, R>(self, f: U) -> Io<R>
351    where
352        U: FnOnce(F) -> R,
353        R: Filter,
354    {
355        self.with_callbacks(|cb| cb.before_processing(&self));
356
357        // Write buffer processing may be delayed,
358        // call the filter chain to process pending writes
359        if let Err(e) = self.st().buffer.process_write_buf(&self) {
360            self.st().terminate_connection(Some(e));
361        }
362
363        let state = self.take_io_ref();
364        state.0.filter.map_filter::<F, U, R>(f);
365
366        let io = Io(UnsafeCell::new(state), marker::PhantomData);
367        io.with_callbacks(|cb| cb.after_processing(&io));
368        io
369    }
370}
371
372impl<F> Io<F> {
373    /// Reads from the incoming I/O stream and decodes a codec item.
374    pub async fn recv<U>(&self, codec: &U) -> Result<Option<U::Item>, Either<U::Error, io::Error>>
375    where
376        U: Decoder,
377    {
378        loop {
379            return match poll_fn(|cx| self.poll_recv(codec, cx)).await {
380                Ok(item) => Ok(Some(item)),
381                Err(RecvError::KeepAlive) => Err(Either::Right(io::Error::new(
382                    io::ErrorKind::TimedOut,
383                    "Timeout",
384                ))),
385                Err(RecvError::WriteBackpressure) => {
386                    poll_fn(|cx| self.poll_flush(cx, false))
387                        .await
388                        .map_err(Either::Right)?;
389                    continue;
390                }
391                Err(RecvError::Decoder(err)) => Err(Either::Left(err)),
392                Err(RecvError::PeerGone(Some(err))) => Err(Either::Right(err)),
393                Err(RecvError::PeerGone(None)) => Ok(None),
394            };
395        }
396    }
397
398    /// Reads bytes from this I/O stream into the specified buffer.
399    ///
400    /// If there is not enough data available, waits for incoming data.
401    /// Returns an error of kind [`io::ErrorKind::UnexpectedEof`] if the stream
402    /// is disconnected before `dst` is completely filled.
403    pub async fn read(&self, dst: &mut [u8]) -> io::Result<()> {
404        loop {
405            let completed = self.with_read_buf(|buf| {
406                if buf.len() >= dst.len() {
407                    let _ = io::Read::read(buf, dst).expect("Cannot fail");
408                    true
409                } else {
410                    false
411                }
412            });
413            if completed {
414                return Ok(());
415            }
416            // `read_ready` resolves with `None` once the io is closed/stopped.
417            if self.read_ready().await?.is_none() {
418                return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Disconnected"));
419            }
420        }
421    }
422
423    #[inline]
424    /// Waits until the I/O stream is ready for reading.
425    pub async fn read_ready(&self) -> io::Result<Option<()>> {
426        poll_fn(|cx| self.poll_read_ready(cx)).await
427    }
428
429    #[inline]
430    /// Waits until the I/O stream receives new data.
431    pub async fn read_notify(&self) -> io::Result<Option<()>> {
432        poll_fn(|cx| self.poll_read_notify(cx)).await
433    }
434
435    #[inline]
436    /// Pauses the read task.
437    pub fn pause(&self) {
438        let st = self.st();
439        if !st.flags.is_read_paused() {
440            st.wake_read_task();
441            st.flags.set_read_paused();
442        }
443    }
444
445    #[inline]
446    /// Encodes an item and sends it to the peer, fully flushing the write buffer.
447    pub async fn send<U>(&self, item: U::Item, codec: &U) -> Result<(), Either<U::Error, io::Error>>
448    where
449        U: Encoder,
450    {
451        self.encode(item, codec).map_err(Either::Left)?;
452
453        poll_fn(|cx| self.poll_flush(cx, true))
454            .await
455            .map_err(Either::Right)?;
456
457        Ok(())
458    }
459
460    #[inline]
461    /// Wakes the write task and requests a flush of buffered data.
462    ///
463    /// This is the asynchronous counterpart to `poll_flush`.
464    pub async fn flush(&self, full: bool) -> io::Result<()> {
465        poll_fn(|cx| self.poll_flush(cx, full)).await
466    }
467
468    #[inline]
469    /// Gracefully shuts down the I/O stream.
470    pub async fn shutdown(&self) -> io::Result<()> {
471        poll_fn(|cx| self.poll_shutdown(cx)).await
472    }
473
474    #[inline]
475    /// Polls for read readiness.
476    ///
477    /// If the I/O stream is not currently ready for reading,
478    /// this method will store a clone of the `Waker` from the provided `Context`.
479    /// When the I/O stream becomes ready for reading, `wake()` will be called on the waker.
480    ///
481    /// # Returns
482    ///
483    /// The function returns:
484    ///
485    /// - `Poll::Pending` if the I/O stream is not ready for reading.
486    /// - `Poll::Ready(Ok(Some(())))` if the I/O stream is ready for reading.
487    /// - `Poll::Ready(Ok(None))` if the I/O stream is disconnected.
488    /// - `Poll::Ready(Err(e))` if an error is encountered.
489    pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Option<()>>> {
490        let st = self.st();
491
492        if st.flags.is_closed() {
493            Poll::Ready(Ok(None))
494        } else {
495            let ready = st.flags.is_read_ready();
496
497            // If the dispatcher requests more data but no read occurs,
498            // restart the read task.
499            if st.flags.is_read_paused_or_backpressure() {
500                st.flags.unset_all_read_flags();
501                st.flags.unset_read_paused();
502                st.wake_read_task();
503                if ready {
504                    Poll::Ready(Ok(Some(())))
505                } else {
506                    st.dispatch_task.register(cx.waker());
507                    Poll::Pending
508                }
509            } else if ready {
510                Poll::Ready(Ok(Some(())))
511            } else {
512                if st.flags.is_read_paused() {
513                    st.wake_read_task();
514                    st.flags.unset_read_paused();
515                }
516                st.dispatch_task.register(cx.waker());
517                Poll::Pending
518            }
519        }
520    }
521
522    #[inline]
523    /// Polls the I/O stream for availability of incoming data.
524    pub fn poll_read_notify(&self, cx: &mut Context<'_>) -> Poll<io::Result<Option<()>>> {
525        let st = self.st();
526        if st.flags.is_stopping() {
527            Poll::Ready(Ok(None))
528        } else if st.flags.check_read_notifed() {
529            Poll::Ready(Ok(Some(())))
530        } else {
531            st.flags.set_read_notify();
532            if self.poll_read_ready(cx).is_ready() {
533                st.dispatch_task.register(cx.waker());
534            }
535            st.dispatch_task.register(cx.waker());
536            Poll::Pending
537        }
538    }
539
540    #[inline]
541    /// Decode codec item from incoming bytes stream.
542    ///
543    /// Wake read task and request to read more data if data is not enough for decoding.
544    /// If error get returned this method does not register waker for later wake up action.
545    pub fn poll_recv<U>(
546        &self,
547        codec: &U,
548        cx: &mut Context<'_>,
549    ) -> Poll<Result<U::Item, RecvError<U>>>
550    where
551        U: Decoder,
552    {
553        let decoded = self.poll_recv_decode(codec, cx)?;
554
555        if let Some(item) = decoded.item {
556            Poll::Ready(Ok(item))
557        } else {
558            Poll::Pending
559        }
560    }
561
562    #[inline]
563    /// Decode codec item from incoming bytes stream.
564    ///
565    /// Wake read task and request to read more data if data is not enough for decoding.
566    /// If error get returned this method does not register waker for later wake up action.
567    pub fn poll_recv_decode<U>(
568        &self,
569        codec: &U,
570        cx: &mut Context<'_>,
571    ) -> Result<Decoded<U::Item>, RecvError<U>>
572    where
573        U: Decoder,
574    {
575        let st = self.st();
576        st.flags.unset_read_ready();
577
578        let decoded = self
579            .decode_item(codec)
580            .map_err(|err| RecvError::Decoder(err))?;
581
582        if decoded.item.is_some() {
583            Ok(decoded)
584        } else if st.flags.is_stopping() {
585            Err(RecvError::PeerGone(st.error()))
586        } else if st.flags.check_dispatcher_timeout() {
587            Err(RecvError::KeepAlive)
588        } else if st.flags.is_wr_backpressure() {
589            Err(RecvError::WriteBackpressure)
590        } else {
591            match self.poll_read_ready(cx) {
592                Poll::Pending | Poll::Ready(Ok(Some(()))) => {
593                    #[cfg(feature = "trace")]
594                    if decoded.remains != 0 {
595                        log::trace!("{}: Not enough data to decode next frame", self.tag());
596                    }
597                    Ok(decoded)
598                }
599                Poll::Ready(Err(e)) => Err(RecvError::PeerGone(Some(e))),
600                Poll::Ready(Ok(None)) => Err(RecvError::PeerGone(None)),
601            }
602        }
603    }
604
605    #[inline]
606    /// Wakes the write task and instructs it to flush data.
607    ///
608    /// If `full` is true, wakes the dispatcher when all data has been flushed;
609    /// otherwise, it wakes when the write buffer size falls below the low-watermark size.
610    pub fn poll_flush(&self, cx: &mut Context<'_>, full: bool) -> Poll<io::Result<()>> {
611        let st = self.st();
612
613        // flush filter state
614        st.buffer.process_write_buf_force(self)?;
615        self.consolidate_write_state(false);
616
617        let len = st.buffer.write_buf_size();
618        if len > 0 {
619            if st.flags.is_closed() {
620                return Poll::Ready(Err(st.error_or_disconnected()));
621            } else if full {
622                st.flags.set_wants_write_flush();
623                st.dispatch_task.register(cx.waker());
624                return Poll::Pending;
625            } else if st.is_wr_backpressure_needed(len) {
626                st.flags.set_wr_backpressure();
627                st.dispatch_task.register(cx.waker());
628                return Poll::Pending;
629            }
630        }
631        if st.flags.is_closed() && !st.flags.is_write_flush() {
632            Poll::Ready(Err(st.error_or_disconnected()))
633        } else {
634            st.flags.unset_wr_backpressure_and_flush();
635            Poll::Ready(Ok(()))
636        }
637    }
638
639    #[inline]
640    /// Gracefully shuts down the I/O stream.
641    pub fn poll_shutdown(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
642        let st = self.st();
643
644        if st.flags.is_stopping() {
645            if let Some(err) = st.error() {
646                Poll::Ready(Err(err))
647            } else {
648                Poll::Ready(Ok(()))
649            }
650        } else {
651            if !st.flags.is_stopping_filters() {
652                st.start_shutdown();
653            }
654            st.flags.unset_all_read_flags();
655            st.flags.unset_read_paused();
656
657            st.wake_read_task();
658            st.dispatch_task.register(cx.waker());
659            Poll::Pending
660        }
661    }
662
663    #[inline]
664    /// Pauses the read task.
665    ///
666    /// Returns status updates.
667    pub fn poll_read_pause(&self, cx: &mut Context<'_>) -> Poll<IoStatusUpdate> {
668        self.pause();
669        self.poll_status_update(cx)
670    }
671
672    #[inline]
673    /// Polls for available status updates.
674    pub fn poll_status_update(&self, cx: &mut Context<'_>) -> Poll<IoStatusUpdate> {
675        let st = self.st();
676        st.dispatch_task.register(cx.waker());
677        if st.flags.is_closed() {
678            Poll::Ready(IoStatusUpdate::PeerGone(st.error()))
679        } else if st.flags.check_dispatcher_timeout() {
680            Poll::Ready(IoStatusUpdate::KeepAlive)
681        } else if st.flags.is_wr_backpressure() {
682            // write backpressure is enabled and write buf smaller than half
683            if st.should_disable_wr_backpressure(st.buffer.write_buf_size()) {
684                st.flags.unset_wr_backpressure();
685            }
686            Poll::Ready(IoStatusUpdate::WriteBackpressure)
687        } else {
688            Poll::Pending
689        }
690    }
691
692    #[inline]
693    /// Registers a dispatch task.
694    pub fn poll_dispatch(&self, cx: &mut Context<'_>) {
695        self.st().dispatch_task.register(cx.waker());
696    }
697}
698
699impl<F> AsRef<IoRef> for Io<F> {
700    #[inline]
701    fn as_ref(&self) -> &IoRef {
702        self.io_ref()
703    }
704}
705
706impl<F> Eq for Io<F> {}
707
708impl<F> PartialEq for Io<F> {
709    #[inline]
710    fn eq(&self, other: &Self) -> bool {
711        self.io_ref().eq(other.io_ref())
712    }
713}
714
715impl<F> hash::Hash for Io<F> {
716    #[inline]
717    fn hash<H: hash::Hasher>(&self, state: &mut H) {
718        self.io_ref().hash(state);
719    }
720}
721
722impl<F> fmt::Debug for Io<F> {
723    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
724        f.debug_struct("Io").field("state", self.st()).finish()
725    }
726}
727
728impl<F> ops::Deref for Io<F> {
729    type Target = IoRef;
730
731    #[inline]
732    fn deref(&self) -> &Self::Target {
733        self.io_ref()
734    }
735}
736
737impl<F> Drop for Io<F> {
738    fn drop(&mut self) {
739        let st = self.st();
740        self.stop_timer();
741
742        if st.filter.is_set() {
743            // filter is unsafe and must be dropped explicitly,
744            // and won't be dropped without special attention
745            if !st.flags.is_terminated() {
746                log::trace!("{}: Io is dropped, terminate connection", st.tag());
747            }
748
749            st.terminate_connection(None);
750            st.filter.drop_filter::<F>();
751        }
752
753        IoManager::unregister(self.io_ref());
754    }
755}
756
757#[derive(Debug)]
758/// The `OnDisconnect` future resolves when the I/O stream is disconnected.
759#[must_use = "OnDisconnect do nothing unless polled"]
760pub struct OnDisconnect {
761    token: usize,
762    inner: Rc<IoState>,
763}
764
765impl OnDisconnect {
766    pub(super) fn new(inner: Rc<IoState>) -> Self {
767        Self::new_inner(inner.flags.is_stopping(), inner)
768    }
769
770    fn new_inner(disconnected: bool, inner: Rc<IoState>) -> Self {
771        let token = if disconnected {
772            usize::MAX
773        } else {
774            inner.extensions.register_disconnect()
775        };
776        Self { token, inner }
777    }
778
779    #[inline]
780    /// Checks if the I/O stream is disconnected.
781    pub fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<()> {
782        if self.token == usize::MAX || self.inner.flags.is_stopping() {
783            Poll::Ready(())
784        } else {
785            self.inner
786                .extensions
787                .poll_disconnect(self.token, cx.waker())
788        }
789    }
790}
791
792impl Clone for OnDisconnect {
793    fn clone(&self) -> Self {
794        if self.token == usize::MAX {
795            OnDisconnect::new_inner(true, self.inner.clone())
796        } else {
797            OnDisconnect::new_inner(false, self.inner.clone())
798        }
799    }
800}
801
802impl Future for OnDisconnect {
803    type Output = ();
804
805    #[inline]
806    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
807        self.poll_ready(cx)
808    }
809}
810
811#[cfg(test)]
812mod tests {
813    use ntex_bytes::{BufMut, BytePages, Bytes, BytesMut};
814    use ntex_codec::BytesCodec;
815    use ntex_util::{future::lazy, time::Millis, time::sleep};
816
817    use super::*;
818    use crate::{FilterBuf, IoContext, IoTaskStatus, Readiness, ops::Iops, testing::IoTest};
819
820    const BIN: &[u8] = b"GET /test HTTP/1\r\n\r\n";
821    const TEXT: &str = "GET /test HTTP/1\r\n\r\n";
822    const BIN2: &[u8] = b"12345678901234561234567890123456";
823
824    #[ntex::test]
825    async fn test_basics() {
826        let (client, server) = IoTest::create();
827        client.remote_buffer_cap(1024);
828
829        let server = Io::from(server);
830        assert!(server.eq(&server));
831        assert!(server.io_ref().eq(server.io_ref()));
832    }
833
834    #[ntex::test]
835    async fn test_recv() {
836        let (client, server) = IoTest::create();
837        client.remote_buffer_cap(1024);
838
839        let server = Io::new(server, SharedCfg::new("SRV"));
840
841        server.st().notify_timeout();
842        let err = server.recv(&BytesCodec).await.err().unwrap();
843        assert!(format!("{err:?}").contains("Timeout"));
844
845        client.write(TEXT);
846        server.st().flags.set_wr_backpressure();
847        let item = server.recv(&BytesCodec).await.ok().unwrap().unwrap();
848        assert_eq!(item, TEXT);
849    }
850
851    #[ntex::test]
852    async fn test_read() {
853        let (client, server) = IoTest::create();
854        client.remote_buffer_cap(1024);
855
856        let server = Io::new(server, SharedCfg::new("SRV"));
857
858        client.write(b"1234");
859        let mut buf: [u8; 4] = [0, 0, 0, 0];
860        server.read(&mut buf).await.unwrap();
861        assert_eq!(&buf, b"1234");
862
863        // disconnect during read
864        let fut = ntex_rt::spawn(async move {
865            let mut buf: [u8; 4] = [0, 0, 0, 0];
866            server.read(&mut buf).await
867        });
868        client.close().await;
869        let err = fut.await.unwrap().err().unwrap();
870        assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
871    }
872
873    #[ntex::test]
874    async fn test_send() {
875        let (client, server) = IoTest::create();
876        client.remote_buffer_cap(1024);
877
878        let server = Io::from(server);
879        assert!(server.eq(&server));
880
881        server
882            .send(Bytes::from_static(BIN), &BytesCodec)
883            .await
884            .ok()
885            .unwrap();
886        let item = client.read_any();
887        assert_eq!(item, TEXT);
888    }
889
890    #[ntex::test]
891    async fn read() {
892        let io = Io::new(
893            IoTest::create().0,
894            SharedCfg::new("SRV").add(IoConfig::default().set_read_buf(8, 4, 16)),
895        );
896        assert!(lazy(|cx| io.poll_read_ready(cx)).await.is_pending());
897        assert!(io.st().dispatch_task.is_set());
898
899        let ctx = IoContext::new(io.get_ref());
900
901        // Ready
902        assert_eq!(
903            lazy(|cx| ctx.poll_read_ready(cx)).await,
904            Poll::Ready(Readiness::Ready)
905        );
906        assert!(io.st().read_task.is_set());
907        assert!(!io.st().flags.is_read_ready());
908        assert!(!io.st().flags.is_rd_backpressure());
909
910        // == Enable backpressure
911        ctx.update_read_status(BytesMut::copy_from_slice(b"1234567890"), Ok(10));
912
913        // dispatcher is woken
914        assert!(!io.st().dispatch_task.is_set());
915        // read task is paused
916        assert!(io.st().flags.is_read_paused());
917        // read buffer is ready
918        assert!(io.st().flags.is_read_ready());
919        // read backpressure is enabled
920        assert!(io.st().flags.is_rd_backpressure());
921        // read task paused
922        assert_eq!(lazy(|cx| ctx.poll_read_ready(cx)).await, Poll::Pending);
923
924        // read one byte
925        assert_eq!(io.with_read_buf(|buf| buf.split_to(1)), b"1");
926        // read buffer is ready
927        assert!(io.st().flags.is_read_ready());
928        // read backpressure is enabled
929        assert!(io.st().flags.is_rd_backpressure());
930
931        // read task is set
932        assert!(io.st().read_task.is_set());
933
934        // read one more byte
935        assert_eq!(io.with_read_buf(|buf| buf.split_to(1)), b"2");
936        // read backpressure is enabled
937        assert!(io.st().flags.is_rd_backpressure());
938
939        // read 4 bytes. buf size is 4, less that half of high watermark
940        assert_eq!(io.with_read_buf(|buf| buf.split_to(4)), b"3456");
941        // read task is not paused anymore
942        assert!(!io.st().flags.is_read_paused());
943        // read buffer is not ready
944        assert!(!io.st().flags.is_read_ready());
945        // read backpressure is disabled
946        assert!(!io.st().flags.is_rd_backpressure());
947        // read task is woken
948        assert!(!io.st().read_task.is_set());
949        assert_eq!(
950            lazy(|cx| ctx.poll_read_ready(cx)).await,
951            Poll::Ready(Readiness::Ready)
952        );
953
954        // register dispatcher task
955        lazy(|cx| io.poll_dispatch(cx)).await;
956
957        // == Enable backpressure, 4 bytes in buffer + 4 more
958        ctx.update_read_status(BytesMut::copy_from_slice(b"1234"), Ok(4));
959
960        // dispatcher is woken
961        assert!(!io.st().dispatch_task.is_set());
962        // read task is paused
963        assert!(io.st().flags.is_read_paused());
964        // read buffer is ready
965        assert!(io.st().flags.is_read_ready());
966        // read backpressure is enabled
967        assert!(io.st().flags.is_rd_backpressure());
968        // read task paused
969        assert_eq!(lazy(|cx| ctx.poll_read_ready(cx)).await, Poll::Pending);
970
971        // read 4 bytes. buf size is 4, less that half of high watermark
972        assert_eq!(io.with_read_buf(|buf| buf.split_to(4)), b"7890");
973        // read backpressure is disabled
974        assert!(!io.st().flags.is_rd_backpressure());
975
976        // register dispatcher task
977        lazy(|cx| io.poll_dispatch(cx)).await;
978
979        // == No backpressure, 4 bytes in buffer + 3 more
980        ctx.update_read_status(BytesMut::copy_from_slice(b"567"), Ok(3));
981
982        // read task is paused
983        assert!(!io.st().flags.is_read_paused());
984        // read buffer is ready
985        assert!(io.st().flags.is_read_ready());
986        // read backpressure is enabled
987        assert!(!io.st().flags.is_rd_backpressure());
988        // read task ready
989        assert_eq!(
990            lazy(|cx| ctx.poll_read_ready(cx)).await,
991            Poll::Ready(Readiness::Ready)
992        );
993
994        // read 4 bytes. buf size is 4, less that half of high watermark
995        assert_eq!(io.with_read_buf(BytesMut::take), b"1234567");
996        // read task is paused
997        assert!(!io.st().flags.is_read_paused());
998        // read buffer is ready
999        assert!(!io.st().flags.is_read_ready());
1000        // read task is not woken
1001        assert!(io.st().read_task.is_set());
1002
1003        // == Terminate
1004        io.terminate();
1005        // read task is woken
1006        assert!(!io.st().read_task.is_set());
1007        // read task ready
1008        assert_eq!(
1009            lazy(|cx| ctx.poll_read_ready(cx)).await,
1010            Poll::Ready(Readiness::Terminate)
1011        );
1012    }
1013
1014    #[ntex::test]
1015    async fn read_notify() {
1016        let io = Io::new(
1017            IoTest::create().0,
1018            SharedCfg::new("SRV").add(IoConfig::default().set_read_buf(8, 4, 16)),
1019        );
1020        assert!(!io.st().flags.is_read_notify());
1021        assert!(lazy(|cx| io.poll_read_notify(cx)).await.is_pending());
1022        assert!(io.st().dispatch_task.is_set());
1023        assert!(io.st().flags.is_read_notify());
1024
1025        let ctx = IoContext::new(io.get_ref());
1026
1027        // incoming bytes
1028        ctx.update_read_status(BytesMut::copy_from_slice(b"1"), Ok(1));
1029
1030        assert!(!io.st().dispatch_task.is_set());
1031        // rd buffer is ready
1032        assert!(io.st().flags.is_read_ready());
1033        assert!(io.st().flags.is_read_notify());
1034        // dispatcher is notified
1035        assert!(io.st().flags.is_read_notified());
1036        let res = lazy(|cx| io.poll_read_notify(cx)).await;
1037        assert!(matches!(res, Poll::Ready(Ok(Some(())))));
1038
1039        // disapcher is not set
1040        assert!(!io.st().dispatch_task.is_set());
1041        // rd buffer is ready
1042        assert!(io.st().flags.is_read_ready());
1043
1044        // == start notification process again
1045        assert!(lazy(|cx| io.poll_read_notify(cx)).await.is_pending());
1046        assert!(io.st().dispatch_task.is_set());
1047        assert!(io.st().flags.is_read_notify());
1048        assert!(io.st().flags.is_read_ready());
1049        // read task ready
1050        assert_eq!(
1051            lazy(|cx| ctx.poll_read_ready(cx)).await,
1052            Poll::Ready(Readiness::Ready)
1053        );
1054
1055        // == enable packpressure
1056        ctx.update_read_status(BytesMut::copy_from_slice(b"2345678"), Ok(7));
1057        // read backpressure is enabled
1058        assert!(io.st().flags.is_rd_backpressure());
1059
1060        // rd buffer is ready
1061        assert!(io.st().flags.is_read_ready());
1062        assert!(io.st().flags.is_read_notify());
1063        // dispatcher is notified
1064        assert!(io.st().flags.is_read_notified());
1065        let res = lazy(|cx| io.poll_read_notify(cx)).await;
1066        assert!(matches!(res, Poll::Ready(Ok(Some(())))));
1067        // read task paused
1068        assert_eq!(lazy(|cx| ctx.poll_read_ready(cx)).await, Poll::Pending);
1069        // read task is set
1070        assert!(io.st().read_task.is_set());
1071
1072        // == start notification process again
1073        assert!(lazy(|cx| io.poll_read_notify(cx)).await.is_pending());
1074        // read flags active
1075        assert!(!io.st().flags.is_rd_backpressure());
1076        assert!(!io.st().flags.is_read_ready());
1077        assert!(!io.st().flags.is_read_paused());
1078        // read task is woken
1079        assert!(!io.st().read_task.is_set());
1080        // read task ready
1081        assert_eq!(
1082            lazy(|cx| ctx.poll_read_ready(cx)).await,
1083            Poll::Ready(Readiness::Ready)
1084        );
1085
1086        // incoming bytes
1087        ctx.update_read_status(BytesMut::copy_from_slice(b"1"), Ok(1));
1088        assert!(!io.st().dispatch_task.is_set());
1089        // rd buffer is ready
1090        assert!(io.st().flags.is_read_ready());
1091        assert!(io.st().flags.is_read_notify());
1092        assert!(io.st().flags.is_read_paused());
1093        assert!(io.st().flags.is_rd_backpressure());
1094        // dispatcher is notified
1095        assert!(io.st().flags.is_read_notified());
1096        assert!(matches!(
1097            lazy(|cx| io.poll_read_notify(cx)).await,
1098            Poll::Ready(Ok(Some(())))
1099        ));
1100
1101        // == Terminate
1102        io.terminate();
1103        let res = lazy(|cx| io.poll_read_notify(cx)).await;
1104        assert!(matches!(res, Poll::Ready(Ok(None))), "{res:?}");
1105    }
1106
1107    #[ntex::test]
1108    async fn read_readiness() {
1109        let (client, server) = IoTest::create();
1110        client.remote_buffer_cap(1024);
1111
1112        let io = Io::from(server);
1113        assert!(lazy(|cx| io.poll_read_ready(cx)).await.is_pending());
1114
1115        client.write(TEXT);
1116        assert_eq!(io.read_ready().await.unwrap(), Some(()));
1117        assert!(matches!(
1118            lazy(|cx| io.poll_read_ready(cx)).await,
1119            Poll::Ready(Ok(Some(())))
1120        ));
1121
1122        let item = io.with_read_buf(BytesMut::take);
1123        assert_eq!(item, Bytes::from_static(BIN));
1124
1125        client.write(TEXT);
1126        sleep(Millis(50)).await;
1127        assert!(lazy(|cx| io.poll_read_ready(cx)).await.is_ready());
1128        assert!(lazy(|cx| io.poll_read_ready(cx)).await.is_ready());
1129    }
1130
1131    #[ntex::test]
1132    async fn read_backpressure() {
1133        let (client, server) = IoTest::create();
1134
1135        let io = Io::new(
1136            server,
1137            SharedCfg::new("SRV").add(IoConfig::default().set_read_buf(64, 32, 12)),
1138        );
1139        assert!(lazy(|cx| io.poll_read_ready(cx)).await.is_pending());
1140
1141        client.write(BIN2);
1142        client.write(BIN2);
1143        sleep(Millis(50)).await;
1144        assert!(io.flags().is_read_ready());
1145        assert!(io.flags().is_rd_backpressure());
1146        let _item = io.recv(&BytesCodec).await.ok().unwrap().unwrap();
1147        assert!(!io.flags().is_read_ready());
1148        assert!(!io.flags().is_rd_backpressure());
1149
1150        client.write(BIN2);
1151        client.write(BIN2);
1152        sleep(Millis(50)).await;
1153        assert!(io.flags().is_read_ready());
1154        assert!(io.flags().is_rd_backpressure());
1155        assert_eq!(io.read_ready().await.unwrap(), Some(()));
1156    }
1157
1158    #[ntex::test]
1159    async fn write() {
1160        let io = Io::new(
1161            IoTest::create().0,
1162            SharedCfg::new("SRV").add(IoConfig::default().set_write_buf(8, 4, 16)),
1163        );
1164        assert!(lazy(|cx| io.poll_status_update(cx)).await.is_pending());
1165        assert!(io.st().dispatch_task.is_set());
1166        assert!(io.st().flags.is_direct_wr_enabled());
1167
1168        let ctx = IoContext::new(io.get_ref());
1169
1170        // == No write work
1171        assert_eq!(lazy(|cx| ctx.poll_write_ready(cx)).await, Poll::Pending);
1172        assert!(io.st().write_task.is_set());
1173        assert!(io.st().flags.is_write_paused());
1174        assert!(!io.st().flags.is_wr_backpressure());
1175
1176        // write
1177        io.with_write_buf(|buf| buf.put_slice(b"1234")).unwrap();
1178        assert_eq!(lazy(|cx| ctx.poll_write_ready(cx)).await, Poll::Pending);
1179        // write task is paused
1180        assert!(io.st().flags.is_write_paused());
1181        // send-buf op is scheduled
1182        assert!(io.st().flags.is_wr_send_scheduled());
1183        // back-pressure is not enabled
1184        assert!(!io.st().flags.is_wr_backpressure());
1185        // dispatch is not woken up
1186        assert!(io.st().dispatch_task.is_set());
1187
1188        // == enable wr backpressure
1189        io.with_write_buf(|buf| buf.put_slice(b"5678")).unwrap();
1190        // back-pressure is enabled
1191        assert!(io.st().flags.is_wr_backpressure());
1192        // dispatch is woken up
1193        assert!(!io.st().dispatch_task.is_set());
1194        // write task is set
1195        assert!(io.st().write_task.is_set());
1196        // dispatcher gets WriteBackpressure
1197        assert!(matches!(
1198            lazy(|cx| io.poll_status_update(cx)).await,
1199            Poll::Ready(IoStatusUpdate::WriteBackpressure)
1200        ));
1201        // flush write buffer
1202        assert!(lazy(|cx| io.poll_flush(cx, false)).await.is_pending());
1203        // full flush is not enabled
1204        assert!(!io.st().flags.is_write_flush());
1205
1206        // run send-buf ops
1207        Iops::run();
1208        // send-buf op is not scheduled
1209        assert!(!io.st().flags.is_wr_send_scheduled());
1210        // write task is not paused
1211        assert!(!io.st().flags.is_write_paused());
1212        // write task has been woken up
1213        assert!(!io.st().write_task.is_set());
1214        // write task can proceed
1215        assert_eq!(
1216            lazy(|cx| ctx.poll_write_ready(cx)).await,
1217            Poll::Ready(Readiness::Ready)
1218        );
1219
1220        // wrote 4 bytes to io
1221        assert_eq!(ctx.with_write_buf(|buf| buf.split_to(4).freeze()), b"1234");
1222        // continue to write
1223        assert_eq!(ctx.update_write_status(Ok(true)), IoTaskStatus::Io);
1224        // write task can proceed
1225        assert_eq!(
1226            lazy(|cx| ctx.poll_write_ready(cx)).await,
1227            Poll::Ready(Readiness::Ready)
1228        );
1229        // write task is not paused
1230        assert!(!io.st().flags.is_write_paused());
1231        // back-pressure is enabled
1232        assert!(io.st().flags.is_wr_backpressure());
1233        // dispatcher gets WriteBackpressure, buf wr-backpressure flags is removed
1234        assert!(matches!(
1235            lazy(|cx| io.poll_status_update(cx)).await,
1236            Poll::Ready(IoStatusUpdate::WriteBackpressure)
1237        ));
1238        // back-pressure is disabled
1239        assert!(!io.st().flags.is_wr_backpressure());
1240        assert!(lazy(|cx| io.poll_status_update(cx)).await.is_pending());
1241        // write buffer is flushed
1242        assert!(matches!(
1243            lazy(|cx| io.poll_flush(cx, false)).await,
1244            Poll::Ready(Ok(()))
1245        ));
1246
1247        // full flush write buffer
1248        io.with_write_buf(|buf| buf.put_slice(b"1234")).unwrap();
1249        assert!(lazy(|cx| io.poll_flush(cx, true)).await.is_pending());
1250        // full flush is enabled
1251        assert!(io.st().flags.is_write_flush());
1252        // back-pressure is enabled
1253        assert!(io.st().flags.is_wr_backpressure());
1254
1255        // wrote all data
1256        Iops::run();
1257        assert_eq!(ctx.with_write_buf(BytePages::freeze), b"56781234");
1258        // write task is not paused, so send-buf op is not scheduled
1259        assert!(!io.st().flags.is_wr_send_scheduled());
1260        // update status, no more work
1261        assert_eq!(ctx.update_write_status(Ok(true)), IoTaskStatus::Pause);
1262        // write task is paused
1263        assert!(io.st().flags.is_write_paused());
1264        // flush is still enabled
1265        assert!(io.st().flags.is_write_flush());
1266        // back-pressure is still enabled
1267        assert!(io.st().flags.is_wr_backpressure());
1268        // dispatch is woken up
1269        assert!(!io.st().dispatch_task.is_set());
1270
1271        // write buffer is flushed
1272        assert!(matches!(
1273            lazy(|cx| io.poll_flush(cx, false)).await,
1274            Poll::Ready(Ok(()))
1275        ));
1276        // full flush is disabled
1277        assert!(!io.st().flags.is_write_flush());
1278        // back-pressure is disabled
1279        assert!(!io.st().flags.is_wr_backpressure());
1280
1281        // == Terminate
1282        io.terminate();
1283        // read task is woken
1284        assert!(!io.st().write_task.is_set());
1285        // write task ready
1286        assert_eq!(
1287            lazy(|cx| ctx.poll_write_ready(cx)).await,
1288            Poll::Ready(Readiness::Terminate)
1289        );
1290        // flush returns error
1291        let Poll::Ready(Err(err)) = lazy(|cx| io.poll_flush(cx, false)).await else {
1292            panic!()
1293        };
1294        assert_eq!(err.kind(), io::ErrorKind::NotConnected);
1295        // statis returns error
1296        assert!(matches!(
1297            lazy(|cx| io.poll_status_update(cx)).await,
1298            Poll::Ready(IoStatusUpdate::PeerGone(None))
1299        ));
1300    }
1301
1302    #[ntex::test]
1303    async fn write_backpressure() {
1304        let (client, server) = IoTest::create();
1305        client.remote_buffer_cap(0);
1306
1307        let io = Io::new(
1308            server,
1309            SharedCfg::new("SRV").add(IoConfig::default().set_write_buf(16, 8, 12)),
1310        );
1311        assert!(lazy(|cx| io.poll_read_ready(cx)).await.is_pending());
1312        assert!(io.flags().is_write_paused());
1313        assert!(!io.flags().is_wr_backpressure());
1314        assert!(!io.is_wr_backpressure());
1315
1316        io.encode_slice(BIN2).unwrap();
1317        assert!(Iops::is_registered(&io));
1318        assert!(io.flags().is_wr_backpressure());
1319
1320        client.remote_buffer_cap(1024);
1321        let item = client.read().await.unwrap();
1322        assert_eq!(item, BIN2);
1323        assert!(io.flags().is_wr_backpressure());
1324        assert!(matches!(
1325            lazy(|cx| io.poll_status_update(cx)).await,
1326            Poll::Ready(IoStatusUpdate::WriteBackpressure)
1327        ));
1328        assert!(!io.flags().is_wr_backpressure());
1329        assert!(matches!(
1330            lazy(|cx| io.poll_flush(cx, false)).await,
1331            Poll::Ready(Ok(()))
1332        ));
1333        assert!(!io.flags().is_wr_backpressure());
1334    }
1335
1336    #[ntex::test]
1337    async fn shutdown_flushes_write_buf_with_read_backpressure() {
1338        // Graceful shutdown must flush the pending write buffer even if
1339        // the peer keeps sending data (read backpressure is enabled).
1340        let (client, server) = IoTest::create();
1341        // remote side does not accept any data yet, write task stalls
1342        client.remote_buffer_cap(0);
1343
1344        let io = Io::new(
1345            server,
1346            SharedCfg::new("SRV").add(
1347                IoConfig::default()
1348                    .set_read_buf(8, 4, 16)
1349                    .set_disconnect_timeout(ntex_util::time::Seconds(2)),
1350            ),
1351        );
1352
1353        // queue response data; remote is stalled so it stays in the write buffer
1354        io.encode_slice(b"response-tail").unwrap();
1355        sleep(Millis(50)).await;
1356        assert_eq!(io.st().buffer.write_buf_size(), 13);
1357
1358        // peer keeps sending, crossing the read high watermark,
1359        // read task gets paused with back-pressure enabled
1360        client.write("0123456789");
1361        sleep(Millis(50)).await;
1362        assert!(io.flags().is_read_paused());
1363        assert!(io.flags().is_rd_backpressure());
1364        assert_eq!(io.st().buffer.write_buf_size(), 13);
1365
1366        // start graceful shutdown while the write buffer is not empty
1367        io.close();
1368        sleep(Millis(50)).await;
1369
1370        // peer starts draining the connection
1371        client.remote_buffer_cap(1024);
1372
1373        // all previously queued data must be written before io stream is closed.
1374        // Without the fix graceful shutdown completes immediately (read is paused
1375        // with back-pressure), dropping the buffered write data, so the read here
1376        // returns nothing instead of the queued response tail.
1377        let data = ntex_util::time::timeout(Millis(2000), client.read())
1378            .await
1379            .expect("write buffer was dropped during shutdown")
1380            .unwrap();
1381        assert_eq!(&data[..], b"response-tail");
1382
1383        // the connection still closes gracefully afterwards (within the
1384        // disconnect timeout) instead of hanging
1385        ntex_util::time::timeout(Millis(4000), io.on_disconnect())
1386            .await
1387            .expect("io stream did not disconnect after flush");
1388    }
1389
1390    #[ntex::test]
1391    async fn shutdown() {
1392        // layer drops all unprocessed data after filter shutdown
1393        #[derive(Debug)]
1394        struct F;
1395
1396        impl FilterLayer for F {
1397            fn process_read_buf(&self, _: &FilterBuf<'_>) -> io::Result<()> {
1398                Ok(())
1399            }
1400            fn process_write_buf(&self, _: &FilterBuf<'_>) -> io::Result<()> {
1401                Ok(())
1402            }
1403        }
1404
1405        let io = Io::new(
1406            IoTest::create().0,
1407            SharedCfg::new("SRV").add(IoConfig::default().set_write_buf(8, 4, 16)),
1408        );
1409        let st = io.st();
1410        assert!(lazy(|cx| io.poll_status_update(cx)).await.is_pending());
1411        assert!(st.dispatch_task.is_set());
1412        assert!(!st.flags.is_closed());
1413        assert!(!st.flags.is_stopping_filters());
1414
1415        let ctx = IoContext::new(io.get_ref());
1416
1417        // == init shutdown
1418        io.close();
1419        assert!(!st.flags.is_closed());
1420        assert!(st.flags.is_stopping_filters());
1421        // encoding is not allowed in shutting down stage
1422        let err = io.with_write_buf(|_| 1).unwrap_err();
1423        assert_eq!(err.kind(), io::ErrorKind::Other);
1424
1425        let io = io.add_filter(F);
1426        let layer = Layer::new(F, Base::new(io.get_ref()));
1427
1428        let st = io.st();
1429        st.buffer.with_write_src(|p| p.put_slice(b"123"));
1430        assert_eq!(st.buffer.write_buf_size(), 3);
1431        let res = st.buffer.with_filter(io.as_ref(), |f| layer.shutdown(f));
1432        assert!(matches!(res, Ok(Poll::Ready(()))));
1433        assert_eq!(st.buffer.write_buf_size(), 0);
1434
1435        // == terminate
1436        ctx.stop(None);
1437        assert!(st.flags.is_closed());
1438        assert!(st.flags.is_terminated());
1439        assert!(st.flags.is_stopping_filters());
1440
1441        let err = io.with_write_buf(|_| 1).unwrap_err();
1442        assert_eq!(err.kind(), io::ErrorKind::NotConnected);
1443    }
1444}