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