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 = "tokio", feature = "dns"))]
153impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::Tokio, QuicPhase<T>> {
154 pub fn with_dns(
155 self,
156 ) -> Result<
157 SwarmBuilder<
158 super::provider::Tokio,
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_config(
171 self,
172 cfg: libp2p_dns::ResolverConfig,
173 opts: libp2p_dns::ResolverOpts,
174 ) -> SwarmBuilder<super::provider::Tokio, WebsocketPhase<impl AuthenticatedMultiplexedTransport>>
175 {
176 self.without_quic()
177 .without_any_other_transports()
178 .with_dns_config(cfg, opts)
179 }
180}
181
182macro_rules! impl_quic_phase_with_websocket {
183 ($providerKebabCase:literal, $providerPascalCase:ty, $websocketStream:ty) => {
184 #[cfg(all(feature = $providerKebabCase, not(target_arch = "wasm32"), feature = "websocket"))]
185 impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<$providerPascalCase, QuicPhase<T>> {
186 pub async fn with_websocket <
188 SecUpgrade,
189 SecStream,
190 SecError,
191 MuxUpgrade,
192 MuxStream,
193 MuxError,
194 > (
195 self,
196 security_upgrade: SecUpgrade,
197 multiplexer_upgrade: MuxUpgrade,
198 ) -> Result<
199 SwarmBuilder<
200 $providerPascalCase,
201 RelayPhase<impl AuthenticatedMultiplexedTransport>,
202 >,
203 super::websocket::WebsocketError<SecUpgrade::Error>,
204 >
205 where
206 SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
207 SecError: std::error::Error + Send + Sync + 'static,
208 SecUpgrade: IntoSecurityUpgrade<$websocketStream>,
209 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,
210 <SecUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<$websocketStream>>>::Future: Send,
211 <SecUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<$websocketStream>>>::Future: Send,
212 <<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
213 <<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::Info: Send,
214
215 MuxStream: StreamMuxer + Send + 'static,
216 MuxStream::Substream: Send + 'static,
217 MuxStream::Error: Send + Sync + 'static,
218 MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
219 MuxUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
220 <MuxUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
221 <MuxUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
222 MuxError: std::error::Error + Send + Sync + 'static,
223 <<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
224 <<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
225 {
226 self.without_quic()
227 .without_any_other_transports()
228 .without_dns()
229 .with_websocket(security_upgrade, multiplexer_upgrade)
230 .await
231 }
232 }
233 }
234}
235
236impl_quic_phase_with_websocket!(
237 "tokio",
238 super::provider::Tokio,
239 rw_stream_sink::RwStreamSink<libp2p_websocket::BytesConnection<libp2p_tcp::tokio::TcpStream>>
240);
241#[cfg(feature = "metrics")]
242impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
243 pub fn with_bandwidth_metrics(
244 self,
245 registry: &mut libp2p_metrics::Registry,
246 ) -> SwarmBuilder<
247 Provider,
248 BehaviourPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
249 > {
250 self.without_quic()
251 .without_any_other_transports()
252 .without_dns()
253 .without_websocket()
254 .without_relay()
255 .with_bandwidth_metrics(registry)
256 }
257}