use super::*; use crate::SwarmBuilder; #[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))] use libp2p_core::muxing::StreamMuxer; #[cfg(any( feature = "relay", all(not(target_arch = "wasm32"), feature = "websocket") ))] use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo}; use std::{marker::PhantomData, sync::Arc}; pub struct QuicPhase { pub(crate) transport: T, } macro_rules! impl_quic_builder { ($providerKebabCase:literal, $providerPascalCase:ty, $quic:ident) => { #[cfg(all(not(target_arch = "wasm32"), feature = "quic", feature = $providerKebabCase))] impl SwarmBuilder<$providerPascalCase, QuicPhase> { pub fn with_quic( self, ) -> SwarmBuilder< $providerPascalCase, OtherTransportPhase, > { self.with_quic_config(std::convert::identity) } pub fn with_quic_config( self, constructor: impl FnOnce(libp2p_quic::Config) -> libp2p_quic::Config, ) -> SwarmBuilder< $providerPascalCase, OtherTransportPhase, > { SwarmBuilder { phase: OtherTransportPhase { transport: self .phase .transport .or_transport( libp2p_quic::$quic::Transport::new(constructor( libp2p_quic::Config::new(&self.keypair), )) .map(|(peer_id, muxer), _| { (peer_id, libp2p_core::muxing::StreamMuxerBox::new(muxer)) }), ) .map(|either, _| either.into_inner()), }, keypair: self.keypair, phantom: PhantomData, } } } }; } impl_quic_builder!("async-std", AsyncStd, async_std); impl_quic_builder!("tokio", super::provider::Tokio, tokio); impl SwarmBuilder> { pub(crate) fn without_quic(self) -> SwarmBuilder> { SwarmBuilder { keypair: self.keypair, phantom: PhantomData, phase: OtherTransportPhase { transport: self.phase.transport, }, } } } // Shortcuts impl SwarmBuilder> { /// See [`SwarmBuilder::with_relay_client`]. #[cfg(feature = "relay")] pub fn with_relay_client( self, security_upgrade: SecUpgrade, multiplexer_upgrade: MuxUpgrade, ) -> Result< SwarmBuilder< Provider, super::websocket::WebsocketPhase, >, SecUpgrade::Error, > where SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static, SecError: std::error::Error + Send + Sync + 'static, SecUpgrade: IntoSecurityUpgrade, SecUpgrade::Upgrade: InboundUpgrade, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundUpgrade, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static, >>::Future: Send, >>::Future: Send, <<>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send, <>::Upgrade as UpgradeInfo>::Info: Send, MuxStream: libp2p_core::muxing::StreamMuxer + Send + 'static, MuxStream::Substream: Send + 'static, MuxStream::Error: Send + Sync + 'static, MuxUpgrade: IntoMultiplexerUpgrade, MuxUpgrade::Upgrade: InboundUpgrade, Output = MuxStream, Error = MuxError> + OutboundUpgrade, Output = MuxStream, Error = MuxError> + Clone + Send + 'static, >>::Future: Send, >>::Future: Send, MuxError: std::error::Error + Send + Sync + 'static, <<>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send, <>::Upgrade as UpgradeInfo>::Info: Send, { self.without_quic() .with_relay_client(security_upgrade, multiplexer_upgrade) } pub fn with_other_transport< Muxer: libp2p_core::muxing::StreamMuxer + Send + 'static, OtherTransport: Transport + Send + Unpin + 'static, R: TryIntoTransport, >( self, constructor: impl FnOnce(&libp2p_identity::Keypair) -> R, ) -> Result< SwarmBuilder>, R::Error, > where ::Error: Send + Sync + 'static, ::Dial: Send, ::ListenerUpgrade: Send, ::Substream: Send, ::Error: Send + Sync, { self.without_quic().with_other_transport(constructor) } pub fn with_behaviour>( self, constructor: impl FnOnce(&libp2p_identity::Keypair) -> R, ) -> Result>, R::Error> { self.without_quic() .without_any_other_transports() .without_dns() .without_relay() .without_websocket() .with_behaviour(constructor) } } #[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))] impl SwarmBuilder> { pub async fn with_dns( self, ) -> Result< SwarmBuilder>, std::io::Error, > { self.without_quic() .without_any_other_transports() .with_dns() .await } } #[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))] impl SwarmBuilder> { pub fn with_dns( self, ) -> Result< SwarmBuilder>, std::io::Error, > { self.without_quic() .without_any_other_transports() .with_dns() } } macro_rules! impl_quic_phase_with_websocket { ($providerKebabCase:literal, $providerPascalCase:ty, $websocketStream:ty) => { #[cfg(all(feature = $providerKebabCase, not(target_arch = "wasm32"), feature = "websocket"))] impl SwarmBuilder<$providerPascalCase, QuicPhase> { /// See [`SwarmBuilder::with_websocket`]. pub async fn with_websocket < SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError, > ( self, security_upgrade: SecUpgrade, multiplexer_upgrade: MuxUpgrade, ) -> Result< SwarmBuilder< $providerPascalCase, BandwidthLoggingPhase, >, super::websocket::WebsocketError, > where SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static, SecError: std::error::Error + Send + Sync + 'static, SecUpgrade: IntoSecurityUpgrade<$websocketStream>, SecUpgrade::Upgrade: InboundUpgrade, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundUpgrade, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static, >>::Future: Send, >>::Future: Send, <<>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send, <>::Upgrade as UpgradeInfo>::Info: Send, MuxStream: StreamMuxer + Send + 'static, MuxStream::Substream: Send + 'static, MuxStream::Error: Send + Sync + 'static, MuxUpgrade: IntoMultiplexerUpgrade, MuxUpgrade::Upgrade: InboundUpgrade, Output = MuxStream, Error = MuxError> + OutboundUpgrade, Output = MuxStream, Error = MuxError> + Clone + Send + 'static, >>::Future: Send, >>::Future: Send, MuxError: std::error::Error + Send + Sync + 'static, <<>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send, <>::Upgrade as UpgradeInfo>::Info: Send, { self.without_quic() .without_any_other_transports() .without_dns() .without_relay() .with_websocket(security_upgrade, multiplexer_upgrade) .await } } } } impl_quic_phase_with_websocket!( "async-std", super::provider::AsyncStd, rw_stream_sink::RwStreamSink< libp2p_websocket::BytesConnection, > ); impl_quic_phase_with_websocket!( "tokio", super::provider::Tokio, rw_stream_sink::RwStreamSink> ); impl SwarmBuilder> { pub fn with_bandwidth_logging( self, ) -> ( SwarmBuilder< Provider, BehaviourPhase, >, Arc, ) { self.without_quic() .without_any_other_transports() .without_dns() .without_relay() .without_websocket() .with_bandwidth_logging() } }