1use airio_core::{StreamMuxer, Upgrade, UpgradeInfo, muxing::StreamMuxerEvent};
2use futures::{AsyncRead, AsyncWrite, future, ready};
3pub use muxing::{Connection, ConnectionError, Endpoint, Stream};
4use std::{
5 collections::VecDeque,
6 io, iter,
7 pin::Pin,
8 task::{Context, Poll, Waker},
9};
10
11#[derive(Debug)]
12pub struct Muxer<C> {
13 connection: Connection<C>,
14 inbound_stream_buffer: VecDeque<Stream>,
15 inbound_stream_waker: Option<Waker>,
16}
17
18impl<C> Muxer<C>
19where
20 C: AsyncRead + AsyncWrite + Unpin + 'static,
21{
22 pub fn new(connection: Connection<C>) -> Self {
23 Muxer {
24 connection,
25 inbound_stream_buffer: VecDeque::with_capacity(MAX_BUFFERED_INBOUND_STREAMS),
26 inbound_stream_waker: None,
27 }
28 }
29
30 fn poll_inner(&mut self, cx: &mut Context<'_>) -> Poll<Result<Stream, ConnectionError>> {
31 let stream =
32 ready!(self.connection.poll_next_inbound(cx)?).ok_or(ConnectionError::Closed)?;
33 Poll::Ready(Ok(stream))
34 }
35}
36
37const MAX_BUFFERED_INBOUND_STREAMS: usize = 256;
38
39impl<C> StreamMuxer for Muxer<C>
40where
41 C: AsyncRead + AsyncWrite + Unpin + 'static,
42{
43 type Substream = Stream;
44 type Error = ConnectionError;
45
46 fn poll_inbound(
47 mut self: Pin<&mut Self>,
48 cx: &mut Context<'_>,
49 ) -> Poll<Result<Self::Substream, Self::Error>> {
50 if let Some(stream) = self.inbound_stream_buffer.pop_front() {
51 return Poll::Ready(Ok(stream));
52 }
53 if let Poll::Ready(res) = self.poll_inner(cx) {
54 return Poll::Ready(res);
55 }
56 self.inbound_stream_waker = Some(cx.waker().clone());
57 Poll::Pending
58 }
59
60 fn poll_outbound(
61 mut self: Pin<&mut Self>,
62 cx: &mut Context<'_>,
63 ) -> Poll<Result<Self::Substream, Self::Error>> {
64 self.as_mut().connection.poll_new_outbound(cx)
65 }
66
67 #[tracing::instrument(level = "trace", name = "StreamMuxer::poll", skip(self, cx))]
68 fn poll(
69 mut self: Pin<&mut Self>,
70 cx: &mut Context<'_>,
71 ) -> Poll<Result<StreamMuxerEvent, Self::Error>> {
72 let mut this = self.as_mut();
73 let inbound_stream = ready!(this.poll_inner(cx))?;
74
75 if this.inbound_stream_buffer.len() >= MAX_BUFFERED_INBOUND_STREAMS {
76 tracing::warn!(
77 "{}: Inbound stream buffer is full, dropping stream:",
78 inbound_stream
79 );
80 drop(inbound_stream);
81 } else {
82 this.inbound_stream_buffer.push_back(inbound_stream);
83 if let Some(waker) = this.inbound_stream_waker.take() {
84 waker.wake();
85 }
86 }
87 cx.waker().wake_by_ref();
89 Poll::Pending
90 }
91
92 #[tracing::instrument(level = "trace", name = "StreamMuxer::poll_close", skip(self, cx))]
93 fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
94 self.as_mut().connection.poll_close(cx)
95 }
96}
97
98#[derive(Debug, Clone)]
99pub struct Config(muxing::Config);
100
101impl Config {
102 pub fn new() -> Self {
103 Config(muxing::Config::default())
104 }
105
106 pub fn set_max_active_streams(&mut self, max_active_streams: usize) -> &mut Self {
107 self.0.set_max_active_streams(max_active_streams);
108 self
109 }
110
111 pub fn set_read_after_close(&mut self, read_after_close: bool) -> &mut Self {
112 self.0.set_read_after_close(read_after_close);
113 self
114 }
115}
116
117impl Default for Config {
118 fn default() -> Self {
119 Config(muxing::Config::default())
120 }
121}
122
123impl UpgradeInfo for Config {
124 type Info = &'static str;
125 type InfoIter = iter::Once<Self::Info>;
126
127 fn protocol_info(&self) -> Self::InfoIter {
128 iter::once("/v1/muxing")
129 }
130}
131
132impl<C> Upgrade<C> for Config
133where
134 C: AsyncRead + AsyncWrite + Send + Unpin + 'static,
135{
136 type Output = Muxer<C>;
137 type Error = io::Error;
138 type Future = future::Ready<Result<Self::Output, Self::Error>>;
139
140 fn upgrade_inbound(self, socket: C, _: Self::Info) -> Self::Future {
141 let connection = Connection::new(socket, self.0, Endpoint::Server);
142 future::ready(Ok(Muxer::new(connection)))
143 }
144
145 fn upgrade_outbound(self, socket: C, _: Self::Info) -> Self::Future {
146 let connection = Connection::new(socket, self.0, Endpoint::Client);
147 future::ready(Ok(Muxer::new(connection)))
148 }
149}