mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
commit
0ef3a2472d
@ -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");
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <iostream>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include "Config.h"
|
||||
#include "util.h"
|
||||
#include "Log.h"
|
||||
#include "Identity.h"
|
||||
@ -37,46 +38,58 @@ namespace client
|
||||
}
|
||||
|
||||
std::shared_ptr<ClientDestination> 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", 4444);
|
||||
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);
|
||||
std::string socksOutProxyAddr = i2p::util::config::GetArg("-socksoutproxyaddress", "");
|
||||
uint16_t socksOutProxyPort = i2p::util::config::GetArg("-socksoutproxyport", 0);
|
||||
LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort);
|
||||
m_SocksProxy = new i2p::proxy::SOCKSProxy(socksProxyAddr, socksProxyPort, socksOutProxyAddr, socksOutProxyPort, 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);
|
||||
std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr);
|
||||
uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort);
|
||||
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, socksOutProxyAddr, socksOutProxyPort, 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 ();
|
||||
@ -87,15 +100,19 @@ namespace client
|
||||
|
||||
void ClientContext::Stop ()
|
||||
{
|
||||
LogPrint(eLogInfo, "Clients: stopping HTTP Proxy");
|
||||
m_HttpProxy->Stop();
|
||||
delete m_HttpProxy;
|
||||
m_HttpProxy = nullptr;
|
||||
if (m_HttpProxy) {
|
||||
LogPrint(eLogInfo, "Clients: stopping HTTP Proxy");
|
||||
m_HttpProxy->Stop();
|
||||
delete m_HttpProxy;
|
||||
m_HttpProxy = nullptr;
|
||||
}
|
||||
|
||||
LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy");
|
||||
m_SocksProxy->Stop();
|
||||
delete m_SocksProxy;
|
||||
m_SocksProxy = nullptr;
|
||||
if (m_SocksProxy) {
|
||||
LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy");
|
||||
m_SocksProxy->Stop();
|
||||
delete m_SocksProxy;
|
||||
m_SocksProxy = nullptr;
|
||||
}
|
||||
|
||||
for (auto& it: m_ClientTunnels)
|
||||
{
|
||||
|
228
Config.cpp
Normal file
228
Config.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
|
||||
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility)")
|
||||
("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("0.0.0.0"), "External IP")
|
||||
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
|
||||
("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 accept transit tunnels at startup")
|
||||
("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will be floodfill")
|
||||
("bandwidth", value<char>()->default_value('-'), "Bandwidth limiting: L - 32kbps, O - 256Kbps, P - unlimited")
|
||||
#ifdef _WIN32
|
||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||
#endif
|
||||
;
|
||||
|
||||
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(""), "File to persist HTTP Proxy 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(""), "File to persist SOCKS Proxy 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
|
100
Config.h
Normal file
100
Config.h
Normal file
@ -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
|
148
Daemon.cpp
148
Daemon.cpp
@ -3,6 +3,7 @@
|
||||
|
||||
#include "Daemon.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
#include "Base.h"
|
||||
#include "version.h"
|
||||
@ -50,78 +51,121 @@ 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);
|
||||
|
||||
std::string config = i2p::util::filesystem::GetConfigFile().string();
|
||||
std::string tunconf = i2p::util::filesystem::GetTunnelsConfigFile().string();
|
||||
std::string datadir = i2p::util::filesystem::GetDataDir().string();
|
||||
|
||||
i2p::config::ParseConfig(config);
|
||||
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());
|
||||
i2p::config::GetOption("daemon", isDaemon);
|
||||
|
||||
isDaemon = i2p::util::config::GetArg("-daemon", 0);
|
||||
isLogging = i2p::util::config::GetArg("-log", (int)isDaemon);
|
||||
// TODO: move log init here
|
||||
|
||||
int port = i2p::util::config::GetArg("-port", 0);
|
||||
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);
|
||||
|
||||
uint16_t port; i2p::config::GetOption("port", port);
|
||||
if (port)
|
||||
i2p::context.UpdatePort (port);
|
||||
std::string host = i2p::util::config::GetArg("-host", "");
|
||||
if (host != "")
|
||||
i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host));
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
|
||||
i2p::context.UpdatePort (port);
|
||||
}
|
||||
|
||||
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);
|
||||
i2p::context.SetFloodfill (isFloodfill);
|
||||
auto bandwidth = i2p::util::config::GetArg("-bandwidth", "");
|
||||
if (bandwidth.length () > 0)
|
||||
std::string host; i2p::config::GetOption("host", host);
|
||||
if (host != "0.0.0.0")
|
||||
{
|
||||
if (bandwidth[0] > 'O')
|
||||
i2p::context.SetExtraBandwidth ();
|
||||
else if (bandwidth[0] > 'L')
|
||||
i2p::context.SetHighBandwidth ();
|
||||
else
|
||||
LogPrint(eLogInfo, "Daemon: setting address for incoming connections to ", 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);
|
||||
i2p::context.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetAcceptsTunnels (!transit);
|
||||
|
||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||
char bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
|
||||
|
||||
if (isFloodfill)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
||||
i2p::context.SetFloodfill (true);
|
||||
}
|
||||
if (bandwidth != '-')
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: bandwidth set to ", bandwidth);
|
||||
if (bandwidth > 'O')
|
||||
i2p::context.SetExtraBandwidth ();
|
||||
else if (bandwidth > 'L')
|
||||
i2p::context.SetHighBandwidth ();
|
||||
else
|
||||
i2p::context.SetLowBandwidth ();
|
||||
}
|
||||
else if (isFloodfill)
|
||||
else if (isFloodfill)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'");
|
||||
i2p::context.SetExtraBandwidth ();
|
||||
LogPrint(eLogDebug, "Daemon: CMD parameters:");
|
||||
for (int i = 0; i < argc; ++i)
|
||||
LogPrint(eLogDebug, i, ": ", argv[i]);
|
||||
}
|
||||
else
|
||||
i2p::context.SetLowBandwidth ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Daemon_Singleton::start()
|
||||
{
|
||||
// initialize log
|
||||
if (isLogging)
|
||||
{
|
||||
std::string logfile_path = IsService () ? "/var/log/i2pd" : i2p::util::filesystem::GetDataDir().string();
|
||||
std::string logs = ""; i2p::config::GetOption("log", logs);
|
||||
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
|
||||
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
|
||||
|
||||
if (isDaemon && (logs == "" || logs == "stdout"))
|
||||
logs = "file";
|
||||
|
||||
if (logs == "file")
|
||||
{
|
||||
if (logfile == "")
|
||||
{
|
||||
// use autodetect of logfile
|
||||
logfile = IsService () ? "/var/log" : 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);
|
||||
}
|
||||
StartLog (logfile);
|
||||
} else {
|
||||
// use stdout
|
||||
StartLog ("");
|
||||
}
|
||||
else
|
||||
StartLog (""); // write to stdout
|
||||
g_Log->SetLogLevel(i2p::util::config::GetArg("-loglevel", "info"));
|
||||
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<i2p::util::HTTPServer>(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: starting HTTP Server at ", httpAddr, ":", httpPort);
|
||||
d.httpServer = std::unique_ptr<i2p::util::HTTPServer>(new i2p::util::HTTPServer(httpAddr, httpPort));
|
||||
d.httpServer->Start();
|
||||
}
|
||||
|
||||
LogPrint(eLogInfo, "Daemon: starting NetDB");
|
||||
i2p::data::netdb.Start();
|
||||
@ -140,10 +184,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<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||
d.m_I2PControlService->Start ();
|
||||
@ -166,9 +210,11 @@ namespace i2p
|
||||
i2p::transport::transports.Stop();
|
||||
LogPrint(eLogInfo, "Daemon: stopping NetDB");
|
||||
i2p::data::netdb.Stop();
|
||||
LogPrint(eLogInfo, "Daemon: stopping HTTP Server");
|
||||
d.httpServer->Stop();
|
||||
d.httpServer = nullptr;
|
||||
if (d.httpServer) {
|
||||
LogPrint(eLogInfo, "Daemon: stopping HTTP Server");
|
||||
d.httpServer->Stop();
|
||||
d.httpServer = nullptr;
|
||||
}
|
||||
if (d.m_I2PControlService)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: stopping I2PControl");
|
||||
|
@ -8,10 +8,10 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -80,6 +80,15 @@ namespace i2p
|
||||
LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length");
|
||||
return msg;
|
||||
}
|
||||
|
||||
std::shared_ptr<I2NPMessage> CopyI2NPMessage (std::shared_ptr<I2NPMessage> msg)
|
||||
{
|
||||
if (!msg) return nullptr;
|
||||
auto newMsg = NewI2NPMessage (msg->len);
|
||||
newMsg->offset = msg->offset;
|
||||
*newMsg = *msg;
|
||||
return newMsg;
|
||||
}
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
|
||||
{
|
||||
|
@ -174,7 +174,7 @@ namespace tunnel
|
||||
from = other.from;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// for SSU only
|
||||
uint8_t * GetSSUHeader () { return buf + offset + I2NP_HEADER_SIZE - I2NP_SHORT_HEADER_SIZE; };
|
||||
void FromSSU (uint32_t msgID) // we have received SSU message and convert it to regular
|
||||
@ -215,7 +215,8 @@ namespace tunnel
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0);
|
||||
std::shared_ptr<I2NPMessage> CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from = nullptr);
|
||||
|
||||
std::shared_ptr<I2NPMessage> CopyI2NPMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID);
|
||||
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
|
||||
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
||||
|
385
I2PControl.cpp
385
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 <stdio.h>
|
||||
#include <sstream>
|
||||
#include <openssl/x509.h>
|
||||
@ -8,10 +6,15 @@
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
|
||||
// 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 <boost/property_tree/json_parser.hpp>
|
||||
#endif
|
||||
|
||||
#include "Log.h"
|
||||
#include "Config.h"
|
||||
#include "NetDb.h"
|
||||
#include "RouterContext.h"
|
||||
#include "Daemon.h"
|
||||
@ -26,56 +29,62 @@ 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)
|
||||
{
|
||||
LoadConfig ();
|
||||
// certificate
|
||||
i2p::config::GetOption("i2pcontrol.password", m_Password);
|
||||
|
||||
// certificate / keys
|
||||
std::string i2pcp_crt; i2p::config::GetOption("i2pcontrol.cert", i2pcp_crt);
|
||||
std::string i2pcp_key; i2p::config::GetOption("i2pcontrol.key", i2pcp_key);
|
||||
auto path = GetPath ();
|
||||
if (!boost::filesystem::exists (path))
|
||||
// TODO: move this to i2p::fs::expand
|
||||
if (i2pcp_crt.at(0) != '/')
|
||||
i2pcp_crt.insert(0, (path / "/").string());
|
||||
if (i2pcp_key.at(0) != '/')
|
||||
i2pcp_key.insert(0, (path / "/").string());
|
||||
if (!boost::filesystem::exists (i2pcp_crt) ||
|
||||
!boost::filesystem::exists (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());
|
||||
} else {
|
||||
LogPrint(eLogDebug, "I2PControl: using cert from ", i2pcp_crt);
|
||||
}
|
||||
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 (i2pcp_crt, boost::asio::ssl::context::pem);
|
||||
m_SSLContext.use_private_key_file (i2pcp_key, 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;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||
|
||||
// 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 ()
|
||||
@ -83,49 +92,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 ());
|
||||
}
|
||||
}
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::Start ()
|
||||
{
|
||||
if (!m_IsRunning)
|
||||
@ -141,28 +107,25 @@ namespace client
|
||||
if (m_IsRunning)
|
||||
{
|
||||
m_IsRunning = false;
|
||||
m_Acceptor.cancel ();
|
||||
m_Acceptor.cancel ();
|
||||
m_Service.stop ();
|
||||
if (m_Thread)
|
||||
{
|
||||
m_Thread->join ();
|
||||
{
|
||||
m_Thread->join ();
|
||||
delete m_Thread;
|
||||
m_Thread = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::Run ()
|
||||
{
|
||||
void I2PControlService::Run ()
|
||||
{
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,13 +142,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<ssl_socket> socket)
|
||||
@ -196,13 +158,12 @@ namespace client
|
||||
|
||||
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> 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<ssl_socket> socket)
|
||||
@ -210,24 +171,22 @@ namespace client
|
||||
auto request = std::make_shared<I2PControlBuffer>();
|
||||
socket->async_read_some (
|
||||
#if defined(BOOST_ASIO_HAS_STD_ARRAY)
|
||||
boost::asio::buffer (*request),
|
||||
boost::asio::buffer (*request),
|
||||
#else
|
||||
boost::asio::buffer (request->data (), request->size ()),
|
||||
#endif
|
||||
std::bind(&I2PControlService::HandleRequestReceived, this,
|
||||
boost::asio::buffer (request->data (), request->size ()),
|
||||
#endif
|
||||
std::bind(&I2PControlService::HandleRequestReceived, this,
|
||||
std::placeholders::_1, std::placeholders::_2, socket, request));
|
||||
}
|
||||
|
||||
void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode,
|
||||
size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
|
||||
size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
|
||||
std::shared_ptr<I2PControlBuffer> 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);
|
||||
@ -238,12 +197,12 @@ namespace client
|
||||
std::string header;
|
||||
size_t contentLength = 0;
|
||||
while (!ss.eof () && header != "\r")
|
||||
{
|
||||
{
|
||||
std::getline(ss, header);
|
||||
auto colon = header.find (':');
|
||||
if (colon != std::string::npos && header.substr (0, colon) == "Content-Length")
|
||||
contentLength = std::stoi (header.substr (colon + 1));
|
||||
}
|
||||
}
|
||||
if (ss.eof ())
|
||||
{
|
||||
LogPrint (eLogError, "Malformed I2PControl request. HTTP header expected");
|
||||
@ -251,10 +210,10 @@ namespace client
|
||||
}
|
||||
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read
|
||||
if (rem > 0)
|
||||
{
|
||||
{
|
||||
bytes_transferred = boost::asio::read (*socket, boost::asio::buffer (buf->data (), rem));
|
||||
ss.write (buf->data (), bytes_transferred);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if GCC47_BOOST149
|
||||
LogPrint (eLogError, "json_read is not supported due bug in boost 1.49 with gcc 4.7");
|
||||
@ -262,17 +221,17 @@ namespace client
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::read_json (ss, pt);
|
||||
|
||||
std::string method = pt.get<std::string>(I2P_CONTROL_PROPERTY_METHOD);
|
||||
std::string id = pt.get<std::string>("id");
|
||||
std::string method = pt.get<std::string>("method");
|
||||
auto it = m_MethodHandlers.find (method);
|
||||
if (it != m_MethodHandlers.end ())
|
||||
{
|
||||
std::ostringstream response;
|
||||
response << "{\"id\":" << pt.get<std::string>(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);
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "Unknown I2PControl method ", method);
|
||||
#endif
|
||||
@ -291,21 +250,21 @@ namespace client
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
|
||||
{
|
||||
ss << "\"" << name << "\":" << value;
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const
|
||||
{
|
||||
ss << "\"" << name << "\":";
|
||||
ss << "\"" << name << "\":";
|
||||
if (value.length () > 0)
|
||||
ss << "\"" << value << "\"";
|
||||
else
|
||||
ss << "null";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, double value) const
|
||||
{
|
||||
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
|
||||
@ -321,48 +280,49 @@ namespace client
|
||||
header << "Date: ";
|
||||
auto facet = new boost::local_time::local_time_facet ("%a, %d %b %Y %H:%M:%S GMT");
|
||||
header.imbue(std::locale (header.getloc(), facet));
|
||||
header << boost::posix_time::second_clock::local_time() << "\r\n";
|
||||
header << boost::posix_time::second_clock::local_time() << "\r\n";
|
||||
header << "\r\n";
|
||||
offset = header.str ().size ();
|
||||
memcpy (buf->data (), header.str ().c_str (), offset);
|
||||
}
|
||||
}
|
||||
memcpy (buf->data () + offset, response.str ().c_str (), len);
|
||||
boost::asio::async_write (*socket, boost::asio::buffer (buf->data (), offset + len),
|
||||
boost::asio::async_write (*socket, boost::asio::buffer (buf->data (), offset + len),
|
||||
boost::asio::transfer_all (),
|
||||
std::bind(&I2PControlService::HandleResponseSent, this,
|
||||
std::bind(&I2PControlService::HandleResponseSent, this,
|
||||
std::placeholders::_1, std::placeholders::_2, socket, buf));
|
||||
}
|
||||
|
||||
void I2PControlService::HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred,
|
||||
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf)
|
||||
{
|
||||
if (ecode)
|
||||
LogPrint (eLogError, "I2PControl write error: ", ecode.message ());
|
||||
if (ecode) {
|
||||
LogPrint (eLogError, "I2PControl: write error: ", ecode.message ());
|
||||
}
|
||||
}
|
||||
|
||||
// handlers
|
||||
|
||||
void I2PControlService::AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
int api = params.get<int> (I2P_CONTROL_PARAM_API);
|
||||
auto password = params.get<std::string> (I2P_CONTROL_PARAM_PASSWORD);
|
||||
LogPrint (eLogDebug, "I2PControl Authenticate API=", api, " Password=", password);
|
||||
int api = params.get<int> ("API");
|
||||
auto password = params.get<std::string> ("Password");
|
||||
LogPrint (eLogDebug, "I2PControl: Authenticate API=", api, " Password=", password);
|
||||
if (password != m_Password) {
|
||||
LogPrint (eLogError, "I2PControl: Authenticate - Invalid password: ", password);
|
||||
return;
|
||||
}
|
||||
InsertParam (results, I2P_CONTROL_PARAM_API, api);
|
||||
InsertParam (results, "API", api);
|
||||
results << ",";
|
||||
std::string token = boost::lexical_cast<std::string>(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<std::string> (I2P_CONTROL_PARAM_ECHO);
|
||||
auto echo = params.get<std::string> ("Echo");
|
||||
LogPrint (eLogDebug, "I2PControl Echo Echo=", echo);
|
||||
InsertParam (results, I2P_CONTROL_PARAM_RESULT, echo);
|
||||
InsertParam (results, "Result", echo);
|
||||
}
|
||||
|
||||
|
||||
@ -370,120 +330,129 @@ 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 ())
|
||||
{
|
||||
(this->*(it1->second))(it.second.data ());
|
||||
InsertParam (results, it.first, "");
|
||||
(this->*(it1->second))(it.second.data ());
|
||||
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);
|
||||
LogPrint (eLogWarning, "I2PControl: new password=", value, ", to make it persistent you should update your config!");
|
||||
m_Password = value;
|
||||
m_Tokens.clear ();
|
||||
SaveConfig ();
|
||||
}
|
||||
|
||||
// RouterInfo
|
||||
|
||||
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 ())
|
||||
{
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2PControl RouterInfo unknown request ", it->first);
|
||||
LogPrint (eLogError, "I2PControl: RouterInfo unknown request ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void I2PControlService::NetTotalReceivedBytes (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.total.received.bytes", (double)i2p::transport::transports.GetTotalReceivedBytes ());
|
||||
}
|
||||
|
||||
void I2PControlService::NetTotalSentBytes (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||
}
|
||||
|
||||
// RouterManager
|
||||
|
||||
|
||||
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)
|
||||
void I2PControlService::ShutdownHandler (std::ostringstream& results)
|
||||
{
|
||||
LogPrint (eLogInfo, "Shutdown requested");
|
||||
InsertParam (results, I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN, "");
|
||||
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 (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
Daemon.running = 0;
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
|
||||
@ -491,42 +460,42 @@ 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, "");
|
||||
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 (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
Daemon.running = 0;
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
|
||||
void I2PControlService::ReseedHandler (std::ostringstream& results)
|
||||
{
|
||||
LogPrint (eLogInfo, "Reseed requested");
|
||||
InsertParam (results, I2P_CONTROL_ROUTER_MANAGER_SHUTDOWN, "");
|
||||
LogPrint (eLogInfo, "I2PControl: Reseed requested");
|
||||
InsertParam (results, "Reseed", "");
|
||||
i2p::data::netdb.Reseed ();
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ());
|
||||
@ -538,42 +507,38 @@ namespace client
|
||||
X509 * x509 = X509_new ();
|
||||
ASN1_INTEGER_set (X509_get_serialNumber (x509), 1);
|
||||
X509_gmtime_adj (X509_get_notBefore (x509), 0);
|
||||
X509_gmtime_adj (X509_get_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration
|
||||
X509_set_pubkey (x509, pkey); // public key
|
||||
X509_gmtime_adj (X509_get_notAfter (x509), I2P_CONTROL_CERTIFICATE_VALIDITY*24*60*60); // expiration
|
||||
X509_set_pubkey (x509, pkey); // public key
|
||||
X509_NAME * name = X509_get_subject_name (x509);
|
||||
X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *)"RU", -1, -1, 0); // country (Russia by default)
|
||||
X509_NAME_add_entry_by_txt (name, "O", MBSTRING_ASC, (unsigned char *)I2P_CONTROL_CERTIFICATE_ORGANIZATION, -1, -1, 0); // organization
|
||||
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);
|
||||
fclose (f);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "Can't open file ", filename);
|
||||
// certificate
|
||||
filename = GetPath () / I2P_CONTROL_CERT_FILE;
|
||||
f= fopen (filename.string ().c_str (), "wb");
|
||||
if (f)
|
||||
{
|
||||
|
||||
// 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);
|
||||
|
||||
X509_free (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));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
76
I2PControl.h
76
I2PControl.h
@ -20,56 +20,8 @@ namespace i2p
|
||||
namespace client
|
||||
{
|
||||
const size_t I2P_CONTROL_MAX_REQUEST_SIZE = 1024;
|
||||
typedef std::array<char, I2P_CONTROL_MAX_REQUEST_SIZE> I2PControlBuffer;
|
||||
typedef std::array<char, I2P_CONTROL_MAX_REQUEST_SIZE> 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_DEFAULT_PASSWORD[] = "itoopie";
|
||||
|
||||
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";
|
||||
|
||||
// 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";
|
||||
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";
|
||||
const char I2P_CONTROL_CERTIFICATE_ORGANIZATION[] = "Purple I2P";
|
||||
@ -87,25 +39,21 @@ namespace client
|
||||
|
||||
private:
|
||||
|
||||
void LoadConfig ();
|
||||
void SaveConfig ();
|
||||
|
||||
void Run ();
|
||||
void Accept ();
|
||||
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket);
|
||||
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket);
|
||||
void Handshake (std::shared_ptr<ssl_socket> socket);
|
||||
void HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket);
|
||||
void ReadRequest (std::shared_ptr<ssl_socket> socket);
|
||||
void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred,
|
||||
void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred,
|
||||
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
|
||||
void SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml);
|
||||
void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred,
|
||||
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
|
||||
|
||||
boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir() / I2P_CONTROL_PATH; };
|
||||
void CreateCertificate ();
|
||||
|
||||
boost::filesystem::path GetPath () const { return i2p::util::filesystem::GetDefaultDataDir(); };
|
||||
void CreateCertificate (const char *crt_path, const char *key_path);
|
||||
|
||||
private:
|
||||
|
||||
@ -121,7 +69,7 @@ namespace client
|
||||
void I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
|
||||
// I2PControl
|
||||
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
|
||||
@ -133,11 +81,13 @@ namespace client
|
||||
void VersionHandler (std::ostringstream& results);
|
||||
void StatusHandler (std::ostringstream& results);
|
||||
void NetDbKnownPeersHandler (std::ostringstream& results);
|
||||
void NetDbActivePeersHandler (std::ostringstream& results);
|
||||
void NetStatusHandler (std::ostringstream& results);
|
||||
void NetDbActivePeersHandler (std::ostringstream& results);
|
||||
void NetStatusHandler (std::ostringstream& results);
|
||||
void TunnelsParticipatingHandler (std::ostringstream& results);
|
||||
void InboundBandwidth1S (std::ostringstream& results);
|
||||
void OutboundBandwidth1S (std::ostringstream& results);
|
||||
void NetTotalReceivedBytes (std::ostringstream& results);
|
||||
void NetTotalSentBytes (std::ostringstream& results);
|
||||
|
||||
// RouterManager
|
||||
typedef void (I2PControlService::*RouterManagerRequestHandler)(std::ostringstream& results);
|
||||
@ -146,20 +96,20 @@ namespace client
|
||||
void ReseedHandler (std::ostringstream& results);
|
||||
|
||||
// NetworkSetting
|
||||
typedef void (I2PControlService::*NetworkSettingRequestHandler)(const std::string& value, std::ostringstream& results);
|
||||
typedef void (I2PControlService::*NetworkSettingRequestHandler)(const std::string& value, std::ostringstream& results);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Password;
|
||||
bool m_IsRunning;
|
||||
std::thread * m_Thread;
|
||||
std::thread * m_Thread;
|
||||
|
||||
boost::asio::io_service m_Service;
|
||||
boost::asio::ip::tcp::acceptor m_Acceptor;
|
||||
boost::asio::ssl::context m_SSLContext;
|
||||
boost::asio::deadline_timer m_ShutdownTimer;
|
||||
std::set<std::string> m_Tokens;
|
||||
|
||||
|
||||
std::map<std::string, MethodHandler> m_MethodHandlers;
|
||||
std::map<std::string, I2PControlRequestHandler> m_I2PControlHandlers;
|
||||
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
|
||||
|
@ -134,7 +134,7 @@ namespace client
|
||||
|
||||
void I2PTunnelConnection::Write (const uint8_t * buf, size_t len)
|
||||
{
|
||||
m_Socket->async_send (boost::asio::buffer (buf, len),
|
||||
boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, len), boost::asio::transfer_all (),
|
||||
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
|
||||
}
|
||||
|
||||
@ -184,11 +184,14 @@ namespace client
|
||||
std::getline(m_InHeader, line);
|
||||
if (!m_InHeader.fail ())
|
||||
{
|
||||
if (line.find ("Host:") != std::string::npos)
|
||||
m_OutHeader << "Host: " << m_Host << "\r\n";
|
||||
else
|
||||
m_OutHeader << line << "\n";
|
||||
if (line == "\r") endOfHeader = true;
|
||||
else
|
||||
{
|
||||
if (line.find ("Host:") != std::string::npos)
|
||||
m_OutHeader << "Host: " << m_Host << "\r\n";
|
||||
else
|
||||
m_OutHeader << line << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
@ -203,7 +206,8 @@ namespace client
|
||||
|
||||
if (endOfHeader)
|
||||
{
|
||||
m_OutHeader << m_InHeader.str (); // data right after header
|
||||
m_OutHeader << "\r\n"; // end of header
|
||||
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
||||
m_HeaderSent = true;
|
||||
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ namespace data
|
||||
}
|
||||
memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE);
|
||||
|
||||
delete[] m_ExtendedBuffer;
|
||||
delete[] m_ExtendedBuffer; m_ExtendedBuffer = nullptr;
|
||||
m_ExtendedLen = bufbe16toh (m_StandardIdentity.certificate + 1);
|
||||
if (m_ExtendedLen)
|
||||
{
|
||||
@ -211,6 +211,7 @@ namespace data
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "Identity: Certificate length ", m_ExtendedLen, " exceeds buffer length ", len - DEFAULT_IDENTITY_SIZE);
|
||||
m_ExtendedLen = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
13
LeaseSet.cpp
13
LeaseSet.cpp
@ -85,13 +85,24 @@ namespace data
|
||||
if (readIdentity || !m_Identity)
|
||||
m_Identity = std::make_shared<IdentityEx>(m_Buffer, m_BufferLen);
|
||||
size_t size = m_Identity->GetFullLen ();
|
||||
if (size > m_BufferLen)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", m_BufferLen);
|
||||
m_IsValid = false;
|
||||
return;
|
||||
}
|
||||
memcpy (m_EncryptionKey, m_Buffer + size, 256);
|
||||
size += 256; // encryption key
|
||||
size += m_Identity->GetSigningPublicKeyLen (); // unused signing key
|
||||
uint8_t num = m_Buffer[size];
|
||||
size++; // num
|
||||
LogPrint (eLogDebug, "LeaseSet: read num=", (int)num);
|
||||
if (!num) m_IsValid = false;
|
||||
if (!num || num > MAX_NUM_LEASES)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num);
|
||||
m_IsValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// process leases
|
||||
const uint8_t * leases = m_Buffer + size;
|
||||
|
@ -31,7 +31,8 @@ namespace data
|
||||
}
|
||||
};
|
||||
|
||||
const int MAX_LS_BUFFER_SIZE = 3072;
|
||||
const int MAX_LS_BUFFER_SIZE = 3072;
|
||||
const uint8_t MAX_NUM_LEASES = 16;
|
||||
class LeaseSet: public RoutingDestination
|
||||
{
|
||||
public:
|
||||
|
6
Log.h
6
Log.h
@ -95,6 +95,12 @@ inline void StopLog ()
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetLogLevel (const std::string& level)
|
||||
{
|
||||
if (g_Log)
|
||||
g_Log->SetLogLevel(level);
|
||||
}
|
||||
|
||||
template<typename TValue>
|
||||
void LogPrint (std::stringstream& s, TValue arg)
|
||||
{
|
||||
|
@ -1,7 +1,11 @@
|
||||
CXX = g++
|
||||
CXXFLAGS = -O2 -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||
NEEDED_CXXFLAGS = -std=c++11
|
||||
BOOST_SUFFIX = -mgw48-mt-1_59
|
||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/ -I/c/dev/openssl/include -I/c/dev/boost/include/boost-1_59
|
||||
BOOST_SUFFIX = -mt
|
||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/c/dev/openssl -L/c/dev/boost/lib
|
||||
LDLIBS = -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) -Wl,-Bstatic -lssl -Wl,-Bstatic -lcrypto -Wl,-Bstatic -lz -Wl,-Bstatic -lwsock32 -Wl,-Bstatic -lws2_32 -Wl,-Bstatic -lgdi32 -Wl,-Bstatic -liphlpapi -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -Wl,-Bstatic -lpthread
|
||||
|
||||
ifeq ($(USE_AESNI),1)
|
||||
CPU_FLAGS = -maes -DAESNI
|
||||
endif
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <fstream>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "Config.h"
|
||||
#include "Crypto.h"
|
||||
#include "Timestamp.h"
|
||||
#include "I2NPProtocol.h"
|
||||
@ -43,11 +44,14 @@ 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);
|
||||
if (host == "0.0.0.0")
|
||||
host = "127.0.0.1"; // replace default address with safe value
|
||||
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 ("netId", std::to_string (I2PD_NET_ID));
|
||||
|
@ -81,7 +81,7 @@ namespace data
|
||||
{
|
||||
s.seekg (0,std::ios::end);
|
||||
m_BufferLen = s.tellg ();
|
||||
if (m_BufferLen < 40)
|
||||
if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE)
|
||||
{
|
||||
LogPrint(eLogError, "RouterInfo: File", m_FullPath, " is malformed");
|
||||
return false;
|
||||
@ -109,13 +109,25 @@ namespace data
|
||||
{
|
||||
m_RouterIdentity = std::make_shared<IdentityEx>(m_Buffer, m_BufferLen);
|
||||
size_t identityLen = m_RouterIdentity->GetFullLen ();
|
||||
if (identityLen >= m_BufferLen)
|
||||
{
|
||||
LogPrint (eLogError, "RouterInfo: identity length ", identityLen, " exceeds buffer size ", m_BufferLen);
|
||||
m_IsUnreachable = true;
|
||||
return;
|
||||
}
|
||||
std::stringstream str (std::string ((char *)m_Buffer + identityLen, m_BufferLen - identityLen));
|
||||
ReadFromStream (str);
|
||||
if (!str)
|
||||
{
|
||||
LogPrint (eLogError, "RouterInfo: malformed message");
|
||||
m_IsUnreachable = true;
|
||||
return;
|
||||
}
|
||||
if (verifySignature)
|
||||
{
|
||||
// verify signature
|
||||
int l = m_BufferLen - m_RouterIdentity->GetSignatureLen ();
|
||||
if (!m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l))
|
||||
int l = m_BufferLen - m_RouterIdentity->GetSignatureLen ();
|
||||
if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l))
|
||||
{
|
||||
LogPrint (eLogError, "RouterInfo: signature verification failed");
|
||||
m_IsUnreachable = true;
|
||||
@ -130,7 +142,7 @@ namespace data
|
||||
m_Timestamp = be64toh (m_Timestamp);
|
||||
// read addresses
|
||||
uint8_t numAddresses;
|
||||
s.read ((char *)&numAddresses, sizeof (numAddresses));
|
||||
s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return;
|
||||
bool introducers = false;
|
||||
for (int i = 0; i < numAddresses; i++)
|
||||
{
|
||||
@ -149,7 +161,7 @@ namespace data
|
||||
address.port = 0;
|
||||
address.mtu = 0;
|
||||
uint16_t size, r = 0;
|
||||
s.read ((char *)&size, sizeof (size));
|
||||
s.read ((char *)&size, sizeof (size)); if (!s) return;
|
||||
size = be16toh (size);
|
||||
while (r < size)
|
||||
{
|
||||
@ -214,17 +226,18 @@ namespace data
|
||||
else if (!strcmp (key, "ikey"))
|
||||
Base64ToByteStream (value, strlen (value), introducer.iKey, 32);
|
||||
}
|
||||
if (!s) return;
|
||||
}
|
||||
if (isValidAddress)
|
||||
m_Addresses.push_back(address);
|
||||
}
|
||||
// read peers
|
||||
uint8_t numPeers;
|
||||
s.read ((char *)&numPeers, sizeof (numPeers));
|
||||
s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return;
|
||||
s.seekg (numPeers*32, std::ios_base::cur); // TODO: read peers
|
||||
// read properties
|
||||
uint16_t size, r = 0;
|
||||
s.read ((char *)&size, sizeof (size));
|
||||
s.read ((char *)&size, sizeof (size)); if (!s) return;
|
||||
size = be16toh (size);
|
||||
while (r < size)
|
||||
{
|
||||
@ -250,6 +263,7 @@ namespace data
|
||||
LogPrint (eLogError, "Unexpected netid=", value);
|
||||
m_IsUnreachable = true;
|
||||
}
|
||||
if (!s) return;
|
||||
}
|
||||
|
||||
if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers))
|
||||
|
@ -182,7 +182,7 @@ namespace data
|
||||
std::string m_FullPath;
|
||||
std::shared_ptr<const IdentityEx> m_RouterIdentity;
|
||||
uint8_t * m_Buffer;
|
||||
int m_BufferLen;
|
||||
size_t m_BufferLen;
|
||||
uint64_t m_Timestamp;
|
||||
std::vector<Address> m_Addresses;
|
||||
std::map<std::string, std::string> m_Properties;
|
||||
|
2
SAM.h
2
SAM.h
@ -41,7 +41,7 @@ namespace client
|
||||
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
|
||||
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
|
||||
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
|
||||
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%zu\n";
|
||||
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
|
||||
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
|
||||
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=INVALID_KEY_NOT_FOUND NAME=%s\n";
|
||||
const char SAM_PARAM_MIN[] = "MIN";
|
||||
|
@ -157,7 +157,7 @@ namespace transport
|
||||
memcpy (frag + 1, buf, 3);
|
||||
buf += 3;
|
||||
uint32_t fragmentInfo = bufbe32toh (frag); // fragment info
|
||||
uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13
|
||||
uint16_t fragmentSize = fragmentInfo & 0x3FFF; // bits 0 - 13
|
||||
bool isLast = fragmentInfo & 0x010000; // bit 16
|
||||
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17
|
||||
if (fragmentSize >= SSU_V4_MAX_PACKET_SIZE)
|
||||
|
@ -499,8 +499,9 @@ namespace transport
|
||||
{
|
||||
m_Service.post([session, this]()
|
||||
{
|
||||
if (!session->GetRemoteIdentity ()) return;
|
||||
auto ident = session->GetRemoteIdentity ()->GetIdentHash ();
|
||||
auto remoteIdentity = session->GetRemoteIdentity ();
|
||||
if (!remoteIdentity) return;
|
||||
auto ident = remoteIdentity->GetIdentHash ();
|
||||
auto it = m_Peers.find (ident);
|
||||
if (it != m_Peers.end ())
|
||||
{
|
||||
@ -520,8 +521,9 @@ namespace transport
|
||||
{
|
||||
m_Service.post([session, this]()
|
||||
{
|
||||
if (!session->GetRemoteIdentity ()) return;
|
||||
auto ident = session->GetRemoteIdentity ()->GetIdentHash ();
|
||||
auto remoteIdentity = session->GetRemoteIdentity ();
|
||||
if (!remoteIdentity) return;
|
||||
auto ident = remoteIdentity->GetIdentHash ();
|
||||
auto it = m_Peers.find (ident);
|
||||
if (it != m_Peers.end ())
|
||||
{
|
||||
|
@ -494,7 +494,7 @@ namespace tunnel
|
||||
if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply)
|
||||
// transit DatabaseStore my contain new/updated RI
|
||||
// or DatabaseSearchReply with new routers
|
||||
i2p::data::netdb.PostI2NPMsg (msg);
|
||||
i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg));
|
||||
tunnel->SendTunnelDataMsg (msg);
|
||||
}
|
||||
|
||||
|
@ -237,6 +237,11 @@ namespace tunnel
|
||||
}
|
||||
auto typeID = msg.data->GetTypeID ();
|
||||
LogPrint (eLogDebug, "TunnelMessage: handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID);
|
||||
// catch RI or reply with new list of routers
|
||||
if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) &&
|
||||
!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal)
|
||||
i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data));
|
||||
|
||||
switch (msg.deliveryType)
|
||||
{
|
||||
case eDeliveryTypeLocal:
|
||||
@ -257,10 +262,6 @@ namespace tunnel
|
||||
default:
|
||||
LogPrint (eLogError, "TunnelMessage: Unknown delivery type ", (int)msg.deliveryType);
|
||||
};
|
||||
// catch RI or reply with new list of routers
|
||||
if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) &&
|
||||
!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal)
|
||||
i2p::data::netdb.PostI2NPMsg (msg.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
api.cpp
5
api.cpp
@ -1,5 +1,6 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#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 ();
|
||||
}
|
||||
|
@ -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"
|
||||
@ -90,11 +91,6 @@ if (WITH_UPNP)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Default build is Debug
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif ()
|
||||
|
||||
# compiler flags customization (by vendor)
|
||||
if (MSVC)
|
||||
add_definitions( -D_WIN32_WINNT=_WIN32_WINNT_WINXP -DWIN32_LEAN_AND_MEAN -DNOMINMAX ) #-DOPENSSL_NO_SSL2 -DOPENSSL_USE_DEPRECATED
|
||||
@ -209,7 +205,7 @@ else()
|
||||
endif ()
|
||||
|
||||
if (WITH_PCH)
|
||||
include_directories(${CMAKE_BINARY_DIR})
|
||||
include_directories(BEFORE ${CMAKE_BINARY_DIR})
|
||||
add_library(stdafx STATIC "${CMAKE_SOURCE_DIR}/stdafx.cpp")
|
||||
if(MSVC)
|
||||
target_compile_options(stdafx PRIVATE /Ycstdafx.h /Zm155)
|
||||
@ -246,11 +242,9 @@ if(NOT DEFINED OPENSSL_INCLUDE_DIR)
|
||||
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
|
||||
endif()
|
||||
|
||||
find_package ( MiniUPnPc )
|
||||
if (MINIUPNPC_FOUND)
|
||||
include_directories( ${MINIUPNPC_INCLUDE_DIR} )
|
||||
else ()
|
||||
set(WITH_UPNP OFF)
|
||||
if (WITH_UPNP)
|
||||
find_package ( MiniUPnPc REQUIRED )
|
||||
include_directories( SYSTEM ${MINIUPNPC_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
find_package ( ZLIB )
|
||||
@ -289,7 +283,7 @@ endif ()
|
||||
link_directories(${CMAKE_CURRENT_BINARY_DIR}/zlib/lib ${ZLIB_ROOT}/lib)
|
||||
|
||||
# load includes
|
||||
include_directories( ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
|
||||
include_directories( SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
|
||||
|
||||
# show summary
|
||||
message(STATUS "---------------------------------------")
|
||||
|
23
debian/i2pd.conf
vendored
23
debian/i2pd.conf
vendored
@ -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
|
||||
|
2
debian/i2pd.init
vendored
2
debian/i2pd.init
vendored
@ -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 $?
|
||||
|
6
debian/i2pd.upstart
vendored
6
debian/i2pd.upstart
vendored
@ -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
|
||||
|
6
debian/postinst
vendored
6
debian/postinst
vendored
@ -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}
|
||||
;;
|
||||
|
@ -23,105 +23,24 @@ paths like /c/dev/ for C:\dev\.
|
||||
msys2
|
||||
-----
|
||||
|
||||
Get it from https://msys2.github.io and update it as described
|
||||
there. Use the installer appropriate for the bitness of your Windows
|
||||
OS. You will be able to build 32-bit applications if you install
|
||||
64-bit version of msys2. For 64-bit, use *mingw-w64-x86_64* prefix
|
||||
instead of *mingw-w64-i686* for the packages mentioned below, and use
|
||||
*/mingw64* as CMake find root.
|
||||
|
||||
Get install file msys2-i686-20150916.exe from https://msys2.github.io.
|
||||
open MSys2Shell (from Start menu).
|
||||
Install all prerequisites and download i2pd source:
|
||||
|
||||
```bash
|
||||
pacman -S mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc mingw-w64-i686-miniupnpc cmake git
|
||||
pacman -S mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc git make
|
||||
mkdir -p /c/dev/i2pd
|
||||
cd /c/dev/i2pd
|
||||
git clone https://github.com/PurpleI2P/i2pd.git
|
||||
cd i2pd
|
||||
```
|
||||
|
||||
Check with `git status` that you are on *openssl* branch. If it is not
|
||||
the case, do `git checkout openssl`.
|
||||
|
||||
```sh
|
||||
git pull origin openssl --ff-only # to update sources if you are rebuilding after a while
|
||||
mkdir -p mingw32.build # CMake build folder
|
||||
cd mingw32.build
|
||||
export PATH=/mingw32/bin:/usr/bin # we need compiler on PATH which is usually heavily cluttered on Windows
|
||||
cmake ../build -G "Unix Makefiles" -DWITH_UPNP=ON -DWITH_PCH=ON \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=../mingw32.stage -DCMAKE_FIND_ROOT_PATH=/mingw32
|
||||
make
|
||||
```
|
||||
|
||||
If your processor has
|
||||
[AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set),
|
||||
you may try adding `-DWITH_AESNI=ON`. No check is done however, it
|
||||
will compile but will crash with `Illegal instruction` if not supported.
|
||||
|
||||
Make sure CMake found proper libraries and compiler. This might be the
|
||||
case if you have Strawberry Perl installed as it alters PATH and you
|
||||
failed to override it like mentioned above. You should see something
|
||||
like
|
||||
|
||||
```
|
||||
-- The C compiler identification is GNU 5.2.0
|
||||
-- The CXX compiler identification is GNU 5.2.0
|
||||
-- Check for working C compiler: /mingw32/bin/gcc.exe
|
||||
-- Check for working C compiler: /mingw32/bin/gcc.exe -- works
|
||||
-- Detecting C compiler ABI info
|
||||
-- Detecting C compiler ABI info - done
|
||||
-- Detecting C compile features
|
||||
-- Detecting C compile features - done
|
||||
-- Check for working CXX compiler: /mingw32/bin/c++.exe
|
||||
-- Check for working CXX compiler: /mingw32/bin/c++.exe -- works
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Performing Test CXX11_SUPPORTED
|
||||
-- Performing Test CXX11_SUPPORTED - Success
|
||||
-- Performing Test CXX0X_SUPPORTED
|
||||
-- Performing Test CXX0X_SUPPORTED - Success
|
||||
-- Looking for include file pthread.h
|
||||
-- Looking for include file pthread.h - found
|
||||
-- Looking for pthread_create
|
||||
-- Looking for pthread_create - found
|
||||
-- Found Threads: TRUE
|
||||
-- Boost version: 1.59.0
|
||||
-- Found the following Boost libraries:
|
||||
-- system
|
||||
-- filesystem
|
||||
-- regex
|
||||
-- program_options
|
||||
-- date_time
|
||||
-- thread
|
||||
-- chrono
|
||||
-- Found OpenSSL: /mingw32/lib/libssl.dll.a;/mingw32/lib/libcrypto.dll.a (found version "1.0.2d")
|
||||
-- Found MiniUPnP headers: /mingw32/include
|
||||
-- Found ZLIB: /mingw32/lib/libz.dll.a (found version "1.2.8")
|
||||
-- ---------------------------------------
|
||||
-- Build type : RelWithDebInfo
|
||||
-- Compiler vendor : GNU
|
||||
-- Compiler version : 5.2.0
|
||||
-- Compiler path : /mingw32/bin/c++.exe
|
||||
-- Install prefix: : ../mingw32.stage
|
||||
-- Options:
|
||||
-- AESNI : OFF
|
||||
-- HARDENING : OFF
|
||||
-- LIBRARY : ON
|
||||
-- BINARY : ON
|
||||
-- STATIC BUILD : OFF
|
||||
-- UPnP : ON
|
||||
-- PCH : ON
|
||||
-- ---------------------------------------
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /c/dev/i2pd/i2pd/mingw32.build
|
||||
```
|
||||
|
||||
Now it is time to compile everything. If you have a multicore processor
|
||||
you can add `-j` flag.
|
||||
|
||||
make -j4 install
|
||||
you use `make USE_AESNI=1`. No check is done however, it
|
||||
will compile, but it might crash with `Illegal instruction` if not supported.
|
||||
|
||||
You should be able to run ./i2pd . If you need to start from the new
|
||||
shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as
|
||||
|
43
docs/config_opts_after_2.3.0.md
Normal file
43
docs/config_opts_after_2.3.0.md
Normal file
@ -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 - тоже
|
@ -4,46 +4,67 @@ i2pd configuration
|
||||
Command line options
|
||||
--------------------
|
||||
|
||||
* --port= - The port to listen on
|
||||
* --httpaddress= - The address to listen on (HTTP server)
|
||||
* --httpport= - The port to listen on (HTTP server)
|
||||
* --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. 0 by default
|
||||
* --log= - Enable or disable logging to the file. 1 for daemon, 0 for non-daemon by default
|
||||
* --svcctl= - Windows service management (--svcctl="install" or --svcctl="remove")
|
||||
* --service= - 1 if uses system folders (/var/run/i2pd.pid, /var/log/i2pd/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= - Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility)
|
||||
* --logfile= - Path to logfile (default - autodetect)
|
||||
* --loglevel= - Log messages above this level (debug, *info, warn, error)
|
||||
* --host= - The external IP
|
||||
* --port= - The port to listen on
|
||||
* --daemon - Router will go to background after start
|
||||
* --service - Router will use system folders like '/var/lib/i2pd'
|
||||
* --ipv6 - Enable communication through ipv6
|
||||
* --notransit - Router will not accept transit tunnels at startup
|
||||
* --floodfill - Router will be floodfill
|
||||
* --bandwidth= - L if bandwidth is limited to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited
|
||||
* --svcctl= - Windows service management (--svcctl="install" or --svcctl="remove")
|
||||
|
||||
* --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)
|
||||
* --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
|
||||
|
||||
* --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 : <key> = <value>.
|
||||
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):
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
121
util.cpp
121
util.cpp
@ -13,6 +13,7 @@
|
||||
#include <boost/program_options/detail/config_file.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "Config.h"
|
||||
#include "util.h"
|
||||
#include "Log.h"
|
||||
|
||||
@ -66,86 +67,6 @@ namespace i2p
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
|
||||
namespace config
|
||||
{
|
||||
std::map<std::string, std::string> 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<std::string> 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");
|
||||
@ -166,8 +87,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,17 +123,34 @@ namespace filesystem
|
||||
|
||||
boost::filesystem::path GetConfigFile()
|
||||
{
|
||||
boost::filesystem::path pathConfigFile(i2p::util::config::GetArg("-conf", "i2p.conf"));
|
||||
if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir() / pathConfigFile;
|
||||
return pathConfigFile;
|
||||
std::string config; i2p::config::GetOption("conf", config);
|
||||
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()
|
||||
{
|
||||
boost::filesystem::path pathTunnelsConfigFile(i2p::util::config::GetArg("-tunnelscfg", "tunnels.cfg"));
|
||||
if (!pathTunnelsConfigFile.is_complete())
|
||||
pathTunnelsConfigFile = GetDataDir() / pathTunnelsConfigFile;
|
||||
return pathTunnelsConfigFile;
|
||||
std::string tunconf; i2p::config::GetOption("tunconf", tunconf);
|
||||
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()
|
||||
@ -225,7 +165,8 @@ namespace filesystem
|
||||
SHGetFolderPath(NULL, CSIDL_APPDATA, 0, NULL, 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");
|
||||
|
8
util.h
8
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);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
|
||||
|
||||
#define I2PD_VERSION_MAJOR 2
|
||||
#define I2PD_VERSION_MINOR 3
|
||||
#define I2PD_VERSION_MINOR 4
|
||||
#define I2PD_VERSION_MICRO 0
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
||||
|
Loading…
Reference in New Issue
Block a user