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 = "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            /// See [`SwarmBuilder::with_websocket`].
187            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}