mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-23 17:36:37 +02:00
commit
260564345a
42 changed files with 539 additions and 2096 deletions
|
@ -15,7 +15,7 @@ ifeq ($(shell expr match $(CXX) 'clang'),5)
|
||||||
NEEDED_CXXFLAGS += -std=c++11
|
NEEDED_CXXFLAGS += -std=c++11
|
||||||
else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10
|
else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10
|
||||||
NEEDED_CXXFLAGS += -std=c++11
|
NEEDED_CXXFLAGS += -std=c++11
|
||||||
else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # gcc 4.7 - 4.9
|
else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9
|
||||||
NEEDED_CXXFLAGS += -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
NEEDED_CXXFLAGS += -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||||
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
|
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
|
||||||
NEEDED_CXXFLAGS += -std=c++11
|
NEEDED_CXXFLAGS += -std=c++11
|
||||||
|
|
|
@ -31,7 +31,8 @@ public:
|
||||||
} else {
|
} else {
|
||||||
Result = E_NOINTERFACE;
|
Result = E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
AddRef();
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,4 +91,4 @@ void SubscribeToEvents() { }
|
||||||
void UnSubscribeFromEvents() { }
|
void UnSubscribeFromEvents() { }
|
||||||
|
|
||||||
#endif // WINVER
|
#endif // WINVER
|
||||||
#endif
|
#endif
|
||||||
|
|
18
appveyor.yml
18
appveyor.yml
|
@ -21,11 +21,25 @@ environment:
|
||||||
MSYS_BITNESS: 32
|
MSYS_BITNESS: 32
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
# install new signing keyring
|
||||||
|
- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
|
||||||
|
- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
|
||||||
|
- c:\msys64\usr\bin\bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
|
||||||
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
|
||||||
|
# disable inaccessible miror (something block sed from changing files, so rewrite them) - https://github.com/msys2/MINGW-packages/issues/7084
|
||||||
|
- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/x86_64/' > /etc/pacman.d/mirrorlist.mingw64"
|
||||||
|
- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/i686/' > /etc/pacman.d/mirrorlist.mingw32"
|
||||||
|
- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/msys/$arch/' > /etc/pacman.d/mirrorlist.msys"
|
||||||
|
# remove packages which can break build
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc"
|
||||||
# TODO: revert that change when appveyor's images will be updated
|
|
||||||
- c:\msys64\usr\bin\bash -l "build/appveyor-msys2-upgrade.bash"
|
|
||||||
# update runtime
|
# update runtime
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
||||||
|
# Kill bash before next try
|
||||||
|
- taskkill /T /F /IM bash.exe /IM gpg.exe /IM gpg-agent.exe | exit /B 0
|
||||||
|
# rewrite mirrorlist again because pacman update can rewrite it
|
||||||
|
- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/x86_64/' > /etc/pacman.d/mirrorlist.mingw64"
|
||||||
|
- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/mingw/i686/' > /etc/pacman.d/mirrorlist.mingw32"
|
||||||
|
- c:\msys64\usr\bin\bash -lc "echo 'Server = https://mirror.yandex.ru/mirrors/msys2/msys/$arch/' > /etc/pacman.d/mirrorlist.msys"
|
||||||
# update packages and install required
|
# update packages and install required
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu ${MSYS_PACKAGES}"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu ${MSYS_PACKAGES}"
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,6 @@ set(LIBI2PD_SRC
|
||||||
"${LIBI2PD_SRC_DIR}/NetDb.cpp"
|
"${LIBI2PD_SRC_DIR}/NetDb.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/NetDbRequests.cpp"
|
"${LIBI2PD_SRC_DIR}/NetDbRequests.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
|
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/NTCPSession.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
|
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Profiling.cpp"
|
"${LIBI2PD_SRC_DIR}/Profiling.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Reseed.cpp"
|
"${LIBI2PD_SRC_DIR}/Reseed.cpp"
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "NTCPSession.h"
|
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
|
@ -135,8 +134,8 @@ namespace i2p
|
||||||
i2p::context.SetNetID (netID);
|
i2p::context.SetNetID (netID);
|
||||||
i2p::context.Init ();
|
i2p::context.Init ();
|
||||||
|
|
||||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||||
#ifdef MESHNET
|
#ifdef MESHNET
|
||||||
// manual override for meshnet
|
// manual override for meshnet
|
||||||
ipv4 = false;
|
ipv4 = false;
|
||||||
|
@ -151,8 +150,7 @@ namespace i2p
|
||||||
i2p::context.SetSupportsV6 (ipv6);
|
i2p::context.SetSupportsV6 (ipv6);
|
||||||
i2p::context.SetSupportsV4 (ipv4);
|
i2p::context.SetSupportsV4 (ipv4);
|
||||||
|
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
|
||||||
i2p::context.PublishNTCPAddress (ntcp, !ipv6);
|
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +158,7 @@ namespace i2p
|
||||||
if (published)
|
if (published)
|
||||||
{
|
{
|
||||||
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
|
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
|
||||||
if (!ntcp && !ntcp2port) ntcp2port = port; // use standard port
|
if (!ntcp2port) ntcp2port = port; // use standard port
|
||||||
i2p::context.PublishNTCP2Address (ntcp2port, true); // publish
|
i2p::context.PublishNTCP2Address (ntcp2port, true); // publish
|
||||||
if (ipv6)
|
if (ipv6)
|
||||||
{
|
{
|
||||||
|
@ -180,13 +178,10 @@ namespace i2p
|
||||||
SetMaxNumTransitTunnels (transitTunnels);
|
SetMaxNumTransitTunnels (transitTunnels);
|
||||||
|
|
||||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||||
if (isFloodfill)
|
if (isFloodfill) {
|
||||||
{
|
|
||||||
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
||||||
i2p::context.SetFloodfill (true);
|
i2p::context.SetFloodfill (true);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
i2p::context.SetFloodfill (false);
|
i2p::context.SetFloodfill (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +249,7 @@ namespace i2p
|
||||||
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
||||||
restricted = fams.size() > 0;
|
restricted = fams.size() > 0;
|
||||||
}
|
}
|
||||||
if (routers.length() > 0)
|
if (routers.length() > 0) {
|
||||||
{
|
|
||||||
std::set<i2p::data::IdentHash> idents;
|
std::set<i2p::data::IdentHash> idents;
|
||||||
size_t pos = 0, comma;
|
size_t pos = 0, comma;
|
||||||
do
|
do
|
||||||
|
@ -291,8 +285,7 @@ namespace i2p
|
||||||
i2p::data::netdb.Start();
|
i2p::data::netdb.Start();
|
||||||
|
|
||||||
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
||||||
if (upnp)
|
if (upnp) {
|
||||||
{
|
|
||||||
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
|
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
|
||||||
d.UPnP->Start ();
|
d.UPnP->Start ();
|
||||||
}
|
}
|
||||||
|
@ -304,16 +297,16 @@ namespace i2p
|
||||||
d.m_NTPSync->Start ();
|
d.m_NTPSync->Start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
LogPrint(eLogInfo, "Daemon: starting Transports");
|
||||||
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
|
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
|
||||||
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
|
||||||
|
|
||||||
i2p::transport::transports.Start(ntcp, ssu);
|
i2p::transport::transports.Start(ntcp2, ssu);
|
||||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||||
/** shut down netdb right away */
|
/** shut down netdb right away */
|
||||||
|
@ -323,23 +316,23 @@ namespace i2p
|
||||||
}
|
}
|
||||||
|
|
||||||
bool http; i2p::config::GetOption("http.enabled", http);
|
bool http; i2p::config::GetOption("http.enabled", http);
|
||||||
if (http)
|
if (http) {
|
||||||
{
|
|
||||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||||
d.httpServer->Start();
|
d.httpServer->Start();
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
|
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
|
||||||
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
||||||
i2p::tunnel::tunnels.Start();
|
i2p::tunnel::tunnels.Start();
|
||||||
|
|
||||||
|
@ -352,12 +345,12 @@ namespace i2p
|
||||||
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
||||||
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||||
d.m_I2PControlService->Start ();
|
d.m_I2PControlService->Start ();
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
|
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
|
||||||
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
||||||
|
@ -374,7 +367,7 @@ namespace i2p
|
||||||
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
||||||
i2p::tunnel::tunnels.Stop();
|
i2p::tunnel::tunnels.Stop();
|
||||||
|
|
||||||
if (d.UPnP)
|
if (d.UPnP)
|
||||||
{
|
{
|
||||||
d.UPnP->Stop ();
|
d.UPnP->Stop ();
|
||||||
d.UPnP = nullptr;
|
d.UPnP = nullptr;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
@ -733,13 +732,6 @@ namespace http {
|
||||||
void ShowTransports (std::stringstream& s)
|
void ShowTransports (std::stringstream& s)
|
||||||
{
|
{
|
||||||
s << "<b>Transports:</b><br>\r\n";
|
s << "<b>Transports:</b><br>\r\n";
|
||||||
auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
|
|
||||||
if (ntcpServer)
|
|
||||||
{
|
|
||||||
auto sessions = ntcpServer->GetNTCPSessions ();
|
|
||||||
if (!sessions.empty ())
|
|
||||||
ShowNTCPTransports (s, sessions, "NTCP");
|
|
||||||
}
|
|
||||||
auto ntcp2Server = i2p::transport::transports.GetNTCP2Server ();
|
auto ntcp2Server = i2p::transport::transports.GetNTCP2Server ();
|
||||||
if (ntcp2Server)
|
if (ntcp2Server)
|
||||||
{
|
{
|
||||||
|
@ -1321,8 +1313,8 @@ namespace http {
|
||||||
void HTTPServer::Accept ()
|
void HTTPServer::Accept ()
|
||||||
{
|
{
|
||||||
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (m_Service);
|
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (m_Service);
|
||||||
m_Acceptor.async_accept (*newSocket, boost::bind (&HTTPServer::HandleAccept, this,
|
m_Acceptor.async_accept (*newSocket, std::bind (&HTTPServer::HandleAccept, this,
|
||||||
boost::asio::placeholders::error, newSocket));
|
std::placeholders::_1, newSocket));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
|
void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2020, 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 <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
@ -14,12 +6,7 @@
|
||||||
#include <boost/date_time/local_time/local_time.hpp>
|
#include <boost/date_time/local_time/local_time.hpp>
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
#include <boost/property_tree/ini_parser.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>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
|
@ -67,28 +54,29 @@ namespace client
|
||||||
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
||||||
|
|
||||||
// handlers
|
// handlers
|
||||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||||
|
|
||||||
// I2PControl
|
// I2PControl
|
||||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||||
|
|
||||||
// RouterInfo
|
// RouterInfo
|
||||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
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.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
|
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
||||||
|
&I2PControlService::TunnelsSuccessRateHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||||
|
|
||||||
|
@ -104,10 +92,10 @@ namespace client
|
||||||
// ClientServicesInfo
|
// ClientServicesInfo
|
||||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
I2PControlService::~I2PControlService ()
|
I2PControlService::~I2PControlService ()
|
||||||
|
@ -242,12 +230,6 @@ namespace client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::ostringstream response;
|
std::ostringstream response;
|
||||||
#if GCC47_BOOST149
|
|
||||||
LogPrint (eLogError, "I2PControl: json_read is not supported due bug in boost 1.49 with gcc 4.7");
|
|
||||||
response << "{\"id\":null,\"error\":";
|
|
||||||
response << "{\"code\":-32603,\"message\":\"JSON requests is not supported with this version of boost\"},";
|
|
||||||
response << "\"jsonrpc\":\"2.0\"}";
|
|
||||||
#else
|
|
||||||
boost::property_tree::ptree pt;
|
boost::property_tree::ptree pt;
|
||||||
boost::property_tree::read_json (ss, pt);
|
boost::property_tree::read_json (ss, pt);
|
||||||
|
|
||||||
|
@ -267,7 +249,6 @@ namespace client
|
||||||
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
||||||
response << "\"jsonrpc\":\"2.0\"}";
|
response << "\"jsonrpc\":\"2.0\"}";
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
SendResponse (socket, buf, response, isHtml);
|
SendResponse (socket, buf, response, isHtml);
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
|
@ -408,8 +389,8 @@ namespace client
|
||||||
auto it1 = m_RouterInfoHandlers.find (it->first);
|
auto it1 = m_RouterInfoHandlers.find (it->first);
|
||||||
if (it1 != m_RouterInfoHandlers.end ())
|
if (it1 != m_RouterInfoHandlers.end ())
|
||||||
{
|
{
|
||||||
if (!first) results << ",";
|
if (!first) results << ",";
|
||||||
else first = false;
|
else first = false;
|
||||||
(this->*(it1->second))(results);
|
(this->*(it1->second))(results);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -507,7 +488,7 @@ namespace client
|
||||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
||||||
m_ShutdownTimer.async_wait (
|
m_ShutdownTimer.async_wait (
|
||||||
[](const boost::system::error_code& ecode)
|
[](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
Daemon.running = 0;
|
Daemon.running = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -521,7 +502,7 @@ namespace client
|
||||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
||||||
m_ShutdownTimer.async_wait (
|
m_ShutdownTimer.async_wait (
|
||||||
[](const boost::system::error_code& ecode)
|
[](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
Daemon.running = 0;
|
Daemon.running = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,9 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2020, 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef USE_UPNP
|
#ifdef USE_UPNP
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
|
@ -88,10 +79,10 @@ namespace transport
|
||||||
void UPnP::Discover ()
|
void UPnP::Discover ()
|
||||||
{
|
{
|
||||||
bool isError;
|
bool isError;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||||
err = UPNPDISCOVER_SUCCESS;
|
err = UPNPDISCOVER_SUCCESS;
|
||||||
|
|
||||||
#if (MINIUPNPC_API_VERSION >= 14)
|
#if (MINIUPNPC_API_VERSION >= 14)
|
||||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
|
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
|
||||||
|
@ -100,9 +91,9 @@ namespace transport
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isError = err != UPNPDISCOVER_SUCCESS;
|
isError = err != UPNPDISCOVER_SUCCESS;
|
||||||
#else // MINIUPNPC_API_VERSION >= 8
|
#else // MINIUPNPC_API_VERSION >= 8
|
||||||
err = 0;
|
err = 0;
|
||||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||||
isError = m_Devlist == NULL;
|
isError = m_Devlist == NULL;
|
||||||
#endif // MINIUPNPC_API_VERSION >= 8
|
#endif // MINIUPNPC_API_VERSION >= 8
|
||||||
{
|
{
|
||||||
|
@ -113,15 +104,15 @@ namespace transport
|
||||||
|
|
||||||
if (isError)
|
if (isError)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
|
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||||
m_upnpUrlsInitialized = err != 0;
|
m_upnpUrlsInitialized=err!=0;
|
||||||
if (err == UPNP_IGD_VALID_CONNECTED)
|
if (err == UPNP_IGD_VALID_CONNECTED)
|
||||||
{
|
{
|
||||||
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||||
if(err != UPNPCOMMAND_SUCCESS)
|
if(err != UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
|
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
|
||||||
|
@ -132,14 +123,14 @@ namespace transport
|
||||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
|
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
|
||||||
if (!m_externalIPAddress[0])
|
if (!m_externalIPAddress[0])
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
|
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
|
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +181,7 @@ namespace transport
|
||||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||||
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
|
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
|
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
|
||||||
|
|
||||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||||
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
|
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
|
||||||
|
@ -210,7 +201,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,14 +218,14 @@ namespace transport
|
||||||
|
|
||||||
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
||||||
{
|
{
|
||||||
if(!m_upnpUrlsInitialized) {
|
if(!m_upnpUrlsInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
|
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
|
||||||
int err = UPNPCOMMAND_SUCCESS;
|
int err = UPNPCOMMAND_SUCCESS;
|
||||||
|
|
||||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||||
if (err == UPNPCOMMAND_SUCCESS)
|
if (err == UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
|
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
|
||||||
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
|
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
|
||||||
|
@ -245,11 +236,11 @@ namespace transport
|
||||||
{
|
{
|
||||||
freeUPNPDevlist (m_Devlist);
|
freeUPNPDevlist (m_Devlist);
|
||||||
m_Devlist = 0;
|
m_Devlist = 0;
|
||||||
if(m_upnpUrlsInitialized){
|
if(m_upnpUrlsInitialized){
|
||||||
FreeUPNPUrls (&m_upnpUrls);
|
FreeUPNPUrls (&m_upnpUrls);
|
||||||
m_upnpUrlsInitialized=false;
|
m_upnpUrlsInitialized=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,9 +58,9 @@ namespace config {
|
||||||
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
|
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
|
||||||
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
|
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
|
||||||
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
|
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
|
||||||
("ntcp", value<bool>()->default_value(false), "Enable NTCP transport (default: disabled)")
|
("ntcp", value<bool>()->default_value(false), "Ignored. Always false")
|
||||||
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
|
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||||
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||||
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
|
||||||
|
@ -96,7 +96,7 @@ namespace config {
|
||||||
("httpproxy.enabled", value<bool>()->default_value(true), "Enable or disable HTTP Proxy")
|
("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.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.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
||||||
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
("httpproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist HTTP Proxy keys. Transient by default")
|
||||||
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||||
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||||
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
||||||
|
@ -116,7 +116,7 @@ namespace config {
|
||||||
("socksproxy.enabled", value<bool>()->default_value(true), "Enable or disable SOCKS Proxy")
|
("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.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.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
||||||
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
("socksproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist SOCKS Proxy keys. Transient by default")
|
||||||
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||||
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||||
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
||||||
|
@ -152,6 +152,7 @@ namespace config {
|
||||||
("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP")
|
("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP")
|
||||||
("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address")
|
("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address")
|
||||||
("i2cp.port", value<uint16_t>()->default_value(7654), "I2CP listen port")
|
("i2cp.port", value<uint16_t>()->default_value(7654), "I2CP listen port")
|
||||||
|
("i2cp.singlethread", value<bool>()->default_value(true), "Destinations run in the I2CP server's thread")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description i2pcontrol("I2PControl options");
|
options_description i2pcontrol("I2PControl options");
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
#include "Config.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
|
@ -464,14 +465,14 @@ namespace client
|
||||||
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
|
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
|
||||||
i2p::data::IdentHash peerHash (buf + 33 + i*32);
|
|
||||||
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
|
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message
|
i2p::data::IdentHash peerHash (buf + 33 + i*32);
|
||||||
i2p::data::netdb.RequestDestination (peerHash);
|
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
|
||||||
|
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
|
||||||
if (floodfill)
|
if (floodfill)
|
||||||
|
@ -603,9 +604,8 @@ namespace client
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
// we must capture this for gcc 4.7 due the bug
|
|
||||||
RequestLeaseSet (ls->GetStoreHash (),
|
RequestLeaseSet (ls->GetStoreHash (),
|
||||||
[s, ls, this](std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
|
[s, ls](std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
|
||||||
{
|
{
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
{
|
{
|
||||||
|
@ -744,14 +744,19 @@ namespace client
|
||||||
request->excluded.insert (nextFloodfill->GetIdentHash ());
|
request->excluded.insert (nextFloodfill->GetIdentHash ());
|
||||||
request->requestTimeoutTimer.cancel ();
|
request->requestTimeoutTimer.cancel ();
|
||||||
|
|
||||||
|
bool isECIES = SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET) &&
|
||||||
|
nextFloodfill->GetVersion () >= MAKE_VERSION_NUMBER(0, 9, 46); // >= 0.9.46;
|
||||||
uint8_t replyKey[32], replyTag[32];
|
uint8_t replyKey[32], replyTag[32];
|
||||||
RAND_bytes (replyKey, 32); // random session key
|
RAND_bytes (replyKey, 32); // random session key
|
||||||
RAND_bytes (replyTag, 32); // random session tag
|
RAND_bytes (replyTag, isECIES ? 8 : 32); // random session tag
|
||||||
AddSessionKey (replyKey, replyTag);
|
if (isECIES)
|
||||||
|
AddECIESx25519Key (replyKey, replyTag);
|
||||||
|
else
|
||||||
|
AddSessionKey (replyKey, replyTag);
|
||||||
|
|
||||||
auto msg = WrapMessage (nextFloodfill,
|
auto msg = WrapMessage (nextFloodfill,
|
||||||
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
||||||
request->replyTunnel, replyKey, replyTag));
|
request->replyTunnel, replyKey, replyTag, isECIES));
|
||||||
request->outboundTunnel->SendTunnelDataMsg (
|
request->outboundTunnel->SendTunnelDataMsg (
|
||||||
{
|
{
|
||||||
i2p::tunnel::TunnelMessageBlock
|
i2p::tunnel::TunnelMessageBlock
|
||||||
|
@ -845,8 +850,9 @@ namespace client
|
||||||
|
|
||||||
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
||||||
bool isPublic, const std::map<std::string, std::string> * params):
|
bool isPublic, const std::map<std::string, std::string> * params):
|
||||||
LeaseSetDestination (service, isPublic, params),
|
LeaseSetDestination (service, isPublic, params),
|
||||||
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
||||||
|
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS),
|
||||||
m_DatagramDestination (nullptr), m_RefCounter (0),
|
m_DatagramDestination (nullptr), m_RefCounter (0),
|
||||||
m_ReadyChecker(service)
|
m_ReadyChecker(service)
|
||||||
{
|
{
|
||||||
|
@ -855,8 +861,7 @@ namespace client
|
||||||
|
|
||||||
// extract encryption type params for LS2
|
// extract encryption type params for LS2
|
||||||
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
|
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
|
||||||
if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
|
if (params)
|
||||||
GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
|
|
||||||
{
|
{
|
||||||
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
|
@ -915,7 +920,10 @@ namespace client
|
||||||
auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
|
auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
m_StreamingAckDelay = std::stoi(it->second);
|
m_StreamingAckDelay = std::stoi(it->second);
|
||||||
|
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
|
||||||
|
if (it != params->end ())
|
||||||
|
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
|
||||||
|
|
||||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
{
|
{
|
||||||
// authentication for encrypted LeaseSet
|
// authentication for encrypted LeaseSet
|
||||||
|
|
|
@ -78,6 +78,8 @@ namespace client
|
||||||
// streaming
|
// streaming
|
||||||
const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay";
|
const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay";
|
||||||
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
|
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
|
||||||
|
const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings";
|
||||||
|
const int DEFAULT_ANSWER_PINGS = true;
|
||||||
|
|
||||||
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
|
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
|
||||||
|
|
||||||
|
@ -242,7 +244,8 @@ namespace client
|
||||||
bool IsAcceptingStreams () const;
|
bool IsAcceptingStreams () const;
|
||||||
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
||||||
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
||||||
|
bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; }
|
||||||
|
|
||||||
// datagram
|
// datagram
|
||||||
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
||||||
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
|
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
|
||||||
|
@ -275,6 +278,7 @@ namespace client
|
||||||
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
|
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
|
||||||
|
|
||||||
int m_StreamingAckDelay;
|
int m_StreamingAckDelay;
|
||||||
|
bool m_IsStreamingAnswerPings;
|
||||||
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
||||||
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
||||||
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
||||||
|
|
|
@ -88,12 +88,67 @@ namespace garlic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RatchetTagSet::DeleteSymmKey (int index)
|
||||||
|
{
|
||||||
|
m_ItermediateSymmKeys.erase (index);
|
||||||
|
}
|
||||||
|
|
||||||
void RatchetTagSet::Expire ()
|
void RatchetTagSet::Expire ()
|
||||||
{
|
{
|
||||||
if (!m_ExpirationTimestamp)
|
if (!m_ExpirationTimestamp)
|
||||||
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
|
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
|
||||||
|
{
|
||||||
|
auto session = GetSession ();
|
||||||
|
if (!session) return false;
|
||||||
|
return session->HandleNextMessage (buf, len, shared_from_this (), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseLookupTagSet::DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key):
|
||||||
|
RatchetTagSet (nullptr), m_Destination (destination)
|
||||||
|
{
|
||||||
|
memcpy (m_Key, key, 32);
|
||||||
|
Expire ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatabaseLookupTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
|
||||||
|
{
|
||||||
|
if (len < 24) return false;
|
||||||
|
uint8_t nonce[12];
|
||||||
|
memset (nonce, 0, 12); // n = 0
|
||||||
|
size_t offset = 8; // first 8 bytes is reply tag used as AD
|
||||||
|
len -= 16; // poly1305
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len - offset, buf, 8, m_Key, nonce, buf + offset, len - offset, false)) // decrypt
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Lookup reply AEAD decryption failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// we assume 1 I2NP block with delivery type local
|
||||||
|
if (offset + 3 > len)
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Lookup reply is too short ", len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buf[offset] != eECIESx25519BlkGalicClove)
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Lookup reply unexpected block ", (int)buf[offset]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
offset++;
|
||||||
|
auto size = bufbe16toh (buf + offset);
|
||||||
|
offset += 2;
|
||||||
|
if (offset + size > len)
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Lookup reply block is too long ", size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (m_Destination)
|
||||||
|
m_Destination->HandleECIESx25519GarlicClove (buf + offset, size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
|
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
|
||||||
GarlicRoutingSession (owner, attachLeaseSet)
|
GarlicRoutingSession (owner, attachLeaseSet)
|
||||||
{
|
{
|
||||||
|
@ -657,7 +712,12 @@ namespace garlic
|
||||||
moreTags -= (receiveTagset->GetNextIndex () - index);
|
moreTags -= (receiveTagset->GetNextIndex () - index);
|
||||||
}
|
}
|
||||||
if (moreTags > 0)
|
if (moreTags > 0)
|
||||||
|
{
|
||||||
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
||||||
|
index -= (moreTags >> 1); // /2
|
||||||
|
if (index > 0)
|
||||||
|
receiveTagset->SetTrimBehind (index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace garlic
|
||||||
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
|
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
|
||||||
|
|
||||||
class ECIESX25519AEADRatchetSession;
|
class ECIESX25519AEADRatchetSession;
|
||||||
class RatchetTagSet
|
class RatchetTagSet: public std::enable_shared_from_this<RatchetTagSet>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -52,14 +52,19 @@ namespace garlic
|
||||||
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
|
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
|
||||||
int GetNextIndex () const { return m_NextIndex; };
|
int GetNextIndex () const { return m_NextIndex; };
|
||||||
void GetSymmKey (int index, uint8_t * key);
|
void GetSymmKey (int index, uint8_t * key);
|
||||||
|
void DeleteSymmKey (int index);
|
||||||
|
|
||||||
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session.lock (); };
|
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session.lock (); };
|
||||||
int GetTagSetID () const { return m_TagSetID; };
|
int GetTagSetID () const { return m_TagSetID; };
|
||||||
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
|
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
|
||||||
|
void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; };
|
||||||
|
|
||||||
void Expire ();
|
void Expire ();
|
||||||
bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; };
|
bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; };
|
||||||
|
virtual bool IsIndexExpired (int index) const { return m_Session.expired () || index < m_TrimBehindIndex; };
|
||||||
|
|
||||||
|
virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
union
|
union
|
||||||
|
@ -73,7 +78,7 @@ namespace garlic
|
||||||
|
|
||||||
} m_KeyData;
|
} m_KeyData;
|
||||||
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
|
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
|
||||||
int m_NextIndex, m_NextSymmKeyIndex;
|
int m_NextIndex, m_NextSymmKeyIndex, m_TrimBehindIndex = 0;
|
||||||
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
|
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
|
||||||
std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
|
std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
|
||||||
int m_TagSetID = 0;
|
int m_TagSetID = 0;
|
||||||
|
@ -91,6 +96,21 @@ namespace garlic
|
||||||
|
|
||||||
std::shared_ptr<ECIESX25519AEADRatchetSession> m_DummySession; // we need a strong pointer for NS
|
std::shared_ptr<ECIESX25519AEADRatchetSession> m_DummySession; // we need a strong pointer for NS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DatabaseLookupTagSet: public RatchetTagSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key);
|
||||||
|
|
||||||
|
bool IsIndexExpired (int index) const { return false; };
|
||||||
|
bool HandleNextMessage (uint8_t * buf, size_t len, int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
GarlicDestination * m_Destination;
|
||||||
|
uint8_t m_Key[32];
|
||||||
|
};
|
||||||
|
|
||||||
enum ECIESx25519BlockType
|
enum ECIESx25519BlockType
|
||||||
{
|
{
|
||||||
|
|
|
@ -460,6 +460,14 @@ namespace garlic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GarlicDestination::AddECIESx25519Key (const uint8_t * key, const uint8_t * tag)
|
||||||
|
{
|
||||||
|
uint64_t t;
|
||||||
|
memcpy (&t, tag, 8);
|
||||||
|
auto tagset = std::make_shared<DatabaseLookupTagSet>(this, key);
|
||||||
|
m_ECIESx25519Tags.emplace (t, ECIESX25519AEADRatchetIndexTagset{0, tagset});
|
||||||
|
}
|
||||||
|
|
||||||
bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
|
bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
|
||||||
{
|
{
|
||||||
AddSessionKey (key, tag);
|
AddSessionKey (key, tag);
|
||||||
|
@ -507,8 +515,7 @@ namespace garlic
|
||||||
if (it1 != m_ECIESx25519Tags.end ())
|
if (it1 != m_ECIESx25519Tags.end ())
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
auto session = it1->second.tagset->GetSession ();
|
if (!it1->second.tagset->HandleNextMessage (buf, length, it1->second.index))
|
||||||
if (!session || !session->HandleNextMessage (buf, length, it1->second.tagset, it1->second.index))
|
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
m_ECIESx25519Tags.erase (it1);
|
m_ECIESx25519Tags.erase (it1);
|
||||||
}
|
}
|
||||||
|
@ -802,14 +809,6 @@ namespace garlic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ECIESx25519
|
// ECIESx25519
|
||||||
for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();)
|
|
||||||
{
|
|
||||||
if (it->second.tagset->IsExpired (ts) || ts > it->second.creationTime + ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
|
||||||
it = m_ECIESx25519Tags.erase (it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = m_ECIESx25519Sessions.begin (); it != m_ECIESx25519Sessions.end ();)
|
for (auto it = m_ECIESx25519Sessions.begin (); it != m_ECIESx25519Sessions.end ();)
|
||||||
{
|
{
|
||||||
if (it->second->CheckExpired (ts))
|
if (it->second->CheckExpired (ts))
|
||||||
|
@ -820,6 +819,20 @@ namespace garlic
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
numExpiredTags = 0;
|
||||||
|
for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();)
|
||||||
|
{
|
||||||
|
if (it->second.tagset->IsExpired (ts) || it->second.tagset->IsIndexExpired (it->second.index))
|
||||||
|
{
|
||||||
|
it->second.tagset->DeleteSymmKey (it->second.index);
|
||||||
|
it = m_ECIESx25519Tags.erase (it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
if (numExpiredTags > 0)
|
||||||
|
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID)
|
void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID)
|
||||||
|
@ -1009,7 +1022,7 @@ namespace garlic
|
||||||
{
|
{
|
||||||
auto index = tagset->GetNextIndex ();
|
auto index = tagset->GetNextIndex ();
|
||||||
uint64_t tag = tagset->GetNextSessionTag ();
|
uint64_t tag = tagset->GetNextSessionTag ();
|
||||||
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
|
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
||||||
|
|
|
@ -220,7 +220,6 @@ namespace garlic
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
RatchetTagSetPtr tagset;
|
RatchetTagSetPtr tagset;
|
||||||
uint64_t creationTime; // seconds since epoch
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GarlicDestination: public i2p::data::LocalDestination
|
class GarlicDestination: public i2p::data::LocalDestination
|
||||||
|
@ -242,6 +241,7 @@ namespace garlic
|
||||||
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
|
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
|
||||||
|
|
||||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||||
|
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
|
||||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||||
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
||||||
|
|
|
@ -171,7 +171,8 @@ namespace i2p
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag)
|
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
|
||||||
|
const uint8_t * replyTag, bool replyECIES)
|
||||||
{
|
{
|
||||||
int cnt = excludedFloodfills.size ();
|
int cnt = excludedFloodfills.size ();
|
||||||
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
||||||
|
@ -180,7 +181,8 @@ namespace i2p
|
||||||
buf += 32;
|
buf += 32;
|
||||||
memcpy (buf, replyTunnel->GetNextIdentHash (), 32); // reply tunnel GW
|
memcpy (buf, replyTunnel->GetNextIdentHash (), 32); // reply tunnel GW
|
||||||
buf += 32;
|
buf += 32;
|
||||||
*buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_ENCRYPTION_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags
|
*buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags
|
||||||
|
*buf |= (replyECIES ? DATABASE_LOOKUP_ECIES_FLAG : DATABASE_LOOKUP_ENCRYPTION_FLAG);
|
||||||
buf ++;
|
buf ++;
|
||||||
htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID
|
htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID
|
||||||
buf += 4;
|
buf += 4;
|
||||||
|
@ -204,8 +206,16 @@ namespace i2p
|
||||||
// encryption
|
// encryption
|
||||||
memcpy (buf, replyKey, 32);
|
memcpy (buf, replyKey, 32);
|
||||||
buf[32] = 1; // 1 tag
|
buf[32] = 1; // 1 tag
|
||||||
memcpy (buf + 33, replyTag, 32);
|
if (replyECIES)
|
||||||
buf += 65;
|
{
|
||||||
|
memcpy (buf + 33, replyTag, 8); // 8 bytes tag
|
||||||
|
buf += 41;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy (buf + 33, replyTag, 32); // 32 bytes tag
|
||||||
|
buf += 65;
|
||||||
|
}
|
||||||
|
|
||||||
m->len += (buf - m->GetPayload ());
|
m->len += (buf - m->GetPayload ());
|
||||||
m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
|
m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
|
||||||
|
|
|
@ -251,8 +251,9 @@ namespace tunnel
|
||||||
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
|
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);
|
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
||||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag);
|
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
|
||||||
|
const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
|
||||||
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers);
|
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers);
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router = nullptr, uint32_t replyToken = 0);
|
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router = nullptr, uint32_t replyToken = 0);
|
||||||
|
|
|
@ -1435,7 +1435,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
|
|
||||||
auto timer = std::make_shared<boost::asio::deadline_timer>(GetService());
|
auto timer = std::make_shared<boost::asio::deadline_timer>(GetService());
|
||||||
auto timeout = NTCP_CONNECT_TIMEOUT * 5;
|
auto timeout = NTCP2_CONNECT_TIMEOUT * 5;
|
||||||
conn->SetTerminationTimeout(timeout * 2);
|
conn->SetTerminationTimeout(timeout * 2);
|
||||||
timer->expires_from_now (boost::posix_time::seconds(timeout));
|
timer->expires_from_now (boost::posix_time::seconds(timeout));
|
||||||
timer->async_wait ([conn, timeout](const boost::system::error_code& ecode)
|
timer->async_wait ([conn, timeout](const boost::system::error_code& ecode)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,242 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2020, 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NTCP_SESSION_H__
|
|
||||||
#define NTCP_SESSION_H__
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include "Crypto.h"
|
|
||||||
#include "Identity.h"
|
|
||||||
#include "RouterInfo.h"
|
|
||||||
#include "I2NPProtocol.h"
|
|
||||||
#include "TransportSession.h"
|
|
||||||
#include "CryptoWorker.h"
|
|
||||||
|
|
||||||
namespace i2p
|
|
||||||
{
|
|
||||||
namespace transport
|
|
||||||
{
|
|
||||||
struct NTCPPhase1
|
|
||||||
{
|
|
||||||
uint8_t pubKey[256];
|
|
||||||
uint8_t HXxorHI[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NTCPPhase2
|
|
||||||
{
|
|
||||||
uint8_t pubKey[256];
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t hxy[32];
|
|
||||||
uint8_t timestamp[4];
|
|
||||||
uint8_t filler[12];
|
|
||||||
} encrypted;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NTCPWork;
|
|
||||||
|
|
||||||
const size_t NTCP_MAX_MESSAGE_SIZE = 16384;
|
|
||||||
const size_t NTCP_BUFFER_SIZE = 1028; // fits 1 tunnel data message
|
|
||||||
const int NTCP_CONNECT_TIMEOUT = 5; // 5 seconds
|
|
||||||
const int NTCP_ESTABLISH_TIMEOUT = 10; // 10 seconds
|
|
||||||
const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
|
|
||||||
const int NTCP_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
|
||||||
const size_t NTCP_DEFAULT_PHASE3_SIZE = 2/*size*/ + i2p::data::DEFAULT_IDENTITY_SIZE/*387*/ + 4/*ts*/ + 15/*padding*/ + 40/*signature*/; // 448
|
|
||||||
const int NTCP_CLOCK_SKEW = 60; // in seconds
|
|
||||||
const int NTCP_MAX_OUTGOING_QUEUE_SIZE = 200; // how many messages we can queue up
|
|
||||||
|
|
||||||
class NTCPServer;
|
|
||||||
class NTCPSession: public TransportSession, public std::enable_shared_from_this<NTCPSession>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
|
||||||
~NTCPSession ();
|
|
||||||
void Terminate ();
|
|
||||||
void Done ();
|
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
|
||||||
boost::asio::io_service & GetService();
|
|
||||||
bool IsEstablished () const { return m_IsEstablished; };
|
|
||||||
bool IsTerminated () const { return m_IsTerminated; };
|
|
||||||
|
|
||||||
void ClientLogin ();
|
|
||||||
void ServerLogin ();
|
|
||||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
|
||||||
void Connected ();
|
|
||||||
void SendTimeSyncMessage ();
|
|
||||||
void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
|
|
||||||
|
|
||||||
void CreateAESKey (uint8_t * pubKey);
|
|
||||||
|
|
||||||
// client
|
|
||||||
void SendPhase3 ();
|
|
||||||
void HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
|
||||||
void HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
|
||||||
void HandlePhase2 (NTCPWork * work=nullptr);
|
|
||||||
void HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
|
||||||
void HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
|
||||||
|
|
||||||
//server
|
|
||||||
void SendPhase2 (NTCPWork * work=nullptr);
|
|
||||||
void SendPhase4 (uint32_t tsA, uint32_t tsB);
|
|
||||||
void HandlePhase1Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
|
||||||
void HandlePhase2Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB);
|
|
||||||
void HandlePhase3Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB);
|
|
||||||
void HandlePhase3ExtraReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB, size_t paddingLen);
|
|
||||||
void HandlePhase3 (uint32_t tsB, size_t paddingLen);
|
|
||||||
void HandlePhase4Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
|
||||||
|
|
||||||
// common
|
|
||||||
void Receive ();
|
|
||||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
|
||||||
bool DecryptNextBlock (const uint8_t * encrypted);
|
|
||||||
|
|
||||||
void Send (std::shared_ptr<i2p::I2NPMessage> msg);
|
|
||||||
boost::asio::const_buffers_1 CreateMsgBuffer (std::shared_ptr<I2NPMessage> msg);
|
|
||||||
void Send (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
|
||||||
void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
NTCPServer& m_Server;
|
|
||||||
boost::asio::ip::tcp::socket m_Socket;
|
|
||||||
bool m_IsEstablished, m_IsTerminated;
|
|
||||||
|
|
||||||
i2p::crypto::CBCDecryption m_Decryption;
|
|
||||||
i2p::crypto::CBCEncryption m_Encryption;
|
|
||||||
|
|
||||||
struct Establisher
|
|
||||||
{
|
|
||||||
NTCPPhase1 phase1;
|
|
||||||
NTCPPhase2 phase2;
|
|
||||||
} * m_Establisher;
|
|
||||||
|
|
||||||
i2p::crypto::AESAlignedBuffer<NTCP_BUFFER_SIZE + 16> m_ReceiveBuffer;
|
|
||||||
i2p::crypto::AESAlignedBuffer<16> m_TimeSyncBuffer;
|
|
||||||
int m_ReceiveBufferOffset;
|
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> m_NextMessage;
|
|
||||||
size_t m_NextMessageOffset;
|
|
||||||
i2p::I2NPMessagesHandler m_Handler;
|
|
||||||
|
|
||||||
bool m_IsSending;
|
|
||||||
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: move to NTCP.h/.cpp
|
|
||||||
class NTCPServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef i2p::worker::ThreadPool<NTCPSession> Pool;
|
|
||||||
|
|
||||||
enum RemoteAddressType
|
|
||||||
{
|
|
||||||
eIP4Address,
|
|
||||||
eIP6Address,
|
|
||||||
eHostname
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ProxyType
|
|
||||||
{
|
|
||||||
eNoProxy,
|
|
||||||
eSocksProxy,
|
|
||||||
eHTTPProxy
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
NTCPServer (int workers=4);
|
|
||||||
~NTCPServer ();
|
|
||||||
|
|
||||||
void Start ();
|
|
||||||
void Stop ();
|
|
||||||
|
|
||||||
bool AddNTCPSession (std::shared_ptr<NTCPSession> session);
|
|
||||||
void RemoveNTCPSession (std::shared_ptr<NTCPSession> session);
|
|
||||||
std::shared_ptr<NTCPSession> FindNTCPSession (const i2p::data::IdentHash& ident);
|
|
||||||
void ConnectWithProxy (const std::string& addr, uint16_t port, RemoteAddressType addrtype, std::shared_ptr<NTCPSession> conn);
|
|
||||||
void Connect(const boost::asio::ip::address & address, uint16_t port, std::shared_ptr<NTCPSession> conn);
|
|
||||||
|
|
||||||
bool IsBoundV4() const { return m_NTCPAcceptor != nullptr; };
|
|
||||||
bool IsBoundV6() const { return m_NTCPV6Acceptor != nullptr; };
|
|
||||||
bool NetworkIsReady() const { return IsBoundV4() || IsBoundV6() || UsingProxy(); };
|
|
||||||
bool UsingProxy() const { return m_ProxyType != eNoProxy; };
|
|
||||||
|
|
||||||
void UseProxy(ProxyType proxy, const std::string & address, uint16_t port);
|
|
||||||
|
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
|
||||||
|
|
||||||
void SetSessionLimits(uint16_t softLimit, uint16_t hardLimit) { m_SoftLimit = softLimit; m_HardLimit = hardLimit; }
|
|
||||||
bool ShouldLimit() const { return ShouldHardLimit() || ShouldSoftLimit(); }
|
|
||||||
void Work(std::shared_ptr<NTCPSession> conn, Pool::WorkFunc work)
|
|
||||||
{
|
|
||||||
m_CryptoPool->Offer({conn, work});
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
|
|
||||||
/** @brief return true for hard limit */
|
|
||||||
bool ShouldHardLimit() const { return m_HardLimit && m_NTCPSessions.size() >= m_HardLimit; }
|
|
||||||
|
|
||||||
/** @brief return true for probabalistic soft backoff */
|
|
||||||
bool ShouldSoftLimit() const
|
|
||||||
{
|
|
||||||
auto sessions = m_NTCPSessions.size();
|
|
||||||
return sessions && m_SoftLimit && m_SoftLimit < sessions && ( rand() % sessions ) <= m_SoftLimit;
|
|
||||||
}
|
|
||||||
void Run ();
|
|
||||||
void HandleAccept (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
|
|
||||||
void HandleAcceptV6 (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
|
|
||||||
|
|
||||||
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
|
|
||||||
|
|
||||||
void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype);
|
|
||||||
void AfterSocksHandshake(std::shared_ptr<NTCPSession> conn, std::shared_ptr<boost::asio::deadline_timer> timer, const std::string & host, uint16_t port, RemoteAddressType adddrtype);
|
|
||||||
|
|
||||||
// timer
|
|
||||||
void ScheduleTermination ();
|
|
||||||
void HandleTerminationTimer (const boost::system::error_code& ecode);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool m_IsRunning;
|
|
||||||
std::thread * m_Thread;
|
|
||||||
boost::asio::io_service m_Service;
|
|
||||||
boost::asio::io_service::work m_Work;
|
|
||||||
boost::asio::deadline_timer m_TerminationTimer;
|
|
||||||
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor, * m_NTCPV6Acceptor;
|
|
||||||
std::map<i2p::data::IdentHash, std::shared_ptr<NTCPSession> > m_NTCPSessions; // access from m_Thread only
|
|
||||||
std::list<std::shared_ptr<NTCPSession> > m_PendingIncomingSessions;
|
|
||||||
|
|
||||||
ProxyType m_ProxyType;
|
|
||||||
std::string m_ProxyAddress;
|
|
||||||
uint16_t m_ProxyPort;
|
|
||||||
boost::asio::ip::tcp::resolver m_Resolver;
|
|
||||||
boost::asio::ip::tcp::endpoint * m_ProxyEndpoint;
|
|
||||||
|
|
||||||
std::shared_ptr<Pool> m_CryptoPool;
|
|
||||||
|
|
||||||
uint16_t m_SoftLimit, m_HardLimit;
|
|
||||||
public:
|
|
||||||
|
|
||||||
// for HTTP/I2PControl
|
|
||||||
const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; };
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -560,6 +560,9 @@ namespace data
|
||||||
updatedCount++;
|
updatedCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// make router reachable back if too few routers
|
||||||
|
if (it.second->IsUnreachable () && total - deletedCount < NETDB_MIN_ROUTERS)
|
||||||
|
it.second->SetUnreachable (false);
|
||||||
// find & mark expired routers
|
// find & mark expired routers
|
||||||
if (it.second->UsesIntroducer ())
|
if (it.second->UsesIntroducer ())
|
||||||
{
|
{
|
||||||
|
@ -575,7 +578,7 @@ namespace data
|
||||||
// delete RI file
|
// delete RI file
|
||||||
m_Storage.Remove(ident);
|
m_Storage.Remove(ident);
|
||||||
deletedCount++;
|
deletedCount++;
|
||||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||||
}
|
}
|
||||||
} // m_RouterInfos iteration
|
} // m_RouterInfos iteration
|
||||||
|
|
||||||
|
@ -610,7 +613,7 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete)
|
void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct)
|
||||||
{
|
{
|
||||||
auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory
|
auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory
|
||||||
if (!dest)
|
if (!dest)
|
||||||
|
@ -621,7 +624,23 @@ namespace data
|
||||||
|
|
||||||
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
||||||
if (floodfill)
|
if (floodfill)
|
||||||
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
{
|
||||||
|
if (direct)
|
||||||
|
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||||
|
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
|
||||||
|
auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr;
|
||||||
|
if (outbound && inbound)
|
||||||
|
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found");
|
||||||
|
m_Requests.RequestComplete (destination, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found");
|
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found");
|
||||||
|
@ -775,37 +794,21 @@ namespace data
|
||||||
// reply to our destination. Try other floodfills
|
// reply to our destination. Try other floodfills
|
||||||
if (outbound && inbound)
|
if (outbound && inbound)
|
||||||
{
|
{
|
||||||
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
|
||||||
auto count = dest->GetExcludedPeers ().size ();
|
auto count = dest->GetExcludedPeers ().size ();
|
||||||
if (count < 7)
|
if (count < 7)
|
||||||
{
|
{
|
||||||
auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ());
|
auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ());
|
||||||
if (nextFloodfill)
|
if (nextFloodfill)
|
||||||
{
|
{
|
||||||
// tell floodfill about us
|
|
||||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
|
||||||
{
|
|
||||||
i2p::tunnel::eDeliveryTypeRouter,
|
|
||||||
nextFloodfill->GetIdentHash (), 0,
|
|
||||||
CreateDatabaseStoreMsg ()
|
|
||||||
});
|
|
||||||
|
|
||||||
// request destination
|
// request destination
|
||||||
LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ());
|
LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ());
|
||||||
auto msg = dest->CreateRequestMessage (nextFloodfill, inbound);
|
outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0,
|
||||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
dest->CreateRequestMessage (nextFloodfill, inbound));
|
||||||
{
|
|
||||||
i2p::tunnel::eDeliveryTypeRouter,
|
|
||||||
nextFloodfill->GetIdentHash (), 0, msg
|
|
||||||
});
|
|
||||||
deleteDest = false;
|
deleteDest = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "NetDb: ", key, " was not found on ", count, " floodfills");
|
LogPrint (eLogWarning, "NetDb: ", key, " was not found on ", count, " floodfills");
|
||||||
|
|
||||||
if (msgs.size () > 0)
|
|
||||||
outbound->SendTunnelDataMsg (msgs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace data
|
||||||
std::shared_ptr<LeaseSet> FindLeaseSet (const IdentHash& destination) const;
|
std::shared_ptr<LeaseSet> FindLeaseSet (const IdentHash& destination) const;
|
||||||
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
||||||
|
|
||||||
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
|
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr, bool direct = true);
|
||||||
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||||
|
|
||||||
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
|
@ -63,7 +63,6 @@ namespace i2p
|
||||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
bool nat; i2p::config::GetOption("nat", nat);
|
bool nat; i2p::config::GetOption("nat", nat);
|
||||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||||
|
@ -83,8 +82,6 @@ namespace i2p
|
||||||
|
|
||||||
if (ssu)
|
if (ssu)
|
||||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||||
if (ntcp)
|
|
||||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
|
||||||
}
|
}
|
||||||
if (ipv6)
|
if (ipv6)
|
||||||
{
|
{
|
||||||
|
@ -99,8 +96,6 @@ namespace i2p
|
||||||
|
|
||||||
if (ssu)
|
if (ssu)
|
||||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||||
if (ntcp)
|
|
||||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
|
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
|
||||||
|
@ -115,20 +110,17 @@ namespace i2p
|
||||||
{
|
{
|
||||||
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
||||||
UpdateNTCP2Address (true);
|
UpdateNTCP2Address (true);
|
||||||
if (!ntcp) // NTCP2 should replace NTCP
|
bool published; i2p::config::GetOption("ntcp2.published", published);
|
||||||
|
if (published)
|
||||||
{
|
{
|
||||||
bool published; i2p::config::GetOption("ntcp2.published", published);
|
PublishNTCP2Address (port, true);
|
||||||
if (published)
|
if (ipv6)
|
||||||
{
|
{
|
||||||
PublishNTCP2Address (port, true);
|
// add NTCP2 ipv6 address
|
||||||
if (ipv6)
|
std::string host = "::1";
|
||||||
{
|
if (!i2p::config::IsDefault ("ntcp2.addressv6"))
|
||||||
// add NTCP2 ipv6 address
|
i2p::config::GetOption ("ntcp2.addressv6", host);
|
||||||
std::string host = "::1";
|
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (host), port);
|
||||||
if (!i2p::config::IsDefault ("ntcp2.addressv6"))
|
|
||||||
i2p::config::GetOption ("ntcp2.addressv6", host);
|
|
||||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (host), port);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,48 +373,19 @@ namespace i2p
|
||||||
return m_RouterInfo.GetCaps () & i2p::data::RouterInfo::eUnreachable;
|
return m_RouterInfo.GetCaps () & i2p::data::RouterInfo::eUnreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterContext::PublishNTCPAddress (bool publish, bool v4only)
|
void RouterContext::RemoveNTCPAddress (bool v4only)
|
||||||
{
|
{
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||||
if (publish)
|
for (auto it = addresses.begin (); it != addresses.end ();)
|
||||||
{
|
{
|
||||||
for (const auto& addr : addresses) // v4
|
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !(*it)->IsNTCP2 () &&
|
||||||
|
(!v4only || (*it)->host.is_v4 ()))
|
||||||
{
|
{
|
||||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
it = addresses.erase (it);
|
||||||
addr->host.is_v4 ())
|
if (v4only) break; // otherwise might be more than one address
|
||||||
{
|
|
||||||
// insert NTCP address with host/port from SSU
|
|
||||||
m_RouterInfo.AddNTCPAddress (addr->host.to_string ().c_str (), addr->port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!v4only)
|
|
||||||
{
|
|
||||||
for (const auto& addr : addresses) // v6
|
|
||||||
{
|
|
||||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU &&
|
|
||||||
addr->host.is_v6 ())
|
|
||||||
{
|
|
||||||
// insert NTCP address with host/port from SSU
|
|
||||||
m_RouterInfo.AddNTCPAddress (addr->host.to_string ().c_str (), addr->port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto it = addresses.begin (); it != addresses.end ();)
|
|
||||||
{
|
|
||||||
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportNTCP && !(*it)->IsNTCP2 () &&
|
|
||||||
(!v4only || (*it)->host.is_v4 ()))
|
|
||||||
{
|
|
||||||
it = addresses.erase (it);
|
|
||||||
if (v4only) break; // otherwise might be more than one address
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,16 +407,10 @@ namespace i2p
|
||||||
addr->ssu->introducers.clear ();
|
addr->ssu->introducers.clear ();
|
||||||
port = addr->port;
|
port = addr->port;
|
||||||
}
|
}
|
||||||
// remove NTCP or NTCP2 v4 address
|
// remove NTCP2 v4 address
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
if (ntcp)
|
if (ntcp2)
|
||||||
PublishNTCPAddress (false);
|
PublishNTCP2Address (port, false, true);
|
||||||
else
|
|
||||||
{
|
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
|
||||||
if (ntcp2)
|
|
||||||
PublishNTCP2Address (port, false, true);
|
|
||||||
}
|
|
||||||
// update
|
// update
|
||||||
UpdateRouterInfo ();
|
UpdateRouterInfo ();
|
||||||
}
|
}
|
||||||
|
@ -477,23 +434,16 @@ namespace i2p
|
||||||
addr->ssu->introducers.clear ();
|
addr->ssu->introducers.clear ();
|
||||||
port = addr->port;
|
port = addr->port;
|
||||||
}
|
}
|
||||||
// insert NTCP or NTCP2 back
|
// insert NTCP2 back
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
if (ntcp)
|
if (ntcp2)
|
||||||
PublishNTCPAddress (true);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// ntcp2
|
bool published; i2p::config::GetOption ("ntcp2.published", published);
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
if (published)
|
||||||
if (ntcp2)
|
|
||||||
{
|
{
|
||||||
bool published; i2p::config::GetOption ("ntcp2.published", published);
|
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
|
||||||
if (published)
|
if (!ntcp2Port) ntcp2Port = port;
|
||||||
{
|
PublishNTCP2Address (ntcp2Port, true, true);
|
||||||
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
|
|
||||||
if (!ntcp2Port) ntcp2Port = port;
|
|
||||||
PublishNTCP2Address (ntcp2Port, true, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update
|
// update
|
||||||
|
@ -506,7 +456,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
m_RouterInfo.EnableV6 ();
|
m_RouterInfo.EnableV6 ();
|
||||||
// insert v6 addresses if necessary
|
// insert v6 addresses if necessary
|
||||||
bool foundSSU = false, foundNTCP = false, foundNTCP2 = false;
|
bool foundSSU = false, foundNTCP2 = false;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr: addresses)
|
for (auto& addr: addresses)
|
||||||
|
@ -515,12 +465,8 @@ namespace i2p
|
||||||
{
|
{
|
||||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||||
foundSSU = true;
|
foundSSU = true;
|
||||||
else if (addr->IsNTCP2 ())
|
else if (addr->IsPublishedNTCP2 ())
|
||||||
{
|
foundNTCP2 = true;
|
||||||
if (addr->IsPublishedNTCP2 ()) foundNTCP2 = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
foundNTCP = true;
|
|
||||||
}
|
}
|
||||||
port = addr->port;
|
port = addr->port;
|
||||||
}
|
}
|
||||||
|
@ -552,16 +498,6 @@ namespace i2p
|
||||||
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port);
|
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (ntcp2Host), ntcp2Port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// NTCP
|
|
||||||
if (!foundNTCP)
|
|
||||||
{
|
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
|
||||||
if (ntcp)
|
|
||||||
{
|
|
||||||
std::string host = "::1";
|
|
||||||
m_RouterInfo.AddNTCPAddress (host.c_str (), port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_RouterInfo.DisableV6 ();
|
m_RouterInfo.DisableV6 ();
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace i2p
|
||||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||||
void PublishNTCP2Address (int port, bool publish = true, bool v4only = false);
|
void PublishNTCP2Address (int port, bool publish = true, bool v4only = false);
|
||||||
void UpdateNTCP2Address (bool enable);
|
void UpdateNTCP2Address (bool enable);
|
||||||
void PublishNTCPAddress (bool publish, bool v4only = true);
|
void RemoveNTCPAddress (bool v4only = true); // delete NTCP address for older routers. TODO: remove later
|
||||||
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
|
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
|
||||||
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||||
bool IsUnreachable () const;
|
bool IsUnreachable () const;
|
||||||
|
|
|
@ -316,7 +316,7 @@ namespace data
|
||||||
}
|
}
|
||||||
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
||||||
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
||||||
if (supportedTransports)
|
if (supportedTransports & ~(eNTCPV4 | eNTCPV6)) // exclude NTCP only
|
||||||
{
|
{
|
||||||
addresses->push_back(address);
|
addresses->push_back(address);
|
||||||
m_SupportedTransports |= supportedTransports;
|
m_SupportedTransports |= supportedTransports;
|
||||||
|
@ -477,7 +477,12 @@ namespace data
|
||||||
s.write ((const char *)&address.date, sizeof (address.date));
|
s.write ((const char *)&address.date, sizeof (address.date));
|
||||||
std::stringstream properties;
|
std::stringstream properties;
|
||||||
if (address.transportStyle == eTransportNTCP)
|
if (address.transportStyle == eTransportNTCP)
|
||||||
WriteString (address.IsNTCP2 () ? "NTCP2" : "NTCP", s);
|
{
|
||||||
|
if (address.IsNTCP2 ())
|
||||||
|
WriteString ("NTCP2", s);
|
||||||
|
else
|
||||||
|
continue; // don't write NTCP address
|
||||||
|
}
|
||||||
else if (address.transportStyle == eTransportSSU)
|
else if (address.transportStyle == eTransportSSU)
|
||||||
{
|
{
|
||||||
WriteString ("SSU", s);
|
WriteString ("SSU", s);
|
||||||
|
@ -704,20 +709,6 @@ namespace data
|
||||||
s.write (str.c_str (), len);
|
s.write (str.c_str (), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::AddNTCPAddress (const char * host, int port)
|
|
||||||
{
|
|
||||||
auto addr = std::make_shared<Address>();
|
|
||||||
addr->host = boost::asio::ip::address::from_string (host);
|
|
||||||
addr->port = port;
|
|
||||||
addr->transportStyle = eTransportNTCP;
|
|
||||||
addr->cost = 6;
|
|
||||||
addr->date = 0;
|
|
||||||
for (const auto& it: *m_Addresses) // don't insert same address twice
|
|
||||||
if (*it == *addr) return;
|
|
||||||
m_SupportedTransports |= addr->host.is_v6 () ? eNTCPV6 : eNTCPV4;
|
|
||||||
m_Addresses->push_front(std::move(addr)); // always make NTCP first
|
|
||||||
}
|
|
||||||
|
|
||||||
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
|
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
|
||||||
{
|
{
|
||||||
auto addr = std::make_shared<Address>();
|
auto addr = std::make_shared<Address>();
|
||||||
|
@ -817,14 +808,6 @@ namespace data
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RouterInfo::IsNTCP (bool v4only) const
|
|
||||||
{
|
|
||||||
if (v4only)
|
|
||||||
return m_SupportedTransports & eNTCPV4;
|
|
||||||
else
|
|
||||||
return m_SupportedTransports & (eNTCPV4 | eNTCPV6);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RouterInfo::IsSSU (bool v4only) const
|
bool RouterInfo::IsSSU (bool v4only) const
|
||||||
{
|
{
|
||||||
if (v4only)
|
if (v4only)
|
||||||
|
@ -907,15 +890,6 @@ namespace data
|
||||||
return m_Caps & Caps::eUnreachable; // non-reachable
|
return m_Caps & Caps::eUnreachable; // non-reachable
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCPAddress (bool v4only) const
|
|
||||||
{
|
|
||||||
return GetAddress (
|
|
||||||
[v4only](std::shared_ptr<const RouterInfo::Address> address)->bool
|
|
||||||
{
|
|
||||||
return (address->transportStyle == eTransportNTCP) && !address->IsNTCP2Only () && (!v4only || address->host.is_v4 ());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
|
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
|
||||||
{
|
{
|
||||||
return GetAddress (
|
return GetAddress (
|
||||||
|
|
|
@ -153,12 +153,10 @@ namespace data
|
||||||
uint64_t GetTimestamp () const { return m_Timestamp; };
|
uint64_t GetTimestamp () const { return m_Timestamp; };
|
||||||
int GetVersion () const { return m_Version; };
|
int GetVersion () const { return m_Version; };
|
||||||
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
||||||
std::shared_ptr<const Address> GetNTCPAddress (bool v4only = true) const;
|
|
||||||
std::shared_ptr<const Address> GetNTCP2Address (bool publishedOnly, bool v4only = true) const;
|
std::shared_ptr<const Address> GetNTCP2Address (bool publishedOnly, bool v4only = true) const;
|
||||||
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
||||||
std::shared_ptr<const Address> GetSSUV6Address () const;
|
std::shared_ptr<const Address> GetSSUV6Address () const;
|
||||||
|
|
||||||
void AddNTCPAddress (const char * host, int port);
|
|
||||||
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
||||||
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0);
|
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0);
|
||||||
bool AddIntroducer (const Introducer& introducer);
|
bool AddIntroducer (const Introducer& introducer);
|
||||||
|
@ -169,7 +167,6 @@ namespace data
|
||||||
void ClearProperties () { m_Properties.clear (); };
|
void ClearProperties () { m_Properties.clear (); };
|
||||||
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
||||||
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
||||||
bool IsNTCP (bool v4only = true) const;
|
|
||||||
bool IsSSU (bool v4only = true) const;
|
bool IsSSU (bool v4only = true) const;
|
||||||
bool IsSSUV6 () const;
|
bool IsSSUV6 () const;
|
||||||
bool IsNTCP2 (bool v4only = true) const;
|
bool IsNTCP2 (bool v4only = true) const;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "NetDb.hpp"
|
#include "NetDb.hpp"
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* See full license text in LICENSE file at top of project tree
|
* See full license text in LICENSE file at top of project tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
|
@ -351,6 +351,28 @@ namespace stream
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stream::HandlePing (Packet * packet)
|
||||||
|
{
|
||||||
|
uint16_t flags = packet->GetFlags ();
|
||||||
|
if (ProcessOptions (flags, packet) && m_RemoteIdentity)
|
||||||
|
{
|
||||||
|
// send pong
|
||||||
|
Packet p;
|
||||||
|
memset (p.buf, 0, 22); // minimal header all zeroes
|
||||||
|
memcpy (p.buf + 4, packet->buf, 4); // but receiveStreamID is the sendStreamID from the ping
|
||||||
|
htobe16buf (p.buf + 18, PACKET_FLAG_ECHO); // and echo flag
|
||||||
|
ssize_t payloadLen = packet->len - (packet->GetPayload () - packet->buf);
|
||||||
|
if (payloadLen > 0)
|
||||||
|
memcpy (p.buf + 22, packet->GetPayload (), payloadLen);
|
||||||
|
else
|
||||||
|
payloadLen = 0;
|
||||||
|
p.len = payloadLen + 22;
|
||||||
|
SendPackets (std::vector<Packet *> { &p });
|
||||||
|
LogPrint (eLogDebug, "Streaming: Pong of ", p.len, " bytes sent");
|
||||||
|
}
|
||||||
|
m_LocalDestination.DeletePacket (packet);
|
||||||
|
}
|
||||||
|
|
||||||
void Stream::ProcessAck (Packet * packet)
|
void Stream::ProcessAck (Packet * packet)
|
||||||
{
|
{
|
||||||
bool acknowledged = false;
|
bool acknowledged = false;
|
||||||
|
@ -609,6 +631,7 @@ namespace stream
|
||||||
packet[size] = 0;
|
packet[size] = 0;
|
||||||
size++; // NACK count
|
size++; // NACK count
|
||||||
}
|
}
|
||||||
|
packet[size] = 0;
|
||||||
size++; // resend delay
|
size++; // resend delay
|
||||||
htobuf16 (packet + size, 0); // no flags set
|
htobuf16 (packet + size, 0); // no flags set
|
||||||
size += 2; // flags
|
size += 2; // flags
|
||||||
|
@ -666,6 +689,7 @@ namespace stream
|
||||||
size += 4; // ack Through
|
size += 4; // ack Through
|
||||||
packet[size] = 0;
|
packet[size] = 0;
|
||||||
size++; // NACK count
|
size++; // NACK count
|
||||||
|
packet[size] = 0;
|
||||||
size++; // resend delay
|
size++; // resend delay
|
||||||
htobe16buf (packet + size, PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
htobe16buf (packet + size, PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
||||||
size += 2; // flags
|
size += 2; // flags
|
||||||
|
@ -1016,6 +1040,13 @@ namespace stream
|
||||||
auto it = m_Streams.find (sendStreamID);
|
auto it = m_Streams.find (sendStreamID);
|
||||||
if (it != m_Streams.end ())
|
if (it != m_Streams.end ())
|
||||||
it->second->HandleNextPacket (packet);
|
it->second->HandleNextPacket (packet);
|
||||||
|
else if (packet->IsEcho () && m_Owner->IsStreamingAnswerPings ())
|
||||||
|
{
|
||||||
|
// ping
|
||||||
|
LogPrint (eLogInfo, "Streaming: Ping received sSID=", sendStreamID);
|
||||||
|
auto s = std::make_shared<Stream> (m_Owner->GetService (), *this);
|
||||||
|
s->HandlePing (packet);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Streaming: Unknown stream sSID=", sendStreamID);
|
LogPrint (eLogInfo, "Streaming: Unknown stream sSID=", sendStreamID);
|
||||||
|
|
|
@ -87,6 +87,7 @@ namespace stream
|
||||||
|
|
||||||
bool IsSYN () const { return GetFlags () & PACKET_FLAG_SYNCHRONIZE; };
|
bool IsSYN () const { return GetFlags () & PACKET_FLAG_SYNCHRONIZE; };
|
||||||
bool IsNoAck () const { return GetFlags () & PACKET_FLAG_NO_ACK; };
|
bool IsNoAck () const { return GetFlags () & PACKET_FLAG_NO_ACK; };
|
||||||
|
bool IsEcho () const { return GetFlags () & PACKET_FLAG_ECHO; };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PacketCmp
|
struct PacketCmp
|
||||||
|
@ -168,6 +169,7 @@ namespace stream
|
||||||
StreamingDestination& GetLocalDestination () { return m_LocalDestination; };
|
StreamingDestination& GetLocalDestination () { return m_LocalDestination; };
|
||||||
|
|
||||||
void HandleNextPacket (Packet * packet);
|
void HandleNextPacket (Packet * packet);
|
||||||
|
void HandlePing (Packet * packet);
|
||||||
size_t Send (const uint8_t * buf, size_t len);
|
size_t Send (const uint8_t * buf, size_t len);
|
||||||
void AsyncSend (const uint8_t * buf, size_t len, SendHandler handler);
|
void AsyncSend (const uint8_t * buf, size_t len, SendHandler handler);
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ namespace transport
|
||||||
Transports::Transports ():
|
Transports::Transports ():
|
||||||
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr),
|
m_IsOnline (true), m_IsRunning (false), m_IsNAT (true), m_Thread (nullptr), m_Service (nullptr),
|
||||||
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr),
|
||||||
m_NTCPServer (nullptr), m_SSUServer (nullptr), m_NTCP2Server (nullptr),
|
m_SSUServer (nullptr), m_NTCP2Server (nullptr),
|
||||||
m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys
|
m_DHKeysPairSupplier (5), m_X25519KeysPairSupplier (5), // 5 pre-generated keys
|
||||||
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
|
m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0),
|
||||||
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0),
|
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0),
|
||||||
|
@ -154,7 +154,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::Start (bool enableNTCP, bool enableSSU)
|
void Transports::Start (bool enableNTCP2, bool enableSSU)
|
||||||
{
|
{
|
||||||
if (!m_Service)
|
if (!m_Service)
|
||||||
{
|
{
|
||||||
|
@ -169,50 +169,10 @@ namespace transport
|
||||||
m_X25519KeysPairSupplier.Start ();
|
m_X25519KeysPairSupplier.Start ();
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
||||||
std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
|
|
||||||
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
|
||||||
i2p::http::URL proxyurl;
|
i2p::http::URL proxyurl;
|
||||||
uint16_t softLimit, hardLimit, threads;
|
|
||||||
i2p::config::GetOption("limits.ntcpsoft", softLimit);
|
|
||||||
i2p::config::GetOption("limits.ntcphard", hardLimit);
|
|
||||||
i2p::config::GetOption("limits.ntcpthreads", threads);
|
|
||||||
if(softLimit > 0 && hardLimit > 0 && softLimit >= hardLimit)
|
|
||||||
{
|
|
||||||
LogPrint(eLogError, "ntcp soft limit must be less than ntcp hard limit");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(ntcpproxy.size() && enableNTCP)
|
|
||||||
{
|
|
||||||
if(proxyurl.parse(ntcpproxy))
|
|
||||||
{
|
|
||||||
if(proxyurl.schema == "socks" || proxyurl.schema == "http")
|
|
||||||
{
|
|
||||||
m_NTCPServer = new NTCPServer(threads);
|
|
||||||
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
|
|
||||||
NTCPServer::ProxyType proxytype = NTCPServer::eSocksProxy;
|
|
||||||
|
|
||||||
if (proxyurl.schema == "http")
|
|
||||||
proxytype = NTCPServer::eHTTPProxy;
|
|
||||||
m_NTCPServer->UseProxy(proxytype, proxyurl.host, proxyurl.port);
|
|
||||||
m_NTCPServer->Start();
|
|
||||||
if(!m_NTCPServer->NetworkIsReady())
|
|
||||||
{
|
|
||||||
LogPrint(eLogError, "Transports: NTCP failed to start with proxy");
|
|
||||||
m_NTCPServer->Stop();
|
|
||||||
delete m_NTCPServer;
|
|
||||||
m_NTCPServer = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint(eLogError, "Transports: unsupported NTCP proxy URL ", ntcpproxy);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint(eLogError, "Transports: invalid NTCP proxy url ", ntcpproxy);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// create NTCP2. TODO: move to acceptor
|
// create NTCP2. TODO: move to acceptor
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
if (enableNTCP2)
|
||||||
if (ntcp2)
|
|
||||||
{
|
{
|
||||||
if(!ntcp2proxy.empty())
|
if(!ntcp2proxy.empty())
|
||||||
{
|
{
|
||||||
|
@ -248,20 +208,6 @@ namespace transport
|
||||||
for (const auto& address : addresses)
|
for (const auto& address : addresses)
|
||||||
{
|
{
|
||||||
if (!address) continue;
|
if (!address) continue;
|
||||||
if (m_NTCPServer == nullptr && enableNTCP)
|
|
||||||
{
|
|
||||||
m_NTCPServer = new NTCPServer (threads);
|
|
||||||
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
|
|
||||||
m_NTCPServer->Start ();
|
|
||||||
if (!(m_NTCPServer->IsBoundV6() || m_NTCPServer->IsBoundV4())) {
|
|
||||||
/** failed to bind to NTCP */
|
|
||||||
LogPrint(eLogError, "Transports: failed to bind to TCP");
|
|
||||||
m_NTCPServer->Stop();
|
|
||||||
delete m_NTCPServer;
|
|
||||||
m_NTCPServer = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address->transportStyle == RouterInfo::eTransportSSU)
|
if (address->transportStyle == RouterInfo::eTransportSSU)
|
||||||
{
|
{
|
||||||
if (m_SSUServer == nullptr && enableSSU)
|
if (m_SSUServer == nullptr && enableSSU)
|
||||||
|
@ -306,13 +252,7 @@ namespace transport
|
||||||
delete m_SSUServer;
|
delete m_SSUServer;
|
||||||
m_SSUServer = nullptr;
|
m_SSUServer = nullptr;
|
||||||
}
|
}
|
||||||
if (m_NTCPServer)
|
|
||||||
{
|
|
||||||
m_NTCPServer->Stop ();
|
|
||||||
delete m_NTCPServer;
|
|
||||||
m_NTCPServer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_NTCP2Server)
|
if (m_NTCP2Server)
|
||||||
{
|
{
|
||||||
m_NTCP2Server->Stop ();
|
m_NTCP2Server->Stop ();
|
||||||
|
@ -472,41 +412,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (peer.numAttempts == 1) // NTCP1
|
if (peer.numAttempts == 1)// SSU
|
||||||
{
|
|
||||||
peer.numAttempts++;
|
|
||||||
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
|
||||||
if (address && m_NTCPServer)
|
|
||||||
{
|
|
||||||
if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ())
|
|
||||||
{
|
|
||||||
if(!m_NTCPServer->ShouldLimit())
|
|
||||||
{
|
|
||||||
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
|
|
||||||
if(m_NTCPServer->UsingProxy())
|
|
||||||
{
|
|
||||||
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address;
|
|
||||||
std::string addr = address->host.to_string();
|
|
||||||
|
|
||||||
if(address->host.is_v6())
|
|
||||||
remote = NTCPServer::eIP6Address;
|
|
||||||
|
|
||||||
m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_NTCPServer->Connect (address->host, address->port, s);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint(eLogWarning, "Transports: NTCP Limit hit falling back to SSU");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint (eLogDebug, "Transports: NTCP address is not present for ", i2p::data::GetIdentHashAbbreviation (ident), ", trying SSU");
|
|
||||||
}
|
|
||||||
if (peer.numAttempts == 2)// SSU
|
|
||||||
{
|
{
|
||||||
peer.numAttempts++;
|
peer.numAttempts++;
|
||||||
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "TransportSession.h"
|
#include "TransportSession.h"
|
||||||
#include "NTCPSession.h"
|
|
||||||
#include "SSU.h"
|
#include "SSU.h"
|
||||||
#include "NTCP2.h"
|
#include "NTCP2.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
|
@ -88,10 +87,9 @@ namespace transport
|
||||||
Transports ();
|
Transports ();
|
||||||
~Transports ();
|
~Transports ();
|
||||||
|
|
||||||
void Start (bool enableNTCP=true, bool enableSSU=true);
|
void Start (bool enableNTCP2=true, bool enableSSU=true);
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
bool IsBoundNTCP() const { return m_NTCPServer != nullptr; }
|
|
||||||
bool IsBoundSSU() const { return m_SSUServer != nullptr; }
|
bool IsBoundSSU() const { return m_SSUServer != nullptr; }
|
||||||
bool IsBoundNTCP2() const { return m_NTCP2Server != nullptr; }
|
bool IsBoundNTCP2() const { return m_NTCP2Server != nullptr; }
|
||||||
|
|
||||||
|
@ -159,7 +157,6 @@ namespace transport
|
||||||
boost::asio::io_service::work * m_Work;
|
boost::asio::io_service::work * m_Work;
|
||||||
boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer;
|
boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer;
|
||||||
|
|
||||||
NTCPServer * m_NTCPServer;
|
|
||||||
SSUServer * m_SSUServer;
|
SSUServer * m_SSUServer;
|
||||||
NTCP2Server * m_NTCP2Server;
|
NTCP2Server * m_NTCP2Server;
|
||||||
mutable std::mutex m_PeersMutex;
|
mutable std::mutex m_PeersMutex;
|
||||||
|
@ -186,7 +183,6 @@ namespace transport
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
const NTCPServer * GetNTCPServer () const { return m_NTCPServer; };
|
|
||||||
const SSUServer * GetSSUServer () const { return m_SSUServer; };
|
const SSUServer * GetSSUServer () const { return m_SSUServer; };
|
||||||
const NTCP2Server * GetNTCP2Server () const { return m_NTCP2Server; };
|
const NTCP2Server * GetNTCP2Server () const { return m_NTCP2Server; };
|
||||||
const decltype(m_Peers)& GetPeers () const { return m_Peers; };
|
const decltype(m_Peers)& GetPeers () const { return m_Peers; };
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace tunnel
|
||||||
const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
|
const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
|
||||||
const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes
|
const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes
|
||||||
const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds
|
const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds
|
||||||
const int STANDARD_NUM_RECORDS = 5; // in VariableTunnelBuild message
|
const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message
|
||||||
|
|
||||||
enum TunnelState
|
enum TunnelState
|
||||||
{
|
{
|
||||||
|
|
|
@ -806,6 +806,7 @@ namespace client
|
||||||
i2p::http::HTTPReq req;
|
i2p::http::HTTPReq req;
|
||||||
req.AddHeader("Host", dest_host);
|
req.AddHeader("Host", dest_host);
|
||||||
req.AddHeader("User-Agent", "Wget/1.11.4");
|
req.AddHeader("User-Agent", "Wget/1.11.4");
|
||||||
|
req.AddHeader("Accept-Encoding", "gzip");
|
||||||
req.AddHeader("X-Accept-Encoding", "x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0");
|
req.AddHeader("X-Accept-Encoding", "x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0");
|
||||||
req.AddHeader("Connection", "close");
|
req.AddHeader("Connection", "close");
|
||||||
if (!m_Etag.empty())
|
if (!m_Etag.empty())
|
||||||
|
@ -816,6 +817,7 @@ namespace client
|
||||||
url.schema = "";
|
url.schema = "";
|
||||||
url.host = "";
|
url.host = "";
|
||||||
req.uri = url.to_string();
|
req.uri = url.to_string();
|
||||||
|
req.version = "HTTP/1.1";
|
||||||
auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
|
auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
|
||||||
std::string request = req.to_string();
|
std::string request = req.to_string();
|
||||||
stream->Send ((const uint8_t *) request.data(), request.length());
|
stream->Send ((const uint8_t *) request.data(), request.length());
|
||||||
|
@ -887,7 +889,7 @@ namespace client
|
||||||
/* assert: res.code == 200 */
|
/* assert: res.code == 200 */
|
||||||
auto it = res.headers.find("ETag");
|
auto it = res.headers.find("ETag");
|
||||||
if (it != res.headers.end()) m_Etag = it->second;
|
if (it != res.headers.end()) m_Etag = it->second;
|
||||||
it = res.headers.find("If-Modified-Since");
|
it = res.headers.find("Last-Modified");
|
||||||
if (it != res.headers.end()) m_LastModified = it->second;
|
if (it != res.headers.end()) m_LastModified = it->second;
|
||||||
if (res.is_chunked())
|
if (res.is_chunked())
|
||||||
{
|
{
|
||||||
|
@ -895,7 +897,7 @@ namespace client
|
||||||
i2p::http::MergeChunkedResponse (in, out);
|
i2p::http::MergeChunkedResponse (in, out);
|
||||||
response = out.str();
|
response = out.str();
|
||||||
}
|
}
|
||||||
else if (res.is_gzipped())
|
if (res.is_gzipped())
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
i2p::data::GzipInflator inflator;
|
i2p::data::GzipInflator inflator;
|
||||||
|
|
|
@ -102,10 +102,11 @@ namespace client
|
||||||
{
|
{
|
||||||
std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
|
std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
|
||||||
uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort);
|
uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort);
|
||||||
|
bool singleThread; i2p::config::GetOption("i2cp.singlethread", singleThread);
|
||||||
LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort);
|
LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort);
|
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort, singleThread);
|
||||||
m_I2CPServer->Start ();
|
m_I2CPServer->Start ();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
@ -401,7 +402,14 @@ namespace client
|
||||||
|
|
||||||
void ClientContext::CreateNewSharedLocalDestination ()
|
void ClientContext::CreateNewSharedLocalDestination ()
|
||||||
{
|
{
|
||||||
m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, EDDSA
|
std::map<std::string, std::string> params
|
||||||
|
{
|
||||||
|
{ I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, "2" },
|
||||||
|
{ I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, "2" },
|
||||||
|
{ I2CP_PARAM_LEASESET_TYPE, "3" }
|
||||||
|
};
|
||||||
|
m_SharedLocalDestination = CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||||
|
i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, ¶ms); // non-public, EDDSA
|
||||||
m_SharedLocalDestination->Acquire ();
|
m_SharedLocalDestination->Acquire ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +444,7 @@ namespace client
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Section>
|
template<typename Section>
|
||||||
void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const
|
void ClientContext::ReadI2CPOptions (const Section& section, bool isServer, std::map<std::string, std::string>& options) const
|
||||||
{
|
{
|
||||||
options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH);
|
options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH);
|
||||||
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
|
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
|
||||||
|
@ -446,6 +454,7 @@ namespace client
|
||||||
options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY);
|
options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY);
|
||||||
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY);
|
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY);
|
||||||
options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY);
|
options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY);
|
||||||
|
options[I2CP_PARAM_STREAMING_ANSWER_PINGS] = GetI2CPOption(section, I2CP_PARAM_STREAMING_ANSWER_PINGS, isServer ? DEFAULT_ANSWER_PINGS : false);
|
||||||
options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE);
|
options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE);
|
||||||
std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "");
|
std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "");
|
||||||
if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType;
|
if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType;
|
||||||
|
@ -561,7 +570,7 @@ namespace client
|
||||||
i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
|
i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
|
||||||
// I2CP
|
// I2CP
|
||||||
std::map<std::string, std::string> options;
|
std::map<std::string, std::string> options;
|
||||||
ReadI2CPOptions (section, options);
|
ReadI2CPOptions (section, false, options);
|
||||||
|
|
||||||
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
||||||
if (keys.length () > 0)
|
if (keys.length () > 0)
|
||||||
|
@ -685,7 +694,7 @@ namespace client
|
||||||
|
|
||||||
// I2CP
|
// I2CP
|
||||||
std::map<std::string, std::string> options;
|
std::map<std::string, std::string> options;
|
||||||
ReadI2CPOptions (section, options);
|
ReadI2CPOptions (section, true, options);
|
||||||
|
|
||||||
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
||||||
auto it = destinations.find (keys);
|
auto it = destinations.find (keys);
|
||||||
|
@ -837,6 +846,8 @@ namespace client
|
||||||
bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy);
|
bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy);
|
||||||
if (socksproxy)
|
if (socksproxy)
|
||||||
{
|
{
|
||||||
|
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
|
||||||
|
// we still need httpProxyKeys to compare with sockProxyKeys
|
||||||
std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys);
|
std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys);
|
||||||
std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr);
|
std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr);
|
||||||
uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort);
|
uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort);
|
||||||
|
@ -845,7 +856,12 @@ namespace client
|
||||||
uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort);
|
uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort);
|
||||||
i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType);
|
i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType);
|
||||||
LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort);
|
LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort);
|
||||||
if (socksProxyKeys.length () > 0)
|
if (httpProxyKeys == socksProxyKeys && m_HttpProxy)
|
||||||
|
{
|
||||||
|
localDestination = m_HttpProxy->GetLocalDestination ();
|
||||||
|
localDestination->Acquire ();
|
||||||
|
}
|
||||||
|
else if (socksProxyKeys.length () > 0)
|
||||||
{
|
{
|
||||||
i2p::data::PrivateKeys keys;
|
i2p::data::PrivateKeys keys;
|
||||||
if (LoadPrivateKeys (keys, socksProxyKeys, sigType))
|
if (LoadPrivateKeys (keys, socksProxyKeys, sigType))
|
||||||
|
|
|
@ -115,7 +115,7 @@ namespace client
|
||||||
template<typename Section>
|
template<typename Section>
|
||||||
void ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map<std::string, std::string>& options) const;
|
void ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map<std::string, std::string>& options) const;
|
||||||
template<typename Section>
|
template<typename Section>
|
||||||
void ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const; // for tunnels
|
void ReadI2CPOptions (const Section& section, bool isServer, std::map<std::string, std::string>& options) const; // for tunnels
|
||||||
void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const; // for HTTP and SOCKS proxy
|
void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const; // for HTTP and SOCKS proxy
|
||||||
|
|
||||||
void CleanupUDP(const boost::system::error_code & ecode);
|
void CleanupUDP(const boost::system::error_code & ecode);
|
||||||
|
|
|
@ -23,36 +23,13 @@ namespace i2p
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
|
|
||||||
I2CPDestination::I2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
||||||
RunnableService ("I2CP"), LeaseSetDestination (GetIOService (), isPublic, ¶ms),
|
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||||
|
LeaseSetDestination (service, isPublic, ¶ms),
|
||||||
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ())
|
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
I2CPDestination::~I2CPDestination ()
|
|
||||||
{
|
|
||||||
if (IsRunning ())
|
|
||||||
Stop ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void I2CPDestination::Start ()
|
|
||||||
{
|
|
||||||
if (!IsRunning ())
|
|
||||||
{
|
|
||||||
LeaseSetDestination::Start ();
|
|
||||||
StartIOService ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void I2CPDestination::Stop ()
|
|
||||||
{
|
|
||||||
if (IsRunning ())
|
|
||||||
{
|
|
||||||
LeaseSetDestination::Stop ();
|
|
||||||
StopIOService ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
|
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
|
||||||
{
|
{
|
||||||
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), key);
|
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), key);
|
||||||
|
@ -217,6 +194,37 @@ namespace client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunnableI2CPDestination::RunnableI2CPDestination (std::shared_ptr<I2CPSession> owner,
|
||||||
|
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||||
|
RunnableService ("I2CP"),
|
||||||
|
I2CPDestination (GetIOService (), owner, identity, isPublic, params)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RunnableI2CPDestination::~RunnableI2CPDestination ()
|
||||||
|
{
|
||||||
|
if (IsRunning ())
|
||||||
|
Stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnableI2CPDestination::Start ()
|
||||||
|
{
|
||||||
|
if (!IsRunning ())
|
||||||
|
{
|
||||||
|
I2CPDestination::Start ();
|
||||||
|
StartIOService ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunnableI2CPDestination::Stop ()
|
||||||
|
{
|
||||||
|
if (IsRunning ())
|
||||||
|
{
|
||||||
|
I2CPDestination::Stop ();
|
||||||
|
StopIOService ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<proto::socket> socket):
|
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<proto::socket> socket):
|
||||||
m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
|
m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
|
||||||
m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true)
|
m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true)
|
||||||
|
@ -451,7 +459,9 @@ namespace client
|
||||||
if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false;
|
if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false;
|
||||||
if (!m_Destination)
|
if (!m_Destination)
|
||||||
{
|
{
|
||||||
m_Destination = std::make_shared<I2CPDestination>(shared_from_this (), identity, isPublic, params);
|
m_Destination = m_Owner.IsSingleThread () ?
|
||||||
|
std::make_shared<I2CPDestination>(m_Owner.GetService (), shared_from_this (), identity, isPublic, params):
|
||||||
|
std::make_shared<RunnableI2CPDestination>(shared_from_this (), identity, isPublic, params);
|
||||||
SendSessionStatusMessage (1); // created
|
SendSessionStatusMessage (1); // created
|
||||||
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created");
|
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created");
|
||||||
m_Destination->Start ();
|
m_Destination->Start ();
|
||||||
|
@ -800,9 +810,9 @@ namespace client
|
||||||
std::placeholders::_1, std::placeholders::_2, buf));
|
std::placeholders::_1, std::placeholders::_2, buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
I2CPServer::I2CPServer (const std::string& interface, int port):
|
I2CPServer::I2CPServer (const std::string& interface, int port, bool isSingleThread):
|
||||||
m_IsRunning (false), m_Thread (nullptr),
|
RunnableService ("I2CP"), m_IsSingleThread (isSingleThread),
|
||||||
m_Acceptor (m_Service,
|
m_Acceptor (GetIOService (),
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
|
I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
|
||||||
#else
|
#else
|
||||||
|
@ -825,20 +835,18 @@ namespace client
|
||||||
|
|
||||||
I2CPServer::~I2CPServer ()
|
I2CPServer::~I2CPServer ()
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (IsRunning ())
|
||||||
Stop ();
|
Stop ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPServer::Start ()
|
void I2CPServer::Start ()
|
||||||
{
|
{
|
||||||
Accept ();
|
Accept ();
|
||||||
m_IsRunning = true;
|
StartIOService ();
|
||||||
m_Thread = new std::thread (std::bind (&I2CPServer::Run, this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPServer::Stop ()
|
void I2CPServer::Stop ()
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
|
||||||
m_Acceptor.cancel ();
|
m_Acceptor.cancel ();
|
||||||
{
|
{
|
||||||
auto sessions = m_Sessions;
|
auto sessions = m_Sessions;
|
||||||
|
@ -846,33 +854,12 @@ namespace client
|
||||||
it.second->Stop ();
|
it.second->Stop ();
|
||||||
}
|
}
|
||||||
m_Sessions.clear ();
|
m_Sessions.clear ();
|
||||||
m_Service.stop ();
|
StopIOService ();
|
||||||
if (m_Thread)
|
|
||||||
{
|
|
||||||
m_Thread->join ();
|
|
||||||
delete m_Thread;
|
|
||||||
m_Thread = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void I2CPServer::Run ()
|
|
||||||
{
|
|
||||||
while (m_IsRunning)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_Service.run ();
|
|
||||||
}
|
|
||||||
catch (std::exception& ex)
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "I2CP: runtime exception: ", ex.what ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPServer::Accept ()
|
void I2CPServer::Accept ()
|
||||||
{
|
{
|
||||||
auto newSocket = std::make_shared<I2CPSession::proto::socket> (m_Service);
|
auto newSocket = std::make_shared<I2CPSession::proto::socket> (GetIOService ());
|
||||||
m_Acceptor.async_accept (*newSocket, std::bind (&I2CPServer::HandleAccept, this,
|
m_Acceptor.async_accept (*newSocket, std::bind (&I2CPServer::HandleAccept, this,
|
||||||
std::placeholders::_1, newSocket));
|
std::placeholders::_1, newSocket));
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,16 +63,14 @@ namespace client
|
||||||
const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability";
|
const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability";
|
||||||
|
|
||||||
class I2CPSession;
|
class I2CPSession;
|
||||||
class I2CPDestination: private i2p::util::RunnableService, public LeaseSetDestination
|
class I2CPDestination: public LeaseSetDestination
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params);
|
I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
||||||
~I2CPDestination ();
|
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params);
|
||||||
|
~I2CPDestination () {};
|
||||||
void Start ();
|
|
||||||
void Stop ();
|
|
||||||
|
|
||||||
void SetEncryptionPrivateKey (const uint8_t * key);
|
void SetEncryptionPrivateKey (const uint8_t * key);
|
||||||
void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; };
|
void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; };
|
||||||
void SetECIESx25519EncryptionPrivateKey (const uint8_t * key);
|
void SetECIESx25519EncryptionPrivateKey (const uint8_t * key);
|
||||||
|
@ -109,6 +107,18 @@ namespace client
|
||||||
uint64_t m_LeaseSetExpirationTime;
|
uint64_t m_LeaseSetExpirationTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
RunnableI2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity,
|
||||||
|
bool isPublic, const std::map<std::string, std::string>& params);
|
||||||
|
~RunnableI2CPDestination ();
|
||||||
|
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
};
|
||||||
|
|
||||||
class I2CPServer;
|
class I2CPServer;
|
||||||
class I2CPSession: public std::enable_shared_from_this<I2CPSession>
|
class I2CPSession: public std::enable_shared_from_this<I2CPSession>
|
||||||
{
|
{
|
||||||
|
@ -179,17 +189,18 @@ namespace client
|
||||||
};
|
};
|
||||||
typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len);
|
typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
class I2CPServer
|
class I2CPServer: private i2p::util::RunnableService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2CPServer (const std::string& interface, int port);
|
I2CPServer (const std::string& interface, int port, bool isSingleThread);
|
||||||
~I2CPServer ();
|
~I2CPServer ();
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return GetIOService (); };
|
||||||
|
bool IsSingleThread () const { return m_IsSingleThread; };
|
||||||
|
|
||||||
bool InsertSession (std::shared_ptr<I2CPSession> session);
|
bool InsertSession (std::shared_ptr<I2CPSession> session);
|
||||||
void RemoveSession (uint16_t sessionID);
|
void RemoveSession (uint16_t sessionID);
|
||||||
|
|
||||||
|
@ -203,12 +214,10 @@ namespace client
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool m_IsSingleThread;
|
||||||
I2CPMessageHandler m_MessagesHandlers[256];
|
I2CPMessageHandler m_MessagesHandlers[256];
|
||||||
std::map<uint16_t, std::shared_ptr<I2CPSession> > m_Sessions;
|
std::map<uint16_t, std::shared_ptr<I2CPSession> > m_Sessions;
|
||||||
|
|
||||||
bool m_IsRunning;
|
|
||||||
std::thread * m_Thread;
|
|
||||||
boost::asio::io_service m_Service;
|
|
||||||
I2CPSession::proto::acceptor m_Acceptor;
|
I2CPSession::proto::acceptor m_Acceptor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -139,22 +139,25 @@ namespace client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
WriteToStream (m_Buffer, bytes_transferred);
|
||||||
if (m_Stream)
|
|
||||||
{
|
|
||||||
auto s = shared_from_this ();
|
|
||||||
m_Stream->AsyncSend (m_Buffer, bytes_transferred,
|
|
||||||
[s](const boost::system::error_code& ecode)
|
|
||||||
{
|
|
||||||
if (!ecode)
|
|
||||||
s->Receive ();
|
|
||||||
else
|
|
||||||
s->Terminate ();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I2PTunnelConnection::WriteToStream (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
if (m_Stream)
|
||||||
|
{
|
||||||
|
auto s = shared_from_this ();
|
||||||
|
m_Stream->AsyncSend (buf, len,
|
||||||
|
[s](const boost::system::error_code& ecode)
|
||||||
|
{
|
||||||
|
if (!ecode)
|
||||||
|
s->Receive ();
|
||||||
|
else
|
||||||
|
s->Terminate ();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void I2PTunnelConnection::HandleWrite (const boost::system::error_code& ecode)
|
void I2PTunnelConnection::HandleWrite (const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
if (ecode)
|
if (ecode)
|
||||||
|
@ -302,7 +305,8 @@ namespace client
|
||||||
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||||
const boost::asio::ip::tcp::endpoint& target, const std::string& host):
|
const boost::asio::ip::tcp::endpoint& target, const std::string& host):
|
||||||
I2PTunnelConnection (owner, stream, socket, target), m_Host (host), m_HeaderSent (false), m_From (stream->GetRemoteIdentity ())
|
I2PTunnelConnection (owner, stream, socket, target), m_Host (host),
|
||||||
|
m_HeaderSent (false), m_ResponseHeaderSent (false), m_From (stream->GetRemoteIdentity ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +328,7 @@ namespace client
|
||||||
if (line == "\r") endOfHeader = true;
|
if (line == "\r") endOfHeader = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_Host.length () > 0 && line.find ("Host:") != std::string::npos)
|
if (m_Host.length () > 0 && !line.compare(0, 5, "Host:"))
|
||||||
m_OutHeader << "Host: " << m_Host << "\r\n"; // override host
|
m_OutHeader << "Host: " << m_Host << "\r\n"; // override host
|
||||||
else
|
else
|
||||||
m_OutHeader << line << "\n";
|
m_OutHeader << line << "\n";
|
||||||
|
@ -333,12 +337,63 @@ namespace client
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// add X-I2P fields
|
|
||||||
if (m_From)
|
if (endOfHeader)
|
||||||
{
|
{
|
||||||
m_OutHeader << X_I2P_DEST_B32 << ": " << context.GetAddressBook ().ToAddress(m_From->GetIdentHash ()) << "\r\n";
|
// add X-I2P fields
|
||||||
m_OutHeader << X_I2P_DEST_HASH << ": " << m_From->GetIdentHash ().ToBase64 () << "\r\n";
|
if (m_From)
|
||||||
m_OutHeader << X_I2P_DEST_B64 << ": " << m_From->ToBase64 () << "\r\n";
|
{
|
||||||
|
m_OutHeader << X_I2P_DEST_B32 << ": " << context.GetAddressBook ().ToAddress(m_From->GetIdentHash ()) << "\r\n";
|
||||||
|
m_OutHeader << X_I2P_DEST_HASH << ": " << m_From->GetIdentHash ().ToBase64 () << "\r\n";
|
||||||
|
m_OutHeader << X_I2P_DEST_B64 << ": " << m_From->ToBase64 () << "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_OutHeader << "\r\n"; // end of header
|
||||||
|
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
||||||
|
m_InHeader.str ("");
|
||||||
|
m_From = nullptr;
|
||||||
|
m_HeaderSent = true;
|
||||||
|
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PServerTunnelConnectionHTTP::WriteToStream (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
if (m_ResponseHeaderSent)
|
||||||
|
I2PTunnelConnection::WriteToStream (buf, len);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_InHeader.clear ();
|
||||||
|
if (m_InHeader.str ().empty ()) m_OutHeader.str (""); // start of response
|
||||||
|
m_InHeader.write ((const char *)buf, len);
|
||||||
|
std::string line;
|
||||||
|
bool endOfHeader = false;
|
||||||
|
while (!endOfHeader)
|
||||||
|
{
|
||||||
|
std::getline(m_InHeader, line);
|
||||||
|
if (!m_InHeader.fail ())
|
||||||
|
{
|
||||||
|
if (line == "\r") endOfHeader = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const std::vector<std::string> excluded // list of excluded headers
|
||||||
|
{
|
||||||
|
"Server:", "Date:", "X-Runtime:", "X-Powered-By:", "Proxy"
|
||||||
|
};
|
||||||
|
bool matched = false;
|
||||||
|
for (const auto& it: excluded)
|
||||||
|
if (!line.compare(0, it.length (), it))
|
||||||
|
{
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!matched)
|
||||||
|
m_OutHeader << line << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endOfHeader)
|
if (endOfHeader)
|
||||||
|
@ -346,12 +401,15 @@ namespace client
|
||||||
m_OutHeader << "\r\n"; // end of header
|
m_OutHeader << "\r\n"; // end of header
|
||||||
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
||||||
m_InHeader.str ("");
|
m_InHeader.str ("");
|
||||||
m_HeaderSent = true;
|
m_ResponseHeaderSent = true;
|
||||||
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
I2PTunnelConnection::WriteToStream ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||||
}
|
m_OutHeader.str ("");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Receive ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||||
const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass):
|
const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass):
|
||||||
|
|
|
@ -57,7 +57,8 @@ namespace client
|
||||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
|
virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
|
||||||
void HandleWrite (const boost::system::error_code& ecode);
|
void HandleWrite (const boost::system::error_code& ecode);
|
||||||
|
virtual void WriteToStream (const uint8_t * buf, size_t len); // can be overloaded
|
||||||
|
|
||||||
void StreamReceive ();
|
void StreamReceive ();
|
||||||
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleConnect (const boost::system::error_code& ecode);
|
void HandleConnect (const boost::system::error_code& ecode);
|
||||||
|
@ -103,12 +104,13 @@ namespace client
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void Write (const uint8_t * buf, size_t len);
|
void Write (const uint8_t * buf, size_t len);
|
||||||
|
void WriteToStream (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string m_Host;
|
std::string m_Host;
|
||||||
std::stringstream m_InHeader, m_OutHeader;
|
std::stringstream m_InHeader, m_OutHeader;
|
||||||
bool m_HeaderSent;
|
bool m_HeaderSent, m_ResponseHeaderSent;
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> m_From;
|
std::shared_ptr<const i2p::data::IdentityEx> m_From;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
|
||||||
../../libi2pd/NetDb.cpp \
|
../../libi2pd/NetDb.cpp \
|
||||||
../../libi2pd/NetDbRequests.cpp \
|
../../libi2pd/NetDbRequests.cpp \
|
||||||
../../libi2pd/NTCP2.cpp \
|
../../libi2pd/NTCP2.cpp \
|
||||||
../../libi2pd/NTCPSession.cpp \
|
|
||||||
../../libi2pd/Poly1305.cpp \
|
../../libi2pd/Poly1305.cpp \
|
||||||
../../libi2pd/Profiling.cpp \
|
../../libi2pd/Profiling.cpp \
|
||||||
../../libi2pd/Reseed.cpp \
|
../../libi2pd/Reseed.cpp \
|
||||||
|
@ -123,7 +122,6 @@ HEADERS += DaemonQT.h mainwindow.h \
|
||||||
../../libi2pd/NetDb.hpp \
|
../../libi2pd/NetDb.hpp \
|
||||||
../../libi2pd/NetDbRequests.h \
|
../../libi2pd/NetDbRequests.h \
|
||||||
../../libi2pd/NTCP2.h \
|
../../libi2pd/NTCP2.h \
|
||||||
../../libi2pd/NTCPSession.h \
|
|
||||||
../../libi2pd/Poly1305.h \
|
../../libi2pd/Poly1305.h \
|
||||||
../../libi2pd/Profiling.h \
|
../../libi2pd/Profiling.h \
|
||||||
../../libi2pd/Queue.h \
|
../../libi2pd/Queue.h \
|
||||||
|
|
Loading…
Add table
Reference in a new issue