Move ArtiConfig to new arti::cfg module
Code motion and import fixups.
This commit is contained in:
parent
ff05ed61d7
commit
8aea5c9e43
|
@ -89,6 +89,7 @@ dependencies = [
|
||||||
"rlimit",
|
"rlimit",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tor-config",
|
||||||
"tor-error",
|
"tor-error",
|
||||||
"tor-rtcompat",
|
"tor-rtcompat",
|
||||||
"tor-socksproto",
|
"tor-socksproto",
|
||||||
|
@ -105,6 +106,7 @@ name = "arti-bench"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"arti",
|
||||||
"arti-client",
|
"arti-client",
|
||||||
"arti-config",
|
"arti-config",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -193,6 +195,7 @@ name = "arti-testing"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"arti",
|
||||||
"arti-client",
|
"arti-client",
|
||||||
"arti-config",
|
"arti-config",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -869,18 +872,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_builder"
|
name = "derive_builder"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ddd8db2d51ce241afb74f9e5cf9482de69c4b77657c2ddaf78993eda8ce2ce8c"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_builder_macro",
|
"derive_builder_macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_builder_core"
|
name = "derive_builder_core"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fcf03b84d76c5bb011d983c17e2675ab49f5498f121bf1ceae5b5855b4a4dddd"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -890,9 +889,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_builder_macro"
|
name = "derive_builder_macro"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5cae44c47bca4fd1eaeda52b3d0eecb664ddcbc0d4e7b238bae7ec2c931646c0"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_builder_core",
|
"derive_builder_core",
|
||||||
"syn",
|
"syn",
|
||||||
|
|
|
@ -22,6 +22,7 @@ tracing = "0.1.18"
|
||||||
tracing-subscriber = { version = "0.3.0", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.0", features = ["env-filter"] }
|
||||||
tokio = { version = "1.7", features = ["full"] }
|
tokio = { version = "1.7", features = ["full"] }
|
||||||
tor-rtcompat = { path="../tor-rtcompat", version = "0.1.0", features = ["tokio", "native-tls"] }
|
tor-rtcompat = { path="../tor-rtcompat", version = "0.1.0", features = ["tokio", "native-tls"] }
|
||||||
|
arti = { path="../arti", version = "0.1.0"}
|
||||||
arti-config = { path="../arti-config", version = "0.1.0"}
|
arti-config = { path="../arti-config", version = "0.1.0"}
|
||||||
arti-client = { package="arti-client", path = "../arti-client", version = "0.1.0"}
|
arti-client = { package="arti-client", path = "../arti-client", version = "0.1.0"}
|
||||||
tokio-socks = "0.5"
|
tokio-socks = "0.5"
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
#![allow(clippy::unwrap_used)]
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use arti::cfg::ArtiConfig;
|
||||||
use arti_client::{IsolationToken, TorAddr, TorClient, TorClientConfig};
|
use arti_client::{IsolationToken, TorAddr, TorClient, TorClientConfig};
|
||||||
use arti_config::ArtiConfig;
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use rand::distributions::Standard;
|
use rand::distributions::Standard;
|
||||||
|
|
|
@ -52,9 +52,8 @@ mod options;
|
||||||
|
|
||||||
pub use cmdline::CmdLine;
|
pub use cmdline::CmdLine;
|
||||||
pub use options::{
|
pub use options::{
|
||||||
ApplicationConfig, ApplicationConfigBuilder, ArtiConfig, ArtiConfigBuilder, LogRotation,
|
ApplicationConfig, ApplicationConfigBuilder, LogRotation, LogfileConfig, LogfileConfigBuilder,
|
||||||
LogfileConfig, LogfileConfigBuilder, LoggingConfig, LoggingConfigBuilder, ProxyConfig,
|
LoggingConfig, LoggingConfigBuilder, ProxyConfig, ProxyConfigBuilder, ARTI_DEFAULTS,
|
||||||
ProxyConfigBuilder,
|
|
||||||
};
|
};
|
||||||
use tor_config::CfgPath;
|
use tor_config::CfgPath;
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
//! Handling for arti's configuration formats.
|
//! Handling for arti's configuration formats.
|
||||||
|
|
||||||
use arti_client::config::{
|
|
||||||
SystemConfig, SystemConfigBuilder, TorClientConfig, TorClientConfigBuilder,
|
|
||||||
};
|
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::convert::TryFrom;
|
|
||||||
use tor_config::{CfgPath, ConfigBuildError};
|
use tor_config::{CfgPath, ConfigBuildError};
|
||||||
|
|
||||||
/// Default options to use for our configuration.
|
/// Default options to use for our configuration.
|
||||||
pub(crate) const ARTI_DEFAULTS: &str = concat!(include_str!("./arti_defaults.toml"),);
|
//
|
||||||
|
// TODO should this be in `arti::cfg` ?
|
||||||
|
pub const ARTI_DEFAULTS: &str = concat!(include_str!("./arti_defaults.toml"),);
|
||||||
|
|
||||||
/// Structure to hold our application configuration options
|
/// Structure to hold our application configuration options
|
||||||
#[derive(Deserialize, Debug, Default, Clone, Builder, Eq, PartialEq)]
|
#[derive(Deserialize, Debug, Default, Clone, Builder, Eq, PartialEq)]
|
||||||
|
@ -207,256 +205,3 @@ impl ProxyConfig {
|
||||||
self.dns_port
|
self.dns_port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Structure to hold Arti's configuration options, whether from a
|
|
||||||
/// configuration file or the command line.
|
|
||||||
//
|
|
||||||
/// These options are declared in a public crate outside of `arti` so that other
|
|
||||||
/// applications can parse and use them, if desired. If you're only embedding
|
|
||||||
/// arti via `arti-client`, and you don't want to use Arti's configuration
|
|
||||||
/// format, use [`arti_client::TorClientConfig`] instead.
|
|
||||||
///
|
|
||||||
/// By default, Arti will run using the default Tor network, store state and
|
|
||||||
/// cache information to a per-user set of directories shared by all
|
|
||||||
/// that user's applications, and run a SOCKS client on a local port.
|
|
||||||
///
|
|
||||||
/// NOTE: These are NOT the final options or their final layout. Expect NO
|
|
||||||
/// stability here.
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
|
||||||
pub struct ArtiConfig {
|
|
||||||
/// Configuration for application behavior.
|
|
||||||
application: ApplicationConfig,
|
|
||||||
|
|
||||||
/// Configuration for proxy listeners
|
|
||||||
proxy: ProxyConfig,
|
|
||||||
|
|
||||||
/// Logging configuration
|
|
||||||
logging: LoggingConfig,
|
|
||||||
|
|
||||||
/// Information on system resources used by Arti.
|
|
||||||
system: SystemConfig,
|
|
||||||
|
|
||||||
/// Configuration of the actual Tor client
|
|
||||||
tor: TorClientConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<config::Config> for ArtiConfig {
|
|
||||||
type Error = config::ConfigError;
|
|
||||||
fn try_from(cfg: config::Config) -> Result<ArtiConfig, Self::Error> {
|
|
||||||
let builder: ArtiConfigBuilder = cfg.try_deserialize()?;
|
|
||||||
builder
|
|
||||||
.build()
|
|
||||||
.map_err(|e| config::ConfigError::Foreign(Box::new(e)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This handwritten impl ought not to exist, but it is needed until #374 is done.
|
|
||||||
impl From<ArtiConfigBuilder> for TorClientConfigBuilder {
|
|
||||||
fn from(cfg: ArtiConfigBuilder) -> TorClientConfigBuilder {
|
|
||||||
cfg.tor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ArtiConfig {
|
|
||||||
/// Construct a [`TorClientConfig`] based on this configuration.
|
|
||||||
pub fn tor_client_config(&self) -> Result<TorClientConfig, ConfigBuildError> {
|
|
||||||
Ok(self.tor.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a new ArtiConfigBuilder.
|
|
||||||
pub fn builder() -> ArtiConfigBuilder {
|
|
||||||
ArtiConfigBuilder::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the [`ApplicationConfig`] for this configuration.
|
|
||||||
pub fn application(&self) -> &ApplicationConfig {
|
|
||||||
&self.application
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the [`LoggingConfig`] for this configuration.
|
|
||||||
pub fn logging(&self) -> &LoggingConfig {
|
|
||||||
&self.logging
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the [`ProxyConfig`] for this configuration.
|
|
||||||
pub fn proxy(&self) -> &ProxyConfig {
|
|
||||||
&self.proxy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Builder object used to construct an ArtiConfig.
|
|
||||||
///
|
|
||||||
/// Most code won't need this, and should use [`TorClientConfigBuilder`] instead.
|
|
||||||
///
|
|
||||||
/// Unlike other builder types in Arti, this builder works by exposing an
|
|
||||||
/// inner builder for each section in the [`TorClientConfig`].
|
|
||||||
#[derive(Default, Clone, Deserialize)]
|
|
||||||
// This ought to be replaced by a derive-builder generated struct (probably as part of #374),
|
|
||||||
// but currently derive-builder can't do this.
|
|
||||||
pub struct ArtiConfigBuilder {
|
|
||||||
/// Builder for the actual Tor client.
|
|
||||||
#[serde(flatten)]
|
|
||||||
tor: TorClientConfigBuilder,
|
|
||||||
|
|
||||||
/// Builder for the application section
|
|
||||||
#[serde(default)]
|
|
||||||
application: ApplicationConfigBuilder,
|
|
||||||
/// Builder for the proxy section.
|
|
||||||
#[serde(default)]
|
|
||||||
proxy: ProxyConfigBuilder,
|
|
||||||
/// Builder for the logging section.
|
|
||||||
#[serde(default)]
|
|
||||||
logging: LoggingConfigBuilder,
|
|
||||||
/// Builder for system resource configuration.
|
|
||||||
#[serde(default)]
|
|
||||||
system: SystemConfigBuilder,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ArtiConfigBuilder {
|
|
||||||
/// Try to construct a new [`ArtiConfig`] from this builder.
|
|
||||||
pub fn build(&self) -> Result<ArtiConfig, ConfigBuildError> {
|
|
||||||
let application = self
|
|
||||||
.application
|
|
||||||
.build()
|
|
||||||
.map_err(|e| e.within("application"))?;
|
|
||||||
let proxy = self.proxy.build().map_err(|e| e.within("proxy"))?;
|
|
||||||
let logging = self.logging.build().map_err(|e| e.within("logging"))?;
|
|
||||||
let system = self.system.build().map_err(|e| e.within("system"))?;
|
|
||||||
let tor = TorClientConfigBuilder::from(self.clone());
|
|
||||||
let tor = tor.build()?;
|
|
||||||
Ok(ArtiConfig {
|
|
||||||
application,
|
|
||||||
proxy,
|
|
||||||
logging,
|
|
||||||
system,
|
|
||||||
tor,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to an [`ApplicationConfigBuilder`] to use in
|
|
||||||
/// configuring the Arti process.
|
|
||||||
pub fn application(&mut self) -> &mut ApplicationConfigBuilder {
|
|
||||||
&mut self.application
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to a [`ProxyConfig`] to use in
|
|
||||||
/// configuring the Arti process.
|
|
||||||
pub fn proxy(&mut self) -> &mut ProxyConfigBuilder {
|
|
||||||
&mut self.proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to a
|
|
||||||
/// [`LoggingConfigBuilder`]
|
|
||||||
/// to use in configuring the Arti process.
|
|
||||||
pub fn logging(&mut self) -> &mut LoggingConfigBuilder {
|
|
||||||
&mut self.logging
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to a `TorClientConfigBuilder`.
|
|
||||||
/// to use in configuring the underlying Tor network.
|
|
||||||
///
|
|
||||||
/// Most programs shouldn't need to alter this configuration: it's only for
|
|
||||||
/// cases when you need to use a nonstandard set of Tor directory authorities
|
|
||||||
/// and fallback caches.
|
|
||||||
pub fn tor(&mut self) -> &mut TorClientConfigBuilder {
|
|
||||||
&mut self.tor
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a mutable reference to a [`SystemConfigBuilder`].
|
|
||||||
///
|
|
||||||
/// This section controls the system parameters used by Arti.
|
|
||||||
pub fn system(&mut self) -> &mut SystemConfigBuilder {
|
|
||||||
&mut self.system
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
|
|
||||||
use arti_client::config::dir;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn default_config() {
|
|
||||||
// TODO: this is duplicate code.
|
|
||||||
let cfg = config::Config::builder()
|
|
||||||
.add_source(config::File::from_str(
|
|
||||||
ARTI_DEFAULTS,
|
|
||||||
config::FileFormat::Toml,
|
|
||||||
))
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let parsed: ArtiConfig = cfg.try_into().unwrap();
|
|
||||||
let default = ArtiConfig::default();
|
|
||||||
assert_eq!(&parsed, &default);
|
|
||||||
|
|
||||||
// Make sure that the client configuration this gives us is the default one.
|
|
||||||
let client_config = parsed.tor_client_config().unwrap();
|
|
||||||
let dflt_client_config = TorClientConfig::default();
|
|
||||||
assert_eq!(&client_config, &dflt_client_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn builder() {
|
|
||||||
use arti_client::config::dir::DownloadSchedule;
|
|
||||||
use tor_config::CfgPath;
|
|
||||||
let sec = std::time::Duration::from_secs(1);
|
|
||||||
|
|
||||||
let auth = dir::Authority::builder()
|
|
||||||
.name("Fred")
|
|
||||||
.v3ident([22; 20].into())
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
let fallback = dir::FallbackDir::builder()
|
|
||||||
.rsa_identity([23; 20].into())
|
|
||||||
.ed_identity([99; 32].into())
|
|
||||||
.orports(vec!["127.0.0.7:7".parse().unwrap()])
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut bld = ArtiConfig::builder();
|
|
||||||
bld.proxy().socks_port(Some(9999));
|
|
||||||
bld.logging().console("warn");
|
|
||||||
bld.tor()
|
|
||||||
.tor_network()
|
|
||||||
.authorities(vec![auth])
|
|
||||||
.fallback_caches(vec![fallback]);
|
|
||||||
bld.tor()
|
|
||||||
.storage()
|
|
||||||
.cache_dir(CfgPath::new("/var/tmp/foo".to_owned()))
|
|
||||||
.state_dir(CfgPath::new("/var/tmp/bar".to_owned()));
|
|
||||||
bld.tor()
|
|
||||||
.download_schedule()
|
|
||||||
.retry_certs(DownloadSchedule::new(10, sec, 3))
|
|
||||||
.retry_microdescs(DownloadSchedule::new(30, 10 * sec, 9));
|
|
||||||
bld.tor()
|
|
||||||
.override_net_params()
|
|
||||||
.insert("wombats-per-quokka".to_owned(), 7);
|
|
||||||
bld.tor()
|
|
||||||
.path_rules()
|
|
||||||
.ipv4_subnet_family_prefix(20)
|
|
||||||
.ipv6_subnet_family_prefix(48);
|
|
||||||
bld.tor()
|
|
||||||
.preemptive_circuits()
|
|
||||||
.disable_at_threshold(12)
|
|
||||||
.initial_predicted_ports(vec![80, 443])
|
|
||||||
.prediction_lifetime(Duration::from_secs(3600))
|
|
||||||
.min_exit_circs_for_port(2);
|
|
||||||
bld.tor()
|
|
||||||
.circuit_timing()
|
|
||||||
.max_dirtiness(90 * sec)
|
|
||||||
.request_timeout(10 * sec)
|
|
||||||
.request_max_retries(22)
|
|
||||||
.request_loyalty(3600 * sec);
|
|
||||||
bld.tor().address_filter().allow_local_addrs(true);
|
|
||||||
|
|
||||||
let val = bld.build().unwrap();
|
|
||||||
|
|
||||||
assert_ne!(val, ArtiConfig::default());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ publish = false
|
||||||
[features]
|
[features]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
arti = { package = "arti", path = "../arti", version = "0.1.0" }
|
||||||
arti-client = { package = "arti-client", path = "../arti-client", version = "0.1.0" }
|
arti-client = { package = "arti-client", path = "../arti-client", version = "0.1.0" }
|
||||||
tor-rtcompat = { path = "../tor-rtcompat", version = "0.1.0" }
|
tor-rtcompat = { path = "../tor-rtcompat", version = "0.1.0" }
|
||||||
arti-config = { path = "../arti-config", version = "0.1.0" }
|
arti-config = { path = "../arti-config", version = "0.1.0" }
|
||||||
|
|
|
@ -83,8 +83,8 @@ mod config;
|
||||||
mod rt;
|
mod rt;
|
||||||
mod traces;
|
mod traces;
|
||||||
|
|
||||||
|
use arti::ArtiConfig;
|
||||||
use arti_client::TorClient;
|
use arti_client::TorClient;
|
||||||
use arti_config::ArtiConfig;
|
|
||||||
use futures::task::SpawnExt;
|
use futures::task::SpawnExt;
|
||||||
use rt::badtcp::BrokenTcpProvider;
|
use rt::badtcp::BrokenTcpProvider;
|
||||||
use tor_rtcompat::{PreferredRuntime, Runtime, SleepProviderExt};
|
use tor_rtcompat::{PreferredRuntime, Runtime, SleepProviderExt};
|
||||||
|
|
|
@ -23,6 +23,7 @@ journald = [ "tracing-journald" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arti-client = { package="arti-client", path = "../arti-client", version = "0.1.0", default-features=false}
|
arti-client = { package="arti-client", path = "../arti-client", version = "0.1.0", default-features=false}
|
||||||
|
tor-config = { path="../tor-config", version = "0.1.0" }
|
||||||
tor-error = { path="../tor-error", version = "0.1.0", default-features=false }
|
tor-error = { path="../tor-error", version = "0.1.0", default-features=false }
|
||||||
tor-rtcompat = { path="../tor-rtcompat", version = "0.1.0", default-features=false }
|
tor-rtcompat = { path="../tor-rtcompat", version = "0.1.0", default-features=false }
|
||||||
tor-socksproto = { path="../tor-socksproto", version = "0.1.0"}
|
tor-socksproto = { path="../tor-socksproto", version = "0.1.0"}
|
||||||
|
|
|
@ -0,0 +1,269 @@
|
||||||
|
//! Configuration for the Arti command line application
|
||||||
|
//
|
||||||
|
// (Thia module is called `cfg` to avoid name clash with the `config` crate, which we use.)
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use arti_client::config::{SystemConfig, SystemConfigBuilder, TorClientConfigBuilder};
|
||||||
|
use arti_client::TorClientConfig;
|
||||||
|
use arti_config::{
|
||||||
|
ApplicationConfig, ApplicationConfigBuilder, LoggingConfig, LoggingConfigBuilder, ProxyConfig,
|
||||||
|
ProxyConfigBuilder,
|
||||||
|
};
|
||||||
|
use tor_config::ConfigBuildError;
|
||||||
|
|
||||||
|
/// Structure to hold Arti's configuration options, whether from a
|
||||||
|
/// configuration file or the command line.
|
||||||
|
//
|
||||||
|
/// These options are declared in a public crate outside of `arti` so that other
|
||||||
|
/// applications can parse and use them, if desired. If you're only embedding
|
||||||
|
/// arti via `arti-client`, and you don't want to use Arti's configuration
|
||||||
|
/// format, use [`arti_client::TorClientConfig`] instead.
|
||||||
|
///
|
||||||
|
/// By default, Arti will run using the default Tor network, store state and
|
||||||
|
/// cache information to a per-user set of directories shared by all
|
||||||
|
/// that user's applications, and run a SOCKS client on a local port.
|
||||||
|
///
|
||||||
|
/// NOTE: These are NOT the final options or their final layout. Expect NO
|
||||||
|
/// stability here.
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
||||||
|
pub struct ArtiConfig {
|
||||||
|
/// Configuration for application behavior.
|
||||||
|
application: ApplicationConfig,
|
||||||
|
|
||||||
|
/// Configuration for proxy listeners
|
||||||
|
proxy: ProxyConfig,
|
||||||
|
|
||||||
|
/// Logging configuration
|
||||||
|
logging: LoggingConfig,
|
||||||
|
|
||||||
|
/// Information on system resources used by Arti.
|
||||||
|
system: SystemConfig,
|
||||||
|
|
||||||
|
/// Configuration of the actual Tor client
|
||||||
|
tor: TorClientConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<config::Config> for ArtiConfig {
|
||||||
|
type Error = config::ConfigError;
|
||||||
|
fn try_from(cfg: config::Config) -> Result<ArtiConfig, Self::Error> {
|
||||||
|
let builder: ArtiConfigBuilder = cfg.try_deserialize()?;
|
||||||
|
builder
|
||||||
|
.build()
|
||||||
|
.map_err(|e| config::ConfigError::Foreign(Box::new(e)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This handwritten impl ought not to exist, but it is needed until #374 is done.
|
||||||
|
impl From<ArtiConfigBuilder> for TorClientConfigBuilder {
|
||||||
|
fn from(cfg: ArtiConfigBuilder) -> TorClientConfigBuilder {
|
||||||
|
cfg.tor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArtiConfig {
|
||||||
|
/// Construct a [`TorClientConfig`] based on this configuration.
|
||||||
|
pub fn tor_client_config(&self) -> Result<TorClientConfig, ConfigBuildError> {
|
||||||
|
Ok(self.tor.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a new ArtiConfigBuilder.
|
||||||
|
pub fn builder() -> ArtiConfigBuilder {
|
||||||
|
ArtiConfigBuilder::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the [`ApplicationConfig`] for this configuration.
|
||||||
|
pub fn application(&self) -> &ApplicationConfig {
|
||||||
|
&self.application
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the [`LoggingConfig`] for this configuration.
|
||||||
|
pub fn logging(&self) -> &LoggingConfig {
|
||||||
|
&self.logging
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the [`ProxyConfig`] for this configuration.
|
||||||
|
pub fn proxy(&self) -> &ProxyConfig {
|
||||||
|
&self.proxy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder object used to construct an ArtiConfig.
|
||||||
|
///
|
||||||
|
/// Most code won't need this, and should use [`TorClientConfigBuilder`] instead.
|
||||||
|
///
|
||||||
|
/// Unlike other builder types in Arti, this builder works by exposing an
|
||||||
|
/// inner builder for each section in the [`TorClientConfig`].
|
||||||
|
#[derive(Default, Clone, Deserialize)]
|
||||||
|
// This ought to be replaced by a derive-builder generated struct (probably as part of #374),
|
||||||
|
// but currently derive-builder can't do this.
|
||||||
|
pub struct ArtiConfigBuilder {
|
||||||
|
/// Builder for the actual Tor client.
|
||||||
|
#[serde(flatten)]
|
||||||
|
tor: TorClientConfigBuilder,
|
||||||
|
|
||||||
|
/// Builder for the application section
|
||||||
|
#[serde(default)]
|
||||||
|
application: ApplicationConfigBuilder,
|
||||||
|
/// Builder for the proxy section.
|
||||||
|
#[serde(default)]
|
||||||
|
proxy: ProxyConfigBuilder,
|
||||||
|
/// Builder for the logging section.
|
||||||
|
#[serde(default)]
|
||||||
|
logging: LoggingConfigBuilder,
|
||||||
|
/// Builder for system resource configuration.
|
||||||
|
#[serde(default)]
|
||||||
|
system: SystemConfigBuilder,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArtiConfigBuilder {
|
||||||
|
/// Try to construct a new [`ArtiConfig`] from this builder.
|
||||||
|
pub fn build(&self) -> Result<ArtiConfig, ConfigBuildError> {
|
||||||
|
let application = self
|
||||||
|
.application
|
||||||
|
.build()
|
||||||
|
.map_err(|e| e.within("application"))?;
|
||||||
|
let proxy = self.proxy.build().map_err(|e| e.within("proxy"))?;
|
||||||
|
let logging = self.logging.build().map_err(|e| e.within("logging"))?;
|
||||||
|
let system = self.system.build().map_err(|e| e.within("system"))?;
|
||||||
|
let tor = TorClientConfigBuilder::from(self.clone());
|
||||||
|
let tor = tor.build()?;
|
||||||
|
Ok(ArtiConfig {
|
||||||
|
application,
|
||||||
|
proxy,
|
||||||
|
logging,
|
||||||
|
system,
|
||||||
|
tor,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a mutable reference to an [`ApplicationConfigBuilder`] to use in
|
||||||
|
/// configuring the Arti process.
|
||||||
|
pub fn application(&mut self) -> &mut ApplicationConfigBuilder {
|
||||||
|
&mut self.application
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a mutable reference to a [`ProxyConfig`] to use in
|
||||||
|
/// configuring the Arti process.
|
||||||
|
pub fn proxy(&mut self) -> &mut ProxyConfigBuilder {
|
||||||
|
&mut self.proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a mutable reference to a
|
||||||
|
/// [`LoggingConfigBuilder`]
|
||||||
|
/// to use in configuring the Arti process.
|
||||||
|
pub fn logging(&mut self) -> &mut LoggingConfigBuilder {
|
||||||
|
&mut self.logging
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a mutable reference to a `TorClientConfigBuilder`.
|
||||||
|
/// to use in configuring the underlying Tor network.
|
||||||
|
///
|
||||||
|
/// Most programs shouldn't need to alter this configuration: it's only for
|
||||||
|
/// cases when you need to use a nonstandard set of Tor directory authorities
|
||||||
|
/// and fallback caches.
|
||||||
|
pub fn tor(&mut self) -> &mut TorClientConfigBuilder {
|
||||||
|
&mut self.tor
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a mutable reference to a [`SystemConfigBuilder`].
|
||||||
|
///
|
||||||
|
/// This section controls the system parameters used by Arti.
|
||||||
|
pub fn system(&mut self) -> &mut SystemConfigBuilder {
|
||||||
|
&mut self.system
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
|
use arti_client::config::dir;
|
||||||
|
use arti_config::ARTI_DEFAULTS;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_config() {
|
||||||
|
// TODO: this is duplicate code.
|
||||||
|
let cfg = config::Config::builder()
|
||||||
|
.add_source(config::File::from_str(
|
||||||
|
ARTI_DEFAULTS,
|
||||||
|
config::FileFormat::Toml,
|
||||||
|
))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let parsed: ArtiConfig = cfg.try_into().unwrap();
|
||||||
|
let default = ArtiConfig::default();
|
||||||
|
assert_eq!(&parsed, &default);
|
||||||
|
|
||||||
|
// Make sure that the client configuration this gives us is the default one.
|
||||||
|
let client_config = parsed.tor_client_config().unwrap();
|
||||||
|
let dflt_client_config = TorClientConfig::default();
|
||||||
|
assert_eq!(&client_config, &dflt_client_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn builder() {
|
||||||
|
use arti_client::config::dir::DownloadSchedule;
|
||||||
|
use tor_config::CfgPath;
|
||||||
|
let sec = std::time::Duration::from_secs(1);
|
||||||
|
|
||||||
|
let auth = dir::Authority::builder()
|
||||||
|
.name("Fred")
|
||||||
|
.v3ident([22; 20].into())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
let fallback = dir::FallbackDir::builder()
|
||||||
|
.rsa_identity([23; 20].into())
|
||||||
|
.ed_identity([99; 32].into())
|
||||||
|
.orports(vec!["127.0.0.7:7".parse().unwrap()])
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut bld = ArtiConfig::builder();
|
||||||
|
bld.proxy().socks_port(Some(9999));
|
||||||
|
bld.logging().console("warn");
|
||||||
|
bld.tor()
|
||||||
|
.tor_network()
|
||||||
|
.authorities(vec![auth])
|
||||||
|
.fallback_caches(vec![fallback]);
|
||||||
|
bld.tor()
|
||||||
|
.storage()
|
||||||
|
.cache_dir(CfgPath::new("/var/tmp/foo".to_owned()))
|
||||||
|
.state_dir(CfgPath::new("/var/tmp/bar".to_owned()));
|
||||||
|
bld.tor()
|
||||||
|
.download_schedule()
|
||||||
|
.retry_certs(DownloadSchedule::new(10, sec, 3))
|
||||||
|
.retry_microdescs(DownloadSchedule::new(30, 10 * sec, 9));
|
||||||
|
bld.tor()
|
||||||
|
.override_net_params()
|
||||||
|
.insert("wombats-per-quokka".to_owned(), 7);
|
||||||
|
bld.tor()
|
||||||
|
.path_rules()
|
||||||
|
.ipv4_subnet_family_prefix(20)
|
||||||
|
.ipv6_subnet_family_prefix(48);
|
||||||
|
bld.tor()
|
||||||
|
.preemptive_circuits()
|
||||||
|
.disable_at_threshold(12)
|
||||||
|
.initial_predicted_ports(vec![80, 443])
|
||||||
|
.prediction_lifetime(Duration::from_secs(3600))
|
||||||
|
.min_exit_circs_for_port(2);
|
||||||
|
bld.tor()
|
||||||
|
.circuit_timing()
|
||||||
|
.max_dirtiness(90 * sec)
|
||||||
|
.request_timeout(10 * sec)
|
||||||
|
.request_max_retries(22)
|
||||||
|
.request_loyalty(3600 * sec);
|
||||||
|
bld.tor().address_filter().allow_local_addrs(true);
|
||||||
|
|
||||||
|
let val = bld.build().unwrap();
|
||||||
|
|
||||||
|
assert_ne!(val, ArtiConfig::default());
|
||||||
|
}
|
||||||
|
}
|
|
@ -114,6 +114,7 @@
|
||||||
#![warn(clippy::unseparated_literal_suffix)]
|
#![warn(clippy::unseparated_literal_suffix)]
|
||||||
#![deny(clippy::unwrap_used)]
|
#![deny(clippy::unwrap_used)]
|
||||||
|
|
||||||
|
pub mod cfg;
|
||||||
pub mod dns;
|
pub mod dns;
|
||||||
pub mod exit;
|
pub mod exit;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
|
@ -121,8 +122,10 @@ pub mod socks;
|
||||||
pub mod trace;
|
pub mod trace;
|
||||||
pub mod watch_cfg;
|
pub mod watch_cfg;
|
||||||
|
|
||||||
|
pub use cfg::{ArtiConfig, ArtiConfigBuilder};
|
||||||
|
|
||||||
use arti_client::{TorClient, TorClientConfig};
|
use arti_client::{TorClient, TorClientConfig};
|
||||||
use arti_config::{default_config_file, ArtiConfig};
|
use arti_config::default_config_file;
|
||||||
use tor_rtcompat::{BlockOn, Runtime};
|
use tor_rtcompat::{BlockOn, Runtime};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
@ -144,7 +147,7 @@ pub async fn run<R: Runtime>(
|
||||||
socks_port: u16,
|
socks_port: u16,
|
||||||
dns_port: u16,
|
dns_port: u16,
|
||||||
config_sources: arti_config::ConfigurationSources,
|
config_sources: arti_config::ConfigurationSources,
|
||||||
arti_config: arti_config::ArtiConfig,
|
arti_config: ArtiConfig,
|
||||||
client_config: TorClientConfig,
|
client_config: TorClientConfig,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Using OnDemand arranges that, while we are bootstrapping, incoming connections wait
|
// Using OnDemand arranges that, while we are bootstrapping, incoming connections wait
|
||||||
|
|
|
@ -8,11 +8,12 @@ use std::time::Duration;
|
||||||
|
|
||||||
use arti_client::config::Reconfigure;
|
use arti_client::config::Reconfigure;
|
||||||
use arti_client::TorClient;
|
use arti_client::TorClient;
|
||||||
use arti_config::ArtiConfig;
|
|
||||||
use notify::Watcher;
|
use notify::Watcher;
|
||||||
use tor_rtcompat::Runtime;
|
use tor_rtcompat::Runtime;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
|
use crate::ArtiConfig;
|
||||||
|
|
||||||
/// How long (worst case) should we take to learn about configuration changes?
|
/// How long (worst case) should we take to learn about configuration changes?
|
||||||
const POLL_INTERVAL: Duration = Duration::from_secs(10);
|
const POLL_INTERVAL: Duration = Duration::from_secs(10);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue