1use crate::{Runtime, RuntimeTrait, Transport, UdpTransport, Url};
2use std::{
3 any::Any,
4 fmt::{self, Debug, Formatter},
5 future::Future,
6 io,
7 net::SocketAddr,
8 pin::Pin,
9 sync::Arc,
10};
11
12mod destination;
13pub use destination::Destination;
14
15#[cfg(test)]
16mod tests;
17
18pub trait Connector: Send + Sync + 'static {
24 type Transport: Transport;
26
27 type Runtime: RuntimeTrait;
29
30 type Udp: UdpTransport;
34
35 fn connect(&self, url: &Url) -> impl Future<Output = io::Result<Self::Transport>> + Send;
37
38 fn connect_to(
53 &self,
54 destination: Destination,
55 ) -> impl Future<Output = io::Result<Self::Transport>> + Send {
56 async move { self.connect(&destination.to_url()?).await }
57 }
58
59 fn connect_over(
76 &self,
77 transport: Box<dyn Transport>,
78 destination: Destination,
79 ) -> impl Future<Output = io::Result<Box<dyn Transport>>> + Send {
80 async move {
81 if destination.secure() {
82 Err(io::Error::new(
83 io::ErrorKind::Unsupported,
84 "connector does not support TLS over an existing transport",
85 ))
86 } else {
87 Ok(transport)
88 }
89 }
90 }
91 fn arced(self) -> ArcedConnector
93 where
94 Self: Sized,
95 {
96 ArcedConnector(Arc::new(self))
97 }
98
99 fn resolve(
101 &self,
102 host: &str,
103 port: u16,
104 ) -> impl Future<Output = io::Result<Vec<SocketAddr>>> + Send;
105
106 fn runtime(&self) -> Self::Runtime;
108}
109
110#[derive(Clone)]
112pub struct ArcedConnector(Arc<dyn ObjectSafeConnector>);
113
114impl Debug for ArcedConnector {
115 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
116 f.debug_tuple("ArcedConnector").finish()
117 }
118}
119
120impl ArcedConnector {
121 #[must_use]
123 pub fn new(connector: impl Connector) -> Self {
124 connector.arced()
125 }
126
127 pub fn is<T: Any + 'static>(&self) -> bool {
129 self.as_any().is::<T>()
130 }
131
132 pub fn downcast_ref<T: Any + 'static>(&self) -> Option<&T> {
135 self.0.as_any().downcast_ref()
136 }
137
138 pub fn downcast_mut<T: Any + 'static>(&mut self) -> Option<&mut T> {
141 Arc::get_mut(&mut self.0)?.as_mut_any().downcast_mut()
142 }
143
144 pub fn runtime(&self) -> Runtime {
146 self.0.runtime()
147 }
148}
149
150type ConnectResult<'fut> =
152 Pin<Box<dyn Future<Output = io::Result<Box<dyn Transport>>> + Send + 'fut>>;
153
154trait ObjectSafeConnector: Send + Sync + 'static {
155 fn connect<'connector, 'url, 'fut>(&'connector self, url: &'url Url) -> ConnectResult<'fut>
156 where
157 'connector: 'fut,
158 'url: 'fut,
159 Self: 'fut;
160 fn as_any(&self) -> &dyn Any;
161 fn as_mut_any(&mut self) -> &mut dyn Any;
162 fn runtime(&self) -> Runtime;
163
164 fn resolve<'connector, 'host, 'fut>(
165 &'connector self,
166 host: &'host str,
167 port: u16,
168 ) -> Pin<Box<dyn Future<Output = io::Result<Vec<SocketAddr>>> + Send + 'fut>>
169 where
170 'connector: 'fut,
171 'host: 'fut,
172 Self: 'fut;
173
174 fn connect_to<'connector, 'fut>(
175 &'connector self,
176 destination: Destination,
177 ) -> ConnectResult<'fut>
178 where
179 'connector: 'fut,
180 Self: 'fut;
181
182 fn connect_over<'connector, 'fut>(
183 &'connector self,
184 transport: Box<dyn Transport>,
185 destination: Destination,
186 ) -> ConnectResult<'fut>
187 where
188 'connector: 'fut,
189 Self: 'fut;
190}
191
192impl<T: Connector> ObjectSafeConnector for T {
193 fn connect<'connector, 'url, 'fut>(
194 &'connector self,
195 url: &'url Url,
196 ) -> Pin<Box<dyn Future<Output = io::Result<Box<dyn Transport>>> + Send + 'fut>>
197 where
198 'connector: 'fut,
199 'url: 'fut,
200 Self: 'fut,
201 {
202 Box::pin(async move {
203 Connector::connect(self, url)
204 .await
205 .map(|t| Box::new(t) as Box<dyn Transport>)
206 })
207 }
208
209 fn as_any(&self) -> &dyn Any {
210 self
211 }
212
213 fn as_mut_any(&mut self) -> &mut dyn Any {
214 self
215 }
216
217 fn runtime(&self) -> Runtime {
218 Connector::runtime(self).into()
219 }
220
221 fn resolve<'connector, 'host, 'fut>(
222 &'connector self,
223 host: &'host str,
224 port: u16,
225 ) -> Pin<Box<dyn Future<Output = io::Result<Vec<SocketAddr>>> + Send + 'fut>>
226 where
227 'connector: 'fut,
228 'host: 'fut,
229 Self: 'fut,
230 {
231 Box::pin(async move { Connector::resolve(self, host, port).await })
232 }
233
234 fn connect_to<'connector, 'fut>(
235 &'connector self,
236 destination: Destination,
237 ) -> ConnectResult<'fut>
238 where
239 'connector: 'fut,
240 Self: 'fut,
241 {
242 Box::pin(async move {
243 Connector::connect_to(self, destination)
244 .await
245 .map(|t| Box::new(t) as Box<dyn Transport>)
246 })
247 }
248
249 fn connect_over<'connector, 'fut>(
250 &'connector self,
251 transport: Box<dyn Transport>,
252 destination: Destination,
253 ) -> ConnectResult<'fut>
254 where
255 'connector: 'fut,
256 Self: 'fut,
257 {
258 Box::pin(async move { Connector::connect_over(self, transport, destination).await })
259 }
260}
261
262impl Connector for ArcedConnector {
263 type Runtime = Runtime;
264 type Transport = Box<dyn Transport>;
265 type Udp = ();
266
267 async fn connect(&self, url: &Url) -> io::Result<Box<dyn Transport>> {
268 self.0.connect(url).await
269 }
270
271 fn arced(self) -> ArcedConnector {
272 self
273 }
274
275 fn runtime(&self) -> Self::Runtime {
276 self.0.runtime()
277 }
278
279 async fn resolve(&self, host: &str, port: u16) -> io::Result<Vec<SocketAddr>> {
280 self.0.resolve(host, port).await
281 }
282
283 async fn connect_to(&self, destination: Destination) -> io::Result<Box<dyn Transport>> {
284 self.0.connect_to(destination).await
285 }
286
287 async fn connect_over(
288 &self,
289 transport: Box<dyn Transport>,
290 destination: Destination,
291 ) -> io::Result<Box<dyn Transport>> {
292 self.0.connect_over(transport, destination).await
293 }
294}
295
296pub trait QuicClientConfig<C: Connector>: Send + Sync + 'static {
305 type Endpoint: crate::QuicEndpoint;
307
308 fn bind(&self, addr: SocketAddr, runtime: &C::Runtime) -> io::Result<Self::Endpoint>;
313}
314
315trait ObjectSafeQuicClientConfig: Send + Sync + 'static {
318 fn bind(&self, addr: SocketAddr) -> io::Result<crate::ArcedQuicEndpoint>;
319}
320
321struct BoundQuicClientConfig<Q, C: Connector> {
323 config: Q,
324 runtime: C::Runtime,
325}
326
327impl<C: Connector, Q: QuicClientConfig<C>> ObjectSafeQuicClientConfig
328 for BoundQuicClientConfig<Q, C>
329{
330 fn bind(&self, addr: SocketAddr) -> io::Result<crate::ArcedQuicEndpoint> {
331 let endpoint = self.config.bind(addr, &self.runtime)?;
332 Ok(crate::ArcedQuicEndpoint::from(endpoint))
333 }
334}
335
336#[derive(Clone)]
341pub struct ArcedQuicClientConfig(Arc<dyn ObjectSafeQuicClientConfig>);
342
343impl Debug for ArcedQuicClientConfig {
344 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
345 f.debug_tuple("ArcedQuicClientConfig").finish()
346 }
347}
348
349impl ArcedQuicClientConfig {
350 #[must_use]
352 pub fn new<C: Connector, Q: QuicClientConfig<C>>(connector: &C, config: Q) -> Self {
353 Self(Arc::new(BoundQuicClientConfig {
354 runtime: connector.runtime(),
355 config,
356 }))
357 }
358
359 pub fn bind(&self, addr: SocketAddr) -> io::Result<crate::ArcedQuicEndpoint> {
361 self.0.bind(addr)
362 }
363}