/* This file is part of DarkFi (https://dark.fi) * * Copyright (C) 2020-2022 Dyne.org foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ use std::sync::Arc; use serde::Deserialize; use structopt::StructOpt; use structopt_toml::StructOptToml; use url::Url; use crate::net::transport::TransportName; /// Atomic pointer to network settings. pub type SettingsPtr = Arc; /// Default settings for the network. Can be manually configured. #[derive(Clone, Debug)] pub struct Settings { /// P2P accept addresses node listens to for inbound connections pub inbound: Vec, /// Outbound connection slots number pub outbound_connections: u32, /// Manual connections retry limit, 0 for forever looping pub manual_attempt_limit: u32, /// Seed connection establishment timeout pub seed_query_timeout_seconds: u32, /// Connection establishment timeout pub connect_timeout_seconds: u32, /// Exchange versions (handshake) timeout pub channel_handshake_seconds: u32, /// Ping-pong exhange execution interval pub channel_heartbeat_seconds: u32, /// Try to fill an outbound slot interval pub outbound_retry_seconds: u64, /// P2P external addresses node advertises so other peers can reach us /// and connect to us, as long us inbound addresses are also configured pub external_addr: Vec, /// Peer nodes to manually connect to pub peers: Vec, /// Seed nodes to connect to for peers retrieval and/or advertising our own /// external address pub seeds: Vec, /// Only used for debugging. Compromises privacy when set. pub node_id: String, /// Application version, used for verification between peers pub app_version: Option, /// Prefered transports for outbound connections pub outbound_transports: Vec, /// Allow localnet hosts pub localnet: bool, /// Enable peer discovery pub peer_discovery: bool, /// Enable channel logging pub channel_log: bool, } impl Default for Settings { fn default() -> Self { Self { inbound: Vec::new(), outbound_connections: 0, manual_attempt_limit: 0, seed_query_timeout_seconds: 8, connect_timeout_seconds: 10, channel_handshake_seconds: 4, channel_heartbeat_seconds: 10, outbound_retry_seconds: 20, external_addr: Vec::new(), peers: Vec::new(), seeds: Vec::new(), node_id: String::new(), app_version: Some(option_env!("CARGO_PKG_VERSION").unwrap_or("").to_string()), outbound_transports: get_outbound_transports(vec![]), localnet: false, peer_discovery: true, channel_log: false, } } } /// Defines the network settings. #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)] #[structopt()] pub struct SettingsOpt { /// P2P accept addresses node listens to for inbound connections #[serde(default)] #[structopt(long = "accept")] pub inbound: Vec, /// Outbound connection slots number #[structopt(long = "slots")] pub outbound_connections: Option, /// P2P external addresses node advertises so other peers can reach us /// and connect to us, as long us inbound addresses are also configured #[serde(default)] #[structopt(long)] pub external_addr: Vec, /// Peer nodes to manually connect to #[serde(default)] #[structopt(long)] pub peers: Vec, /// Seed nodes to connect to for peers retrieval and/or advertising our own /// external address #[serde(default)] #[structopt(long)] pub seeds: Vec, /// Manual connections retry limit #[structopt(skip)] pub manual_attempt_limit: Option, /// Seed connection establishment timeout #[structopt(skip)] pub seed_query_timeout_seconds: Option, /// Connection establishment timeout #[structopt(skip)] pub connect_timeout_seconds: Option, /// Exchange versions (handshake) timeout #[structopt(skip)] pub channel_handshake_seconds: Option, /// Ping-pong exhange execution interval #[structopt(skip)] pub channel_heartbeat_seconds: Option, /// Try to fill an outbound slot interval #[structopt(skip)] pub outbound_retry_seconds: Option, /// Only used for debugging. Compromises privacy when set. #[serde(default)] #[structopt(skip)] pub node_id: String, /// Application version, used for verification between peers #[serde(default)] #[structopt(skip)] pub app_version: Option, /// Prefered transports for outbound connections #[serde(default)] #[structopt(long = "transports")] pub outbound_transports: Vec, /// Allow localnet hosts #[serde(default)] #[structopt(long)] pub localnet: bool, /// Enable peer discovery #[serde(default = "default_as_true")] #[structopt(long)] pub peer_discovery: bool, /// Enable channel logging #[serde(default)] #[structopt(long)] pub channel_log: bool, } impl From for Settings { fn from(settings_opt: SettingsOpt) -> Self { Self { inbound: settings_opt.inbound, outbound_connections: settings_opt.outbound_connections.unwrap_or(0), manual_attempt_limit: settings_opt.manual_attempt_limit.unwrap_or(0), seed_query_timeout_seconds: settings_opt.seed_query_timeout_seconds.unwrap_or(8), connect_timeout_seconds: settings_opt.connect_timeout_seconds.unwrap_or(10), channel_handshake_seconds: settings_opt.channel_handshake_seconds.unwrap_or(4), channel_heartbeat_seconds: settings_opt.channel_heartbeat_seconds.unwrap_or(10), outbound_retry_seconds: settings_opt.outbound_retry_seconds.unwrap_or(1200), external_addr: settings_opt.external_addr, peers: settings_opt.peers, seeds: settings_opt.seeds, node_id: settings_opt.node_id, app_version: settings_opt.app_version, outbound_transports: get_outbound_transports(settings_opt.outbound_transports), localnet: settings_opt.localnet, peer_discovery: settings_opt.peer_discovery, channel_log: settings_opt.channel_log, } } } /// Auxiliary function to convert outbound transport Vec /// to Vec, using defaults if empty. pub fn get_outbound_transports(opt_outbound_transports: Vec) -> Vec { let mut outbound_transports = vec![]; for transport in opt_outbound_transports { let transport_name = TransportName::try_from(transport.as_str()).unwrap(); outbound_transports.push(transport_name); } if outbound_transports.is_empty() { let tls = TransportName::Tcp(Some("tls".into())); outbound_transports.push(tls); let tcp = TransportName::Tcp(None); outbound_transports.push(tcp); } outbound_transports } /// Auxiliary function to set serde bool value to true. fn default_as_true() -> bool { true }