diff --git a/config_example.toml b/config_example.toml index d6e5ffe..24d6c3c 100644 --- a/config_example.toml +++ b/config_example.toml @@ -9,3 +9,7 @@ disable_peer_discovery = false no_tun = false #metrics_api_address = 0.0.0.0:9999 #firewall_mark = 30 + +## Options below only apply when myceliumd-private is used +#network_name = "private network name" +#network_key_file = "path_to_key_file" diff --git a/myceliumd-private/Cargo.lock b/myceliumd-private/Cargo.lock index 6549b19..49f2d82 100644 --- a/myceliumd-private/Cargo.lock +++ b/myceliumd-private/Cargo.lock @@ -230,6 +230,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -247,6 +253,9 @@ name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] [[package]] name = "bitvec" @@ -273,6 +282,15 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "borsh" version = "1.5.1" @@ -442,12 +460,61 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "config" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" +dependencies = [ + "async-trait", + "convert_case", + "json5", + "lazy_static", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", + "yaml-rust", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + [[package]] name = "constant_time_eq" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -473,6 +540,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -549,6 +622,25 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -559,6 +651,18 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -581,6 +685,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + [[package]] name = "encode_unicode" version = "1.0.0" @@ -830,6 +943,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + [[package]] name = "hashbrown" version = "0.14.5" @@ -1020,6 +1139,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1062,6 +1192,12 @@ dependencies = [ "libc", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -1139,6 +1275,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.3" @@ -1200,7 +1342,7 @@ name = "mycelium-api" version = "0.5.3" dependencies = [ "axum", - "base64", + "base64 0.22.1", "mycelium", "mycelium-metrics", "serde", @@ -1212,7 +1354,7 @@ dependencies = [ name = "mycelium-cli" version = "0.5.3" dependencies = [ - "base64", + "base64 0.22.1", "byte-unit", "mycelium", "mycelium-api", @@ -1240,8 +1382,10 @@ dependencies = [ name = "myceliumd-private" version = "0.5.3" dependencies = [ - "base64", + "base64 0.22.1", "clap", + "config", + "dirs", "mycelium", "mycelium-api", "mycelium-cli", @@ -1375,6 +1519,16 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1479,6 +1633,22 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-multimap" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" +dependencies = [ + "dlv-list", + "hashbrown 0.13.2", +] + [[package]] name = "overload" version = "0.1.1" @@ -1514,13 +1684,19 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "pem" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64", + "base64 0.22.1", "serde", ] @@ -1530,6 +1706,51 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "pest_meta" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -1612,7 +1833,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit", + "toml_edit 0.21.1", ] [[package]] @@ -1890,7 +2111,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-core", "futures-util", @@ -1963,6 +2184,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.5.0", + "serde", + "serde_derive", +] + [[package]] name = "rtnetlink" version = "0.14.1" @@ -1981,6 +2214,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "rust-ini" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rust_decimal" version = "1.35.0" @@ -2139,6 +2382,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2151,6 +2403,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2363,6 +2626,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2456,11 +2728,26 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.15", +] + [[package]] name = "toml_datetime" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -2470,7 +2757,20 @@ checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.13", ] [[package]] @@ -2602,6 +2902,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -2623,6 +2929,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "unicode-width" version = "0.1.13" @@ -3006,6 +3318,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.52.0" @@ -3063,6 +3384,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yasna" version = "0.5.2" diff --git a/myceliumd-private/Cargo.toml b/myceliumd-private/Cargo.toml index ec87123..abd2132 100644 --- a/myceliumd-private/Cargo.toml +++ b/myceliumd-private/Cargo.toml @@ -31,3 +31,5 @@ tokio = { version = "1.37.0", features = [ ] } reqwest = { version = "0.12.4", default-features = false, features = ["json"] } base64 = "0.22.1" +config = "0.14.0" +dirs = "5.0.1" diff --git a/myceliumd-private/src/main.rs b/myceliumd-private/src/main.rs index 89af8a6..f8e31f9 100644 --- a/myceliumd-private/src/main.rs +++ b/myceliumd-private/src/main.rs @@ -9,11 +9,12 @@ use std::{ use std::{fmt::Display, str::FromStr}; use clap::{Args, Parser, Subcommand}; +use serde::{Deserialize, Deserializer}; use tokio::fs::File; use tokio::io::{AsyncReadExt, AsyncWriteExt}; #[cfg(target_family = "unix")] use tokio::signal::{self, unix::SignalKind}; -use tracing::{debug, error, warn}; +use tracing::{debug, error, info, warn}; use crypto::PublicKey; use mycelium::endpoint::Endpoint; @@ -81,6 +82,10 @@ struct Cli { #[arg(short = 'k', long = "key-file", global = true)] key_file: Option, + // Configuration file + #[arg(short = 'c', long = "config-file", global = true)] + config_file: Option, + /// Enable debug logging. Does nothing if `--silent` is set. #[arg(short = 'd', long = "debug", default_value_t = false)] debug: bool, @@ -285,10 +290,83 @@ pub struct NodeArguments { firewall_mark: Option, } +#[derive(Debug, Deserialize, Default)] +struct MyceliumConfig { + #[serde(deserialize_with = "deserialize_optional_endpoint_str_from_toml")] + peers: Option>, + tcp_listen_port: Option, + quic_listen_port: Option, + no_tun: Option, + tun_name: Option, + disable_peer_discovery: Option, + peer_discovery_port: Option, + api_addr: Option, + metrics_api_address: Option, + network_name: Option, + network_key_file: Option, + firewall_mark: Option, +} + #[tokio::main] async fn main() -> Result<(), Box> { let cli = Cli::parse(); + // Init default configuration + let mut mycelium_config = MyceliumConfig::default(); + + // Load configuration file + if let Some(config_file_path) = &cli.config_file { + if Path::new(config_file_path).exists() { + let config = config::Config::builder() + .add_source(config::File::new( + config_file_path.to_str().unwrap(), + config::FileFormat::Toml, + )) + .build()?; + + mycelium_config = config.try_deserialize()?; + } else { + let error_msg = format!("Config file {:?} not found", config_file_path); + return Err(io::Error::new(io::ErrorKind::NotFound, error_msg).into()); + } + } else if let Some(mut conf) = dirs::config_dir() { + // Windows: %APPDATA%/ThreeFold Tech/Mycelium/mycelium.conf + #[cfg(target_os = "windows")] + { + conf = conf + .join("ThreeFold Tech") + .join("Mycelium") + .join("mycelium.toml") + }; + // Linux: $HOME/.config/mycelium/mycelium.conf + #[cfg(target_os = "linux")] + { + conf = conf.join("mycelium").join("mycelium.toml") + }; + // MacOS: $HOME/Library/Application Support/ThreeFold Tech/Mycelium/mycelium.conf + #[cfg(target_os = "macos")] + { + conf = conf + .join("ThreeFold Tech") + .join("Mycelium") + .join("mycelium.toml") + }; + + if conf.exists() { + info!( + conf_dir = conf.to_str().unwrap(), + "Mycelium is starting with configuration file", + ); + let config = config::Config::builder() + .add_source(config::File::new( + conf.to_str().unwrap(), + config::FileFormat::Toml, + )) + .build()?; + mycelium_config = config.try_deserialize()?; + } + } + let level = if cli.silent { tracing::Level::ERROR } else if cli.debug { @@ -317,8 +395,10 @@ async fn main() -> Result<(), Box> { match cli.command { None => { + let merged_config = merge_config(cli.node_args, mycelium_config); + let private_network_config = - match (cli.node_args.network_name, cli.node_args.network_key_file) { + match (merged_config.network_name, merged_config.network_key_file) { (Some(network_name), Some(network_key_file)) => { let net_key = load_key_file(&network_key_file).await?; @@ -337,46 +417,46 @@ async fn main() -> Result<(), Box> { secret_key }; - let _api = if let Some(metrics_api_addr) = cli.node_args.metrics_api_address { + let _api = if let Some(metrics_api_addr) = merged_config.metrics_api_address { let metrics = mycelium_metrics::PrometheusExporter::new(); let config = mycelium::Config { node_key: node_secret_key, - peers: cli.node_args.static_peers, - no_tun: cli.node_args.no_tun, - tcp_listen_port: cli.node_args.tcp_listen_port, - quic_listen_port: Some(cli.node_args.quic_listen_port), - peer_discovery_port: if cli.node_args.disable_peer_discovery { + peers: merged_config.static_peers, + no_tun: merged_config.no_tun, + tcp_listen_port: merged_config.tcp_listen_port, + quic_listen_port: Some(merged_config.quic_listen_port), + peer_discovery_port: if merged_config.disable_peer_discovery { None } else { - Some(cli.node_args.peer_discovery_port) + Some(merged_config.peer_discovery_port) }, - tun_name: cli.node_args.tun_name, + tun_name: merged_config.tun_name, private_network_config, metrics: metrics.clone(), - firewall_mark: cli.node_args.firewall_mark, + firewall_mark: merged_config.firewall_mark, }; metrics.spawn(metrics_api_addr); let node = Node::new(config).await?; - mycelium_api::Http::spawn(node, cli.node_args.api_addr) + mycelium_api::Http::spawn(node, merged_config.api_addr) } else { let config = mycelium::Config { node_key: node_secret_key, - peers: cli.node_args.static_peers, - no_tun: cli.node_args.no_tun, - tcp_listen_port: cli.node_args.tcp_listen_port, - quic_listen_port: Some(cli.node_args.quic_listen_port), - peer_discovery_port: if cli.node_args.disable_peer_discovery { + peers: merged_config.static_peers, + no_tun: merged_config.no_tun, + tcp_listen_port: merged_config.tcp_listen_port, + quic_listen_port: Some(merged_config.quic_listen_port), + peer_discovery_port: if merged_config.disable_peer_discovery { None } else { - Some(cli.node_args.peer_discovery_port) + Some(merged_config.peer_discovery_port) }, - tun_name: cli.node_args.tun_name, + tun_name: merged_config.tun_name, private_network_config, metrics: mycelium_metrics::NoMetrics, - firewall_mark: cli.node_args.firewall_mark, + firewall_mark: merged_config.firewall_mark, }; let node = Node::new(config).await?; - mycelium_api::Http::spawn(node, cli.node_args.api_addr) + mycelium_api::Http::spawn(node, merged_config.api_addr) }; // TODO: put in dedicated file so we can only rely on certain signals on unix platforms @@ -527,3 +607,86 @@ async fn save_key_file(key: &crypto::SecretKey, path: &Path) -> io::Result<()> { Ok(()) } + +fn merge_config(cli_args: NodeArguments, file_config: MyceliumConfig) -> NodeArguments { + NodeArguments { + static_peers: if !cli_args.static_peers.is_empty() { + cli_args.static_peers + } else { + file_config.peers.unwrap_or_default() + }, + tcp_listen_port: if cli_args.tcp_listen_port != DEFAULT_TCP_LISTEN_PORT { + cli_args.tcp_listen_port + } else { + file_config + .tcp_listen_port + .unwrap_or(DEFAULT_TCP_LISTEN_PORT) + }, + quic_listen_port: if cli_args.quic_listen_port != DEFAULT_QUIC_LISTEN_PORT { + cli_args.quic_listen_port + } else { + file_config + .quic_listen_port + .unwrap_or(DEFAULT_QUIC_LISTEN_PORT) + }, + peer_discovery_port: if cli_args.peer_discovery_port != DEFAULT_PEER_DISCOVERY_PORT { + cli_args.peer_discovery_port + } else { + file_config + .peer_discovery_port + .unwrap_or(DEFAULT_PEER_DISCOVERY_PORT) + }, + disable_peer_discovery: cli_args.disable_peer_discovery + || file_config.disable_peer_discovery.unwrap_or(false), + api_addr: if cli_args.api_addr != DEFAULT_HTTP_API_SERVER_ADDRESS { + cli_args.api_addr + } else { + file_config + .api_addr + .unwrap_or(DEFAULT_HTTP_API_SERVER_ADDRESS) + }, + no_tun: cli_args.no_tun || file_config.no_tun.unwrap_or(false), + tun_name: if cli_args.tun_name != *TUN_NAME { + cli_args.tun_name + } else { + file_config.tun_name.unwrap_or_else(|| TUN_NAME.to_string()) + }, + metrics_api_address: cli_args + .metrics_api_address + .or(file_config.metrics_api_address), + network_name: cli_args.network_name.or(file_config.network_name), + network_key_file: cli_args.network_key_file.or(file_config.network_key_file), + firewall_mark: cli_args.firewall_mark.or(file_config.firewall_mark), + } +} + +/// Deserialize an optional list of endpoints from TOML format. The endpoints can be provided +/// either as a list `[...]`, or in case there is only 1 endpoint, it can also be provided as a +/// single string element. If no value is provided, it returns None. +fn deserialize_optional_endpoint_str_from_toml<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrVec { + String(String), + Vec(Vec), + } + + Ok(match Option::::deserialize(deserializer)? { + Some(StringOrVec::Vec(v)) => Some( + v.into_iter() + .map(|s| { + ::from_str(&s).map_err(serde::de::Error::custom) + }) + .collect::, _>>()?, + ), + Some(StringOrVec::String(s)) => Some(vec![ + ::from_str(&s).map_err(serde::de::Error::custom)? + ]), + None => None, + }) +} diff --git a/myceliumd/src/main.rs b/myceliumd/src/main.rs index b900432..abb48f7 100644 --- a/myceliumd/src/main.rs +++ b/myceliumd/src/main.rs @@ -622,20 +622,10 @@ fn merge_config(cli_args: NodeArguments, file_config: MyceliumConfig) -> NodeArg } else { file_config.tun_name.unwrap_or_else(|| TUN_NAME.to_string()) }, - metrics_api_address: if cli_args.metrics_api_address.is_some() { - cli_args.metrics_api_address - } else if file_config.metrics_api_address.is_some() { - file_config.metrics_api_address - } else { - None - }, - firewall_mark: if cli_args.firewall_mark.is_some() { - cli_args.firewall_mark - } else if file_config.firewall_mark.is_some() { - file_config.firewall_mark - } else { - None - }, + metrics_api_address: cli_args + .metrics_api_address + .or(file_config.metrics_api_address), + firewall_mark: cli_args.firewall_mark.or(file_config.firewall_mark), } }