libp2p/builder/phase/
quic.rs

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
77// Shortcuts
78impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
79    /// See [`SwarmBuilder::with_relay_client`].
80    #[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            /// See [`SwarmBuilder::with_websocket`].
219            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}