libp2p/builder/phase/
other_transport.rs

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