diff --git a/common/async-file-watcher/src/lib.rs b/common/async-file-watcher/src/lib.rs index e4602ef55c..dea2cfd335 100644 --- a/common/async-file-watcher/src/lib.rs +++ b/common/async-file-watcher/src/lib.rs @@ -3,7 +3,7 @@ use futures::channel::mpsc; use futures::StreamExt; -use notify::event::{DataChange, ModifyKind}; +use notify::event::{DataChange, MetadataKind, ModifyKind}; use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; use std::collections::HashMap; use std::path::{Path, PathBuf}; @@ -37,6 +37,7 @@ impl AsyncFileWatcher { Some(vec![ EventKind::Modify(ModifyKind::Data(DataChange::Content)), EventKind::Modify(ModifyKind::Data(DataChange::Any)), + EventKind::Modify(ModifyKind::Metadata(MetadataKind::Any)), ]), None, ) @@ -79,7 +80,7 @@ impl AsyncFileWatcher { self } - pub fn with_filter(mut self, filter: notify::EventKind) -> Self { + pub fn with_filter(mut self, filter: EventKind) -> Self { match &mut self.filters { None => { self.filters = Some(vec![filter]); @@ -133,6 +134,8 @@ impl AsyncFileWatcher { if let Err(_err) = self.event_sender.unbounded_send(event) { log::error!("the file watcher receiver has been dropped!"); } + } else { + log::debug!("will not propagate information about {:?}", event); } } Err(err) => { diff --git a/service-providers/network-requester/src/allowed_hosts/hosts.rs b/service-providers/network-requester/src/allowed_hosts/hosts.rs index 260e075b95..896c14c8d6 100644 --- a/service-providers/network-requester/src/allowed_hosts/hosts.rs +++ b/service-providers/network-requester/src/allowed_hosts/hosts.rs @@ -20,8 +20,17 @@ impl HostsStore { /// /// You can inject a list of standard hosts that you want to support, in addition to the ones /// in the user-defined storefile. - pub(crate) fn new(base_dir: PathBuf, filename: PathBuf) -> HostsStore { - let storefile = Self::setup_storefile(base_dir, filename); + pub(crate) fn new>(storefile: P) -> HostsStore { + let storefile = storefile.as_ref().to_path_buf(); + if !storefile.is_file() { + // there's no error handling in here and I'm not going to be changing it now. + panic!( + "the provided storefile {:?} is not a valid file!", + storefile + ) + } + + Self::setup_storefile(&storefile); let hosts = Self::load_from_storefile(&storefile) .unwrap_or_else(|_| panic!("Could not load hosts from storefile at {storefile:?}")); @@ -77,25 +86,15 @@ impl HostsStore { HostsStore::append(&self.storefile, host); } - /// Returns the default base directory for the storefile. - /// - /// This is split out so we can easily inject our own base_dir for unit tests. - pub fn default_base_dir() -> PathBuf { - dirs::home_dir() - .expect("no home directory known for this OS") - .join(".nym") - } - - fn setup_storefile(base_dir: PathBuf, filename: PathBuf) -> PathBuf { - let dirpath = base_dir.join("service-providers").join("network-requester"); - fs::create_dir_all(&dirpath) - .unwrap_or_else(|_| panic!("could not create storage directory at {dirpath:?}")); - let storefile = dirpath.join(filename); - let exists = std::path::Path::new(&storefile).exists(); - if !exists { - File::create(&storefile).unwrap(); + fn setup_storefile(file: &PathBuf) { + if !file.exists() { + let parent_dir = file + .parent() + .expect("parent dir does not exist for {file:?}"); + fs::create_dir_all(&parent_dir) + .unwrap_or_else(|_| panic!("could not create storage directory at {parent_dir:?}")); + File::create(&file).unwrap(); } - storefile } /// Loads the storefile contents into memory. diff --git a/service-providers/network-requester/src/allowed_hosts/stored_allowed_hosts.rs b/service-providers/network-requester/src/allowed_hosts/stored_allowed_hosts.rs index b57c385372..d195fab8ec 100644 --- a/service-providers/network-requester/src/allowed_hosts/stored_allowed_hosts.rs +++ b/service-providers/network-requester/src/allowed_hosts/stored_allowed_hosts.rs @@ -18,8 +18,7 @@ pub(crate) struct StoredAllowedHosts { impl StoredAllowedHosts { pub(crate) fn new>(path: P) -> Self { - let allowed_hosts = - HostsStore::new(HostsStore::default_base_dir(), path.as_ref().to_path_buf()); + let allowed_hosts = HostsStore::new(path); StoredAllowedHosts { inner: Arc::new(RwLock::new(allowed_hosts)), diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index 59495cff06..4735592f7d 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -24,7 +24,11 @@ pub struct Config { #[serde(flatten)] base: BaseConfig, - pub debug: Debug, + #[serde(default)] + pub network_requester: NetworkRequster, + + #[serde(default)] + pub network_requester_debug: Debug, } impl NymConfig for Config { @@ -32,7 +36,6 @@ impl NymConfig for Config { config_template() } - // TODO: merge base dir with `HostStore`. fn default_root_directory() -> PathBuf { dirs::home_dir() .expect("Failed to evaluate $HOME value") @@ -66,6 +69,28 @@ impl ClientCoreConfigTrait for Config { } } +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct NetworkRequster { + /// Location of the file containing our allow.list + pub allowed_list_location: PathBuf, + + /// Location of the file containing our unknown.list + pub unknown_list_location: PathBuf, +} + +impl Default for NetworkRequster { + fn default() -> Self { + // same defaults as we had in <= v1.1.13 + NetworkRequster { + allowed_list_location: ::default_root_directory() + .join("allowed.list"), + unknown_list_location: ::default_root_directory() + .join("unknown.list"), + } + } +} + #[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)] #[serde(default, deny_unknown_fields)] pub struct Debug { @@ -84,10 +109,14 @@ impl Default for Debug { impl Config { pub fn new>(id: S) -> Self { - Config { + let mut cfg = Config { base: BaseConfig::new(id), - debug: Default::default(), - } + ..Default::default() + }; + + cfg.network_requester.allowed_list_location = cfg.data_directory().join("allowed.list"); + cfg.network_requester.unknown_list_location = cfg.data_directory().join("unknown.list"); + cfg } // getters @@ -95,6 +124,14 @@ impl Config { self.config_directory().join(Self::config_file_name()) } + pub fn allow_list_file_location(&self) -> PathBuf { + self.network_requester.allowed_list_location.clone() + } + + pub fn unknown_list_file_location(&self) -> PathBuf { + self.network_requester.unknown_list_location.clone() + } + pub fn get_base(&self) -> &BaseConfig { &self.base } diff --git a/service-providers/network-requester/src/config/old_config_v1_1_13.rs b/service-providers/network-requester/src/config/old_config_v1_1_13.rs index d747e9e0de..1b92cec438 100644 --- a/service-providers/network-requester/src/config/old_config_v1_1_13.rs +++ b/service-providers/network-requester/src/config/old_config_v1_1_13.rs @@ -54,7 +54,8 @@ impl From for Config { fn from(value: OldConfigV1_1_13) -> Self { Config { base: value.base.into(), - debug: Default::default(), + network_requester: Default::default(), + network_requester_debug: Default::default(), } } } diff --git a/service-providers/network-requester/src/config/template.rs b/service-providers/network-requester/src/config/template.rs index bc85b76e90..e1371955c7 100644 --- a/service-providers/network-requester/src/config/template.rs +++ b/service-providers/network-requester/src/config/template.rs @@ -76,6 +76,14 @@ gateway_owner = '{{ client.gateway_endpoint.gateway_owner }}' # Address of the gateway listener to which all client requests should be sent. gateway_listener = '{{ client.gateway_endpoint.gateway_listener }}' +##### network requester specific config options ##### + +[network_requester] +# Location of the file containing our allow.list +allowed_list_location = '{{ network_requester.allowed_list_location }}' + +# Location of the file containing our unknown.list +unknown_list_location = '{{ network_requester.unknown_list_location }}' ##### logging configuration options ##### diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 29f81eaf34..bf4b7eaa98 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -31,7 +31,6 @@ use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_statistics_common::collector::StatisticsSender; use nym_task::connections::LaneQueueLengths; use nym_task::{TaskClient, TaskManager}; -use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; // Since it's an atomic, it's safe to be kept static and shared across threads @@ -160,12 +159,8 @@ impl NRServiceProviderBuilder { ) -> NRServiceProviderBuilder { let standard_list = StandardList::new(); - let allowed_hosts = StoredAllowedHosts::new("allowed.list"); - - let unknown_hosts = allowed_hosts::HostsStore::new( - allowed_hosts::HostsStore::default_base_dir(), - PathBuf::from("unknown.list"), - ); + let allowed_hosts = StoredAllowedHosts::new(config.allow_list_file_location()); + let unknown_hosts = allowed_hosts::HostsStore::new(config.unknown_list_file_location()); let outbound_request_filter = OutboundRequestFilter::new(allowed_hosts.clone(), standard_list.clone(), unknown_hosts); @@ -234,7 +229,9 @@ impl NRServiceProviderBuilder { // start the standard list updater StandardListUpdater::new( - self.config.debug.standard_list_update_interval, + self.config + .network_requester_debug + .standard_list_update_interval, self.standard_list, shutdown.subscribe(), )