1use std::{
4 io::{self, IoSlice},
5 marker::PhantomData,
6 mem::MaybeUninit,
7 pin::Pin,
8 sync::{Arc, Mutex, MutexGuard},
9 task::{Context, Poll, Waker},
10};
11
12use bytes::{Buf, BufMut, BytesMut};
13use futures::io::{AsyncRead, AsyncWrite};
14
15use crate::{
16 Limits,
17 fragment::Kind,
18 fragment::{Flags, FragmentHeader},
19 transport::{AnyRecv, AnySend, RecvFrame, SendFrame},
20 window::{ControlSink, SessionWindow},
21};
22
23fn lock<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
24 mutex
25 .lock()
26 .unwrap_or_else(|poisoned| poisoned.into_inner())
27}
28
29fn register_waker(slot: &mut Option<Waker>, waker: &Waker) {
30 if !slot
31 .as_ref()
32 .is_some_and(|current| current.will_wake(waker))
33 {
34 *slot = Some(waker.clone());
35 }
36}
37
38fn wake(waker: Option<Waker>) {
39 if let Some(waker) = waker {
40 waker.wake();
41 }
42}
43
44#[derive(Clone, Copy, Debug, Eq, PartialEq)]
45pub(crate) enum SendAction {
46 Fragment,
47 Finish,
48 Abort,
49}
50
51#[derive(Clone, Copy, Debug, Eq, PartialEq)]
52enum SendState {
53 Idle,
55 Demand,
58 Granted,
62 Staging,
67 Fragment,
70 FragmentDemand,
73 Finish,
74 FragmentFinish,
75 Abort,
83 Failed,
88}
89
90pub(crate) struct SendShared {
91 token: Option<AnySend<'static>>,
92 kind: Kind,
93 id: u64,
94 max_fragment_size: usize,
95 copy_threshold: usize,
96 written: usize,
100 reserved: usize,
106 session: Arc<SessionWindow>,
111 buffer: BytesMut,
114 state: SendState,
115 error: Option<(io::ErrorKind, String)>,
120 started: bool,
132 writer_waker: Option<Waker>,
133 driver_waker: Option<Waker>,
134}
135
136impl SendShared {
137 pub(crate) fn new(
138 kind: Kind,
139 id: u64,
140 limits: &Limits,
141 session: Arc<SessionWindow>,
142 ) -> Arc<Mutex<Self>> {
143 Arc::new(Mutex::new(Self {
144 token: None,
145 kind,
146 id,
147 max_fragment_size: limits.max_fragment_size,
148 copy_threshold: limits.trailer_send_copy_threshold,
149 written: 0,
150 reserved: 0,
151 session,
152 buffer: BytesMut::new(),
153 state: SendState::Idle,
154 error: None,
155 started: false,
156 writer_waker: None,
157 driver_waker: None,
158 }))
159 }
160
161 pub(crate) fn start(shared: &Mutex<Self>) {
164 let mut inner = lock(shared);
165 if inner.started {
166 return;
167 }
168 inner.started = true;
169 let writer = inner.writer_waker.take();
170 drop(inner);
171 wake(writer);
172 }
173
174 pub(crate) fn poll_action(shared: &Mutex<Self>, cx: &mut Context<'_>) -> Poll<SendAction> {
175 let mut inner = lock(shared);
176 inner.driver_waker.take();
177 match inner.state {
178 SendState::Demand
179 | SendState::Fragment
180 | SendState::FragmentDemand
181 | SendState::FragmentFinish => Poll::Ready(SendAction::Fragment),
182 SendState::Finish => Poll::Ready(SendAction::Finish),
183 SendState::Abort => Poll::Ready(SendAction::Abort),
184 SendState::Idle | SendState::Granted | SendState::Staging => {
185 register_waker(&mut inner.driver_waker, cx.waker());
186 Poll::Pending
187 }
188 SendState::Failed => {
189 register_waker(&mut inner.driver_waker, cx.waker());
196 Poll::Pending
197 }
198 }
199 }
200
201 pub(crate) unsafe fn grant<'a>(
211 shared: &Arc<Mutex<Self>>,
212 token: AnySend<'a>,
213 max_fragment_size: usize,
214 ) -> SendLease<'a> {
215 let token = unsafe { std::mem::transmute::<AnySend<'a>, AnySend<'static>>(token) };
218 let mut inner = lock(shared);
219 assert!(inner.token.is_none());
220 if inner.buffer.is_empty() {
221 inner.state = SendState::Granted;
222 }
223 inner.token = Some(token);
224 inner.max_fragment_size = max_fragment_size;
225 let writer = inner.writer_waker.take();
226 drop(inner);
227 wake(writer);
228 SendLease {
229 shared: shared.clone(),
230 armed: true,
231 _borrow: PhantomData,
232 }
233 }
234
235 pub(crate) async fn wait_fragment(shared: &Mutex<Self>) -> io::Result<SendAction> {
250 let mut needed_drain = false;
251 let mut yielded = false;
252 loop {
253 let outcome = std::future::poll_fn(|cx| {
254 let mut inner = lock(shared);
255 inner.driver_waker.take();
256 if inner.state == SendState::Failed {
257 let (kind, message) = inner.error.clone().expect("error set for Failed");
258 return Poll::Ready(Err(io::Error::new(kind, message)));
259 }
260 if !inner.buffer.is_empty() {
261 needed_drain = true;
262 let result = poll_flush_buffer(&mut inner, cx);
263 match result {
264 Poll::Pending => return Poll::Pending,
265 Poll::Ready(Err(error)) => {
266 inner.state = SendState::Failed;
267 inner.error = Some((error.kind(), error.to_string()));
268 let writer = inner.writer_waker.take();
269 drop(inner);
270 wake(writer);
271 return Poll::Ready(Err(error));
272 }
273 Poll::Ready(Ok(())) => {}
274 }
275 }
276 match inner.state {
277 SendState::Fragment | SendState::FragmentDemand | SendState::FragmentFinish => {
278 Poll::Ready(Ok(Some(SendAction::Fragment)))
279 }
280 SendState::Finish => Poll::Ready(Ok(Some(SendAction::Finish))),
281 SendState::Abort => Poll::Ready(Ok(Some(SendAction::Abort))),
282 SendState::Granted if !yielded => {
283 Poll::Ready(Ok(None))
286 }
287 SendState::Granted => {
288 inner.state = SendState::Staging;
289 register_waker(&mut inner.driver_waker, cx.waker());
290 Poll::Pending
291 }
292 SendState::Idle | SendState::Demand | SendState::Staging => {
293 register_waker(&mut inner.driver_waker, cx.waker());
298 Poll::Pending
299 }
300 SendState::Failed => unreachable!("handled above"),
301 }
302 })
303 .await?;
304 match outcome {
305 Some(result) => return Ok(result),
306 None => {
307 yielded = true;
308 tokio::task::yield_now().await;
309 }
310 }
311 }
312 }
313
314 fn poll_flush(shared: &Mutex<Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
315 let mut inner = lock(shared);
316 inner.writer_waker.take();
317 match inner.state {
318 SendState::Abort | SendState::Failed => {
319 let (kind, message) = inner.error.clone().expect("error set for Abort/Failed");
320 Poll::Ready(Err(io::Error::new(kind, message)))
321 }
322 _ if !inner.buffer.is_empty() => {
323 register_waker(&mut inner.writer_waker, cx.waker());
324 Poll::Pending
325 }
326 _ => Poll::Ready(Ok(())),
327 }
328 }
329
330 fn finish(shared: &Mutex<Self>) {
331 let mut inner = lock(shared);
332 inner.state = match inner.state {
333 SendState::Fragment | SendState::FragmentDemand => SendState::FragmentFinish,
334 SendState::FragmentFinish => SendState::FragmentFinish,
335 aborted @ (SendState::Abort | SendState::Failed) => aborted,
340 _ => SendState::Finish,
341 };
342 let driver = inner.driver_waker.take();
343 let writer = inner.writer_waker.take();
344 drop(inner);
345 wake(driver);
346 wake(writer);
347 }
348
349 fn abandon(shared: &Mutex<Self>) {
351 Self::set_aborted(shared, io::ErrorKind::BrokenPipe, "trailer is closed");
352 }
353
354 pub(crate) fn discard(shared: &Mutex<Self>) {
365 Self::set_aborted(
366 shared,
367 io::ErrorKind::BrokenPipe,
368 "trailer discarded by peer",
369 );
370 }
371
372 fn set_aborted(shared: &Mutex<Self>, kind: io::ErrorKind, message: &str) {
373 let mut inner = lock(shared);
374 if !matches!(
375 inner.state,
376 SendState::Finish | SendState::FragmentFinish | SendState::Failed
377 ) {
378 inner.state = SendState::Abort;
379 inner.error = Some((kind, message.into()));
380 }
381 let driver = inner.driver_waker.take();
382 let writer = inner.writer_waker.take();
383 let session = inner.session.clone();
384 let id = inner.id;
385 drop(inner);
386 session.settle(id);
391 wake(driver);
392 wake(writer);
393 }
394
395 fn reserve(&mut self, want: usize) -> usize {
403 let granted = self.session.debit_up_to(self.id, want);
404 self.written += granted;
405 granted
406 }
407
408 fn unreserve(&mut self, len: usize) {
410 if len == 0 {
411 return;
412 }
413 self.written -= len;
414 self.session.refund(self.id, len);
415 }
416}
417
418const RESERVED_HELD: &str = "Granted/Staging is only reached from Demand, which reserves";
425
426fn park_for_credit(shared: &mut SendShared, cx: &mut Context<'_>) {
435 register_waker(&mut shared.writer_waker, cx.waker());
438 shared.session.park(cx.waker());
439}
440
441fn poll_flush_buffer(shared: &mut SendShared, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
442 let Some(token) = shared.token.as_mut() else {
443 return Poll::Ready(Err(io::Error::other("send lease has no frame token")));
444 };
445 loop {
446 if shared.buffer.is_empty() {
447 break Poll::Ready(Ok(()));
448 }
449 match token.poll_write_once(cx, &shared.buffer) {
450 Poll::Ready(Ok(0)) => break Poll::Ready(Err(io::ErrorKind::WriteZero.into())),
451 Poll::Ready(Ok(n)) => shared.buffer.advance(n),
452 Poll::Ready(Err(error)) => break Poll::Ready(Err(error)),
453 Poll::Pending => break Poll::Pending,
454 }
455 }
456}
457
458pub(crate) struct SendLease<'a> {
459 shared: Arc<Mutex<SendShared>>,
460 armed: bool,
461 _borrow: PhantomData<&'a mut ()>,
462}
463
464impl SendLease<'_> {
465 pub(crate) fn complete(mut self) {
466 let mut shared = lock(&self.shared);
467 shared.token.take();
468 shared.buffer.clear();
469 shared.state = match shared.state {
470 SendState::Fragment | SendState::FragmentDemand => SendState::Idle,
471 SendState::FragmentFinish => SendState::Finish,
472 state => state,
473 };
474 let writer = shared.writer_waker.take();
475 self.armed = false;
476 drop(shared);
477 wake(writer);
478 }
479}
480
481impl Drop for SendLease<'_> {
482 fn drop(&mut self) {
483 if !self.armed {
484 return;
485 }
486 let mut shared = lock(&self.shared);
487 shared.token.take();
488 shared.buffer = BytesMut::new();
489 if shared.state != SendState::Failed {
494 shared.state = SendState::Abort;
495 if shared.error.is_none() {
496 shared.error = Some((
497 io::ErrorKind::ConnectionAborted,
498 "send grant was revoked".into(),
499 ));
500 }
501 }
502 let writer = shared.writer_waker.take();
503 shared.driver_waker.take();
504 drop(shared);
505 wake(writer);
506 }
507}
508
509pub struct TrailerSend<T> {
515 shared: Arc<Mutex<SendShared>>,
516 completion: Option<T>,
517}
518
519impl<T> TrailerSend<T> {
520 pub(crate) fn new(shared: Arc<Mutex<SendShared>>, completion: T) -> Self {
521 Self {
522 shared,
523 completion: Some(completion),
524 }
525 }
526
527 pub fn finish(mut self) -> T {
533 SendShared::finish(&self.shared);
534 self.completion.take().unwrap()
535 }
536}
537
538impl<T: Unpin> AsyncWrite for TrailerSend<T> {
539 fn poll_write(
540 self: Pin<&mut Self>,
541 cx: &mut Context<'_>,
542 buf: &[u8],
543 ) -> Poll<io::Result<usize>> {
544 if buf.is_empty() {
545 return Poll::Ready(Ok(0));
546 }
547 let this = self.get_mut();
548 let mut inner = lock(&this.shared);
549 inner.writer_waker.take();
550 match inner.state {
551 SendState::Finish | SendState::FragmentFinish => Poll::Ready(Err(io::Error::new(
552 io::ErrorKind::BrokenPipe,
553 "trailer is closed",
554 ))),
555 SendState::Abort | SendState::Failed => {
556 let (kind, message) = inner.error.clone().expect("error set for Abort/Failed");
557 Poll::Ready(Err(io::Error::new(kind, message)))
558 }
559 SendState::Fragment | SendState::FragmentDemand => {
560 inner.state = SendState::FragmentDemand;
566 register_waker(&mut inner.writer_waker, cx.waker());
567 let driver = inner.driver_waker.take();
568 drop(inner);
569 wake(driver);
570 Poll::Pending
571 }
572 SendState::Idle => {
573 if !inner.started {
577 register_waker(&mut inner.writer_waker, cx.waker());
578 return Poll::Pending;
579 }
580 let want = buf.len().min(inner.max_fragment_size.max(1));
589 let len = inner.reserve(want);
590 if len == 0 {
591 park_for_credit(&mut inner, cx);
592 return Poll::Pending;
593 }
594 if len <= inner.copy_threshold {
595 FragmentHeader {
596 flags: Flags::NONE,
597 kind: inner.kind,
598 id: inner.id,
599 payload_len: len,
600 }
601 .encode_into(&mut inner.buffer);
602 inner.buffer.extend_from_slice(&buf[..len]);
603 inner.state = SendState::Fragment;
604 let driver = inner.driver_waker.take();
605 drop(inner);
606 wake(driver);
607 return Poll::Ready(Ok(len));
608 }
609 inner.reserved = len;
612 inner.state = SendState::Demand;
613 register_waker(&mut inner.writer_waker, cx.waker());
614 let driver = inner.driver_waker.take();
615 drop(inner);
616 wake(driver);
617 Poll::Pending
618 }
619 SendState::Demand => {
620 register_waker(&mut inner.writer_waker, cx.waker());
621 Poll::Pending
622 }
623 SendState::Staging => {
624 debug_assert!(inner.reserved > 0, "{RESERVED_HELD}");
628 let len = buf
629 .len()
630 .min(inner.max_fragment_size.max(1))
631 .min(inner.reserved);
632 let unused = inner.reserved - len;
633 inner.unreserve(unused);
634 inner.reserved = 0;
635 FragmentHeader {
636 flags: Flags::NONE,
637 kind: inner.kind,
638 id: inner.id,
639 payload_len: len,
640 }
641 .encode_into(&mut inner.buffer);
642 inner.buffer.extend_from_slice(&buf[..len]);
643 inner.state = SendState::Fragment;
644 let driver = inner.driver_waker.take();
645 drop(inner);
646 wake(driver);
647 Poll::Ready(Ok(len))
648 }
649 SendState::Granted => {
650 debug_assert!(inner.reserved > 0, "{RESERVED_HELD}");
653 let len = buf
654 .len()
655 .min(inner.max_fragment_size.max(1))
656 .min(inner.reserved);
657 let unused = inner.reserved - len;
662 inner.unreserve(unused);
663 inner.reserved = len;
664 FragmentHeader {
665 flags: Flags::NONE,
666 kind: inner.kind,
667 id: inner.id,
668 payload_len: len,
669 }
670 .encode_into(&mut inner.buffer);
671
672 let header_len = inner.buffer.len();
673 let write_result = {
674 let shared = &mut *inner;
675 let bufs = [IoSlice::new(&shared.buffer), IoSlice::new(&buf[..len])];
676 shared
677 .token
678 .as_mut()
679 .expect("installed send token")
680 .poll_write_vectored_once(cx, &bufs)
681 };
682 match write_result {
683 Poll::Ready(Ok(0)) => {
684 let error = io::Error::from(io::ErrorKind::WriteZero);
685 inner.buffer.clear();
686 inner.unreserve(len);
687 inner.reserved = 0;
688 inner.state = SendState::Failed;
689 inner.error = Some((error.kind(), error.to_string()));
690 let driver = inner.driver_waker.take();
691 drop(inner);
692 wake(driver);
693 Poll::Ready(Err(error))
694 }
695 Poll::Ready(Ok(n)) => {
696 debug_assert!(n <= header_len + len);
697 if n < header_len {
698 inner.buffer.advance(n);
699 inner.buffer.extend_from_slice(&buf[..len]);
700 } else {
701 inner.buffer.clear();
702 inner.buffer.extend_from_slice(&buf[n - header_len..len]);
703 }
704 inner.reserved = 0;
705 inner.state = SendState::Fragment;
706 let driver = inner.driver_waker.take();
707 drop(inner);
708 wake(driver);
709 Poll::Ready(Ok(len))
710 }
711 Poll::Ready(Err(error)) => {
712 inner.buffer.clear();
713 inner.unreserve(len);
714 inner.reserved = 0;
715 inner.state = SendState::Failed;
716 inner.error = Some((error.kind(), error.to_string()));
717 let driver = inner.driver_waker.take();
718 drop(inner);
719 wake(driver);
720 Poll::Ready(Err(error))
721 }
722 Poll::Pending => {
723 inner.buffer.clear();
728 Poll::Pending
729 }
730 }
731 }
732 }
733 }
734
735 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
736 SendShared::poll_flush(&self.get_mut().shared, cx)
737 }
738
739 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
740 let this = self.get_mut();
741 SendShared::finish(&this.shared);
742 SendShared::poll_flush(&this.shared, cx)
743 }
744}
745
746impl<T> Drop for TrailerSend<T> {
747 fn drop(&mut self) {
748 if self.completion.is_some() {
749 SendShared::abandon(&self.shared);
750 }
751 }
752}
753
754#[derive(Clone, Copy, Debug, Eq, PartialEq)]
755enum RecvState {
756 Idle,
757 Demand,
760 Reading,
764 Unclaimed,
771 Draining,
777 Fragment,
778 FragmentDemand,
781 Eof,
782 Discard,
783 Failed,
787}
788
789pub(crate) struct RecvShared {
790 token: Option<AnyRecv<'static>>,
791 remaining: usize,
792 stage: BytesMut,
797 copy_threshold: usize,
798 demand_copy_threshold: usize,
799 state: RecvState,
800 error: Option<(io::ErrorKind, String)>,
802 reader_waker: Option<Waker>,
803 driver_waker: Option<Waker>,
804 credit_interval: usize,
808 received: usize,
812 retired: usize,
813 pending: usize,
815 auto_release: bool,
818 sink: Arc<dyn ControlSink>,
821 id: u64,
823 session: Arc<SessionWindow>,
826}
827
828impl RecvShared {
829 pub(crate) fn new(
830 copy_threshold: usize,
831 demand_copy_threshold: usize,
832 credit_interval: usize,
833 session: Arc<SessionWindow>,
834 id: u64,
835 sink: Arc<dyn ControlSink>,
836 ) -> Arc<Mutex<Self>> {
837 Arc::new(Mutex::new(Self {
838 token: None,
839 remaining: 0,
840 stage: BytesMut::new(),
841 copy_threshold,
842 demand_copy_threshold,
843 state: RecvState::Idle,
844 error: None,
845 reader_waker: None,
846 driver_waker: None,
847 credit_interval,
848 received: 0,
849 retired: 0,
850 pending: 0,
851 auto_release: true,
852 sink,
853 id,
854 session,
855 }))
856 }
857
858 pub(crate) fn accept_bytes(shared: &Mutex<Self>, len: usize) -> Option<&'static str> {
867 let mut inner = lock(shared);
868 if inner.state == RecvState::Discard {
872 return None;
873 }
874 if !inner.session.accept_bytes(inner.id, len) {
875 return Some("exceeded the session trailer credit window");
876 }
877 inner.received += len;
878 None
879 }
880
881 fn retire(inner: &mut Self, len: usize) -> Option<(Arc<dyn ControlSink>, u64, u32)> {
892 if inner.state == RecvState::Discard {
897 return None;
898 }
899 inner.pending += len;
900 inner.retired += len;
901 if inner.pending * 2 < inner.credit_interval && !Self::must_flush(inner) {
902 return None;
903 }
904 Self::flush(inner)
905 }
906
907 fn must_flush(inner: &Self) -> bool {
921 inner.state == RecvState::Eof || inner.session.is_exhausted() || Self::is_stalled(inner)
922 }
923
924 fn is_stalled(inner: &Self) -> bool {
927 matches!(inner.state, RecvState::Demand | RecvState::FragmentDemand)
928 && inner.stage.is_empty()
929 }
930
931 fn flush(inner: &mut Self) -> Option<(Arc<dyn ControlSink>, u64, u32)> {
933 if inner.state == RecvState::Discard || inner.pending == 0 {
934 return None;
935 }
936 let count = u32::try_from(inner.pending).unwrap_or(u32::MAX) as usize;
937 inner.pending -= count;
938 inner.session.refund(inner.id, count);
939 Some((inner.sink.clone(), inner.id, count as u32))
940 }
941
942 fn retire_and_emit(shared: &Mutex<Self>, len: usize) {
945 let mut inner = lock(shared);
946 if !inner.auto_release {
947 return;
948 }
949 let emit = Self::retire(&mut inner, len);
950 drop(inner);
951 if let Some((sink, id, count)) = emit {
952 sink.credit(id, count);
953 }
954 }
955
956 pub(crate) unsafe fn grant<'a>(
959 shared: &Arc<Mutex<Self>>,
960 token: AnyRecv<'a>,
961 remaining: usize,
962 ) -> RecvLease<'a> {
963 let token = unsafe { std::mem::transmute::<AnyRecv<'a>, AnyRecv<'static>>(token) };
966 let mut inner = lock(shared);
967 assert!(inner.token.is_none());
968 if inner.state != RecvState::Discard {
969 let demanded = inner.state == RecvState::Demand;
970 let copy_threshold = if demanded {
971 inner.demand_copy_threshold
972 } else {
973 inner.copy_threshold
974 };
975 inner.state = if remaining == 0 {
976 if demanded {
977 RecvState::FragmentDemand
978 } else {
979 RecvState::Fragment
980 }
981 } else if remaining <= copy_threshold {
982 RecvState::Draining
983 } else {
984 RecvState::Unclaimed
985 };
986 }
987 inner.token = Some(token);
988 inner.remaining = remaining;
989 let reader = if inner.state == RecvState::Unclaimed {
990 inner.reader_waker.take()
991 } else {
992 None
993 };
994 drop(inner);
995 wake(reader);
996 RecvLease {
997 shared: shared.clone(),
998 armed: true,
999 _borrow: PhantomData,
1000 }
1001 }
1002
1003 pub(crate) async fn wait_fragment(shared: &Mutex<Self>) -> io::Result<bool> {
1014 let mut grace_given = false;
1019 std::future::poll_fn(|cx| {
1020 let mut inner = lock(shared);
1021 inner.driver_waker.take();
1022 loop {
1023 match inner.state {
1024 RecvState::Fragment | RecvState::FragmentDemand => {
1025 return Poll::Ready(Ok(false));
1026 }
1027 RecvState::Discard if inner.remaining == 0 => return Poll::Ready(Ok(true)),
1028 RecvState::Draining | RecvState::Discard => {}
1029 RecvState::Reading => {
1030 register_waker(&mut inner.driver_waker, cx.waker());
1033 return Poll::Pending;
1034 }
1035 RecvState::Unclaimed => {
1036 if !grace_given {
1037 grace_given = true;
1045 cx.waker().wake_by_ref();
1046 return Poll::Pending;
1047 }
1048 inner.state = RecvState::Draining;
1049 }
1050 RecvState::Idle | RecvState::Demand | RecvState::Eof => {
1051 register_waker(&mut inner.driver_waker, cx.waker());
1052 return Poll::Pending;
1053 }
1054 RecvState::Failed => {
1055 register_waker(&mut inner.driver_waker, cx.waker());
1061 return Poll::Pending;
1062 }
1063 }
1064 let discard = inner.state == RecvState::Discard;
1065 let result = if discard {
1066 let mut sink = [0u8; 8192];
1067 let n = inner.remaining.min(sink.len());
1068 let mut dest = &mut sink[..n];
1069 inner
1070 .token
1071 .as_mut()
1072 .expect("installed receive token")
1073 .poll_read_once(cx, &mut dest)
1074 } else {
1075 let remaining = inner.remaining;
1076 inner.stage.reserve(remaining);
1077 let RecvShared { token, stage, .. } = &mut *inner;
1078 let mut limited = stage.limit(remaining);
1085 token
1086 .as_mut()
1087 .expect("installed receive token")
1088 .poll_read_once(cx, &mut limited)
1089 };
1090 match result {
1091 Poll::Ready(Ok(0)) => {
1092 return Poll::Ready(Err(io::ErrorKind::UnexpectedEof.into()));
1093 }
1094 Poll::Ready(Ok(n)) => {
1095 inner.remaining -= n;
1096 if inner.remaining == 0 && inner.state == RecvState::Draining {
1097 inner.state = RecvState::Fragment;
1098 }
1099 if !discard {
1100 let reader = inner.reader_waker.take();
1101 wake(reader);
1102 }
1103 }
1106 Poll::Ready(Err(error)) => return Poll::Ready(Err(error)),
1107 Poll::Pending => {
1108 register_waker(&mut inner.driver_waker, cx.waker());
1109 return Poll::Pending;
1110 }
1111 }
1112 }
1113 })
1114 .await
1115 }
1116
1117 pub(crate) fn finish(shared: &Mutex<Self>) {
1129 let mut inner = lock(shared);
1130 inner.state = RecvState::Eof;
1131 let emit = Self::retire(&mut inner, 0);
1133 let reader = inner.reader_waker.take();
1134 drop(inner);
1135 wake(reader);
1136 if let Some((sink, id, count)) = emit {
1137 sink.credit(id, count);
1138 }
1139 }
1140
1141 pub(crate) fn fail(shared: &Mutex<Self>, error: io::Error) {
1142 let mut inner = lock(shared);
1143 inner.state = RecvState::Failed;
1144 inner.error = Some((error.kind(), error.to_string()));
1145 let reader = inner.reader_waker.take();
1146 drop(inner);
1147 wake(reader);
1148 }
1149
1150 pub(crate) fn discard(shared: &Mutex<Self>) {
1164 let mut inner = lock(shared);
1165 if inner.state == RecvState::Discard {
1169 return;
1170 }
1171 let ended = inner.state == RecvState::Eof;
1175 if !matches!(inner.state, RecvState::Eof | RecvState::Failed) {
1176 inner.state = RecvState::Discard;
1177 }
1178 let driver = inner.driver_waker.take();
1179 let notify = (!ended).then(|| (inner.sink.clone(), inner.id));
1180 inner.pending = 0;
1184 inner.retired = inner.received;
1185 let session = inner.session.clone();
1186 let id = inner.id;
1187 drop(inner);
1188 session.settle(id);
1189 wake(driver);
1190 if let Some((sink, id)) = notify {
1191 sink.discard(id);
1192 }
1193 }
1194}
1195
1196pub(crate) struct RecvLease<'a> {
1197 shared: Arc<Mutex<RecvShared>>,
1198 armed: bool,
1199 _borrow: PhantomData<&'a mut ()>,
1200}
1201
1202impl RecvLease<'_> {
1203 pub(crate) fn complete(mut self) {
1204 let mut shared = lock(&self.shared);
1205 shared.token.take();
1206 shared.remaining = 0;
1207 shared.state = match shared.state {
1208 RecvState::Fragment => RecvState::Idle,
1209 RecvState::FragmentDemand => RecvState::Demand,
1210 state => state,
1211 };
1212 self.armed = false;
1213 }
1214}
1215
1216impl Drop for RecvLease<'_> {
1217 fn drop(&mut self) {
1218 if !self.armed {
1219 return;
1220 }
1221 let mut shared = lock(&self.shared);
1222 shared.token.take();
1223 shared.remaining = 0;
1224 shared.state = RecvState::Failed;
1228 if shared.error.is_none() {
1229 shared.error = Some((
1230 io::ErrorKind::ConnectionAborted,
1231 "receive grant was revoked".into(),
1232 ));
1233 }
1234 let reader = shared.reader_waker.take();
1235 shared.driver_waker.take();
1236 drop(shared);
1237 wake(reader);
1238 }
1239}
1240
1241pub struct TrailerRecv {
1243 pub(crate) shared: Arc<Mutex<RecvShared>>,
1244}
1245
1246impl TrailerRecv {
1247 pub(crate) fn new(shared: Arc<Mutex<RecvShared>>) -> Self {
1248 Self { shared }
1249 }
1250
1251 pub(crate) fn set_manual_credit(&mut self) {
1259 let mut inner = lock(&self.shared);
1260 debug_assert!(
1261 inner.retired == 0,
1262 "manual credit must be selected before the first read"
1263 );
1264 inner.auto_release = false;
1265 }
1266
1267 pub fn release(&mut self, n: usize) {
1287 let mut inner = lock(&self.shared);
1288 debug_assert!(
1289 !inner.auto_release,
1290 "release requires a manual-credit trailer; credit is returned on read otherwise"
1291 );
1292 debug_assert!(
1293 inner.retired + n <= inner.received,
1294 "released more trailer credit than was delivered"
1295 );
1296 if n == 0 {
1297 return;
1298 }
1299 let emit = RecvShared::retire(&mut inner, n);
1300 drop(inner);
1301 if let Some((sink, id, count)) = emit {
1302 sink.credit(id, count);
1303 }
1304 }
1305}
1306
1307impl TrailerRecv {
1308 pub fn poll_read_uninit(
1314 &mut self,
1315 cx: &mut Context<'_>,
1316 mut buf: &mut [MaybeUninit<u8>],
1317 ) -> Poll<io::Result<usize>> {
1318 if buf.is_empty() {
1319 return Poll::Ready(Ok(0));
1320 }
1321 let mut inner = lock(&self.shared);
1322 inner.reader_waker.take();
1323 if !inner.stage.is_empty() {
1338 let n = buf.len().min(inner.stage.len());
1339 buf.put_slice(&inner.stage[..n]);
1340 let _ = inner.stage.split_to(n);
1341 drop(inner);
1346 RecvShared::retire_and_emit(&self.shared, n);
1347 return Poll::Ready(Ok(n));
1348 }
1349 match inner.state {
1350 RecvState::Failed => {
1351 let (kind, message) = inner.error.clone().expect("error set for Failed");
1352 Poll::Ready(Err(io::Error::new(kind, message)))
1353 }
1354 RecvState::Eof => Poll::Ready(Ok(0)),
1355 RecvState::Idle | RecvState::Fragment => {
1356 inner.state = if inner.state == RecvState::Idle {
1357 RecvState::Demand
1358 } else {
1359 RecvState::FragmentDemand
1360 };
1361 register_waker(&mut inner.reader_waker, cx.waker());
1362 let emit = RecvShared::flush(&mut inner);
1371 drop(inner);
1372 if let Some((sink, id, count)) = emit {
1373 sink.credit(id, count);
1374 }
1375 Poll::Pending
1376 }
1377 RecvState::Demand | RecvState::FragmentDemand => {
1378 register_waker(&mut inner.reader_waker, cx.waker());
1379 Poll::Pending
1380 }
1381 RecvState::Draining | RecvState::Discard => {
1382 register_waker(&mut inner.reader_waker, cx.waker());
1386 Poll::Pending
1387 }
1388 RecvState::Reading | RecvState::Unclaimed => {
1389 let mut limited = (&mut buf).limit(inner.remaining);
1393 let result = inner
1394 .token
1395 .as_mut()
1396 .expect("installed receive token")
1397 .poll_read_once(cx, &mut limited);
1398 match result {
1399 Poll::Ready(Ok(0)) => Poll::Ready(Err(io::ErrorKind::UnexpectedEof.into())),
1400 Poll::Ready(Ok(n)) => {
1401 inner.remaining -= n;
1402 if inner.remaining == 0 {
1403 inner.state = RecvState::Fragment;
1404 } else {
1405 inner.state = RecvState::Draining;
1424 }
1425 let driver = inner.driver_waker.take();
1426 drop(inner);
1427 wake(driver);
1428 RecvShared::retire_and_emit(&self.shared, n);
1430 Poll::Ready(Ok(n))
1431 }
1432 Poll::Ready(Err(error)) => Poll::Ready(Err(error)),
1433 Poll::Pending => {
1434 inner.state = RecvState::Reading;
1439 Poll::Pending
1440 }
1441 }
1442 }
1443 }
1444 }
1445}
1446
1447impl AsyncRead for TrailerRecv {
1448 fn poll_read(
1449 self: Pin<&mut Self>,
1450 cx: &mut Context<'_>,
1451 buf: &mut [u8],
1452 ) -> Poll<io::Result<usize>> {
1453 let buf = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };
1455 self.get_mut().poll_read_uninit(cx, buf)
1456 }
1457}
1458
1459impl Drop for TrailerRecv {
1460 fn drop(&mut self) {
1461 RecvShared::discard(&self.shared);
1462 }
1463}
1464
1465#[cfg(test)]
1466mod tests {
1467 use super::*;
1468 use crate::transport::{AnyReceiver, AnySender, Receiver, Sender, generic};
1469
1470 fn unbounded_limits() -> Limits {
1473 Limits {
1474 trailer_session_window: usize::MAX,
1475 ..zero_copy_limits()
1476 }
1477 }
1478
1479 fn zero_copy_limits() -> Limits {
1483 Limits {
1484 trailer_send_copy_threshold: 0,
1485 ..Limits::default()
1486 }
1487 }
1488
1489 fn demand<T: Unpin>(trailer: &mut TrailerSend<T>, buf: &[u8]) {
1494 let mut cx = Context::from_waker(Waker::noop());
1495 assert!(
1496 Pin::new(trailer).poll_write(&mut cx, buf).is_pending(),
1497 "a write past the copy threshold must demand a token"
1498 );
1499 }
1500
1501 fn send_shared(limits: Limits) -> Arc<Mutex<SendShared>> {
1502 send_shared_id(1, limits)
1503 }
1504
1505 fn send_shared_id(id: u64, limits: Limits) -> Arc<Mutex<SendShared>> {
1506 let session = Arc::new(SessionWindow::new(limits.trailer_session_window));
1507 let shared = SendShared::new(Kind::Request, id, &limits, session);
1508 SendShared::start(&shared);
1511 shared
1512 }
1513
1514 #[derive(Default)]
1517 struct RecordingSink {
1518 credits: Mutex<Vec<(u64, u32)>>,
1519 discards: Mutex<Vec<u64>>,
1520 }
1521
1522 impl ControlSink for Arc<RecordingSink> {
1523 fn payload_credit(&self, _count: u32) {
1524 unreachable!("trailer tests never release payload quota")
1525 }
1526
1527 fn credit(&self, id: u64, count: u32) {
1528 lock(&self.credits).push((id, count));
1529 }
1530
1531 fn discard(&self, id: u64) {
1532 lock(&self.discards).push(id);
1533 }
1534 }
1535
1536 fn recv_shared(limits: Limits) -> (Arc<Mutex<RecvShared>>, Arc<RecordingSink>) {
1537 let session = Arc::new(SessionWindow::new(limits.trailer_session_window));
1538 let sink = Arc::new(RecordingSink::default());
1539 let shared = RecvShared::new(
1540 limits.trailer_recv_copy_threshold,
1541 limits.trailer_recv_demand_copy_threshold,
1542 limits.trailer_credit_interval,
1543 session,
1544 7,
1545 Arc::new(sink.clone()),
1546 );
1547 (shared, sink)
1548 }
1549
1550 fn poll_read_once(trailer: &mut TrailerRecv, output: &mut [u8]) -> Poll<io::Result<usize>> {
1551 let mut cx = Context::from_waker(Waker::noop());
1552 Pin::new(trailer).poll_read(&mut cx, output)
1553 }
1554
1555 struct CappedSink {
1556 bytes: Arc<Mutex<Vec<u8>>>,
1557 max_write: usize,
1558 }
1559
1560 impl AsyncWrite for CappedSink {
1561 fn poll_write(
1562 self: Pin<&mut Self>,
1563 _cx: &mut Context<'_>,
1564 buf: &[u8],
1565 ) -> Poll<io::Result<usize>> {
1566 let len = buf.len().min(self.max_write);
1567 lock(&self.bytes).extend_from_slice(&buf[..len]);
1568 Poll::Ready(Ok(len))
1569 }
1570
1571 fn poll_write_vectored(
1572 self: Pin<&mut Self>,
1573 _cx: &mut Context<'_>,
1574 bufs: &[IoSlice<'_>],
1575 ) -> Poll<io::Result<usize>> {
1576 let mut remaining = self.max_write;
1577 let mut written = 0;
1578 let mut output = lock(&self.bytes);
1579 for buf in bufs {
1580 let len = buf.len().min(remaining);
1581 output.extend_from_slice(&buf[..len]);
1582 written += len;
1583 remaining -= len;
1584 if remaining == 0 {
1585 break;
1586 }
1587 }
1588 Poll::Ready(Ok(written))
1589 }
1590
1591 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
1592 Poll::Ready(Ok(()))
1593 }
1594
1595 fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
1596 Poll::Ready(Ok(()))
1597 }
1598 }
1599
1600 #[test]
1601 fn small_send_stages_without_a_grant_and_large_send_demands_one() {
1602 let limits = Limits {
1603 max_fragment_size: 8,
1604 trailer_send_copy_threshold: 4,
1605 ..Limits::default()
1606 };
1607
1608 let small_shared = send_shared(limits);
1609 let mut small = TrailerSend::new(small_shared.clone(), ());
1610 let mut cx = Context::from_waker(Waker::noop());
1611 assert!(matches!(
1612 Pin::new(&mut small).poll_write(&mut cx, b"data"),
1613 Poll::Ready(Ok(4))
1614 ));
1615 let header = FragmentHeader {
1616 flags: Flags::NONE,
1617 kind: Kind::Request,
1618 id: 1,
1619 payload_len: 4,
1620 }
1621 .encode();
1622 assert_eq!(
1623 &small_shared.lock().unwrap().buffer[..],
1624 [&header[..], b"data"].concat()
1625 );
1626 assert_eq!(small_shared.lock().unwrap().state, SendState::Fragment);
1627
1628 let large_shared = send_shared(limits);
1629 let mut large = TrailerSend::new(large_shared.clone(), ());
1630 assert!(
1631 Pin::new(&mut large)
1632 .poll_write(&mut cx, b"large")
1633 .is_pending()
1634 );
1635 assert_eq!(large_shared.lock().unwrap().state, SendState::Demand);
1636 assert!(large_shared.lock().unwrap().buffer.is_empty());
1637 }
1638
1639 #[test]
1640 fn receive_copy_threshold_depends_on_demand_for_this_fragment() {
1641 let undemanded = recv_shared(Limits {
1642 trailer_recv_copy_threshold: 1,
1643 trailer_recv_demand_copy_threshold: 4,
1644 ..unbounded_limits()
1645 })
1646 .0;
1647 let (_, receiver) = generic(futures::io::empty(), futures::io::sink());
1648 let mut receiver = AnyReceiver::Generic(receiver);
1649 let lease = unsafe { RecvShared::grant(&undemanded, receiver.recv(), 4) };
1650 assert_eq!(undemanded.lock().unwrap().state, RecvState::Unclaimed);
1651 drop(lease);
1652
1653 let demanded = recv_shared(Limits {
1654 trailer_recv_copy_threshold: 1,
1655 trailer_recv_demand_copy_threshold: 4,
1656 ..unbounded_limits()
1657 })
1658 .0;
1659 let mut trailer = TrailerRecv::new(demanded.clone());
1660 let mut output = [0; 4];
1661 assert!(poll_read_once(&mut trailer, &mut output).is_pending());
1662 assert_eq!(demanded.lock().unwrap().state, RecvState::Demand);
1663 let (_, receiver) = generic(futures::io::empty(), futures::io::sink());
1664 let mut receiver = AnyReceiver::Generic(receiver);
1665 let lease = unsafe { RecvShared::grant(&demanded, receiver.recv(), 4) };
1666 assert_eq!(demanded.lock().unwrap().state, RecvState::Draining);
1667 drop(lease);
1668 }
1669
1670 #[test]
1671 fn demand_at_a_completed_fragment_boundary_applies_to_the_next_fragment() {
1672 let shared = recv_shared(Limits {
1673 trailer_recv_copy_threshold: 0,
1674 trailer_recv_demand_copy_threshold: 0,
1675 ..unbounded_limits()
1676 })
1677 .0;
1678 let mut trailer = TrailerRecv::new(shared.clone());
1679 let (_, receiver) = generic(futures::io::empty(), futures::io::sink());
1680 let mut receiver = AnyReceiver::Generic(receiver);
1681 let lease = unsafe { RecvShared::grant(&shared, receiver.recv(), 0) };
1682 assert_eq!(shared.lock().unwrap().state, RecvState::Fragment);
1683
1684 let mut output = [0; 1];
1685 assert!(poll_read_once(&mut trailer, &mut output).is_pending());
1686 assert_eq!(shared.lock().unwrap().state, RecvState::FragmentDemand);
1687 lease.complete();
1688 assert_eq!(shared.lock().unwrap().state, RecvState::Demand);
1689 }
1690
1691 #[tokio::test]
1692 async fn unclaimed_large_receive_falls_back_to_driver_draining() {
1693 use futures::io::AsyncWriteExt;
1694
1695 let shared = recv_shared(Limits {
1696 trailer_recv_copy_threshold: 0,
1697 trailer_recv_demand_copy_threshold: 0,
1698 ..unbounded_limits()
1699 })
1700 .0;
1701 let (mut writer, reader) = crate::tests::duplex(16);
1702 writer.write_all(b"data").await.unwrap();
1703 let (_, receiver) = generic(reader, futures::io::sink());
1704 let mut receiver = AnyReceiver::Generic(receiver);
1705 let lease = unsafe { RecvShared::grant(&shared, receiver.recv(), 4) };
1706 assert_eq!(shared.lock().unwrap().state, RecvState::Unclaimed);
1707
1708 assert!(!RecvShared::wait_fragment(&shared).await.unwrap());
1709 assert_eq!(shared.lock().unwrap().state, RecvState::Fragment);
1710 assert_eq!(&shared.lock().unwrap().stage[..], b"data");
1711 lease.complete();
1712 }
1713
1714 #[tokio::test]
1715 async fn demanded_large_receive_can_claim_the_grant_directly() {
1716 use futures::io::AsyncWriteExt;
1717
1718 let shared = recv_shared(Limits {
1719 trailer_recv_copy_threshold: 0,
1720 trailer_recv_demand_copy_threshold: 0,
1721 ..unbounded_limits()
1722 })
1723 .0;
1724 let mut trailer = TrailerRecv::new(shared.clone());
1725 let mut output = [0; 4];
1726 assert!(poll_read_once(&mut trailer, &mut output).is_pending());
1727
1728 let (mut writer, reader) = crate::tests::duplex(16);
1729 writer.write_all(b"data").await.unwrap();
1730 let (_, receiver) = generic(reader, futures::io::sink());
1731 let mut receiver = AnyReceiver::Generic(receiver);
1732 let lease = unsafe { RecvShared::grant(&shared, receiver.recv(), 4) };
1733 assert_eq!(shared.lock().unwrap().state, RecvState::Unclaimed);
1734 assert!(matches!(
1735 poll_read_once(&mut trailer, &mut output),
1736 Poll::Ready(Ok(4))
1737 ));
1738 assert_eq!(&output, b"data");
1739 assert!(!RecvShared::wait_fragment(&shared).await.unwrap());
1740 lease.complete();
1741 assert_eq!(shared.lock().unwrap().state, RecvState::Idle);
1742 }
1743
1744 #[tokio::test]
1745 async fn abandoned_fragment_flushes_only_its_real_staged_suffix() {
1746 let output = Arc::new(Mutex::new(Vec::new()));
1747 let (sender, _) = generic(
1748 futures::io::empty(),
1749 CappedSink {
1750 bytes: output.clone(),
1751 max_write: 16,
1752 },
1753 );
1754 let mut sender = AnySender::Generic(sender);
1755 let shared = send_shared(unbounded_limits());
1756 let data = (0..100).map(|value| value as u8).collect::<Vec<_>>();
1757 let mut trailer = TrailerSend::new(shared.clone(), ());
1758 demand(&mut trailer, &data);
1759 let lease = unsafe { SendShared::grant(&shared, sender.send(), 1024) };
1760
1761 let written = std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, &data))
1762 .await
1763 .unwrap();
1764 assert_eq!(written, data.len());
1765 {
1766 let inner = lock(&shared);
1767 let header_len = FragmentHeader {
1768 flags: Flags::NONE,
1769 kind: Kind::Request,
1770 id: 1,
1771 payload_len: data.len(),
1772 }
1773 .encode()
1774 .len();
1775 assert_eq!(&inner.buffer[..], &data[16 - header_len..]);
1776 }
1777
1778 drop(trailer);
1779 assert_eq!(
1780 SendShared::wait_fragment(&shared).await.unwrap(),
1781 SendAction::Abort
1782 );
1783 let header_len = FragmentHeader {
1784 flags: Flags::NONE,
1785 kind: Kind::Request,
1786 id: 1,
1787 payload_len: data.len(),
1788 }
1789 .encode()
1790 .len();
1791 assert_eq!(&lock(&output)[header_len..], data);
1792 lease.complete();
1793 }
1794
1795 #[tokio::test]
1796 async fn partial_header_and_payload_share_the_stage_buffer() {
1797 let output = Arc::new(Mutex::new(Vec::new()));
1798 let (sender, _) = generic(
1799 futures::io::empty(),
1800 CappedSink {
1801 bytes: output.clone(),
1802 max_write: 5,
1803 },
1804 );
1805 let mut sender = AnySender::Generic(sender);
1806 let shared = send_shared_id(7, unbounded_limits());
1807 let data = (0..32).map(|value| value as u8).collect::<Vec<_>>();
1808 let mut trailer = TrailerSend::new(shared.clone(), ());
1809 demand(&mut trailer, &data);
1810 let lease = unsafe { SendShared::grant(&shared, sender.send(), 1024) };
1811
1812 let written = std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, &data))
1813 .await
1814 .unwrap();
1815 assert_eq!(written, data.len());
1816
1817 let header = FragmentHeader {
1818 flags: Flags::NONE,
1819 kind: Kind::Request,
1820 id: 7,
1821 payload_len: data.len(),
1822 }
1823 .encode();
1824 let mut expected_stage = Vec::from(&header[5..]);
1825 expected_stage.extend_from_slice(&data);
1826 assert_eq!(&lock(&shared).buffer[..], expected_stage);
1827
1828 assert_eq!(
1829 SendShared::wait_fragment(&shared).await.unwrap(),
1830 SendAction::Fragment
1831 );
1832 assert_eq!(&lock(&output)[..], [&header[..], &data].concat());
1833 lease.complete();
1834 }
1835
1836 #[tokio::test]
1837 async fn finish_releases_an_unused_live_grant() {
1838 let (sender, _) = generic(futures::io::empty(), futures::io::sink());
1839 let mut sender = AnySender::Generic(sender);
1840 let shared = send_shared(unbounded_limits());
1841 let lease = unsafe { SendShared::grant(&shared, sender.send(), 1024) };
1842
1843 TrailerSend::new(shared.clone(), ()).finish();
1844 assert_eq!(
1845 SendShared::wait_fragment(&shared).await.unwrap(),
1846 SendAction::Finish
1847 );
1848 lease.complete();
1849 }
1850
1851 #[tokio::test]
1860 async fn an_unstarted_trailer_reserves_no_credit() {
1861 let session = Arc::new(SessionWindow::new(64));
1862 let shared = SendShared::new(Kind::Request, 1, &Limits::default(), session.clone());
1866 let mut trailer = TrailerSend::new(shared.clone(), ());
1867
1868 let mut cx = Context::from_waker(Waker::noop());
1869 assert!(matches!(
1870 Pin::new(&mut trailer).poll_write(&mut cx, b"abcd"),
1871 Poll::Pending
1872 ));
1873 assert_eq!(session.available(), 64, "nothing may be spent yet");
1874 assert_eq!(lock(&shared).state, SendState::Idle);
1875
1876 SendShared::start(&shared);
1877 let written = std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, b"abcd"))
1878 .await
1879 .unwrap();
1880 assert_eq!(written, 4);
1881 assert_eq!(session.available(), 60);
1882 }
1883
1884 #[tokio::test]
1885 async fn exhausted_credit_parks_the_writer_until_credit_arrives() {
1886 let (sender, _) = generic(futures::io::empty(), futures::io::sink());
1887 let mut sender = AnySender::Generic(sender);
1888 let session = Arc::new(SessionWindow::new(4));
1889 let shared = SendShared::new(Kind::Request, 1, &zero_copy_limits(), session.clone());
1890 SendShared::start(&shared);
1891 let mut trailer = TrailerSend::new(shared.clone(), ());
1892
1893 demand(&mut trailer, b"abcd");
1895 let lease = unsafe { SendShared::grant(&shared, sender.send(), 1024) };
1896 let written = std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, b"abcd"))
1897 .await
1898 .unwrap();
1899 assert_eq!(written, 4);
1900 let action = SendShared::wait_fragment(&shared).await.unwrap();
1901 assert_eq!(action, SendAction::Fragment);
1902 lease.complete();
1903
1904 let mut cx = Context::from_waker(Waker::noop());
1907 assert!(matches!(
1908 Pin::new(&mut trailer).poll_write(&mut cx, b"e"),
1909 Poll::Pending
1910 ));
1911 assert_eq!(lock(&shared).state, SendState::Idle);
1912 assert!(matches!(
1913 SendShared::poll_action(&shared, &mut cx),
1914 Poll::Pending
1915 ));
1916
1917 session.refund(1, 2);
1919 demand(&mut trailer, b"ef");
1920 let lease = unsafe { SendShared::grant(&shared, sender.send(), 1024) };
1921 let written = std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, b"ef"))
1922 .await
1923 .unwrap();
1924 assert_eq!(written, 2);
1925 lease.complete();
1926 }
1927
1928 #[tokio::test]
1932 async fn pool_below_fragment_size_still_makes_progress() {
1933 let (sender, _) = generic(futures::io::empty(), futures::io::sink());
1934 let mut sender = AnySender::Generic(sender);
1935 let session = Arc::new(SessionWindow::new(3));
1936 let limits = Limits {
1937 max_fragment_size: 1024,
1938 ..zero_copy_limits()
1939 };
1940 let shared = SendShared::new(Kind::Request, 1, &limits, session.clone());
1941 SendShared::start(&shared);
1942 let mut trailer = TrailerSend::new(shared.clone(), ());
1943 let mut total = 0;
1944 for _ in 0..4 {
1945 demand(&mut trailer, b"abcdefghij");
1946 let lease = unsafe { SendShared::grant(&shared, sender.send(), 1024) };
1947 let n = std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, b"abcdefghij"))
1948 .await
1949 .unwrap();
1950 assert_eq!(n, 3, "each write is clamped to the pool, not dropped");
1951 total += n;
1952 SendShared::wait_fragment(&shared).await.unwrap();
1953 lease.complete();
1954 session.refund(1, 3);
1955 }
1956 assert_eq!(total, 12);
1957 }
1958
1959 #[tokio::test]
1964 async fn one_trailer_exhausting_the_pool_parks_another() {
1965 let (sender, _) = generic(futures::io::empty(), futures::io::sink());
1966 let mut sender = AnySender::Generic(sender);
1967 let session = Arc::new(SessionWindow::new(4));
1968 let limits = zero_copy_limits();
1969 let first = SendShared::new(Kind::Request, 1, &limits, session.clone());
1970 let second = SendShared::new(Kind::Request, 2, &limits, session.clone());
1971 SendShared::start(&first);
1972 SendShared::start(&second);
1973
1974 let mut trailer = TrailerSend::new(first.clone(), ());
1975 demand(&mut trailer, b"abcdefgh");
1976 let lease = unsafe { SendShared::grant(&first, sender.send(), 1024) };
1977 let written = std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, b"abcdefgh"))
1978 .await
1979 .unwrap();
1980 assert_eq!(written, 4, "clamped by the pool");
1981 SendShared::wait_fragment(&first).await.unwrap();
1982 lease.complete();
1983
1984 let mut other = TrailerSend::new(second.clone(), ());
1985 let mut cx = Context::from_waker(Waker::noop());
1986 assert!(matches!(
1987 Pin::new(&mut other).poll_write(&mut cx, b"i"),
1988 Poll::Pending
1989 ));
1990 assert_eq!(
1991 lock(&second).state,
1992 SendState::Idle,
1993 "a parked writer must hold no transport grant"
1994 );
1995 assert!(matches!(
1996 SendShared::poll_action(&second, &mut cx),
1997 Poll::Pending
1998 ));
1999
2000 session.refund(1, 2);
2001 demand(&mut other, b"ij");
2002 let lease = unsafe { SendShared::grant(&second, sender.send(), 1024) };
2003 let written = std::future::poll_fn(|cx| Pin::new(&mut other).poll_write(cx, b"ij"))
2004 .await
2005 .unwrap();
2006 assert_eq!(written, 2);
2007 lease.complete();
2008 }
2009
2010 #[tokio::test]
2013 async fn aborting_a_trailer_returns_its_session_debt() {
2014 let (sender, _) = generic(futures::io::empty(), futures::io::sink());
2015 let mut sender = AnySender::Generic(sender);
2016 let session = Arc::new(SessionWindow::new(64));
2017 let shared = SendShared::new(Kind::Request, 1, &zero_copy_limits(), session.clone());
2018 SendShared::start(&shared);
2019 let mut trailer = TrailerSend::new(shared.clone(), ());
2020 demand(&mut trailer, b"abcdefgh");
2021 let lease = unsafe { SendShared::grant(&shared, sender.send(), 1024) };
2022 std::future::poll_fn(|cx| Pin::new(&mut trailer).poll_write(cx, b"abcdefgh"))
2023 .await
2024 .unwrap();
2025 SendShared::wait_fragment(&shared).await.unwrap();
2026 lease.complete();
2027 assert_eq!(session.available(), 56);
2028
2029 SendShared::discard(&shared);
2030 assert_eq!(session.available(), 64, "the pool is made whole again");
2031 }
2032
2033 #[test]
2036 fn auto_release_credits_on_delivery() {
2037 let (shared, sink) = recv_shared(Limits {
2038 trailer_credit_interval: 8,
2039 ..Limits::default()
2040 });
2041 RecvShared::accept_bytes(&shared, 8);
2042 lock(&shared).stage.extend_from_slice(b"abcdefgh");
2043 let mut trailer = TrailerRecv::new(shared.clone());
2044
2045 let mut out = [0u8; 8];
2046 assert!(matches!(
2047 poll_read_once(&mut trailer, &mut out),
2048 Poll::Ready(Ok(8))
2049 ));
2050 assert_eq!(&*lock(&sink.credits), &[(7, 8)]);
2051 }
2052
2053 #[test]
2055 fn manual_release_does_not_credit_on_read() {
2056 let (shared, sink) = recv_shared(Limits {
2057 trailer_credit_interval: 8,
2058 ..Limits::default()
2059 });
2060 RecvShared::accept_bytes(&shared, 8);
2061 lock(&shared).stage.extend_from_slice(b"abcdefgh");
2062 let mut trailer = TrailerRecv::new(shared.clone());
2063 trailer.set_manual_credit();
2064
2065 let mut out = [0u8; 8];
2066 assert!(matches!(
2067 poll_read_once(&mut trailer, &mut out),
2068 Poll::Ready(Ok(8))
2069 ));
2070 assert!(lock(&sink.credits).is_empty(), "reading must not credit");
2071
2072 trailer.release(8);
2073 assert_eq!(&*lock(&sink.credits), &[(7, 8)]);
2074 }
2075
2076 #[test]
2079 fn credit_is_coalesced_below_half_an_interval() {
2080 let (shared, sink) = recv_shared(Limits {
2081 trailer_credit_interval: 64,
2082 trailer_session_window: 1024,
2083 ..Limits::default()
2084 });
2085 RecvShared::accept_bytes(&shared, 32);
2086 let mut trailer = TrailerRecv::new(shared.clone());
2087 trailer.set_manual_credit();
2088
2089 trailer.release(8);
2090 assert!(lock(&sink.credits).is_empty());
2091 trailer.release(8);
2092 assert!(lock(&sink.credits).is_empty());
2093 trailer.release(16);
2096 assert_eq!(&*lock(&sink.credits), &[(7, 32)]);
2097 }
2098
2099 #[test]
2103 fn credit_is_flushed_when_the_peer_is_starved() {
2104 let (shared, sink) = recv_shared(Limits {
2105 trailer_credit_interval: 64,
2106 trailer_session_window: 64,
2107 ..Limits::default()
2108 });
2109 assert_eq!(RecvShared::accept_bytes(&shared, 64), None);
2111 let mut trailer = TrailerRecv::new(shared.clone());
2112 trailer.set_manual_credit();
2113
2114 trailer.release(1);
2115 assert_eq!(
2116 &*lock(&sink.credits),
2117 &[(7, 1)],
2118 "a starved peer must be credited immediately, however little"
2119 );
2120 }
2121
2122 #[test]
2127 fn credit_is_flushed_when_the_consumer_starts_waiting() {
2128 let (shared, sink) = recv_shared(Limits {
2129 trailer_credit_interval: 64,
2130 trailer_session_window: 1024,
2131 ..Limits::default()
2132 });
2133 RecvShared::accept_bytes(&shared, 8);
2134 lock(&shared).stage.extend_from_slice(b"abcdefgh");
2135 let mut trailer = TrailerRecv::new(shared.clone());
2136
2137 let mut out = [0u8; 8];
2138 assert!(matches!(
2139 poll_read_once(&mut trailer, &mut out),
2140 Poll::Ready(Ok(8))
2141 ));
2142 assert!(
2143 lock(&sink.credits).is_empty(),
2144 "8 bytes is below half the interval, so it coalesces while reading"
2145 );
2146
2147 assert!(poll_read_once(&mut trailer, &mut out).is_pending());
2150 assert_eq!(&*lock(&sink.credits), &[(7, 8)]);
2151 }
2152
2153 #[test]
2157 fn credit_released_while_waiting_is_flushed_immediately() {
2158 let (shared, sink) = recv_shared(Limits {
2159 trailer_credit_interval: 64,
2160 trailer_session_window: 1024,
2161 ..Limits::default()
2162 });
2163 RecvShared::accept_bytes(&shared, 8);
2164 lock(&shared).stage.extend_from_slice(b"abcdefgh");
2165 let mut trailer = TrailerRecv::new(shared.clone());
2166 trailer.set_manual_credit();
2167
2168 let mut out = [0u8; 8];
2169 assert!(matches!(
2170 poll_read_once(&mut trailer, &mut out),
2171 Poll::Ready(Ok(8))
2172 ));
2173 assert!(poll_read_once(&mut trailer, &mut out).is_pending());
2174 assert!(
2175 lock(&sink.credits).is_empty(),
2176 "manual mode retires nothing on read, so the stall flushes nothing"
2177 );
2178
2179 trailer.release(8);
2180 assert_eq!(
2181 &*lock(&sink.credits),
2182 &[(7, 8)],
2183 "a waiting consumer's release goes out below the threshold"
2184 );
2185 }
2186
2187 #[test]
2193 fn credit_is_flushed_when_another_trailer_drained_the_pool() {
2194 let limits = Limits {
2195 trailer_credit_interval: 1024,
2196 trailer_session_window: 64,
2197 ..Limits::default()
2198 };
2199 let session = Arc::new(SessionWindow::new(limits.trailer_session_window));
2200 let make = |id| {
2201 let sink = Arc::new(RecordingSink::default());
2202 let shared = RecvShared::new(
2203 limits.trailer_recv_copy_threshold,
2204 limits.trailer_recv_demand_copy_threshold,
2205 limits.trailer_credit_interval,
2206 session.clone(),
2207 id,
2208 Arc::new(sink.clone()),
2209 );
2210 (shared, sink)
2211 };
2212 let (first, first_sink) = make(1);
2213 let (second, _second_sink) = make(2);
2214
2215 assert_eq!(RecvShared::accept_bytes(&first, 1), None);
2218 assert_eq!(RecvShared::accept_bytes(&second, 63), None);
2219
2220 let mut trailer = TrailerRecv::new(first.clone());
2221 trailer.set_manual_credit();
2222 trailer.release(1);
2223 assert_eq!(
2224 &*lock(&first_sink.credits),
2225 &[(1, 1)],
2226 "a drained pool must flush even a single byte, whoever drained it"
2227 );
2228 }
2229
2230 #[test]
2234 fn session_ledger_settles_each_byte_exactly_once() {
2235 let session = SessionWindow::new(100);
2236 assert_eq!(session.debit_up_to(1, 40), 40);
2237 assert_eq!(session.debit_up_to(2, 30), 30);
2238 assert_eq!(session.available(), 30);
2239
2240 session.refund(1, 1000);
2242 assert_eq!(session.available(), 70);
2243 session.refund(1, 1000);
2245 assert_eq!(session.available(), 70);
2246
2247 session.settle(2);
2249 assert_eq!(session.available(), 100);
2250 session.settle(2);
2251 session.refund(2, 30);
2252 assert_eq!(session.available(), 100);
2253
2254 session.refund(99, 10);
2257 session.settle(99);
2258 assert_eq!(session.available(), 100);
2259 }
2260
2261 #[test]
2265 fn reading_staged_bytes_after_a_discard_does_not_double_refund() {
2266 let limits = Limits {
2267 trailer_credit_interval: 8,
2268 trailer_session_window: 64,
2269 ..Limits::default()
2270 };
2271 let session = Arc::new(SessionWindow::new(limits.trailer_session_window));
2272 let sink = Arc::new(RecordingSink::default());
2273 let shared = RecvShared::new(
2274 limits.trailer_recv_copy_threshold,
2275 limits.trailer_recv_demand_copy_threshold,
2276 limits.trailer_credit_interval,
2277 session.clone(),
2278 7,
2279 Arc::new(sink.clone()),
2280 );
2281
2282 assert!(RecvShared::accept_bytes(&shared, 8).is_none());
2283 assert_eq!(session.available(), 56);
2284 lock(&shared).stage.extend_from_slice(b"abcdefgh");
2285
2286 let mut trailer = TrailerRecv::new(shared.clone());
2287 RecvShared::discard(&shared);
2288 assert_eq!(session.available(), 64, "the debt is returned in full");
2289
2290 let mut out = [0u8; 8];
2292 assert!(matches!(
2293 poll_read_once(&mut trailer, &mut out),
2294 Poll::Ready(Ok(8))
2295 ));
2296 assert_eq!(session.available(), 64);
2297 assert!(lock(&sink.credits).is_empty());
2298 }
2299
2300 #[test]
2303 fn dropping_a_trailer_discards_eagerly_exactly_once() {
2304 let (shared, sink) = recv_shared(unbounded_limits());
2305 let trailer = TrailerRecv::new(shared.clone());
2306 RecvShared::discard(&shared);
2307 assert_eq!(&*lock(&sink.discards), &[7]);
2308 drop(trailer);
2309 assert_eq!(&*lock(&sink.discards), &[7], "idempotent");
2310 }
2311}