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!("tokio", super::provider::Tokio, tokio);
63
64impl<Provider, T> SwarmBuilder<Provider, QuicPhase<T>> {
65 pub(crate) fn without_quic(self) -> SwarmBuilder<Provider, OtherTransportPhase<T>> {
66 SwarmBuilder {
67 keypair: self.keypair,
68 phantom: PhantomData,
69 phase: OtherTransportPhase {
70 transport: self.phase.transport,
71 },
72 }
73 }
74}
75
76impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
78 #[cfg(feature = "relay")]
80 pub fn with_relay_client<SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError>(
81 self,
82 security_upgrade: SecUpgrade,
83 multiplexer_upgrade: MuxUpgrade,
84 ) -> Result<
85 SwarmBuilder<
86 Provider,
87 BandwidthMetricsPhase<impl AuthenticatedMultiplexedTransport, libp2p_relay::client::Behaviour>,
88 >,
89 SecUpgrade::Error,
90 > where
91
92 SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
93 SecError: std::error::Error + Send + Sync + 'static,
94 SecUpgrade: IntoSecurityUpgrade<libp2p_relay::client::Connection>,
95 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,
96 <SecUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
97 <SecUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
98 <<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
99 <<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::Info: Send,
100
101 MuxStream: libp2p_core::muxing::StreamMuxer + Send + 'static,
102 MuxStream::Substream: Send + 'static,
103 MuxStream::Error: Send + Sync + 'static,
104 MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
105 MuxUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
106 <MuxUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
107 <MuxUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
108 MuxError: std::error::Error + Send + Sync + 'static,
109 <<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
110 <<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
111 {
112 self.without_quic()
113 .without_any_other_transports()
114 .without_dns()
115 .without_websocket()
116 .with_relay_client(security_upgrade, multiplexer_upgrade)
117 }
118
119 pub fn with_other_transport<
120 Muxer: libp2p_core::muxing::StreamMuxer + Send + 'static,
121 OtherTransport: Transport<Output = (libp2p_identity::PeerId, Muxer)> + Send + Unpin + 'static,
122 R: TryIntoTransport<OtherTransport>,
123 >(
124 self,
125 constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
126 ) -> Result<
127 SwarmBuilder<Provider, OtherTransportPhase<impl AuthenticatedMultiplexedTransport>>,
128 R::Error,
129 >
130 where
131 <OtherTransport as Transport>::Error: Send + Sync + 'static,
132 <OtherTransport as Transport>::Dial: Send,
133 <OtherTransport as Transport>::ListenerUpgrade: Send,
134 <Muxer as libp2p_core::muxing::StreamMuxer>::Substream: Send,
135 <Muxer as libp2p_core::muxing::StreamMuxer>::Error: Send + Sync,
136 {
137 self.without_quic().with_other_transport(constructor)
138 }
139
140 pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
141 self,
142 constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
143 ) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
144 self.without_quic()
145 .without_any_other_transports()
146 .without_dns()
147 .without_websocket()
148 .without_relay()
149 .with_behaviour(constructor)
150 }
151}
152#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
153impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::AsyncStd, QuicPhase<T>> {
154 pub fn with_dns(
155 self,
156 ) -> Result<
157 SwarmBuilder<
158 super::provider::AsyncStd,
159 WebsocketPhase<impl AuthenticatedMultiplexedTransport>,
160 >,
161 std::io::Error,
162 > {
163 self.without_quic()
164 .without_any_other_transports()
165 .with_dns()
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);
278#[cfg(feature = "metrics")]
279impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
280 pub fn with_bandwidth_metrics(
281 self,
282 registry: &mut libp2p_metrics::Registry,
283 ) -> SwarmBuilder<
284 Provider,
285 BehaviourPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
286 > {
287 self.without_quic()
288 .without_any_other_transports()
289 .without_dns()
290 .without_websocket()
291 .without_relay()
292 .with_bandwidth_metrics(registry)
293 }
294}