1use std::{
2 future::Future,
3 pin::Pin,
4 task::{Context, Poll},
5};
6
7use actix_codec::{AsyncRead, AsyncWrite, Framed};
8use actix_service::{IntoService, Service};
9use pin_project_lite::pin_project;
10
11use super::{Codec, Frame, Message};
12
13pin_project! {
14 pub struct Dispatcher<S, T>
15 where
16 S: Service<Frame, Response = Message>,
17 S: 'static,
18 T: AsyncRead,
19 T: AsyncWrite,
20 {
21 #[pin]
22 inner: inner::Dispatcher<S, T, Codec, Message>,
23 }
24}
25
26impl<S, T> Dispatcher<S, T>
27where
28 T: AsyncRead + AsyncWrite,
29 S: Service<Frame, Response = Message>,
30 S::Future: 'static,
31 S::Error: 'static,
32{
33 pub fn new<F: IntoService<S, Frame>>(io: T, service: F) -> Self {
34 Dispatcher {
35 inner: inner::Dispatcher::new(Framed::new(io, Codec::new()), service),
36 }
37 }
38
39 pub fn with<F: IntoService<S, Frame>>(framed: Framed<T, Codec>, service: F) -> Self {
40 Dispatcher {
41 inner: inner::Dispatcher::new(framed, service),
42 }
43 }
44}
45
46impl<S, T> Future for Dispatcher<S, T>
47where
48 T: AsyncRead + AsyncWrite,
49 S: Service<Frame, Response = Message>,
50 S::Future: 'static,
51 S::Error: 'static,
52{
53 type Output = Result<(), inner::DispatcherError<S::Error, Codec, Message>>;
54
55 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
56 self.project().inner.poll(cx)
57 }
58}
59
60mod inner {
62 #![allow(dead_code)]
64
65 use core::{
66 fmt,
67 future::Future,
68 mem,
69 pin::Pin,
70 task::{Context, Poll},
71 };
72
73 use actix_codec::Framed;
74 use actix_service::{IntoService, Service};
75 use futures_core::stream::Stream;
76 use local_channel::mpsc;
77 use pin_project_lite::pin_project;
78 use tokio::{
79 io::{AsyncRead, AsyncWrite},
80 task::spawn_local,
81 };
82 use tokio_util::codec::{Decoder, Encoder};
83 use tracing::debug;
84
85 use crate::{body::BoxBody, Response};
86
87 pub enum DispatcherError<E, U, I>
89 where
90 U: Encoder<I> + Decoder,
91 {
92 Service(E),
94
95 Encoder(<U as Encoder<I>>::Error),
97
98 Decoder(<U as Decoder>::Error),
100 }
101
102 impl<E, U, I> From<E> for DispatcherError<E, U, I>
103 where
104 U: Encoder<I> + Decoder,
105 {
106 fn from(err: E) -> Self {
107 DispatcherError::Service(err)
108 }
109 }
110
111 impl<E, U, I> fmt::Debug for DispatcherError<E, U, I>
112 where
113 E: fmt::Debug,
114 U: Encoder<I> + Decoder,
115 <U as Encoder<I>>::Error: fmt::Debug,
116 <U as Decoder>::Error: fmt::Debug,
117 {
118 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
119 match *self {
120 DispatcherError::Service(ref err) => {
121 write!(fmt, "DispatcherError::Service({err:?})")
122 }
123 DispatcherError::Encoder(ref err) => {
124 write!(fmt, "DispatcherError::Encoder({err:?})")
125 }
126 DispatcherError::Decoder(ref err) => {
127 write!(fmt, "DispatcherError::Decoder({err:?})")
128 }
129 }
130 }
131 }
132
133 impl<E, U, I> fmt::Display for DispatcherError<E, U, I>
134 where
135 E: fmt::Display,
136 U: Encoder<I> + Decoder,
137 <U as Encoder<I>>::Error: fmt::Debug,
138 <U as Decoder>::Error: fmt::Debug,
139 {
140 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
141 match *self {
142 DispatcherError::Service(ref err) => write!(fmt, "{err}"),
143 DispatcherError::Encoder(ref err) => write!(fmt, "{err:?}"),
144 DispatcherError::Decoder(ref err) => write!(fmt, "{err:?}"),
145 }
146 }
147 }
148
149 impl<E, U, I> From<DispatcherError<E, U, I>> for Response<BoxBody>
150 where
151 E: fmt::Debug + fmt::Display,
152 U: Encoder<I> + Decoder,
153 <U as Encoder<I>>::Error: fmt::Debug,
154 <U as Decoder>::Error: fmt::Debug,
155 {
156 fn from(err: DispatcherError<E, U, I>) -> Self {
157 Response::internal_server_error().set_body(BoxBody::new(err.to_string()))
158 }
159 }
160
161 pub enum Message<T> {
163 Item(T),
165
166 Close,
168 }
169
170 pin_project! {
171 pub struct Dispatcher<S, T, U, I>
173 where
174 S: Service<<U as Decoder>::Item, Response = I>,
175 S::Error: 'static,
176 S::Future: 'static,
177 T: AsyncRead,
178 T: AsyncWrite,
179 U: Encoder<I>,
180 U: Decoder,
181 I: 'static,
182 <U as Encoder<I>>::Error: fmt::Debug,
183 {
184 service: S,
185 state: State<S, U, I>,
186 #[pin]
187 framed: Framed<T, U>,
188 rx: mpsc::Receiver<Result<Message<I>, S::Error>>,
189 tx: mpsc::Sender<Result<Message<I>, S::Error>>,
190 }
191 }
192
193 enum State<S, U, I>
194 where
195 S: Service<<U as Decoder>::Item>,
196 U: Encoder<I> + Decoder,
197 {
198 Processing,
199 Error(DispatcherError<S::Error, U, I>),
200 FramedError(DispatcherError<S::Error, U, I>),
201 FlushAndStop,
202 Stopping,
203 }
204
205 impl<S, U, I> State<S, U, I>
206 where
207 S: Service<<U as Decoder>::Item>,
208 U: Encoder<I> + Decoder,
209 {
210 fn take_error(&mut self) -> DispatcherError<S::Error, U, I> {
211 match mem::replace(self, State::Processing) {
212 State::Error(err) => err,
213 _ => panic!(),
214 }
215 }
216
217 fn take_framed_error(&mut self) -> DispatcherError<S::Error, U, I> {
218 match mem::replace(self, State::Processing) {
219 State::FramedError(err) => err,
220 _ => panic!(),
221 }
222 }
223 }
224
225 impl<S, T, U, I> Dispatcher<S, T, U, I>
226 where
227 S: Service<<U as Decoder>::Item, Response = I>,
228 S::Error: 'static,
229 S::Future: 'static,
230 T: AsyncRead + AsyncWrite,
231 U: Decoder + Encoder<I>,
232 I: 'static,
233 <U as Decoder>::Error: fmt::Debug,
234 <U as Encoder<I>>::Error: fmt::Debug,
235 {
236 pub fn new<F>(framed: Framed<T, U>, service: F) -> Self
238 where
239 F: IntoService<S, <U as Decoder>::Item>,
240 {
241 let (tx, rx) = mpsc::channel();
242 Dispatcher {
243 framed,
244 rx,
245 tx,
246 service: service.into_service(),
247 state: State::Processing,
248 }
249 }
250
251 pub fn with_rx<F>(
253 framed: Framed<T, U>,
254 service: F,
255 rx: mpsc::Receiver<Result<Message<I>, S::Error>>,
256 ) -> Self
257 where
258 F: IntoService<S, <U as Decoder>::Item>,
259 {
260 let tx = rx.sender();
261 Dispatcher {
262 framed,
263 rx,
264 tx,
265 service: service.into_service(),
266 state: State::Processing,
267 }
268 }
269
270 pub fn tx(&self) -> mpsc::Sender<Result<Message<I>, S::Error>> {
272 self.tx.clone()
273 }
274
275 pub fn service(&self) -> &S {
277 &self.service
278 }
279
280 pub fn service_mut(&mut self) -> &mut S {
282 &mut self.service
283 }
284
285 pub fn framed(&self) -> &Framed<T, U> {
287 &self.framed
288 }
289
290 pub fn framed_mut(&mut self) -> &mut Framed<T, U> {
292 &mut self.framed
293 }
294
295 fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> bool
297 where
298 S: Service<<U as Decoder>::Item, Response = I>,
299 S::Error: 'static,
300 S::Future: 'static,
301 T: AsyncRead + AsyncWrite,
302 U: Decoder + Encoder<I>,
303 I: 'static,
304 <U as Encoder<I>>::Error: fmt::Debug,
305 {
306 loop {
307 let this = self.as_mut().project();
308 match this.service.poll_ready(cx) {
309 Poll::Ready(Ok(_)) => {
310 let item = match this.framed.next_item(cx) {
311 Poll::Ready(Some(Ok(el))) => el,
312 Poll::Ready(Some(Err(err))) => {
313 *this.state = State::FramedError(DispatcherError::Decoder(err));
314 return true;
315 }
316 Poll::Pending => return false,
317 Poll::Ready(None) => {
318 *this.state = State::Stopping;
319 return true;
320 }
321 };
322
323 let tx = this.tx.clone();
324 let fut = this.service.call(item);
325 spawn_local(async move {
326 let item = fut.await;
327 let _ = tx.send(item.map(Message::Item));
328 });
329 }
330 Poll::Pending => return false,
331 Poll::Ready(Err(err)) => {
332 *this.state = State::Error(DispatcherError::Service(err));
333 return true;
334 }
335 }
336 }
337 }
338
339 fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> bool
341 where
342 S: Service<<U as Decoder>::Item, Response = I>,
343 S::Error: 'static,
344 S::Future: 'static,
345 T: AsyncRead + AsyncWrite,
346 U: Decoder + Encoder<I>,
347 I: 'static,
348 <U as Encoder<I>>::Error: fmt::Debug,
349 {
350 loop {
351 let mut this = self.as_mut().project();
352 while !this.framed.is_write_buf_full() {
353 match Pin::new(&mut this.rx).poll_next(cx) {
354 Poll::Ready(Some(Ok(Message::Item(msg)))) => {
355 if let Err(err) = this.framed.as_mut().write(msg) {
356 *this.state = State::FramedError(DispatcherError::Encoder(err));
357 return true;
358 }
359 }
360 Poll::Ready(Some(Ok(Message::Close))) => {
361 *this.state = State::FlushAndStop;
362 return true;
363 }
364 Poll::Ready(Some(Err(err))) => {
365 *this.state = State::Error(DispatcherError::Service(err));
366 return true;
367 }
368 Poll::Ready(None) | Poll::Pending => break,
369 }
370 }
371
372 if !this.framed.is_write_buf_empty() {
373 match this.framed.flush(cx) {
374 Poll::Pending => break,
375 Poll::Ready(Ok(_)) => {}
376 Poll::Ready(Err(err)) => {
377 debug!("Error sending data: {:?}", err);
378 *this.state = State::FramedError(DispatcherError::Encoder(err));
379 return true;
380 }
381 }
382 } else {
383 break;
384 }
385 }
386
387 false
388 }
389 }
390
391 impl<S, T, U, I> Future for Dispatcher<S, T, U, I>
392 where
393 S: Service<<U as Decoder>::Item, Response = I>,
394 S::Error: 'static,
395 S::Future: 'static,
396 T: AsyncRead + AsyncWrite,
397 U: Decoder + Encoder<I>,
398 I: 'static,
399 <U as Encoder<I>>::Error: fmt::Debug,
400 <U as Decoder>::Error: fmt::Debug,
401 {
402 type Output = Result<(), DispatcherError<S::Error, U, I>>;
403
404 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
405 loop {
406 let this = self.as_mut().project();
407
408 return match this.state {
409 State::Processing => {
410 if self.as_mut().poll_read(cx) || self.as_mut().poll_write(cx) {
411 continue;
412 } else {
413 Poll::Pending
414 }
415 }
416 State::Error(_) => {
417 if !this.framed.is_write_buf_empty() && this.framed.flush(cx).is_pending() {
419 return Poll::Pending;
420 }
421 Poll::Ready(Err(this.state.take_error()))
422 }
423 State::FlushAndStop => {
424 if !this.framed.is_write_buf_empty() {
425 this.framed.flush(cx).map(|res| {
426 if let Err(err) = res {
427 debug!("Error sending data: {:?}", err);
428 }
429
430 Ok(())
431 })
432 } else {
433 Poll::Ready(Ok(()))
434 }
435 }
436 State::FramedError(_) => Poll::Ready(Err(this.state.take_framed_error())),
437 State::Stopping => Poll::Ready(Ok(())),
438 };
439 }
440 }
441 }
442}