libp2p/builder/phase/
other_transport.rs

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