From 35200a1ee52aae5ac349ce2c0299b05edfa46fb3 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 20 Jan 2016 00:00:00 +0000 Subject: [PATCH 01/32] + new cmdline & config impl --- Config.cpp | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Config.h | 100 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 Config.cpp create mode 100644 Config.h diff --git a/Config.cpp b/Config.cpp new file mode 100644 index 00000000..4e6f52d3 --- /dev/null +++ b/Config.cpp @@ -0,0 +1,137 @@ +/* +* Copyright (c) 2013-2016, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Config.h" +#include "version.h" + +using namespace boost::program_options; + +namespace i2p { +namespace config { + options_description m_OptionsDesc; + variables_map m_Options; + + void Init() { + options_description general("General options"); + general.add_options() + ("help,h", "Show this message") + ("conf,c", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf)") + ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") + ("pidfile", value()->default_value(""), "Write pidfile to given path") + ("log", value()->zero_tokens(), "Write logs to file instead stdout") + ("loglevel", value()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") + ("host", value()->default_value(""), "External IP (deprecated)") + ("port,p", value()->default_value(4567), "Port to listen for incoming connections") + ("ipv6,6", value()->zero_tokens(), "Enable communication through ipv6") + ("daemon", value()->zero_tokens(), "Router will go to background after start") + ("service", value()->zero_tokens(), "Router will use system folders like '/var/lib/i2pd'") + ("notransit", value()->zero_tokens(), "Router will not forward transit traffic") + ("floodfill", value()->zero_tokens(), "Router will try to become floodfill") + ("bandwidth", value()->default_value('O'), "Bandwidth limiting: L - 32kbps, O - 256Kbps, P - unlimited") + ; + + options_description httpserver("HTTP Server options"); + httpserver.add_options() + ("http.enabled", value()->default_value(true), "Enable or disable webconsole") + ("http.address", value()->default_value("127.0.0.1"), "Webconsole listen address") + ("http.port", value()->default_value(7070), "Webconsole listen port") + ; + + options_description httpproxy("HTTP Proxy options"); + httpproxy.add_options() + ("httpproxy.enabled", value()->default_value(true), "Enable or disable HTTP Proxy") + ("httpproxy.address", value()->default_value("127.0.0.1"), "HTTP Proxy listen address") + ("httpproxy.port", value()->default_value(4446), "HTTP Proxy listen port") + ("httpproxy.keys", value()->default_value("httpproxy-keys.dat"), "HTTP Proxy encryption keys") + ; + + options_description socksproxy("SOCKS Proxy options"); + socksproxy.add_options() + ("socksproxy.enabled", value()->default_value(true), "Enable or disable SOCKS Proxy") + ("socksproxy.address", value()->default_value("127.0.0.1"), "SOCKS Proxy listen address") + ("socksproxy.port", value()->default_value(4447), "SOCKS Proxy listen port") + ("socksproxy.keys", value()->default_value("socksproxy-keys.dat"), "SOCKS Proxy encryption keys") + ; + + options_description sam("SAM bridge options"); + sam.add_options() + ("sam.enabled", value()->default_value(false), "Enable or disable SAM Application bridge") + ("sam.address", value()->default_value("127.0.0.1"), "SAM listen address") + ("sam.port", value()->default_value(7656), "SAM listen port") + ; + + options_description bob("BOB options"); + bob.add_options() + ("bob.enabled", value()->default_value(false), "Enable or disable BOB command channel") + ("bob.address", value()->default_value("127.0.0.1"), "BOB listen address") + ("bob.port", value()->default_value(2827), "BOB listen port") + ; + + options_description i2pcontrol("I2PControl options"); + i2pcontrol.add_options() + ("i2pcontrol.enabled", value()->default_value(false), "Enable or disable I2P Control Protocol") + ("i2pcontrol.address", value()->default_value("127.0.0.1"), "I2PCP listen address") + ("i2pcontrol.port", value()->default_value(7650), "I2PCP listen port") + ; + + m_OptionsDesc + .add(general) + .add(httpserver) + .add(httpproxy) + .add(socksproxy) + .add(sam) + .add(bob) + .add(i2pcontrol) + ; + } + + void ParseCmdline(int argc, char* argv[]) { + try { + store(parse_command_line(argc, argv, m_OptionsDesc), m_Options); + } catch (boost::program_options::error e) { + std::cerr << "args: " << e.what() << std::endl; + exit(EXIT_FAILURE); + } + + if (m_Options.count("help")) { + std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; + std::cout << m_OptionsDesc; + exit(EXIT_SUCCESS); + } + } + + void ParseConfig(const std::string& path) { + std::ifstream config(path, std::ios::in); + + if (!config.is_open()) { + std::cerr << "missing/unreadable config file: " << path << std::endl; + exit(EXIT_FAILURE); + } + + try { + store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options); + } catch (boost::program_options::error e) { + std::cerr << e.what() << std::endl; + exit(EXIT_FAILURE); + }; + } + + void Finalize() { + notify(m_Options); + }; +} // namespace config +} // namespace i2p diff --git a/Config.h b/Config.h new file mode 100644 index 00000000..5418022a --- /dev/null +++ b/Config.h @@ -0,0 +1,100 @@ +#ifndef CONFIG_H__ +#define CONFIG_H__ + +#include +#include +#include + +/** + * Functions to parse and store i2pd parameters + * + * General usage flow: + * Init() -- early as possible + * ParseCmdline() -- somewhere close to main() + * ParseConfig() -- after detecting path to config + * Finalize() -- right after all Parse*() functions called + * GetOption() -- may be called after Finalize() + */ + +namespace i2p { +namespace config { + extern boost::program_options::variables_map m_Options; + + /** + * @brief Initialize list of acceptable parameters + * + * Should be called before any Parse* functions. + */ + void Init(); + + /** + * @brief Parse cmdline parameters, and show help if requested + * @param argc Cmdline arguments count, should be passed from main(). + * @param argv Cmdline parameters array, should be passed from main() + * + * If --help is given in parameters, shows it's list with description + * terminates the program with exitcode 0. + * + * In case of parameter misuse boost throws an exception. + * We internally handle type boost::program_options::unknown_option, + * and then terminate program with exitcode 1. + * + * Other exceptions will be passed to higher level. + */ + void ParseCmdline(int argc, char* argv[]); + + /** + * @brief Load and parse given config file + * @param path Path to config file + * + * If error occured when opening file path is points to, + * we show the error message and terminate program. + * + * In case of parameter misuse boost throws an exception. + * We internally handle type boost::program_options::unknown_option, + * and then terminate program with exitcode 1. + * + * Other exceptions will be passed to higher level. + */ + void ParseConfig(const std::string& path); + + /** + * @brief Used to combine options from cmdline, config and default values + */ + void Finalize(); + + /* @brief Accessor to parameters by name + * @param name Name of the requested parameter + * @param value Variable where to store option + * @return this function returns false if parameter not found + * + * @example uint16_t port; GetOption("sam.port", port); + */ + template + bool GetOption(const char *name, T& value) { + if (!m_Options.count(name)) + return false; + value = m_Options[name].as(); + return true; + } + + /** + * @brief Set value of given parameter + * @param name Name of settable parameter + * @param value New parameter value + * @return true if value set up successful, false otherwise + * + * @example uint16_t port = 2827; SetOption("bob.port", port); + */ + template + bool SetOption(const char *name, const T& value) { + if (!m_Options.count(name)) + return false; + m_Options[name] = value; + notify(m_Options); + return true; + } +} +} + +#endif // CONFIG_H__ From 209934ad675357fa3078a7c9ba62b995266ca763 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 20 Jan 2016 00:00:00 +0000 Subject: [PATCH 02/32] * update buildsystems to include Config.cpp --- build/CMakeLists.txt | 1 + filelist.mk | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index cbcfc275..71ce57ad 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -17,6 +17,7 @@ set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" ) set ( CMAKE_SOURCE_DIR ".." ) set (LIBI2PD_SRC + "${CMAKE_SOURCE_DIR}/Config.cpp" "${CMAKE_SOURCE_DIR}/Crypto.cpp" "${CMAKE_SOURCE_DIR}/Garlic.cpp" "${CMAKE_SOURCE_DIR}/I2NPProtocol.cpp" diff --git a/filelist.mk b/filelist.mk index 147ef259..ce3a12f5 100644 --- a/filelist.mk +++ b/filelist.mk @@ -8,9 +8,9 @@ LIB_SRC = \ LIB_CLIENT_SRC = \ AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \ - SAM.cpp SOCKS.cpp HTTPProxy.cpp + SAM.cpp SOCKS.cpp HTTPProxy.cpp Config.cpp # also: Daemon{Linux,Win32}.cpp will be added later DAEMON_SRC = \ - HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp + HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp Config.cpp i2pd.cpp From 2335d3879e009613bfe13f432c5502de207258a9 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 20 Jan 2016 00:00:00 +0000 Subject: [PATCH 03/32] * migrate to new settings --- ClientContext.cpp | 65 ++++++++++++++++++++++++----------------- Config.h | 6 ++-- Daemon.cpp | 74 ++++++++++++++++++++++++++--------------------- DaemonLinux.cpp | 6 ++-- DaemonWin32.cpp | 3 +- RouterContext.cpp | 8 +++-- api.cpp | 5 +++- util.cpp | 19 ++++++++---- 8 files changed, 109 insertions(+), 77 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 4e189f26..57ccc32e 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "Config.h" #include "util.h" #include "Log.h" #include "Identity.h" @@ -37,44 +38,56 @@ namespace client } std::shared_ptr localDestination; - // proxies - std::string proxyKeys = i2p::util::config::GetArg("-proxykeys", ""); - if (proxyKeys.length () > 0) - { - i2p::data::PrivateKeys keys; - LoadPrivateKeys (keys, proxyKeys); - localDestination = CreateNewLocalDestination (keys, false); + bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); + if (httproxy) { + std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); + std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); + uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); + LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); + if (httpProxyKeys.length () > 0) + { + i2p::data::PrivateKeys keys; + LoadPrivateKeys (keys, httpProxyKeys); + localDestination = CreateNewLocalDestination (keys, false); + } + m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); + m_HttpProxy->Start(); } - std::string httpProxyAddr = i2p::util::config::GetArg("-httpproxyaddress", "127.0.0.1"); - uint16_t httpProxyPort = i2p::util::config::GetArg("-httpproxyport", 4446); - LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); - m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); - m_HttpProxy->Start(); - std::string socksProxyAddr = i2p::util::config::GetArg("-socksproxyaddress", "127.0.0.1"); - uint16_t socksProxyPort = i2p::util::config::GetArg("-socksproxyport", 4447); - LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort); - m_SocksProxy = new i2p::proxy::SOCKSProxy(socksProxyAddr, socksProxyPort, localDestination); - m_SocksProxy->Start(); + bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); + if (socksproxy) { + std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); + std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr); + uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort); + LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort); + if (socksProxyKeys.length () > 0) + { + i2p::data::PrivateKeys keys; + LoadPrivateKeys (keys, socksProxyKeys); + localDestination = CreateNewLocalDestination (keys, false); + } + m_SocksProxy = new i2p::proxy::SOCKSProxy(socksProxyAddr, socksProxyPort, localDestination); + m_SocksProxy->Start(); + } // I2P tunnels ReadTunnels (); // SAM - std::string samAddr = i2p::util::config::GetArg("-samaddress", "127.0.0.1"); - uint16_t samPort = i2p::util::config::GetArg("-samport", 0); - if (samPort) - { - LogPrint(eLogInfo, "Clients: starting SAM bridge at", samAddr, ":", samPort); + bool sam; i2p::config::GetOption("sam.enabled", sam); + if (sam) { + std::string samAddr; i2p::config::GetOption("sam.address", samAddr); + uint16_t samPort; i2p::config::GetOption("sam.port", samPort); + LogPrint(eLogInfo, "Clients: starting SAM bridge at ", samAddr, ":", samPort); m_SamBridge = new SAMBridge (samAddr, samPort); m_SamBridge->Start (); } // BOB - std::string bobAddr = i2p::util::config::GetArg("-bobaddress", "127.0.0.1"); - uint16_t bobPort = i2p::util::config::GetArg("-bobport", 0); - if (bobPort) - { + bool bob; i2p::config::GetOption("bob.enabled", bob); + if (bob) { + std::string bobAddr; i2p::config::GetOption("bob.address", bobAddr); + uint16_t bobPort; i2p::config::GetOption("bob.port", bobPort); LogPrint(eLogInfo, "Clients: starting BOB command channel at ", bobAddr, ":", bobPort); m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort); m_BOBCommandChannel->Start (); diff --git a/Config.h b/Config.h index 5418022a..51a12d70 100644 --- a/Config.h +++ b/Config.h @@ -1,5 +1,5 @@ -#ifndef CONFIG_H__ -#define CONFIG_H__ +#ifndef CONFIG_H +#define CONFIG_H #include #include @@ -97,4 +97,4 @@ namespace config { } } -#endif // CONFIG_H__ +#endif // CONFIG_H diff --git a/Daemon.cpp b/Daemon.cpp index 1415435a..8530b93e 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -3,6 +3,7 @@ #include "Daemon.h" +#include "Config.h" #include "Log.h" #include "Base.h" #include "version.h" @@ -50,52 +51,55 @@ namespace i2p bool Daemon_Singleton::IsService () const { + bool service = false; #ifndef _WIN32 - return i2p::util::config::GetArg("-service", 0); -#else - return false; + i2p::config::GetOption("service", service); #endif + return service; } bool Daemon_Singleton::init(int argc, char* argv[]) { + i2p::config::Init(); + i2p::config::ParseCmdline(argc, argv); + i2p::config::ParseConfig(i2p::util::filesystem::GetConfigFile().string()); + i2p::config::Finalize(); + i2p::crypto::InitCrypto (); - i2p::util::config::OptionParser(argc, argv); i2p::context.Init (); LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); LogPrint(eLogDebug, "FS: data directory: ", i2p::util::filesystem::GetDataDir().string()); - i2p::util::config::ReadConfigFile(i2p::util::filesystem::GetConfigFile()); - isDaemon = i2p::util::config::GetArg("-daemon", 0); - isLogging = i2p::util::config::GetArg("-log", 1); + i2p::config::GetOption("daemon", isDaemon); + i2p::config::GetOption("log", isLogging); - int port = i2p::util::config::GetArg("-port", 0); + uint16_t port; i2p::config::GetOption("port", port); if (port) i2p::context.UpdatePort (port); - std::string host = i2p::util::config::GetArg("-host", ""); + std::string host; i2p::config::GetOption("host", host); if (host != "") i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host)); - i2p::context.SetSupportsV6 (i2p::util::config::GetArg("-v6", 0)); - i2p::context.SetAcceptsTunnels (!i2p::util::config::GetArg("-notransit", 0)); - bool isFloodfill = i2p::util::config::GetArg("-floodfill", 0); + bool ipv6; i2p::config::GetOption("ipv6", ipv6); + bool transit; i2p::config::GetOption("notransit", transit); + i2p::context.SetSupportsV6 (ipv6); + i2p::context.SetAcceptsTunnels (!transit); + + bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); i2p::context.SetFloodfill (isFloodfill); - auto bandwidth = i2p::util::config::GetArg("-bandwidth", ""); - if (bandwidth.length () > 0) + + char bandwidth; i2p::config::GetOption("bandwidth", bandwidth); + if (bandwidth != '-') { - if (bandwidth[0] > 'O') - i2p::context.SetExtraBandwidth (); - else if (bandwidth[0] > 'L') - i2p::context.SetHighBandwidth (); - else - i2p::context.SetLowBandwidth (); + switch (bandwidth) { + case 'P' : i2p::context.SetExtraBandwidth (); break; + case 'L' : i2p::context.SetHighBandwidth (); break; + default : i2p::context.SetLowBandwidth (); break; + } } else if (isFloodfill) i2p::context.SetExtraBandwidth (); - LogPrint(eLogDebug, "Daemon: CMD parameters:"); - for (int i = 0; i < argc; ++i) - LogPrint(eLogDebug, i, ": ", argv[i]); return true; } @@ -117,14 +121,18 @@ namespace i2p } else { StartLog (""); // write to stdout } - g_Log->SetLogLevel(i2p::util::config::GetArg("-loglevel", "info")); + std::string loglevel; i2p::config::GetOption("loglevel", loglevel); + g_Log->SetLogLevel(loglevel); } - std::string httpAddr = i2p::util::config::GetArg("-httpaddress", "127.0.0.1"); - uint16_t httpPort = i2p::util::config::GetArg("-httpport", 7070); - LogPrint(eLogInfo, "Daemon: staring HTTP Server at ", httpAddr, ":", httpPort); - d.httpServer = std::unique_ptr(new i2p::util::HTTPServer(httpAddr, httpPort)); - d.httpServer->Start(); + bool http; i2p::config::GetOption("http.enabled", http); + if (http) { + std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); + uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); + LogPrint(eLogInfo, "Daemon: staring HTTP Server at ", httpAddr, ":", httpPort); + d.httpServer = std::unique_ptr(new i2p::util::HTTPServer(httpAddr, httpPort)); + d.httpServer->Start(); + } LogPrint(eLogInfo, "Daemon: starting NetDB"); i2p::data::netdb.Start(); @@ -143,10 +151,10 @@ namespace i2p i2p::client::context.Start (); // I2P Control Protocol - std::string i2pcpAddr = i2p::util::config::GetArg("-i2pcontroladdress", "127.0.0.1"); - uint16_t i2pcpPort = i2p::util::config::GetArg("-i2pcontrolport", 0); - if (i2pcpPort) - { + bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); + if (i2pcontrol) { + std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr); + uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort); LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort); d.m_I2PControlService = std::unique_ptr(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort)); d.m_I2PControlService->Start (); diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 306fc7ca..89df5306 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -8,10 +8,10 @@ #include #include +#include "Config.h" #include "Log.h" #include "util.h" - void handle_signal(int sig) { switch (sig) @@ -28,7 +28,6 @@ void handle_signal(int sig) } } - namespace i2p { namespace util @@ -74,7 +73,7 @@ namespace i2p // Pidfile // this code is c-styled and a bit ugly, but we need fd for locking pidfile - pidfile = i2p::util::config::GetArg("-pidfile", ""); + std::string pidfile; i2p::config::GetOption("pidfile", pidfile); if (pidfile == "") { pidfile = IsService () ? "/var/run" : i2p::util::filesystem::GetDataDir().string(); pidfile.append("/i2pd.pid"); @@ -120,7 +119,6 @@ namespace i2p return Daemon_Singleton::stop(); } - } } diff --git a/DaemonWin32.cpp b/DaemonWin32.cpp index e09bf077..4ab65040 100644 --- a/DaemonWin32.cpp +++ b/DaemonWin32.cpp @@ -1,3 +1,4 @@ +#include "Config.h" #include "Daemon.h" #include "util.h" #include "Log.h" @@ -23,7 +24,7 @@ namespace i2p else isDaemon = 0; - std::string serviceControl = i2p::util::config::GetArg("-svcctl", ""); + std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl); if (serviceControl == "install") { LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service"); diff --git a/RouterContext.cpp b/RouterContext.cpp index 7d35ccf1..db6f1c71 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -1,5 +1,6 @@ #include #include +#include "Config.h" #include "Crypto.h" #include "Timestamp.h" #include "I2NPProtocol.h" @@ -43,11 +44,12 @@ namespace i2p { i2p::data::RouterInfo routerInfo; routerInfo.SetRouterIdentity (GetIdentity ()); - int port = i2p::util::config::GetArg("-port", 0); + uint16_t port; i2p::config::GetOption("port", port); if (!port) port = rand () % (30777 - 9111) + 9111; // I2P network ports range - routerInfo.AddSSUAddress (i2p::util::config::GetArg("-host", "127.0.0.1").c_str (), port, routerInfo.GetIdentHash ()); - routerInfo.AddNTCPAddress (i2p::util::config::GetArg("-host", "127.0.0.1").c_str (), port); + std::string host; i2p::config::GetOption("host", host); + routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); + routerInfo.AddNTCPAddress (host.c_str(), port); routerInfo.SetCaps (i2p::data::RouterInfo::eReachable | i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC routerInfo.SetProperty ("coreVersion", I2P_VERSION); diff --git a/api.cpp b/api.cpp index 9a9c5c46..cd527550 100644 --- a/api.cpp +++ b/api.cpp @@ -1,5 +1,6 @@ #include #include +#include "Config.h" #include "Log.h" #include "NetDb.h" #include "Transports.h" @@ -18,7 +19,9 @@ namespace api void InitI2P (int argc, char* argv[], const char * appName) { i2p::util::filesystem::SetAppName (appName); - i2p::util::config::OptionParser(argc, argv); + i2p::config::Init (); + i2p::config::ParseCmdline (argc, argv); + i2p::config::Finalize (); i2p::crypto::InitCrypto (); i2p::context.Init (); } diff --git a/util.cpp b/util.cpp index cff2aa75..4d6b203d 100644 --- a/util.cpp +++ b/util.cpp @@ -13,6 +13,7 @@ #include #include #include +#include "Config.h" #include "util.h" #include "Log.h" @@ -166,8 +167,10 @@ namespace filesystem // TODO: datadir parameter is useless because GetDataDir is called before OptionParser // and mapArgs is not initialized yet - /*if (i2p::util::config::mapArgs.count("-datadir")) - path = boost::filesystem::system_complete(i2p::util::config::mapArgs["-datadir"]); + /* + std::string datadir; i2p::config::GetOption("datadir", datadir); + if (datadir != "") + path = boost::filesystem::system_complete(datadir); else */ path = GetDefaultDataDir(); @@ -200,14 +203,17 @@ namespace filesystem boost::filesystem::path GetConfigFile() { - boost::filesystem::path pathConfigFile(i2p::util::config::GetArg("-conf", "i2p.conf")); - if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir() / pathConfigFile; + std::string config; i2p::config::GetOption("conf", config); + boost::filesystem::path pathConfigFile(config); + if (!pathConfigFile.is_complete()) + pathConfigFile = GetDataDir() / pathConfigFile; return pathConfigFile; } boost::filesystem::path GetTunnelsConfigFile() { - boost::filesystem::path pathTunnelsConfigFile(i2p::util::config::GetArg("-tunnelscfg", "tunnels.cfg")); + std::string tunconf; i2p::config::GetOption("tunconf", tunconf); + boost::filesystem::path pathTunnelsConfigFile(tunconf); if (!pathTunnelsConfigFile.is_complete()) pathTunnelsConfigFile = GetDataDir() / pathTunnelsConfigFile; return pathTunnelsConfigFile; @@ -225,7 +231,8 @@ namespace filesystem SHGetFolderPath(NULL, CSIDL_PROFILE, 0, 0, localAppData); return boost::filesystem::path(std::string(localAppData) + "\\" + "." + appName); #else /* UNIX */ - if (i2p::util::config::GetArg("-service", 0)) // use system folder + bool service; i2p::config::GetOption("service", service); + if (service) // use system folder return boost::filesystem::path(std::string ("/var/lib/") + appName); boost::filesystem::path pathRet; char* pszHome = getenv("HOME"); From 1bcc31173896f4b50aeae411ae7b3d1e138a126b Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 20 Jan 2016 00:00:00 +0000 Subject: [PATCH 04/32] - drop i2p::util::config namespace : not used anymore --- util.cpp | 80 -------------------------------------------------------- util.h | 8 ------ 2 files changed, 88 deletions(-) diff --git a/util.cpp b/util.cpp index 4d6b203d..e559d7f9 100644 --- a/util.cpp +++ b/util.cpp @@ -67,86 +67,6 @@ namespace i2p { namespace util { - -namespace config -{ - std::map mapArgs; - - void OptionParser(int argc, const char* const argv[]) - { - mapArgs.clear(); - for (int i = 1; i < argc; i++) - { - std::string strKey (argv[i]); - std::string strValue; - size_t has_data = strKey.find('='); - if (has_data != std::string::npos) - { - strValue = strKey.substr(has_data+1); - strKey = strKey.substr(0, has_data); - } - -#ifdef WIN32 - boost::to_lower(strKey); - if (boost::algorithm::starts_with(strKey, "/")) - strKey = "-" + strKey.substr(1); -#endif - if (strKey[0] != '-') - break; - - mapArgs[strKey] = strValue; - } - - BOOST_FOREACH(PAIRTYPE(const std::string,std::string)& entry, mapArgs) - { - std::string name = entry.first; - - // interpret --foo as -foo (as long as both are not set) - if (name.find("--") == 0) - { - std::string singleDash(name.begin()+1, name.end()); - if (mapArgs.count(singleDash) == 0) - mapArgs[singleDash] = entry.second; - name = singleDash; - } - } - } - - std::string GetArg(const std::string& strArg, const std::string& strDefault) - { - if (mapArgs.count(strArg)) - return mapArgs[strArg]; - return strDefault; - } - - int GetArg(const std::string& strArg, int nDefault) - { - if (mapArgs.count(strArg)) - return atoi(mapArgs[strArg].c_str()); - return nDefault; - } - - void ReadConfigFile(boost::filesystem::path path) - { - boost::filesystem::ifstream streamConfig(path); - if (!streamConfig.good()) - return; // No i2pd.conf file is OK - - std::set setOptions; - setOptions.insert("*"); - - for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it) - { - // Don't overwrite existing settings so command line settings override i2pd.conf - std::string strKey = std::string("-") + it->string_key; - if (mapArgs.count(strKey) == 0) - { - mapArgs[strKey] = it->value[0]; - } - } - } -} - namespace filesystem { std::string appName ("i2pd"); diff --git a/util.h b/util.h index 905c2a8d..0377ef8d 100644 --- a/util.h +++ b/util.h @@ -14,14 +14,6 @@ namespace i2p { namespace util { - namespace config - { - void OptionParser(int argc, const char* const argv[]); - int GetArg(const std::string& strArg, int nDefault); - std::string GetArg(const std::string& strArg, const std::string& strDefault); - void ReadConfigFile(boost::filesystem::path path); - } - namespace filesystem { void SetAppName (const std::string& name); From 3686a27c19d0b9c9c36b6dbbd71c1bbcff972cb0 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 20 Jan 2016 00:00:00 +0000 Subject: [PATCH 05/32] * update docs/configuration.md --- docs/configuration.md | 75 ++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 7181cc4c..f3b84952 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -4,47 +4,64 @@ i2pd configuration Command line options -------------------- -* --host= - The external IP (deprecated). -* --port= - The port to listen on -* --httpaddress= - The address to listen on (HTTP server) -* --httpport= - The port to listen on (HTTP server) -* --log= - Enable or disable logging to file. 1 for yes, 0 for no. -* --loglevel= - Log messages above this level (debug, *info, warn, error) -* --pidfile= - Where to write pidfile (dont write by default) -* --daemon= - Enable or disable daemon mode. 1 for yes, 0 for no. -* --svcctl= - Windows service management (--svcctl="install" or --svcctl="remove") -* --service= - 1 if uses system folders (/var/run/i2pd.pid, /var/log/i2pd.log, /var/lib/i2pd). -* --v6= - 1 if supports communication through ipv6, off by default -* --floodfill= - 1 if router is floodfill, off by default -* --bandwidth= - L if bandwidth is limited to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited -* --notransit= - 1 if router doesn't accept transit tunnels at startup. 0 by default -* --httpproxyaddress= - The address to listen on (HTTP Proxy) -* --httpproxyport= - The port to listen on (HTTP Proxy) 4446 by default -* --socksproxyaddress= - The address to listen on (SOCKS Proxy) -* --socksproxyport= - The port to listen on (SOCKS Proxy). 4447 by default -* --proxykeys= - optional keys file for proxy local destination (both HTTP and SOCKS) -* --samaddress= - The address to listen on (SAM bridge) -* --samport= - Port of SAM bridge. Usually 7656. SAM is off if not specified -* --bobaddress= - The address to listen on (BOB command channel) -* --bobport= - Port of BOB command channel. Usually 2827. BOB is off if not specified -* --i2pcontroladdress= - The address to listen on (I2P control service) -* --i2pcontrolport= - Port of I2P control service. Usually 7650. I2PControl is off if not specified -* --tunnelscfg= - Tunnels Config file (default: ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg) * --conf= - Config file (default: ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf) This parameter will be silently ignored if the specified config file does not exist. Options specified on the command line take precedence over those in the config file. +* --tunconf= - Tunnels Config file (default: ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg) +* --pidfile= - Where to write pidfile (dont write by default) +* --log - Enable or disable logging to file. 1 for yes, 0 for no. +* --loglevel= - Log messages above this level (debug, *info, warn, error) +* --host= - The external IP (deprecated) +* --port= - The port to listen on +* --daemon - Enable or disable daemon mode. 1 for yes, 0 for no. +* --svcctl= - Windows service management (--svcctl="install" or --svcctl="remove") +* --service - Use system folders (/var/run/i2pd.pid, /var/log/i2pd.log, /var/lib/i2pd). +* --ipv6 - Enable communication through ipv6, off by default +* --notransit - Router will not accept transit tunnels at startup. 0 by default +* --floodfill - Router will be floodfill, off by default +* --bandwidth= - L if bandwidth is limited to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited + +* --http.address= - The address to listen on (HTTP server) +* --http.port= - The port to listen on (HTTP server) + +* --httpproxy.address= - The address to listen on (HTTP Proxy) +* --httpproxy.port= - The port to listen on (HTTP Proxy) 4446 by default +* --httpproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS) + +* --socksproxy.address= - The address to listen on (SOCKS Proxy) +* --socksproxy.port= - The port to listen on (SOCKS Proxy). 4447 by default +* --socksproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS) + +* --sam.address= - The address to listen on (SAM bridge) +* --sam.port= - Port of SAM bridge. Usually 7656. SAM is off if not specified + +* --bob.address= - The address to listen on (BOB command channel) +* --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified + +* --i2pcontrol.address= - The address to listen on (I2P control service) +* --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified Config files ------------ INI-like, syntax is the following : = . Comments are "#", not ";" as you may expect. See [boost ticket](https://svn.boost.org/trac/boost/ticket/808) -All command-line parameters are allowed as keys, for example: +All command-line parameters are allowed as keys, but note for those which contains dot (.). + +For example: i2p.conf: - log = 1 - v6 = 0 + # comment + log = yes + ipv6 = yes + # settings for specific module + [httpproxy] + port = 4444 + # ^^ this will be --httproxy.port= in cmdline + # another one + [sam] + enabled = yes tunnels.cfg (filename of this config is subject of change): From 1f6f4d9c493598635bd4eae40076f3032c1fa3df Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 20 Jan 2016 00:00:00 +0000 Subject: [PATCH 06/32] + docs/config_opts_after_2.3.0.md --- docs/config_opts_after_2.3.0.md | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docs/config_opts_after_2.3.0.md diff --git a/docs/config_opts_after_2.3.0.md b/docs/config_opts_after_2.3.0.md new file mode 100644 index 00000000..1b2adcdb --- /dev/null +++ b/docs/config_opts_after_2.3.0.md @@ -0,0 +1,43 @@ +Изменения обработки параметров в релизах > 2.3.0 +------------------------------------------------ + +Система параметров отличается от того, что было ранее и достаточно сильно: + +* изменения имён и стиля параметров + +Все параметры теперь в виде --help (gnu-style), у некоторых есть шорткаты в виде -h (unix-style). +Это касается всех систем, в том числе винды. + +--daemon=1 и подобное -> просто --daemon, без параметра. Нет опции - false, есть - true +--notransit=1 -> --notransit, то же что и выше: есть опция - false, нет - true +--v6 -> --ipv6 (первое было похоже на версию какого-то своего протокола, типа socksproxy --v5) +--tunnelscfg -> --tunconf (имя параметра было слишком длинным, cfg переделан на conf - единообразно с --conf) +--sockskeys -> разделён на два, для socks и httpproxy по-отдельности + +* поддержка секций в основном конфиге + +Выглядит это так: + + # основные опции + pidfile = /var/run/i2pd.pid + # + # настройки конкретного модуля + [httproxy] + address = 1.2.3.4 + port = 4446 + keys = httproxy-keys.dat + # и так далее + [sam] + enabled = no + addresss = 127.0.0.2 + # ^^ переопределяется только адрес, остальное берётся из дефолта + +Точно так же сейчас работает конфиг туннелей: секция до точки - имя, после - параметр + +* поддержка выключения отдельных сервисов "на корню" см sam.enabled и подобное + +Это позволило задать дефолт для номера порта и не писать его руками для включения. + +* добавлен --help (см #110) + +* присутствует некая валидация параметров, --port=abcd - не прокатит, --port=100500 - тоже From 8aa158c1e0b61ee5156e61a01c1e0755ae8b80b5 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 20 Jan 2016 00:00:00 +0000 Subject: [PATCH 07/32] * update debian/ --- debian/i2pd.conf | 23 +++++++++++++---------- debian/i2pd.init | 2 +- debian/i2pd.upstart | 6 +++--- debian/postinst | 6 ++++-- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/debian/i2pd.conf b/debian/i2pd.conf index a6e9c23f..4a518916 100644 --- a/debian/i2pd.conf +++ b/debian/i2pd.conf @@ -1,16 +1,19 @@ -floodfill=0 -v6=0 +ipv6 -httpproxyaddress=127.0.0.1 -httpproxyport=4444 +[httpproxy] +address = 127.0.0.1 +port = 4444 # other services (disabled by default) # -# samaddress=127.0.0.1 -# samport=7656 +#[sam] +#address = 127.0.0.1 +#port = 7656 # -# bobaddress=127.0.0.1 -# bobport=2827 +#[bob] +#address = 127.0.0.1 +#port = 2827 # -# i2pcontroladdress=127.0.0.1 -# i2pcontrolport=7650 +#[i2pcontrol] +#address = 127.0.0.1 +#port = 7650 diff --git a/debian/i2pd.init b/debian/i2pd.init index 609a3407..d87aa000 100644 --- a/debian/i2pd.init +++ b/debian/i2pd.init @@ -46,7 +46,7 @@ do_start() start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \ - --service=1 --daemon=1 --log=1 --conf=$I2PCONF --tunnelscfg=$TUNCONF \ + --service --daemon --log --conf=$I2PCONF --tunconf=$TUNCONF \ --port=$I2PD_PORT $DAEMON_OPTS > /dev/null 2>&1 \ || return 2 return $? diff --git a/debian/i2pd.upstart b/debian/i2pd.upstart index 0527935d..d1536ea3 100644 --- a/debian/i2pd.upstart +++ b/debian/i2pd.upstart @@ -4,7 +4,7 @@ start on runlevel [2345] stop on runlevel [016] or unmounting-filesystem # these can be overridden in /etc/init/i2pd.override -env I2P_HOST="1.2.3.4" -env I2P_PORT="4567" +env I2PD_HOST="1.2.3.4" +env I2PD_PORT="4567" -exec /usr/sbin/i2pd --daemon=0 --log=1 --host=$I2P_HOST --port=$I2P_PORT +exec /usr/sbin/i2pd --daemon --log --host=$I2PD_HOST --port=$I2PD_PORT diff --git a/debian/postinst b/debian/postinst index 4be6bf3f..1de58c1e 100755 --- a/debian/postinst +++ b/debian/postinst @@ -1,6 +1,7 @@ #!/bin/sh set -e +LOGFILE='/var/log/i2pd.log' I2PDHOME='/var/lib/i2pd' I2PDUSER='i2pd' @@ -16,8 +17,9 @@ case "$1" in adduser --system --quiet --group --home $I2PDHOME $I2PDUSER fi - touch /var/log/i2pd.log - chown -f ${I2PDUSER}:adm /var/log/i2pd.log + touch $LOGFILE + chmod 640 $LOGFILE + chown -f ${I2PDUSER}:adm $LOGFILE mkdir -p -m0750 $I2PDHOME chown -f -R -P ${I2PDUSER}:${I2PDUSER} ${I2PDHOME} ;; From 23cf6ebc89d5340372eda266bd906aa28118647d Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 21 Jan 2016 07:35:26 +0000 Subject: [PATCH 08/32] * add new option 'i2pcontrol.password' --- Config.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Config.cpp b/Config.cpp index 4e6f52d3..b2121b4e 100644 --- a/Config.cpp +++ b/Config.cpp @@ -86,6 +86,7 @@ namespace config { ("i2pcontrol.enabled", value()->default_value(false), "Enable or disable I2P Control Protocol") ("i2pcontrol.address", value()->default_value("127.0.0.1"), "I2PCP listen address") ("i2pcontrol.port", value()->default_value(7650), "I2PCP listen port") + ("i2pcontrol.password", value()->default_value("itoopie"), "I2PCP access password") ; m_OptionsDesc From e1a1aef990849ae654a350c6c1a496204bb48412 Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 21 Jan 2016 07:37:38 +0000 Subject: [PATCH 09/32] * I2PControl : use password option from main config --- I2PControl.cpp | 6 ++++-- I2PControl.h | 6 ------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index a706cd79..534a85d7 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -12,6 +12,7 @@ #include #endif #include "Log.h" +#include "Config.h" #include "NetDb.h" #include "RouterContext.h" #include "Daemon.h" @@ -26,11 +27,12 @@ namespace i2p namespace client { I2PControlService::I2PControlService (const std::string& address, int port): - m_Password (I2P_CONTROL_DEFAULT_PASSWORD), m_IsRunning (false), m_Thread (nullptr), + m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)), m_SSLContext (m_Service, boost::asio::ssl::context::sslv23), m_ShutdownTimer (m_Service) { + GetOption("i2pcontrol.password", m_Password); LoadConfig (); // certificate auto path = GetPath (); @@ -385,7 +387,7 @@ namespace client void I2PControlService::PasswordHandler (const std::string& value) { - LogPrint (eLogDebug, "I2PControl new password=", value); + LogPrint (eLogDebug, "I2PControl: new password=", value, ", to make it persistent you should update your config!"); m_Password = value; m_Tokens.clear (); SaveConfig (); diff --git a/I2PControl.h b/I2PControl.h index 10b6b651..bed84666 100644 --- a/I2PControl.h +++ b/I2PControl.h @@ -26,7 +26,6 @@ namespace client const char I2P_CONTROL_KEY_FILE[] = "key.pem"; const char I2P_CONTROL_CERT_FILE[] = "cert.pem"; const char I2P_CONTROL_CONFIG_FILE[] = "i2pcontrol.conf"; - const char I2P_CONTROL_DEFAULT_PASSWORD[] = "itoopie"; const char I2P_CONTROL_PROPERTY_ID[] = "id"; const char I2P_CONTROL_PROPERTY_METHOD[] = "method"; @@ -48,11 +47,6 @@ namespace client const char I2P_CONTROL_PARAM_ECHO[] = "Echo"; const char I2P_CONTROL_PARAM_RESULT[] = "Result"; - // I2PControl - const char I2P_CONTROL_I2PCONTROL_ADDRESS[] = "i2pcontrol.address"; - const char I2P_CONTROL_I2PCONTROL_PASSWORD[] = "i2pcontrol.password"; - const char I2P_CONTROL_I2PCONTROL_PORT[] = "i2pcontrol.port"; - // RouterInfo requests const char I2P_CONTROL_ROUTER_INFO_UPTIME[] = "i2p.router.uptime"; const char I2P_CONTROL_ROUTER_INFO_VERSION[] = "i2p.router.version"; From db9c20f3dd0c77c8a1396fb92461caa790fa9a32 Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 21 Jan 2016 07:38:11 +0000 Subject: [PATCH 10/32] * I2PControl : move boost1.49+gcc4.7 hack --- I2PControl.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index 534a85d7..8c3380b8 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -1,5 +1,3 @@ -// There is bug in boost 1.49 with gcc 4.7 coming with Debian Wheezy -#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) #include #include #include @@ -8,9 +6,13 @@ #include #include #include + +// There is bug in boost 1.49 with gcc 4.7 coming with Debian Wheezy +#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) #if !GCC47_BOOST149 #include #endif + #include "Log.h" #include "Config.h" #include "NetDb.h" From 2cace0008e3534fbf88c3e74aca9bd2c405e240a Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 21 Jan 2016 07:41:09 +0000 Subject: [PATCH 11/32] - I2PControlService::SaveConfig : not used anymore --- I2PControl.cpp | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index 8c3380b8..39817e92 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -110,24 +110,7 @@ namespace client LogPrint (eLogError, "Can't read ", filename, ": ", ex.what ()); } } - m_Password = pt.get (I2P_CONTROL_I2PCONTROL_PASSWORD, I2P_CONTROL_DEFAULT_PASSWORD); - if (isNew) SaveConfig (); - } - - void I2PControlService::SaveConfig () - { - boost::property_tree::ptree pt; - pt.put (I2P_CONTROL_I2PCONTROL_PASSWORD, m_Password); - auto filename = GetPath () / I2P_CONTROL_CONFIG_FILE; - // we take care about directory in LoadConfig - try - { - boost::property_tree::write_ini (filename.string (), pt); - } - catch (std::exception& ex) - { - LogPrint (eLogError, "Can't write ", filename, ": ", ex.what ()); - } + GetOption("i2pcontrol.password", m_Password); } void I2PControlService::Start () @@ -392,7 +375,6 @@ namespace client LogPrint (eLogDebug, "I2PControl: new password=", value, ", to make it persistent you should update your config!"); m_Password = value; m_Tokens.clear (); - SaveConfig (); } // RouterInfo From 928abf7094753030c931e122f0ea0110abc0793a Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 21 Jan 2016 07:46:17 +0000 Subject: [PATCH 12/32] - I2PControlService::LoadConfig : not used anymore --- I2PControl.cpp | 28 +--------------------------- I2PControl.h | 4 ---- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index 39817e92..062f02ff 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -35,7 +35,7 @@ namespace client m_ShutdownTimer (m_Service) { GetOption("i2pcontrol.password", m_Password); - LoadConfig (); + // certificate auto path = GetPath (); if (!boost::filesystem::exists (path)) @@ -87,32 +87,6 @@ namespace client Stop (); } - void I2PControlService::LoadConfig () - { - auto path = GetPath (); - if (!boost::filesystem::exists (path)) - { - if (!boost::filesystem::create_directory (path)) - LogPrint (eLogError, "Failed to create i2pcontrol directory"); - } - boost::property_tree::ptree pt; - auto filename = path / I2P_CONTROL_CONFIG_FILE; - bool isNew = true; - if (boost::filesystem::exists (filename)) - { - try - { - boost::property_tree::read_ini (filename.string (), pt); - isNew = false; - } - catch (std::exception& ex) - { - LogPrint (eLogError, "Can't read ", filename, ": ", ex.what ()); - } - } - GetOption("i2pcontrol.password", m_Password); - } - void I2PControlService::Start () { if (!m_IsRunning) diff --git a/I2PControl.h b/I2PControl.h index bed84666..9d97b267 100644 --- a/I2PControl.h +++ b/I2PControl.h @@ -81,9 +81,6 @@ namespace client private: - void LoadConfig (); - void SaveConfig (); - void Run (); void Accept (); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); @@ -99,7 +96,6 @@ namespace client boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir() / I2P_CONTROL_PATH; }; void CreateCertificate (); - private: From 97ca8b7ada70418f4987d83b276d614f4199668d Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 21 Jan 2016 12:56:53 +0000 Subject: [PATCH 13/32] * fix build --- I2PControl.cpp | 2 +- I2PControl.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index 062f02ff..eabea408 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -34,7 +34,7 @@ namespace client m_SSLContext (m_Service, boost::asio::ssl::context::sslv23), m_ShutdownTimer (m_Service) { - GetOption("i2pcontrol.password", m_Password); + i2p::config::GetOption("i2pcontrol.password", m_Password); // certificate auto path = GetPath (); diff --git a/I2PControl.h b/I2PControl.h index 9d97b267..7f8e7c30 100644 --- a/I2PControl.h +++ b/I2PControl.h @@ -47,6 +47,8 @@ namespace client const char I2P_CONTROL_PARAM_ECHO[] = "Echo"; const char I2P_CONTROL_PARAM_RESULT[] = "Result"; + const char I2P_CONTROL_I2PCONTROL_PASSWORD[] = "i2pcontrol.password"; + // RouterInfo requests const char I2P_CONTROL_ROUTER_INFO_UPTIME[] = "i2p.router.uptime"; const char I2P_CONTROL_ROUTER_INFO_VERSION[] = "i2p.router.version"; From de0658eaab3e688a8cd04a18299fe47f20b8c5f0 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 22 Jan 2016 00:00:00 +0000 Subject: [PATCH 14/32] * I2PControlService::CreateCertificate : use function parameters instead direct GetPath calls --- I2PControl.cpp | 41 +++++++++++++++++++---------------------- I2PControl.h | 2 +- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index eabea408..3a8f8919 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -483,8 +483,9 @@ namespace client } // certificate - void I2PControlService::CreateCertificate () + void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path) { + FILE *f = NULL; EVP_PKEY * pkey = EVP_PKEY_new (); RSA * rsa = RSA_new (); BIGNUM * e = BN_dup (i2p::crypto::GetRSAE ()); @@ -504,34 +505,30 @@ namespace client X509_NAME_add_entry_by_txt (name, "CN", MBSTRING_ASC, (unsigned char *)I2P_CONTROL_CERTIFICATE_COMMON_NAME, -1, -1, 0); // common name X509_set_issuer_name (x509, name); // set issuer to ourselves X509_sign (x509, pkey, EVP_sha1 ()); // sign - // save key and certificate - // keys - auto filename = GetPath () / I2P_CONTROL_KEY_FILE; - FILE * f= fopen (filename.string ().c_str (), "wb"); - if (f) - { - PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL); + + // save cert + if ((f = fopen (crt_path, "wb")) != NULL) { + LogPrint (eLogInfo, "I2PControl: saving new cert to ", crt_path); + PEM_write_X509 (f, x509); fclose (f); + } else { + LogPrint (eLogError, "I2PControl: can't write cert: ", strerror(errno)); } - else - LogPrint (eLogError, "Can't open file ", filename); - // certificate - filename = GetPath () / I2P_CONTROL_CERT_FILE; - f= fopen (filename.string ().c_str (), "wb"); - if (f) - { - PEM_write_X509 (f, x509); + + // save key + if ((f = fopen (key_path, "wb")) != NULL) { + LogPrint (eLogInfo, "I2PControl: saving cert key to : ", key_path); + PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL); fclose (f); + } else { + LogPrint (eLogError, "I2PControl: can't write key: ", strerror(errno)); } - else - LogPrint (eLogError, "Can't open file ", filename); - X509_free (x509); + X509_free (x509); + } else { + LogPrint (eLogError, "I2PControl: can't create RSA key for certificate"); } - else - LogPrint (eLogError, "Couldn't create RSA key for certificate"); EVP_PKEY_free (pkey); } - } } diff --git a/I2PControl.h b/I2PControl.h index 7f8e7c30..850bab10 100644 --- a/I2PControl.h +++ b/I2PControl.h @@ -97,7 +97,7 @@ namespace client std::shared_ptr socket, std::shared_ptr buf); boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir() / I2P_CONTROL_PATH; }; - void CreateCertificate (); + void CreateCertificate (const char *crt_path, const char *key_path); private: From d5aa1a4880a7c329122e6f5200a488752f216b5e Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 22 Jan 2016 00:00:00 +0000 Subject: [PATCH 15/32] * use GetOption instead hardcoded values in header * move cert/key from $DATADIR/i2pcontrol/ to $DATADIR/ --- Config.cpp | 2 ++ I2PControl.cpp | 23 ++++++++++------------- I2PControl.h | 7 +------ 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/Config.cpp b/Config.cpp index b2121b4e..81a0bdea 100644 --- a/Config.cpp +++ b/Config.cpp @@ -87,6 +87,8 @@ namespace config { ("i2pcontrol.address", value()->default_value("127.0.0.1"), "I2PCP listen address") ("i2pcontrol.port", value()->default_value(7650), "I2PCP listen port") ("i2pcontrol.password", value()->default_value("itoopie"), "I2PCP access password") + ("i2pcontrol.cert", value()->default_value("i2pcontrol.crt.pem"), "I2PCP connection cerificate") + ("i2pcontrol.key", value()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key") ; m_OptionsDesc diff --git a/I2PControl.cpp b/I2PControl.cpp index 3a8f8919..2efba45f 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -36,23 +36,20 @@ namespace client { i2p::config::GetOption("i2pcontrol.password", m_Password); - // certificate + // certificate / keys + std::string i2pcp_crt; i2p::config::GetOption("i2pcontrol.cert", i2pcp_crt); + std::string i2pcp_key; i2p::config::GetOption("i2pcontrol.key", i2pcp_key); + // TODO: properly handle absolute paths auto path = GetPath (); - if (!boost::filesystem::exists (path)) + if (!boost::filesystem::exists (path / i2pcp_crt) || + !boost::filesystem::exists (path / i2pcp_key)) { - if (!boost::filesystem::create_directory (path)) - LogPrint (eLogError, "Failed to create i2pcontrol directory"); - } - if (!boost::filesystem::exists (path / I2P_CONTROL_KEY_FILE) || - !boost::filesystem::exists (path / I2P_CONTROL_CERT_FILE)) - { - // create new certificate - CreateCertificate (); - LogPrint (eLogInfo, "I2PControl certificates created"); + LogPrint (eLogInfo, "I2PControl: creating new certificate for control connection"); + CreateCertificate (i2pcp_crt.c_str(), i2pcp_key.c_str()); } m_SSLContext.set_options (boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); - m_SSLContext.use_certificate_file ((path / I2P_CONTROL_CERT_FILE).string (), boost::asio::ssl::context::pem); - m_SSLContext.use_private_key_file ((path / I2P_CONTROL_KEY_FILE).string (), boost::asio::ssl::context::pem); + m_SSLContext.use_certificate_file ((path / i2pcp_crt).string (), boost::asio::ssl::context::pem); + m_SSLContext.use_private_key_file ((path / i2pcp_crt).string (), boost::asio::ssl::context::pem); // handlers m_MethodHandlers[I2P_CONTROL_METHOD_AUTHENTICATE] = &I2PControlService::AuthenticateHandler; diff --git a/I2PControl.h b/I2PControl.h index 850bab10..38e3db55 100644 --- a/I2PControl.h +++ b/I2PControl.h @@ -22,11 +22,6 @@ namespace client const size_t I2P_CONTROL_MAX_REQUEST_SIZE = 1024; typedef std::array I2PControlBuffer; - const char I2P_CONTROL_PATH[] = "ipcontrol"; - const char I2P_CONTROL_KEY_FILE[] = "key.pem"; - const char I2P_CONTROL_CERT_FILE[] = "cert.pem"; - const char I2P_CONTROL_CONFIG_FILE[] = "i2pcontrol.conf"; - const char I2P_CONTROL_PROPERTY_ID[] = "id"; const char I2P_CONTROL_PROPERTY_METHOD[] = "method"; const char I2P_CONTROL_PROPERTY_PARAMS[] = "params"; @@ -96,7 +91,7 @@ namespace client void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::shared_ptr socket, std::shared_ptr buf); - boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir() / I2P_CONTROL_PATH; }; + boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir(); }; void CreateCertificate (const char *crt_path, const char *key_path); private: From b70b3ec85b932865e1c3f531113a3c20bc2b0cb7 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 22 Jan 2016 00:00:00 +0000 Subject: [PATCH 16/32] * I2PControl : drop I2P_CONTROL_ID* vars : ugly --- I2PControl.cpp | 85 ++++++++++++++++++++++++++------------------------ I2PControl.h | 38 ---------------------- 2 files changed, 44 insertions(+), 79 deletions(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index 2efba45f..128bd0f8 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -52,31 +52,31 @@ namespace client m_SSLContext.use_private_key_file ((path / i2pcp_crt).string (), boost::asio::ssl::context::pem); // handlers - m_MethodHandlers[I2P_CONTROL_METHOD_AUTHENTICATE] = &I2PControlService::AuthenticateHandler; - m_MethodHandlers[I2P_CONTROL_METHOD_ECHO] = &I2PControlService::EchoHandler; - m_MethodHandlers[I2P_CONTROL_METHOD_I2PCONTROL] = &I2PControlService::I2PControlHandler; - m_MethodHandlers[I2P_CONTROL_METHOD_ROUTER_INFO] = &I2PControlService::RouterInfoHandler; - m_MethodHandlers[I2P_CONTROL_METHOD_ROUTER_MANAGER] = &I2PControlService::RouterManagerHandler; - m_MethodHandlers[I2P_CONTROL_METHOD_NETWORK_SETTING] = &I2PControlService::NetworkSettingHandler; + m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler; + m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler; + m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler; + m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler; + m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler; + m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler; // I2PControl - m_I2PControlHandlers[I2P_CONTROL_I2PCONTROL_PASSWORD] = &I2PControlService::PasswordHandler; + m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler; // RouterInfo - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_UPTIME] = &I2PControlService::UptimeHandler; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_VERSION] = &I2PControlService::VersionHandler; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_STATUS] = &I2PControlService::StatusHandler; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_NETDB_KNOWNPEERS] = &I2PControlService::NetDbKnownPeersHandler; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_NETDB_ACTIVEPEERS] = &I2PControlService::NetDbActivePeersHandler; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_NET_STATUS] = &I2PControlService::NetStatusHandler; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_TUNNELS_PARTICIPATING] = &I2PControlService::TunnelsParticipatingHandler; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_BW_IB_1S] = &I2PControlService::InboundBandwidth1S ; - m_RouterInfoHandlers[I2P_CONTROL_ROUTER_INFO_BW_OB_1S] = &I2PControlService::OutboundBandwidth1S ; + m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler; + m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler; + m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler; + m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler; + m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler; + m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S; + m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S; + m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler; + m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler; // RouterManager - m_RouterManagerHandlers[I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN] = &I2PControlService::ShutdownHandler; - m_RouterManagerHandlers[I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN_GRACEFUL] = &I2PControlService::ShutdownGracefulHandler; - m_RouterManagerHandlers[I2P_CONTROL_ROUTER_MANAGER_RESEED] = &I2PControlService::ReseedHandler; + m_RouterManagerHandlers["Reseed"] = &I2PControlService::ReseedHandler; + m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler; + m_RouterManagerHandlers["ShutdownGraceful"] = &I2PControlService::ShutdownGracefulHandler; } I2PControlService::~I2PControlService () @@ -220,14 +220,14 @@ namespace client boost::property_tree::ptree pt; boost::property_tree::read_json (ss, pt); - std::string method = pt.get(I2P_CONTROL_PROPERTY_METHOD); + std::string id = pt.get("id"); + std::string method = pt.get("method"); auto it = m_MethodHandlers.find (method); if (it != m_MethodHandlers.end ()) { std::ostringstream response; - response << "{\"id\":" << pt.get(I2P_CONTROL_PROPERTY_ID) << ",\"result\":{"; - - (this->*(it->second))(pt.get_child (I2P_CONTROL_PROPERTY_PARAMS), response); + response << "{\"id\":" << id << ",\"result\":{"; + (this->*(it->second))(pt.get_child ("params"), response); response << "},\"jsonrpc\":\"2.0\"}"; SendResponse (socket, buf, response, isHtml); } @@ -302,23 +302,23 @@ namespace client void I2PControlService::AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - int api = params.get (I2P_CONTROL_PARAM_API); - auto password = params.get (I2P_CONTROL_PARAM_PASSWORD); + int api = params.get ("API"); + auto password = params.get ("Password"); LogPrint (eLogDebug, "I2PControl Authenticate API=", api, " Password=", password); if (password != m_Password) LogPrint (eLogError, "I2PControl Authenticate Invalid password ", password, " expected ", m_Password); - InsertParam (results, I2P_CONTROL_PARAM_API, api); + InsertParam (results, "API", api); results << ","; std::string token = boost::lexical_cast(i2p::util::GetSecondsSinceEpoch ()); m_Tokens.insert (token); - InsertParam (results, I2P_CONTROL_PARAM_TOKEN, token); + InsertParam (results, "Token", token); } void I2PControlService::EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - auto echo = params.get (I2P_CONTROL_PARAM_ECHO); + auto echo = params.get ("Echo"); LogPrint (eLogDebug, "I2PControl Echo Echo=", echo); - InsertParam (results, I2P_CONTROL_PARAM_RESULT, echo); + InsertParam (results, "Result", echo); } @@ -369,47 +369,50 @@ namespace client void I2PControlService::UptimeHandler (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_UPTIME, (int)i2p::context.GetUptime ()*1000); + InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000); } void I2PControlService::VersionHandler (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_VERSION, VERSION); + InsertParam (results, "i2p.router.version", VERSION); } void I2PControlService::StatusHandler (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_STATUS, "???"); // TODO: + InsertParam (results, "i2p.router.status", "???"); // TODO: } void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_NETDB_KNOWNPEERS, i2p::data::netdb.GetNumRouters ()); + InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ()); } void I2PControlService::NetDbActivePeersHandler (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_NETDB_ACTIVEPEERS, (int)i2p::transport::transports.GetPeers ().size ()); + InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ()); } void I2PControlService::NetStatusHandler (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_NET_STATUS, (int)i2p::context.GetStatus ()); + InsertParam (results, "i2p.router.net.status", (int)i2p::context.GetStatus ()); } void I2PControlService::TunnelsParticipatingHandler (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_TUNNELS_PARTICIPATING, (int)i2p::tunnel::tunnels.GetTransitTunnels ().size ()); + int transit = i2p::tunnel::tunnels.GetTransitTunnels ().size (); + InsertParam (results, "i2p.router.net.tunnels.participating", transit); } void I2PControlService::InboundBandwidth1S (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_BW_IB_1S, (double)i2p::transport::transports.GetInBandwidth ()); + double bw = i2p::transport::transports.GetInBandwidth (); + InsertParam (results, "i2p.router.net.bw.inbound.1s", bw); } void I2PControlService::OutboundBandwidth1S (std::ostringstream& results) { - InsertParam (results, I2P_CONTROL_ROUTER_INFO_BW_OB_1S, (double)i2p::transport::transports.GetOutBandwidth ()); + double bw = i2p::transport::transports.GetOutBandwidth (); + InsertParam (results, "i2p.router.net.bw.outbound.1s", bw); } // RouterManager @@ -433,7 +436,7 @@ namespace client void I2PControlService::ShutdownHandler (std::ostringstream& results) { LogPrint (eLogInfo, "Shutdown requested"); - InsertParam (results, I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN, ""); + InsertParam (results, "Shutdown", ""); m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent m_ShutdownTimer.async_wait ( [](const boost::system::error_code& ecode) @@ -447,7 +450,7 @@ namespace client i2p::context.SetAcceptsTunnels (false); int timeout = i2p::tunnel::tunnels.GetTransitTunnelsExpirationTimeout (); LogPrint (eLogInfo, "Graceful shutdown requested. Will shutdown after ", timeout, " seconds"); - InsertParam (results, I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN_GRACEFUL, ""); + InsertParam (results, "ShutdownGraceful", ""); m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second m_ShutdownTimer.async_wait ( [](const boost::system::error_code& ecode) @@ -459,7 +462,7 @@ namespace client void I2PControlService::ReseedHandler (std::ostringstream& results) { LogPrint (eLogInfo, "Reseed requested"); - InsertParam (results, I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN, ""); + InsertParam (results, "Reseed", ""); i2p::data::netdb.Reseed (); } diff --git a/I2PControl.h b/I2PControl.h index 38e3db55..f3ddc3fe 100644 --- a/I2PControl.h +++ b/I2PControl.h @@ -22,44 +22,6 @@ namespace client const size_t I2P_CONTROL_MAX_REQUEST_SIZE = 1024; typedef std::array I2PControlBuffer; - const char I2P_CONTROL_PROPERTY_ID[] = "id"; - const char I2P_CONTROL_PROPERTY_METHOD[] = "method"; - const char I2P_CONTROL_PROPERTY_PARAMS[] = "params"; - const char I2P_CONTROL_PROPERTY_RESULT[] = "result"; - - // methods - const char I2P_CONTROL_METHOD_AUTHENTICATE[] = "Authenticate"; - const char I2P_CONTROL_METHOD_ECHO[] = "Echo"; - const char I2P_CONTROL_METHOD_I2PCONTROL[] = "I2PControl"; - const char I2P_CONTROL_METHOD_ROUTER_INFO[] = "RouterInfo"; - const char I2P_CONTROL_METHOD_ROUTER_MANAGER[] = "RouterManager"; - const char I2P_CONTROL_METHOD_NETWORK_SETTING[] = "NetworkSetting"; - - // params - const char I2P_CONTROL_PARAM_API[] = "API"; - const char I2P_CONTROL_PARAM_PASSWORD[] = "Password"; - const char I2P_CONTROL_PARAM_TOKEN[] = "Token"; - const char I2P_CONTROL_PARAM_ECHO[] = "Echo"; - const char I2P_CONTROL_PARAM_RESULT[] = "Result"; - - const char I2P_CONTROL_I2PCONTROL_PASSWORD[] = "i2pcontrol.password"; - - // RouterInfo requests - const char I2P_CONTROL_ROUTER_INFO_UPTIME[] = "i2p.router.uptime"; - const char I2P_CONTROL_ROUTER_INFO_VERSION[] = "i2p.router.version"; - const char I2P_CONTROL_ROUTER_INFO_STATUS[] = "i2p.router.status"; - const char I2P_CONTROL_ROUTER_INFO_NETDB_KNOWNPEERS[] = "i2p.router.netdb.knownpeers"; - const char I2P_CONTROL_ROUTER_INFO_NETDB_ACTIVEPEERS[] = "i2p.router.netdb.activepeers"; - const char I2P_CONTROL_ROUTER_INFO_NET_STATUS[] = "i2p.router.net.status"; - const char I2P_CONTROL_ROUTER_INFO_TUNNELS_PARTICIPATING[] = "i2p.router.net.tunnels.participating"; - const char I2P_CONTROL_ROUTER_INFO_BW_IB_1S[] = "i2p.router.net.bw.inbound.1s"; - const char I2P_CONTROL_ROUTER_INFO_BW_OB_1S[] = "i2p.router.net.bw.outbound.1s"; - - // RouterManager requests - const char I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN[] = "Shutdown"; - const char I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN_GRACEFUL[] = "ShutdownGraceful"; - const char I2P_CONTROL_ROUTER_MANAGER_RESEED[] = "Reseed"; - // Certificate const long I2P_CONTROL_CERTIFICATE_VALIDITY = 365*10; // 10 years const char I2P_CONTROL_CERTIFICATE_COMMON_NAME[] = "i2pd.i2pcontrol"; From ac2cb773df6bc07a4cf11ac84dface9c41b71781 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 22 Jan 2016 00:00:00 +0000 Subject: [PATCH 17/32] * I2PControl.cpp : tune logs --- I2PControl.cpp | 90 +++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/I2PControl.cpp b/I2PControl.cpp index 128bd0f8..35f3d0c6 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -114,13 +114,10 @@ namespace client { while (m_IsRunning) { - try - { + try { m_Service.run (); - } - catch (std::exception& ex) - { - LogPrint (eLogError, "I2PControl: ", ex.what ()); + } catch (std::exception& ex) { + LogPrint (eLogError, "I2PControl: runtime exception: ", ex.what ()); } } } @@ -137,13 +134,12 @@ namespace client if (ecode != boost::asio::error::operation_aborted) Accept (); - if (!ecode) - { - LogPrint (eLogInfo, "New I2PControl request from ", socket->lowest_layer ().remote_endpoint ()); - Handshake (socket); + if (ecode) { + LogPrint (eLogError, "I2PControl: accept error: ", ecode.message ()); + return; } - else - LogPrint (eLogError, "I2PControl accept error: ", ecode.message ()); + LogPrint (eLogDebug, "I2PControl: new request from ", socket->lowest_layer ().remote_endpoint ()); + Handshake (socket); } void I2PControlService::Handshake (std::shared_ptr socket) @@ -154,13 +150,12 @@ namespace client void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr socket) { - if (!ecode) - { - //std::this_thread::sleep_for (std::chrono::milliseconds(5)); - ReadRequest (socket); + if (ecode) { + LogPrint (eLogError, "I2PControl: handshake error: ", ecode.message ()); + return; } - else - LogPrint (eLogError, "I2PControl handshake error: ", ecode.message ()); + //std::this_thread::sleep_for (std::chrono::milliseconds(5)); + ReadRequest (socket); } void I2PControlService::ReadRequest (std::shared_ptr socket) @@ -180,12 +175,10 @@ namespace client size_t bytes_transferred, std::shared_ptr socket, std::shared_ptr buf) { - if (ecode) - { - LogPrint (eLogError, "I2PControl read error: ", ecode.message ()); - } - else - { + if (ecode) { + LogPrint (eLogError, "I2PControl: read error: ", ecode.message ()); + return; + } else { try { bool isHtml = !memcmp (buf->data (), "POST", 4); @@ -294,8 +287,9 @@ namespace client void I2PControlService::HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::shared_ptr socket, std::shared_ptr buf) { - if (ecode) - LogPrint (eLogError, "I2PControl write error: ", ecode.message ()); + if (ecode) { + LogPrint (eLogError, "I2PControl: write error: ", ecode.message ()); + } } // handlers @@ -304,9 +298,11 @@ namespace client { int api = params.get ("API"); auto password = params.get ("Password"); - LogPrint (eLogDebug, "I2PControl Authenticate API=", api, " Password=", password); - if (password != m_Password) - LogPrint (eLogError, "I2PControl Authenticate Invalid password ", password, " expected ", m_Password); + LogPrint (eLogDebug, "I2PControl: Authenticate API=", api, " Password=", password); + if (password != m_Password) { + LogPrint (eLogError, "I2PControl: Authenticate Invalid password: ", password); + return; + } InsertParam (results, "API", api); results << ","; std::string token = boost::lexical_cast(i2p::util::GetSecondsSinceEpoch ()); @@ -326,10 +322,9 @@ namespace client void I2PControlService::I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - LogPrint (eLogDebug, "I2PControl I2PControl"); for (auto& it: params) { - LogPrint (eLogDebug, it.first); + LogPrint (eLogDebug, "I2PControl: I2PControl request: ", it.first); auto it1 = m_I2PControlHandlers.find (it.first); if (it1 != m_I2PControlHandlers.end ()) { @@ -337,13 +332,13 @@ namespace client InsertParam (results, it.first, ""); } else - LogPrint (eLogError, "I2PControl I2PControl unknown request ", it.first); + LogPrint (eLogError, "I2PControl: I2PControl unknown request: ", it.first); } } void I2PControlService::PasswordHandler (const std::string& value) { - LogPrint (eLogDebug, "I2PControl: new password=", value, ", to make it persistent you should update your config!"); + LogPrint (eLogWarning, "I2PControl: new password=", value, ", to make it persistent you should update your config!"); m_Password = value; m_Tokens.clear (); } @@ -352,10 +347,9 @@ namespace client void I2PControlService::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - LogPrint (eLogDebug, "I2PControl RouterInfo"); for (auto it = params.begin (); it != params.end (); it++) { - LogPrint (eLogDebug, it->first); + LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first); auto it1 = m_RouterInfoHandlers.find (it->first); if (it1 != m_RouterInfoHandlers.end ()) { @@ -363,7 +357,7 @@ namespace client (this->*(it1->second))(results); } else - LogPrint (eLogError, "I2PControl RouterInfo unknown request ", it->first); + LogPrint (eLogError, "I2PControl: RouterInfo unknown request ", it->first); } } @@ -419,23 +413,22 @@ namespace client void I2PControlService::RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - LogPrint (eLogDebug, "I2PControl RouterManager"); for (auto it = params.begin (); it != params.end (); it++) { if (it != params.begin ()) results << ","; - LogPrint (eLogDebug, it->first); + LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first); auto it1 = m_RouterManagerHandlers.find (it->first); - if (it1 != m_RouterManagerHandlers.end ()) + if (it1 != m_RouterManagerHandlers.end ()) { (this->*(it1->second))(results); - else - LogPrint (eLogError, "I2PControl RouterManager unknown request ", it->first); + } else + LogPrint (eLogError, "I2PControl: RouterManager unknown request: ", it->first); } } void I2PControlService::ShutdownHandler (std::ostringstream& results) { - LogPrint (eLogInfo, "Shutdown requested"); + LogPrint (eLogInfo, "I2PControl: Shutdown requested"); InsertParam (results, "Shutdown", ""); m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent m_ShutdownTimer.async_wait ( @@ -449,7 +442,7 @@ namespace client { i2p::context.SetAcceptsTunnels (false); int timeout = i2p::tunnel::tunnels.GetTransitTunnelsExpirationTimeout (); - LogPrint (eLogInfo, "Graceful shutdown requested. Will shutdown after ", timeout, " seconds"); + LogPrint (eLogInfo, "I2PControl: Graceful shutdown requested, ", timeout, " seconds remains"); InsertParam (results, "ShutdownGraceful", ""); m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second m_ShutdownTimer.async_wait ( @@ -461,7 +454,7 @@ namespace client void I2PControlService::ReseedHandler (std::ostringstream& results) { - LogPrint (eLogInfo, "Reseed requested"); + LogPrint (eLogInfo, "I2PControl: Reseed requested"); InsertParam (results, "Reseed", ""); i2p::data::netdb.Reseed (); } @@ -469,16 +462,15 @@ namespace client // network setting void I2PControlService::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { - LogPrint (eLogDebug, "I2PControl NetworkSetting"); for (auto it = params.begin (); it != params.end (); it++) { if (it != params.begin ()) results << ","; - LogPrint (eLogDebug, it->first); + LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first); auto it1 = m_NetworkSettingHandlers.find (it->first); - if (it1 != m_NetworkSettingHandlers.end ()) + if (it1 != m_NetworkSettingHandlers.end ()) { (this->*(it1->second))(it->second.data (), results); - else - LogPrint (eLogError, "I2PControl NetworkSetting unknown request ", it->first); + } else + LogPrint (eLogError, "I2PControl NetworkSetting unknown request: ", it->first); } } From e6e2f04a10aa7217da46e6bd6489d4d1be3181a4 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 11:04:15 +0000 Subject: [PATCH 18/32] * Config.cpp : set default value for boolean options --- Config.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Config.cpp b/Config.cpp index 81a0bdea..4704816d 100644 --- a/Config.cpp +++ b/Config.cpp @@ -36,12 +36,12 @@ namespace config { ("loglevel", value()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") ("host", value()->default_value(""), "External IP (deprecated)") ("port,p", value()->default_value(4567), "Port to listen for incoming connections") - ("ipv6,6", value()->zero_tokens(), "Enable communication through ipv6") - ("daemon", value()->zero_tokens(), "Router will go to background after start") - ("service", value()->zero_tokens(), "Router will use system folders like '/var/lib/i2pd'") - ("notransit", value()->zero_tokens(), "Router will not forward transit traffic") - ("floodfill", value()->zero_tokens(), "Router will try to become floodfill") - ("bandwidth", value()->default_value('O'), "Bandwidth limiting: L - 32kbps, O - 256Kbps, P - unlimited") + ("ipv6,6", value()->zero_tokens()->default_value(false), "Enable communication through ipv6") + ("daemon", value()->zero_tokens()->default_value(false), "Router will go to background after start") + ("service", value()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'") + ("notransit", value()->zero_tokens()->default_value(false), "Router will not forward transit traffic") + ("floodfill", value()->zero_tokens()->default_value(false), "Router will try to become floodfill") + ("bandwidth", value()->default_value('O'), "Bandwidth limiting: L - 32kbps, O - 256Kbps, P - unlimited (ignored if floodfill)") ; options_description httpserver("HTTP Server options"); From 022642f4d5a8b2a1259d4290f87c86dbe7599d1e Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 11:04:41 +0000 Subject: [PATCH 19/32] * Config.cpp : don't try to parse config, if path is empty --- Config.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Config.cpp b/Config.cpp index 4704816d..1b0c3072 100644 --- a/Config.cpp +++ b/Config.cpp @@ -118,6 +118,9 @@ namespace config { } void ParseConfig(const std::string& path) { + if (path == "") + return; + std::ifstream config(path, std::ios::in); if (!config.is_open()) { From efa48a7e397d226ba5c70a542f7d2153afe4e8b7 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 11:05:16 +0000 Subject: [PATCH 20/32] * tune logs --- AddressBook.cpp | 2 +- Daemon.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 00b735ae..754d314a 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -396,7 +396,7 @@ namespace client LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded"); } else - LogPrint (eLogWarning, "Addresbook: subscriptions.txt not found"); + LogPrint (eLogWarning, "Addresbook: subscriptions.txt not found in datadir"); } else LogPrint (eLogError, "Addressbook: subscriptions already loaded"); diff --git a/Daemon.cpp b/Daemon.cpp index 8530b93e..4b0f7b64 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -129,7 +129,7 @@ namespace i2p if (http) { std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); - LogPrint(eLogInfo, "Daemon: staring HTTP Server at ", httpAddr, ":", httpPort); + LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort); d.httpServer = std::unique_ptr(new i2p::util::HTTPServer(httpAddr, httpPort)); d.httpServer->Start(); } From 26d232c567ef808f313ec5086830a6d3c350b078 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 11:06:17 +0000 Subject: [PATCH 21/32] * Daemon_Singleton::init : unwrap spagetti-code --- Daemon.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index 4b0f7b64..34a90f9a 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -60,17 +60,23 @@ namespace i2p bool Daemon_Singleton::init(int argc, char* argv[]) { + std::string config = i2p::util::filesystem::GetConfigFile().string(); + std::string tunconf = i2p::util::filesystem::GetTunnelsConfigFile().string(); + std::string datadir = i2p::util::filesystem::GetDataDir().string(); + + LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); + LogPrint(eLogDebug, "FS: main config file: ", config); + LogPrint(eLogDebug, "FS: tunnels config: ", tunconf); + LogPrint(eLogDebug, "FS: data directory: ", datadir); + i2p::config::Init(); i2p::config::ParseCmdline(argc, argv); - i2p::config::ParseConfig(i2p::util::filesystem::GetConfigFile().string()); + i2p::config::ParseConfig(config); i2p::config::Finalize(); i2p::crypto::InitCrypto (); i2p::context.Init (); - LogPrint(eLogInfo, "i2pd v", VERSION, " starting"); - LogPrint(eLogDebug, "FS: data directory: ", i2p::util::filesystem::GetDataDir().string()); - i2p::config::GetOption("daemon", isDaemon); i2p::config::GetOption("log", isLogging); From 0f7e2ad11ac09ef69679f3f8f0e37d40eccb1dd2 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 11:06:54 +0000 Subject: [PATCH 22/32] * Daemon_Singleton::init : rewrite setting bandwidth limit and floodfill mode --- Daemon.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index 34a90f9a..22ca2ac1 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -93,19 +93,20 @@ namespace i2p i2p::context.SetAcceptsTunnels (!transit); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); - i2p::context.SetFloodfill (isFloodfill); + char bandwidth; i2p::config::GetOption("bandwidth", bandwidth); - char bandwidth; i2p::config::GetOption("bandwidth", bandwidth); - if (bandwidth != '-') - { + if (isFloodfill) { + LogPrint(eLogInfo, "Daemon: router will be floodfill, bandwidth set to 'extra'"); + i2p::context.SetFloodfill (true); + i2p::context.SetExtraBandwidth (); + } else if (bandwidth != '-') { + LogPrint(eLogInfo, "Daemon: bandwidth set to ", bandwidth); switch (bandwidth) { case 'P' : i2p::context.SetExtraBandwidth (); break; case 'L' : i2p::context.SetHighBandwidth (); break; default : i2p::context.SetLowBandwidth (); break; } } - else if (isFloodfill) - i2p::context.SetExtraBandwidth (); return true; } From 415314a90d21ac60d9ef9f2eec18a8c8f0340e51 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 11:07:05 +0000 Subject: [PATCH 23/32] * update docs --- docs/configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration.md b/docs/configuration.md index f3b84952..64925d4b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -20,6 +20,7 @@ Command line options * --notransit - Router will not accept transit tunnels at startup. 0 by default * --floodfill - Router will be floodfill, off by default * --bandwidth= - L if bandwidth is limited to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited + This option will be ignored if --floodfill given * --http.address= - The address to listen on (HTTP server) * --http.port= - The port to listen on (HTTP server) From 7b23d79dc2a5761298d6f997390886d174c581b9 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 11:13:38 +0000 Subject: [PATCH 24/32] * util.cpp : update Get*ConfigFile() : autodetect configs --- util.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/util.cpp b/util.cpp index e559d7f9..5f36f409 100644 --- a/util.cpp +++ b/util.cpp @@ -124,19 +124,33 @@ namespace filesystem boost::filesystem::path GetConfigFile() { std::string config; i2p::config::GetOption("conf", config); - boost::filesystem::path pathConfigFile(config); - if (!pathConfigFile.is_complete()) - pathConfigFile = GetDataDir() / pathConfigFile; - return pathConfigFile; + if (config != "") { + /* config file set with cmdline */ + boost::filesystem::path path(config); + return path; + } + /* else - try autodetect */ + boost::filesystem::path path("i2p.conf"); + path = GetDataDir() / path; + if (!boost::filesystem::exists(path)) + path = ""; /* reset */ + return path; } boost::filesystem::path GetTunnelsConfigFile() { std::string tunconf; i2p::config::GetOption("tunconf", tunconf); - boost::filesystem::path pathTunnelsConfigFile(tunconf); - if (!pathTunnelsConfigFile.is_complete()) - pathTunnelsConfigFile = GetDataDir() / pathTunnelsConfigFile; - return pathTunnelsConfigFile; + if (tunconf != "") { + /* config file set with cmdline */ + boost::filesystem::path path(tunconf); + return path; + } + /* else - try autodetect */ + boost::filesystem::path path("tunnels.cfg"); + path = GetDataDir() / path; + if (!boost::filesystem::exists(path)) + path = ""; /* reset */ + return path; } boost::filesystem::path GetDefaultDataDir() From 7da17ba21e3a2f9d04a6d0ebd23b59e350da49e7 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 24 Jan 2016 12:41:08 +0000 Subject: [PATCH 25/32] * tune logs --- Daemon.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index 22ca2ac1..a2d33720 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -81,11 +81,14 @@ namespace i2p i2p::config::GetOption("log", isLogging); uint16_t port; i2p::config::GetOption("port", port); - if (port) - i2p::context.UpdatePort (port); + LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port); + i2p::context.UpdatePort (port); + std::string host; i2p::config::GetOption("host", host); - if (host != "") + if (host != "") { + LogPrint(eLogInfo, "Daemon: address for incoming connections is ", host); i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host)); + } bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool transit; i2p::config::GetOption("notransit", transit); From 9774865d4a18acca901d502bde972108be8e9a1d Mon Sep 17 00:00:00 2001 From: hagen Date: Tue, 26 Jan 2016 00:00:00 +0000 Subject: [PATCH 26/32] * docs/configuration.md --- docs/configuration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 64925d4b..a48f0f66 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -32,6 +32,8 @@ Command line options * --socksproxy.address= - The address to listen on (SOCKS Proxy) * --socksproxy.port= - The port to listen on (SOCKS Proxy). 4447 by default * --socksproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS) +* --socksproxy.outproxy= - Address of outproxy. requests outside i2p will go there +* --socksproxy.outproxyport= - Outproxy remote port * --sam.address= - The address to listen on (SAM bridge) * --sam.port= - Port of SAM bridge. Usually 7656. SAM is off if not specified From d6d6ae8af2c8423eb02dc6ae319321959c9a5bd2 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 27 Jan 2016 00:00:00 +0000 Subject: [PATCH 27/32] * Config.cpp : add old options remapping (revert this after 2.6.0) --- Config.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/Config.cpp b/Config.cpp index 1b0c3072..27753c87 100644 --- a/Config.cpp +++ b/Config.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,83 @@ namespace config { options_description m_OptionsDesc; variables_map m_Options; + /* list of renamed options */ + std::map remapped_options = { + { "tunnelscfg", "tunconf" }, + { "v6", "ipv6" }, + { "httpaddress", "http.address" }, + { "httpport", "http.port" }, + { "httpproxyaddress", "httpproxy.address" }, + { "httpproxyport", "httpproxy.port" }, + { "socksproxyaddress", "socksproxy.address" }, + { "socksproxyport", "socksproxy.port" }, + { "samaddress", "sam.address" }, + { "samport", "sam.port" }, + { "bobaddress", "bob.address" }, + { "bobport", "bob.port" }, + { "i2pcontroladdress", "i2pcontrol.address" }, + { "i2pcontroladdress", "i2pcontrol.port" }, + { "proxykeys", "httpproxy.keys" }, + }; + /* list of options, that loose their argument and become simple switch */ + std::set boolean_options = { + "daemon", "log", "floodfill", "notransit", "service", "ipv6" + }; + + /* this function is a solid piece of shit, remove it after 2.6.0 */ + std::pair old_syntax_parser(const std::string& s) { + std::string name = ""; + std::string value = ""; + std::size_t pos = 0; + /* shortcuts -- -h */ + if (s.length() == 2 && s.at(0) == '-' && s.at(1) != '-') + return make_pair(s.substr(1), ""); + /* old-style -- -log, /log, etc */ + if (s.at(0) == '/' || (s.at(0) == '-' && s.at(1) != '-')) { + if ((pos = s.find_first_of("= ")) != std::string::npos) { + name = s.substr(1, pos - 1); + value = s.substr(pos + 1); + } else { + name = s.substr(1, pos); + value = ""; + } + if (boolean_options.count(name) > 0 && value != "") + std::cerr << "args: don't give an argument to switch option: " << s << std::endl; + if (m_OptionsDesc.find_nothrow(name, false)) { + std::cerr << "args: option " << s << " style is DEPRECATED, use --" << name << " instead" << std::endl; + return std::make_pair(name, value); + } + if (remapped_options.count(name) > 0) { + name = remapped_options[name]; + std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl; + return std::make_pair(name, value); + } /* else */ + } + /* long options -- --help */ + if (s.substr(0, 2) == "--") { + if ((pos = s.find_first_of("= ")) != std::string::npos) { + name = s.substr(2, pos - 2); + value = s.substr(pos + 1); + } else { + name = s.substr(2, pos); + value = ""; + } + if (boolean_options.count(name) > 0 && value != "") { + std::cerr << "args: don't give an argument to switch option: " << s << std::endl; + value = ""; + } + if (m_OptionsDesc.find_nothrow(name, false)) + return std::make_pair(name, value); + if (remapped_options.count(name) > 0) { + name = remapped_options[name]; + std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl; + return std::make_pair(name, value); + } /* else */ + } + std::cerr << "args: unknown option -- " << s << std::endl; + return std::make_pair("", ""); + } + void Init() { options_description general("General options"); general.add_options() @@ -104,13 +182,16 @@ namespace config { void ParseCmdline(int argc, char* argv[]) { try { - store(parse_command_line(argc, argv, m_OptionsDesc), m_Options); + auto style = boost::program_options::command_line_style::unix_style + | boost::program_options::command_line_style::allow_long_disguise; + style &= ~ boost::program_options::command_line_style::allow_guessing; + store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options); } catch (boost::program_options::error e) { std::cerr << "args: " << e.what() << std::endl; exit(EXIT_FAILURE); } - if (m_Options.count("help")) { + if (m_Options.count("help") || m_Options.count("h")) { std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; std::cout << m_OptionsDesc; exit(EXIT_SUCCESS); From 0c56cd63bdd7f8b8c8cf60843a0ed7ed86660b49 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 1 Feb 2016 00:00:00 +0000 Subject: [PATCH 28/32] * chg default port for http proxy --- Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.cpp b/Config.cpp index 27753c87..ab99f293 100644 --- a/Config.cpp +++ b/Config.cpp @@ -133,7 +133,7 @@ namespace config { httpproxy.add_options() ("httpproxy.enabled", value()->default_value(true), "Enable or disable HTTP Proxy") ("httpproxy.address", value()->default_value("127.0.0.1"), "HTTP Proxy listen address") - ("httpproxy.port", value()->default_value(4446), "HTTP Proxy listen port") + ("httpproxy.port", value()->default_value(4444), "HTTP Proxy listen port") ("httpproxy.keys", value()->default_value("httpproxy-keys.dat"), "HTTP Proxy encryption keys") ; From d2d4fa29e4fac1fee522d41910a6b486a381fa48 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 1 Feb 2016 00:00:00 +0000 Subject: [PATCH 29/32] * add --logfile option --- Config.cpp | 1 + Daemon.cpp | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Config.cpp b/Config.cpp index ab99f293..a29e4b02 100644 --- a/Config.cpp +++ b/Config.cpp @@ -111,6 +111,7 @@ namespace config { ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") ("pidfile", value()->default_value(""), "Write pidfile to given path") ("log", value()->zero_tokens(), "Write logs to file instead stdout") + ("logfile", value()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") ("loglevel", value()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") ("host", value()->default_value(""), "External IP (deprecated)") ("port,p", value()->default_value(4567), "Port to listen for incoming connections") diff --git a/Daemon.cpp b/Daemon.cpp index a2d33720..a0c3f5bb 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -116,22 +116,25 @@ namespace i2p bool Daemon_Singleton::start() { - // initialize log if (isLogging) { - if (isDaemon) - { - std::string logfile_path = IsService () ? "/var/log" : i2p::util::filesystem::GetDataDir().string(); + // set default to stdout + std::string logfile = ""; i2p::config::GetOption("logfile", logfile); + std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel); + if (isDaemon && logfile == "") { + // can't log to stdout, use autodetect of logfile + if (IsService ()) { + logfile = "/var/log"; + } else { + logfile = i2p::util::filesystem::GetDataDir().string(); + } #ifndef _WIN32 - logfile_path.append("/i2pd.log"); + logfile.append("/i2pd.log"); #else - logfile_path.append("\\i2pd.log"); + logfile.append("\\i2pd.log"); #endif - StartLog (logfile_path); - } else { - StartLog (""); // write to stdout } - std::string loglevel; i2p::config::GetOption("loglevel", loglevel); + StartLog (logfile); g_Log->SetLogLevel(loglevel); } From 8baf7f3f6abe98016be0af89601f25f846e6c9b9 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 1 Feb 2016 00:00:00 +0000 Subject: [PATCH 30/32] * temporary remove short options : conflicts with remapping --- Config.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Config.cpp b/Config.cpp index a29e4b02..536277b4 100644 --- a/Config.cpp +++ b/Config.cpp @@ -106,16 +106,16 @@ namespace config { void Init() { options_description general("General options"); general.add_options() - ("help,h", "Show this message") - ("conf,c", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf)") + ("help", "Show this message") + ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf)") ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") ("pidfile", value()->default_value(""), "Write pidfile to given path") ("log", value()->zero_tokens(), "Write logs to file instead stdout") ("logfile", value()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") ("loglevel", value()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") ("host", value()->default_value(""), "External IP (deprecated)") - ("port,p", value()->default_value(4567), "Port to listen for incoming connections") - ("ipv6,6", value()->zero_tokens()->default_value(false), "Enable communication through ipv6") + ("port", value()->default_value(4567), "Port to listen for incoming connections") + ("ipv6", value()->zero_tokens()->default_value(false), "Enable communication through ipv6") ("daemon", value()->zero_tokens()->default_value(false), "Router will go to background after start") ("service", value()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'") ("notransit", value()->zero_tokens()->default_value(false), "Router will not forward transit traffic") From ed44d23afb6f04744a63212e7e27b8ab83d5a8e0 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 1 Feb 2016 00:00:00 +0000 Subject: [PATCH 31/32] * update docs/ --- docs/configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configuration.md b/docs/configuration.md index a48f0f66..e16240ba 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -10,6 +10,7 @@ Command line options * --tunconf= - Tunnels Config file (default: ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg) * --pidfile= - Where to write pidfile (dont write by default) * --log - Enable or disable logging to file. 1 for yes, 0 for no. +* --logfile= - Path to logfile (stdout if not set, autodetect if daemon) * --loglevel= - Log messages above this level (debug, *info, warn, error) * --host= - The external IP (deprecated) * --port= - The port to listen on From deb87f1d4cbb974969f2bea91ccfb24b57972132 Mon Sep 17 00:00:00 2001 From: hagen Date: Mon, 1 Feb 2016 00:00:00 +0000 Subject: [PATCH 32/32] * for compatibility - leave --log option with arg --- Config.cpp | 4 ++-- Daemon.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Config.cpp b/Config.cpp index 536277b4..60af0319 100644 --- a/Config.cpp +++ b/Config.cpp @@ -46,7 +46,7 @@ namespace config { }; /* list of options, that loose their argument and become simple switch */ std::set boolean_options = { - "daemon", "log", "floodfill", "notransit", "service", "ipv6" + "daemon", "floodfill", "notransit", "service", "ipv6" }; /* this function is a solid piece of shit, remove it after 2.6.0 */ @@ -110,7 +110,7 @@ namespace config { ("conf", value()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf)") ("tunconf", value()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") ("pidfile", value()->default_value(""), "Write pidfile to given path") - ("log", value()->zero_tokens(), "Write logs to file instead stdout") + ("log", value()->default_value(""), "Write logs to file instead stdout") ("logfile", value()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") ("loglevel", value()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") ("host", value()->default_value(""), "External IP (deprecated)") diff --git a/Daemon.cpp b/Daemon.cpp index a0c3f5bb..ce8ad35c 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -78,7 +78,11 @@ namespace i2p i2p::context.Init (); i2p::config::GetOption("daemon", isDaemon); - i2p::config::GetOption("log", isLogging); + // temporary hack + std::string logs = ""; + i2p::config::GetOption("log", logs); + if (logs != "") + isLogging = true; uint16_t port; i2p::config::GetOption("port", port); LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);