diff --git a/.drone.jsonnet b/.drone.jsonnet index 87aaf71ff..684841501 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -16,7 +16,10 @@ local default_deps = ['g++'] + default_deps_nocxx; local default_windows_deps = ['mingw-w64', 'zip', 'nsis']; local docker_base = 'registry.oxen.rocks/lokinet-ci-'; -local submodule_commands = ['git fetch --tags', 'git submodule update --init --recursive --depth=1 --jobs=4']; +local submodule_commands = [ + 'git fetch --tags', + 'git submodule update --init --recursive --depth=1 --jobs=4', +]; local submodules = { name: 'submodules', image: 'drone/git', diff --git a/.gitmodules b/.gitmodules index 60d5d9621..005334d4b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,9 +10,6 @@ [submodule "test/Catch2"] path = test/Catch2 url = https://github.com/catchorg/Catch2 -[submodule "external/date"] - path = external/date - url = https://github.com/HowardHinnant/date.git [submodule "external/pybind11"] path = external/pybind11 url = https://github.com/pybind/pybind11 @@ -36,3 +33,6 @@ [submodule "external/oxen-encoding"] path = external/oxen-encoding url = https://github.com/oxen-io/oxen-encoding.git +[submodule "external/oxen-logging"] + path = external/oxen-logging + url = https://github.com/oxen-io/oxen-logging.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 83f6d3e41..0758f6c1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,6 @@ set(CMAKE_C_EXTENSIONS OFF) include(cmake/target_link_libraries_system.cmake) include(cmake/add_import_library.cmake) -include(cmake/add_log_tag.cmake) include(cmake/libatomic.cmake) if (STATIC_LINK) diff --git a/cmake/add_log_tag.cmake b/cmake/add_log_tag.cmake deleted file mode 100644 index b86ab5717..000000000 --- a/cmake/add_log_tag.cmake +++ /dev/null @@ -1,7 +0,0 @@ -function(add_log_tag target) - get_target_property(TARGET_SRCS ${target} SOURCES) - foreach(F ${TARGET_SRCS}) - get_filename_component(fpath "${F}" ABSOLUTE) - set_property(SOURCE ${F} APPEND PROPERTY COMPILE_DEFINITIONS SOURCE_ROOT=\"${PROJECT_SOURCE_DIR}\") - endforeach() -endfunction() diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 083d6bfb6..e4cedd9b6 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -57,7 +57,6 @@ else() endif() enable_lto(lokinet-cryptography) -add_log_tag(lokinet-cryptography) if (WARNINGS_AS_ERRORS) target_compile_options(lokinet-cryptography PUBLIC -Wall -Wextra -Werror) diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 233c436ce..5f3d91aa9 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -58,7 +58,6 @@ foreach(exe ${exetargets}) target_link_libraries(${exe} PUBLIC liblokinet) target_include_directories(${exe} PUBLIC "${PROJECT_SOURCE_DIR}") target_compile_definitions(${exe} PRIVATE -DVERSIONTAG=${GIT_VERSION_REAL}) - add_log_tag(${exe}) if(should_install) if(APPLE) install(TARGETS ${exe} BUNDLE DESTINATION "${PROJECT_BINARY_DIR}" COMPONENT lokinet) diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index ebddf84e1..dbdb6be59 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -3,8 +3,6 @@ #include #include #include -#include -#include #include #ifdef _WIN32 @@ -379,11 +377,14 @@ main(int argc, char* argv[]) int lokinet_main(int argc, char* argv[]) { - auto result = Lokinet_INIT(); - if (result) - { + if (auto result = Lokinet_INIT()) return result; - } + + // Set up a default, stderr logging for very early logging; we'll replace this later once we read + // the desired log info from config. + llarp::log::add_sink(llarp::log::Type::Print, "stderr"); + llarp::log::reset_level(llarp::log::Level::info); + llarp::RuntimeOptions opts; #ifdef _WIN32 @@ -410,7 +411,6 @@ lokinet_main(int argc, char* argv[]) ("g,generate", "generate default configuration and exit", cxxopts::value()) ("r,router", "run in routing mode instead of client only mode", cxxopts::value()) ("f,force", "force writing config even if it already exists", cxxopts::value()) - ("c,colour", "colour output", cxxopts::value()->default_value("true")) ("config", "path to lokinet.ini configuration file", cxxopts::value()) ; // clang-format on @@ -424,12 +424,6 @@ lokinet_main(int argc, char* argv[]) { auto result = options.parse(argc, argv); - if (!result["colour"].as()) - { - llarp::LogContext::Instance().logStream = - std::make_unique(false, std::cerr); - } - if (result.count("help")) { std::cout << options.help() << std::endl; @@ -554,6 +548,7 @@ lokinet_main(int argc, char* argv[]) // do periodic non lokinet related tasks here if (ctx and ctx->IsUp() and not ctx->LooksAlive()) { + auto deadlock_cat = llarp::log::Cat("deadlock"); for (const auto& wtf : {"you have been visited by the mascott of the deadlocked router.", "⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠄⠄⠄⠄", @@ -575,8 +570,8 @@ lokinet_main(int argc, char* argv[]) "file a bug report now or be cursed with this " "annoying image in your syslog for all time."}) { - llarp::LogError{wtf}; - llarp::LogContext::Instance().ImmediateFlush(); + llarp::log::critical(deadlock_cat, wtf); + llarp::log::flush(); } #ifdef _WIN32 TellWindowsServiceStopped(); @@ -604,7 +599,7 @@ lokinet_main(int argc, char* argv[]) code = 2; } - llarp::LogContext::Instance().ImmediateFlush(); + llarp::log::flush(); if (ctx) { ctx.reset(); diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index b851ff986..0ea284a78 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -12,13 +12,23 @@ if(SUBMODULE_CHECK) else() message(FATAL_ERROR "Submodule 'external/${relative_path}' is not up-to-date. Please update with\ngit submodule update --init --recursive\nor run cmake with -DSUBMODULE_CHECK=OFF") endif() + + # Extra arguments check nested submodules + foreach(submod ${ARGN}) + execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${relative_path}/${submod} OUTPUT_VARIABLE localHead) + execute_process(COMMAND git rev-parse "HEAD:${submod}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${relative_path} OUTPUT_VARIABLE checkedHead) + string(COMPARE EQUAL "${localHead}" "${checkedHead}" upToDate) + if (NOT upToDate) + message(FATAL_ERROR "Nested submodule '${relative_path}/${submod}' is not up-to-date. Please update with\ngit submodule update --init --recursive\nor run cmake with -DSUBMODULE_CHECK=OFF") + endif() + endforeach() endfunction () message(STATUS "Checking submodules") check_submodule(nlohmann) check_submodule(cxxopts) check_submodule(ghc-filesystem) - check_submodule(date) + check_submodule(oxen-logging fmt spdlog) check_submodule(pybind11) check_submodule(sqlite_orm) check_submodule(oxen-mq) @@ -56,13 +66,17 @@ system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.12 oxen-mq) set(JSON_BuildTests OFF CACHE INTERNAL "") system_or_submodule(NLOHMANN nlohmann_json nlohmann_json>=3.7.0 nlohmann) +if (STATIC OR FORCE_SPDLOG_SUBMODULE OR FORCE_FMT_SUBMODULE) + set(OXEN_LOGGING_FORCE_SUBMODULES ON CACHE INTERNAL "") +endif() +set(OXEN_LOGGING_SOURCE_ROOT "${PROJECT_SOURCE_DIR}" CACHE INTERNAL "") +add_subdirectory(oxen-logging) if(WITH_HIVE) add_subdirectory(pybind11 EXCLUDE_FROM_ALL) endif() add_subdirectory(cxxopts EXCLUDE_FROM_ALL) -add_subdirectory(date EXCLUDE_FROM_ALL) add_library(sqlite_orm INTERFACE) target_include_directories(sqlite_orm SYSTEM INTERFACE sqlite_orm/include) diff --git a/external/date b/external/date deleted file mode 160000 index cac99da8d..000000000 --- a/external/date +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cac99da8dc88be719a728dc1b597b0ac307c1800 diff --git a/external/oxen-logging b/external/oxen-logging new file mode 160000 index 000000000..0fc1b3528 --- /dev/null +++ b/external/oxen-logging @@ -0,0 +1 @@ +Subproject commit 0fc1b3528a52475c4007d734a7861faa2212fe75 diff --git a/include/lokinet/lokinet_misc.h b/include/lokinet/lokinet_misc.h index b09b20e2c..cc928a0a8 100644 --- a/include/lokinet/lokinet_misc.h +++ b/include/lokinet/lokinet_misc.h @@ -7,7 +7,7 @@ extern "C" /// change our network id globally across all contexts void EXPORT - lokinet_set_netid(const char*); + lokinet_set_netid(const char* netid); /// get our current netid /// must be free()'d after use @@ -15,17 +15,27 @@ extern "C" lokinet_get_netid(); /// set log level - /// possible values: trace, debug, info, warn, error, none + /// possible values: trace, debug, info, warn, error, critical, none /// return 0 on success /// return non zero on fail int EXPORT - lokinet_log_level(const char*); + lokinet_log_level(const char* level); - typedef void (*lokinet_logger_func)(const char*, void*); + /// Function pointer to invoke with lokinet log messages + typedef void (*lokinet_logger_func)(const char* message, void* context); - /// set a custom logger function + /// Optional function to call when flushing lokinet log messages; can be NULL if flushing is not + /// meaningful for the logging system. + typedef void (*lokinet_logger_sync)(void* context); + + /// set a custom logger function; it is safe (and often desirable) to call this before calling + /// initializing lokinet via lokinet_context_new. + void EXPORT + lokinet_set_syncing_logger(lokinet_logger_func func, lokinet_logger_sync sync, void* context); + + /// shortcut for calling `lokinet_set_syncing_logger` with a NULL sync void EXPORT - lokinet_set_logger(lokinet_logger_func func, void* user); + lokinet_set_logger(lokinet_logger_func func, void* context); /// @brief take in hex and turn it into base32z /// @return value must be free()'d later diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 8be49a236..0cd9edd9c 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -8,12 +8,6 @@ add_library(lokinet-util util/fs.cpp util/json.cpp util/logging/buffer.cpp - util/logging/file_logger.cpp - util/logging/logger.cpp - util/logging/logger_internal.cpp - util/logging/loglevel.cpp - util/logging/ostream_logger.cpp - util/logging/syslog_logger.cpp util/lokinet_init.c util/mem.cpp util/printer.cpp @@ -31,8 +25,8 @@ target_link_libraries(lokinet-util PUBLIC lokinet-cryptography nlohmann_json::nlohmann_json filesystem - date::date oxenc::oxenc + oxen::logging ) if(ANDROID) @@ -213,7 +207,6 @@ add_library(liblokinet service/name.cpp service/outbound_context.cpp service/protocol.cpp - service/protocol_type.cpp service/router_lookup_job.cpp service/sendcontext.cpp service/session.cpp @@ -236,7 +229,15 @@ if(WITH_HIVE) ) endif() -target_link_libraries(liblokinet PUBLIC cxxopts oxenc::oxenc lokinet-platform lokinet-util lokinet-cryptography sqlite_orm ngtcp2_static oxenmq::oxenmq) +target_link_libraries(liblokinet PUBLIC + cxxopts + oxenc::oxenc + lokinet-platform + lokinet-util + lokinet-cryptography + sqlite_orm + ngtcp2_static + oxenmq::oxenmq) target_link_libraries(liblokinet PRIVATE libunbound) pkg_check_modules(CRYPT libcrypt IMPORTED_TARGET) if(CRYPT_FOUND AND NOT CMAKE_CROSSCOMPILING) @@ -262,17 +263,12 @@ if(BUILD_LIBLOKINET) else() install(TARGETS lokinet-shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT liblokinet) endif() - add_log_tag(lokinet-shared) endif() if(APPLE) add_subdirectory(apple) endif() -foreach(lokinet_lib liblokinet lokinet-platform lokinet-util lokinet-cryptography) - add_log_tag(${lokinet_lib}) -endforeach() - file(GLOB_RECURSE docs_SRC */*.hpp *.hpp) set(DOCS_SRC ${docs_SRC} PARENT_SCOPE) diff --git a/llarp/apple/apple_logger.cpp b/llarp/apple/apple_logger.cpp deleted file mode 100644 index 6dca15fa3..000000000 --- a/llarp/apple/apple_logger.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "apple_logger.hpp" - -namespace llarp::apple -{ - void - NSLogStream::PreLog( - std::stringstream& ss, - LogLevel lvl, - std::string_view fname, - int lineno, - const std::string& nodename) const - { - ss << "[" << LogLevelToString(lvl) << "] "; - ss << "[" << nodename << "]" - << "(" << thread_id_string() << ") " << log_timestamp() << " " << fname << ":" << lineno - << "\t"; - } - - void - NSLogStream::Print(LogLevel, std::string_view, const std::string& msg) - { - ns_logger(msg.c_str()); - } - -} // namespace llarp::apple diff --git a/llarp/apple/apple_logger.hpp b/llarp/apple/apple_logger.hpp deleted file mode 100644 index 954d5b402..000000000 --- a/llarp/apple/apple_logger.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include - -namespace llarp::apple -{ - struct NSLogStream : public ILogStream - { - using ns_logger_callback = void (*)(const char* log_this); - - NSLogStream(ns_logger_callback logger) : ns_logger{logger} - {} - - void - PreLog( - std::stringstream& s, - LogLevel lvl, - std::string_view fname, - int lineno, - const std::string& nodename) const override; - - void - Print(LogLevel lvl, std::string_view tag, const std::string& msg) override; - - void - PostLog(std::stringstream&) const override - {} - - void - ImmediateFlush() override - {} - - void Tick(llarp_time_t) override - {} - - private: - ns_logger_callback ns_logger; - }; -} // namespace llarp::apple diff --git a/llarp/apple/context_wrapper.cpp b/llarp/apple/context_wrapper.cpp index fd662967c..31768f3f3 100644 --- a/llarp/apple/context_wrapper.cpp +++ b/llarp/apple/context_wrapper.cpp @@ -6,10 +6,11 @@ #include #include #include +#include +#include #include "vpn_interface.hpp" #include "context_wrapper.h" #include "context.hpp" -#include "apple_logger.hpp" namespace { @@ -34,8 +35,10 @@ const uint16_t dns_trampoline_port = 1053; void* llarp_apple_init(llarp_apple_config* appleconf) { - llarp::LogContext::Instance().logStream = - std::make_unique(appleconf->ns_logger); + llarp::log::ReplaceLogger(std::make_shared( + [](const char* msg, void* nslog) { reinterpret_cast(nslog)(msg); }, + nullptr, + appleconf->ns_logger)); try { @@ -43,7 +46,7 @@ llarp_apple_init(llarp_apple_config* appleconf) auto config = std::make_shared(config_dir); fs::path config_path = config_dir / "lokinet.ini"; if (!fs::exists(config_path)) - llarp::ensureConfig(config_dir, config_path, /*overwrite=*/false, /*router=*/false); + llarp::ensureConfig(config_dir, config_path, /*overwrite=*/false, /*asRouter=*/false); config->Load(config_path); // If no range is specified then go look for a free one, set that in the config, and then return diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index 32f273de4..56731257f 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -1,6 +1,6 @@ #include "bootstrap.hpp" #include "util/bencode.hpp" -#include "util/logging/logger.hpp" +#include "util/logging.hpp" #include "util/logging/buffer.hpp" namespace llarp diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index dde090362..3ea4d970b 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -4,12 +4,15 @@ #include "config/definition.hpp" #include "ini.hpp" #include +#include +#include #include #include #include #include #include -#include +#include +#include #include #include @@ -19,7 +22,6 @@ #include #include #include -#include namespace llarp { @@ -58,8 +60,8 @@ namespace llarp }, [this](std::string arg) { if (arg.size() > NetID::size()) - throw std::invalid_argument( - stringify("netid is too long, max length is ", NetID::size())); + throw std::invalid_argument{ + fmt::format("netid is too long, max length is {}", NetID::size())}; m_netId = std::move(arg); }); @@ -75,7 +77,8 @@ namespace llarp }, [=](int arg) { if (arg < minConnections) - throw std::invalid_argument(stringify("min-connections must be >= ", minConnections)); + throw std::invalid_argument{ + fmt::format("min-connections must be >= {}", minConnections)}; m_minConnectedRouters = arg; }); @@ -91,7 +94,8 @@ namespace llarp }, [=](int arg) { if (arg < maxConnections) - throw std::invalid_argument(stringify("max-connections must be >= ", maxConnections)); + throw std::invalid_argument{ + fmt::format("max-connections must be >= {}", maxConnections)}; m_maxConnectedRouters = arg; }); @@ -110,8 +114,8 @@ namespace llarp if (arg.empty()) throw std::invalid_argument("[router]:data-dir is empty"); if (not fs::exists(arg)) - throw std::runtime_error( - stringify("Specified [router]:data-dir ", arg, " does not exist")); + throw std::runtime_error{ + fmt::format("Specified [router]:data-dir {} does not exist", arg)}; m_dataDir = std::move(arg); }); @@ -130,11 +134,11 @@ namespace llarp return; nuint32_t addr{}; if (not addr.FromString(arg)) - throw std::invalid_argument{stringify(arg, " is not a valid IPv4 address")}; + throw std::invalid_argument{fmt::format("{} is not a valid IPv4 address", arg)}; if (IsIPv4Bogon(addr)) throw std::invalid_argument{ - stringify(addr, " looks like it is not a publicly routable ip address")}; + fmt::format("{} is not a publicly routable ip address", addr)}; m_PublicIP = addr; }); @@ -352,7 +356,7 @@ namespace llarp [this](std::string arg) { service::Address addr; if (not addr.FromString(arg)) - throw std::invalid_argument(stringify("bad loki address: ", arg)); + throw std::invalid_argument{fmt::format("bad loki address: {}", arg)}; m_AuthWhitelist.emplace(std::move(addr)); }); @@ -368,7 +372,7 @@ namespace llarp [this](fs::path arg) { if (not fs::exists(arg)) throw std::invalid_argument{ - stringify("cannot load auth file ", arg, " as it does not seem to exist")}; + fmt::format("cannot load auth file {}: file does not exist", arg)}; m_AuthFiles.emplace(std::move(arg)); }); conf.defineOption( @@ -514,7 +518,7 @@ namespace llarp if (arg != "null" and not exit.FromString(arg)) { - throw std::invalid_argument(stringify("[network]:exit-node bad address: ", arg)); + throw std::invalid_argument{fmt::format("[network]:exit-node bad address: {}", arg)}; } m_ExitMap.Insert(range, exit); }); @@ -603,7 +607,7 @@ namespace llarp [this](std::string arg) { if (not m_ifaddr.FromString(arg)) { - throw std::invalid_argument(stringify("[network]:ifaddr invalid value: '", arg, "'")); + throw std::invalid_argument{fmt::format("[network]:ifaddr invalid value: '{}'", arg)}; } }); @@ -630,8 +634,8 @@ namespace llarp } m_baseV6Address = huint128_t{}; if (not m_baseV6Address->FromString(arg)) - throw std::invalid_argument( - stringify("[network]:ip6-range invalid value: '", arg, "'")); + throw std::invalid_argument{ + fmt::format("[network]:ip6-range invalid value: '{}'", arg)}; }); // TODO: could be useful for snodes in the future, but currently only implemented for clients: conf.defineOption( @@ -653,7 +657,7 @@ namespace llarp const auto pos = arg.find(":"); if (pos == std::string::npos) { - throw std::invalid_argument(stringify("[endpoint]:mapaddr invalid entry: ", arg)); + throw std::invalid_argument{fmt::format("[endpoint]:mapaddr invalid entry: {}", arg)}; } std::string addrstr = arg.substr(0, pos); std::string ipstr = arg.substr(pos + 1); @@ -662,18 +666,19 @@ namespace llarp huint32_t ipv4; if (not ipv4.FromString(ipstr)) { - throw std::invalid_argument(stringify("[endpoint]:mapaddr invalid ip: ", ipstr)); + throw std::invalid_argument{fmt::format("[endpoint]:mapaddr invalid ip: {}", ipstr)}; } ip = net::ExpandV4(ipv4); } if (not addr.FromString(addrstr)) { - throw std::invalid_argument( - stringify("[endpoint]:mapaddr invalid addresss: ", addrstr)); + throw std::invalid_argument{ + fmt::format("[endpoint]:mapaddr invalid addresss: {}", addrstr)}; } if (m_mapAddrs.find(ip) != m_mapAddrs.end()) { - throw std::invalid_argument(stringify("[endpoint]:mapaddr ip already mapped: ", ipstr)); + throw std::invalid_argument{ + fmt::format("[endpoint]:mapaddr ip already mapped: {}", ipstr)}; } m_mapAddrs[ip] = addr; }); @@ -690,11 +695,11 @@ namespace llarp [this](std::string arg) { RouterID id; if (not id.FromString(arg)) - throw std::invalid_argument(stringify("Invalid RouterID: ", arg)); + throw std::invalid_argument{fmt::format("Invalid RouterID: {}", arg)}; auto itr = m_snodeBlacklist.emplace(std::move(id)); if (not itr.second) - throw std::invalid_argument(stringify("Duplicate blacklist-snode: ", arg)); + throw std::invalid_argument{fmt::format("Duplicate blacklist-snode: {}", arg)}; }); // TODO: support SRV records for routers, but for now client only @@ -711,7 +716,7 @@ namespace llarp [this](std::string arg) { llarp::dns::SRVData newSRV; if (not newSRV.fromString(arg)) - throw std::invalid_argument(stringify("Invalid SRV Record string: ", arg)); + throw std::invalid_argument{fmt::format("Invalid SRV Record string: {}", arg)}; m_SRVRecords.push_back(std::move(newSRV)); }); @@ -817,7 +822,7 @@ namespace llarp return; if (not fs::exists(path)) throw std::invalid_argument{ - stringify("cannot add hosts file ", path, " as it does not seem to exist")}; + fmt::format("cannot add hosts file {} as it does not exist", path)}; m_hostfiles.emplace_back(std::move(path)); }); @@ -897,7 +902,7 @@ namespace llarp "if the 0.0.0.0 all-address IP is given then you must also specify the", "public-ip= and public-port= settings in the [router] section with a public", "address at which this router can be reached.", - "" + "", "Typically this section can be left blank: if no inbound bind addresses are", "configured then lokinet will search for a local network interface with a public", "IP address and use that (with port 1090).", @@ -932,8 +937,8 @@ namespace llarp LinkInfo info = LinkInfoFromINIValues(name, value); if (info.port <= 0) - throw std::invalid_argument( - stringify("Invalid [bind] port specified on interface", name)); + throw std::invalid_argument{ + fmt::format("Invalid [bind] port specified on interface {}", name)}; assert(name != "*"); // handled by defineOption("bind", "*", ...) above @@ -950,14 +955,11 @@ namespace llarp "connect", [this](std::string_view section, std::string_view name, std::string_view value) { fs::path file{value.begin(), value.end()}; if (not fs::exists(file)) - throw std::runtime_error(stringify( - "Specified bootstrap file ", + throw std::runtime_error{fmt::format( + "Specified bootstrap file {} specified in [{}]:{} does not exist", value, - "specified in [", section, - "]:", - name, - " does not exist")); + name)}; routers.emplace_back(std::move(file)); return true; @@ -1088,7 +1090,8 @@ namespace llarp { (void)params; - constexpr Default DefaultLogType{"file"}; + constexpr Default DefaultLogType{ + platform::is_android or platform::is_apple ? "system" : "print"}; constexpr Default DefaultLogFile{""}; constexpr Default DefaultLogLevel{"warn"}; @@ -1097,16 +1100,17 @@ namespace llarp "type", DefaultLogType, [this](std::string arg) { - LogType type = LogTypeFromString(arg); - if (type == LogType::Unknown) - throw std::invalid_argument(stringify("invalid log type: ", arg)); + auto type = log::type_from_string(arg); + if (type == log::Type::Unknown) + throw std::invalid_argument{fmt::format("invalid log type: {}", arg)}; m_logType = type; }, Comment{ "Log type (format). Valid options are:", - " file - plaintext formatting", - " syslog - logs directed to syslog", + " print - print logs to standard output", + " system - logs directed to the system logger (syslog/eventlog/etc.)", + " file - plaintext formatting to a file", }); conf.defineOption( @@ -1114,9 +1118,9 @@ namespace llarp "level", DefaultLogLevel, [this](std::string arg) { - std::optional level = LogLevelFromString(arg); + std::optional level = log::level_from_string(arg); if (not level) - throw std::invalid_argument(stringify("invalid log level value: ", arg)); + throw std::invalid_argument{fmt::format("invalid log level value: {}", arg)}; m_logLevel = *level; }, @@ -1128,6 +1132,8 @@ namespace llarp " info", " warn", " error", + " critical", + " none", }); conf.defineOption( @@ -1136,9 +1142,7 @@ namespace llarp DefaultLogFile, AssignmentAcceptor(m_logFile), Comment{ - "When using type=file this is the output filename. If given the value 'stdout' or", - "left empty then logging is printed as standard output rather than written to a", - "file.", + "When using type=file this is the output filename.", }); } @@ -1390,7 +1394,7 @@ namespace llarp // open a filestream auto stream = llarp::util::OpenFileStream(confFile.c_str(), std::ios::binary); if (not stream or not stream->is_open()) - throw std::runtime_error(stringify("Failed to open file ", confFile, " for writing")); + throw std::runtime_error{fmt::format("Failed to open file {} for writing", confFile)}; *stream << confStr; stream->flush(); @@ -1495,7 +1499,7 @@ namespace llarp { auto config = std::make_shared(fs::path{}); config->Load(); - config->logging.m_logLevel = eLogNone; + config->logging.m_logLevel = log::Level::off; config->api.m_enableRPCServer = false; config->network.m_endpointType = "null"; config->network.m_saveProfiles = false; diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 975a8ac99..8d96ab71b 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "ini.hpp" #include "definition.hpp" #include @@ -209,8 +210,8 @@ namespace llarp struct LoggingConfig { - LogType m_logType = LogType::Unknown; - LogLevel m_logLevel = eLogNone; + log::Type m_logType = log::Type::Unknown; + log::Level m_logLevel = log::Level::off; std::string m_logFile; void diff --git a/llarp/config/definition.cpp b/llarp/config/definition.cpp index 217cd77d3..9156acaee 100644 --- a/llarp/config/definition.cpp +++ b/llarp/config/definition.cpp @@ -1,5 +1,5 @@ #include "definition.hpp" -#include +#include #include #include @@ -17,7 +17,7 @@ namespace llarp else if (input == "true" || input == "on" || input == "1" || input == "yes") return true; else - throw std::invalid_argument(stringify(input, " is not a valid bool")); + throw std::invalid_argument{fmt::format("{} is not a valid bool", input)}; } ConfigDefinition& @@ -53,8 +53,8 @@ namespace llarp auto [it, added] = m_definitions[section].try_emplace(std::string{def->name}, std::move(def)); if (!added) - throw std::invalid_argument( - stringify("definition for [", def->section, "]:", def->name, " already exists")); + throw std::invalid_argument{ + fmt::format("definition for [{}]:{} already exists", def->section, def->name)}; m_definitionOrdering[section].push_back(it->first); @@ -79,13 +79,10 @@ namespace llarp { // fallback to undeclared handler if available if (not haveUndeclaredHandler) - throw std::invalid_argument(stringify("unrecognized section [", section, "]")); - else - { - auto& handler = undItr->second; - handler(section, name, value); - return *this; - } + throw std::invalid_argument{fmt::format("unrecognized section [{}]", section)}; + auto& handler = undItr->second; + handler(section, name, value); + return *this; } // section was valid, get definition by name @@ -95,13 +92,10 @@ namespace llarp if (defItr == sectionDefinitions.end()) { if (not haveUndeclaredHandler) - throw std::invalid_argument(stringify("unrecognized option [", section, "]:", name)); - else - { - auto& handler = undItr->second; - handler(section, name, value); - return *this; - } + throw std::invalid_argument{fmt::format("unrecognized option [{}]:{}", section, name)}; + auto& handler = undItr->second; + handler(section, name, value); + return *this; } OptionDefinition_ptr& definition = defItr->second; @@ -115,7 +109,7 @@ namespace llarp { auto itr = m_undeclaredHandlers.find(section); if (itr != m_undeclaredHandlers.end()) - throw std::logic_error(stringify("section ", section, " already has a handler")); + throw std::logic_error{fmt::format("section {} already has a handler", section)}; m_undeclaredHandlers[section] = std::move(handler); } @@ -135,8 +129,8 @@ namespace llarp visitDefinitions(section, [&](const std::string&, const OptionDefinition_ptr& def) { if (def->required and def->getNumberFound() < 1) { - throw std::invalid_argument( - stringify("[", section, "]:", def->name, " is required but missing")); + throw std::invalid_argument{ + fmt::format("[{}]:{} is required but missing", section, def->name)}; } // should be handled earlier in OptionDefinition::parseValue() @@ -241,12 +235,13 @@ namespace llarp { const auto sectionItr = m_definitions.find(std::string(section)); if (sectionItr == m_definitions.end()) - throw std::invalid_argument(stringify("No config section [", section, "]")); + throw std::invalid_argument{fmt::format("No config section [{}]", section)}; auto& sectionDefinitions = sectionItr->second; const auto definitionItr = sectionDefinitions.find(std::string(name)); if (definitionItr == sectionDefinitions.end()) - throw std::invalid_argument(stringify("No config item ", name, " within section ", section)); + throw std::invalid_argument{ + fmt::format("No config item {} within section {}", name, section)}; return definitionItr->second; } diff --git a/llarp/config/definition.hpp b/llarp/config/definition.hpp index 0e3d638b2..07e448c01 100644 --- a/llarp/config/definition.hpp +++ b/llarp/config/definition.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -259,8 +260,8 @@ namespace llarp getValueAt(size_t index) const { if (index >= parsedValues.size()) - throw std::range_error( - stringify("no value at index ", index, ", size: ", parsedValues.size())); + throw std::range_error{ + fmt::format("no value at index {}, size: {}", index, parsedValues.size())}; return parsedValues[index]; } @@ -293,8 +294,8 @@ namespace llarp { if (not multiValued and parsedValues.size() > 0) { - throw std::invalid_argument( - stringify("duplicate value for ", name, ", previous value: ", parsedValues[0])); + throw std::invalid_argument{ + fmt::format("duplicate value for {}, previous value: {}", name, parsedValues[0])}; } parsedValues.emplace_back(fromString(input)); @@ -313,7 +314,7 @@ namespace llarp T t; iss >> t; if (iss.fail()) - throw std::invalid_argument(stringify(input, " is not a valid ", typeid(T).name())); + throw std::invalid_argument{fmt::format("{} is not a valid {}", input, typeid(T).name())}; else return t; } @@ -341,12 +342,10 @@ namespace llarp { if (required and parsedValues.size() == 0) { - throw std::runtime_error(stringify( - "cannot call tryAccept() on [", + throw std::runtime_error{fmt::format( + "cannot call tryAccept() on [{}]:{} when required but no value available", section, - "]:", - name, - " when required but no value available")); + name)}; } // don't use default value if we are multi-valued and have no value @@ -472,8 +471,8 @@ namespace llarp auto derived = dynamic_cast*>(definition.get()); if (not derived) - throw std::invalid_argument( - stringify("", typeid(T).name(), " is the incorrect type for [", section, "]:", name)); + throw std::invalid_argument{ + fmt::format("{} is the incorrect type for [{}]:{}", typeid(T).name(), section, name)}; return derived->getValue(); } diff --git a/llarp/config/ini.cpp b/llarp/config/ini.cpp index beb4c6c96..dbacc412b 100644 --- a/llarp/config/ini.cpp +++ b/llarp/config/ini.cpp @@ -1,6 +1,7 @@ #include "ini.hpp" -#include +#include +#include #include #include diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index 4e17c0ef4..8268d089f 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -1,7 +1,7 @@ #include "key_manager.hpp" #include -#include +#include #include "config.hpp" #include #include diff --git a/llarp/consensus/reachability_testing.cpp b/llarp/consensus/reachability_testing.cpp index dd3b2a5ef..f238907d0 100644 --- a/llarp/consensus/reachability_testing.cpp +++ b/llarp/consensus/reachability_testing.cpp @@ -2,7 +2,7 @@ #include "reachability_testing.hpp" #include #include -#include +#include #include using std::chrono::steady_clock; diff --git a/llarp/context.cpp b/llarp/context.cpp index ecba8ee09..6bc5a3c3e 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -10,7 +10,7 @@ #include "nodedb.hpp" #include "router/router.hpp" #include "service/context.hpp" -#include "util/logging/logger.hpp" +#include "util/logging.hpp" #include #include diff --git a/llarp/crypto/encrypted_frame.cpp b/llarp/crypto/encrypted_frame.cpp index 79d89bbda..210f0e1dc 100644 --- a/llarp/crypto/encrypted_frame.cpp +++ b/llarp/crypto/encrypted_frame.cpp @@ -1,7 +1,7 @@ #include "encrypted_frame.hpp" #include "crypto.hpp" -#include +#include #include namespace llarp diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 225be8278..bc4b6e2a2 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -35,7 +35,7 @@ namespace llarp operator RouterID() const { - return RouterID(as_array()); + return {as_array()}; } PubKey& @@ -46,12 +46,6 @@ namespace llarp } }; - inline std::ostream& - operator<<(std::ostream& out, const PubKey& k) - { - return out << k.ToString(); - } - inline bool operator==(const PubKey& lhs, const PubKey& rhs) { @@ -97,12 +91,10 @@ namespace llarp bool Recalculate(); - std::ostream& - print(std::ostream& stream, int level, int spaces) const + std::string_view + ToString() const { - Printer printer(stream, level, spaces); - printer.printValue("secretkey"); - return stream; + return "[secretkey]"; } PubKey @@ -123,14 +115,6 @@ namespace llarp SaveToFile(const fs::path& fname) const; }; - inline std::ostream& - operator<<(std::ostream& out, const SecretKey&) - { - // return out << k.ToHex(); - // make sure we never print out secret keys - return out << "[secretkey]"; - } - /// PrivateKey is similar to SecretKey except that it only stores the private /// key value and a hash, unlike SecretKey which stores the seed from which /// the private key and hash value are generated. This is primarily intended @@ -162,12 +146,10 @@ namespace llarp return data() + 32; } - std::ostream& - print(std::ostream& stream, int level, int spaces) const + std::string_view + ToString() const { - Printer printer(stream, level, spaces); - printer.printValue("privatekey"); - return stream; + return "[privatekey]"; } /// Computes the public key @@ -175,14 +157,6 @@ namespace llarp toPublic(PubKey& pubkey) const; }; - inline std::ostream& - operator<<(std::ostream& out, const PrivateKey&) - { - // return out << k.ToHex(); - // make sure we never print out private keys - return out << "[privatekey]"; - } - /// IdentitySecret is a secret key from a service node secret seed struct IdentitySecret final : public AlignedBuffer<32> { @@ -197,14 +171,22 @@ namespace llarp /// load service node seed from file bool LoadFromFile(const fs::path& fname); + + std::string_view + ToString() const + { + return "[IdentitySecret]"; + } }; - inline std::ostream& - operator<<(std::ostream& out, const IdentitySecret&) - { - // make sure we never print out secret keys - return out << "[IdentitySecret]"; - } + template <> + constexpr inline bool IsToStringFormattable = true; + template <> + constexpr inline bool IsToStringFormattable = true; + template <> + constexpr inline bool IsToStringFormattable = true; + template <> + constexpr inline bool IsToStringFormattable = true; using ShortHash = AlignedBuffer; using LongHash = AlignedBuffer; diff --git a/llarp/dht/key.hpp b/llarp/dht/key.hpp index 242c783df..a9c815717 100644 --- a/llarp/dht/key.hpp +++ b/llarp/dht/key.hpp @@ -2,6 +2,7 @@ #include #include +#include #include diff --git a/llarp/dht/localrouterlookup.cpp b/llarp/dht/localrouterlookup.cpp index e45c9cf64..a70edd923 100644 --- a/llarp/dht/localrouterlookup.cpp +++ b/llarp/dht/localrouterlookup.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include namespace llarp { diff --git a/llarp/dht/localserviceaddresslookup.cpp b/llarp/dht/localserviceaddresslookup.cpp index fda3260db..177294cf4 100644 --- a/llarp/dht/localserviceaddresslookup.cpp +++ b/llarp/dht/localserviceaddresslookup.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace llarp { diff --git a/llarp/dht/tx.hpp b/llarp/dht/tx.hpp index f50fe3d8e..43ac5c077 100644 --- a/llarp/dht/tx.hpp +++ b/llarp/dht/tx.hpp @@ -3,7 +3,7 @@ #include "key.hpp" #include "txowner.hpp" -#include +#include #include #include diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index 65b30c78d..a6957116f 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -4,7 +4,7 @@ #include "dns.hpp" #include "srv_data.hpp" #include -#include +#include #include #include diff --git a/llarp/dns/message.hpp b/llarp/dns/message.hpp index 937c37d97..9ba58ed1e 100644 --- a/llarp/dns/message.hpp +++ b/llarp/dns/message.hpp @@ -96,6 +96,14 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + std::string + ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + MsgID_t hdr_id; Fields_t hdr_fields; std::vector questions; @@ -103,12 +111,8 @@ namespace llarp std::vector authorities; std::vector additional; }; - - inline std::ostream& - operator<<(std::ostream& out, const Message& msg) - { - msg.print(out, -1, -1); - return out; - } } // namespace dns + + template <> + constexpr inline bool IsToStringFormattable = true; } // namespace llarp diff --git a/llarp/dns/question.cpp b/llarp/dns/question.cpp index a8c60c260..aef0d1e01 100644 --- a/llarp/dns/question.cpp +++ b/llarp/dns/question.cpp @@ -1,6 +1,6 @@ #include "question.hpp" -#include +#include #include #include #include "dns.hpp" @@ -117,10 +117,18 @@ namespace llarp && qname.rfind(tld) == (qname.size() - tld.size()) - 1; } + std::string + Question::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } std::ostream& Question::print(std::ostream& stream, int level, int spaces) const { - Printer printer(stream, level, spaces); + std::ostringstream o; + Printer printer(o, level, spaces); printer.printAttribute("qname", qname); printer.printAttributeAsHex("qtype", qtype); printer.printAttributeAsHex("qclass", qclass); diff --git a/llarp/dns/question.hpp b/llarp/dns/question.hpp index 5434bbcdd..38eef2963 100644 --- a/llarp/dns/question.hpp +++ b/llarp/dns/question.hpp @@ -25,6 +25,8 @@ namespace llarp bool Decode(llarp_buffer_t* buf) override; + std::string + ToString() const; std::ostream& print(std::ostream& stream, int level, int spaces) const; @@ -65,12 +67,8 @@ namespace llarp util::StatusObject ToJSON() const override; }; - - inline std::ostream& - operator<<(std::ostream& out, const Question& q) - { - q.print(out, -1, -1); - return out; - } } // namespace dns } // namespace llarp + +template <> +constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/dns/rr.cpp b/llarp/dns/rr.cpp index 82ed20470..7bb8c417b 100644 --- a/llarp/dns/rr.cpp +++ b/llarp/dns/rr.cpp @@ -1,7 +1,7 @@ #include "rr.hpp" #include "dns.hpp" #include -#include +#include #include namespace llarp @@ -109,6 +109,14 @@ namespace llarp return stream; } + std::string + ResourceRecord::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + bool ResourceRecord::HasCNameForTLD(const std::string& tld) const { diff --git a/llarp/dns/rr.hpp b/llarp/dns/rr.hpp index e9fa72c27..9f3e5d9f1 100644 --- a/llarp/dns/rr.hpp +++ b/llarp/dns/rr.hpp @@ -35,6 +35,8 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + std::string + ToString() const; bool HasCNameForTLD(const std::string& tld) const; @@ -45,11 +47,8 @@ namespace llarp RR_TTL_t ttl; RR_RData_t rData; }; - - inline std::ostream& - operator<<(std::ostream& out, const ResourceRecord& rr) - { - return rr.print(out, -1, -1); - } } // namespace dns } // namespace llarp + +template <> +constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/dns/srv_data.cpp b/llarp/dns/srv_data.cpp index e46b90732..9528d7e39 100644 --- a/llarp/dns/srv_data.cpp +++ b/llarp/dns/srv_data.cpp @@ -1,6 +1,6 @@ #include "srv_data.hpp" #include -#include +#include #include diff --git a/llarp/dns/unbound_resolver.cpp b/llarp/dns/unbound_resolver.cpp index 82022cce0..a65728285 100644 --- a/llarp/dns/unbound_resolver.cpp +++ b/llarp/dns/unbound_resolver.cpp @@ -186,7 +186,8 @@ namespace llarp::dns const auto str = file.u8string(); if (auto ret = ub_ctx_hosts(unboundContext, str.c_str())) { - throw std::runtime_error{stringify("Failed to add host file ", file, ": ", ub_strerror(ret))}; + throw std::runtime_error{ + fmt::format("Failed to add host file {}: {}", file, ub_strerror(ret))}; } else { diff --git a/llarp/ev/ev_libuv.cpp b/llarp/ev/ev_libuv.cpp index c7356f432..1fd2476ca 100644 --- a/llarp/ev/ev_libuv.cpp +++ b/llarp/ev/ev_libuv.cpp @@ -111,9 +111,6 @@ namespace llarp::uv { llarp::LogTrace("ticking event loop."); FlushLogic(); - auto& log = llarp::LogContext::Instance(); - if (log.logStream) - log.logStream->Tick(time_now()); } Loop::Loop(size_t queue_size) : llarp::EventLoop{}, m_LogicCalls{queue_size} diff --git a/llarp/exit/context.cpp b/llarp/exit/context.cpp index ab360ec15..e229262ba 100644 --- a/llarp/exit/context.cpp +++ b/llarp/exit/context.cpp @@ -111,14 +111,14 @@ namespace llarp const std::string& name, const NetworkConfig& networkConfig, const DnsConfig& dnsConfig) { if (m_Exits.find(name) != m_Exits.end()) - throw std::invalid_argument(stringify("An exit with name ", name, " already exists")); + throw std::invalid_argument{fmt::format("An exit with name {} already exists", name)}; auto endpoint = std::make_unique(name, m_Router); endpoint->Configure(networkConfig, dnsConfig); // add endpoint if (!endpoint->Start()) - throw std::runtime_error(stringify("Failed to start endpoint ", name)); + throw std::runtime_error{fmt::format("Failed to start endpoint {}", name)}; m_Exits.emplace(name, std::move(endpoint)); } diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 3b13e1d16..66dcee92b 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "tun.hpp" #include @@ -117,9 +118,9 @@ namespace llarp obj["ifname"] = m_IfName; std::vector resolvers; for (const auto& addr : m_UpstreamResolvers) - resolvers.emplace_back(addr.toString()); + resolvers.emplace_back(addr.ToString()); obj["ustreamResolvers"] = resolvers; - obj["localResolver"] = m_LocalResolverAddr.toString(); + obj["localResolver"] = m_LocalResolverAddr.ToString(); util::StatusObject ips{}; for (const auto& item : m_IPActivity) { @@ -528,10 +529,10 @@ namespace llarp } else { - std::stringstream ss; + std::string recs; for (const auto& rc : found) - rc.ToTXTRecord(ss); - msg.AddTXTReply(ss.str()); + recs += rc.ToTXTRecord(); + msg.AddTXTReply(std::move(recs)); } reply(msg); }); @@ -544,11 +545,11 @@ namespace llarp { if (HasExit()) { - std::stringstream ss; - m_ExitMap.ForEachEntry([&ss](const auto& range, const auto& exit) { - ss << range.ToString() << "=" << exit.ToString() << "; "; + std::string s; + m_ExitMap.ForEachEntry([&s](const auto& range, const auto& exit) { + fmt::format_to(std::back_inserter(s), "{}={}; ", range, exit); }); - msg.AddTXTReply(ss.str()); + msg.AddTXTReply(std::move(s)); } else { @@ -557,9 +558,7 @@ namespace llarp } else if (subdomain == "netid") { - std::stringstream ss; - ss << "netid=" << m_router->rc().netID.ToString() << ";"; - msg.AddTXTReply(ss.str()); + msg.AddTXTReply(fmt::format("netid={};", m_router->rc().netID)); } else { @@ -965,7 +964,7 @@ namespace llarp env.emplace("IF_NAME", m_IfName); std::string strictConnect; for (const auto& addr : m_StrictConnectAddrs) - strictConnect += addr.toString() + " "; + strictConnect += addr.ToString() + " "; env.emplace("STRICT_CONNECT_ADDRS", strictConnect); return env; } diff --git a/llarp/iwp/session.cpp b/llarp/iwp/session.cpp index 9aa88d01a..382e75c64 100644 --- a/llarp/iwp/session.cpp +++ b/llarp/iwp/session.cpp @@ -343,7 +343,7 @@ namespace llarp {"replayFilter", m_ReplayFilter.size()}, {"txMsgQueueSize", m_TXMsgs.size()}, {"rxMsgQueueSize", m_RXMsgs.size()}, - {"remoteAddr", m_RemoteAddr.toString()}, + {"remoteAddr", m_RemoteAddr.ToString()}, {"remoteRC", m_RemoteRC.ExtractStatus()}, {"created", to_json(m_CreatedAt)}, {"uptime", to_json(now - m_CreatedAt)}}; diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 528b9d37b..c22b0b863 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -196,8 +196,7 @@ namespace llarp } catch (const std::exception& ex) { - LogError( - stringify("Could not use ifname ", ifname, " to configure ILinkLayer: ", ex.what())); + LogError("Could not use ifname ", ifname, " to configure ILinkLayer: ", ex.what()); throw ex; } } @@ -344,7 +343,7 @@ namespace llarp return { {"name", Name()}, {"rank", uint64_t(Rank())}, - {"addr", m_ourAddr.toString()}, + {"addr", m_ourAddr.ToString()}, {"sessions", util::StatusObject{{"pending", pending}, {"established", established}}}}; } diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index 2075ba421..2452686ed 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -8,7 +8,9 @@ #include #include +#include #include +#include #include @@ -22,34 +24,6 @@ namespace { - struct Logger : public llarp::ILogStream - { - lokinet_logger_func func; - void* user; - - explicit Logger(lokinet_logger_func _func, void* _user) : func{_func}, user{_user} - {} - - void - PreLog(std::stringstream&, llarp::LogLevel, std::string_view, int, const std::string&) - const override - {} - - void - Print(llarp::LogLevel, std::string_view, const std::string& msg) override - { - func(msg.c_str(), user); - } - - void - PostLog(std::stringstream&) const override{}; - - void - ImmediateFlush() override{}; - - void Tick(llarp_time_t) override{}; - }; - struct Context : public llarp::Context { using llarp::Context::Context; @@ -132,7 +106,7 @@ namespace , m_Recv{recv} , m_Timeout{timeout} , m_User{user} - , m_Endpoint{ep} + , m_Endpoint{std::move(ep)} {} void @@ -222,16 +196,12 @@ struct lokinet_context { std::mutex m_access; - std::shared_ptr impl; - std::shared_ptr config; + std::shared_ptr impl = std::make_shared(); + std::shared_ptr config = llarp::Config::EmbeddedConfig(); std::unique_ptr runner; - int _socket_id; - - lokinet_context() - : impl{std::make_shared()}, config{llarp::Config::EmbeddedConfig()}, _socket_id{0} - {} + int _socket_id = 0; ~lokinet_context() { @@ -390,8 +360,7 @@ namespace { return {host, serv->s_port}; } - else - return {host, std::stoi(portStr)}; + return {host, std::stoi(portStr)}; } int @@ -457,8 +426,8 @@ struct lokinet_srv_lookup_private void IterateAll(std::function visit) { - for (size_t idx = 0; idx < results.size(); ++idx) - visit(&results[idx]); + for (auto& result : results) + visit(&result); // null terminator visit(nullptr); } @@ -479,12 +448,15 @@ extern "C" return strdup(netid.c_str()); } + static auto last_log_set = llarp::log::Level::info; + int EXPORT lokinet_log_level(const char* level) { - if (auto maybe = llarp::LogLevelFromString(level)) + if (auto maybe = llarp::log::level_from_string(level)) { - llarp::SetLogLevel(*maybe); + last_log_set = *maybe; + llarp::log::reset_level(*maybe); return 0; } return -1; @@ -561,7 +533,7 @@ extern "C" return -1; auto lock = ctx->acquire(); ctx->config->router.m_netId = lokinet_get_netid(); - ctx->config->logging.m_logLevel = llarp::GetLogLevel(); + ctx->config->logging.m_logLevel = last_log_set; ctx->runner = std::make_unique([ctx]() { llarp::util::SetThreadName("llarp-mainloop"); ctx->impl->Configure(ctx->config); @@ -719,7 +691,7 @@ extern "C" { auto [addr, id] = quic->open( remotehost, remoteport, [](auto) {}, localAddr); - auto [host, port] = split_host_port(addr.toString()); + auto [host, port] = split_host_port(addr.ToString()); ctx->outbound_stream(id); stream_okay(result, host, port, id); } @@ -826,17 +798,13 @@ extern "C" if (not oxenc::is_hex(hexview)) return nullptr; - const size_t byte_len = hexview.size() / 2; - const size_t b32z_len = (byte_len * 8 + 4) / 5; // = ⌈N×8÷5⌉ because 5 bits per 32z char + const size_t b32z_len = oxenc::to_base32z_size(oxenc::from_hex_size(hexview.size())); auto buf = std::make_unique(b32z_len + 1); - char* end = buf.get() + b32z_len; - *end = 0; // null terminate - // Write the bytes into the *end* of the buffer so that when we rewrite the final b32z chars - // into the buffer we won't overwrite any byte values until after we've consumed them. - char* bytepos = end - byte_len; - oxenc::from_hex(hexview.begin(), hexview.end(), bytepos); - // In-place conversion into the buffer - oxenc::to_base32z(bytepos, end, buf.get()); + buf[b32z_len] = '\0'; // null terminate + + oxenc::hex_decoder decode{hexview.begin(), hexview.end()}; + oxenc::base32z_encoder encode{decode, decode.end()}; + std::copy(encode, encode.end(), buf.get()); return buf.release(); // leak the buffer to the caller } @@ -1060,8 +1028,7 @@ extern "C" itr->second->AddFlow(*maybe, *remote, flow_data, flow_timeoutseconds); return 0; } - else - return EADDRINUSE; + return EADDRINUSE; } } else @@ -1070,9 +1037,16 @@ extern "C" return EINVAL; } + void EXPORT + lokinet_set_syncing_logger(lokinet_logger_func func, lokinet_logger_sync sync, void* user) + { + llarp::log::clear_sinks(); + llarp::log::add_sink(std::make_shared(func, sync, user)); + } + void EXPORT lokinet_set_logger(lokinet_logger_func func, void* user) { - llarp::LogContext::Instance().logStream.reset(new Logger{func, user}); + lokinet_set_syncing_logger(func, nullptr, user); } } diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp index 9144baf20..88d1af2d1 100644 --- a/llarp/messages/link_intro.cpp +++ b/llarp/messages/link_intro.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace llarp { diff --git a/llarp/messages/link_message_parser.cpp b/llarp/messages/link_message_parser.cpp index bd47ac67a..971af9a6d 100644 --- a/llarp/messages/link_message_parser.cpp +++ b/llarp/messages/link_message_parser.cpp @@ -9,7 +9,7 @@ #include "relay.hpp" #include #include -#include +#include #include diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index 3dc67d7a5..74b5ecc35 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 67dcb3294..8d0732059 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -289,32 +289,33 @@ namespace llarp return status == other.status; } + using namespace std::literals; + static constexpr std::array code_strings = { + std::make_pair(LR_StatusRecord::SUCCESS, "success"sv), + std::make_pair(LR_StatusRecord::FAIL_TIMEOUT, "timeout"sv), + std::make_pair(LR_StatusRecord::FAIL_CONGESTION, "congestion"sv), + std::make_pair(LR_StatusRecord::FAIL_DEST_UNKNOWN, "destination unknown"sv), + std::make_pair(LR_StatusRecord::FAIL_DECRYPT_ERROR, "decrypt error"sv), + std::make_pair(LR_StatusRecord::FAIL_MALFORMED_RECORD, "malformed record"sv), + std::make_pair(LR_StatusRecord::FAIL_DEST_INVALID, "destination invalid"sv), + std::make_pair(LR_StatusRecord::FAIL_CANNOT_CONNECT, "cannot connect"sv), + std::make_pair(LR_StatusRecord::FAIL_DUPLICATE_HOP, "duplicate hop"sv)}; + std::string LRStatusCodeToString(uint64_t status) { - std::map codes = { - {LR_StatusRecord::SUCCESS, "success"}, - {LR_StatusRecord::FAIL_TIMEOUT, "timeout"}, - {LR_StatusRecord::FAIL_CONGESTION, "congestion"}, - {LR_StatusRecord::FAIL_DEST_UNKNOWN, "destination unknown"}, - {LR_StatusRecord::FAIL_DECRYPT_ERROR, "decrypt error"}, - {LR_StatusRecord::FAIL_MALFORMED_RECORD, "malformed record"}, - {LR_StatusRecord::FAIL_DEST_INVALID, "destination invalid"}, - {LR_StatusRecord::FAIL_CANNOT_CONNECT, "cannot connect"}, - {LR_StatusRecord::FAIL_DUPLICATE_HOP, "duplicate hop"}}; - std::stringstream ss; - ss << "["; - bool found = false; - for (const auto& [val, message] : codes) + std::string s = "["; + for (const auto& [val, message] : code_strings) { if ((status & val) == val) { - ss << (found ? ", " : "") << message; - found = true; + if (s.size() > 1) + s += ", "; + s += message; } } - ss << "]"; - return ss.str(); + s += ']'; + return s; } } // namespace llarp diff --git a/llarp/net/address_info.cpp b/llarp/net/address_info.cpp index d4b8cd398..5c18e276f 100644 --- a/llarp/net/address_info.cpp +++ b/llarp/net/address_info.cpp @@ -166,7 +166,7 @@ namespace llarp void AddressInfo::fromSockAddr(const SockAddr& addr) { - const sockaddr_in6* addr6 = addr; + const auto* addr6 = static_cast(addr); memcpy(ip.s6_addr, addr6->sin6_addr.s6_addr, sizeof(ip.s6_addr)); port = addr.getPort(); } @@ -184,6 +184,14 @@ namespace llarp return stream; } + std::string + AddressInfo::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + void to_json(nlohmann::json& j, const AddressInfo& a) { diff --git a/llarp/net/address_info.hpp b/llarp/net/address_info.hpp index a66f77112..f9982b36b 100644 --- a/llarp/net/address_info.hpp +++ b/llarp/net/address_info.hpp @@ -55,23 +55,23 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + + std::string + ToString() const; }; void to_json(nlohmann::json& j, const AddressInfo& a); - inline std::ostream& - operator<<(std::ostream& out, const AddressInfo& a) - { - return a.print(out, -1, -1); - } - bool operator==(const AddressInfo& lhs, const AddressInfo& rhs); bool operator<(const AddressInfo& lhs, const AddressInfo& rhs); + template <> + constexpr inline bool IsToStringFormattable = true; + } // namespace llarp namespace std diff --git a/llarp/net/exit_info.cpp b/llarp/net/exit_info.cpp index e001c915a..46f9cb92e 100644 --- a/llarp/net/exit_info.cpp +++ b/llarp/net/exit_info.cpp @@ -17,10 +17,10 @@ namespace llarp ExitInfo::BEncode(llarp_buffer_t* buf) const { SockAddr exitaddr = ipAddress.createSockAddr(); - const sockaddr_in6* exitaddr6 = exitaddr; + const auto* exitaddr6 = static_cast(exitaddr); SockAddr netmaskaddr = netmask.createSockAddr(); - const sockaddr_in6* netmaskaddr6 = netmaskaddr; + const auto* netmaskaddr6 = static_cast(netmaskaddr); char tmp[128] = {0}; if (!bencode_start_dict(buf)) @@ -119,8 +119,14 @@ namespace llarp #endif printer.printValue(ss.str()); */ - stream << ipAddress.toString(); + stream << ipAddress.ToString(); return stream; } + std::string + ExitInfo::ToString() const + { + return ipAddress.ToString(); + } + } // namespace llarp diff --git a/llarp/net/exit_info.hpp b/llarp/net/exit_info.hpp index b3727c4f5..bad9c0ba8 100644 --- a/llarp/net/exit_info.hpp +++ b/llarp/net/exit_info.hpp @@ -42,11 +42,12 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + + std::string + ToString() const; }; - inline std::ostream& - operator<<(std::ostream& out, const ExitInfo& xi) - { - return xi.print(out, -1, -1); - } + template <> + constexpr inline bool IsToStringFormattable = true; + } // namespace llarp diff --git a/llarp/net/ip_address.cpp b/llarp/net/ip_address.cpp index 62fb2f428..818df7ac8 100644 --- a/llarp/net/ip_address.cpp +++ b/llarp/net/ip_address.cpp @@ -20,7 +20,7 @@ namespace llarp IpAddress::IpAddress(const SockAddr& addr) { - m_ipAddress = addr.toString(); + m_ipAddress = addr.ToString(); uint16_t port = addr.getPort(); if (port > 0) m_port = port; @@ -43,7 +43,7 @@ namespace llarp { SockAddr addr(other); - m_ipAddress = addr.toString(); + m_ipAddress = addr.ToString(); uint16_t port = addr.getPort(); if (port > 0) m_port = port; @@ -125,13 +125,13 @@ namespace llarp IpAddress::isBogon() const { SockAddr addr(m_ipAddress); - const sockaddr_in6* addr6 = addr; + const auto* addr6 = static_cast(addr); const uint8_t* raw = addr6->sin6_addr.s6_addr; return IsIPv4Bogon(ipaddr_ipv4_bits(raw[12], raw[13], raw[14], raw[15])); } std::string - IpAddress::toString() const + IpAddress::ToString() const { return m_ipAddress; // TODO: port } @@ -180,12 +180,4 @@ namespace llarp { return createSockAddr() == other.createSockAddr(); } - - std::ostream& - operator<<(std::ostream& out, const IpAddress& address) - { - out << address.toString(); - return out; - } - } // namespace llarp diff --git a/llarp/net/ip_address.hpp b/llarp/net/ip_address.hpp index 2414f4f8e..d86c77314 100644 --- a/llarp/net/ip_address.hpp +++ b/llarp/net/ip_address.hpp @@ -8,6 +8,8 @@ #include "net_int.hpp" +#include + namespace llarp { /// A struct that can represent either an IPv4 or IPv6 address. It is meant for representation @@ -118,7 +120,7 @@ namespace llarp /// /// @return string representation of this IpAddress std::string - toString() const; + ToString() const; std::string toHost() const; @@ -147,8 +149,8 @@ namespace llarp std::optional m_port = std::nullopt; }; - std::ostream& - operator<<(std::ostream& out, const IpAddress& address); + template <> + constexpr inline bool IsToStringFormattable = true; } // namespace llarp @@ -160,7 +162,7 @@ namespace std std::size_t operator()(const llarp::IpAddress& address) const noexcept { - return std::hash{}(address.toString()); + return std::hash{}(address.ToString()); } }; } // namespace std diff --git a/llarp/net/ip_range.hpp b/llarp/net/ip_range.hpp index 1a9b98683..31aee44d6 100644 --- a/llarp/net/ip_range.hpp +++ b/llarp/net/ip_range.hpp @@ -101,12 +101,6 @@ namespace llarp return Contains(net::ExpandV4(ip)); } - friend std::ostream& - operator<<(std::ostream& out, const IPRange& a) - { - return out << a.ToString(); - } - /// get the highest address on this range constexpr huint128_t HighestAddr() const @@ -147,6 +141,9 @@ namespace llarp BDecode(llarp_buffer_t* buf); }; + template <> + constexpr inline bool IsToStringFormattable = true; + } // namespace llarp namespace std diff --git a/llarp/net/net.cpp b/llarp/net/net.cpp index 0c73e3167..09877e944 100644 --- a/llarp/net/net.cpp +++ b/llarp/net/net.cpp @@ -16,7 +16,7 @@ #include "ip.hpp" #include "ip_range.hpp" -#include +#include #include #ifdef ANDROID @@ -540,9 +540,7 @@ namespace llarp int num = 0; while (num < 255) { - std::stringstream ifname_ss; - ifname_ss << "lokitun" << num; - std::string iftestname = ifname_ss.str(); + std::string iftestname = fmt::format("lokitun{}", num); bool found = llarp_getifaddr(iftestname.c_str(), AF_INET, nullptr); if (!found) { @@ -599,7 +597,7 @@ namespace llarp addr6.sin6_addr = IN6ADDR_ANY_INIT; return SockAddr{addr6}; } - throw llarp::make_exception(af, " is not a valid address family"); + throw std::invalid_argument{fmt::format("{} is not a valid address family", af)}; } } // namespace diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp index b5ec0e7cb..051d8c665 100644 --- a/llarp/net/net_int.hpp +++ b/llarp/net/net_int.hpp @@ -17,6 +17,8 @@ #include #include +#include + #include "uint128.hpp" namespace llarp @@ -111,12 +113,6 @@ namespace llarp bool FromString(const std::string&); - - friend std::ostream& - operator<<(std::ostream& out, const huint_t& i) - { - return out << i.ToString(); - } }; using huint32_t = huint_t; @@ -193,14 +189,14 @@ namespace llarp *this = ToNet(x); return true; } - - friend std::ostream& - operator<<(std::ostream& out, const nuint_t& i) - { - return out << i.ToString(); - } }; + template + inline constexpr bool IsToStringFormattable> = true; + + template + inline constexpr bool IsToStringFormattable> = true; + using nuint32_t = nuint_t; using nuint16_t = nuint_t; using nuint128_t = nuint_t; diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index dbb1734a2..b0ed8f2eb 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -3,7 +3,7 @@ #include "ip.hpp" #include "net_bits.hpp" #include -#include +#include #include #include @@ -262,21 +262,22 @@ namespace llarp // splits[0] should be dot-separated IPv4 auto ipSplits = split(splits[0], "."); if (ipSplits.size() != 4) - throw std::invalid_argument(stringify(str, " is not a valid IPv4 address")); + throw std::invalid_argument(fmt::format("{} is not a valid IPv4 address", str)); std::array ipBytes; for (int i = 0; i < 4; ++i) if (not parse_int(ipSplits[i], ipBytes[i])) - throw std::runtime_error(stringify(str, " contains invalid numeric value")); + throw std::runtime_error(fmt::format("{} contains invalid numeric value", str)); // attempt port before setting IPv4 bytes if (splits.size() == 2) { if (not allow_port) - throw std::runtime_error{stringify("invalid ip address (port not allowed here): ", str)}; + throw std::runtime_error{ + fmt::format("invalid ip address (port not allowed here): {}", str)}; uint16_t port; if (not parse_int(splits[1], port)) - throw std::runtime_error{stringify(splits[1], " is not a valid port")}; + throw std::runtime_error{fmt::format("{} is not a valid port", splits[1])}; setPort(port); } @@ -284,7 +285,7 @@ namespace llarp } std::string - SockAddr::toString() const + SockAddr::ToString() const { // TODO: review if (isEmpty()) @@ -435,11 +436,4 @@ namespace llarp return ntohs(m_addr.sin6_port); } - std::ostream& - operator<<(std::ostream& out, const SockAddr& address) - { - out << address.toString(); - return out; - } - } // namespace llarp diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp index a51379b13..df9838ac0 100644 --- a/llarp/net/sock_addr.hpp +++ b/llarp/net/sock_addr.hpp @@ -13,6 +13,7 @@ #include #include "net_int.hpp" #include +#include namespace llarp { @@ -60,9 +61,9 @@ namespace llarp SockAddr& operator=(const in6_addr& addr); - operator const sockaddr*() const; - operator const sockaddr_in*() const; - operator const sockaddr_in6*() const; + explicit operator const sockaddr*() const; + explicit operator const sockaddr_in*() const; + explicit operator const sockaddr_in6*() const; size_t sockaddr_len() const; @@ -77,7 +78,7 @@ namespace llarp fromString(std::string_view str, bool allow_port = true); std::string - toString() const; + ToString() const; std::string hostString() const; @@ -163,8 +164,8 @@ namespace llarp applyIPv4MapBytes(); }; - std::ostream& - operator<<(std::ostream& out, const SockAddr& address); + template <> + inline constexpr bool IsToStringFormattable = true; } // namespace llarp diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 22feb80f3..78a313ca7 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -5,7 +5,8 @@ #include "router_contact.hpp" #include "util/buffer.hpp" #include "util/fs.hpp" -#include "util/logging/logger.hpp" +#include "util/logging.hpp" +#include "util/time.hpp" #include "util/mem.hpp" #include "util/str.hpp" #include "dht/kademlia.hpp" @@ -38,7 +39,7 @@ namespace llarp } if (not fs::is_directory(nodedbDir)) - throw std::runtime_error(llarp::stringify("nodedb ", nodedbDir, " is not a directory")); + throw std::runtime_error{fmt::format("nodedb {} is not a directory", nodedbDir)}; for (const char& ch : skiplist_subdirs) { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 1e0540f0f..516a6d02d 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -135,10 +135,15 @@ namespace llarp std::string Path::HopsString() const { - std::stringstream ss; + std::string hops_str; + hops_str.reserve(hops.size() * 62); // 52 for the pkey, 6 for .snode, 4 for the ' -> ' joiner for (const auto& hop : hops) - ss << RouterID(hop.rc.pubkey) << " -> "; - return ss.str(); + { + if (!hops.empty()) + hops_str += " -> "; + hops_str += RouterID(hop.rc.pubkey).ToString(); + } + return hops_str; } bool @@ -568,9 +573,7 @@ namespace llarp std::string Path::Name() const { - std::stringstream ss; - ss << "TX=" << TXID() << " RX=" << RXID(); - return ss.str(); + return fmt::format("TX={} RX={}", TXID(), RXID()); } void diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index c401965aa..eaefcf40c 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -4,6 +4,7 @@ #include #include #include "path_context.hpp" +#include "util/logging.hpp" #include #include #include @@ -15,6 +16,11 @@ namespace llarp { + namespace + { + auto log_path = log::Cat("path"); + } + struct AsyncPathKeyExchangeContext : std::enable_shared_from_this { using WorkFunc_t = std::function; @@ -344,7 +350,7 @@ namespace llarp const auto maybe = SelectFirstHop(exclude); if (not maybe.has_value()) { - LogWarn(Name(), " has no first hop candidate"); + log::warning(log_path, "{} has no first hop candidate", Name()); return std::nullopt; } hops.emplace_back(*maybe); diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index 50a40ef75..c3ba852d6 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -365,13 +365,13 @@ namespace llarp std::string BuildStats::ToString() const { - std::stringstream ss; - ss << (SuccessRatio() * 100.0) << " percent success "; - ss << "(success=" << success << " "; - ss << "attempts=" << attempts << " "; - ss << "timeouts=" << timeouts << " "; - ss << "fails=" << fails << ")"; - return ss.str(); + return fmt::format( + "{:.2f} percent success (success={} attempts={} timeouts={} fails={})", + SuccessRatio() * 100.0, + success, + attempts, + timeouts, + fails); } double diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 5bef0a643..734b5b26b 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -71,12 +71,6 @@ namespace llarp std::string ToString() const; - - friend std::ostream& - operator<<(std::ostream& o, const BuildStats& st) - { - return o << st.ToString(); - } }; /// the role of this path can fulfill @@ -326,4 +320,8 @@ namespace llarp }; } // namespace path + + template <> + constexpr inline bool IsToStringFormattable = true; + } // namespace llarp diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index e52251996..a3b2cb19d 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -33,6 +33,14 @@ namespace llarp return stream; } + std::string + TransitHopInfo::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + TransitHop::TransitHop() : m_UpstreamGather(transit_hop_queue_size), m_DownstreamGather(transit_hop_queue_size) { @@ -442,6 +450,14 @@ namespace llarp return stream; } + std::string + TransitHop::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + void TransitHop::Stop() { diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 798c2d063..86080a330 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -30,6 +30,9 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + + std::string + ToString() const; }; inline bool @@ -52,12 +55,6 @@ namespace llarp < std::tie(rhs.txID, rhs.rxID, rhs.upstream, rhs.downstream); } - inline std::ostream& - operator<<(std::ostream& out, const TransitHopInfo& info) - { - return info.print(out, -1, -1); - } - struct TransitHop : public IHopHandler, public routing::IMessageHandler, std::enable_shared_from_this @@ -109,6 +106,8 @@ namespace llarp HandleLRSM( uint64_t status, std::array& frames, AbstractRouter* r) override; + std::string + ToString() const; std::ostream& print(std::ostream& stream, int level, int spaces) const; @@ -211,13 +210,13 @@ namespace llarp std::atomic m_UpstreamWorkCounter; std::atomic m_DownstreamWorkCounter; }; - - inline std::ostream& - operator<<(std::ostream& out, const TransitHop& h) - { - return h.print(out, -1, -1); - } } // namespace path + + template <> + constexpr inline bool IsToStringFormattable = true; + template <> + constexpr inline bool IsToStringFormattable = true; + } // namespace llarp namespace std diff --git a/llarp/peerstats/orm.hpp b/llarp/peerstats/orm.hpp index bd60c5d20..0c0df851b 100644 --- a/llarp/peerstats/orm.hpp +++ b/llarp/peerstats/orm.hpp @@ -62,9 +62,7 @@ namespace sqlite_orm std::string operator()(const llarp_time_t& value) const { - std::stringstream stream; - stream << value.count(); - return stream.str(); + return fmt::format("{}", value.count()); } }; diff --git a/llarp/peerstats/peer_db.cpp b/llarp/peerstats/peer_db.cpp index 6e1ff7d6a..78e904137 100644 --- a/llarp/peerstats/peer_db.cpp +++ b/llarp/peerstats/peer_db.cpp @@ -1,6 +1,6 @@ #include "peer_db.hpp" -#include +#include #include #include @@ -105,8 +105,8 @@ namespace llarp PeerDb::accumulatePeerStats(const RouterID& routerId, const PeerStats& delta) { if (routerId != delta.routerId) - throw std::invalid_argument( - stringify("routerId ", routerId, " doesn't match ", delta.routerId)); + throw std::invalid_argument{ + fmt::format("routerId {} doesn't match {}", routerId, delta.routerId)}; std::lock_guard guard(m_statsLock); auto itr = m_peerStats.find(routerId); diff --git a/llarp/pow.cpp b/llarp/pow.cpp index 0a5b7993d..48158f6b4 100644 --- a/llarp/pow.cpp +++ b/llarp/pow.cpp @@ -65,4 +65,12 @@ namespace llarp return stream; } + std::string + PoW::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + } // namespace llarp diff --git a/llarp/pow.hpp b/llarp/pow.hpp index be075ca6c..0a01bc85c 100644 --- a/llarp/pow.hpp +++ b/llarp/pow.hpp @@ -40,11 +40,12 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + + std::string + ToString() const; }; - inline std::ostream& - operator<<(std::ostream& out, const PoW& p) - { - return p.print(out, -1, -1); - } + template <> + constexpr inline bool IsToStringFormattable = true; + } // namespace llarp diff --git a/llarp/quic/address.cpp b/llarp/quic/address.cpp index 48dd05261..89e171104 100644 --- a/llarp/quic/address.cpp +++ b/llarp/quic/address.cpp @@ -25,7 +25,7 @@ namespace llarp::quic } std::string - Address::to_string() const + Address::ToString() const { if (a.addrlen != sizeof(sockaddr_in6)) return "(unknown-addr)"; @@ -39,15 +39,10 @@ namespace llarp::quic return result; } - std::ostream& - operator<<(std::ostream& o, const Address& a) - { - return o << a.to_string(); - } - std::ostream& - operator<<(std::ostream& o, const Path& p) + std::string + Path::ToString() const { - return o << p.local << "<-" << p.remote; + return local.ToString() + "<-" + remote.ToString(); } } // namespace llarp::quic diff --git a/llarp/quic/address.hpp b/llarp/quic/address.hpp index a6b56a243..793713e62 100644 --- a/llarp/quic/address.hpp +++ b/llarp/quic/address.hpp @@ -36,13 +36,16 @@ namespace llarp::quic operator=(const Address&); // Implicit conversion to sockaddr* and ngtcp2_addr& so that an Address can be passed wherever - // one of those is expected. - operator sockaddr*() + // one of those is expected. Templatized so that implicit conversion to other things doesn't + // happen. + template , int> = 0> + operator T*() { return reinterpret_cast(&saddr); } - operator const sockaddr*() const + template , int> = 0> + operator const T*() const { return reinterpret_cast(&saddr); } @@ -90,7 +93,7 @@ namespace llarp::quic } std::string - to_string() const; + ToString() const; }; // Wraps an ngtcp2_path (which is basically just and address pair) with remote/local components. @@ -124,24 +127,25 @@ namespace llarp::quic } // Equivalent to `&obj.path`, but slightly more convenient for passing into ngtcp2 functions - // taking a ngtcp2_path pointer. - operator ngtcp2_path*() + // taking a ngtcp2_path pointer. Templatized to prevent implicit conversion to other type of + // pointers/ints. + template , int> = 0> + operator T*() { return &path; } - operator const ngtcp2_path*() const + template , int> = 0> + operator const T*() const { return &path; } std::string - to_string() const; + ToString() const; }; - - std::ostream& - operator<<(std::ostream& o, const Address& a); - - std::ostream& - operator<<(std::ostream& o, const Path& p); - } // namespace llarp::quic + +template <> +constexpr inline bool llarp::IsToStringFormattable = true; +template <> +constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/quic/client.cpp b/llarp/quic/client.cpp index a2a081edf..8cf9d7f80 100644 --- a/llarp/quic/client.cpp +++ b/llarp/quic/client.cpp @@ -1,7 +1,7 @@ #include "client.hpp" #include "tunnel.hpp" #include -#include +#include #include #include diff --git a/llarp/quic/connection.cpp b/llarp/quic/connection.cpp index fed88401e..71b84cfd4 100644 --- a/llarp/quic/connection.cpp +++ b/llarp/quic/connection.cpp @@ -2,7 +2,7 @@ #include "client.hpp" #include "server.hpp" #include -#include +#include #include #include @@ -32,10 +32,10 @@ namespace llarp::quic std::memmove(data, cid, datalen); } - std::ostream& - operator<<(std::ostream& o, const ConnectionID& c) + std::string + ConnectionID::ToString() const { - return o << oxenc::to_hex(c.data, c.data + c.datalen); + return oxenc::to_hex(data, data + datalen); } ConnectionID diff --git a/llarp/quic/connection.hpp b/llarp/quic/connection.hpp index be8eb715c..0f2b4cc46 100644 --- a/llarp/quic/connection.hpp +++ b/llarp/quic/connection.hpp @@ -72,11 +72,16 @@ namespace llarp::quic static ConnectionID random(size_t size = ConnectionID::max_size()); + + std::string + ToString() const; }; - std::ostream& - operator<<(std::ostream& o, const ConnectionID& c); } // namespace llarp::quic + +template <> +constexpr inline bool llarp::IsToStringFormattable = true; + namespace std { template <> diff --git a/llarp/quic/null_crypto.cpp b/llarp/quic/null_crypto.cpp index 49623dfac..5043fcf8a 100644 --- a/llarp/quic/null_crypto.cpp +++ b/llarp/quic/null_crypto.cpp @@ -1,5 +1,5 @@ #include "null_crypto.hpp" -#include +#include #include diff --git a/llarp/quic/server.cpp b/llarp/quic/server.cpp index 690a97fac..ebda2bd40 100644 --- a/llarp/quic/server.cpp +++ b/llarp/quic/server.cpp @@ -1,6 +1,6 @@ #include "server.hpp" +#include #include -#include #include #include @@ -55,7 +55,6 @@ namespace llarp::quic { auto connptr = std::make_shared(*this, it->first, hd, p.path); it->second = connptr; - LogDebug("Created local Connection ", it->first, " for incoming connection"); return connptr; } } diff --git a/llarp/quic/stream.cpp b/llarp/quic/stream.cpp index a990372be..93f297068 100644 --- a/llarp/quic/stream.cpp +++ b/llarp/quic/stream.cpp @@ -1,7 +1,7 @@ #include "stream.hpp" #include "connection.hpp" #include "endpoint.hpp" -#include +#include #include #include @@ -43,10 +43,10 @@ namespace llarp::quic { - std::ostream& - operator<<(std::ostream& o, const StreamID& s) + std::string + StreamID::ToString() const { - return o << u8"Str❰" << s.id << u8"❱"; + return fmt::format(u8"Str❰{}❱", id); } Stream::Stream( diff --git a/llarp/quic/stream.hpp b/llarp/quic/stream.hpp index 176a2ab84..bed6f483a 100644 --- a/llarp/quic/stream.hpp +++ b/llarp/quic/stream.hpp @@ -12,6 +12,8 @@ #include #include +#include + namespace llarp::quic { class Connection; @@ -70,6 +72,9 @@ namespace llarp::quic { return s.id >= id; } + + std::string + ToString() const; }; // Application error code we close with if the data handle throws @@ -78,11 +83,11 @@ namespace llarp::quic // Error code we send to a stream close callback if the stream's connection expires; this is *not* // sent over quic, hence using a value >= 2^62 (quic's maximum serializable integer). inline constexpr uint64_t STREAM_ERROR_CONNECTION_EXPIRED = (1ULL << 62) + 1; - - std::ostream& - operator<<(std::ostream& o, const StreamID& s); } // namespace llarp::quic +template <> +constexpr inline bool llarp::IsToStringFormattable = true; + namespace std { template <> diff --git a/llarp/quic/tunnel.cpp b/llarp/quic/tunnel.cpp index 6954e20f4..480d14177 100644 --- a/llarp/quic/tunnel.cpp +++ b/llarp/quic/tunnel.cpp @@ -4,8 +4,8 @@ #include "service/name.hpp" #include "stream.hpp" #include +#include #include -#include #include #include #include @@ -479,9 +479,8 @@ namespace llarp::quic if (failed) { tcp_tunnel->close(); - throw std::runtime_error{ - "Failed to bind/listen local TCP tunnel socket on " + bind_addr.toString() + ": " - + failed}; + throw std::runtime_error{fmt::format( + "Failed to bind/listen local TCP tunnel socket on {}: {}", bind_addr, failed)}; } auto bound = tcp_tunnel->sock(); diff --git a/llarp/router/i_outbound_session_maker.hpp b/llarp/router/i_outbound_session_maker.hpp index 76ef6ddbd..97dd0aed9 100644 --- a/llarp/router/i_outbound_session_maker.hpp +++ b/llarp/router/i_outbound_session_maker.hpp @@ -2,6 +2,9 @@ #include #include +#include + +#include #include @@ -21,26 +24,19 @@ namespace llarp EstablishFail }; - inline std::ostream& - operator<<(std::ostream& out, const SessionResult& st) + constexpr std::string_view + ToString(SessionResult sr) { - switch (st) - { - case SessionResult::Establish: - return out << "success"; - case SessionResult::Timeout: - return out << "timeout"; - case SessionResult::NoLink: - return out << "no link"; - case SessionResult::InvalidRouter: - return out << "invalid router"; - case SessionResult::RouterNotFound: - return out << "not found"; - case SessionResult::EstablishFail: - return out << "establish failed"; - } - return out << "???"; + return sr == llarp::SessionResult::Establish ? "success"sv + : sr == llarp::SessionResult::Timeout ? "timeout"sv + : sr == llarp::SessionResult::NoLink ? "no link"sv + : sr == llarp::SessionResult::InvalidRouter ? "invalid router"sv + : sr == llarp::SessionResult::RouterNotFound ? "not found"sv + : sr == llarp::SessionResult::EstablishFail ? "establish failed"sv + : "???"sv; } + template <> + constexpr inline bool IsToStringFormattable = true; using RouterCallback = std::function; diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 1abbb8c05..0a793b2ff 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -152,7 +152,7 @@ namespace llarp return SendStatus::NoLink; } throw std::invalid_argument{ - stringify("SessionResult ", result, " has no corrispoding SendStatus when transforming")}; + fmt::format("SessionResult {} has no corresponding SendStatus when transforming", result)}; } void diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 1680e086c..c59e8aea0 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -15,9 +15,7 @@ #include #include #include -#include -#include -#include +#include #include #include #include @@ -658,7 +656,7 @@ namespace llarp { if (not BDecodeReadFile(router, b_list)) { - throw std::runtime_error(stringify("failed to read bootstrap list file '", router, "'")); + throw std::runtime_error{fmt::format("failed to read bootstrap list file '{}'", router)}; } } else @@ -666,8 +664,8 @@ namespace llarp RouterContact rc; if (not rc.Read(router)) { - throw std::runtime_error( - stringify("failed to decode bootstrap RC, file='", router, "' rc=", rc)); + throw std::runtime_error{ + fmt::format("failed to decode bootstrap RC, file='{}', rc={}", router, rc)}; } b_list.insert(rc); } @@ -759,7 +757,8 @@ namespace llarp uint16_t port = serverConfig.port; if (!server->Configure(this, key, af, port)) { - throw std::runtime_error(stringify("failed to bind inbound link on ", key, " port ", port)); + throw std::runtime_error{ + fmt::format("failed to bind inbound link on {} port {}", key, port)}; } _linkManager.AddLink(std::move(server), true); } @@ -794,12 +793,16 @@ namespace llarp } // Logging config - LogContext::Instance().Initialize( - conf.logging.m_logLevel, - conf.logging.m_logType, - conf.logging.m_logFile, - conf.router.m_nickname, - util::memFn(&AbstractRouter::QueueDiskIO, this)); + + // Backwards compat: before 0.9.10 we used `type=file` with `file=|-|stdout` for print mode + auto log_type = conf.logging.m_logType; + if (log_type == log::Type::File + && (conf.logging.m_logFile == "stdout" || conf.logging.m_logFile == "-" + || conf.logging.m_logFile.empty())) + log_type = log::Type::Print; + + log::reset_level(conf.logging.m_logLevel); + log::add_sink(log_type, conf.logging.m_logFile); return true; } @@ -861,42 +864,54 @@ namespace llarp #if defined(WITH_SYSTEMD) { - std::stringstream ss; - ss << "WATCHDOG=1\nSTATUS=v" << llarp::VERSION_STR; + std::string status; + auto out = std::back_inserter(status); + out = fmt::format_to(out, "WATCHDOG=1\nSTATUS=v{}", llarp::VERSION_STR); if (IsServiceNode()) { - ss << " snode | known/svc/clients: " << nodedb()->NumLoaded() << "/" - << NumberOfConnectedRouters() << "/" << NumberOfConnectedClients() << " | " - << pathContext().CurrentTransitPaths() << " active paths | " - << "block " << (m_lokidRpcClient ? m_lokidRpcClient->BlockHeight() : 0) << " | gossip: " - << "(next/last) " << time_delta{_rcGossiper.NextGossipAt()} - << " / "; + out = fmt::format_to( + out, + " snode | known/svc/clients: {}/{}/{}", + nodedb()->NumLoaded(), + NumberOfConnectedRouters(), + NumberOfConnectedClients()); + out = fmt::format_to( + out, + " | {} active paths | block {} ", + pathContext().CurrentTransitPaths(), + (m_lokidRpcClient ? m_lokidRpcClient->BlockHeight() : 0)); + out = fmt::format_to( + out, + " | gossip: (next/last) {} / ", + time_delta{_rcGossiper.NextGossipAt()}); if (auto maybe = _rcGossiper.LastGossipAt()) - { - ss << time_delta{*maybe}; - } + out = fmt::format_to(out, "{}", time_delta{*maybe}); else - { - ss << "never"; - } + out = fmt::format_to(out, "never"); } else { - ss << " client | known/connected: " << nodedb()->NumLoaded() << "/" - << NumberOfConnectedRouters(); + out = fmt::format_to( + out, + " client | known/connected: {}/{}", + nodedb()->NumLoaded(), + NumberOfConnectedRouters()); + if (auto ep = hiddenServiceContext().GetDefault()) { - ss << " | paths/endpoints " << pathContext().CurrentOwnedPaths() << "/" - << ep->UniqueEndpoints(); - auto success_rate = ep->CurrentBuildStats().SuccessRatio(); - if (success_rate < 0.5) + out = fmt::format_to( + out, + " | paths/endpoints {}/{}", + pathContext().CurrentOwnedPaths(), + ep->UniqueEndpoints()); + + if (auto success_rate = ep->CurrentBuildStats().SuccessRatio(); success_rate < 0.5) { - ss << " [ !!! Low Build Success Rate (" << std::setprecision(4) - << (100.0 * success_rate) << "%) !!! ] "; + out = fmt::format_to( + out, " [ !!! Low Build Success Rate ({:.1f}%) !!! ]", (100.0 * success_rate)); } }; } - const auto status = ss.str(); ::sd_notify(0, status.c_str()); } #endif @@ -1194,7 +1209,7 @@ namespace llarp if (enableRPCServer) { m_RPCServer->AsyncServeRPC(rpcBindAddr); - LogInfo("Bound RPC server to ", rpcBindAddr); + LogInfo("Bound RPC server to ", rpcBindAddr.full_address()); } return true; @@ -1404,7 +1419,7 @@ namespace llarp } }); } - LogContext::Instance().DropToRuntimeLevel(); + log::reset_level(log::Level::warn); return _running; } @@ -1453,7 +1468,7 @@ namespace llarp return; _stopping.store(true); - LogContext::Instance().RevertRuntimeLevel(); + log::reset_level(log::Level::info); LogWarn("stopping router hard"); #if defined(WITH_SYSTEMD) sd_notify(0, "STOPPING=1\nSTATUS=Shutting down HARD"); @@ -1473,7 +1488,7 @@ namespace llarp return; _stopping.store(true); - LogContext::Instance().RevertRuntimeLevel(); + log::reset_level(log::Level::info); LogInfo("stopping router"); #if defined(WITH_SYSTEMD) sd_notify(0, "STOPPING=1\nSTATUS=Shutting down"); @@ -1623,8 +1638,8 @@ namespace llarp _linkManager.AddLink(std::move(link), false); return true; } - throw std::runtime_error( - stringify("Failed to init AF_INET and AF_INET6 on port ", m_OutboundPort)); + throw std::runtime_error{ + fmt::format("Failed to init AF_INET and AF_INET6 on port {}", m_OutboundPort)}; } void diff --git a/llarp/router/systemd_resolved.cpp b/llarp/router/systemd_resolved.cpp index 5f1e40813..61d9ef930 100644 --- a/llarp/router/systemd_resolved.cpp +++ b/llarp/router/systemd_resolved.cpp @@ -1,5 +1,5 @@ #include "systemd_resolved.hpp" -#include +#include #ifndef WITH_SYSTEMD diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 76dac45fa..b1266145d 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -5,7 +5,7 @@ #include "net/net.hpp" #include "util/bencode.hpp" #include "util/buffer.hpp" -#include "util/logging/logger.hpp" +#include "util/logging.hpp" #include "util/mem.hpp" #include "util/printer.hpp" #include "util/time.hpp" @@ -56,8 +56,7 @@ namespace llarp std::string NetID::ToString() const { - auto term = std::find(begin(), end(), '\0'); - return std::string(begin(), term); + return {begin(), std::find(begin(), end(), '\0')}; } bool @@ -105,19 +104,17 @@ namespace llarp return false; } - std::ostream& - RouterContact::ToTXTRecord(std::ostream& out) const + std::string + RouterContact::ToTXTRecord() const { + std::string result; + auto out = std::back_inserter(result); for (const auto& addr : addrs) - { - out << "ai_addr=" << addr.toIpAddress() << "; "; - out << "ai_pk=" << addr.pubkey.ToHex() << "; "; - } - out << "updated=" << last_updated.count() << "; "; - out << "onion_pk=" << enckey.ToHex() << "; "; + out = fmt::format_to(out, "ai_addr={}; ai_pk={}; ", addr.toIpAddress(), addr.pubkey); + out = fmt::format_to(out, "updated={}; onion_pk={}; ", last_updated.count(), enckey.ToHex()); if (routerVersion.has_value()) - out << "router_version=" << routerVersion->ToString() << "; "; - return out; + out = fmt::format_to(out, "router_version={}; ", *routerVersion); + return result; } bool @@ -591,4 +588,12 @@ namespace llarp return stream; } + std::string + RouterContact::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + } // namespace llarp diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 53f29bd38..33ed5f4d7 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -48,14 +48,6 @@ namespace llarp return !(*this == other); } - std::ostream& - print(std::ostream& stream, int level, int spaces) const - { - Printer printer(stream, level, spaces); - printer.printValue(ToString()); - return stream; - } - std::string ToString() const; @@ -66,12 +58,6 @@ namespace llarp BEncode(llarp_buffer_t* buf) const; }; - inline std::ostream& - operator<<(std::ostream& out, const NetID& id) - { - return id.print(out, -1, -1); - } - /// RouterContact struct RouterContact { @@ -120,10 +106,7 @@ namespace llarp } std::string - ToString() const - { - return ToJson().dump(); - } + ToString() const; bool BEncode(llarp_buffer_t* buf) const; @@ -131,8 +114,8 @@ namespace llarp bool BEncodeSignedSection(llarp_buffer_t* buf) const; - std::ostream& - ToTXTRecord(std::ostream& out) const; + std::string + ToTXTRecord() const; bool operator==(const RouterContact& other) const @@ -229,11 +212,10 @@ namespace llarp DecodeVersion_1(oxenc::bt_list_consumer& btlist); }; - inline std::ostream& - operator<<(std::ostream& out, const RouterContact& rc) - { - return rc.print(out, -1, -1); - } + template <> + constexpr inline bool IsToStringFormattable = true; + template <> + constexpr inline bool IsToStringFormattable = true; using RouterLookupHandler = std::function&)>; } // namespace llarp diff --git a/llarp/router_id.hpp b/llarp/router_id.hpp index 70c4dfbc3..273460f91 100644 --- a/llarp/router_id.hpp +++ b/llarp/router_id.hpp @@ -37,12 +37,6 @@ namespace llarp std::copy(ptr, ptr + SIZE, begin()); return *this; } - - friend std::ostream& - operator<<(std::ostream& out, const RouterID& id) - { - return out << id.ToString(); - } }; inline bool @@ -51,6 +45,9 @@ namespace llarp return lhs.as_array() == rhs.as_array(); } + template <> + constexpr inline bool IsToStringFormattable = true; + } // namespace llarp namespace std diff --git a/llarp/router_version.hpp b/llarp/router_version.hpp index 0df69a7d1..30429483b 100644 --- a/llarp/router_version.hpp +++ b/llarp/router_version.hpp @@ -4,6 +4,7 @@ #include "util/bencode.hpp" #include "constants/version.hpp" #include "constants/proto.hpp" +#include "util/formattable.hpp" namespace llarp { @@ -60,11 +61,8 @@ namespace llarp int64_t m_ProtoVersion = llarp::constants::proto_version; }; - inline std::ostream& - operator<<(std::ostream& out, const RouterVersion& rv) - { - return out << rv.ToString(); - } + template <> + constexpr inline bool IsToStringFormattable = true; static constexpr int64_t INVALID_VERSION = -1; static const RouterVersion emptyRouterVersion({0, 0, 0}, INVALID_VERSION); diff --git a/llarp/rpc/endpoint_rpc.cpp b/llarp/rpc/endpoint_rpc.cpp index 8fa90bf95..a5edd2c34 100644 --- a/llarp/rpc/endpoint_rpc.cpp +++ b/llarp/rpc/endpoint_rpc.cpp @@ -27,7 +27,7 @@ namespace llarp::rpc oxenmq::address{m_AuthURL}, [self = shared_from_this()](oxenmq::ConnectionID c) { self->m_Conn = std::move(c); - LogInfo("connected to endpoint auth server via ", *self->m_Conn); + LogInfo("connected to endpoint auth server"); }, [self = shared_from_this()](oxenmq::ConnectionID, std::string_view fail) { LogWarn("failed to connect to endpoint auth server: ", fail); diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index 44e5c9520..be448c4eb 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -1,7 +1,7 @@ #include "lokid_rpc_client.hpp" #include -#include +#include #include @@ -14,20 +14,23 @@ namespace llarp { namespace rpc { - static oxenmq::LogLevel - toLokiMQLogLevel(llarp::LogLevel level) + static constexpr oxenmq::LogLevel + toLokiMQLogLevel(log::Level level) { switch (level) { - case eLogError: + case log::Level::critical: + return oxenmq::LogLevel::fatal; + case log::Level::err: return oxenmq::LogLevel::error; - case eLogWarn: + case log::Level::warn: return oxenmq::LogLevel::warn; - case eLogInfo: + case log::Level::info: return oxenmq::LogLevel::info; - case eLogDebug: + case log::Level::debug: return oxenmq::LogLevel::debug; - case eLogNone: + case log::Level::trace: + case log::Level::off: default: return oxenmq::LogLevel::trace; } @@ -58,7 +61,7 @@ namespace llarp { throw std::runtime_error("we cannot talk to lokid while not a service node"); } - LogInfo("connecting to lokid via LMQ at ", url); + LogInfo("connecting to lokid via LMQ at ", url.full_address()); m_Connection = m_lokiMQ->connect_remote( url, [self = shared_from_this()](oxenmq::ConnectionID) { self->Connected(); }, @@ -344,8 +347,8 @@ namespace llarp const auto nonce = oxenc::from_hex(j["nonce"].get()); if (nonce.size() != result.nonce.size()) { - throw std::invalid_argument(stringify( - "nonce size mismatch: ", nonce.size(), " != ", result.nonce.size())); + throw std::invalid_argument{fmt::format( + "nonce size mismatch: {} != {}", nonce.size(), result.nonce.size())}; } std::copy_n(nonce.data(), nonce.size(), result.nonce.data()); diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 7bc2f3f42..957bba6db 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -203,7 +203,7 @@ namespace llarp::rpc auto [addr, id] = quic->open( remoteHost, port, [](auto&&) {}, laddr); util::StatusObject status; - status["addr"] = addr.toString(); + status["addr"] = addr.ToString(); status["id"] = id; reply(CreateJSONResponse(status)); } @@ -632,7 +632,7 @@ namespace llarp::rpc { if (not itr->is_object()) { - reply(CreateJSONError(stringify("override is not an object"))); + reply(CreateJSONError("override is not an object")); return; } for (const auto& [section, value] : itr->items()) @@ -640,15 +640,15 @@ namespace llarp::rpc if (not value.is_object()) { reply(CreateJSONError( - stringify("failed to set [", section, "] section is not an object"))); + fmt::format("failed to set [{}]: section is not an object", section))); return; } for (const auto& [key, value] : value.items()) { if (not value.is_string()) { - reply(CreateJSONError(stringify( - "failed to set [", section, "]:", key, " value is not a string"))); + reply(CreateJSONError(fmt::format( + "failed to set [{}]:{}: value is not a string", section, key))); return; } r->GetConfig()->Override(section, key, value.get()); diff --git a/llarp/service/address.hpp b/llarp/service/address.hpp index bddfc822a..fd437b76b 100644 --- a/llarp/service/address.hpp +++ b/llarp/service/address.hpp @@ -61,12 +61,6 @@ namespace llarp return as_array() < other.as_array(); } - friend std::ostream& - operator<<(std::ostream& out, const Address& self) - { - return out << self.ToString(); - } - bool operator==(const Address& other) const { @@ -96,6 +90,9 @@ namespace llarp ParseAddress(std::string_view lokinet_addr); } // namespace service + + template <> + constexpr inline bool IsToStringFormattable = true; } // namespace llarp namespace std diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index a376b14b5..60d23a916 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -190,11 +190,12 @@ namespace llarp // use factory to create endpoint const auto itr = endpointConstructors.find(endpointType); if (itr == endpointConstructors.end()) - throw std::invalid_argument(stringify("Endpoint type ", endpointType, " does not exist")); + throw std::invalid_argument{fmt::format("Endpoint type {} does not exist", endpointType)}; auto service = itr->second(m_Router, this); if (not service) - throw std::runtime_error(stringify("Failed to construct endpoint of type ", endpointType)); + throw std::runtime_error{ + fmt::format("Failed to construct endpoint of type {}", endpointType)}; // pass conf to service service->Configure(conf.network, conf.dns); diff --git a/llarp/service/endpoint_util.cpp b/llarp/service/endpoint_util.cpp index a77bc9feb..06dec211f 100644 --- a/llarp/service/endpoint_util.cpp +++ b/llarp/service/endpoint_util.cpp @@ -3,7 +3,7 @@ #include #include "outbound_context.hpp" #include "lookup.hpp" -#include +#include namespace llarp { diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index d91da7411..0d106c24a 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -104,16 +104,16 @@ namespace llarp // write auto optional_f = util::OpenFileStream(fname, std::ios::binary); if (!optional_f) - throw std::runtime_error(stringify("can not open ", fname)); + throw std::runtime_error{fmt::format("can not open {}", fname)}; auto& f = *optional_f; if (!f.is_open()) - throw std::runtime_error(stringify("did not open ", fname)); + throw std::runtime_error{fmt::format("did not open {}", fname)}; f.write((char*)buf.cur, buf.sz); } if (not fs::is_regular_file(fname)) { - throw std::invalid_argument(stringify(fname, " is not a regular file")); + throw std::invalid_argument{fmt::format("{} is not a regular file", fname)}; } // read file diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index 3e2d15fd4..a969e8284 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -107,5 +107,13 @@ namespace llarp return stream; } + std::string + ServiceInfo::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + } // namespace service } // namespace llarp diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp index 1a56f13bf..bd8f5e58f 100644 --- a/llarp/service/info.hpp +++ b/llarp/service/info.hpp @@ -66,6 +66,9 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + std::string + ToString() const; + /// .loki address std::string Name() const; @@ -101,11 +104,8 @@ namespace llarp bool DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf); }; - - inline std::ostream& - operator<<(std::ostream& out, const ServiceInfo& i) - { - return i.print(out, -1, -1); - } } // namespace service } // namespace llarp + +template <> +constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/service/intro.cpp b/llarp/service/intro.cpp index b7fde5556..41d15aaaa 100644 --- a/llarp/service/intro.cpp +++ b/llarp/service/intro.cpp @@ -1,4 +1,5 @@ #include "intro.hpp" +#include "util/time.hpp" namespace llarp { @@ -77,5 +78,14 @@ namespace llarp return stream; } + + std::string + Introduction::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + } // namespace service } // namespace llarp diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index 36ea34c2a..2495957b4 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -36,6 +36,8 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + std::string + ToString() const; bool BEncode(llarp_buffer_t* buf) const; @@ -72,12 +74,6 @@ namespace llarp } }; - inline std::ostream& - operator<<(std::ostream& out, const Introduction& i) - { - return i.print(out, -1, -1); - } - /// comparator for introset timestamp struct CompareIntroTimestamp { @@ -90,6 +86,9 @@ namespace llarp } // namespace service } // namespace llarp +template <> +constexpr inline bool llarp::IsToStringFormattable = true; + namespace std { template <> diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index e0deda9e4..431f9dbfe 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -81,6 +81,14 @@ namespace llarp::service return out; } + std::string + EncryptedIntroSet::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } + std::optional EncryptedIntroSet::MaybeDecrypt(const PubKey& root) const { @@ -155,11 +163,7 @@ namespace llarp::service supportedProtocols.begin(), supportedProtocols.end(), std::back_inserter(protocols), - [](const auto& proto) -> util::StatusObject { - std::stringstream ss; - ss << proto; - return ss.str(); - }); + [](const auto& proto) -> util::StatusObject { return service::ToString(proto); }); obj["protos"] = protocols; std::vector ranges; std::transform( @@ -449,4 +453,12 @@ namespace llarp::service return stream; } + + std::string + IntroSet::ToString() const + { + std::ostringstream o; + print(o, -1, -1); + return o.str(); + } } // namespace llarp::service diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index c39a08404..71a19288e 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -59,6 +59,8 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + std::string + ToString() const; llarp_time_t GetNewestIntroExpiration() const; @@ -131,12 +133,6 @@ namespace llarp return !(lhs == rhs); } - inline std::ostream& - operator<<(std::ostream& out, const IntroSet& i) - { - return i.print(out, -1, -1); - } - /// public version of the introset that is encrypted struct EncryptedIntroSet { @@ -176,6 +172,8 @@ namespace llarp std::ostream& print(std::ostream& stream, int level, int spaces) const; + std::string + ToString() const; util::StatusObject ExtractStatus() const; @@ -184,12 +182,6 @@ namespace llarp MaybeDecrypt(const PubKey& rootKey) const; }; - inline std::ostream& - operator<<(std::ostream& out, const EncryptedIntroSet& i) - { - return i.print(out, -1, -1); - } - inline bool operator<(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) { @@ -215,3 +207,8 @@ namespace llarp } // namespace service } // namespace llarp + +template <> +constexpr inline bool llarp::IsToStringFormattable = true; +template <> +constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/service/protocol_type.cpp b/llarp/service/protocol_type.cpp deleted file mode 100644 index 4a6861681..000000000 --- a/llarp/service/protocol_type.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "protocol_type.hpp" - -namespace llarp::service -{ - std::ostream& - operator<<(std::ostream& o, ProtocolType t) - { - return o - << (t == ProtocolType::Control ? "Control" - : t == ProtocolType::TrafficV4 ? "TrafficV4" - : t == ProtocolType::TrafficV6 ? "TrafficV6" - : t == ProtocolType::Exit ? "Exit" - : t == ProtocolType::Auth ? "Auth" - : t == ProtocolType::QUIC ? "QUIC" - : "(unknown-protocol-type)"); - } - -} // namespace llarp::service diff --git a/llarp/service/protocol_type.hpp b/llarp/service/protocol_type.hpp index 8af8614a8..3864717be 100644 --- a/llarp/service/protocol_type.hpp +++ b/llarp/service/protocol_type.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace llarp::service { @@ -19,7 +20,20 @@ namespace llarp::service }; - std::ostream& - operator<<(std::ostream& o, ProtocolType t); + constexpr std::string_view + ToString(ProtocolType t) + { + using namespace std::literals; + return t == ProtocolType::Control ? "Control"sv + : t == ProtocolType::TrafficV4 ? "TrafficV4"sv + : t == ProtocolType::TrafficV6 ? "TrafficV6"sv + : t == ProtocolType::Exit ? "Exit"sv + : t == ProtocolType::Auth ? "Auth"sv + : t == ProtocolType::QUIC ? "QUIC"sv + : "(unknown-protocol-type)"sv; + } } // namespace llarp::service + +template <> +constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index 713220614..d41fff48f 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -1,8 +1,9 @@ #pragma once #include "bencode.h" -#include +#include #include +#include #include "printer.hpp" #include @@ -69,12 +70,6 @@ namespace llarp return *this; } - friend std::ostream& - operator<<(std::ostream& out, const AlignedBuffer& self) - { - return out << oxenc::to_hex(self.begin(), self.end()); - } - /// bitwise NOT AlignedBuffer operator~() const @@ -300,8 +295,43 @@ namespace llarp private: Data m_data; }; + + namespace detail + { + template + static std::true_type + is_aligned_buffer_impl(AlignedBuffer*); + + static std::false_type + is_aligned_buffer_impl(...); + } // namespace detail + // True if T is or is derived from AlignedBuffer for any N + template + constexpr inline bool is_aligned_buffer = + decltype(detail::is_aligned_buffer_impl(static_cast(nullptr)))::value; + } // namespace llarp +namespace fmt +{ + // Any AlignedBuffer (or subclass) gets hex formatted when output: + template + struct formatter< + T, + char, + std::enable_if_t && !llarp::IsToStringFormattable>> + : formatter + { + template + auto + format(const T& val, FormatContext& ctx) + { + auto it = oxenc::hex_encoder{val.begin(), val.end()}; + return std::copy(it, it.end(), ctx.out()); + } + }; +} // namespace fmt + namespace std { template diff --git a/llarp/util/bencode.cpp b/llarp/util/bencode.cpp index 2ff9bc567..73966291b 100644 --- a/llarp/util/bencode.cpp +++ b/llarp/util/bencode.cpp @@ -1,5 +1,4 @@ #include "bencode.hpp" -#include #include #include #include diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index 7ccabdcab..c02453f58 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -3,7 +3,7 @@ #include "buffer.hpp" #include "bencode.h" #include "fs.hpp" -#include +#include #include "mem.hpp" #include diff --git a/llarp/util/formattable.hpp b/llarp/util/formattable.hpp new file mode 100644 index 000000000..edc4285e3 --- /dev/null +++ b/llarp/util/formattable.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include +#include + +// Formattable types can specialize this to true and will get automatic fmt formattering support via +// their .ToString() method. + +namespace llarp +{ + // Types can opt-in to being formatting via .ToString() by specializing this to true. This also + // allows scoped enums by instead looking for a call to `ToString(val)` (and so there should be a + // ToString function in the same namespace as the scoped enum to pick it up via ADL). + template + constexpr bool IsToStringFormattable = false; + + // e.g.: + // template <> inline constexpr bool IsToStringFormattable = true; + +#ifdef __cpp_lib_is_scoped_enum + using std::is_scoped_enum; + using std::is_scoped_enum_v; +#else + template > + struct is_scoped_enum : std::false_type + {}; + + template + struct is_scoped_enum + : std::bool_constant>> + {}; + + template + constexpr bool is_scoped_enum_v = is_scoped_enum::value; +#endif + +} // namespace llarp + +#if !defined(USE_GHC_FILESYSTEM) && FMT_VERSION >= 80102 + +// Native support in fmt added after fmt 8.1.1 +#include + +#else + +#include + +namespace fmt +{ + template <> + struct formatter : formatter + { + template + auto + format(const fs::path& p, FormatContext& ctx) + { + return formatter::format(p.string(), ctx); + } + }; +} // namespace fmt + +#endif + +namespace fmt +{ + template + struct formatter>> + : formatter + { + template + auto + format(const T& val, FormatContext& ctx) + { + if constexpr (llarp::is_scoped_enum_v) + return formatter::format(ToString(val), ctx); + else + return formatter::format(val.ToString(), ctx); + } + }; + +} // namespace fmt diff --git a/llarp/util/fs.cpp b/llarp/util/fs.cpp index 187ea2228..95b345a58 100644 --- a/llarp/util/fs.cpp +++ b/llarp/util/fs.cpp @@ -1,6 +1,7 @@ #include "fs.hpp" -#include +#include +#include #include #include @@ -13,55 +14,6 @@ #include #endif -namespace cpp17 -{ - namespace filesystem - { -#ifdef LOKINET_USE_CPPBACKPORT - const fs::perms active_bits( - fs::perms::all | fs::perms::set_uid | fs::perms::set_gid | fs::perms::sticky_bit); - inline mode_t - mode_cast(fs::perms prms) - { - return prms & active_bits; - } - - void - permissions(const fs::path& p, fs::perms prms, std::error_code& ec) - { - std::error_code local_ec; - - // OS X <10.10, iOS <8.0 and some other platforms don't support - // fchmodat(). Solaris (SunPro and gcc) only support fchmodat() on - // Solaris 11 and higher, and a runtime check is too much trouble. Linux - // does not support permissions on symbolic links and has no plans to - // support them in the future. The chmod() code is thus more practical, - // rather than always hitting ENOTSUP when sending in - // AT_SYMLINK_NO_FOLLOW. - // - See the 3rd paragraph of - // "Symbolic link ownership, permissions, and timestamps" at: - // "http://man7.org/linux/man-pages/man7/symlink.7.html" - // - See the fchmodat() Linux man page: - // "http://man7.org/linux/man-pages/man2/fchmodat.2.html" -#if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) \ - && !(defined(__SUNPRO_CC) || defined(__sun) || defined(sun)) \ - && !(defined(linux) || defined(__linux) || defined(__linux__)) \ - && !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000) \ - && !(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 80000) \ - && !(defined(__QNX__) && (_NTO_VERSION <= 700)) - if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms), 0)) -#else // fallback if fchmodat() not supported - if (::chmod(p.c_str(), mode_cast(prms))) -#endif - { - const int err = errno; - ec.assign(err, std::generic_category()); - } - } -#endif - } // namespace filesystem -} // namespace cpp17 - namespace llarp { namespace util diff --git a/llarp/util/logging.hpp b/llarp/util/logging.hpp new file mode 100644 index 000000000..9c9cd27c4 --- /dev/null +++ b/llarp/util/logging.hpp @@ -0,0 +1,102 @@ +#pragma once + +// Header for making actual log statements such as llarp::log::Info and so on work. + +#include +#include + +#include + +namespace llarp +{ + namespace log = oxen::log; +} + +// Not ready to pollute these deprecation warnings everywhere yet +#if 0 +#define LOKINET_LOG_DEPRECATED(Meth) \ + [[deprecated("Use formatted log::" #Meth "(cat, fmt, args...) instead")]] +#else +#define LOKINET_LOG_DEPRECATED(Meth) +#endif + +// Deprecated loggers (in the top-level llarp namespace): +namespace llarp +{ + namespace log_detail + { + inline log::CategoryLogger legacy_logger = log::Cat(""); + + template + struct concat_args_fmt_impl; + template + struct concat_args_fmt_impl> + { + constexpr static std::array format{(I % 2 == 0 ? '{' : '}')...}; + }; + template + constexpr std::string_view + concat_args_fmt() + { + return std::string_view{ + concat_args_fmt_impl>::format.data(), 2 * N}; + } + + template + struct LegacyLeveledLogger : log::detail::LeveledLogger + { + LegacyLeveledLogger( + T&&... args, const slns::source_location& location = slns::source_location::current()) + : log::detail::LeveledLogger::LeveledLogger{ + legacy_logger, concat_args_fmt(), std::forward(args)..., location} + {} + }; + } // namespace log_detail + + template + struct LOKINET_LOG_DEPRECATED(Trace) LogTrace + : log_detail::LegacyLeveledLogger + { + using log_detail::LegacyLeveledLogger::LegacyLeveledLogger; + }; + template + struct LOKINET_LOG_DEPRECATED(Debug) LogDebug + : log_detail::LegacyLeveledLogger + { + using log_detail::LegacyLeveledLogger::LegacyLeveledLogger; + }; + template + struct LOKINET_LOG_DEPRECATED(Info) LogInfo + : log_detail::LegacyLeveledLogger + { + using log_detail::LegacyLeveledLogger::LegacyLeveledLogger; + }; + template + struct LOKINET_LOG_DEPRECATED(Warning) LogWarn + : log_detail::LegacyLeveledLogger + { + using log_detail::LegacyLeveledLogger::LegacyLeveledLogger; + }; + template + struct LOKINET_LOG_DEPRECATED(Error) LogError + : log_detail::LegacyLeveledLogger + { + using log_detail::LegacyLeveledLogger::LegacyLeveledLogger; + }; + + template + LogTrace(T&&...) -> LogTrace; + + template + LogDebug(T&&...) -> LogDebug; + + template + LogInfo(T&&...) -> LogInfo; + + template + LogWarn(T&&...) -> LogWarn; + + template + LogError(T&&...) -> LogError; + +} // namespace llarp diff --git a/llarp/util/logging/android_logger.cpp b/llarp/util/logging/android_logger.cpp deleted file mode 100644 index ae4bdb793..000000000 --- a/llarp/util/logging/android_logger.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "android_logger.hpp" -#include "logger_internal.hpp" - -#include -namespace llarp -{ - void - AndroidLogStream::PreLog( - std::stringstream& ss, LogLevel lvl, std::string_view fname, int lineno, const std::string&) - const - { - switch (lvl) - { - case eLogNone: - return; - case eLogTrace: - ss << "[TRC] "; - break; - case eLogDebug: - ss << "[DBG] "; - break; - case eLogInfo: - ss << "[NFO] "; - break; - case eLogWarn: - ss << "[WRN] "; - break; - case eLogError: - ss << "[ERR] "; - break; - } - - ss << "(" << thread_id_string() << ") " << log_timestamp() << " " << fname << ":" << lineno - << "\t"; - } - - void - AndroidLogStream::PostLog(std::stringstream&) const - {} - - void AndroidLogStream::Tick(llarp_time_t) - {} - - void - AndroidLogStream::Print(LogLevel lvl, std::string_view tag, const std::string& msg) - { - std::string str("lokinet|"); - str += tag; - switch (lvl) - { - case eLogTrace: - case eLogDebug: - __android_log_write(ANDROID_LOG_DEBUG, str.c_str(), msg.c_str()); - return; - case eLogInfo: - __android_log_write(ANDROID_LOG_INFO, str.c_str(), msg.c_str()); - return; - case eLogWarn: - __android_log_write(ANDROID_LOG_WARN, str.c_str(), msg.c_str()); - return; - case eLogError: - __android_log_write(ANDROID_LOG_ERROR, str.c_str(), msg.c_str()); - return; - default: - return; - } - - } // namespace llarp -} // namespace llarp diff --git a/llarp/util/logging/android_logger.hpp b/llarp/util/logging/android_logger.hpp deleted file mode 100644 index e42989910..000000000 --- a/llarp/util/logging/android_logger.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "logstream.hpp" - -#include - -namespace llarp -{ - struct AndroidLogStream : public ILogStream - { - void - PreLog( - std::stringstream& s, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const override; - - void - Print(LogLevel lvl, std::string_view filename, const std::string& msg) override; - - void - PostLog(std::stringstream&) const override; - - void Tick(llarp_time_t) override; - - void - ImmediateFlush() override{}; - }; -} // namespace llarp diff --git a/llarp/util/logging/buffer.cpp b/llarp/util/logging/buffer.cpp index 284bf8633..a3dfd347c 100644 --- a/llarp/util/logging/buffer.cpp +++ b/llarp/util/logging/buffer.cpp @@ -4,43 +4,42 @@ namespace llarp { - std::ostream& - operator<<(std::ostream& o, const buffer_printer& bp) + std::string + buffer_printer::ToString() const { - auto& b = bp.buf; - auto oldfill = o.fill(); - o.fill('0'); - o << "Buffer[" << b.size() << "/0x" << std::hex << b.size() << " bytes]:"; + auto& b = buf; + std::string out; + auto ins = std::back_inserter(out); + fmt::format_to(ins, "Buffer[{}/{:#x} bytes]:", b.size(), b.size()); + for (size_t i = 0; i < b.size(); i += 32) { - o << "\n" << std::setw(4) << i << " "; + fmt::format_to(ins, "\n{:04x} ", i); size_t stop = std::min(b.size(), i + 32); for (size_t j = 0; j < 32; j++) { auto k = i + j; if (j % 4 == 0) - o << ' '; - if (k >= stop) - o << " "; + out.push_back(' '); + if (j >= stop) + out.append(" "); else - o << std::setw(2) << std::to_integer(b[k]); + fmt::format_to(ins, "{:02x}", std::to_integer(b[k])); } - o << u8" ┃"; + out.append(u8" ┃"); for (size_t j = i; j < stop; j++) { auto c = std::to_integer(b[j]); if (c == 0x00) - o << u8"∅"; + out.append(u8"∅"); else if (c < 0x20 || c > 0x7e) - o << u8"·"; + out.append(u8"·"); else - o << c; + out.push_back(c); } - o << u8"┃"; + out.append(u8"┃"); } - o << std::dec; - o.fill(oldfill); - return o; + return out; } } // namespace llarp diff --git a/llarp/util/logging/buffer.hpp b/llarp/util/logging/buffer.hpp index e9cc2db75..c228927d2 100644 --- a/llarp/util/logging/buffer.hpp +++ b/llarp/util/logging/buffer.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -13,7 +14,9 @@ namespace llarp // visual representation of the data for logging purposes. Wraps the string data with a object // that prints the buffer format during output; use as: // - // out << buffer_printer(my_buffer); + // fmt::print("{}", buffer_printer(my_buffer)); + // + // or similarly in a log statement. // struct buffer_printer { @@ -48,7 +51,11 @@ namespace llarp explicit buffer_printer(const llarp_buffer_t& buf) : buffer_printer(std::basic_string_view{buf.base, buf.sz}) {} + + std::string + ToString() const; }; - std::ostream& - operator<<(std::ostream& o, const buffer_printer& bp); + + template <> + constexpr inline bool IsToStringFormattable = true; } // namespace llarp diff --git a/llarp/util/logging/callback_sink.hpp b/llarp/util/logging/callback_sink.hpp new file mode 100644 index 000000000..9b5538562 --- /dev/null +++ b/llarp/util/logging/callback_sink.hpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +namespace llarp::logging +{ + // Logger that calls a C function with the formatted log message + template + class CallbackSink : public spdlog::sinks::base_sink + { + private: + lokinet_logger_func log_; + lokinet_logger_sync sync_; + void* ctx_; + + public: + explicit CallbackSink( + lokinet_logger_func log, lokinet_logger_sync sync = nullptr, void* context = nullptr) + : log_{log}, sync_{sync}, ctx_{context} + {} + + protected: + void + sink_it_(const spdlog::details::log_msg& msg) override + { + if (!log_) + return; + spdlog::memory_buf_t formatted; + spdlog::sinks::base_sink::formatter_->format(msg, formatted); + log_(fmt::to_string(formatted).c_str(), ctx_); + } + + void + flush_() override + { + if (sync_) + sync_(ctx_); + } + }; + + // Convenience aliases with or without thread safety + using CallbackSink_mt = CallbackSink; + using CallbackSink_st = CallbackSink; + +} // namespace llarp::logging diff --git a/llarp/util/logging/file_logger.cpp b/llarp/util/logging/file_logger.cpp deleted file mode 100644 index c41d092e8..000000000 --- a/llarp/util/logging/file_logger.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include "file_logger.hpp" -#include "logger_internal.hpp" -#include - -#include - -namespace llarp -{ - void - FileLogStream::Flush(Lines_t* lines, FILE* const f) - { - bool wrote_stuff = false; - do - { - auto maybe_line = lines->tryPopFront(); - if (not maybe_line) - break; - if (fprintf(f, "%s\n", maybe_line->c_str()) >= 0) - wrote_stuff = true; - } while (true); - - if (wrote_stuff) - fflush(f); - } - - // namespace - FileLogStream::FileLogStream( - std::function disk, FILE* f, llarp_time_t flushInterval, bool closeFile) - : m_Lines(1024 * 8) - , m_Disk(std::move(disk)) - , m_File(f) - , m_FlushInterval(flushInterval) - , m_Close(closeFile) - { - m_Lines.enable(); - } - - FileLogStream::~FileLogStream() - { - m_Lines.disable(); - do - { - auto line = m_Lines.tryPopFront(); - if (not line) - break; - } while (true); - fflush(m_File); - if (m_Close) - fclose(m_File); - } - - bool - FileLogStream::ShouldFlush(llarp_time_t now) const - { - if (m_Lines.full()) - return true; - if (m_LastFlush >= now) - return false; - const auto dlt = now - m_LastFlush; - return dlt >= m_FlushInterval; - } - - void - FileLogStream::PreLog( - std::stringstream& ss, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const - { - ss << "[" << LogLevelToString(lvl) << "] "; - ss << "[" << nodename << "]" - << "(" << thread_id_string() << ") " << log_timestamp() << " " << filename << ":" << lineno - << "\t"; - } - - void - FileLogStream::Print(LogLevel, std::string_view, const std::string& msg) - { - m_Lines.pushBack(msg); - } - - void - FileLogStream::AppendLog( - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename, - const std::string msg) - { - ILogStream::AppendLog(lvl, filename, lineno, nodename, msg); - Tick(llarp::time_now_ms()); - } - - void - FileLogStream::ImmediateFlush() - { - Flush(&m_Lines, m_File); - m_LastFlush = time_now_ms(); - } - - void - FileLogStream::Tick(llarp_time_t now) - { - if (ShouldFlush(now)) - FlushLinesToDisk(now); - } - - void - FileLogStream::FlushLinesToDisk(llarp_time_t now) - { - FILE* const f = m_File; - auto lines = &m_Lines; - m_Disk([f, lines]() { Flush(lines, f); }); - m_LastFlush = now; - } -} // namespace llarp diff --git a/llarp/util/logging/file_logger.hpp b/llarp/util/logging/file_logger.hpp deleted file mode 100644 index 07af96102..000000000 --- a/llarp/util/logging/file_logger.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include "logstream.hpp" - -#include -#include - -#include - -namespace llarp -{ - /// flushable file based log stream - struct FileLogStream : public ILogStream - { - using Work_t = std::function; - - FileLogStream( - std::function io, FILE* f, llarp_time_t flushInterval, bool closefile = true); - - ~FileLogStream() override; - - void - PreLog( - std::stringstream& out, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const override; - - void - Print(LogLevel, std::string_view filename, const std::string& msg) override; - - void - Tick(llarp_time_t now) override; - - void - PostLog(std::stringstream&) const override{}; - - void - AppendLog( - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename, - const std::string msg) override; - - virtual void - ImmediateFlush() override; - - using Lines_t = thread::Queue; - - protected: - Lines_t m_Lines; - - private: - static void - Flush(Lines_t* const, FILE* const); - - bool - ShouldFlush(llarp_time_t now) const; - - void - FlushLinesToDisk(llarp_time_t now); - - const std::function m_Disk; - FILE* const m_File; - const llarp_time_t m_FlushInterval; - llarp_time_t m_LastFlush = 0s; - const bool m_Close; - }; -} // namespace llarp diff --git a/llarp/util/logging/logger.cpp b/llarp/util/logging/logger.cpp deleted file mode 100644 index 3357ab291..000000000 --- a/llarp/util/logging/logger.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "logger.hpp" -#include "ostream_logger.hpp" -#include "logger_syslog.hpp" -#include "file_logger.hpp" -#if defined(_WIN32) -#include "win32_logger.hpp" -#endif -#if defined(ANDROID) -#include "android_logger.hpp" -#endif - -#include - -#include - -namespace llarp -{ -#if defined(_WIN32) - using Stream_t = Win32LogStream; -#define _LOGSTREAM_INIT std::cout -#else -#if defined(ANDROID) - using Stream_t = AndroidLogStream; -#define _LOGSTREAM_INIT -#else - using Stream_t = OStreamLogStream; -#define _LOGSTREAM_INIT true, std::cout -#endif -#endif - - LogType - LogTypeFromString(const std::string& str) - { - if (str == "unknown") - return LogType::Unknown; - else if (str == "file") - return LogType::File; - else if (str == "syslog") - return LogType::Syslog; - - return LogType::Unknown; - } - - LogContext::LogContext() : logStream{std::make_unique(_LOGSTREAM_INIT)} - {} - - LogContext& - LogContext::Instance() - { - static LogContext ctx; - return ctx; - } - - void - LogContext::DropToRuntimeLevel() - { - curLevel = runtimeLevel; - } - - void - LogContext::RevertRuntimeLevel() - { - curLevel = startupLevel; - } - - log_timestamp::log_timestamp() : log_timestamp("%c %Z") - {} - - log_timestamp::log_timestamp(const char* fmt) - : format{fmt}, now{llarp::time_now_ms()}, delta{llarp::uptime()} - {} - - void - SetLogLevel(LogLevel lvl) - { - LogContext::Instance().curLevel = lvl; - LogContext::Instance().runtimeLevel = lvl; - } - - LogLevel - GetLogLevel() - { - return LogContext::Instance().curLevel; - } - - void - LogContext::ImmediateFlush() - { - logStream->ImmediateFlush(); - } - - void - LogContext::Initialize( - LogLevel level, - LogType type, - const std::string& file, - const std::string& nickname, - std::function io) - { - SetLogLevel(level); - if (level == eLogTrace) - LogTrace("Set log level to trace."); - - nodeName = nickname; - - FILE* logfile = nullptr; - if (file == "stdout" or file == "-" or file.empty()) - { - logfile = stdout; - } - else if (type != LogType::Syslog) - { - logfile = ::fopen(file.c_str(), "a"); - if (not logfile) - { - throw std::runtime_error( - stringify("could not open logfile ", file, ", errno: ", strerror(errno))); - } - } - - switch (type) - { - case LogType::Unknown: - // tolerate as fallback to LogType::File - - case LogType::File: - if (logfile != stdout) - { - LogInfo("Switching logger to file ", file); - std::cout << std::flush; - - LogContext::Instance().logStream = - std::make_unique(io, logfile, 100ms, true); - } - else - { - LogInfo("Logger remains stdout"); - } - - break; - case LogType::Syslog: -#if defined(_WIN32) - throw std::runtime_error("syslog not supported on win32"); -#else - LogContext::Instance().logStream = std::make_unique(); -#endif - break; - } - } - - LogSilencer::LogSilencer() : LogSilencer(LogContext::Instance()) - {} - - LogSilencer::LogSilencer(LogContext& ctx) : parent(ctx), stream(std::move(ctx.logStream)) - {} - - LogSilencer::~LogSilencer() - { - parent.logStream = std::move(stream); - } - -} // namespace llarp diff --git a/llarp/util/logging/logger.hpp b/llarp/util/logging/logger.hpp deleted file mode 100644 index fd5b6ef60..000000000 --- a/llarp/util/logging/logger.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#pragma once - -#include -#include -#include -#include "logstream.hpp" -#include "logger_internal.hpp" -#include "source_location.hpp" - -namespace llarp -{ - enum class LogType - { - Unknown = 0, - File, - Syslog, - }; - LogType - LogTypeFromString(const std::string&); - - struct LogContext - { - using IOFunc_t = std::function; - - LogContext(); - LogLevel curLevel = eLogInfo; - LogLevel startupLevel = eLogInfo; - LogLevel runtimeLevel = eLogWarn; - ILogStream_ptr logStream; - std::string nodeName = "lokinet"; - - static LogContext& - Instance(); - - void - DropToRuntimeLevel(); - - void - RevertRuntimeLevel(); - - /// A blocking call that will not return until any existing log functions have flushed. - /// Should only be called in rare circumstances, such as when the program is about to exit. - void - ImmediateFlush(); - - /// Initialize the logging system. - /// - /// @param level is the new log level (below which log statements will be ignored) - /// @param type is the type of logger to set up - /// @param file is the file to log to (relevant for types File and Json) - /// @param nickname is a tag to add to each log statement - /// @param io is a callable that queues work that does io, async - void - Initialize( - LogLevel level, - LogType type, - const std::string& file, - const std::string& nickname, - std::function io); - }; - - /// RAII type to turn logging off - /// logging is suppressed as long as the silencer is in scope - struct LogSilencer - { - LogSilencer(); - ~LogSilencer(); - explicit LogSilencer(LogContext& ctx); - - private: - LogContext& parent; - ILogStream_ptr stream; - }; - - void - SetLogLevel(LogLevel lvl); - - LogLevel - GetLogLevel(); - - namespace - { - /** internal */ - template - inline static void - _log(LogLevel lvl, const slns::source_location& location, TArgs&&... args) noexcept - { - auto& log = LogContext::Instance(); - if (log.curLevel > lvl || log.logStream == nullptr) - return; - std::ostringstream ss; - if constexpr (sizeof...(args) > 0) - LogAppend(ss, std::forward(args)...); - log.logStream->AppendLog( - lvl, - strip_prefix(location.file_name(), SOURCE_ROOT), - location.line(), - log.nodeName, - ss.str()); - } - } // namespace - - template - struct LogTrace - { - LogTrace(T... args, const slns::source_location& location = slns::source_location::current()) - { -#ifdef NDEBUG - ((void)args, ...); - (void)location; -#else - _log(eLogTrace, location, std::forward(args)...); -#endif - } - }; - - template - LogTrace(T&&...) -> LogTrace; - - template - struct LogDebug - { - LogDebug(T... args, const slns::source_location& location = slns::source_location::current()) - { - _log(eLogDebug, location, std::forward(args)...); - } - }; - - template - LogDebug(T&&...) -> LogDebug; - - template - struct LogInfo - { - LogInfo(T... args, const slns::source_location& location = slns::source_location::current()) - { - _log(eLogInfo, location, std::forward(args)...); - } - }; - - template - LogInfo(T&&...) -> LogInfo; - - template - struct LogWarn - { - LogWarn(T... args, const slns::source_location& location = slns::source_location::current()) - { - _log(eLogWarn, location, std::forward(args)...); - } - }; - - template - LogWarn(T&&...) -> LogWarn; - - template - struct LogError - { - LogError(T... args, const slns::source_location& location = slns::source_location::current()) - { - _log(eLogError, location, std::forward(args)...); - } - }; - - template - LogError(T&&...) -> LogError; - -} // namespace llarp diff --git a/llarp/util/logging/logger_internal.cpp b/llarp/util/logging/logger_internal.cpp deleted file mode 100644 index 2cff1a9a1..000000000 --- a/llarp/util/logging/logger_internal.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "logger_internal.hpp" - -#include - -namespace llarp -{ - std::ostream& - operator<<(std::ostream& out, const log_timestamp& ts) - { - std::chrono::time_point now{ - std::chrono::milliseconds{ts.now}}; - return date::operator<<(out, now) << " GMT [+" << ts.delta << "]"; - } -} // namespace llarp diff --git a/llarp/util/logging/logger_internal.hpp b/llarp/util/logging/logger_internal.hpp deleted file mode 100644 index 06f0ac9b9..000000000 --- a/llarp/util/logging/logger_internal.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -namespace llarp -{ - /** internal */ - - // true if T is the same as any of V... - template - constexpr bool is_same_any_v = (std::is_same_v || ...); - - template - void - LogAppend(std::ostringstream& ss, TArg&& arg, TArgs&&... args) noexcept - { - // If you are logging a char/unsigned char/uint8_t then promote it to an integer so that we - // print numeric values rather than std::ostream's default of printing it as a raw char. - using PlainT = std::remove_reference_t; - if constexpr (is_same_any_v) - ss << +std::forward(arg); // Promote to int - else if constexpr (std::is_same_v) - ss << std::to_integer(arg); - else - ss << std::forward(arg); - if constexpr (sizeof...(TArgs) > 0) - LogAppend(ss, std::forward(args)...); - } - - inline std::string - thread_id_string() - { - auto tid = std::this_thread::get_id(); - std::hash h; - uint16_t id = h(tid) % 1000; -#if defined(ANDROID) - char buff[8] = {0}; - snprintf(buff, sizeof(buff), "%u", id); - return buff; -#else - return std::to_string(id); -#endif - } - - struct log_timestamp - { - const char* format; - const Duration_t now; - const Duration_t delta; - - log_timestamp(); - - explicit log_timestamp(const char* fmt); - }; - - std::ostream& - operator<<(std::ostream& out, const log_timestamp& ts); - -} // namespace llarp diff --git a/llarp/util/logging/logger_syslog.hpp b/llarp/util/logging/logger_syslog.hpp deleted file mode 100644 index dee7523de..000000000 --- a/llarp/util/logging/logger_syslog.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "logstream.hpp" -#include - -namespace llarp -{ - struct SysLogStream : public ILogStream - { - void - PreLog( - std::stringstream& s, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const override; - - void - Print(LogLevel lvl, std::string_view tag, const std::string& msg) override; - - void - PostLog(std::stringstream& ss) const override; - - virtual void - ImmediateFlush() override - {} - - void Tick(llarp_time_t) override - {} - }; -} // namespace llarp diff --git a/llarp/util/logging/loglevel.cpp b/llarp/util/logging/loglevel.cpp deleted file mode 100644 index 4faf02d19..000000000 --- a/llarp/util/logging/loglevel.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "loglevel.hpp" -#include -#include - -namespace llarp -{ - std::string - LogLevelToString(LogLevel lvl) - { - switch (lvl) - { - case eLogTrace: - return "TRC"; - case eLogDebug: - return "DBG"; - case eLogInfo: - return "NFO"; - case eLogWarn: - return "WRN"; - case eLogError: - return "ERR"; - default: - return "???"; - } - } - - std::string - LogLevelToName(LogLevel lvl) - { - switch (lvl) - { - case eLogTrace: - return "Trace"; - case eLogDebug: - return "Debug"; - case eLogInfo: - return "Info"; - case eLogWarn: - return "Warn"; - case eLogError: - return "Error"; - case eLogNone: - return "None"; - default: - return "???"; - } - } - - std::optional - LogLevelFromString(std::string level) - { - std::transform(level.begin(), level.end(), level.begin(), [](const unsigned char ch) -> char { - return std::tolower(ch); - }); - static const std::unordered_map levels = { - {"trace", eLogTrace}, - {"debug", eLogDebug}, - {"info", eLogInfo}, - {"warn", eLogWarn}, - {"error", eLogError}, - {"none", eLogNone}}; - - const auto itr = levels.find(level); - if (itr == levels.end()) - return {}; - return itr->second; - } -} // namespace llarp diff --git a/llarp/util/logging/loglevel.hpp b/llarp/util/logging/loglevel.hpp deleted file mode 100644 index adf99f313..000000000 --- a/llarp/util/logging/loglevel.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include -#include - -namespace llarp -{ - // probably will need to move out of llarp namespace for c api - enum LogLevel - { - eLogTrace, - eLogDebug, - eLogInfo, - eLogWarn, - eLogError, - eLogNone - }; - - std::string - LogLevelToString(LogLevel level); - - std::string - LogLevelToName(LogLevel lvl); - - std::optional - LogLevelFromString(std::string level); - -} // namespace llarp diff --git a/llarp/util/logging/logstream.hpp b/llarp/util/logging/logstream.hpp deleted file mode 100644 index d5e00d90d..000000000 --- a/llarp/util/logging/logstream.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include "loglevel.hpp" - -#include - -#include -#include -#include -#include - -namespace llarp -{ - /// logger stream interface - struct ILogStream - { - virtual ~ILogStream() = default; - - virtual void - PreLog( - std::stringstream& out, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const = 0; - - virtual void - Print(LogLevel lvl, std::string_view filename, const std::string& msg) = 0; - - virtual void - PostLog(std::stringstream& out) const = 0; - - virtual void - AppendLog( - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename, - const std::string msg) - { - std::stringstream ss; - PreLog(ss, lvl, filename, lineno, nodename); - ss << msg; - PostLog(ss); - Print(lvl, filename, ss.str()); - } - - /// A blocking call to flush to disk. Should only be called in rare circumstances. - virtual void - ImmediateFlush() = 0; - - /// called every end of event loop tick - virtual void - Tick(llarp_time_t now) = 0; - }; - - using ILogStream_ptr = std::unique_ptr; - -} // namespace llarp diff --git a/llarp/util/logging/ostream_logger.cpp b/llarp/util/logging/ostream_logger.cpp deleted file mode 100644 index 15078e870..000000000 --- a/llarp/util/logging/ostream_logger.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "ostream_logger.hpp" -#include "logger_internal.hpp" - -namespace llarp -{ - OStreamLogStream::OStreamLogStream(bool withColours, std::ostream& out) - : m_withColours(withColours), m_Out(out) - {} - - void - OStreamLogStream::PreLog( - std::stringstream& ss, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const - { - if (m_withColours) - { - switch (lvl) - { - case eLogNone: - return; - case eLogTrace: - case eLogDebug: - ss << (char)27 << "[0m"; - break; - case eLogInfo: - ss << (char)27 << "[1m"; - break; - case eLogWarn: - ss << (char)27 << "[1;33m"; - break; - case eLogError: - ss << (char)27 << "[1;31m"; - break; - } - } - ss << "[" << LogLevelToString(lvl) << "] "; - ss << "[" << nodename << "]" - << "(" << thread_id_string() << ") " << log_timestamp() << " " << filename << ":" << lineno - << "\t"; - } - - void - OStreamLogStream::PostLog(std::stringstream& ss) const - { - if (m_withColours) - ss << (char)27 << "[0;0m"; - ss << std::endl; - } - - void - OStreamLogStream::Print(LogLevel, std::string_view, const std::string& msg) - { - m_Out << msg << std::flush; - } - - void - OStreamLogStream::ImmediateFlush() - { - m_Out << std::flush; - } - -} // namespace llarp diff --git a/llarp/util/logging/ostream_logger.hpp b/llarp/util/logging/ostream_logger.hpp deleted file mode 100644 index 5961447e4..000000000 --- a/llarp/util/logging/ostream_logger.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "logstream.hpp" -#include - -namespace llarp -{ - struct OStreamLogStream : public ILogStream - { - OStreamLogStream(bool withColours, std::ostream& out); - - ~OStreamLogStream() override = default; - - void - PreLog( - std::stringstream& s, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const override; - - virtual void - Print(LogLevel lvl, std::string_view tag, const std::string& msg) override; - - void - PostLog(std::stringstream& ss) const override; - - virtual void - ImmediateFlush() override; - - void Tick(llarp_time_t) override - {} - - private: - bool m_withColours; - std::ostream& m_Out; - }; -} // namespace llarp diff --git a/llarp/util/logging/source_location.hpp b/llarp/util/logging/source_location.hpp deleted file mode 100644 index 39b707a30..000000000 --- a/llarp/util/logging/source_location.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#ifdef __cpp_lib_source_location -#include -namespace slns = std; -#else -#include -namespace slns -{ - struct source_location - { - public: - static constexpr source_location - current( - const char* fileName = __builtin_FILE(), - const char* functionName = __builtin_FUNCTION(), - const uint_least32_t lineNumber = __builtin_LINE()) noexcept - { - return source_location{fileName, functionName, lineNumber}; - } - - source_location(const source_location&) = default; - source_location(source_location&&) = default; - - constexpr const char* - file_name() const noexcept - { - return fileName; - } - - constexpr const char* - function_name() const noexcept - { - return functionName; - } - - constexpr uint_least32_t - line() const noexcept - { - return lineNumber; - } - - private: - constexpr explicit source_location( - const char* fileName, const char* functionName, const uint_least32_t lineNumber) noexcept - : fileName(fileName), functionName(functionName), lineNumber(lineNumber) - {} - - const char* const fileName; - const char* const functionName; - const uint_least32_t lineNumber; - }; -} // namespace slns -#endif diff --git a/llarp/util/logging/syslog_logger.cpp b/llarp/util/logging/syslog_logger.cpp deleted file mode 100644 index feb124806..000000000 --- a/llarp/util/logging/syslog_logger.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _WIN32 -#include "logger_syslog.hpp" - -#include "logger_internal.hpp" - -#include -namespace llarp -{ - void - SysLogStream::PreLog( - std::stringstream& ss, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const - { - ss << "[" << LogLevelToString(lvl) << "] "; - ss << "[" << nodename << "]" - << "(" << thread_id_string() << ") " << log_timestamp() << " " << filename << ":" << lineno - << "\t"; - } - - void - SysLogStream::Print(LogLevel lvl, std::string_view, const std::string& msg) - { - switch (lvl) - { - case eLogNone: - return; - case eLogTrace: - case eLogDebug: - ::syslog(LOG_DEBUG, "%s", msg.c_str()); - return; - case eLogInfo: - ::syslog(LOG_INFO, "%s", msg.c_str()); - return; - case eLogWarn: - ::syslog(LOG_WARNING, "%s", msg.c_str()); - return; - case eLogError: - ::syslog(LOG_ERR, "%s", msg.c_str()); - return; - } - } - - void - SysLogStream::PostLog(std::stringstream&) const - {} - -} // namespace llarp -#endif diff --git a/llarp/util/logging/win32_logger.cpp b/llarp/util/logging/win32_logger.cpp deleted file mode 100644 index 0792f8d92..000000000 --- a/llarp/util/logging/win32_logger.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "win32_logger.hpp" -#include "logger_internal.hpp" - -static CONSOLE_SCREEN_BUFFER_INFO consoleInfo; -static short old_attrs; - -namespace llarp -{ - Win32LogStream::Win32LogStream(std::ostream& out) : OStreamLogStream(true, out), m_Out(out) - { - // Attempt to use ANSI escapes directly - // if the modern console is active. - DWORD mode_flags; - - GetConsoleMode(fd1, &mode_flags); - // since release SDKs don't have ANSI escape support yet - // we get all or nothing: if we can't get it, then we wouldn't - // be able to get any of them individually - mode_flags |= 0x0004 | 0x0008; - BOOL t = SetConsoleMode(fd1, mode_flags); - if (!t) - this->isConsoleModern = false; // fall back to setting colours manually - } - - void - Win32LogStream::PreLog( - std::stringstream& ss, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const - { - if (!isConsoleModern) - { - switch (lvl) - { - case eLogNone: - break; - case eLogTrace: - ss << "[TRC] "; - break; - case eLogDebug: - ss << "[DBG] "; - break; - case eLogInfo: - ss << "[NFO] "; - break; - case eLogWarn: - ss << "[WRN] "; - break; - case eLogError: - ss << "[ERR] "; - break; - } - ss << "[" << nodename << "]" - << "(" << thread_id_string() << ") " << log_timestamp() << " " << filename << ":" << lineno - << "\t"; - } - else - OStreamLogStream::PreLog(ss, lvl, filename, lineno, nodename); - } - - void - Win32LogStream::PostLog(std::stringstream& ss) const - { - if (!isConsoleModern) - ss << std::endl; - else - OStreamLogStream::PostLog(ss); - } - - void - Win32LogStream::Print(LogLevel lvl, std::string_view, const std::string& msg) - { - if (!isConsoleModern) - { - GetConsoleScreenBufferInfo(fd1, &consoleInfo); - old_attrs = consoleInfo.wAttributes; - switch (lvl) - { - case eLogNone: - break; - case eLogTrace: - case eLogDebug: - SetConsoleTextAttribute( - fd1, - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); // low white on black - break; - case eLogInfo: - SetConsoleTextAttribute( - fd1, - FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN - | FOREGROUND_BLUE); // high white on black - break; - case eLogWarn: - SetConsoleTextAttribute( - fd1, - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // bright yellow - break; - case eLogError: - SetConsoleTextAttribute(fd1, FOREGROUND_RED | FOREGROUND_INTENSITY); // bright red - break; - } - } - - m_Out << msg << std::flush; - - if (!isConsoleModern) - { - SetConsoleTextAttribute(fd1, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - } - } - -} // namespace llarp diff --git a/llarp/util/logging/win32_logger.hpp b/llarp/util/logging/win32_logger.hpp deleted file mode 100644 index 2be5e5609..000000000 --- a/llarp/util/logging/win32_logger.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#if defined(_WIN32) -#include "ostream_logger.hpp" -#define VC_EXTRALEAN -#include - -namespace llarp -{ - struct Win32LogStream : public OStreamLogStream - { - Win32LogStream(std::ostream& out); - - void - PreLog( - std::stringstream& s, - LogLevel lvl, - std::string_view filename, - int lineno, - const std::string& nodename) const override; - - void - PostLog(std::stringstream& s) const override; - - void Tick(llarp_time_t) override{}; - - void - Print(LogLevel lvl, std::string_view, const std::string& msg) override; - - private: - std::ostream& m_Out; - - bool isConsoleModern = true; // qol fix so oldfag clients don't see ugly escapes - - HANDLE fd1 = GetStdHandle(STD_OUTPUT_HANDLE); - }; -} // namespace llarp -#endif diff --git a/llarp/util/str.hpp b/llarp/util/str.hpp index 1e564b6cf..ce330dac1 100644 --- a/llarp/util/str.hpp +++ b/llarp/util/str.hpp @@ -26,26 +26,6 @@ namespace llarp [[nodiscard]] std::string_view TrimWhitespace(std::string_view str); - template - std::string - stringify(T&&... stuff) - { - std::ostringstream o; - (o << ... << std::forward(stuff)); - return o.str(); - } - - /// util for constructing an exception with a message constructed from a set of whatever passed - /// into stringify - /// E must be derived from std::exception here - template - E - make_exception(T&&... stuff) - { - static_assert(std::is_base_of_v); - return E{stringify(std::forward(stuff)...)}; - } - using namespace std::literals; /// Returns true if the first string is equal to the second string, compared case-insensitively. @@ -68,21 +48,21 @@ namespace llarp } /// Returns true if the first argument begins with the second argument - inline bool + inline constexpr bool starts_with(std::string_view str, std::string_view prefix) { return str.substr(0, prefix.size()) == prefix; } /// Returns true if the first argument ends with the second argument - inline bool + inline constexpr bool ends_with(std::string_view str, std::string_view suffix) { return str.size() >= suffix.size() && str.substr(str.size() - suffix.size()) == suffix; } /// removes a prefix from a string if it exists - inline std::string_view + inline constexpr std::string_view strip_prefix(std::string_view str, std::string_view prefix) { if (starts_with(str, prefix)) diff --git a/llarp/util/thread/queue_manager.hpp b/llarp/util/thread/queue_manager.hpp index 9761b1012..f202b4ad9 100644 --- a/llarp/util/thread/queue_manager.hpp +++ b/llarp/util/thread/queue_manager.hpp @@ -28,26 +28,22 @@ namespace llarp QueueFull }; - inline std::ostream& - operator<<(std::ostream& os, QueueReturn val) + constexpr std::string_view + ToString(QueueReturn val) { + using namespace std::literals; switch (val) { case QueueReturn::Success: - os << "Success"; - break; + return "Success"sv; case QueueReturn::QueueDisabled: - os << "QueueDisabled"; - break; + return "QueueDisabled"sv; case QueueReturn::QueueEmpty: - os << "QueueEmpty"; - break; + return "QueueEmpty"sv; case QueueReturn::QueueFull: - os << "QueueFull"; - break; + return "QueueFull"sv; } - - return os; + return "(queue-return-unknown)"sv; } class QueueManager diff --git a/llarp/util/thread/threading.cpp b/llarp/util/thread/threading.cpp index 826177ef9..84710e9d0 100644 --- a/llarp/util/thread/threading.cpp +++ b/llarp/util/thread/threading.cpp @@ -1,6 +1,6 @@ #include "threading.hpp" -#include +#include #include #ifdef POSIX diff --git a/llarp/util/time.cpp b/llarp/util/time.cpp index cd6a3b4fd..46d9a5fa4 100644 --- a/llarp/util/time.cpp +++ b/llarp/util/time.cpp @@ -49,40 +49,4 @@ namespace llarp { return ToMS(t); } - - std::ostream& - operator<<(std::ostream& out, const Duration_t& t) - { - std::chrono::milliseconds amount{ToMS(t)}; - auto h = std::chrono::duration_cast(amount); - amount -= h; - auto m = std::chrono::duration_cast(amount); - amount -= m; - auto s = std::chrono::duration_cast(amount); - amount -= s; - auto ms = amount; - auto old_fill = out.fill('0'); - if (h > 0h) - { - out << h.count() << 'h'; - out.width(2); // 0-fill minutes if we have hours - } - if (h > 0h || m > 0min) - { - out << m.count() << 'm'; - out.width(2); // 0-fill seconds if we have minutes - } - out << s.count() << '.'; - out.width(3); - out << ms.count(); - out.fill(old_fill); - return out << "s"; - } - - std::ostream& - operator<<(std::ostream& out, const TimePoint_t& tp) - { - auto t = TimePoint_t::clock::to_time_t(tp); - return out << std::put_time(std::localtime(&t), "%c %Z"); - } } // namespace llarp diff --git a/llarp/util/time.hpp b/llarp/util/time.hpp index abd725f05..fbf999773 100644 --- a/llarp/util/time.hpp +++ b/llarp/util/time.hpp @@ -3,6 +3,8 @@ #include "types.hpp" #include #include +#include +#include using namespace std::chrono_literals; @@ -20,42 +22,72 @@ namespace llarp uint64_t ToMS(Duration_t duration); - std::ostream& - operator<<(std::ostream& out, const Duration_t& t); - nlohmann::json to_json(const Duration_t& t); - std::ostream& - operator<<(std::ostream& out, const TimePoint_t& t); - template struct time_delta { const TimePoint_t at; + }; +} // namespace llarp - std::ostream& - operator()(std::ostream& out) const +namespace fmt +{ + template + struct formatter> : formatter + { + template + auto + format(const llarp::time_delta& td, FormatContext& ctx) { - const auto dlt = std::chrono::duration_cast(TimePoint_t::clock::now() - at); + const auto dlt = + std::chrono::duration_cast(llarp::TimePoint_t::clock::now() - td.at); + using Parent = formatter; if (dlt > 0s) - return out << std::chrono::duration_cast(dlt) << " ago "; - else if (dlt < 0s) - return out << "in " << std::chrono::duration_cast(-dlt); - else - return out << "now"; + return Parent::format(fmt::format("{} ago", dlt), ctx); + if (dlt < 0s) + return Parent::format(fmt::format("in {}", -dlt), ctx); + return Parent::format("now", ctx); } }; - inline std::ostream& - operator<<(std::ostream& out, const time_delta& td) + template <> + struct formatter : formatter { - return td(out); - } + template + auto + format(llarp::Duration_t elapsed, FormatContext& ctx) + { + bool neg = elapsed < 0s; + if (neg) + elapsed = -elapsed; + const auto hours = std::chrono::duration_cast(elapsed).count(); + const auto mins = (std::chrono::duration_cast(elapsed) % 1h).count(); + const auto secs = (std::chrono::duration_cast(elapsed) % 1min).count(); + const auto ms = (std::chrono::duration_cast(elapsed) % 1s).count(); + return formatter::format( + fmt::format( + elapsed >= 1h ? "{0}{1:d}h{2:02d}m{3:02d}.{4:03d}s" + : elapsed >= 1min ? "{0}{2:d}m{3:02d}.{4:03d}s" + : "{0}{3:d}.{4:03d}s", + neg ? "-" : "", + hours, + mins, + secs, + ms), + ctx); + } + }; - inline std::ostream& - operator<<(std::ostream& out, const time_delta& td) + template <> + struct formatter : formatter { - return td(out); - } -} // namespace llarp + template + auto + format(const llarp::TimePoint_t& tp, FormatContext& ctx) + { + return formatter::format(fmt::format("{:%c %Z}", tp), ctx); + } + }; +} // namespace fmt