#pragma once #include "definition.hpp" #include "ini.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace llarp { using SectionValues = llarp::ConfigParser::SectionValues; using ConfigMap = llarp::ConfigParser::ConfigMap; inline const std::string QUAD_ZERO{"0.0.0.0"}; inline constexpr uint16_t DEFAULT_LISTEN_PORT{1090}; inline constexpr int CLIENT_ROUTER_CONNECTIONS = 4; // TODO: don't use these maps. they're sloppy and difficult to follow /// Small struct to gather all parameters needed for config generation to reduce the number of /// parameters that need to be passed around. struct ConfigGenParameters { ConfigGenParameters() = default; virtual ~ConfigGenParameters() = default; ConfigGenParameters(const ConfigGenParameters&) = delete; ConfigGenParameters(ConfigGenParameters&&) = delete; bool is_relay = false; fs::path default_data_dir; /// get network platform (virtual for unit test mocks) virtual const llarp::net::Platform* Net_ptr() const = 0; }; struct RouterConfig { int client_router_connections{CLIENT_ROUTER_CONNECTIONS}; std::string net_id; fs::path data_dir; bool block_bogons = false; int worker_threads = -1; int net_threads = -1; size_t job_que_size = 0; std::string rc_file; std::string enckey_file; std::string idkey_file; std::string transkey_file; bool is_relay = false; std::optional public_ip; std::optional public_port; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; /// config for path hop selection struct PeerSelectionConfig { /// in our hops what netmask will we use for unique ips for hops /// i.e. 32 for every hop unique ip, 24 unique /24 per hop, etc /// int unique_hop_netmask; /// set of countrys to exclude from path building (2 char country code) std::unordered_set exclude_countries; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); /// return true if this set of router contacts is acceptable against this config bool check_rcs(const std::set& hops) const; }; struct NetworkConfig { std::optional enable_profiling; bool save_profiles; std::set strict_connect; std::string if_name; IPRange if_addr; std::optional keyfile; std::string endpoint_type; bool is_reachable = false; std::optional hops; std::optional paths; bool allow_exit = false; std::set snode_blacklist; net::IPRangeMap exit_map; net::IPRangeMap ons_exit_map; std::unordered_map exit_auths; std::unordered_map ons_exit_auths; std::unordered_map map_addrs; service::AuthType auth_type = service::AuthType::NONE; service::AuthFileType auth_file_type = service::AuthFileType::HASHES; std::optional auth_url; std::optional auth_method; std::unordered_set auth_whitelist; std::unordered_set auth_static_tokens; std::set auth_files; std::vector srv_records; std::optional base_ipv6_addr; std::set owned_ranges; std::optional traffic_policy; std::optional path_alignment_timeout; std::optional addr_map_persist_file; bool enable_route_poker; bool blackhole_routes; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct DnsConfig { bool raw; std::vector bind_addr; std::vector upstream_dns; std::vector hostfiles; std::optional query_bind; std::unordered_multimap extra_opts; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct LinksConfig { // DEPRECATED -- use [Router]:public_addr std::optional public_addr; // DEPRECATED -- use [Router]:public_port std::optional public_port; std::optional listen_addr; bool using_user_value = false; bool using_new_api = false; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; // TODO: remove oxenmq from this header struct ApiConfig { bool enable_rpc_server = false; std::vector rpc_bind_addrs; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct LokidConfig { fs::path id_keyfile; oxenmq::address rpc_addr; bool disable_testing = true; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct BootstrapConfig { std::vector files; bool seednode; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct LoggingConfig { log::Type type = log::Type::Print; log::Level level = log::Level::off; std::string file; void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct Config { explicit Config(std::optional datadir = std::nullopt); virtual ~Config() = default; /// create generation params (virtual for unit test mock) virtual std::unique_ptr make_gen_params() const; RouterConfig router; NetworkConfig network; PeerSelectionConfig paths; DnsConfig dns; LinksConfig links; ApiConfig api; LokidConfig lokid; BootstrapConfig bootstrap; LoggingConfig logging; // Initialize config definition void init_config(ConfigDefinition& conf, const ConfigGenParameters& params); /// Insert config entries for backwards-compatibility (e.g. so that the config system will /// tolerate old values that are no longer accepted) /// /// @param conf is the config to modify void add_backcompat_opts(ConfigDefinition& conf); // Load a config from the given file if the config file is not provided LoadDefault is called bool load(std::optional fname = std::nullopt, bool isRelay = false); // Load a config from a string of ini, same effects as Config::Load bool load_string(std::string_view ini, bool isRelay = false); std::string generate_client_config_base(); std::string generate_router_config_base(); void save(); void override(std::string section, std::string key, std::string value); void add_default(std::string section, std::string key, std::string value); /// create a config with the default parameters for an embedded lokinet static std::shared_ptr make_embedded_config(); private: /// Load (initialize) a default config. /// /// This delegates to the ConfigDefinition to generate a default config, /// as though an empty config were specified. /// /// If using Config without the intention of loading from file (or string), this is necessary /// in order to obtain sane defaults. /// /// @param isRelay determines whether the config will reflect that of a relay or client /// @param dataDir is a path representing a directory to be used as the data dir /// @return true on success, false otherwise bool load_default_config(bool isRelay); bool load_config_data( std::string_view ini, std::optional fname = std::nullopt, bool isRelay = false); void load_overrides(ConfigDefinition& conf) const; std::vector> additional; ConfigParser parser; const fs::path data_dir; }; void ensure_config(fs::path dataDir, fs::path confFile, bool overwrite, bool asRouter); } // namespace llarp