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#[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 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>);