trillium_server_common/
client.rs1use 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
12pub trait Connector: Send + Sync + 'static {
18 type Transport: Transport;
20
21 type Runtime: RuntimeTrait;
23
24 type Udp: UdpTransport;
28
29 fn connect(&self, url: &Url) -> impl Future<Output = io::Result<Self::Transport>> + Send;
31
32 fn arced(self) -> ArcedConnector
34 where
35 Self: Sized,
36 {
37 ArcedConnector(Arc::new(self))
38 }
39
40 fn resolve(
42 &self,
43 host: &str,
44 port: u16,
45 ) -> impl Future<Output = io::Result<Vec<SocketAddr>>> + Send;
46
47 fn runtime(&self) -> Self::Runtime;
49}
50
51#[derive(Clone)]
53pub struct ArcedConnector(Arc<dyn ObjectSafeConnector>);
54
55impl Debug for ArcedConnector {
56 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
57 f.debug_tuple("ArcedConnector").finish()
58 }
59}
60
61impl ArcedConnector {
62 #[must_use]
64 pub fn new(connector: impl Connector) -> Self {
65 connector.arced()
66 }
67
68 pub fn is<T: Any + 'static>(&self) -> bool {
70 self.as_any().is::<T>()
71 }
72
73 pub fn downcast_ref<T: Any + 'static>(&self) -> Option<&T> {
76 self.0.as_any().downcast_ref()
77 }
78
79 pub fn downcast_mut<T: Any + 'static>(&mut self) -> Option<&mut T> {
82 Arc::get_mut(&mut self.0)?.as_mut_any().downcast_mut()
83 }
84
85 pub fn runtime(&self) -> Runtime {
87 self.0.runtime()
88 }
89}
90
91type ConnectResult<'fut> =
93 Pin<Box<dyn Future<Output = io::Result<Box<dyn Transport>>> + Send + 'fut>>;
94
95trait ObjectSafeConnector: Send + Sync + 'static {
96 #[must_use]
97 fn connect<'connector, 'url, 'fut>(&'connector self, url: &'url Url) -> ConnectResult<'fut>
98 where
99 'connector: 'fut,
100 'url: 'fut,
101 Self: 'fut;
102 fn as_any(&self) -> &dyn Any;
103 fn as_mut_any(&mut self) -> &mut dyn Any;
104 fn runtime(&self) -> Runtime;
105
106 fn resolve<'connector, 'host, 'fut>(
107 &'connector self,
108 host: &'host str,
109 port: u16,
110 ) -> Pin<Box<dyn Future<Output = io::Result<Vec<SocketAddr>>> + Send + 'fut>>
111 where
112 'connector: 'fut,
113 'host: 'fut,
114 Self: 'fut;
115}
116
117impl<T: Connector> ObjectSafeConnector for T {
118 fn connect<'connector, 'url, 'fut>(
119 &'connector self,
120 url: &'url Url,
121 ) -> Pin<Box<dyn Future<Output = io::Result<Box<dyn Transport>>> + Send + 'fut>>
122 where
123 'connector: 'fut,
124 'url: 'fut,
125 Self: 'fut,
126 {
127 Box::pin(async move {
128 Connector::connect(self, url)
129 .await
130 .map(|t| Box::new(t) as Box<dyn Transport>)
131 })
132 }
133
134 fn as_any(&self) -> &dyn Any {
135 self
136 }
137
138 fn as_mut_any(&mut self) -> &mut dyn Any {
139 self
140 }
141
142 fn runtime(&self) -> Runtime {
143 Connector::runtime(self).into()
144 }
145
146 fn resolve<'connector, 'host, 'fut>(
147 &'connector self,
148 host: &'host str,
149 port: u16,
150 ) -> Pin<Box<dyn Future<Output = io::Result<Vec<SocketAddr>>> + Send + 'fut>>
151 where
152 'connector: 'fut,
153 'host: 'fut,
154 Self: 'fut,
155 {
156 Box::pin(async move { Connector::resolve(self, host, port).await })
157 }
158}
159
160impl Connector for ArcedConnector {
161 type Runtime = Runtime;
162 type Transport = Box<dyn Transport>;
163 type Udp = ();
164
165 async fn connect(&self, url: &Url) -> io::Result<Box<dyn Transport>> {
166 self.0.connect(url).await
167 }
168
169 fn arced(self) -> ArcedConnector {
170 self
171 }
172
173 fn runtime(&self) -> Self::Runtime {
174 self.0.runtime()
175 }
176
177 async fn resolve(&self, host: &str, port: u16) -> io::Result<Vec<SocketAddr>> {
178 self.0.resolve(host, port).await
179 }
180}
181
182pub trait QuicClientConfig<C: Connector>: Send + Sync + 'static {
191 type Endpoint: crate::QuicEndpoint;
193
194 fn bind(&self, addr: SocketAddr, runtime: &C::Runtime) -> io::Result<Self::Endpoint>;
199}
200
201trait ObjectSafeQuicClientConfig: Send + Sync + 'static {
204 fn bind(&self, addr: SocketAddr) -> io::Result<crate::ArcedQuicEndpoint>;
205}
206
207struct BoundQuicClientConfig<Q, C: Connector> {
209 config: Q,
210 runtime: C::Runtime,
211}
212
213impl<C: Connector, Q: QuicClientConfig<C>> ObjectSafeQuicClientConfig
214 for BoundQuicClientConfig<Q, C>
215{
216 fn bind(&self, addr: SocketAddr) -> io::Result<crate::ArcedQuicEndpoint> {
217 let endpoint = self.config.bind(addr, &self.runtime)?;
218 Ok(crate::ArcedQuicEndpoint::from(endpoint))
219 }
220}
221
222#[derive(Clone)]
227pub struct ArcedQuicClientConfig(Arc<dyn ObjectSafeQuicClientConfig>);
228
229impl Debug for ArcedQuicClientConfig {
230 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
231 f.debug_tuple("ArcedQuicClientConfig").finish()
232 }
233}
234
235impl ArcedQuicClientConfig {
236 #[must_use]
238 pub fn new<C: Connector, Q: QuicClientConfig<C>>(connector: &C, config: Q) -> Self {
239 Self(Arc::new(BoundQuicClientConfig {
240 runtime: connector.runtime(),
241 config,
242 }))
243 }
244
245 pub fn bind(&self, addr: SocketAddr) -> io::Result<crate::ArcedQuicEndpoint> {
247 self.0.bind(addr)
248 }
249}