diff --git a/cmake/target_link_libraries_system.cmake b/cmake/target_link_libraries_system.cmake index 761b7c767..eca571601 100644 --- a/cmake/target_link_libraries_system.cmake +++ b/cmake/target_link_libraries_system.cmake @@ -4,6 +4,6 @@ function(target_link_libraries_system target) foreach(lib ${libs}) get_target_property(lib_include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) target_include_directories(${target} SYSTEM PUBLIC ${lib_include_dirs}) - target_link_libraries(${target} ${lib}) + target_link_libraries(${target} PUBLIC ${lib}) endforeach(lib) endfunction() diff --git a/daemon/main.cpp b/daemon/main.cpp index aaaf3fa2c..2fce4f6fb 100644 --- a/daemon/main.cpp +++ b/daemon/main.cpp @@ -1,9 +1,9 @@ -#include // for ensure_config +#include // for ensure_config #include #include #include -#include +#include #if !defined(_WIN32) && !defined(__OpenBSD__) #include diff --git a/include/llarp.hpp b/include/llarp.hpp index 56d3aa322..da5aa4f8d 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -18,11 +18,12 @@ struct llarp_threadpool; namespace llarp { + class Logic; + struct AbstractRouter; struct Config; struct Crypto; struct CryptoManager; - class Logic; - struct AbstractRouter; + struct MetricsConfig; struct RouterContact; namespace metrics @@ -47,13 +48,8 @@ namespace llarp std::unique_ptr< metrics::DefaultManagerGuard > m_metricsManager; std::unique_ptr< metrics::PublisherScheduler > m_metricsPublisher; - int num_nethreads = 1; - bool singleThreaded = false; - bool disableMetrics = false; - bool disableMetricLogs = false; - fs::path jsonMetricsPath; - std::string metricTankHost; - std::map< std::string, std::string > metricTags; + int num_nethreads = 1; + bool singleThreaded = false; std::unique_ptr< Crypto > crypto; std::unique_ptr< CryptoManager > cryptoManager; @@ -111,14 +107,11 @@ namespace llarp bool ReloadConfig(); - void - iter_config(const char *section, const char *key, const char *val); - void progress(); void - setupMetrics(); + setupMetrics(const MetricsConfig &metricsConfig); std::string configfile; std::string pidfile; diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index de365675c..211ca19bc 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -1,4 +1,6 @@ set(LIB_UTIL_SRC + config/config.cpp + config/ini.cpp constants/defaults.cpp constants/link_layer.cpp constants/path.cpp @@ -13,7 +15,6 @@ set(LIB_UTIL_SRC util/encode.cpp util/endian.cpp util/fs.cpp - util/ini.cpp util/json.cpp util/logger.cpp util/android_logger.cpp @@ -52,6 +53,7 @@ set(LIB_UTIL_SRC add_library(${UTIL_LIB} STATIC ${LIB_UTIL_SRC}) target_include_directories(${UTIL_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include) +target_link_libraries(${UTIL_LIB} PUBLIC ${CRYPTOGRAPHY_LIB}) target_link_libraries_system(${UTIL_LIB} absl::synchronization absl::hash absl::container nlohmann_json::nlohmann_json) # cut back on fluff @@ -125,7 +127,6 @@ set(DNSLIB_SRC set(LIB_SRC ${DNSLIB_SRC} - config.cpp context.cpp crypto/constants.cpp crypto/crypto_libsodium.cpp diff --git a/llarp/config.cpp b/llarp/config.cpp deleted file mode 100644 index ca1ec36ea..000000000 --- a/llarp/config.cpp +++ /dev/null @@ -1,369 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace llarp -{ - template < typename Config, typename Section > - Section - find_section(Config &c, const std::string &name, const Section &fallback) - { - Section ret; - if(c.VisitSection(name.c_str(), - [&ret](const ConfigParser::Section_t &s) -> bool { - for(const auto &item : s) - { - ret.emplace_back(string_view_string(item.first), - string_view_string(item.second)); - } - return true; - })) - return ret; - else - return fallback; - } - - bool - Config::Load(const char *fname) - { - ConfigParser parser; - if(!parser.LoadFile(fname)) - { - return false; - } - router = find_section(parser, "router", section_t{}); - network = find_section(parser, "network", section_t{}); - connect = find_section(parser, "connect", section_t{}); - netdb = find_section(parser, "netdb", section_t{}); - dns = find_section(parser, "dns", section_t{}); - iwp_links = find_section(parser, "bind", section_t{}); - services = find_section(parser, "services", section_t{}); - system = find_section(parser, "system", section_t{}); - metrics = find_section(parser, "metrics", section_t{}); - api = find_section(parser, "api", section_t{}); - lokid = find_section(parser, "lokid", section_t{}); - bootstrap = find_section(parser, "bootstrap", section_t{}); - logging = find_section(parser, "logging", section_t{}); - return true; - } - - void - Config::visit(const Visitor &functor) - { - std::unordered_map< std::string, const llarp::Config::section_t & > - sections = {{"network", network}, - {"connect", connect}, - {"bootstrap", bootstrap}, - {"system", system}, - {"metrics", metrics}, - {"netdb", netdb}, - {"api", api}, - {"services", services}}; - - auto visitor = [&](const char *name, const auto &item) { - functor(name, item.first.c_str(), item.second.c_str()); - }; - - using namespace std::placeholders; - - std::for_each(logging.begin(), logging.end(), - std::bind(visitor, "logging", _1)); - // end of logging section commit settings and go - functor("logging", "", ""); - std::for_each(lokid.begin(), lokid.end(), std::bind(visitor, "lokid", _1)); - std::for_each(router.begin(), router.end(), - std::bind(visitor, "router", _1)); - - std::for_each(dns.begin(), dns.end(), std::bind(visitor, "dns", _1)); - std::for_each(iwp_links.begin(), iwp_links.end(), - std::bind(visitor, "bind", _1)); - - std::for_each(sections.begin(), sections.end(), [&](const auto §ion) { - std::for_each(section.second.begin(), section.second.end(), - std::bind(visitor, section.first.c_str(), _1)); - }); - } - -} // namespace llarp - -/// fname should be a relative path (from CWD) or absolute path to the config -/// file -extern "C" bool -llarp_ensure_config(const char *fname, const char *basedir, bool overwrite, - bool asRouter) -{ - std::error_code ec; - if(fs::exists(fname, ec) && !overwrite) - { - return true; - } - if(ec) - { - llarp::LogError(ec); - return false; - } - - std::string basepath = ""; - if(basedir) - { - basepath = basedir; -#ifndef _WIN32 - basepath += "/"; -#else - basepath += "\\"; -#endif - } - - llarp::LogInfo("Attempting to create config file ", fname); - - // abort if config already exists - if(!asRouter) - { - if(fs::exists(fname, ec) && !overwrite) - { - llarp::LogError(fname, " currently exists, please use -f to overwrite"); - return true; - } - if(ec) - { - llarp::LogError(ec); - return false; - } - } - - // write fname ini - auto optional_f = - llarp::util::OpenFileStream< std::ofstream >(fname, std::ios::binary); - if(!optional_f || !optional_f.value().is_open()) - { - llarp::LogError("failed to open ", fname, " for writing"); - return false; - } - auto &f = optional_f.value(); - llarp_generic_ensure_config(f, basepath); - if(asRouter) - { - llarp_ensure_router_config(f, basepath); - } - else - { - llarp_ensure_client_config(f, basepath); - } - llarp::LogInfo("Generated new config ", fname); - return true; -} - -void -llarp_generic_ensure_config(std::ofstream &f, std::string basepath) -{ - f << "# this configuration was auto generated with 'sane' defaults" - << std::endl; - f << "# change these values as desired" << std::endl; - f << std::endl << std::endl; - f << "[router]" << std::endl; - f << "# number of crypto worker threads " << std::endl; - f << "threads=4" << std::endl; - f << "# path to store signed RC" << std::endl; - f << "contact-file=" << basepath << "self.signed" << std::endl; - f << "# path to store transport private key" << std::endl; - f << "transport-privkey=" << basepath << "transport.private" << std::endl; - f << "# path to store identity signing key" << std::endl; - f << "ident-privkey=" << basepath << "identity.private" << std::endl; - f << "# encryption key for onion routing" << std::endl; - f << "encryption-privkey=" << basepath << "encryption.private" << std::endl; - f << std::endl; - f << "# uncomment following line to set router nickname to 'lokinet'" - << std::endl; - f << "#nickname=lokinet" << std::endl; - f << std::endl << std::endl; - - // logging - f << "[logging]" << std::endl; - f << "level=info" << std::endl; - f << "# uncomment for logging to file" << std::endl; - f << "#type=file" << std::endl; - f << "#file=/path/to/logfile" << std::endl; - f << "# uncomment for syslog logging" << std::endl; - f << "#type=syslog" << std::endl; - - // metrics - f << "[metrics]" << std::endl; - f << "json-metrics-path=" << basepath << "metrics.json" << std::endl; - - f << std::endl << std::endl; - - f << "# admin api (disabled by default)" << std::endl; - f << "[api]" << std::endl; - f << "enabled=false" << std::endl; - f << "#authkey=insertpubkey1here" << std::endl; - f << "#authkey=insertpubkey2here" << std::endl; - f << "#authkey=insertpubkey3here" << std::endl; - f << "bind=127.0.0.1:1190" << std::endl; - f << std::endl << std::endl; - - f << "# system settings for privileges and such" << std::endl; - f << "[system]" << std::endl; - f << "user=" << DEFAULT_LOKINET_USER << std::endl; - f << "group=" << DEFAULT_LOKINET_GROUP << std::endl; - f << "pidfile=" << basepath << "lokinet.pid" << std::endl; - f << std::endl << std::endl; - - f << "# dns provider configuration section" << std::endl; - f << "[dns]" << std::endl; - f << "# resolver" << std::endl; - f << "upstream=" << DEFAULT_RESOLVER_US << std::endl; - -// Make auto-config smarter -// will this break reproducibility rules? -// (probably) -#ifdef __linux__ -#ifdef ANDROID - f << "bind=127.0.0.1:1153" << std::endl; -#else - f << "bind=127.3.2.1:53" << std::endl; -#endif -#else - f << "bind=127.0.0.1:53" << std::endl; -#endif - f << std::endl << std::endl; - - f << "# network database settings block " << std::endl; - f << "[netdb]" << std::endl; - f << "# directory for network database skiplist storage" << std::endl; - f << "dir=" << basepath << "netdb" << std::endl; - f << std::endl << std::endl; - - f << "# bootstrap settings" << std::endl; - f << "[bootstrap]" << std::endl; - f << "# add a bootstrap node's signed identity to the list of nodes we want " - "to bootstrap from" - << std::endl; - f << "# if we don't have any peers we connect to this router" << std::endl; - f << "add-node=" << basepath << "bootstrap.signed" << std::endl; - // we only process one of these... - // f << "# add another bootstrap node" << std::endl; - // f << "#add-node=/path/to/alternative/self.signed" << std::endl; - f << std::endl << std::endl; -} - -void -llarp_ensure_router_config(std::ofstream &f, std::string basepath) -{ - f << "# lokid settings (disabled by default)" << std::endl; - f << "[lokid]" << std::endl; - f << "enabled=false" << std::endl; - f << "jsonrpc=127.0.0.1:22023" << std::endl; - f << "#service-node-seed=/path/to/servicenode/seed" << std::endl; - f << std::endl; - f << "# network settings " << std::endl; - f << "[network]" << std::endl; - f << "profiles=" << basepath << "profiles.dat" << std::endl; - // better to let the routers auto-configure - // f << "ifaddr=auto" << std::endl; - // f << "ifname=auto" << std::endl; - f << "enabled=true" << std::endl; - f << "exit=false" << std::endl; - f << "#exit-blacklist=tcp:25" << std::endl; - f << "#exit-whitelist=tcp:*" << std::endl; - f << "#exit-whitelist=udp:*" << std::endl; - f << std::endl; - f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic" - << std::endl; - f << "[bind]" << std::endl; - // get ifname - std::string ifname; - if(llarp::GetBestNetIF(ifname, AF_INET)) - f << ifname << "=1090" << std::endl; - else - f << "# could not autodetect network interface" << std::endl - << "#eth0=1090" << std::endl; - - f << std::endl; -} - -bool -llarp_ensure_client_config(std::ofstream &f, std::string basepath) -{ - // write snapp-example.ini - const std::string snappExample_fpath = basepath + "snapp-example.ini"; - { - auto stream = llarp::util::OpenFileStream< std::ofstream >( - snappExample_fpath, std::ios::binary); - if(!stream) - return false; - auto &example_f = stream.value(); - if(example_f.is_open()) - { - // pick ip - // don't revert me - const static std::string ip = "10.33.0.1/16"; - /* - std::string ip = llarp::findFreePrivateRange(); - if(ip == "") - { - llarp::LogError( - "Couldn't easily detect a private range to map lokinet onto"); - return false; - } - */ - example_f << "# this is an example configuration for a snapp" - << std::endl; - example_f << "[example-snapp]" << std::endl; - example_f << "# keyfile is the path to the private key of the snapp, " - "your .loki is tied to this key, DON'T LOSE IT" - << std::endl; - example_f << "keyfile=" << basepath << "example-snap-keyfile.private" - << std::endl; - example_f << "# ifaddr is the ip range to allocate to this snapp" - << std::endl; - example_f << "ifaddr=" << ip << std::endl; - // probably fine to leave this (and not-auto-detect it) I'm not worried - // about any collisions - example_f << "# ifname is the name to try and give to the network " - "interface this snap owns" - << std::endl; - example_f << "ifname=snapp-tun0" << std::endl; - } - else - { - llarp::LogError("failed to write ", snappExample_fpath); - } - } - // now do up fname - f << std::endl << std::endl; - f << "# snapps configuration section" << std::endl; - f << "[services]"; - f << "# uncomment next line to enable a snapp" << std::endl; - f << "#example-snapp=" << snappExample_fpath << std::endl; - f << std::endl << std::endl; - - f << "# network settings " << std::endl; - f << "[network]" << std::endl; - f << "profiles=" << basepath << "profiles.dat" << std::endl; - f << "# uncomment next line to add router with pubkey to list of routers we " - "connect directly to" - << std::endl; - f << "#strict-connect=pubkey" << std::endl; - f << "# uncomment next line to use router with pubkey as an exit node" - << std::endl; - f << "#exit-node=pubkey" << std::endl; - - // better to set them to auto then to hard code them now - // operating environment may change over time and this will help adapt - // f << "ifname=auto" << std::endl; - // f << "ifaddr=auto" << std::endl; - - // should this also be auto? or not declared? - // probably auto in case they want to set up a hidden service - f << "enabled=true" << std::endl; - return true; -} diff --git a/llarp/config.hpp b/llarp/config.hpp deleted file mode 100644 index 520733bd9..000000000 --- a/llarp/config.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef LLARP_CONFIG_HPP -#define LLARP_CONFIG_HPP - -#include -#include -#include -#include - -namespace llarp -{ - struct Config - { - using section_t = std::vector< std::pair< std::string, std::string > >; - - section_t router; - section_t network; - section_t netdb; - section_t dns; - section_t iwp_links; - section_t connect; - section_t services; - section_t system; - section_t metrics; - section_t api; - section_t lokid; - section_t bootstrap; - section_t logging; - - bool - Load(const char *fname); - - using Visitor = std::function< void(const char *section, const char *key, - const char *val) >; - - void - visit(const Visitor &visitor); - }; - -} // namespace llarp - -void -llarp_generic_ensure_config(std::ofstream &f, std::string basepath); - -void -llarp_ensure_router_config(std::ofstream &f, std::string basepath); - -bool -llarp_ensure_client_config(std::ofstream &f, std::string basepath); - -#endif diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp new file mode 100644 index 000000000..d7092a4d5 --- /dev/null +++ b/llarp/config/config.cpp @@ -0,0 +1,704 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace llarp +{ + bool + RouterConfig::fromSection(string_view key, string_view val) + { + if(key == "netid") + { + if(val.size() <= rc.netID.size()) + { + llarp::LogWarn("!!!! you have manually set netid to be '", val, + "' which does not equal '", Version::LLARP_NET_ID, + "' you will run as a different network, good luck " + "and " + "don't forget: something something MUH traffic " + "shape " + "correlation !!!!"); + NetID::DefaultValue() = + NetID(reinterpret_cast< const byte_t * >(std::string(val).c_str())); + // re set netid in our rc + rc.netID = llarp::NetID(); + netid.assign(val.begin(), val.end()); + } + else + { + llarp::LogError("invalid netid '", val, "', is too long"); + } + } + if(key == "max-connections") + { + std::string sVal(val.begin(), val.end()); + auto ival = atoi(sVal.c_str()); + if(ival > 0) + { + maxConnectedRouters = ival; + LogInfo("max connections set to ", maxConnectedRouters); + } + } + if(key == "min-connections") + { + std::string sVal(val.begin(), val.end()); + auto ival = atoi(sVal.c_str()); + if(ival > 0) + { + minConnectedRouters = ival; + LogInfo("min connections set to ", minConnectedRouters); + } + } + if(key == "nickname") + { + rc.SetNick(val); + // set logger name here + LogContext::Instance().nodeName = rc.Nick(); + } + if(key == "encryption-privkey") + { + encryption_keyfile.assign(val.begin(), val.end()); + } + if(key == "contact-file") + { + our_rc_file.assign(val.begin(), val.end()); + } + if(key == "transport-privkey") + { + transport_keyfile.assign(val.begin(), val.end()); + } + if((key == "identity-privkey" || key == "ident-privkey")) + { + ident_keyfile.assign(val.begin(), val.end()); + } + if(key == "public-address" || key == "public-ip") + { + llarp::LogInfo("public ip ", val, " size ", val.size()); + if(val.size() < 17) + { + // assume IPv4 + llarp::Addr a(val); + llarp::LogInfo("setting public ipv4 ", a); + addrInfo.ip = *a.addr6(); + publicOverride = true; + } + // llarp::Addr a(val); + } + if(key == "public-port") + { + llarp::LogInfo("Setting public port ", val); + int p = atoi(std::string(val).c_str()); + // Not needed to flip upside-down - this is done in llarp::Addr(const + // AddressInfo&) + ip4addr.sin_port = p; + addrInfo.port = p; + publicOverride = true; + } + if(key == "worker-threads") + { + workerThreads = atoi(std::string(val).c_str()); + } + if(key == "net-threads") + { + num_nethreads = atoi(std::string(val).c_str()); + if(num_nethreads <= 0) + num_nethreads = 1; + } + + return true; + } + bool + NetworkConfig::fromSection(string_view key, string_view val) + { + if(key == "profiling") + { + if(IsTrueValue(val)) + { + enableProfiling.emplace(true); + } + else if(IsFalseValue(val)) + { + enableProfiling.emplace(false); + } + } + if(key == "profiles") + { + routerProfilesFile.assign(val.begin(), val.end()); + llarp::LogInfo("setting profiles to ", routerProfilesFile); + } + else if(key == "strict-connect") + { + strictConnect.assign(val.begin(), val.end()); + } + else + { + netConfig.emplace(key, val); + } + return true; + } + + bool + NetdbConfig::fromSection(string_view key, string_view val) + { + if(key == "dir") + { + nodedb_dir.assign(val.begin(), val.end()); + } + + return true; + } + + bool + DnsConfig::fromSection(string_view key, string_view val) + { + if(key == "upstream") + { + llarp::LogInfo("add upstream resolver ", val); + netConfig.emplace("upstream-dns", val); + } + if(key == "bind") + { + llarp::LogInfo("set local dns to ", val); + netConfig.emplace("local-dns", val); + } + return true; + } + + bool + IwpConfig::fromSection(string_view key, string_view val) + { + // try IPv4 first + uint16_t proto = 0; + + std::set< std::string > parsed_opts; + std::string v(val.begin(), val.end()); + std::string::size_type idx; + do + { + idx = v.find_first_of(','); + if(idx != std::string::npos) + { + parsed_opts.insert(v.substr(0, idx)); + v = v.substr(idx + 1); + } + else + { + parsed_opts.insert(v); + } + } while(idx != std::string::npos); + + /// for each option + for(const auto &item : parsed_opts) + { + /// see if it's a number + auto port = std::atoi(item.c_str()); + if(port > 0) + { + /// set port + if(proto == 0) + { + proto = port; + } + } + } + + if(key == "*") + { + m_OutboundPort = proto; + } + else + { + servers.emplace_back(key, AF_INET, proto); + } + return true; + } + + bool + ConnectConfig::fromSection(ABSL_ATTRIBUTE_UNUSED string_view key, + string_view val) + { + routers.emplace_back(val.begin(), val.end()); + return true; + } + + bool + ServicesConfig::fromSection(string_view key, string_view val) + { + services.emplace_back(std::string(key.begin(), key.end()), + std::string(val.begin(), val.end())); + return true; + } + + bool + SystemConfig::fromSection(string_view key, string_view val) + { + if(key == "pidfile") + { + pidfile.assign(val.begin(), val.end()); + } + + return true; + } + + bool + MetricsConfig::fromSection(string_view key, string_view val) + { + if(key == "disable-metrics") + { + disableMetrics = true; + } + else if(key == "disable-metrics-log") + { + disableMetricLogs = true; + } + else if(key == "json-metrics-path") + { + jsonMetricsPath.assign(val.begin(), val.end()); + } + else if(key == "metric-tank-host") + { + metricTankHost.assign(val.begin(), val.end()); + } + else + { + // consume everything else as a metric tag + metricTags[std::string(key)] = std::string(val); + } + + return true; + } + + bool + ApiConfig::fromSection(string_view key, string_view val) + { + if(key == "enabled") + { + enableRPCServer = IsTrueValue(val); + } + if(key == "bind") + { + rpcBindAddr.assign(val.begin(), val.end()); + } + if(key == "authkey") + { + // TODO: add pubkey to whitelist + } + + return true; + } + + bool + LokidConfig::fromSection(string_view key, string_view val) + { + if(key == "service-node-seed") + { + usingSNSeed = true; + ident_keyfile.assign(val.begin(), val.end()); + } + if(key == "enabled") + { + whitelistRouters = IsTrueValue(val); + } + if(key == "jsonrpc" || key == "addr") + { + lokidRPCAddr.assign(val.begin(), val.end()); + } + if(key == "username") + { + lokidRPCUser.assign(val.begin(), val.end()); + } + if(key == "password") + { + lokidRPCPassword.assign(val.begin(), val.end()); + } + + return true; + } + + bool + BootstrapConfig::fromSection(string_view key, string_view val) + { + if(key == "add-node") + { + routers.emplace_back(val.begin(), val.end()); + } + + return true; + } + + bool + LoggingConfig::fromSection(string_view key, string_view val) + { + if(key == "type" && val == "syslog") + { + // TODO(despair): write event log syslog class +#if defined(_WIN32) + LogError("syslog not supported on win32"); +#else + LogInfo("Switching to syslog"); + LogContext::Instance().logStream = std::make_unique< SysLogStream >(); +#endif + } + if(key == "type" && val == "json") + { + m_LogJSON = true; + } + if(key == "file") + { + LogInfo("open log file: ", val); + std::string fname(val.begin(), val.end()); + FILE *const logfile = ::fopen(fname.c_str(), "a"); + if(logfile) + { + m_LogFile = logfile; + LogInfo("will log to file ", val); + } + else if(errno) + { + LogError("could not open log file at '", val, "': ", strerror(errno)); + errno = 0; + } + else + { + LogError("failed to open log file at '", val, + "' for an unknown reason, bailing tf out kbai"); + ::abort(); + } + } + + return true; + } + + template < typename Section, typename Config > + Section + find_section(Config &c, const std::string &name) + { + Section ret; + + auto visitor = [&ret](const ConfigParser::Section_t §ion) -> bool { + for(const auto &sec : section) + { + if(!ret.fromSection(sec.first, sec.second)) + { + return false; + } + } + return true; + }; + + if(c.VisitSection(name.c_str(), visitor)) + return ret; + else + return {}; + } + + bool + Config::Load(const char *fname) + { + ConfigParser parser; + if(!parser.LoadFile(fname)) + { + return false; + } + router = find_section< RouterConfig >(parser, "router"); + network = find_section< NetworkConfig >(parser, "network"); + connect = find_section< ConnectConfig >(parser, "connect"); + netdb = find_section< NetdbConfig >(parser, "netdb"); + dns = find_section< DnsConfig >(parser, "dns"); + iwp_links = find_section< IwpConfig >(parser, "bind"); + services = find_section< ServicesConfig >(parser, "services"); + system = find_section< SystemConfig >(parser, "system"); + metrics = find_section< MetricsConfig >(parser, "metrics"); + api = find_section< ApiConfig >(parser, "api"); + lokid = find_section< LokidConfig >(parser, "lokid"); + bootstrap = find_section< BootstrapConfig >(parser, "bootstrap"); + logging = find_section< LoggingConfig >(parser, "logging"); + return true; + } + +} // namespace llarp + +/// fname should be a relative path (from CWD) or absolute path to the config +/// file +extern "C" bool +llarp_ensure_config(const char *fname, const char *basedir, bool overwrite, + bool asRouter) +{ + std::error_code ec; + if(fs::exists(fname, ec) && !overwrite) + { + return true; + } + if(ec) + { + llarp::LogError(ec); + return false; + } + + std::string basepath = ""; + if(basedir) + { + basepath = basedir; +#ifndef _WIN32 + basepath += "/"; +#else + basepath += "\\"; +#endif + } + + llarp::LogInfo("Attempting to create config file ", fname); + + // abort if config already exists + if(!asRouter) + { + if(fs::exists(fname, ec) && !overwrite) + { + llarp::LogError(fname, " currently exists, please use -f to overwrite"); + return true; + } + if(ec) + { + llarp::LogError(ec); + return false; + } + } + + // write fname ini + auto optional_f = + llarp::util::OpenFileStream< std::ofstream >(fname, std::ios::binary); + if(!optional_f || !optional_f.value().is_open()) + { + llarp::LogError("failed to open ", fname, " for writing"); + return false; + } + auto &f = optional_f.value(); + llarp_generic_ensure_config(f, basepath); + if(asRouter) + { + llarp_ensure_router_config(f, basepath); + } + else + { + llarp_ensure_client_config(f, basepath); + } + llarp::LogInfo("Generated new config ", fname); + return true; +} + +void +llarp_generic_ensure_config(std::ofstream &f, std::string basepath) +{ + f << "# this configuration was auto generated with 'sane' defaults" + << std::endl; + f << "# change these values as desired" << std::endl; + f << std::endl << std::endl; + f << "[router]" << std::endl; + f << "# number of crypto worker threads " << std::endl; + f << "threads=4" << std::endl; + f << "# path to store signed RC" << std::endl; + f << "contact-file=" << basepath << "self.signed" << std::endl; + f << "# path to store transport private key" << std::endl; + f << "transport-privkey=" << basepath << "transport.private" << std::endl; + f << "# path to store identity signing key" << std::endl; + f << "ident-privkey=" << basepath << "identity.private" << std::endl; + f << "# encryption key for onion routing" << std::endl; + f << "encryption-privkey=" << basepath << "encryption.private" << std::endl; + f << std::endl; + f << "# uncomment following line to set router nickname to 'lokinet'" + << std::endl; + f << "#nickname=lokinet" << std::endl; + f << std::endl << std::endl; + + // logging + f << "[logging]" << std::endl; + f << "level=info" << std::endl; + f << "# uncomment for logging to file" << std::endl; + f << "#type=file" << std::endl; + f << "#file=/path/to/logfile" << std::endl; + f << "# uncomment for syslog logging" << std::endl; + f << "#type=syslog" << std::endl; + + // metrics + f << "[metrics]" << std::endl; + f << "json-metrics-path=" << basepath << "metrics.json" << std::endl; + + f << std::endl << std::endl; + + f << "# admin api (disabled by default)" << std::endl; + f << "[api]" << std::endl; + f << "enabled=false" << std::endl; + f << "#authkey=insertpubkey1here" << std::endl; + f << "#authkey=insertpubkey2here" << std::endl; + f << "#authkey=insertpubkey3here" << std::endl; + f << "bind=127.0.0.1:1190" << std::endl; + f << std::endl << std::endl; + + f << "# system settings for privileges and such" << std::endl; + f << "[system]" << std::endl; + f << "user=" << DEFAULT_LOKINET_USER << std::endl; + f << "group=" << DEFAULT_LOKINET_GROUP << std::endl; + f << "pidfile=" << basepath << "lokinet.pid" << std::endl; + f << std::endl << std::endl; + + f << "# dns provider configuration section" << std::endl; + f << "[dns]" << std::endl; + f << "# resolver" << std::endl; + f << "upstream=" << DEFAULT_RESOLVER_US << std::endl; + +// Make auto-config smarter +// will this break reproducibility rules? +// (probably) +#ifdef __linux__ +#ifdef ANDROID + f << "bind=127.0.0.1:1153" << std::endl; +#else + f << "bind=127.3.2.1:53" << std::endl; +#endif +#else + f << "bind=127.0.0.1:53" << std::endl; +#endif + f << std::endl << std::endl; + + f << "# network database settings block " << std::endl; + f << "[netdb]" << std::endl; + f << "# directory for network database skiplist storage" << std::endl; + f << "dir=" << basepath << "netdb" << std::endl; + f << std::endl << std::endl; + + f << "# bootstrap settings" << std::endl; + f << "[bootstrap]" << std::endl; + f << "# add a bootstrap node's signed identity to the list of nodes we want " + "to bootstrap from" + << std::endl; + f << "# if we don't have any peers we connect to this router" << std::endl; + f << "add-node=" << basepath << "bootstrap.signed" << std::endl; + // we only process one of these... + // f << "# add another bootstrap node" << std::endl; + // f << "#add-node=/path/to/alternative/self.signed" << std::endl; + f << std::endl << std::endl; +} + +void +llarp_ensure_router_config(std::ofstream &f, std::string basepath) +{ + f << "# lokid settings (disabled by default)" << std::endl; + f << "[lokid]" << std::endl; + f << "enabled=false" << std::endl; + f << "jsonrpc=127.0.0.1:22023" << std::endl; + f << "#service-node-seed=/path/to/servicenode/seed" << std::endl; + f << std::endl; + f << "# network settings " << std::endl; + f << "[network]" << std::endl; + f << "profiles=" << basepath << "profiles.dat" << std::endl; + // better to let the routers auto-configure + // f << "ifaddr=auto" << std::endl; + // f << "ifname=auto" << std::endl; + f << "enabled=true" << std::endl; + f << "exit=false" << std::endl; + f << "#exit-blacklist=tcp:25" << std::endl; + f << "#exit-whitelist=tcp:*" << std::endl; + f << "#exit-whitelist=udp:*" << std::endl; + f << std::endl; + f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic" + << std::endl; + f << "[bind]" << std::endl; + // get ifname + std::string ifname; + if(llarp::GetBestNetIF(ifname, AF_INET)) + f << ifname << "=1090" << std::endl; + else + f << "# could not autodetect network interface" << std::endl + << "#eth0=1090" << std::endl; + + f << std::endl; +} + +bool +llarp_ensure_client_config(std::ofstream &f, std::string basepath) +{ + // write snapp-example.ini + const std::string snappExample_fpath = basepath + "snapp-example.ini"; + { + auto stream = llarp::util::OpenFileStream< std::ofstream >( + snappExample_fpath, std::ios::binary); + if(!stream) + return false; + auto &example_f = stream.value(); + if(example_f.is_open()) + { + // pick ip + // don't revert me + const static std::string ip = "10.33.0.1/16"; + /* + std::string ip = llarp::findFreePrivateRange(); + if(ip == "") + { + llarp::LogError( + "Couldn't easily detect a private range to map lokinet onto"); + return false; + } + */ + example_f << "# this is an example configuration for a snapp" + << std::endl; + example_f << "[example-snapp]" << std::endl; + example_f << "# keyfile is the path to the private key of the snapp, " + "your .loki is tied to this key, DON'T LOSE IT" + << std::endl; + example_f << "keyfile=" << basepath << "example-snap-keyfile.private" + << std::endl; + example_f << "# ifaddr is the ip range to allocate to this snapp" + << std::endl; + example_f << "ifaddr=" << ip << std::endl; + // probably fine to leave this (and not-auto-detect it) I'm not worried + // about any collisions + example_f << "# ifname is the name to try and give to the network " + "interface this snap owns" + << std::endl; + example_f << "ifname=snapp-tun0" << std::endl; + } + else + { + llarp::LogError("failed to write ", snappExample_fpath); + } + } + // now do up fname + f << std::endl << std::endl; + f << "# snapps configuration section" << std::endl; + f << "[services]"; + f << "# uncomment next line to enable a snapp" << std::endl; + f << "#example-snapp=" << snappExample_fpath << std::endl; + f << std::endl << std::endl; + + f << "# network settings " << std::endl; + f << "[network]" << std::endl; + f << "profiles=" << basepath << "profiles.dat" << std::endl; + f << "# uncomment next line to add router with pubkey to list of routers we " + "connect directly to" + << std::endl; + f << "#strict-connect=pubkey" << std::endl; + f << "# uncomment next line to use router with pubkey as an exit node" + << std::endl; + f << "#exit-node=pubkey" << std::endl; + + // better to set them to auto then to hard code them now + // operating environment may change over time and this will help adapt + // f << "ifname=auto" << std::endl; + // f << "ifaddr=auto" << std::endl; + + // should this also be auto? or not declared? + // probably auto in case they want to set up a hidden service + f << "enabled=true" << std::endl; + return true; +} diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp new file mode 100644 index 000000000..3cbe53c75 --- /dev/null +++ b/llarp/config/config.hpp @@ -0,0 +1,190 @@ +#ifndef LLARP_CONFIG_HPP +#define LLARP_CONFIG_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace llarp +{ + struct RouterConfig + { + /// always maintain this many connections to other routers + size_t minConnectedRouters = 2; + + /// hard upperbound limit on the number of router to router connections + size_t maxConnectedRouters = 2000; + + std::string netid; + RouterContact rc; + + fs::path encryption_keyfile = "encryption.key"; + + // path to write our self signed rc to + fs::path our_rc_file = "rc.signed"; + + // transient iwp encryption key + fs::path transport_keyfile = "transport.key"; + + // long term identity key + fs::path ident_keyfile = "identity.key"; + + bool publicOverride = false; + struct sockaddr_in ip4addr; + AddressInfo addrInfo; + + int workerThreads; + int num_nethreads; + + bool + fromSection(string_view key, string_view val); + }; + + struct NetworkConfig + { + absl::optional< bool > enableProfiling; + std::string routerProfilesFile = "profiles.dat"; + std::string strictConnect; + std::unordered_multimap< std::string, std::string > netConfig; + + bool + fromSection(string_view key, string_view val); + }; + + struct NetdbConfig + { + std::string nodedb_dir; + + bool + fromSection(string_view key, string_view val); + }; + + struct DnsConfig + { + std::unordered_multimap< std::string, std::string > netConfig; + + bool + fromSection(string_view key, string_view val); + }; + + struct IwpConfig + { + uint16_t m_OutboundPort = 0; + + std::vector< std::tuple< std::string, int, uint16_t > > servers; + + bool + fromSection(string_view key, string_view val); + }; + + struct ConnectConfig + { + std::vector< std::string > routers; + + bool + fromSection(string_view key, string_view val); + }; + + struct ServicesConfig + { + std::vector< std::pair< std::string, std::string > > services; + bool + fromSection(string_view key, string_view val); + }; + + struct SystemConfig + { + std::string pidfile; + + bool + fromSection(string_view key, string_view val); + }; + + struct MetricsConfig + { + bool disableMetrics = false; + bool disableMetricLogs = false; + fs::path jsonMetricsPath; + std::string metricTankHost; + std::map< std::string, std::string > metricTags; + + bool + fromSection(string_view key, string_view val); + }; + + struct ApiConfig + { + bool enableRPCServer = false; + std::string rpcBindAddr; + + bool + fromSection(string_view key, string_view val); + }; + + struct LokidConfig + { + bool usingSNSeed = false; + bool whitelistRouters = false; + fs::path ident_keyfile = "identity.key"; + std::string lokidRPCAddr = "127.0.0.1:22023"; + std::string lokidRPCUser; + std::string lokidRPCPassword; + + bool + fromSection(string_view key, string_view val); + }; + + struct BootstrapConfig + { + std::vector< std::string > routers; + bool + fromSection(string_view key, string_view val); + }; + + struct LoggingConfig + { + bool m_LogJSON = false; + FILE *m_LogFile = stdout; + + bool + fromSection(string_view key, string_view val); + }; + + struct Config + { + RouterConfig router; + NetworkConfig network; + ConnectConfig connect; + NetdbConfig netdb; + DnsConfig dns; + IwpConfig iwp_links; + ServicesConfig services; + SystemConfig system; + MetricsConfig metrics; + ApiConfig api; + LokidConfig lokid; + BootstrapConfig bootstrap; + LoggingConfig logging; + + bool + Load(const char *fname); + }; + +} // namespace llarp + +void +llarp_generic_ensure_config(std::ofstream &f, std::string basepath); + +void +llarp_ensure_router_config(std::ofstream &f, std::string basepath); + +bool +llarp_ensure_client_config(std::ofstream &f, std::string basepath); + +#endif diff --git a/llarp/util/ini.cpp b/llarp/config/ini.cpp similarity index 94% rename from llarp/util/ini.cpp rename to llarp/config/ini.cpp index 0f7c4bb69..70f8df1ae 100644 --- a/llarp/util/ini.cpp +++ b/llarp/config/ini.cpp @@ -1,8 +1,9 @@ -#include +#include +#include + #include #include #include -#include #ifdef LoadString #undef LoadString @@ -11,10 +12,11 @@ namespace llarp { bool - ConfigParser::LoadFile(const char* fname) + ConfigParser::LoadFile(string_view fname) { + std::string name{fname}; { - std::ifstream f(fname, std::ios::in | std::ios::binary); + std::ifstream f(name, std::ios::in | std::ios::binary); if(!f.is_open()) return false; f.seekg(0, std::ios::end); @@ -24,12 +26,12 @@ namespace llarp return false; f.read(m_Data.data(), m_Data.size()); } - m_FileName = fname; + m_FileName = name; return Parse(); } bool - ConfigParser::LoadString(const std::string& str) + ConfigParser::LoadString(string_view str) { m_Data.resize(str.size()); std::copy(str.begin(), str.end(), m_Data.begin()); diff --git a/llarp/util/ini.hpp b/llarp/config/ini.hpp similarity index 94% rename from llarp/util/ini.hpp rename to llarp/config/ini.hpp index 4bd2a627b..1610dcea6 100644 --- a/llarp/util/ini.hpp +++ b/llarp/config/ini.hpp @@ -1,9 +1,11 @@ #ifndef LOKINET_BOOTSERV_CONFIG_HPP #define LOKINET_BOOTSERV_CONFIG_HPP -#include + #include + #include #include +#include #include namespace llarp @@ -23,13 +25,13 @@ namespace llarp /// return true on success /// return false on error bool - LoadFile(const char* fname); + LoadFile(string_view fname); /// load from string /// return true on success /// return false on error bool - LoadString(const std::string& str); + LoadString(string_view str); /// iterate all sections and thier values void diff --git a/llarp/context.cpp b/llarp/context.cpp index 4200b2a8d..28c41c677 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include #include @@ -52,92 +52,49 @@ namespace llarp llarp::LogError("failed to load config file ", configfile); return false; } - config->visit(util::memFn(&Context::iter_config, this)); - if(!disableMetrics) + // System config + if(!config->system.pidfile.empty()) { - setupMetrics(); - if(!disableMetricLogs) - { - m_metricsManager->instance()->addGlobalPublisher( - std::make_shared< metrics::StreamPublisher >(std::cerr)); - } + SetPIDFile(config->system.pidfile); } - return true; - } - void - Context::iter_config(const char *section, const char *key, const char *val) - { - if(!strcmp(section, "system")) + // Router config + if(!singleThreaded && config->router.workerThreads > 0 && !worker) { - if(!strcmp(key, "pidfile")) - { - SetPIDFile(val); - } + worker.reset( + llarp_init_threadpool(config->router.workerThreads, "llarp-worker")); } - if(!strcmp(section, "metrics")) + + if(singleThreaded) { - if(!strcmp(key, "disable-metrics")) - { - disableMetrics = true; - } - else if(!strcmp(key, "disable-metrics-log")) - { - disableMetricLogs = true; - } - else if(!strcmp(key, "json-metrics-path")) - { - jsonMetricsPath = val; - } - else if(!strcmp(key, "metric-tank-host")) - { - metricTankHost = val; - } - else - { - // consume everything else as a metric tag - metricTags[key] = val; - } + num_nethreads = 0; } - if(!strcmp(section, "router")) + else { - if(!strcmp(key, "worker-threads") && !singleThreaded) - { - int workers = atoi(val); - if(workers > 0 && worker == nullptr) - { - worker.reset(llarp_init_threadpool(workers, "llarp-worker")); - } - } - else if(!strcmp(key, "net-threads")) - { - num_nethreads = atoi(val); - if(num_nethreads <= 0) - num_nethreads = 1; - if(singleThreaded) - num_nethreads = 0; - } - else if(!strcmp(key, "netid")) - { - metricTags["netid"] = val; - } - else if(!strcmp(key, "nickname")) - { - metricTags["nickname"] = val; - } + num_nethreads = config->router.num_nethreads; } - if(!strcmp(section, "netdb")) + + nodedb_dir = config->netdb.nodedb_dir; + + if(!config->metrics.disableMetrics) { - if(!strcmp(key, "dir")) + auto &metricsConfig = config->metrics; + auto &tags = metricsConfig.metricTags; + tags["netid"] = config->router.netid; + tags["nickname"] = config->router.rc.Nick(); + setupMetrics(metricsConfig); + if(!config->metrics.disableMetricLogs) { - nodedb_dir = val; + m_metricsManager->instance()->addGlobalPublisher( + std::make_shared< metrics::StreamPublisher >(std::cerr)); } } + return true; } void - Context::setupMetrics() + Context::setupMetrics(const MetricsConfig &metricsConfig) { if(!m_scheduler) { @@ -153,15 +110,15 @@ namespace llarp *m_scheduler, m_metricsManager->instance()); } - if(!jsonMetricsPath.native().empty()) + if(!metricsConfig.jsonMetricsPath.native().empty()) { m_metricsManager->instance()->addGlobalPublisher( std::make_shared< metrics::JsonPublisher >( std::bind(&metrics::JsonPublisher::directoryPublisher, - std::placeholders::_1, jsonMetricsPath))); + std::placeholders::_1, metricsConfig.jsonMetricsPath))); } - if(!metricTankHost.empty()) + if(!metricsConfig.metricTankHost.empty()) { if(std::getenv("LOKINET_ENABLE_METRIC_TANK")) { @@ -186,11 +143,11 @@ __ ___ ____ _ _ ___ _ _ ____ std::cerr << WARNING << '\n'; std::pair< std::string, std::string > split = - absl::StrSplit(metricTankHost, ':'); + absl::StrSplit(metricsConfig.metricTankHost, ':'); m_metricsManager->instance()->addGlobalPublisher( std::make_shared< metrics::MetricTankPublisher >( - metricTags, split.first, stoi(split.second))); + metricsConfig.metricTags, split.first, stoi(split.second))); } else { diff --git a/llarp/exit/context.cpp b/llarp/exit/context.cpp index 8f798aa40..f8e995c92 100644 --- a/llarp/exit/context.cpp +++ b/llarp/exit/context.cpp @@ -70,8 +70,8 @@ namespace llarp } } - llarp::exit::Endpoint* - Context::FindEndpointForPath(const llarp::PathID_t& path) const + exit::Endpoint* + Context::FindEndpointForPath(const PathID_t& path) const { auto itr = m_Exits.begin(); while(itr != m_Exits.end()) @@ -85,7 +85,7 @@ namespace llarp } bool - Context::ObtainNewExit(const llarp::PubKey& pk, const llarp::PathID_t& path, + Context::ObtainNewExit(const PubKey& pk, const PathID_t& path, bool permitInternet) { auto itr = m_Exits.begin(); @@ -106,13 +106,13 @@ namespace llarp auto itr = m_Exits.find(name); if(itr != m_Exits.end()) { - llarp::LogError("duplicate exit with name ", name); + LogError("duplicate exit with name ", name); return false; } } - std::unique_ptr< llarp::handlers::ExitEndpoint > endpoint; + std::unique_ptr< handlers::ExitEndpoint > endpoint; // make new endpoint - endpoint.reset(new llarp::handlers::ExitEndpoint(name, m_Router)); + endpoint.reset(new handlers::ExitEndpoint(name, m_Router)); // configure { auto itr = conf.begin(); @@ -120,8 +120,7 @@ namespace llarp { if(!endpoint->SetOption(itr->first, itr->second)) { - llarp::LogWarn("Couldn't set option ", itr->first, " to ", - itr->second); + LogWarn("Couldn't set option ", itr->first, " to ", itr->second); return false; } ++itr; @@ -130,7 +129,7 @@ namespace llarp // add endpoint if(!endpoint->Start()) { - llarp::LogWarn("Couldn't start exit endpoint"); + LogWarn("Couldn't start exit endpoint"); return false; } m_Exits.emplace(name, std::move(endpoint)); diff --git a/llarp/exit/context.hpp b/llarp/exit/context.hpp index b977c28f4..4dc10cb7d 100644 --- a/llarp/exit/context.hpp +++ b/llarp/exit/context.hpp @@ -35,11 +35,11 @@ namespace llarp AddExitEndpoint(const std::string &name, const Config_t &config); bool - ObtainNewExit(const llarp::PubKey &remote, const llarp::PathID_t &path, + ObtainNewExit(const PubKey &remote, const PathID_t &path, bool permitInternet); - llarp::exit::Endpoint * - FindEndpointForPath(const llarp::PathID_t &path) const; + exit::Endpoint * + FindEndpointForPath(const PathID_t &path) const; /// calculate (pk, tx, rx) for all exit traffic using TrafficStats = @@ -52,9 +52,9 @@ namespace llarp private: AbstractRouter *m_Router; std::unordered_map< std::string, - std::shared_ptr< llarp::handlers::ExitEndpoint > > + std::shared_ptr< handlers::ExitEndpoint > > m_Exits; - std::list< std::shared_ptr< llarp::handlers::ExitEndpoint > > m_Closed; + std::list< std::shared_ptr< handlers::ExitEndpoint > > m_Closed; }; } // namespace exit } // namespace llarp diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 7dc659156..ad688d940 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -607,6 +607,7 @@ namespace llarp pk, path, !wantInternet, ip, this)); m_Paths[path] = pk; + return HasLocalMappedAddrFor(pk); } diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 0f66b1cf3..739dfef3b 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -116,7 +116,7 @@ namespace llarp return false; } else if(!GetIFAddr(ifname, m_ourAddr, af)) - m_ourAddr = ifname; + m_ourAddr = Addr(ifname); m_ourAddr.port(port); return llarp_ev_add_udp(m_Loop.get(), &m_udp, m_ourAddr) != -1; } diff --git a/llarp/net/net_addr.cpp b/llarp/net/net_addr.cpp index 383c73ce8..ac33a7f33 100644 --- a/llarp/net/net_addr.cpp +++ b/llarp/net/net_addr.cpp @@ -63,14 +63,14 @@ namespace llarp return (const in_addr*)&_addr.sin6_addr.s6_addr[12]; } - Addr::Addr(const std::string str) + Addr::Addr(string_view str) { - this->from_char_array(str.c_str()); + this->from_char_array(str); } - Addr::Addr(const std::string str, const uint16_t p_port) + Addr::Addr(string_view str, const uint16_t p_port) { - this->from_char_array(str.c_str()); + this->from_char_array(str); this->port(p_port); } @@ -81,25 +81,17 @@ namespace llarp } bool - Addr::from_char_array(const char* in) + Addr::from_char_array(string_view in) { - char* str = (char*)in; - char* pPosition = strchr(str, ':'); - bool freeStr = false; - if(pPosition) + auto str = in.begin(); + auto pPosition = in.find(':'); + if(pPosition != string_view::npos) { // parse port - char buf[6]; - snprintf(buf, 6, "%s", pPosition + 1); - uint16_t port = std::atoi(buf); + uint16_t port = + std::atoi(std::string(in.begin() + pPosition + 1, in.end()).c_str()); LogDebug("Setting port ", std::to_string(port)); this->port(port); - // trim str - // can't VLA - str = strdup(in); // copy it - str[pPosition - in] = '\0'; // nul terminate it early - LogDebug("Truncating to ", str); - freeStr = true; } Zero(&_addr, sizeof(sockaddr_in6)); struct addrinfo hint, *res = NULL; @@ -110,27 +102,30 @@ namespace llarp hint.ai_family = PF_UNSPEC; hint.ai_flags = AI_NUMERICHOST; - ret = getaddrinfo(str, NULL, &hint, &res); + if(pPosition != string_view::npos) + { + ret = getaddrinfo(std::string(in.begin(), in.begin() + pPosition).c_str(), + NULL, &hint, &res); + } + else + { + ret = getaddrinfo(std::string(in).c_str(), NULL, &hint, &res); + } + if(ret) { LogError("failed to determine address family: ", str); - if(freeStr) - free(str); return false; } if(res->ai_family == AF_INET6) { LogError("IPv6 address not supported yet", str); - if(freeStr) - free(str); return false; } else if(res->ai_family != AF_INET) { LogError("Address family not supported yet", str); - if(freeStr) - free(str); return false; } @@ -139,12 +134,8 @@ namespace llarp if(inet_aton(str, addr) == 0) { LogError("failed to parse ", str); - if(freeStr) - free(str); return false; } - if(freeStr) - free(str); _addr.sin6_family = res->ai_family; _addr4.sin_family = res->ai_family; @@ -162,11 +153,6 @@ namespace llarp return true; } - Addr::Addr(const char* str) - { - this->from_char_array(str); - } - bool Addr::from_4int(const uint8_t one, const uint8_t two, const uint8_t three, const uint8_t four) diff --git a/llarp/net/net_addr.hpp b/llarp/net/net_addr.hpp index c469ae0d2..8ee0691d0 100644 --- a/llarp/net/net_addr.hpp +++ b/llarp/net/net_addr.hpp @@ -23,6 +23,12 @@ namespace llarp Addr(const Addr& other); + Addr(string_view str); + + Addr(string_view str, const uint16_t p_port); + + Addr(string_view addr_str, string_view port_str); + void port(uint16_t port); @@ -38,16 +44,8 @@ namespace llarp const in_addr* addr4() const; - Addr(const std::string str); - - Addr(const std::string str, const uint16_t p_port); - - Addr(string_view addr_str, string_view port_str); - bool - from_char_array(const char* str); - - Addr(const char* str); + from_char_array(string_view str); bool from_4int(const uint8_t one, const uint8_t two, const uint8_t three, diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 981e201b0..a4a48db55 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include #include @@ -464,7 +464,8 @@ namespace llarp bool Router::Configure(Config *conf) { - conf->visit(util::memFn(&Router::router_iter_config, this)); + fromConfig(conf); + if(!InitOutboundLinks()) return false; if(!Ready()) @@ -766,260 +767,142 @@ namespace llarp } void - Router::router_iter_config(const char *section, const char *key, - const char *val) + Router::fromConfig(Config *conf) { - llarp::LogDebug(section, " ", key, "=", val); + // IWP config + m_OutboundPort = conf->iwp_links.m_OutboundPort; - int af; - uint16_t proto = 0; - std::set< std::string > opts; - if(StrEq(val, "eth")) - { -#ifdef AF_LINK - af = AF_LINK; -#endif -#ifdef AF_PACKET - af = AF_PACKET; -#endif - proto = LLARP_ETH_PROTO; - } - else if(StrEq(section, "bind")) + for(const auto &serverConfig : conf->iwp_links.servers) { - // try IPv4 first - af = AF_INET; - std::set< std::string > parsed_opts; - std::string v = val; - std::string::size_type idx; - do + auto server = llarp::utp::NewServerFromRouter(this); + if(!server->EnsureKeys(transport_keyfile.string().c_str())) { - idx = v.find_first_of(','); - if(idx != std::string::npos) - { - parsed_opts.insert(v.substr(0, idx)); - v = v.substr(idx + 1); - } - else - parsed_opts.insert(v); - } while(idx != std::string::npos); + llarp::LogError("failed to ensure keyfile ", transport_keyfile); + return; + } - /// for each option - for(const auto &item : parsed_opts) + const auto &key = std::get< 0 >(serverConfig); + int af = std::get< 1 >(serverConfig); + uint16_t port = std::get< 2 >(serverConfig); + if(server->Configure(netloop(), key, af, port)) { - /// see if it's a number - auto port = std::atoi(item.c_str()); - if(port > 0) - { - /// set port - if(proto == 0) - proto = port; - } /// otherwise add to opts - else - opts.insert(item); + AddLink(std::move(server), true); + return; } + LogError("failed to bind inbound link on ", key, " port ", port); } - if(StrEq(section, "bind")) + // set network config + netConfig = conf->network.netConfig; + + // Network config + if(conf->network.enableProfiling.has_value()) { - if(StrEq(key, "*")) + if(conf->network.enableProfiling.value()) { - m_OutboundPort = proto; + routerProfiling().Enable(); + LogInfo("router profiling explicitly enabled"); } else { - auto server = llarp::utp::NewServerFromRouter(this); - if(!server->EnsureKeys(transport_keyfile.string().c_str())) - { - llarp::LogError("failed to ensure keyfile ", transport_keyfile); - return; - } - if(server->Configure(netloop(), key, af, proto)) - { - AddLink(std::move(server), true); - return; - } - LogError("failed to bind inbound link on ", key, " port ", proto); + routerProfiling().Disable(); + LogInfo("router profiling explicitly disabled"); } } - else if(StrEq(section, "network")) + + if(!conf->network.routerProfilesFile.empty()) { - if(StrEq(key, "profiling")) + routerProfilesFile = conf->network.routerProfilesFile; + routerProfiling().Load(routerProfilesFile.c_str()); + llarp::LogInfo("setting profiles to ", routerProfilesFile); + } + + if(!conf->network.strictConnect.empty()) + { + const auto &val = conf->network.strictConnect; + if(IsServiceNode()) { - if(IsTrueValue(val)) - { - routerProfiling().Enable(); - LogInfo("router profiling explicitly enabled"); - } - else if(IsFalseValue(val)) - { - routerProfiling().Disable(); - LogInfo("router profiling explicitly disabled"); - } + llarp::LogError("cannot use strict-connect option as service node"); + return; } - if(StrEq(key, "profiles")) + llarp::RouterID snode; + llarp::PubKey pk; + if(pk.FromString(val)) { - routerProfilesFile = val; - routerProfiling().Load(val); - llarp::LogInfo("setting profiles to ", routerProfilesFile); + if(strictConnectPubkeys.emplace(pk).second) + llarp::LogInfo("added ", pk, " to strict connect list"); + else + llarp::LogWarn("duplicate key for strict connect: ", pk); } - else if(StrEq(key, "strict-connect")) + else if(snode.FromString(val)) { - if(IsServiceNode()) - { - llarp::LogError("cannot use strict-connect option as service node"); - return; - } - llarp::RouterID snode; - llarp::PubKey pk; - if(pk.FromString(val)) + if(strictConnectPubkeys.insert(snode).second) { - if(strictConnectPubkeys.emplace(pk).second) - llarp::LogInfo("added ", pk, " to strict connect list"); - else - llarp::LogWarn("duplicate key for strict connect: ", pk); - } - else if(snode.FromString(val)) - { - if(strictConnectPubkeys.insert(snode).second) - { - llarp::LogInfo("added ", snode, " to strict connect list"); - netConfig.emplace(key, val); - } - else - llarp::LogWarn("duplicate key for strict connect: ", snode); + llarp::LogInfo("added ", snode, " to strict connect list"); + netConfig.emplace("strict-connect", val); } else - llarp::LogError("invalid key for strict-connect: ", val); + llarp::LogWarn("duplicate key for strict connect: ", snode); } else - { - netConfig.emplace(key, val); - } - } - else if(StrEq(section, "api")) - { - if(StrEq(key, "enabled")) - { - enableRPCServer = IsTrueValue(val); - } - if(StrEq(key, "bind")) - { - rpcBindAddr = val; - } - if(StrEq(key, "authkey")) - { - // TODO: add pubkey to whitelist - } + llarp::LogError("invalid key for strict-connect: ", val); } - else if(StrEq(section, "services")) + + + // API config + enableRPCServer = conf->api.enableRPCServer; + rpcBindAddr = conf->api.rpcBindAddr; + + // Services config + for(const auto &service : conf->services.services) { - if(LoadHiddenServiceConfig(val)) + if(LoadHiddenServiceConfig(service.second)) { - llarp::LogInfo("loaded hidden service config for ", key); + llarp::LogInfo("loaded hidden service config for ", service.first); } else { - llarp::LogWarn("failed to load hidden service config for ", key); - } - } - else if(StrEq(section, "logging")) - { - if(strlen(key) == 0 && strlen(val) == 0) - { - if(m_LogJSON) - { - LogContext::Instance().logStream = std::make_unique< JSONLogStream >( - diskworker(), m_LogFile, 100, m_LogFile != stdout); - } - else if(m_LogFile != stdout) - { - LogContext::Instance().logStream = std::make_unique< FileLogStream >( - diskworker(), m_LogFile, 100, true); - } - } - if(StrEq(key, "type") && StrEq(val, "syslog")) - { - // TODO(despair): write event log syslog class -#if defined(_WIN32) - LogError("syslog not supported on win32"); -#else - LogInfo("Switching to syslog"); - LogContext::Instance().logStream = std::make_unique< SysLogStream >(); -#endif - } - if(StrEq(key, "type") && StrEq(val, "json")) - { - m_LogJSON = true; - } - if(StrEq(key, "file")) - { - LogInfo("open log file: ", val); - FILE *const logfile = ::fopen(val, "a"); - if(logfile) - { - m_LogFile = logfile; - LogInfo("will log to file ", val); - } - else if(errno) - { - LogError("could not open log file at '", val, "': ", strerror(errno)); - errno = 0; - } - else - { - LogError("failed to open log file at '", val, - "' for an unknown reason, bailing tf out kbai"); - ::abort(); - } + llarp::LogWarn("failed to load hidden service config for ", + service.first); } } - else if(StrEq(section, "lokid")) + + // Logging config + + auto logfile = conf->logging.m_LogFile; + + if(conf->logging.m_LogJSON) { - if(StrEq(key, "service-node-seed")) - { - usingSNSeed = true; - ident_keyfile = val; - } - if(StrEq(key, "enabled")) - { - whitelistRouters = IsTrueValue(val); - } - if(StrEq(key, "jsonrpc") || StrEq(key, "addr")) - { - lokidRPCAddr = val; - } - if(StrEq(key, "username")) - { - lokidRPCUser = val; - } - if(StrEq(key, "password")) - { - lokidRPCPassword = val; - } + LogContext::Instance().logStream = std::make_unique< JSONLogStream >( + diskworker(), logfile, 100, logfile != stdout); } - else if(StrEq(section, "dns")) + else if(logfile != stdout) { - if(StrEq(key, "upstream")) - { - llarp::LogInfo("add upstream resolver ", val); - netConfig.emplace("upstream-dns", val); - } - if(StrEq(key, "bind")) - { - llarp::LogInfo("set local dns to ", val); - netConfig.emplace("local-dns", val); - } + LogContext::Instance().logStream = + std::make_unique< FileLogStream >(diskworker(), logfile, 100, true); } - else if(StrEq(section, "connect") - || (StrEq(section, "bootstrap") && StrEq(key, "add-node"))) + + // Lokid Config + usingSNSeed = conf->lokid.usingSNSeed; + ident_keyfile = conf->lokid.ident_keyfile; + whitelistRouters = conf->lokid.whitelistRouters; + lokidRPCAddr = conf->lokid.lokidRPCAddr; + lokidRPCUser = conf->lokid.lokidRPCUser; + lokidRPCPassword = conf->lokid.lokidRPCPassword; + + netConfig.insert(conf->dns.netConfig.begin(), conf->dns.netConfig.end()); + + std::vector< std::string > configRouters = conf->connect.routers; + configRouters.insert(configRouters.end(), conf->bootstrap.routers.begin(), + conf->bootstrap.routers.end()); + for(const auto &router : configRouters) { // llarp::LogDebug("connect section has ", key, "=", val); RouterContact rc; - if(!rc.Read(val)) + if(!rc.Read(router.c_str())) { - llarp::LogWarn("failed to decode bootstrap RC, file='", val, + llarp::LogWarn("failed to decode bootstrap RC, file='", router, "' rc=", rc); - ; return; } if(rc.Verify(Now())) @@ -1039,98 +922,25 @@ namespace llarp } else { - llarp::LogError("malformed rc file='", val, "' rc=", rc); + llarp::LogError("malformed rc file='", router, "' rc=", rc); } } } - else if(StrEq(section, "router")) + + // Router config + _rc = conf->router.rc; + maxConnectedRouters = conf->router.maxConnectedRouters; + minConnectedRouters = conf->router.minConnectedRouters; + encryption_keyfile = conf->router.encryption_keyfile; + our_rc_file = conf->router.our_rc_file; + transport_keyfile = conf->router.transport_keyfile; + addrInfo = conf->router.addrInfo; + publicOverride = conf->router.publicOverride; + ip4addr = conf->router.ip4addr; + + if(!usingSNSeed) { - if(StrEq(key, "netid")) - { - if(strlen(val) <= _rc.netID.size()) - { - llarp::LogWarn("!!!! you have manually set netid to be '", val, - "' which does not equal '", Version::LLARP_NET_ID, - "' you will run as a different network, good luck " - "and " - "don't forget: something something MUH traffic " - "shape " - "correlation !!!!"); - llarp::NetID::DefaultValue() = - llarp::NetID(reinterpret_cast< const byte_t * >(strdup(val))); - // re set netid in our rc - _rc.netID = llarp::NetID(); - } - else - llarp::LogError("invalid netid '", val, "', is too long"); - } - if(StrEq(key, "max-connections")) - { - auto ival = atoi(val); - if(ival > 0) - { - maxConnectedRouters = ival; - LogInfo("max connections set to ", maxConnectedRouters); - } - } - if(StrEq(key, "min-connections")) - { - auto ival = atoi(val); - if(ival > 0) - { - minConnectedRouters = ival; - LogInfo("min connections set to ", minConnectedRouters); - } - } - if(StrEq(key, "nickname")) - { - _rc.SetNick(val); - // set logger name here - LogContext::Instance().nodeName = rc().Nick(); - } - if(StrEq(key, "encryption-privkey")) - { - encryption_keyfile = val; - } - if(StrEq(key, "contact-file")) - { - our_rc_file = val; - } - if(StrEq(key, "transport-privkey")) - { - transport_keyfile = val; - } - if((StrEq(key, "identity-privkey") || StrEq(key, "ident-privkey")) - && !usingSNSeed) - { - ident_keyfile = val; - } - if(StrEq(key, "public-address") || StrEq(key, "public-ip")) - { - llarp::LogInfo("public ip ", val, " size ", strlen(val)); - if(strlen(val) < 17) - { - // assume IPv4 - // inet_pton(AF_INET, val, &ip4addr.sin_addr); - // struct sockaddr dest; - // sockaddr *dest = (sockaddr *)&ip4addr; - llarp::Addr a(val); - llarp::LogInfo("setting public ipv4 ", a); - addrInfo.ip = *a.addr6(); - publicOverride = true; - } - // llarp::Addr a(val); - } - if(StrEq(key, "public-port")) - { - llarp::LogInfo("Setting public port ", val); - int p = atoi(val); - // Not needed to flip upside-down - this is done in llarp::Addr(const - // AddressInfo&) - ip4addr.sin_port = p; - addrInfo.port = p; - publicOverride = true; - } + ident_keyfile = conf->router.ident_keyfile; } } @@ -1966,58 +1776,10 @@ namespace llarp return _exitContext.AddExitEndpoint("default-connectivity", netConfig); } - /// validate a new configuration against an already made and running - /// router - struct RouterConfigValidator - { - void - ValidateEntry(const char *section, const char *key, const char *val) - { - if(valid) - { - if(!OnEntry(section, key, val)) - { - LogError("invalid entry in section [", section, "]: '", key, "'='", - val, "'"); - valid = false; - } - } - } - - const Router *router; - Config *config; - bool valid; - RouterConfigValidator(const Router *r, Config *conf) - : router(r), config(conf), valid(true) - { - } - - /// checks the (section, key, value) config tuple - /// return false if that entry conflicts - /// with existing configuration in router - bool - OnEntry(const char *, const char *, const char *) const - { - // TODO: implement me - return true; - } - - /// do validation - /// return true if this config is valid - /// return false if this config is not valid - bool - Validate() - { - config->visit(util::memFn(&RouterConfigValidator::ValidateEntry, this)); - return valid; - } - }; - bool - Router::ValidateConfig(Config *conf) const + Router::ValidateConfig(ABSL_ATTRIBUTE_UNUSED Config *conf) const { - RouterConfigValidator validator(this, conf); - return validator.Validate(); + return true; } bool @@ -2095,7 +1857,7 @@ namespace llarp } bool - Router::LoadHiddenServiceConfig(const char *fname) + Router::LoadHiddenServiceConfig(string_view fname) { LogDebug("opening hidden service config ", fname); service::Config conf; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 0df026967..03306e635 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -260,16 +260,15 @@ namespace llarp ShouldCreateDefaultHiddenService(); const std::string DefaultRPCBindAddr = "127.0.0.1:1190"; - bool enableRPCServer = true; + bool enableRPCServer = false; std::unique_ptr< rpc::Server > rpcServer; std::string rpcBindAddr = DefaultRPCBindAddr; /// lokid caller - const std::string DefaultLokidRPCAddr = "127.0.0.1:22023"; std::unique_ptr< rpc::Caller > rpcCaller; - std::string lokidRPCAddr = DefaultLokidRPCAddr; - std::string lokidRPCUser = ""; - std::string lokidRPCPassword = ""; + std::string lokidRPCAddr = "127.0.0.1:22023"; + std::string lokidRPCUser; + std::string lokidRPCPassword; using LinkSet = std::set< LinkLayer_ptr, ComparePtr< LinkLayer_ptr > >; @@ -305,11 +304,6 @@ namespace llarp // set to max value right now std::unordered_map< RouterID, llarp_time_t, PubKey::Hash > lokinetRouters; - // set to true if we are configured to run with json logging - bool m_LogJSON = false; - // the file we are logging to - FILE *m_LogFile = stdout; - Router(struct llarp_threadpool *tp, llarp_ev_loop_ptr __netloop, std::shared_ptr< Logic > logic); @@ -344,7 +338,7 @@ namespace llarp Close(); bool - LoadHiddenServiceConfig(const char *fname); + LoadHiddenServiceConfig(string_view fname); bool AddHiddenService(const service::Config::section_t &config); @@ -572,7 +566,7 @@ namespace llarp } void - router_iter_config(const char *section, const char *key, const char *val); + fromConfig(Config *conf); }; } // namespace llarp diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 8321f756c..973ec7a92 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -223,7 +223,7 @@ namespace llarp } void - RouterContact::SetNick(const std::string &nick) + RouterContact::SetNick(string_view nick) { nickname.Zero(); std::copy(nick.begin(), diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 4226ab02e..fb31d6db4 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -162,7 +162,7 @@ namespace llarp IsPublicRouter() const; void - SetNick(const std::string &nick); + SetNick(string_view nick); bool Verify(llarp_time_t now, bool allowExpired = true) const; diff --git a/llarp/service/config.cpp b/llarp/service/config.cpp index 84e3a6585..a33dcfd95 100644 --- a/llarp/service/config.cpp +++ b/llarp/service/config.cpp @@ -1,16 +1,16 @@ #include -#include +#include namespace llarp { namespace service { bool - Config::Load(const std::string& fname) + Config::Load(string_view fname) { ConfigParser parser; - if(!parser.LoadFile(fname.c_str())) + if(!parser.LoadFile(fname)) return false; parser.IterAll([&](const ConfigParser::String_t& name, const ConfigParser::Section_t& section) { diff --git a/llarp/service/config.hpp b/llarp/service/config.hpp index 1f8d9cbe2..ec0401bc8 100644 --- a/llarp/service/config.hpp +++ b/llarp/service/config.hpp @@ -1,5 +1,8 @@ #ifndef LLARP_SERVICE_CONFIG_HPP #define LLARP_SERVICE_CONFIG_HPP + +#include + #include #include @@ -16,7 +19,7 @@ namespace llarp std::list< section_t > services; bool - Load(const std::string& fname); + Load(string_view fname); }; } // namespace service } // namespace llarp diff --git a/llarp/util/str.cpp b/llarp/util/str.cpp index ed911975b..6469f8003 100644 --- a/llarp/util/str.cpp +++ b/llarp/util/str.cpp @@ -3,25 +3,57 @@ #include #include #include +#include namespace llarp { bool - IsFalseValue(const char* str) + CaselessCmp::operator()(string_view lhs, string_view rhs) const { - std::string value = str; - std::transform(value.begin(), value.end(), value.begin(), - [](char ch) -> char { return std::tolower(ch); }); - return value == "no" || value == "false" || value == "0" || value == "off"; + if(lhs.size() < rhs.size()) + { + return true; + } + else if(lhs.size() > rhs.size()) + { + return false; + } + else + { + for(size_t i = 0; i < lhs.size(); ++i) + { + auto l = std::tolower(lhs[i]); + auto r = std::tolower(rhs[i]); + + if(l < r) + { + return true; + } + else if(l > r) + { + return false; + } + } + return false; + } + } + + bool + IsFalseValue(string_view str) + { + static const std::set< string_view, CaselessCmp > vals{"no", "false", "0", + "off"}; + + return vals.count(str) > 0; } bool - IsTrueValue(const char* str) + IsTrueValue(string_view str) { - std::string value = str; - std::transform(value.begin(), value.end(), value.begin(), - [](char ch) -> char { return std::tolower(ch); }); - return value == "yes" || value == "true" || value == "1" || value == "on"; + static const std::set< string_view, CaselessCmp > vals{"yes", "true", "1", + "on"}; + + return vals.count(str) > 0; } bool diff --git a/llarp/util/str.hpp b/llarp/util/str.hpp index 505de5292..7468a4d5e 100644 --- a/llarp/util/str.hpp +++ b/llarp/util/str.hpp @@ -1,16 +1,24 @@ #ifndef LLARP_STR_HPP #define LLARP_STR_HPP +#include + namespace llarp { bool StrEq(const char *s1, const char *s2); bool - IsFalseValue(const char *str); + IsFalseValue(string_view str); + + struct CaselessCmp + { + bool + operator()(string_view lhs, string_view rhs) const; + }; bool - IsTrueValue(const char *str); + IsTrueValue(string_view str); } // namespace llarp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fad7fd87d..54b5a4dea 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,7 @@ set(TEST_EXE testAll) list(APPEND TEST_SRC + config/test_llarp_config_ini.cpp crypto/test_llarp_crypto_types.cpp crypto/test_llarp_crypto.cpp dht/test_llarp_dht_bucket.cpp @@ -36,7 +37,6 @@ list(APPEND TEST_SRC util/test_llarp_util_bencode.cpp util/test_llarp_util_bits.cpp util/test_llarp_util_encode.cpp - util/test_llarp_util_ini.cpp util/test_llarp_util_metrics_core.cpp util/test_llarp_util_metrics_types.cpp util/test_llarp_util_memfn.cpp @@ -48,6 +48,7 @@ list(APPEND TEST_SRC util/test_llarp_util_timerqueue.cpp util/test_llarp_util_traits.cpp util/test_llarp_utils_scheduler.cpp + util/test_llarp_utils_str.cpp ) add_executable(${TEST_EXE} @@ -72,4 +73,4 @@ endif(NOT WIN32) if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") target_link_directories(${TEST_EXE} PRIVATE /usr/local/lib) -endif() \ No newline at end of file +endif() diff --git a/test/util/test_llarp_util_ini.cpp b/test/config/test_llarp_config_ini.cpp similarity index 98% rename from test/util/test_llarp_util_ini.cpp rename to test/config/test_llarp_config_ini.cpp index b3fa9947b..64081ff67 100644 --- a/test/util/test_llarp_util_ini.cpp +++ b/test/config/test_llarp_config_ini.cpp @@ -1,6 +1,6 @@ #include -#include +#include struct TestINIParser : public ::testing::Test { diff --git a/test/exit/test_llarp_exit_context.cpp b/test/exit/test_llarp_exit_context.cpp index db5e504da..6a0d4b699 100644 --- a/test/exit/test_llarp_exit_context.cpp +++ b/test/exit/test_llarp_exit_context.cpp @@ -1,15 +1,18 @@ #include #include +#include #include struct ExitTest : public ::testing::Test { - ExitTest() : r(nullptr, nullptr, nullptr) + ExitTest() : r(nullptr, nullptr, nullptr), context(&r) { } + llarp::Router r; + llarp::exit::Context context; }; TEST_F(ExitTest, AddMultipleIP) @@ -23,9 +26,10 @@ TEST_F(ExitTest, AddMultipleIP) conf.emplace("exit", "true"); conf.emplace("type", "null"); conf.emplace("ifaddr", "10.0.0.1/24"); - ASSERT_TRUE(r.exitContext().AddExitEndpoint("test-exit", conf)); - ASSERT_TRUE(r.exitContext().ObtainNewExit(pk, firstPath, true)); - ASSERT_TRUE(r.exitContext().ObtainNewExit(pk, secondPath, true)); - ASSERT_TRUE(r.exitContext().FindEndpointForPath(firstPath)->LocalIP() - == r.exitContext().FindEndpointForPath(secondPath)->LocalIP()); + + ASSERT_TRUE(context.AddExitEndpoint("test-exit", conf)); + ASSERT_TRUE(context.ObtainNewExit(pk, firstPath, true)); + ASSERT_TRUE(context.ObtainNewExit(pk, secondPath, true)); + ASSERT_TRUE(context.FindEndpointForPath(firstPath)->LocalIP() + == context.FindEndpointForPath(secondPath)->LocalIP()); } diff --git a/test/util/test_llarp_utils_str.cpp b/test/util/test_llarp_utils_str.cpp new file mode 100644 index 000000000..7836c3132 --- /dev/null +++ b/test/util/test_llarp_utils_str.cpp @@ -0,0 +1,68 @@ +#include + +#include +#include + +using namespace llarp; +using namespace ::testing; + +struct CmpTestData +{ + bool lt; + std::string lhs; + std::string rhs; +}; + +class CaselessCmpTest : public ::testing::TestWithParam< CmpTestData > +{ +}; + +TEST_P(CaselessCmpTest, test) +{ + CaselessCmp cmp; + auto d = GetParam(); + ASSERT_EQ(d.lt, cmp(d.lhs, d.rhs)); +} + +std::vector< CmpTestData > CMPTESTDATA{ + {true, "", "1"}, {false, "1", ""}, {true, "abc", "abcd"}, + {true, "abc", "abd"}, {false, "11", "1"}, {false, "a", "A"}, + {false, "abc", "aBc"}, {false, "ABC", "abc"}}; + +INSTANTIATE_TEST_SUITE_P(TestStr, CaselessCmpTest, ValuesIn(CMPTESTDATA)); + +using TestData = std::pair< bool, std::string >; + +class TestIsFalseValue : public ::testing::TestWithParam< TestData > +{ +}; + +TEST_P(TestIsFalseValue, test) +{ + ASSERT_EQ(GetParam().first, IsFalseValue(GetParam().second)); +} + +std::vector< TestData > FALSE_DATA{ + {true, "false"}, {true, "FaLsE"}, {true, "no"}, {true, "nO"}, + {true, "No"}, {true, "NO"}, {true, "NO"}, {true, "0"}, + {true, "off"}, {true, "oFF"}, {false, "false y"}, {false, "true"}, + {false, "tRue"}, {false, "on"}}; + +INSTANTIATE_TEST_SUITE_P(TestStr, TestIsFalseValue, ValuesIn(FALSE_DATA)); + +class TestIsTrueValue : public ::testing::TestWithParam< TestData > +{ +}; + +TEST_P(TestIsTrueValue, test) +{ + ASSERT_EQ(GetParam().first, IsTrueValue(GetParam().second)); +} + +std::vector< TestData > TRUE_DATA{ + {true, "true"}, {true, "TruE"}, {true, "yes"}, {true, "yeS"}, + {true, "yES"}, {true, "YES"}, {true, "1"}, {false, "0"}, + {true, "on"}, {true, "oN"}, {false, "false y"}, {false, "truth"}, + {false, "false"}, {false, "off"}}; + +INSTANTIATE_TEST_SUITE_P(TestStr, TestIsTrueValue, ValuesIn(TRUE_DATA));