Commit 9e526aad authored by Ian Jackson's avatar Ian Jackson
Browse files

Split TorClientConfig out of ArtiConfig, and Resolvable trait

This gets rid of `#[serde(flatten)]` which prevents serde_ignored (and
other kinds of introspection) from working properly.

The price is now that the toplevel has to deal with two configuration
objects.

The Resolvable trait is overkill right now, but is going to do More
Things in a moment.  In particular, we need the impl on tuples, so
that the whole config can be processed in one go.
parent 687e5c36
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@
#![allow(clippy::unwrap_used)]

use anyhow::{anyhow, Result};
use arti::cfg::ArtiConfig;
use arti::cfg::ArtiCombinedConfig;
use arti_client::{IsolationToken, TorAddr, TorClient, TorClientConfig};
use clap::{App, Arg};
use futures::StreamExt;
@@ -367,8 +367,7 @@ fn main() -> Result<()> {
    config_sources.set_mistrust(mistrust);

    let cfg = config_sources.load()?;
    let config: ArtiConfig = cfg.try_into()?;
    let tcc = config.tor_client_config()?;
    let (_config, tcc) = tor_config::resolve::<ArtiCombinedConfig>(cfg)?;
    info!("Binding local TCP listener...");
    let listener = TcpListener::bind("0.0.0.0:0")?;
    let local_addr = listener.local_addr()?;
+4 −0
Original line number Diff line number Diff line
@@ -288,6 +288,10 @@ pub struct TorClientConfig {
}
impl_standard_builder! { TorClientConfig }

impl tor_config::load::TopLevel for TorClientConfig {
    type Builder = TorClientConfigBuilder;
}

/// Helper to convert convert_override_net_params
fn convert_override_net_params(
    builder: &HashMap<String, i32>,
+3 −3
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ mod dirfilter;
mod rt;
mod traces;

use arti::ArtiConfig;
use arti::ArtiCombinedConfig;
use arti_client::TorClient;
use futures::task::SpawnExt;
use rt::badtcp::BrokenTcpProvider;
@@ -222,9 +222,9 @@ struct Job {
impl Job {
    /// Make a new unbootstrapped client for this job.
    fn make_client<R: Runtime>(&self, runtime: R) -> Result<TorClient<R>> {
        let config: ArtiConfig = self.config.load()?.try_into()?;
        let (_arti, tcc) = tor_config::resolve::<ArtiCombinedConfig>(self.config.load()?)?;
        let client = TorClient::with_runtime(runtime)
            .config(config.tor_client_config()?)
            .config(tcc)
            .dirfilter(self.dir_filter.clone())
            .create_unbootstrapped()?;
        Ok(client)
+14 −35
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@
use derive_builder::Builder;
use serde::{Deserialize, Serialize};

use arti_client::config::TorClientConfigBuilder;
use arti_client::TorClientConfig;
use tor_config::{impl_standard_builder, ConfigBuildError};

@@ -111,37 +110,17 @@ pub struct ArtiConfig {
    #[builder(sub_builder)]
    #[builder_field_attr(serde(default))]
    pub(crate) system: SystemConfig,

    /// Configuration of the actual Tor client
    #[builder(sub_builder)]
    #[builder_field_attr(serde(flatten))]
    pub(crate) tor: TorClientConfig,
}
impl_standard_builder! { ArtiConfig }

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)))
    }
impl tor_config::load::TopLevel for ArtiConfig {
    type Builder = ArtiConfigBuilder;
}

// 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
    }
}
/// Convenience alias
pub type ArtiCombinedConfig = (ArtiConfig, TorClientConfig);

impl ArtiConfig {
    /// Construct a [`TorClientConfig`] based on this configuration.
    pub fn tor_client_config(&self) -> Result<TorClientConfig, ConfigBuildError> {
        Ok(self.tor.clone())
    }

    /// Return the [`ApplicationConfig`] for this configuration.
    pub fn application(&self) -> &ApplicationConfig {
        &self.application
@@ -163,6 +142,7 @@ mod test {
    #![allow(clippy::unwrap_used)]

    use arti_client::config::dir;
    use arti_client::config::TorClientConfigBuilder;
    use regex::Regex;
    use std::time::Duration;

@@ -179,7 +159,7 @@ mod test {
    #[test]
    fn default_config() {
        let empty_config = config::Config::builder().build().unwrap();
        let empty_config: ArtiConfig = empty_config.try_into().unwrap();
        let empty_config: ArtiCombinedConfig = tor_config::resolve(empty_config).unwrap();

        let example = uncomment_example_settings(ARTI_EXAMPLE_CONFIG);
        let cfg = config::Config::builder()
@@ -199,19 +179,18 @@ mod test {
        // Also we should ideally test that every setting from the config appears here in
        // the file.  Possibly that could be done with some kind of stunt Deserializer,
        // but it's not trivial.
        let parsed: ArtiConfig = cfg.try_into().unwrap();
        let default = ArtiConfig::default();
        let parsed: ArtiCombinedConfig = tor_config::resolve(cfg).unwrap();

        let default = (ArtiConfig::default(), TorClientConfig::default());
        assert_eq!(&parsed, &default);
        assert_eq!(&parsed, &empty_config);

        let built_default = ArtiConfigBuilder::default().build().unwrap();
        let built_default = (
            ArtiConfigBuilder::default().build().unwrap(),
            TorClientConfigBuilder::default().build().unwrap(),
        );
        assert_eq!(&parsed, &built_default);
        assert_eq!(&default, &built_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]
@@ -231,11 +210,11 @@ mod test {
            .push("127.0.0.7:7".parse().unwrap());

        let mut bld = ArtiConfig::builder();
        let mut bld_tor = TorClientConfig::builder();

        bld.proxy().socks_port(Some(9999));
        bld.logging().console("warn");

        let bld_tor = bld.tor();
        bld_tor.tor_network().set_authorities(vec![auth]);
        bld_tor.tor_network().set_fallback_caches(vec![fallback]);
        bld_tor
+5 −7
Original line number Diff line number Diff line
@@ -125,8 +125,8 @@ pub mod watch_cfg;
use std::fmt::Write;

pub use cfg::{
    ApplicationConfig, ApplicationConfigBuilder, ArtiConfig, ArtiConfigBuilder, ProxyConfig,
    ProxyConfigBuilder, SystemConfig, SystemConfigBuilder, ARTI_EXAMPLE_CONFIG,
    ApplicationConfig, ApplicationConfigBuilder, ArtiCombinedConfig, ArtiConfig, ArtiConfigBuilder,
    ProxyConfig, ProxyConfigBuilder, SystemConfig, SystemConfigBuilder, ARTI_EXAMPLE_CONFIG,
};
pub use logging::{LoggingConfig, LoggingConfigBuilder};

@@ -371,13 +371,13 @@ pub fn main_main() -> Result<()> {
    };

    let cfg = cfg_sources.load()?;

    let config: ArtiConfig = cfg.try_into().context("read configuration")?;
    let (config, client_config) =
        tor_config::resolve::<ArtiCombinedConfig>(cfg).context("read configuration")?;

    let log_mistrust = if fs_mistrust_disabled {
        fs_mistrust::Mistrust::new_dangerously_trust_everyone()
    } else {
        config.tor.fs_mistrust().clone()
        client_config.fs_mistrust().clone()
    };
    let _log_guards = logging::setup_logging(
        config.logging(),
@@ -401,8 +401,6 @@ pub fn main_main() -> Result<()> {
            (None, None) => 0,
        };

        let client_config = config.tor_client_config()?;

        info!(
            "Starting Arti {} in SOCKS proxy mode on port {}...",
            env!("CARGO_PKG_VERSION"),
Loading