Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/cont_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ jobs:
run: cargo test -- --ignored test_local_timeout
- run: cargo check --verbose --features=use-openssl
- run: cargo check --verbose --no-default-features --features=proxy
- run: cargo check --verbose --no-default-features --features=minimal
- run: cargo check --verbose --no-default-features --features=minimal,debug-calls
- run: cargo check --verbose --no-default-features --features=proxy,use-openssl
- run: cargo check --verbose --no-default-features --features=proxy,use-rustls
- run: cargo check --verbose --no-default-features --features=proxy,use-rustls-ring
Expand Down
13 changes: 8 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ libc = { version = "0.2", optional = true }
winapi = { version="0.3.9", features=["winsock2"], optional = true }

[features]
default = ["proxy", "use-rustls"]
minimal = []
debug-calls = []
default = ["proxy", "rustls"]
proxy = ["byteorder", "winapi", "libc"]
use-rustls = ["webpki-roots", "rustls/default"]
use-rustls-ring = ["webpki-roots", "rustls/ring", "rustls/logging", "rustls/std", "rustls/tls12"]
rustls = ["webpki-roots", "dep:rustls", "rustls/default"]
rustls-ring = ["webpki-roots", "dep:rustls", "rustls/ring", "rustls/logging", "rustls/std", "rustls/tls12"]
openssl = ["dep:openssl"]

# Old feature names
use-rustls = ["rustls"]
use-rustls-ring = ["rustls-ring"]
use-openssl = ["openssl"]
3 changes: 0 additions & 3 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ where
(**self).ping()
}

#[cfg(feature = "debug-calls")]
fn calls_made(&self) -> Result<usize, Error> {
(**self).calls_made()
}
Expand Down Expand Up @@ -402,7 +401,6 @@ pub trait ElectrumApi {
/// of incoming block header or script notifications.
fn ping(&self) -> Result<(), Error>;

#[cfg(feature = "debug-calls")]
/// Returns the number of network calls made since the creation of the client.
fn calls_made(&self) -> Result<usize, Error>;
}
Expand Down Expand Up @@ -611,7 +609,6 @@ mod test {
unreachable!()
}

#[cfg(feature = "debug-calls")]
fn calls_made(&self) -> Result<usize, super::Error> {
unreachable!()
}
Expand Down
21 changes: 16 additions & 5 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ use std::convert::TryFrom;
/// [`RawClient`](client/struct.RawClient.html) and provides a more user-friendly
/// constructor that can choose the right backend based on the url prefix.
///
/// **This is available only with the `default` features, or if `proxy` and one ssl implementation are enabled**
/// **Note the `Socks5` client type requires the "proxy" feature to be enabled.**
pub enum ClientType {
#[allow(missing_docs)]
TCP(RawClient<ElectrumPlaintextStream>),
#[allow(missing_docs)]
SSL(RawClient<ElectrumSslStream>),
#[allow(missing_docs)]
#[cfg(feature = "proxy")]
Socks5(RawClient<ElectrumProxyStream>),
}

Expand All @@ -44,6 +45,7 @@ macro_rules! impl_inner_call {
let res = match &*read_client {
ClientType::TCP(inner) => inner.$name( $($args, )* ),
ClientType::SSL(inner) => inner.$name( $($args, )* ),
#[cfg(feature = "proxy")]
ClientType::Socks5(inner) => inner.$name( $($args, )* ),
};
drop(read_client);
Expand Down Expand Up @@ -110,6 +112,7 @@ impl ClientType {
pub fn from_config(url: &str, config: &Config) -> Result<Self, Error> {
if url.starts_with("ssl://") {
let url = url.replacen("ssl://", "", 1);
#[cfg(feature = "proxy")]
let client = match config.socks5() {
Some(socks5) => RawClient::new_proxy_ssl(
url.as_str(),
Expand All @@ -121,19 +124,28 @@ impl ClientType {
RawClient::new_ssl(url.as_str(), config.validate_domain(), config.timeout())?
}
};
#[cfg(not(feature = "proxy"))]
let client =
RawClient::new_ssl(url.as_str(), config.validate_domain(), config.timeout())?;

Ok(ClientType::SSL(client))
} else {
let url = url.replacen("tcp://", "", 1);

Ok(match config.socks5().as_ref() {
None => ClientType::TCP(RawClient::new(url.as_str(), config.timeout())?),
#[cfg(feature = "proxy")]
let client = match config.socks5() {
Some(socks5) => ClientType::Socks5(RawClient::new_proxy(
url.as_str(),
socks5,
config.timeout(),
)?),
})
None => ClientType::TCP(RawClient::new(url.as_str(), config.timeout())?),
};

#[cfg(not(feature = "proxy"))]
let client = ClientType::TCP(RawClient::new(url.as_str(), config.timeout())?);

Ok(client)
}
}
}
Expand Down Expand Up @@ -368,7 +380,6 @@ impl ElectrumApi for Client {
}

#[inline]
#[cfg(feature = "debug-calls")]
fn calls_made(&self) -> Result<usize, Error> {
impl_inner_call!(self, calls_made)
}
Expand Down
39 changes: 10 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! plaintext connections over a socks proxy, useful for Onion servers. Using different features,
//! the SSL implementation can be removed or replaced with [`openssl`](https://docs.rs/openssl).
//!
//! A `minimal` configuration is also provided, which only includes the plaintext TCP client.
//! For a minimal configuration the library can be built with `--no-default-features`, which only includes the plaintext TCP client.
//!
//! # Example
//!
Expand All @@ -22,46 +22,31 @@
pub extern crate bitcoin;
extern crate core;
extern crate log;
#[cfg(feature = "use-openssl")]
#[cfg(feature = "openssl")]
extern crate openssl;
#[cfg(all(
any(
feature = "default",
feature = "use-rustls",
feature = "use-rustls-ring"
),
not(feature = "use-openssl")
))]
#[cfg(any(feature = "rustls", feature = "rustls-ring"))]
extern crate rustls;
extern crate serde;
extern crate serde_json;

#[cfg(any(
feature = "default",
feature = "use-rustls",
feature = "use-rustls-ring"
))]
#[cfg(any(feature = "rustls", feature = "rustls-ring"))]
extern crate webpki_roots;

#[cfg(any(feature = "default", feature = "proxy"))]
#[cfg(feature = "proxy")]
extern crate byteorder;

#[cfg(all(unix, any(feature = "default", feature = "proxy")))]
#[cfg(all(unix, feature = "proxy"))]
extern crate libc;
#[cfg(all(windows, any(feature = "default", feature = "proxy")))]
#[cfg(all(windows, feature = "proxy"))]
extern crate winapi;

#[cfg(any(feature = "default", feature = "proxy"))]
#[cfg(feature = "proxy")]
pub mod socks;

mod api;
mod batch;

#[cfg(any(
all(feature = "proxy", feature = "use-openssl"),
all(feature = "proxy", feature = "use-rustls"),
all(feature = "proxy", feature = "use-rustls-ring")
))]
#[cfg(any(feature = "openssl", feature = "rustls", feature = "rustls-ring"))]
pub mod client;

mod config;
Expand All @@ -73,11 +58,7 @@ pub mod utils;

pub use api::ElectrumApi;
pub use batch::Batch;
#[cfg(any(
all(feature = "proxy", feature = "use-openssl"),
all(feature = "proxy", feature = "use-rustls"),
all(feature = "proxy", feature = "use-rustls-ring")
))]
#[cfg(any(feature = "openssl", feature = "rustls", feature = "rustls-ring"))]
pub use client::*;
pub use config::{Config, ConfigBuilder, Socks5Config};
pub use types::*;
73 changes: 22 additions & 51 deletions src/raw_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,18 @@ use bitcoin::consensus::encode::deserialize;
use bitcoin::hex::{DisplayHex, FromHex};
use bitcoin::{Script, Txid};

#[cfg(feature = "use-openssl")]
#[cfg(feature = "openssl")]
use openssl::ssl::{SslConnector, SslMethod, SslStream, SslVerifyMode};

#[cfg(all(
any(
feature = "default",
feature = "use-rustls",
feature = "use-rustls-ring"
),
not(feature = "use-openssl")
))]
#[cfg(any(feature = "rustls", feature = "rustls-ring"))]
#[allow(unused_imports)]
use rustls::{
pki_types::ServerName,
pki_types::{Der, TrustAnchor},
ClientConfig, ClientConnection, RootCertStore, StreamOwned,
};

#[cfg(any(feature = "default", feature = "proxy"))]
#[cfg(feature = "proxy")]
use crate::socks::{Socks5Stream, TargetAddr, ToTargetAddr};

use crate::stream::ClonableStream;
Expand Down Expand Up @@ -93,7 +87,7 @@ impl ToSocketAddrsDomain for (&str, u16) {
}
}

#[cfg(any(feature = "default", feature = "proxy"))]
#[cfg(feature = "proxy")]
impl ToSocketAddrsDomain for TargetAddr {
fn domain(&self) -> Option<&str> {
match self {
Expand Down Expand Up @@ -142,7 +136,6 @@ where
headers: Mutex<VecDeque<RawHeaderNotification>>,
script_notifications: Mutex<HashMap<ScriptHash, VecDeque<ScriptStatus>>>,

#[cfg(feature = "debug-calls")]
calls: AtomicUsize,
}

Expand All @@ -163,7 +156,6 @@ where
headers: Mutex::new(VecDeque::new()),
script_notifications: Mutex::new(HashMap::new()),

#[cfg(feature = "debug-calls")]
calls: AtomicUsize::new(0),
}
}
Expand Down Expand Up @@ -228,10 +220,10 @@ fn connect_with_total_timeout<A: ToSocketAddrs>(
Err(Error::AllAttemptsErrored(errors))
}

#[cfg(feature = "use-openssl")]
#[cfg(feature = "openssl")]
/// Transport type used to establish an OpenSSL TLS encrypted/authenticated connection with the server
pub type ElectrumSslStream = SslStream<TcpStream>;
#[cfg(feature = "use-openssl")]
#[cfg(feature = "openssl")]
impl RawClient<ElectrumSslStream> {
/// Creates a new SSL client and tries to connect to `socket_addr`. Optionally, if
/// `validate_domain` is `true`, validate the server's certificate.
Expand Down Expand Up @@ -289,14 +281,8 @@ impl RawClient<ElectrumSslStream> {
}
}

#[cfg(all(
any(
feature = "default",
feature = "use-rustls",
feature = "use-rustls-ring"
),
not(feature = "use-openssl")
))]
#[cfg(any(feature = "rustls", feature = "rustls-ring"))]
#[allow(unused)]
mod danger {
use crate::raw_client::ServerName;
use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified};
Expand Down Expand Up @@ -350,22 +336,14 @@ mod danger {
}

#[cfg(all(
any(
feature = "default",
feature = "use-rustls",
feature = "use-rustls-ring"
),
not(feature = "use-openssl")
any(feature = "rustls", feature = "rustls-ring"),
not(feature = "openssl")
))]
/// Transport type used to establish a Rustls TLS encrypted/authenticated connection with the server
pub type ElectrumSslStream = StreamOwned<ClientConnection, TcpStream>;
#[cfg(all(
any(
feature = "default",
feature = "use-rustls",
feature = "use-rustls-ring"
),
not(feature = "use-openssl")
any(feature = "rustls", feature = "rustls-ring"),
not(feature = "openssl")
))]
impl RawClient<ElectrumSslStream> {
/// Creates a new SSL client and tries to connect to `socket_addr`. Optionally, if
Expand Down Expand Up @@ -408,7 +386,7 @@ impl RawClient<ElectrumSslStream> {

if rustls::crypto::CryptoProvider::get_default().is_none() {
// We install a crypto provider depending on the set feature.
#[cfg(all(feature = "use-rustls", not(feature = "use-rustls-ring")))]
#[cfg(all(feature = "rustls", not(feature = "rustls-ring")))]
rustls::crypto::CryptoProvider::install_default(
rustls::crypto::aws_lc_rs::default_provider(),
)
Expand All @@ -418,7 +396,7 @@ impl RawClient<ElectrumSslStream> {
))
})?;

#[cfg(feature = "use-rustls-ring")]
#[cfg(feature = "rustls-ring")]
rustls::crypto::CryptoProvider::install_default(
rustls::crypto::ring::default_provider(),
)
Expand Down Expand Up @@ -449,9 +427,9 @@ impl RawClient<ElectrumSslStream> {
builder
.dangerous()
.with_custom_certificate_verifier(std::sync::Arc::new(
#[cfg(all(feature = "use-rustls", not(feature = "use-rustls-ring")))]
#[cfg(all(feature = "rustls", not(feature = "rustls-ring")))]
danger::NoCertificateVerification::new(rustls::crypto::aws_lc_rs::default_provider()),
#[cfg(feature = "use-rustls-ring")]
#[cfg(feature = "rustls-ring")]
danger::NoCertificateVerification::new(rustls::crypto::ring::default_provider()),
))
.with_no_client_auth()
Expand All @@ -470,10 +448,10 @@ impl RawClient<ElectrumSslStream> {
}
}

#[cfg(any(feature = "default", feature = "proxy"))]
#[cfg(feature = "proxy")]
/// Transport type used to establish a connection to a server through a socks proxy
pub type ElectrumProxyStream = Socks5Stream;
#[cfg(any(feature = "default", feature = "proxy"))]
#[cfg(feature = "proxy")]
impl RawClient<ElectrumProxyStream> {
/// Creates a new socks client and tries to connect to `target_addr` using `proxy_addr` as a
/// socks proxy server. The DNS resolution of `target_addr`, if required, is done
Expand All @@ -499,10 +477,9 @@ impl RawClient<ElectrumProxyStream> {
Ok(stream.into())
}

#[cfg(any(
feature = "use-openssl",
feature = "use-rustls",
feature = "use-rustls-ring"
#[cfg(all(
any(feature = "openssl", feature = "rustls", feature = "rustls-ring",),
feature = "proxy",
))]
/// Creates a new TLS client that connects to `target_addr` using `proxy_addr` as a socks proxy
/// server. The DNS resolution of `target_addr`, if required, is done through the proxy. This
Expand Down Expand Up @@ -762,14 +739,9 @@ impl<S: Read + Write> RawClient<S> {
}

#[inline]
#[cfg(feature = "debug-calls")]
fn increment_calls(&self) {
self.calls.fetch_add(1, Ordering::SeqCst);
}

#[inline]
#[cfg(not(feature = "debug-calls"))]
fn increment_calls(&self) {}
}

impl<T: Read + Write> ElectrumApi for RawClient<T> {
Expand Down Expand Up @@ -1190,7 +1162,6 @@ impl<T: Read + Write> ElectrumApi for RawClient<T> {
Ok(())
}

#[cfg(feature = "debug-calls")]
fn calls_made(&self) -> Result<usize, Error> {
Ok(self.calls.load(Ordering::SeqCst))
}
Expand Down
Loading
Loading