1use std::{
2 fmt,
3 future::Future,
4 net::SocketAddr,
5 pin::Pin,
6 task::{Context, Poll},
7};
8
9use futures::future::BoxFuture;
10use hyper::{
11 Request, Response, Uri,
12 body::{Body, Bytes},
13 rt::Executor,
14};
15use tower::{
16 Service,
17 buffer::{Buffer, future::ResponseFuture as BufferResponseFuture},
18 util::BoxService,
19};
20
21use crate::client_conn;
22use crate::{client_body::H3IncomingClient, executor::SharedExec};
23
24const DEFAULT_BUFFER_SIZE: usize = 1024;
25
26pub trait H3Connector: Send + 'static + Clone {
27 type CONN: h3::quic::Connection<
28 Bytes,
29 OpenStreams = Self::OS,
30 SendStream = Self::SS,
31 RecvStream = Self::RS,
32 > + Send;
33 type OS: h3::quic::OpenStreams<Bytes, BidiStream = Self::BS> + Clone + Send; type SS: h3::quic::SendStream<Bytes> + Send;
35 type RS: h3::quic::RecvStream + Send;
36 type BS: h3::quic::BidiStream<Bytes, RecvStream = Self::RS, SendStream = Self::SS> + Send;
37
38 fn connect(
39 &self,
40 ) -> impl std::future::Future<Output = Result<Self::CONN, crate::Error>> + std::marker::Send;
41}
42
43pub async fn dns_resolve(uri: &Uri) -> std::io::Result<Vec<SocketAddr>> {
47 let host_port = uri
48 .authority()
49 .ok_or(std::io::Error::from(std::io::ErrorKind::InvalidInput))?
50 .as_str();
51 match host_port.parse::<SocketAddr>() {
52 Ok(addr) => Ok(vec![addr]),
53 Err(_) => {
54 tokio::net::lookup_host(host_port)
56 .await
57 .map(|a| a.collect::<Vec<_>>())
58 }
59 }
60}
61
62pub struct H3Channel<C, B>
64where
65 C: H3Connector,
66 B: Body + Send + 'static + Unpin,
67 B::Data: Send,
68 B::Error: Into<crate::Error> + Send,
69{
70 #[allow(clippy::type_complexity)]
71 svc: Buffer<
72 Request<B>,
73 BoxFuture<'static, Result<Response<H3IncomingClient<C::RS, Bytes>>, crate::Error>>,
74 >,
75}
76
77impl<C, B> Clone for H3Channel<C, B>
78where
79 C: H3Connector,
80 B: Body + Send + 'static + Unpin,
81 B::Data: Send,
82 B::Error: Into<crate::Error> + Send,
83{
84 fn clone(&self) -> Self {
85 Self {
86 svc: self.svc.clone(),
87 }
88 }
89}
90
91pub struct ResponseFuture<C>
92where
93 C: H3Connector,
94{
95 #[allow(clippy::type_complexity)]
96 inner: BufferResponseFuture<
97 BoxFuture<'static, Result<Response<H3IncomingClient<C::RS, Bytes>>, crate::Error>>,
98 >,
99}
100
101impl<C, B> H3Channel<C, B>
102where
103 C: H3Connector,
104 B: Body + Send + 'static + Unpin,
105 B::Data: Send,
106 B::Error: Into<crate::Error> + Send,
107{
108 pub fn new(connector: C, uri: Uri, executor: Option<SharedExec>) -> Self {
109 let executor = executor.unwrap_or_else(SharedExec::tokio);
110 let svc = H3Connection::new(connector, uri, Some(executor.clone()));
111 let (svc, worker) = Buffer::pair(svc, DEFAULT_BUFFER_SIZE);
112 executor.execute(worker);
113 Self { svc }
114 }
115}
116
117impl<C, B> Service<Request<B>> for H3Channel<C, B>
118where
119 C: H3Connector,
120 B: Body + Send + 'static + Unpin,
121 B::Data: Send,
122 B::Error: Into<crate::Error> + Send,
123{
124 type Response = Response<H3IncomingClient<C::RS, Bytes>>;
125 type Error = crate::Error;
126 type Future = ResponseFuture<C>;
127
128 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
129 Service::poll_ready(&mut self.svc, cx).map_err(crate::Error::from)
130 }
131
132 fn call(&mut self, req: Request<B>) -> Self::Future {
133 let inner = Service::call(&mut self.svc, req);
134 ResponseFuture { inner }
135 }
136}
137
138impl<C> Future for ResponseFuture<C>
139where
140 C: H3Connector,
141{
142 type Output = Result<Response<H3IncomingClient<C::RS, Bytes>>, crate::Error>;
143
144 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
145 Pin::new(&mut self.inner)
146 .poll(cx)
147 .map_err(crate::Error::from)
148 }
149}
150
151impl<C, B> fmt::Debug for H3Channel<C, B>
152where
153 C: H3Connector,
154 B: Body + Send + 'static + Unpin,
155 B::Data: Send,
156 B::Error: Into<crate::Error> + Send,
157{
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 f.debug_struct("H3Channel").finish()
160 }
161}
162
163impl<C> fmt::Debug for ResponseFuture<C>
164where
165 C: H3Connector,
166{
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 f.debug_struct("ResponseFuture").finish()
169 }
170}
171
172pub struct H3Connection<C, B>
177where
178 C: H3Connector,
179 B: Body + Send + 'static + Unpin,
180 B::Data: Send,
181 B::Error: Into<crate::Error>,
182{
183 #[allow(clippy::type_complexity)]
184 inner: BoxService<Request<B>, Response<H3IncomingClient<C::RS, Bytes>>, crate::Error>,
185}
186
187impl<C, B> H3Connection<C, B>
188where
189 C: H3Connector,
190 B: Body + Send + 'static + Unpin,
191 B::Data: Send,
192 B::Error: Into<crate::Error> + Send,
193{
194 pub fn new(connector: C, uri: Uri, executor: Option<SharedExec>) -> Self {
195 let executor = executor.unwrap_or_else(SharedExec::tokio);
196 let sender = client_conn::RequestSender::new(connector, uri, executor);
197 Self {
198 inner: BoxService::new(sender),
199 }
200 }
201}
202
203impl<C, B> Service<Request<B>> for H3Connection<C, B>
204where
205 C: H3Connector,
206 B: Body + Send + 'static + Unpin,
207 B::Data: Send,
208 B::Error: Into<crate::Error>,
209{
210 type Response = Response<H3IncomingClient<C::RS, Bytes>>;
211 type Error = crate::Error;
212 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
213
214 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
215 Service::poll_ready(&mut self.inner, cx)
216 }
217
218 fn call(&mut self, req: Request<B>) -> Self::Future {
219 self.inner.call(req)
220 }
221}
222
223pub struct H3Client<C, B>
228where
229 C: H3Connector,
230 B: Body + Send + 'static + Unpin,
231 B::Data: Send,
232 B::Error: Into<crate::Error> + Send,
233{
234 channel: H3Connection<C, B>,
235}
236
237impl<C, B> H3Client<C, B>
238where
239 C: H3Connector,
240 B: Body + Send + 'static + Unpin,
241 B::Data: Send,
242 B::Error: Into<crate::Error> + Send,
243{
244 pub fn new(inner: H3Connection<C, B>) -> Self {
245 Self { channel: inner }
246 }
247
248 pub async fn send(
249 &mut self,
250 req: Request<B>,
251 ) -> Result<Response<H3IncomingClient<C::RS, Bytes>>, crate::Error> {
252 futures::future::poll_fn(|cx| self.channel.poll_ready(cx)).await?;
254 self.channel.call(req).await
255 }
256}