forked from libp2p/rust-libp2p
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
123 lines (104 loc) · 3.88 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#![doc(html_logo_url = "https://libp2p.io/img/logo_small.png")]
#![doc(html_favicon_url = "https://libp2p.io/img/favicon.png")]
use std::pin::Pin;
use std::sync::Arc;
use address::dangerous_extract_tor_address;
use arti_client::{TorAddrError, TorClient, TorClientBuilder};
use futures::{future::BoxFuture, FutureExt};
use libp2p_core::{transport::TransportError, Multiaddr, Transport};
use tor_rtcompat::PreferredRuntime;
mod address;
mod provider;
#[doc(inline)]
pub use provider::OnionStream;
#[derive(Debug, thiserror::Error)]
pub enum OnionError {
#[error("error during address translation")]
AddrErr(#[from] TorAddrError),
#[error("error in arti")]
ArtiErr(#[from] arti_client::Error),
#[error("onion services are not implented yet, since arti doesn't support it. (awaiting Arti 1.2.0)")]
OnionServiceUnimplemented,
}
#[derive(Clone)]
pub struct OnionClient {
// client is in an Arc, because wihtout it the Transport::Dial method can't be implemented,
// due to lifetime issues. With the, eventual, stabilization of static async traits this issue
// will be resolved.
client: Arc<TorClient<PreferredRuntime>>,
}
pub type OnionBuilder = TorClientBuilder<PreferredRuntime>;
impl OnionClient {
#[inline]
pub fn builder() -> OnionBuilder {
TorClient::builder()
}
#[inline]
pub fn from_builder(builder: OnionBuilder) -> Result<Self, OnionError> {
let client = Arc::new(builder.create_unbootstrapped()?);
Ok(Self { client })
}
pub async fn bootstrap(&self) -> Result<(), OnionError> {
Ok(self.client.bootstrap().await?)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct AlwaysErrorListenerUpgrade;
impl core::future::Future for AlwaysErrorListenerUpgrade {
type Output = Result<OnionStream, OnionError>;
fn poll(
self: std::pin::Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
core::task::Poll::Ready(Err(OnionError::OnionServiceUnimplemented))
}
}
impl Transport for OnionClient {
type Output = OnionStream;
type Error = OnionError;
type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>;
type ListenerUpgrade = AlwaysErrorListenerUpgrade;
/// Always returns `TransportError::MultiaddrNotSupported`
fn listen_on(
&mut self,
addr: libp2p_core::Multiaddr,
) -> Result<
libp2p_core::transport::ListenerId,
libp2p_core::transport::TransportError<Self::Error>,
> {
// although this address might be supported, this is returned in order to not provoke an
// error when trying to listen on this transport.
Err(TransportError::MultiaddrNotSupported(addr))
}
/// Always returns false
fn remove_listener(&mut self, _id: libp2p_core::transport::ListenerId) -> bool {
false
}
fn dial(&mut self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
let tor_address = dangerous_extract_tor_address(&addr)
.map_err(OnionError::from)
.map_err(TransportError::Other)?;
let onion_client = self.client.clone();
Ok(async move { Ok(OnionStream::new(onion_client.connect(tor_address).await?)) }.boxed())
}
/// Equivalent to `Transport::dial`
fn dial_as_listener(
&mut self,
addr: Multiaddr,
) -> Result<Self::Dial, TransportError<Self::Error>> {
self.dial(addr)
}
/// always returns `None`
fn address_translation(&self, _listen: &Multiaddr, _observed: &Multiaddr) -> Option<Multiaddr> {
None
}
/// always returns pending
fn poll(
self: Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<libp2p_core::transport::TransportEvent<Self::ListenerUpgrade, Self::Error>>
{
// pending is returned here, because this won't panic an OrTransport.
std::task::Poll::Pending
}
}