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