mirror of https://github.com/PurpleI2P/i2pd.git
Browse Source
Conflicts: ClientContext.cpp Daemon.cpp I2PControl.cpp I2PControl.h docs/configuration.mdpull/358/head
hagen
9 years ago
21 changed files with 745 additions and 477 deletions
@ -0,0 +1,225 @@ |
|||||||
|
/*
|
||||||
|
* 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 <cstdlib> |
||||||
|
#include <iostream> |
||||||
|
#include <fstream> |
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
#include <boost/program_options/cmdline.hpp> |
||||||
|
#include <boost/program_options/options_description.hpp> |
||||||
|
#include <boost/program_options/parsers.hpp> |
||||||
|
#include <boost/program_options/variables_map.hpp> |
||||||
|
|
||||||
|
#include "Config.h" |
||||||
|
#include "version.h" |
||||||
|
|
||||||
|
using namespace boost::program_options; |
||||||
|
|
||||||
|
namespace i2p { |
||||||
|
namespace config { |
||||||
|
options_description m_OptionsDesc; |
||||||
|
variables_map m_Options; |
||||||
|
|
||||||
|
/* list of renamed options */ |
||||||
|
std::map<std::string, std::string> 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<std::string> boolean_options = { |
||||||
|
"daemon", "floodfill", "notransit", "service", "ipv6" |
||||||
|
}; |
||||||
|
|
||||||
|
/* this function is a solid piece of shit, remove it after 2.6.0 */ |
||||||
|
std::pair<std::string, std::string> 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() |
||||||
|
("help", "Show this message") |
||||||
|
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2p.conf or /var/lib/i2pd/i2p.conf)") |
||||||
|
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg)") |
||||||
|
("pidfile", value<std::string>()->default_value(""), "Write pidfile to given path") |
||||||
|
("log", value<std::string>()->default_value(""), "Write logs to file instead stdout") |
||||||
|
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)") |
||||||
|
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)") |
||||||
|
("host", value<std::string>()->default_value(""), "External IP (deprecated)") |
||||||
|
("port", value<uint16_t>()->default_value(4567), "Port to listen for incoming connections") |
||||||
|
("ipv6", value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6") |
||||||
|
("daemon", value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start") |
||||||
|
("service", value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'") |
||||||
|
("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not forward transit traffic") |
||||||
|
("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will try to become floodfill") |
||||||
|
("bandwidth", value<char>()->default_value('O'), "Bandwidth limiting: L - 32kbps, O - 256Kbps, P - unlimited (ignored if floodfill)") |
||||||
|
; |
||||||
|
|
||||||
|
options_description httpserver("HTTP Server options"); |
||||||
|
httpserver.add_options() |
||||||
|
("http.enabled", value<bool>()->default_value(true), "Enable or disable webconsole") |
||||||
|
("http.address", value<std::string>()->default_value("127.0.0.1"), "Webconsole listen address") |
||||||
|
("http.port", value<uint16_t>()->default_value(7070), "Webconsole listen port") |
||||||
|
; |
||||||
|
|
||||||
|
options_description httpproxy("HTTP Proxy options"); |
||||||
|
httpproxy.add_options() |
||||||
|
("httpproxy.enabled", value<bool>()->default_value(true), "Enable or disable HTTP Proxy") |
||||||
|
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address") |
||||||
|
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port") |
||||||
|
("httpproxy.keys", value<std::string>()->default_value("httpproxy-keys.dat"), "HTTP Proxy encryption keys") |
||||||
|
; |
||||||
|
|
||||||
|
options_description socksproxy("SOCKS Proxy options"); |
||||||
|
socksproxy.add_options() |
||||||
|
("socksproxy.enabled", value<bool>()->default_value(true), "Enable or disable SOCKS Proxy") |
||||||
|
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address") |
||||||
|
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port") |
||||||
|
("socksproxy.keys", value<std::string>()->default_value("socksproxy-keys.dat"), "SOCKS Proxy encryption keys") |
||||||
|
; |
||||||
|
|
||||||
|
options_description sam("SAM bridge options"); |
||||||
|
sam.add_options() |
||||||
|
("sam.enabled", value<bool>()->default_value(false), "Enable or disable SAM Application bridge") |
||||||
|
("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address") |
||||||
|
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port") |
||||||
|
; |
||||||
|
|
||||||
|
options_description bob("BOB options"); |
||||||
|
bob.add_options() |
||||||
|
("bob.enabled", value<bool>()->default_value(false), "Enable or disable BOB command channel") |
||||||
|
("bob.address", value<std::string>()->default_value("127.0.0.1"), "BOB listen address") |
||||||
|
("bob.port", value<uint16_t>()->default_value(2827), "BOB listen port") |
||||||
|
; |
||||||
|
|
||||||
|
options_description i2pcontrol("I2PControl options"); |
||||||
|
i2pcontrol.add_options() |
||||||
|
("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol") |
||||||
|
("i2pcontrol.address", value<std::string>()->default_value("127.0.0.1"), "I2PCP listen address") |
||||||
|
("i2pcontrol.port", value<uint16_t>()->default_value(7650), "I2PCP listen port") |
||||||
|
("i2pcontrol.password", value<std::string>()->default_value("itoopie"), "I2PCP access password") |
||||||
|
("i2pcontrol.cert", value<std::string>()->default_value("i2pcontrol.crt.pem"), "I2PCP connection cerificate") |
||||||
|
("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key") |
||||||
|
; |
||||||
|
|
||||||
|
m_OptionsDesc |
||||||
|
.add(general) |
||||||
|
.add(httpserver) |
||||||
|
.add(httpproxy) |
||||||
|
.add(socksproxy) |
||||||
|
.add(sam) |
||||||
|
.add(bob) |
||||||
|
.add(i2pcontrol) |
||||||
|
; |
||||||
|
} |
||||||
|
|
||||||
|
void ParseCmdline(int argc, char* argv[]) { |
||||||
|
try { |
||||||
|
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") || m_Options.count("h")) { |
||||||
|
std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl; |
||||||
|
std::cout << m_OptionsDesc; |
||||||
|
exit(EXIT_SUCCESS); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ParseConfig(const std::string& path) { |
||||||
|
if (path == "") |
||||||
|
return; |
||||||
|
|
||||||
|
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
|
@ -0,0 +1,100 @@ |
|||||||
|
#ifndef CONFIG_H |
||||||
|
#define CONFIG_H |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <boost/program_options/options_description.hpp> |
||||||
|
#include <boost/program_options/variables_map.hpp> |
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<typename T> |
||||||
|
bool GetOption(const char *name, T& value) { |
||||||
|
if (!m_Options.count(name)) |
||||||
|
return false; |
||||||
|
value = m_Options[name].as<T>(); |
||||||
|
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<typename T> |
||||||
|
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
|
@ -1,16 +1,19 @@ |
|||||||
floodfill=0 |
ipv6 |
||||||
v6=0 |
|
||||||
|
|
||||||
httpproxyaddress=127.0.0.1 |
[httpproxy] |
||||||
httpproxyport=4444 |
address = 127.0.0.1 |
||||||
|
port = 4444 |
||||||
|
|
||||||
# other services (disabled by default) |
# other services (disabled by default) |
||||||
# |
# |
||||||
# samaddress=127.0.0.1 |
#[sam] |
||||||
# samport=7656 |
#address = 127.0.0.1 |
||||||
|
#port = 7656 |
||||||
# |
# |
||||||
# bobaddress=127.0.0.1 |
#[bob] |
||||||
# bobport=2827 |
#address = 127.0.0.1 |
||||||
|
#port = 2827 |
||||||
# |
# |
||||||
# i2pcontroladdress=127.0.0.1 |
#[i2pcontrol] |
||||||
# i2pcontrolport=7650 |
#address = 127.0.0.1 |
||||||
|
#port = 7650 |
||||||
|
@ -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 - тоже |
Loading…
Reference in new issue