diff --git a/tentacle/src/runtime/tokio_runtime/mod.rs b/tentacle/src/runtime/tokio_runtime/mod.rs index e74dc4f2..7415d33e 100644 --- a/tentacle/src/runtime/tokio_runtime/mod.rs +++ b/tentacle/src/runtime/tokio_runtime/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod socks5; +use multiaddr::MultiAddr; use socks5::Socks5Config; pub use tokio::{ net::{TcpListener, TcpStream}, @@ -147,3 +148,10 @@ pub(crate) async fn connect( } } } + +pub(crate) async fn connect_tor_proxy( + onion_addr: MultiAddr, + tcp_config: TcpSocketConfig, +) -> io::Result { + todo!("connect multiaddr by proxy"); +} diff --git a/tentacle/src/transports/mod.rs b/tentacle/src/transports/mod.rs index 9078273c..9b3ffe59 100644 --- a/tentacle/src/transports/mod.rs +++ b/tentacle/src/transports/mod.rs @@ -16,6 +16,8 @@ mod browser; #[cfg(not(target_family = "wasm"))] mod memory; #[cfg(not(target_family = "wasm"))] +mod onion; +#[cfg(not(target_family = "wasm"))] mod tcp; #[cfg(not(target_family = "wasm"))] mod tcp_base_listen; @@ -95,6 +97,8 @@ mod os { }; use futures::{prelude::Stream, FutureExt, StreamExt}; + use multiaddr::MultiAddr; + use onion::OnionTransport; use std::{ collections::HashMap, fmt, @@ -162,7 +166,7 @@ mod os { fn listen(self, address: Multiaddr) -> Result { match find_type(&address) { - TransportType::Tcp => { + TransportType::Tcp | TransportType::Onion => { match TcpTransport::from_multi_transport(self, TcpListenMode::Tcp) .listen(address) { @@ -216,6 +220,12 @@ mod os { Err(e) => Err(e), } } + TransportType::Onion => { + match OnionTransport::new(self.timeout, self.tcp_config.tcp).dial(address) { + Ok(res) => Ok(MultiDialFuture::Tcp(res)), + Err(e) => Err(e), + } + } #[cfg(feature = "ws")] TransportType::Ws => { match WsTransport::new(self.timeout, self.tcp_config.ws).dial(address) { @@ -436,6 +446,24 @@ mod os { Ok(res) => res.map_err(Into::into), } } + + /// onion common dial realization + #[inline(always)] + pub async fn onion_dial( + onion_addr: MultiAddr, + tcp_config: TcpSocketConfig, + timeout: Duration, + ) -> Result { + match crate::runtime::timeout( + timeout, + crate::runtime::connect_tor_proxy(onion_addr, tcp_config), + ) + .await + { + Err(_) => Err(TransportErrorKind::Io(io::ErrorKind::TimedOut.into())), + Ok(res) => res.map_err(Into::into), + } + } } #[cfg(target_family = "wasm")] diff --git a/tentacle/src/transports/onion.rs b/tentacle/src/transports/onion.rs new file mode 100644 index 00000000..63b3b76f --- /dev/null +++ b/tentacle/src/transports/onion.rs @@ -0,0 +1,62 @@ +use futures::future::ok; +use std::{ + collections::HashMap, future::Future, net::SocketAddr, pin::Pin, sync::Arc, time::Duration, +}; + +#[cfg(feature = "tls")] +use crate::service::TlsConfig; +use crate::{ + multiaddr::Multiaddr, + runtime::TcpStream, + service::config::TcpSocketConfig, + transports::{ + onion_dial, tcp_base_listen::UpgradeMode, Result, TcpListenMode, TransportDial, + TransportFuture, + }, +}; + +/// Onion connect +async fn connect( + onion_address: impl Future>, + timeout: Duration, + tcp_config: TcpSocketConfig, +) -> Result<(Multiaddr, TcpStream)> { + let onion_addr = onion_address.await?; + let stream = onion_dial(onion_addr.clone(), tcp_config, timeout).await?; + Ok((addr, stream)) +} + +/// Onion transport +pub struct OnionTransport { + timeout: Duration, + tcp_config: TcpSocketConfig, + listen_mode: TcpListenMode, + global: Arc>>, + #[cfg(feature = "tls")] + tls_config: TlsConfig, +} + +impl OnionTransport { + pub fn new(timeout: Duration, tcp_config: TcpSocketConfig) -> Self { + Self { + timeout, + tcp_config, + listen_mode: TcpListenMode::Tcp, + global: Arc::new(crate::lock::Mutex::new(Default::default())), + #[cfg(feature = "tls")] + tls_config: Default::default(), + } + } +} + +pub type OnionDialFuture = + TransportFuture> + Send>>>; + +impl TransportDial for OnionTransport { + type DialFuture = OnionDialFuture; + + fn dial(self, address: Multiaddr) -> Result { + let dial = connect(ok(address), self.timeout, self.tcp_config); + Ok(TransportFuture::new(Box::pin(dial))) + } +} diff --git a/tentacle/src/utils.rs b/tentacle/src/utils.rs index a35894ae..1e83b035 100644 --- a/tentacle/src/utils.rs +++ b/tentacle/src/utils.rs @@ -127,6 +127,8 @@ pub enum TransportType { Tls, /// Memory Memory, + /// Onion + Onion, } /// Confirm the transport used by multiaddress @@ -142,6 +144,8 @@ pub fn find_type(addr: &Multiaddr) -> TransportType { Some(TransportType::Tls) } else if let Protocol::Memory(_) = proto { Some(TransportType::Memory) + } else if let Protocol::Onion3(_) = proto { + Some(TransportType::Onion) } else { None } diff --git a/tentacle/src/utils/dns.rs b/tentacle/src/utils/dns.rs index edf39b96..d38e689b 100644 --- a/tentacle/src/utils/dns.rs +++ b/tentacle/src/utils/dns.rs @@ -1,4 +1,5 @@ use futures::FutureExt; +use log::warn; use std::{ borrow::Cow, future::Future, @@ -86,6 +87,9 @@ impl DnsResolver { } TransportType::Ws => address.push(Protocol::Ws), TransportType::Wss => address.push(Protocol::Wss), + TransportType::Onion => { + warn!("Onion transport type should not have dns resolve") + } } if let Some(peer_id) = self.peer_id.take() {