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
22pub struct Io<F = Base>(UnsafeCell<IoRef>, marker::PhantomData<F>);
27
28#[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 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 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 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 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 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 pub fn get_ref(&self) -> IoRef {
252 self.io_ref().clone()
253 }
254
255 #[inline]
256 #[must_use]
257 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 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 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 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 pub fn boxed(self) -> IoBoxed {
308 self.seal().into()
309 }
310
311 #[inline]
312 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 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 unsafe { &mut *(Rc::as_ptr(&state.0).cast_mut()) }
332 .buffer
333 .add_layer(state.0.cfg.write_page_size());
334
335 state.0.filter.add_filter::<F, U>(nf);
337
338 let io = Io(UnsafeCell::new(state), marker::PhantomData);
339
340 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 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 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 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 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 if self.read_ready().await?.is_none() {
418 return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Disconnected"));
419 }
420 }
421 }
422
423 #[inline]
424 pub async fn read_ready(&self) -> io::Result<Option<()>> {
426 poll_fn(|cx| self.poll_read_ready(cx)).await
427 }
428
429 #[inline]
430 pub async fn read_notify(&self) -> io::Result<Option<()>> {
432 poll_fn(|cx| self.poll_read_notify(cx)).await
433 }
434
435 #[inline]
436 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 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 pub async fn flush(&self, full: bool) -> io::Result<()> {
465 poll_fn(|cx| self.poll_flush(cx, full)).await
466 }
467
468 #[inline]
469 pub async fn shutdown(&self) -> io::Result<()> {
471 poll_fn(|cx| self.poll_shutdown(cx)).await
472 }
473
474 #[inline]
475 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 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 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 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 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 pub fn poll_flush(&self, cx: &mut Context<'_>, full: bool) -> Poll<io::Result<()>> {
611 let st = self.st();
612
613 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 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 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 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 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 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 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#[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 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 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 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 ctx.update_read_status(BytesMut::copy_from_slice(b"1234567890"), Ok(10));
912
913 assert!(!io.st().dispatch_task.is_set());
915 assert!(io.st().flags.is_read_paused());
917 assert!(io.st().flags.is_read_ready());
919 assert!(io.st().flags.is_rd_backpressure());
921 assert_eq!(lazy(|cx| ctx.poll_read_ready(cx)).await, Poll::Pending);
923
924 assert_eq!(io.with_read_buf(|buf| buf.split_to(1)), b"1");
926 assert!(io.st().flags.is_read_ready());
928 assert!(io.st().flags.is_rd_backpressure());
930
931 assert!(io.st().read_task.is_set());
933
934 assert_eq!(io.with_read_buf(|buf| buf.split_to(1)), b"2");
936 assert!(io.st().flags.is_rd_backpressure());
938
939 assert_eq!(io.with_read_buf(|buf| buf.split_to(4)), b"3456");
941 assert!(!io.st().flags.is_read_paused());
943 assert!(!io.st().flags.is_read_ready());
945 assert!(!io.st().flags.is_rd_backpressure());
947 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 lazy(|cx| io.poll_dispatch(cx)).await;
956
957 ctx.update_read_status(BytesMut::copy_from_slice(b"1234"), Ok(4));
959
960 assert!(!io.st().dispatch_task.is_set());
962 assert!(io.st().flags.is_read_paused());
964 assert!(io.st().flags.is_read_ready());
966 assert!(io.st().flags.is_rd_backpressure());
968 assert_eq!(lazy(|cx| ctx.poll_read_ready(cx)).await, Poll::Pending);
970
971 assert_eq!(io.with_read_buf(|buf| buf.split_to(4)), b"7890");
973 assert!(!io.st().flags.is_rd_backpressure());
975
976 lazy(|cx| io.poll_dispatch(cx)).await;
978
979 ctx.update_read_status(BytesMut::copy_from_slice(b"567"), Ok(3));
981
982 assert!(!io.st().flags.is_read_paused());
984 assert!(io.st().flags.is_read_ready());
986 assert!(!io.st().flags.is_rd_backpressure());
988 assert_eq!(
990 lazy(|cx| ctx.poll_read_ready(cx)).await,
991 Poll::Ready(Readiness::Ready)
992 );
993
994 assert_eq!(io.with_read_buf(BytesMut::take), b"1234567");
996 assert!(!io.st().flags.is_read_paused());
998 assert!(!io.st().flags.is_read_ready());
1000 assert!(io.st().read_task.is_set());
1002
1003 io.terminate();
1005 assert!(!io.st().read_task.is_set());
1007 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 ctx.update_read_status(BytesMut::copy_from_slice(b"1"), Ok(1));
1029
1030 assert!(!io.st().dispatch_task.is_set());
1031 assert!(io.st().flags.is_read_ready());
1033 assert!(io.st().flags.is_read_notify());
1034 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 assert!(!io.st().dispatch_task.is_set());
1041 assert!(io.st().flags.is_read_ready());
1043
1044 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 assert_eq!(
1051 lazy(|cx| ctx.poll_read_ready(cx)).await,
1052 Poll::Ready(Readiness::Ready)
1053 );
1054
1055 ctx.update_read_status(BytesMut::copy_from_slice(b"2345678"), Ok(7));
1057 assert!(io.st().flags.is_rd_backpressure());
1059
1060 assert!(io.st().flags.is_read_ready());
1062 assert!(io.st().flags.is_read_notify());
1063 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 assert_eq!(lazy(|cx| ctx.poll_read_ready(cx)).await, Poll::Pending);
1069 assert!(io.st().read_task.is_set());
1071
1072 assert!(lazy(|cx| io.poll_read_notify(cx)).await.is_pending());
1074 assert!(!io.st().flags.is_rd_backpressure());
1076 assert!(!io.st().flags.is_read_ready());
1077 assert!(!io.st().flags.is_read_paused());
1078 assert!(!io.st().read_task.is_set());
1080 assert_eq!(
1082 lazy(|cx| ctx.poll_read_ready(cx)).await,
1083 Poll::Ready(Readiness::Ready)
1084 );
1085
1086 ctx.update_read_status(BytesMut::copy_from_slice(b"1"), Ok(1));
1088 assert!(!io.st().dispatch_task.is_set());
1089 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 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 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 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 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 assert!(io.st().flags.is_write_paused());
1181 assert!(io.st().flags.is_wr_send_scheduled());
1183 assert!(!io.st().flags.is_wr_backpressure());
1185 assert!(io.st().dispatch_task.is_set());
1187
1188 io.with_write_buf(|buf| buf.put_slice(b"5678")).unwrap();
1190 assert!(io.st().flags.is_wr_backpressure());
1192 assert!(!io.st().dispatch_task.is_set());
1194 assert!(io.st().write_task.is_set());
1196 assert!(matches!(
1198 lazy(|cx| io.poll_status_update(cx)).await,
1199 Poll::Ready(IoStatusUpdate::WriteBackpressure)
1200 ));
1201 assert!(lazy(|cx| io.poll_flush(cx, false)).await.is_pending());
1203 assert!(!io.st().flags.is_write_flush());
1205
1206 Iops::run();
1208 assert!(!io.st().flags.is_wr_send_scheduled());
1210 assert!(!io.st().flags.is_write_paused());
1212 assert!(!io.st().write_task.is_set());
1214 assert_eq!(
1216 lazy(|cx| ctx.poll_write_ready(cx)).await,
1217 Poll::Ready(Readiness::Ready)
1218 );
1219
1220 assert_eq!(ctx.with_write_buf(|buf| buf.split_to(4).freeze()), b"1234");
1222 assert_eq!(ctx.update_write_status(Ok(true)), IoTaskStatus::Io);
1224 assert_eq!(
1226 lazy(|cx| ctx.poll_write_ready(cx)).await,
1227 Poll::Ready(Readiness::Ready)
1228 );
1229 assert!(!io.st().flags.is_write_paused());
1231 assert!(io.st().flags.is_wr_backpressure());
1233 assert!(matches!(
1235 lazy(|cx| io.poll_status_update(cx)).await,
1236 Poll::Ready(IoStatusUpdate::WriteBackpressure)
1237 ));
1238 assert!(!io.st().flags.is_wr_backpressure());
1240 assert!(lazy(|cx| io.poll_status_update(cx)).await.is_pending());
1241 assert!(matches!(
1243 lazy(|cx| io.poll_flush(cx, false)).await,
1244 Poll::Ready(Ok(()))
1245 ));
1246
1247 io.with_write_buf(|buf| buf.put_slice(b"1234")).unwrap();
1249 assert!(lazy(|cx| io.poll_flush(cx, true)).await.is_pending());
1250 assert!(io.st().flags.is_write_flush());
1252 assert!(io.st().flags.is_wr_backpressure());
1254
1255 Iops::run();
1257 assert_eq!(ctx.with_write_buf(BytePages::freeze), b"56781234");
1258 assert!(!io.st().flags.is_wr_send_scheduled());
1260 assert_eq!(ctx.update_write_status(Ok(true)), IoTaskStatus::Pause);
1262 assert!(io.st().flags.is_write_paused());
1264 assert!(io.st().flags.is_write_flush());
1266 assert!(io.st().flags.is_wr_backpressure());
1268 assert!(!io.st().dispatch_task.is_set());
1270
1271 assert!(matches!(
1273 lazy(|cx| io.poll_flush(cx, false)).await,
1274 Poll::Ready(Ok(()))
1275 ));
1276 assert!(!io.st().flags.is_write_flush());
1278 assert!(!io.st().flags.is_wr_backpressure());
1280
1281 io.terminate();
1283 assert!(!io.st().write_task.is_set());
1285 assert_eq!(
1287 lazy(|cx| ctx.poll_write_ready(cx)).await,
1288 Poll::Ready(Readiness::Terminate)
1289 );
1290 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 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 let (client, server) = IoTest::create();
1341 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 io.encode_slice(b"response-tail").unwrap();
1355 sleep(Millis(50)).await;
1356 assert_eq!(io.st().buffer.write_buf_size(), 13);
1357
1358 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 io.close();
1368 sleep(Millis(50)).await;
1369
1370 client.remote_buffer_cap(1024);
1372
1373 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 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 #[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 io.close();
1419 assert!(!st.flags.is_closed());
1420 assert!(st.flags.is_stopping_filters());
1421 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 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}