1use std::fmt;
2use std::sync::{Arc, Mutex};
3use std::task::{Context, Poll};
4
5use atomic_waker::AtomicWaker;
6use bytes::Bytes;
7use http::HeaderMap;
8
9use crate::common::lock::LockResultExt;
10
11pub(crate) fn channel(wanter: bool) -> (Sender, Receiver) {
12 let shared = Arc::new(Shared {
13 state: Mutex::new(State {
14 item: None,
15 pending_error: None,
16 trailers: None,
17 sender_open: true,
18 receiver_open: true,
19 want: !wanter,
20 }),
21 sender_waker: AtomicWaker::new(),
22 receiver_waker: AtomicWaker::new(),
23 });
24
25 (
26 Sender {
27 shared: Arc::clone(&shared),
28 trailers_sent: false,
29 },
30 Receiver {
31 shared,
32 terminated: false,
33 },
34 )
35}
36
37#[must_use = "Sender does nothing unless sent on"]
38pub(crate) struct Sender {
39 shared: Arc<Shared>,
40 trailers_sent: bool,
41}
42
43pub(crate) struct Receiver {
44 shared: Arc<Shared>,
45 terminated: bool,
46}
47
48struct Shared {
49 state: Mutex<State>,
50 sender_waker: AtomicWaker,
51 receiver_waker: AtomicWaker,
52}
53
54struct State {
55 item: Option<Result<Bytes, crate::Error>>,
56 pending_error: Option<crate::Error>,
59 trailers: Option<HeaderMap>,
60 sender_open: bool,
61 receiver_open: bool,
62 want: bool,
63}
64
65impl Sender {
66 pub(crate) fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<crate::Result<()>> {
67 self.shared.sender_waker.register(cx.waker());
68 let state = self.shared.state.lock().panic_if_poisoned();
69 if !state.receiver_open {
70 Poll::Ready(Err(crate::Error::new_closed()))
71 } else if state.want && state.item.is_none() && state.pending_error.is_none() {
72 Poll::Ready(Ok(()))
73 } else {
74 Poll::Pending
75 }
76 }
77
78 #[cfg(test)]
79 pub(crate) async fn ready(&mut self) -> crate::Result<()> {
80 futures_util::future::poll_fn(|cx| self.poll_ready(cx)).await
81 }
82
83 #[cfg(test)]
84 #[allow(dead_code)]
85 pub(crate) async fn send_data(&mut self, chunk: Bytes) -> crate::Result<()> {
86 self.ready().await?;
87 self.try_send_data(chunk)
88 .map_err(|_| crate::Error::new_closed())
89 }
90
91 pub(crate) fn try_send_data(&mut self, chunk: Bytes) -> Result<(), Bytes> {
92 let mut state = self.shared.state.lock().panic_if_poisoned();
93 if !state.receiver_open
94 || !state.want
95 || state.item.is_some()
96 || state.pending_error.is_some()
97 {
98 return Err(chunk);
99 }
100 state.item = Some(Ok(chunk));
101 drop(state);
102 self.shared.receiver_waker.wake();
103 Ok(())
104 }
105
106 pub(crate) fn try_send_trailers(
107 &mut self,
108 trailers: HeaderMap,
109 ) -> Result<(), Option<HeaderMap>> {
110 if self.trailers_sent {
111 return Err(None);
112 }
113 self.trailers_sent = true;
114
115 let mut state = self.shared.state.lock().panic_if_poisoned();
116 if !state.receiver_open {
117 return Err(Some(trailers));
118 }
119 state.trailers = Some(trailers);
120 drop(state);
121 self.shared.receiver_waker.wake();
122 Ok(())
123 }
124
125 #[allow(dead_code)]
126 #[allow(clippy::unused_async_trait_impl)]
127 #[allow(clippy::map_err_ignore)]
128 pub(crate) async fn send_trailers(&mut self, trailers: HeaderMap) -> crate::Result<()> {
129 self.try_send_trailers(trailers)
130 .map_err(|_| crate::Error::new_closed())
131 }
132
133 pub(crate) fn send_error(&mut self, err: crate::Error) {
134 let mut state = self.shared.state.lock().panic_if_poisoned();
135 if !state.receiver_open {
136 return;
137 }
138 if state.item.is_none() {
139 state.item = Some(Err(err));
140 } else if state.pending_error.is_none() {
141 state.pending_error = Some(err);
142 }
143 drop(state);
144 self.shared.receiver_waker.wake();
145 }
146
147 #[cfg(test)]
148 pub(crate) fn abort(mut self) {
149 self.send_error(crate::Error::new_body_write_aborted());
150 }
151
152 fn is_closed(&self) -> bool {
153 !self.shared.state.lock().panic_if_poisoned().receiver_open
154 }
155}
156
157impl Receiver {
158 pub(crate) fn poll_next(
159 &mut self,
160 cx: &mut Context<'_>,
161 ) -> Poll<Option<Result<bytes::Bytes, crate::Error>>> {
162 if self.terminated {
163 return Poll::Ready(None);
164 }
165
166 self.shared.receiver_waker.register(cx.waker());
167 let mut state = self.shared.state.lock().panic_if_poisoned();
168 let wake_sender = if !state.want {
169 state.want = true;
170 true
171 } else {
172 false
173 };
174 if let Some(item) = state.item.take() {
175 drop(state);
176 self.shared.sender_waker.wake();
177 return Poll::Ready(Some(item));
178 }
179 if let Some(err) = state.pending_error.take() {
180 drop(state);
181 if wake_sender {
182 self.shared.sender_waker.wake();
183 }
184 return Poll::Ready(Some(Err(err)));
185 }
186 let sender_open = state.sender_open;
187 drop(state);
188 if wake_sender {
189 self.shared.sender_waker.wake();
190 }
191 if sender_open {
192 Poll::Pending
193 } else {
194 self.terminated = true;
195 Poll::Ready(None)
196 }
197 }
198
199 pub(crate) fn take_trailers(&mut self) -> Option<HeaderMap> {
200 debug_assert!(self.terminated, "data channel still open before trailers");
201 let mut state = self.shared.state.lock().panic_if_poisoned();
202 state.trailers.take()
203 }
204}
205
206impl Drop for Sender {
207 fn drop(&mut self) {
208 let mut state = self.shared.state.lock().panic_if_poisoned();
209 state.sender_open = false;
210 let receiver_open = state.receiver_open;
211 drop(state);
212 if receiver_open {
213 self.shared.receiver_waker.wake();
214 }
215 }
216}
217
218impl Drop for Receiver {
219 fn drop(&mut self) {
220 let mut state = self.shared.state.lock().panic_if_poisoned();
221 state.receiver_open = false;
222 let sender_open = state.sender_open;
223 drop(state);
224 if sender_open {
225 self.shared.sender_waker.wake();
226 }
227 }
228}
229
230impl fmt::Debug for Sender {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 if self.is_closed() {
233 f.debug_tuple("Sender").field(&"Closed").finish()
234 } else {
235 f.debug_tuple("Sender").field(&"Open").finish()
236 }
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use std::{
243 sync::atomic::{AtomicUsize, Ordering},
244 task::{Wake, Waker},
245 };
246
247 use super::*;
248
249 async fn recv(rx: &mut Receiver) -> Option<Result<Bytes, crate::Error>> {
250 futures_util::future::poll_fn(|cx| rx.poll_next(cx)).await
251 }
252
253 #[tokio::test]
254 async fn error_queued_behind_accepted_data() {
255 let (mut tx, mut rx) = channel(false);
256 tx.try_send_data(Bytes::from_static(b"data")).unwrap();
257 tx.send_error(crate::Error::new_incomplete());
258 drop(tx);
259
260 assert_eq!(recv(&mut rx).await.unwrap().unwrap(), "data");
261 assert!(recv(&mut rx).await.unwrap().is_err());
262 assert!(recv(&mut rx).await.is_none());
263 }
264
265 #[tokio::test]
266 async fn trailers_follow_data_close() {
267 let (mut tx, mut rx) = channel(false);
268 let mut trailers = HeaderMap::new();
269 trailers.insert("x-trailer", "value".parse().unwrap());
270 tx.try_send_trailers(trailers).unwrap();
271 drop(tx);
272
273 assert!(recv(&mut rx).await.is_none());
274 assert_eq!(rx.take_trailers().unwrap()["x-trailer"], "value");
275 }
276
277 #[test]
278 fn drop_wakes_only_an_open_peer() {
279 struct Count(AtomicUsize);
280
281 impl Wake for Count {
282 fn wake(self: Arc<Self>) {
283 self.0.fetch_add(1, Ordering::Relaxed);
284 }
285 }
286
287 let count = Arc::new(Count(AtomicUsize::new(0)));
288 let waker = Waker::from(count.clone());
289 let mut cx = Context::from_waker(&waker);
290 let wakes = || count.0.load(Ordering::Relaxed);
291
292 let (mut tx, rx) = channel(true);
294 assert!(tx.poll_ready(&mut cx).is_pending());
295 drop(tx);
296 drop(rx);
297 assert_eq!(wakes(), 0);
298
299 let (tx, mut rx) = channel(false);
301 assert!(rx.poll_next(&mut cx).is_pending());
302 drop(rx);
303 drop(tx);
304 assert_eq!(wakes(), 0);
305
306 let (mut tx, rx) = channel(true);
308 assert!(tx.poll_ready(&mut cx).is_pending());
309 drop(rx);
310 assert_eq!(wakes(), 1);
311 let (tx, mut rx) = channel(false);
312 assert!(rx.poll_next(&mut cx).is_pending());
313 drop(tx);
314 assert_eq!(wakes(), 2);
315 }
316}