1use std::{marker::PhantomData, sync::Arc};
2
3#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
4use libp2p_core::muxing::StreamMuxer;
5use libp2p_core::upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade};
6#[cfg(any(
7 feature = "relay",
8 all(not(target_arch = "wasm32"), feature = "websocket")
9))]
10use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo};
11
12use super::*;
13use crate::SwarmBuilder;
14
15pub struct QuicPhase<T> {
16 pub(crate) transport: T,
17}
18
19macro_rules! impl_quic_builder {
20 ($providerKebabCase:literal, $providerPascalCase:ty, $quic:ident) => {
21 #[cfg(all(not(target_arch = "wasm32"), feature = "quic", feature = $providerKebabCase))]
22 impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<$providerPascalCase, QuicPhase<T>> {
23 pub fn with_quic(
24 self,
25 ) -> SwarmBuilder<
26 $providerPascalCase,
27 OtherTransportPhase<impl AuthenticatedMultiplexedTransport>,
28 > {
29 self.with_quic_config(std::convert::identity)
30 }
31
32 pub fn with_quic_config(
33 self,
34 constructor: impl FnOnce(libp2p_quic::Config) -> libp2p_quic::Config,
35 ) -> SwarmBuilder<
36 $providerPascalCase,
37 OtherTransportPhase<impl AuthenticatedMultiplexedTransport>,
38 > {
39 SwarmBuilder {
40 phase: OtherTransportPhase {
41 transport: self
42 .phase
43 .transport
44 .or_transport(
45 libp2p_quic::$quic::Transport::new(constructor(
46 libp2p_quic::Config::new(&self.keypair),
47 ))
48 .map(|(peer_id, muxer), _| {
49 (peer_id, libp2p_core::muxing::StreamMuxerBox::new(muxer))
50 }),
51 )
52 .map(|either, _| either.into_inner()),
53 },
54 keypair: self.keypair,
55 phantom: PhantomData,
56 }
57 }
58 }
59 };
60}
61
62impl_quic_builder!("async-std", AsyncStd, async_std);
63impl_quic_builder!("tokio", super::provider::Tokio, tokio);
64
65impl<Provider, T> SwarmBuilder<Provider, QuicPhase<T>> {
66 pub(crate) fn without_quic(self) -> SwarmBuilder<Provider, OtherTransportPhase<T>> {
67 SwarmBuilder {
68 keypair: self.keypair,
69 phantom: PhantomData,
70 phase: OtherTransportPhase {
71 transport: self.phase.transport,
72 },
73 }
74 }
75}
76
77impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
79 #[cfg(feature = "relay")]
81 pub fn with_relay_client<SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError>(
82 self,
83 security_upgrade: SecUpgrade,
84 multiplexer_upgrade: MuxUpgrade,
85 ) -> Result<
86 SwarmBuilder<
87 Provider,
88 BandwidthLoggingPhase<impl AuthenticatedMultiplexedTransport, libp2p_relay::client::Behaviour>,
89 >,
90 SecUpgrade::Error,
91 > where
92
93 SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
94 SecError: std::error::Error + Send + Sync + 'static,
95 SecUpgrade: IntoSecurityUpgrade<libp2p_relay::client::Connection>,
96 SecUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
97 <SecUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
98 <SecUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
99 <<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
100 <<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::Info: Send,
101
102 MuxStream: libp2p_core::muxing::StreamMuxer + Send + 'static,
103 MuxStream::Substream: Send + 'static,
104 MuxStream::Error: Send + Sync + 'static,
105 MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
106 MuxUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
107 <MuxUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
108 <MuxUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
109 MuxError: std::error::Error + Send + Sync + 'static,
110 <<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
111 <<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
112 {
113 self.without_quic()
114 .without_any_other_transports()
115 .without_dns()
116 .without_websocket()
117 .with_relay_client(security_upgrade, multiplexer_upgrade)
118 }
119
120 pub fn with_other_transport<
121 Muxer: libp2p_core::muxing::StreamMuxer + Send + 'static,
122 OtherTransport: Transport<Output = (libp2p_identity::PeerId, Muxer)> + Send + Unpin + 'static,
123 R: TryIntoTransport<OtherTransport>,
124 >(
125 self,
126 constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
127 ) -> Result<
128 SwarmBuilder<Provider, OtherTransportPhase<impl AuthenticatedMultiplexedTransport>>,
129 R::Error,
130 >
131 where
132 <OtherTransport as Transport>::Error: Send + Sync + 'static,
133 <OtherTransport as Transport>::Dial: Send,
134 <OtherTransport as Transport>::ListenerUpgrade: Send,
135 <Muxer as libp2p_core::muxing::StreamMuxer>::Substream: Send,
136 <Muxer as libp2p_core::muxing::StreamMuxer>::Error: Send + Sync,
137 {
138 self.without_quic().with_other_transport(constructor)
139 }
140
141 pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
142 self,
143 constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
144 ) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
145 self.without_quic()
146 .without_any_other_transports()
147 .without_dns()
148 .without_websocket()
149 .without_relay()
150 .with_behaviour(constructor)
151 }
152}
153#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
154impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::AsyncStd, QuicPhase<T>> {
155 pub fn with_dns(
156 self,
157 ) -> Result<
158 SwarmBuilder<
159 super::provider::AsyncStd,
160 WebsocketPhase<impl AuthenticatedMultiplexedTransport>,
161 >,
162 std::io::Error,
163 > {
164 self.without_quic()
165 .without_any_other_transports()
166 .with_dns()
167 }
168}
169#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
170impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::Tokio, QuicPhase<T>> {
171 pub fn with_dns(
172 self,
173 ) -> Result<
174 SwarmBuilder<
175 super::provider::Tokio,
176 WebsocketPhase<impl AuthenticatedMultiplexedTransport>,
177 >,
178 std::io::Error,
179 > {
180 self.without_quic()
181 .without_any_other_transports()
182 .with_dns()
183 }
184}
185#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
186impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::AsyncStd, QuicPhase<T>> {
187 pub fn with_dns_config(
188 self,
189 cfg: libp2p_dns::ResolverConfig,
190 opts: libp2p_dns::ResolverOpts,
191 ) -> SwarmBuilder<
192 super::provider::AsyncStd,
193 WebsocketPhase<impl AuthenticatedMultiplexedTransport>,
194 > {
195 self.without_quic()
196 .without_any_other_transports()
197 .with_dns_config(cfg, opts)
198 }
199}
200#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
201impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::Tokio, QuicPhase<T>> {
202 pub fn with_dns_config(
203 self,
204 cfg: libp2p_dns::ResolverConfig,
205 opts: libp2p_dns::ResolverOpts,
206 ) -> SwarmBuilder<super::provider::Tokio, WebsocketPhase<impl AuthenticatedMultiplexedTransport>>
207 {
208 self.without_quic()
209 .without_any_other_transports()
210 .with_dns_config(cfg, opts)
211 }
212}
213
214macro_rules! impl_quic_phase_with_websocket {
215 ($providerKebabCase:literal, $providerPascalCase:ty, $websocketStream:ty) => {
216 #[cfg(all(feature = $providerKebabCase, not(target_arch = "wasm32"), feature = "websocket"))]
217 impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<$providerPascalCase, QuicPhase<T>> {
218 pub async fn with_websocket <
220 SecUpgrade,
221 SecStream,
222 SecError,
223 MuxUpgrade,
224 MuxStream,
225 MuxError,
226 > (
227 self,
228 security_upgrade: SecUpgrade,
229 multiplexer_upgrade: MuxUpgrade,
230 ) -> Result<
231 SwarmBuilder<
232 $providerPascalCase,
233 RelayPhase<impl AuthenticatedMultiplexedTransport>,
234 >,
235 super::websocket::WebsocketError<SecUpgrade::Error>,
236 >
237 where
238 SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
239 SecError: std::error::Error + Send + Sync + 'static,
240 SecUpgrade: IntoSecurityUpgrade<$websocketStream>,
241 SecUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundConnectionUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
242 <SecUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<$websocketStream>>>::Future: Send,
243 <SecUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<$websocketStream>>>::Future: Send,
244 <<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
245 <<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::Info: Send,
246
247 MuxStream: StreamMuxer + Send + 'static,
248 MuxStream::Substream: Send + 'static,
249 MuxStream::Error: Send + Sync + 'static,
250 MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
251 MuxUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
252 <MuxUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
253 <MuxUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
254 MuxError: std::error::Error + Send + Sync + 'static,
255 <<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
256 <<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
257 {
258 self.without_quic()
259 .without_any_other_transports()
260 .without_dns()
261 .with_websocket(security_upgrade, multiplexer_upgrade)
262 .await
263 }
264 }
265 }
266}
267impl_quic_phase_with_websocket!(
268 "async-std",
269 super::provider::AsyncStd,
270 rw_stream_sink::RwStreamSink<
271 libp2p_websocket::BytesConnection<libp2p_tcp::async_io::TcpStream>,
272 >
273);
274impl_quic_phase_with_websocket!(
275 "tokio",
276 super::provider::Tokio,
277 rw_stream_sink::RwStreamSink<libp2p_websocket::BytesConnection<libp2p_tcp::tokio::TcpStream>>
278);
279impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
280 #[allow(deprecated)]
281 #[deprecated(note = "Use `with_bandwidth_metrics` instead.")]
282 pub fn with_bandwidth_logging(
283 self,
284 ) -> (
285 SwarmBuilder<
286 Provider,
287 BandwidthMetricsPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
288 >,
289 Arc<crate::bandwidth::BandwidthSinks>,
290 ) {
291 #[allow(deprecated)]
292 self.without_quic()
293 .without_any_other_transports()
294 .without_dns()
295 .without_websocket()
296 .without_relay()
297 .with_bandwidth_logging()
298 }
299}
300#[cfg(feature = "metrics")]
301impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
302 pub fn with_bandwidth_metrics(
303 self,
304 registry: &mut libp2p_metrics::Registry,
305 ) -> SwarmBuilder<
306 Provider,
307 BehaviourPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
308 > {
309 self.without_quic()
310 .without_any_other_transports()
311 .without_dns()
312 .without_websocket()
313 .without_relay()
314 .without_bandwidth_logging()
315 .with_bandwidth_metrics(registry)
316 }
317}