diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index 01a95f3..dc56e42 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -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 diff --git a/Cargo.toml b/Cargo.toml index cb9f189..ba66fe2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] diff --git a/src/api.rs b/src/api.rs index 26cd769..bcea1d4 100644 --- a/src/api.rs +++ b/src/api.rs @@ -176,7 +176,6 @@ where (**self).ping() } - #[cfg(feature = "debug-calls")] fn calls_made(&self) -> Result { (**self).calls_made() } @@ -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; } @@ -611,7 +609,6 @@ mod test { unreachable!() } - #[cfg(feature = "debug-calls")] fn calls_made(&self) -> Result { unreachable!() } diff --git a/src/client.rs b/src/client.rs index 1ed336b..15c78f1 100644 --- a/src/client.rs +++ b/src/client.rs @@ -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), #[allow(missing_docs)] SSL(RawClient), #[allow(missing_docs)] + #[cfg(feature = "proxy")] Socks5(RawClient), } @@ -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); @@ -110,6 +112,7 @@ impl ClientType { pub fn from_config(url: &str, config: &Config) -> Result { 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(), @@ -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) } } } @@ -368,7 +380,6 @@ impl ElectrumApi for Client { } #[inline] - #[cfg(feature = "debug-calls")] fn calls_made(&self) -> Result { impl_inner_call!(self, calls_made) } diff --git a/src/lib.rs b/src/lib.rs index 491665a..384156a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 //! @@ -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; @@ -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::*; diff --git a/src/raw_client.rs b/src/raw_client.rs index 5d67467..3a80da8 100644 --- a/src/raw_client.rs +++ b/src/raw_client.rs @@ -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; @@ -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 { @@ -142,7 +136,6 @@ where headers: Mutex>, script_notifications: Mutex>>, - #[cfg(feature = "debug-calls")] calls: AtomicUsize, } @@ -163,7 +156,6 @@ where headers: Mutex::new(VecDeque::new()), script_notifications: Mutex::new(HashMap::new()), - #[cfg(feature = "debug-calls")] calls: AtomicUsize::new(0), } } @@ -228,10 +220,10 @@ fn connect_with_total_timeout( 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; -#[cfg(feature = "use-openssl")] +#[cfg(feature = "openssl")] impl RawClient { /// Creates a new SSL client and tries to connect to `socket_addr`. Optionally, if /// `validate_domain` is `true`, validate the server's certificate. @@ -289,14 +281,8 @@ impl RawClient { } } -#[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}; @@ -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; #[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 { /// Creates a new SSL client and tries to connect to `socket_addr`. Optionally, if @@ -408,7 +386,7 @@ impl RawClient { 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(), ) @@ -418,7 +396,7 @@ impl RawClient { )) })?; - #[cfg(feature = "use-rustls-ring")] + #[cfg(feature = "rustls-ring")] rustls::crypto::CryptoProvider::install_default( rustls::crypto::ring::default_provider(), ) @@ -449,9 +427,9 @@ impl RawClient { 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() @@ -470,10 +448,10 @@ impl RawClient { } } -#[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 { /// 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 @@ -499,10 +477,9 @@ impl RawClient { 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 @@ -762,14 +739,9 @@ impl RawClient { } #[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 ElectrumApi for RawClient { @@ -1190,7 +1162,6 @@ impl ElectrumApi for RawClient { Ok(()) } - #[cfg(feature = "debug-calls")] fn calls_made(&self) -> Result { Ok(self.calls.load(Ordering::SeqCst)) } diff --git a/src/types.rs b/src/types.rs index ce3ef9f..9277be1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -326,14 +326,14 @@ pub enum Error { CouldntLockReader, /// Broken IPC communication channel: the other thread probably has exited Mpsc, - #[cfg(any(feature = "use-rustls", feature = "use-rustls-ring"))] + #[cfg(any(feature = "rustls", feature = "rustls-ring"))] /// Could not create a rustls client connection CouldNotCreateConnection(rustls::Error), - #[cfg(feature = "use-openssl")] + #[cfg(feature = "openssl")] /// Invalid OpenSSL method used InvalidSslMethod(openssl::error::ErrorStack), - #[cfg(feature = "use-openssl")] + #[cfg(feature = "openssl")] /// SSL Handshake failed with the server SslHandshakeError(openssl::ssl::HandshakeError), } @@ -346,13 +346,13 @@ impl Display for Error { Error::Hex(e) => Display::fmt(e, f), Error::Bitcoin(e) => Display::fmt(e, f), Error::SharedIOError(e) => Display::fmt(e, f), - #[cfg(feature = "use-openssl")] + #[cfg(feature = "openssl")] Error::SslHandshakeError(e) => Display::fmt(e, f), - #[cfg(feature = "use-openssl")] + #[cfg(feature = "openssl")] Error::InvalidSslMethod(e) => Display::fmt(e, f), #[cfg(any( - feature = "use-rustls", - feature = "use-rustls-ring", + feature = "rustls", + feature = "rustls-ring", ))] Error::CouldNotCreateConnection(e) => Display::fmt(e, f),