libp2p/builder/phase/
other_transport.rs

1use std::{convert::Infallible, marker::PhantomData, sync::Arc};
2
3use libp2p_core::{
4    upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade},
5    Transport,
6};
7#[cfg(feature = "relay")]
8use libp2p_core::{Negotiated, UpgradeInfo};
9#[cfg(feature = "relay")]
10use libp2p_identity::PeerId;
11
12use super::*;
13#[allow(deprecated)]
14use crate::bandwidth::BandwidthSinks;
15use crate::SwarmBuilder;
16
17pub struct OtherTransportPhase<T> {
18    pub(crate) transport: T,
19}
20
21impl<Provider, T: AuthenticatedMultiplexedTransport>
22    SwarmBuilder<Provider, OtherTransportPhase<T>>
23{
24    pub fn with_other_transport<
25        Muxer: libp2p_core::muxing::StreamMuxer + Send + 'static,
26        OtherTransport: Transport<Output = (libp2p_identity::PeerId, Muxer)> + Send + Unpin + 'static,
27        R: TryIntoTransport<OtherTransport>,
28    >(
29        self,
30        constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
31    ) -> Result<
32        SwarmBuilder<Provider, OtherTransportPhase<impl AuthenticatedMultiplexedTransport>>,
33        R::Error,
34    >
35    where
36        <OtherTransport as Transport>::Error: Send + Sync + 'static,
37        <OtherTransport as Transport>::Dial: Send,
38        <OtherTransport as Transport>::ListenerUpgrade: Send,
39        <Muxer as libp2p_core::muxing::StreamMuxer>::Substream: Send,
40        <Muxer as libp2p_core::muxing::StreamMuxer>::Error: Send + Sync,
41    {
42        Ok(SwarmBuilder {
43            phase: OtherTransportPhase {
44                transport: self
45                    .phase
46                    .transport
47                    .or_transport(
48                        constructor(&self.keypair)
49                            .try_into_transport()?
50                            .map(|(peer_id, conn), _| (peer_id, StreamMuxerBox::new(conn))),
51                    )
52                    .map(|either, _| either.into_inner()),
53            },
54            keypair: self.keypair,
55            phantom: PhantomData,
56        })
57    }
58
59    pub(crate) fn without_any_other_transports(self) -> SwarmBuilder<Provider, DnsPhase<T>> {
60        SwarmBuilder {
61            keypair: self.keypair,
62            phantom: PhantomData,
63            phase: DnsPhase {
64                transport: self.phase.transport,
65            },
66        }
67    }
68}
69
70// Shortcuts
71#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
72impl<T: AuthenticatedMultiplexedTransport>
73    SwarmBuilder<super::provider::AsyncStd, OtherTransportPhase<T>>
74{
75    pub fn with_dns(
76        self,
77    ) -> Result<
78        SwarmBuilder<
79            super::provider::AsyncStd,
80            WebsocketPhase<impl AuthenticatedMultiplexedTransport>,
81        >,
82        std::io::Error,
83    > {
84        self.without_any_other_transports().with_dns()
85    }
86}
87#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
88impl<T: AuthenticatedMultiplexedTransport>
89    SwarmBuilder<super::provider::Tokio, OtherTransportPhase<T>>
90{
91    pub fn with_dns(
92        self,
93    ) -> Result<
94        SwarmBuilder<
95            super::provider::Tokio,
96            WebsocketPhase<impl AuthenticatedMultiplexedTransport>,
97        >,
98        std::io::Error,
99    > {
100        self.without_any_other_transports().with_dns()
101    }
102}
103#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
104impl<T: AuthenticatedMultiplexedTransport>
105    SwarmBuilder<super::provider::AsyncStd, OtherTransportPhase<T>>
106{
107    pub fn with_dns_config(
108        self,
109        cfg: libp2p_dns::ResolverConfig,
110        opts: libp2p_dns::ResolverOpts,
111    ) -> SwarmBuilder<
112        super::provider::AsyncStd,
113        WebsocketPhase<impl AuthenticatedMultiplexedTransport>,
114    > {
115        self.without_any_other_transports()
116            .with_dns_config(cfg, opts)
117    }
118}
119#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
120impl<T: AuthenticatedMultiplexedTransport>
121    SwarmBuilder<super::provider::Tokio, OtherTransportPhase<T>>
122{
123    pub fn with_dns_config(
124        self,
125        cfg: libp2p_dns::ResolverConfig,
126        opts: libp2p_dns::ResolverOpts,
127    ) -> SwarmBuilder<super::provider::Tokio, WebsocketPhase<impl AuthenticatedMultiplexedTransport>>
128    {
129        self.without_any_other_transports()
130            .with_dns_config(cfg, opts)
131    }
132}
133#[cfg(feature = "relay")]
134impl<T: AuthenticatedMultiplexedTransport, Provider>
135    SwarmBuilder<Provider, OtherTransportPhase<T>>
136{
137    /// See [`SwarmBuilder::with_relay_client`].
138    pub fn with_relay_client<SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError>(
139        self,
140        security_upgrade: SecUpgrade,
141        multiplexer_upgrade: MuxUpgrade,
142    ) -> Result<
143        SwarmBuilder<
144            Provider,
145            BandwidthLoggingPhase<impl AuthenticatedMultiplexedTransport, libp2p_relay::client::Behaviour>,
146        >,
147        SecUpgrade::Error,
148        > where
149
150        SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
151        SecError: std::error::Error + Send + Sync + 'static,
152        SecUpgrade: IntoSecurityUpgrade<libp2p_relay::client::Connection>,
153        SecUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (PeerId, SecStream), Error = SecError> + OutboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
154    <SecUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
155    <SecUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
156    <<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
157    <<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::Info: Send,
158
159        MuxStream: libp2p_core::muxing::StreamMuxer + Send + 'static,
160        MuxStream::Substream: Send + 'static,
161        MuxStream::Error: Send + Sync + 'static,
162        MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
163        MuxUpgrade::Upgrade: InboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundConnectionUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
164    <MuxUpgrade::Upgrade as InboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
165    <MuxUpgrade::Upgrade as OutboundConnectionUpgrade<Negotiated<SecStream>>>::Future: Send,
166        MuxError: std::error::Error + Send + Sync + 'static,
167    <<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
168    <<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
169    {
170        self.without_any_other_transports()
171            .without_dns()
172            .without_websocket()
173            .with_relay_client(security_upgrade, multiplexer_upgrade)
174    }
175}
176impl<Provider, T: AuthenticatedMultiplexedTransport>
177    SwarmBuilder<Provider, OtherTransportPhase<T>>
178{
179    #[allow(deprecated)]
180    #[deprecated(note = "Use `with_bandwidth_metrics` instead.")]
181    pub fn with_bandwidth_logging(
182        self,
183    ) -> (
184        SwarmBuilder<
185            Provider,
186            BandwidthMetricsPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
187        >,
188        Arc<BandwidthSinks>,
189    ) {
190        #[allow(deprecated)]
191        self.without_any_other_transports()
192            .without_dns()
193            .without_websocket()
194            .without_relay()
195            .with_bandwidth_logging()
196    }
197}
198#[cfg(feature = "metrics")]
199impl<Provider, T: AuthenticatedMultiplexedTransport>
200    SwarmBuilder<Provider, OtherTransportPhase<T>>
201{
202    pub fn with_bandwidth_metrics(
203        self,
204        registry: &mut libp2p_metrics::Registry,
205    ) -> SwarmBuilder<
206        Provider,
207        BehaviourPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
208    > {
209        self.without_any_other_transports()
210            .without_dns()
211            .without_websocket()
212            .without_relay()
213            .without_bandwidth_logging()
214            .with_bandwidth_metrics(registry)
215    }
216}
217impl<Provider, T: AuthenticatedMultiplexedTransport>
218    SwarmBuilder<Provider, OtherTransportPhase<T>>
219{
220    pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
221        self,
222        constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
223    ) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
224        self.without_any_other_transports()
225            .without_dns()
226            .without_websocket()
227            .without_relay()
228            .without_bandwidth_logging()
229            .with_behaviour(constructor)
230    }
231}
232
233pub trait TryIntoTransport<T>: private::Sealed<Self::Error> {
234    type Error;
235
236    fn try_into_transport(self) -> Result<T, Self::Error>;
237}
238
239impl<T: Transport> TryIntoTransport<T> for T {
240    type Error = Infallible;
241
242    fn try_into_transport(self) -> Result<T, Self::Error> {
243        Ok(self)
244    }
245}
246
247impl<T: Transport> TryIntoTransport<T> for Result<T, Box<dyn std::error::Error + Send + Sync>> {
248    type Error = TransportError;
249
250    fn try_into_transport(self) -> Result<T, Self::Error> {
251        self.map_err(TransportError)
252    }
253}
254
255mod private {
256    pub trait Sealed<Error> {}
257}
258
259impl<T: Transport> private::Sealed<Infallible> for T {}
260
261impl<T: Transport> private::Sealed<TransportError>
262    for Result<T, Box<dyn std::error::Error + Send + Sync>>
263{
264}
265
266#[derive(Debug, thiserror::Error)]
267#[error("failed to build transport: {0}")]
268pub struct TransportError(Box<dyn std::error::Error + Send + Sync + 'static>);