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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
use std::time::Duration;
/// Configuration for an electrum client
///
/// Refer to [`Client::from_config`] and [`ClientType::from_config`].
///
/// [`Client::from_config`]: crate::Client::from_config
/// [`ClientType::from_config`]: crate::ClientType::from_config
#[derive(Debug, Clone)]
pub struct Config {
/// Proxy socks5 configuration, default None
socks5: Option<Socks5Config>,
/// timeout in seconds, default None (depends on TcpStream default)
timeout: Option<Duration>,
/// number of retry if any error, default 1
retry: u8,
/// when ssl, validate the domain, default true
validate_domain: bool,
}
/// Configuration for Socks5
#[derive(Debug, Clone)]
pub struct Socks5Config {
/// The address of the socks5 service
pub addr: String,
/// Optional credential for the service
pub credentials: Option<Socks5Credential>,
}
/// Credential for the proxy
#[derive(Debug, Clone)]
pub struct Socks5Credential {
pub username: String,
pub password: String,
}
/// [Config] Builder
pub struct ConfigBuilder {
config: Config,
}
impl ConfigBuilder {
/// Create a builder with a default config, equivalent to [ConfigBuilder::default()]
pub fn new() -> Self {
ConfigBuilder {
config: Config::default(),
}
}
/// Set the socks5 config if Some, it accept an `Option` because it's easier for the caller to use
/// in a method chain
pub fn socks5(mut self, socks5_config: Option<Socks5Config>) -> Self {
self.config.socks5 = socks5_config;
self
}
/// Sets the timeout
pub fn timeout(mut self, timeout: Option<u8>) -> Self {
self.config.timeout = timeout.map(|t| Duration::from_secs(t as u64));
self
}
/// Sets the retry attempts number
pub fn retry(mut self, retry: u8) -> Self {
self.config.retry = retry;
self
}
/// Sets if the domain has to be validated
pub fn validate_domain(mut self, validate_domain: bool) -> Self {
self.config.validate_domain = validate_domain;
self
}
/// Return the config and consume the builder
pub fn build(self) -> Config {
self.config
}
}
impl Default for ConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl Socks5Config {
/// Socks5Config constructor without credentials
pub fn new(addr: impl ToString) -> Self {
let addr = addr.to_string().replacen("socks5://", "", 1);
Socks5Config {
addr,
credentials: None,
}
}
/// Socks5Config constructor if we have credentials
pub fn with_credentials(addr: impl ToString, username: String, password: String) -> Self {
let mut config = Socks5Config::new(addr);
config.credentials = Some(Socks5Credential { username, password });
config
}
}
impl Config {
/// Get the configuration for `socks5`
///
/// Set this with [`ConfigBuilder::socks5`]
pub fn socks5(&self) -> &Option<Socks5Config> {
&self.socks5
}
/// Get the configuration for `retry`
///
/// Set this with [`ConfigBuilder::retry`]
pub fn retry(&self) -> u8 {
self.retry
}
/// Get the configuration for `timeout`
///
/// Set this with [`ConfigBuilder::timeout`]
pub fn timeout(&self) -> Option<Duration> {
self.timeout
}
/// Get the configuration for `validate_domain`
///
/// Set this with [`ConfigBuilder::validate_domain`]
pub fn validate_domain(&self) -> bool {
self.validate_domain
}
/// Convenience method for calling [`ConfigBuilder::new`]
pub fn builder() -> ConfigBuilder {
ConfigBuilder::new()
}
}
impl Default for Config {
fn default() -> Self {
Config {
socks5: None,
timeout: None,
retry: 1,
validate_domain: true,
}
}
}