diff --git a/Cargo.toml b/Cargo.toml index 437aa435..abd18e36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ tokio = { version = "1.12.0", features = ["sync"] } tracing = "~0.1.26" webpki = "~0.21.3" rustls = { version = "0.20.2", default-features = false, features = ["quic", "dangerous_configuration"] } +structopt = {version = "0.3.25", optional = true} [dev-dependencies] color-eyre = "0.5.11" diff --git a/src/config.rs b/src/config.rs index 25391eaf..b4592edb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,6 +15,9 @@ use rustls::{Certificate, ClientConfig, ServerName}; use serde::{Deserialize, Serialize}; use std::{future::Future, net::IpAddr, sync::Arc, time::Duration}; +#[cfg(feature = "structopt")] +use structopt::StructOpt; + /// Default for [`Config::upnp_lease_duration`] (2 minutes). pub const DEFAULT_UPNP_LEASE_DURATION: Duration = Duration::from_secs(120); @@ -23,6 +26,8 @@ pub const DEFAULT_UPNP_LEASE_DURATION: Duration = Duration::from_secs(120); /// Together with the default max and multiplier, /// gives 5-6 retries in ~30 s total retry time. pub const DEFAULT_INITIAL_RETRY_INTERVAL: Duration = Duration::from_millis(500); +#[cfg(feature = "structopt")] +const DEFAULT_INITIAL_RETRY_INTERVAL_STR: &str = "500"; /// Default for [`Config::idle_timeout`] (18seconds). /// @@ -34,18 +39,26 @@ pub const DEFAULT_IDLE_TIMEOUT: Duration = Duration::from_secs(18); /// Together with the default min and multiplier, /// gives 5-6 retries in ~30 s total retry time. pub const DEFAULT_MAX_RETRY_INTERVAL: Duration = Duration::from_secs(15); +#[cfg(feature = "structopt")] +const DEFAULT_MAX_RETRY_INTERVAL_STR: &str = "15"; /// Default for [`RetryConfig::retry_delay_multiplier`] (x1.5). /// /// Together with the default max and initial, /// gives 5-6 retries in ~30 s total retry time. pub const DEFAULT_RETRY_INTERVAL_MULTIPLIER: f64 = 1.5; +#[cfg(feature = "structopt")] +const DEFAULT_RETRY_INTERVAL_MULTIPLIER_STR: &str = "1.5"; /// Default for [`RetryConfig::retry_delay_rand_factor`] (0.3). pub const DEFAULT_RETRY_DELAY_RAND_FACTOR: f64 = 0.3; +#[cfg(feature = "structopt")] +const DEFAULT_RETRY_DELAY_RAND_FACTOR_STR: &str = "0.3"; /// Default for [`RetryConfig::retrying_max_elapsed_time`] (30 s). pub const DEFAULT_RETRYING_MAX_ELAPSED_TIME: Duration = Duration::from_secs(30); +#[cfg(feature = "structopt")] +const DEFAULT_RETRYING_MAX_ELAPSED_TIME_STR: &str = "30"; // We use a hard-coded server name for self-signed certificates. pub(crate) const SERVER_NAME: &str = "maidsafe.net"; @@ -88,21 +101,25 @@ pub struct CertificateGenerationError( ); /// QuicP2p configurations +#[cfg_attr(feature = "structopt", derive(StructOpt))] #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct Config { /// Specify if port forwarding via UPnP should be done or not. This can be set to false if the network /// is run locally on the network loopback or on a local area network. #[cfg(feature = "igd")] + #[cfg_attr(feature = "structopt", structopt(long))] pub forward_port: bool, /// External port number assigned to the socket address of the program. /// If this is provided, QP2p considers that the local port provided has been mapped to the /// provided external port number and automatic port forwarding will be skipped. + #[cfg_attr(feature = "structopt", structopt(long))] pub external_port: Option, /// External IP address of the computer on the WAN. This field is mandatory if the node is the genesis node and /// port forwarding is not available. In case of non-genesis nodes, the external IP address will be resolved /// using the Echo service. + #[cfg_attr(feature = "structopt", structopt(long))] pub external_ip: Option, /// How long to wait to hear from a peer before timing out a connection. @@ -112,6 +129,7 @@ pub struct Config { /// /// If unspecified, this will default to [`DEFAULT_IDLE_TIMEOUT`]. #[serde(default)] + #[cfg_attr(feature = "structopt", structopt(long, parse(try_from_str = parse_millis), value_name = "MILLIS"))] pub idle_timeout: Option, /// Interval at which to send keep-alives to maintain otherwise idle connections. @@ -120,6 +138,7 @@ pub struct Config { /// /// If unspecified, this will default to `None`, disabling keep-alives. #[serde(default)] + #[cfg_attr(feature = "structopt", structopt(long, parse(try_from_str = parse_millis), value_name = "MILLIS"))] pub keep_alive_interval: Option, /// How long UPnP port mappings will last. @@ -129,22 +148,31 @@ pub struct Config { /// If unspecified, this will default to [`DEFAULT_UPNP_LEASE_DURATION`], which should be /// suitable in most cases but some routers may clear UPnP port mapping more frequently. #[serde(default)] + #[cfg_attr(feature = "structopt", structopt(long, parse(try_from_str = parse_millis), value_name = "MILLIS"))] pub upnp_lease_duration: Option, /// Retry configurations for establishing connections and sending messages. /// Determines the retry behaviour of requests, by setting the back off strategy used. #[serde(default)] + #[cfg_attr(feature = "structopt", structopt(flatten))] pub retry_config: RetryConfig, } +#[cfg(feature = "structopt")] +fn parse_millis(millis: &str) -> Result { + Ok(Duration::from_millis(millis.parse()?)) +} + /// Retry configurations for establishing connections and sending messages. /// Determines the retry behaviour of requests, by setting the back off strategy used. +#[cfg_attr(feature = "structopt", derive(StructOpt))] #[derive(Clone, Debug, Copy, Serialize, Deserialize)] pub struct RetryConfig { /// The initial retry interval. /// /// This is the first delay before a retry, for establishing connections and sending messages. /// The subsequent delay will be decided by the `retry_delay_multiplier`. + #[cfg_attr(feature = "structopt", structopt(long, default_value = DEFAULT_INITIAL_RETRY_INTERVAL_STR, parse(try_from_str = parse_millis), value_name = "MILLIS"))] pub initial_retry_interval: Duration, /// The maximum value of the back off period. Once the retry interval reaches this /// value it stops increasing. @@ -154,18 +182,22 @@ pub struct RetryConfig { /// Retrying continues even after the duration times have reached this duration. /// The number of retries before that happens, will be decided by the `retry_delay_multiplier`. /// The number of retries after that, will be decided by the `retrying_max_elapsed_time`. + #[cfg_attr(feature = "structopt", structopt(long, default_value = DEFAULT_MAX_RETRY_INTERVAL_STR, parse(try_from_str = parse_millis), value_name = "MILLIS"))] pub max_retry_interval: Duration, /// The value to multiply the current interval with for each retry attempt. + #[cfg_attr(feature = "structopt", structopt(long, default_value = DEFAULT_RETRY_INTERVAL_MULTIPLIER_STR))] pub retry_delay_multiplier: f64, /// The randomization factor to use for creating a range around the retry interval. /// /// A randomization factor of 0.5 results in a random period ranging between 50% below and 50% /// above the retry interval. + #[cfg_attr(feature = "structopt", structopt(long, default_value = DEFAULT_RETRY_DELAY_RAND_FACTOR_STR))] pub retry_delay_rand_factor: f64, /// The maximum elapsed time after instantiating /// /// Retrying continues until this time has elapsed. /// The number of retries before that happens, will be decided by the other retry config options. + #[cfg_attr(feature = "structopt", structopt(long, default_value = DEFAULT_RETRYING_MAX_ELAPSED_TIME_STR, parse(try_from_str = parse_millis), value_name = "MILLIS"))] pub retrying_max_elapsed_time: Duration, }