mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-16 18:59:56 +00:00
commit
260564345a
@ -15,7 +15,7 @@ ifeq ($(shell expr match $(CXX) 'clang'),5)
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10
|
||||
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
|
||||
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
|
||||
NEEDED_CXXFLAGS += -std=c++11
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
} else {
|
||||
Result = E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -90,4 +91,4 @@ void SubscribeToEvents() { }
|
||||
void UnSubscribeFromEvents() { }
|
||||
|
||||
#endif // WINVER
|
||||
#endif
|
||||
#endif
|
||||
|
18
appveyor.yml
18
appveyor.yml
@ -21,11 +21,25 @@ environment:
|
||||
MSYS_BITNESS: 32
|
||||
|
||||
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"
|
||||
# TODO: revert that change when appveyor's images will be updated
|
||||
- c:\msys64\usr\bin\bash -l "build/appveyor-msys2-upgrade.bash"
|
||||
# update runtime
|
||||
- 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
|
||||
- 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}/NetDbRequests.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/NTCPSession.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Profiling.cpp"
|
||||
"${LIBI2PD_SRC_DIR}/Reseed.cpp"
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "Base.h"
|
||||
#include "version.h"
|
||||
#include "Transports.h"
|
||||
#include "NTCPSession.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "RouterContext.h"
|
||||
#include "Tunnel.h"
|
||||
@ -135,8 +134,8 @@ namespace i2p
|
||||
i2p::context.SetNetID (netID);
|
||||
i2p::context.Init ();
|
||||
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
#ifdef MESHNET
|
||||
// manual override for meshnet
|
||||
ipv4 = false;
|
||||
@ -151,8 +150,7 @@ namespace i2p
|
||||
i2p::context.SetSupportsV6 (ipv6);
|
||||
i2p::context.SetSupportsV4 (ipv4);
|
||||
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
i2p::context.PublishNTCPAddress (ntcp, !ipv6);
|
||||
i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
@ -160,7 +158,7 @@ namespace i2p
|
||||
if (published)
|
||||
{
|
||||
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
|
||||
if (ipv6)
|
||||
{
|
||||
@ -180,13 +178,10 @@ namespace i2p
|
||||
SetMaxNumTransitTunnels (transitTunnels);
|
||||
|
||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||
if (isFloodfill)
|
||||
{
|
||||
if (isFloodfill) {
|
||||
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
||||
i2p::context.SetFloodfill (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
i2p::context.SetFloodfill (false);
|
||||
}
|
||||
|
||||
@ -254,8 +249,7 @@ namespace i2p
|
||||
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
||||
restricted = fams.size() > 0;
|
||||
}
|
||||
if (routers.length() > 0)
|
||||
{
|
||||
if (routers.length() > 0) {
|
||||
std::set<i2p::data::IdentHash> idents;
|
||||
size_t pos = 0, comma;
|
||||
do
|
||||
@ -291,8 +285,7 @@ namespace i2p
|
||||
i2p::data::netdb.Start();
|
||||
|
||||
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->Start ();
|
||||
}
|
||||
@ -304,16 +297,16 @@ namespace i2p
|
||||
d.m_NTPSync->Start ();
|
||||
}
|
||||
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
||||
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);
|
||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
i2p::transport::transports.Start(ntcp2, ssu);
|
||||
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||
else
|
||||
else
|
||||
{
|
||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||
/** shut down netdb right away */
|
||||
@ -323,23 +316,23 @@ namespace i2p
|
||||
}
|
||||
|
||||
bool http; i2p::config::GetOption("http.enabled", http);
|
||||
if (http)
|
||||
{
|
||||
if (http) {
|
||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
||||
try
|
||||
try
|
||||
{
|
||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||
d.httpServer->Start();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
|
||||
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
||||
i2p::tunnel::tunnels.Start();
|
||||
|
||||
@ -352,12 +345,12 @@ namespace i2p
|
||||
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
||||
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
||||
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
||||
try
|
||||
try
|
||||
{
|
||||
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||
d.m_I2PControlService->Start ();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
|
||||
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
||||
@ -374,7 +367,7 @@ namespace i2p
|
||||
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
||||
i2p::tunnel::tunnels.Stop();
|
||||
|
||||
if (d.UPnP)
|
||||
if (d.UPnP)
|
||||
{
|
||||
d.UPnP->Stop ();
|
||||
d.UPnP = nullptr;
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "Base.h"
|
||||
@ -733,13 +732,6 @@ namespace http {
|
||||
void ShowTransports (std::stringstream& s)
|
||||
{
|
||||
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 ();
|
||||
if (ntcp2Server)
|
||||
{
|
||||
@ -1321,8 +1313,8 @@ namespace http {
|
||||
void HTTPServer::Accept ()
|
||||
{
|
||||
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (m_Service);
|
||||
m_Acceptor.async_accept (*newSocket, boost::bind (&HTTPServer::HandleAccept, this,
|
||||
boost::asio::placeholders::error, newSocket));
|
||||
m_Acceptor.async_accept (*newSocket, std::bind (&HTTPServer::HandleAccept, this,
|
||||
std::placeholders::_1, newSocket));
|
||||
}
|
||||
|
||||
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 <sstream>
|
||||
#include <openssl/x509.h>
|
||||
@ -14,12 +6,7 @@
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
|
||||
// There is bug in boost 1.49 with gcc 4.7 coming with Debian Wheezy
|
||||
#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))
|
||||
#if !GCC47_BOOST149
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#endif
|
||||
|
||||
#include "Crypto.h"
|
||||
#include "FS.h"
|
||||
@ -67,28 +54,29 @@ namespace client
|
||||
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
||||
|
||||
// handlers
|
||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||
|
||||
// I2PControl
|
||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||
|
||||
// RouterInfo
|
||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||
m_RouterInfoHandlers["i2p.router.net.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.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||
|
||||
@ -104,10 +92,10 @@ namespace client
|
||||
// ClientServicesInfo
|
||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
}
|
||||
|
||||
I2PControlService::~I2PControlService ()
|
||||
@ -242,12 +230,6 @@ namespace client
|
||||
}
|
||||
}
|
||||
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::read_json (ss, pt);
|
||||
|
||||
@ -267,7 +249,6 @@ namespace client
|
||||
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
||||
response << "\"jsonrpc\":\"2.0\"}";
|
||||
}
|
||||
#endif
|
||||
SendResponse (socket, buf, response, isHtml);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
@ -408,8 +389,8 @@ namespace client
|
||||
auto it1 = m_RouterInfoHandlers.find (it->first);
|
||||
if (it1 != m_RouterInfoHandlers.end ())
|
||||
{
|
||||
if (!first) results << ",";
|
||||
else first = false;
|
||||
if (!first) results << ",";
|
||||
else first = false;
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
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.async_wait (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
{
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
@ -521,7 +502,7 @@ namespace client
|
||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
||||
m_ShutdownTimer.async_wait (
|
||||
[](const boost::system::error_code& ecode)
|
||||
{
|
||||
{
|
||||
Daemon.running = 0;
|
||||
});
|
||||
}
|
||||
|
@ -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
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
@ -88,10 +79,10 @@ namespace transport
|
||||
void UPnP::Discover ()
|
||||
{
|
||||
bool isError;
|
||||
int err;
|
||||
int err;
|
||||
|
||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||
err = UPNPDISCOVER_SUCCESS;
|
||||
err = UPNPDISCOVER_SUCCESS;
|
||||
|
||||
#if (MINIUPNPC_API_VERSION >= 14)
|
||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
|
||||
@ -100,9 +91,9 @@ namespace transport
|
||||
#endif
|
||||
|
||||
isError = err != UPNPDISCOVER_SUCCESS;
|
||||
#else // MINIUPNPC_API_VERSION >= 8
|
||||
err = 0;
|
||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||
#else // MINIUPNPC_API_VERSION >= 8
|
||||
err = 0;
|
||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||
isError = m_Devlist == NULL;
|
||||
#endif // MINIUPNPC_API_VERSION >= 8
|
||||
{
|
||||
@ -113,15 +104,15 @@ namespace transport
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -190,7 +181,7 @@ namespace transport
|
||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||
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))
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -227,14 +218,14 @@ namespace transport
|
||||
|
||||
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
||||
{
|
||||
if(!m_upnpUrlsInitialized) {
|
||||
return;
|
||||
}
|
||||
if(!m_upnpUrlsInitialized) {
|
||||
return;
|
||||
}
|
||||
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
|
||||
int err = UPNPCOMMAND_SUCCESS;
|
||||
|
||||
|
||||
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);
|
||||
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
|
||||
@ -245,11 +236,11 @@ namespace transport
|
||||
{
|
||||
freeUPNPDevlist (m_Devlist);
|
||||
m_Devlist = 0;
|
||||
if(m_upnpUrlsInitialized){
|
||||
FreeUPNPUrls (&m_upnpUrls);
|
||||
m_upnpUrlsInitialized=false;
|
||||
}
|
||||
}
|
||||
if(m_upnpUrlsInitialized){
|
||||
FreeUPNPUrls (&m_upnpUrls);
|
||||
m_upnpUrlsInitialized=false;
|
||||
}
|
||||
}
|
||||
|
||||
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)")
|
||||
("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)")
|
||||
("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)")
|
||||
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
|
||||
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
|
||||
#ifdef _WIN32
|
||||
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
|
||||
("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.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
|
||||
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
||||
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
||||
("httpproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist HTTP Proxy keys. Transient by default")
|
||||
("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")
|
||||
("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.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
|
||||
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
||||
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
||||
("socksproxy.keys", value<std::string>()->default_value("transient-proxy"), "File to persist SOCKS Proxy keys. Transient by default")
|
||||
("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")
|
||||
("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.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.singlethread", value<bool>()->default_value(true), "Destinations run in the I2CP server's thread")
|
||||
;
|
||||
|
||||
options_description i2pcontrol("I2PControl options");
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <vector>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "Crypto.h"
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
#include "FS.h"
|
||||
#include "Timestamp.h"
|
||||
@ -464,14 +465,14 @@ namespace client
|
||||
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
|
||||
{
|
||||
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::netdb.RequestDestination (peerHash);
|
||||
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");
|
||||
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
|
||||
if (floodfill)
|
||||
@ -603,9 +604,8 @@ namespace client
|
||||
return;
|
||||
}
|
||||
auto s = shared_from_this ();
|
||||
// we must capture this for gcc 4.7 due the bug
|
||||
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)
|
||||
{
|
||||
@ -744,14 +744,19 @@ namespace client
|
||||
request->excluded.insert (nextFloodfill->GetIdentHash ());
|
||||
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];
|
||||
RAND_bytes (replyKey, 32); // random session key
|
||||
RAND_bytes (replyTag, 32); // random session tag
|
||||
AddSessionKey (replyKey, replyTag);
|
||||
RAND_bytes (replyTag, isECIES ? 8 : 32); // random session tag
|
||||
if (isECIES)
|
||||
AddECIESx25519Key (replyKey, replyTag);
|
||||
else
|
||||
AddSessionKey (replyKey, replyTag);
|
||||
|
||||
auto msg = WrapMessage (nextFloodfill,
|
||||
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
||||
request->replyTunnel, replyKey, replyTag));
|
||||
request->replyTunnel, replyKey, replyTag, isECIES));
|
||||
request->outboundTunnel->SendTunnelDataMsg (
|
||||
{
|
||||
i2p::tunnel::TunnelMessageBlock
|
||||
@ -845,8 +850,9 @@ namespace client
|
||||
|
||||
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
||||
bool isPublic, const std::map<std::string, std::string> * params):
|
||||
LeaseSetDestination (service, isPublic, params),
|
||||
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
||||
LeaseSetDestination (service, isPublic, params),
|
||||
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
||||
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS),
|
||||
m_DatagramDestination (nullptr), m_RefCounter (0),
|
||||
m_ReadyChecker(service)
|
||||
{
|
||||
@ -855,8 +861,7 @@ namespace client
|
||||
|
||||
// extract encryption type params for LS2
|
||||
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
|
||||
if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
|
||||
GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
|
||||
if (params)
|
||||
{
|
||||
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
||||
if (it != params->end ())
|
||||
@ -915,7 +920,10 @@ namespace client
|
||||
auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
|
||||
if (it != params->end ())
|
||||
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)
|
||||
{
|
||||
// authentication for encrypted LeaseSet
|
||||
|
@ -78,6 +78,8 @@ namespace client
|
||||
// streaming
|
||||
const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay";
|
||||
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;
|
||||
|
||||
@ -242,7 +244,8 @@ namespace client
|
||||
bool IsAcceptingStreams () const;
|
||||
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
||||
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
||||
|
||||
bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; }
|
||||
|
||||
// datagram
|
||||
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
||||
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
|
||||
@ -275,6 +278,7 @@ namespace client
|
||||
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
|
||||
|
||||
int m_StreamingAckDelay;
|
||||
bool m_IsStreamingAnswerPings;
|
||||
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
||||
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
||||
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
||||
|
@ -88,12 +88,67 @@ namespace garlic
|
||||
}
|
||||
}
|
||||
|
||||
void RatchetTagSet::DeleteSymmKey (int index)
|
||||
{
|
||||
m_ItermediateSymmKeys.erase (index);
|
||||
}
|
||||
|
||||
void RatchetTagSet::Expire ()
|
||||
{
|
||||
if (!m_ExpirationTimestamp)
|
||||
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):
|
||||
GarlicRoutingSession (owner, attachLeaseSet)
|
||||
{
|
||||
@ -657,7 +712,12 @@ namespace garlic
|
||||
moreTags -= (receiveTagset->GetNextIndex () - index);
|
||||
}
|
||||
if (moreTags > 0)
|
||||
{
|
||||
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
||||
index -= (moreTags >> 1); // /2
|
||||
if (index > 0)
|
||||
receiveTagset->SetTrimBehind (index);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace garlic
|
||||
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
|
||||
|
||||
class ECIESX25519AEADRatchetSession;
|
||||
class RatchetTagSet
|
||||
class RatchetTagSet: public std::enable_shared_from_this<RatchetTagSet>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -52,14 +52,19 @@ namespace garlic
|
||||
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
|
||||
int GetNextIndex () const { return m_NextIndex; };
|
||||
void GetSymmKey (int index, uint8_t * key);
|
||||
void DeleteSymmKey (int index);
|
||||
|
||||
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session.lock (); };
|
||||
int GetTagSetID () const { return m_TagSetID; };
|
||||
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
|
||||
void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; };
|
||||
|
||||
void Expire ();
|
||||
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:
|
||||
|
||||
union
|
||||
@ -73,7 +78,7 @@ namespace garlic
|
||||
|
||||
} m_KeyData;
|
||||
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::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
|
||||
int m_TagSetID = 0;
|
||||
@ -91,6 +96,21 @@ namespace garlic
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
AddSessionKey (key, tag);
|
||||
@ -507,8 +515,7 @@ namespace garlic
|
||||
if (it1 != m_ECIESx25519Tags.end ())
|
||||
{
|
||||
found = true;
|
||||
auto session = it1->second.tagset->GetSession ();
|
||||
if (!session || !session->HandleNextMessage (buf, length, it1->second.tagset, it1->second.index))
|
||||
if (!it1->second.tagset->HandleNextMessage (buf, length, it1->second.index))
|
||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||
m_ECIESx25519Tags.erase (it1);
|
||||
}
|
||||
@ -802,14 +809,6 @@ namespace garlic
|
||||
}
|
||||
}
|
||||
// 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 ();)
|
||||
{
|
||||
if (it->second->CheckExpired (ts))
|
||||
@ -820,6 +819,20 @@ namespace garlic
|
||||
else
|
||||
++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)
|
||||
@ -1009,7 +1022,7 @@ namespace garlic
|
||||
{
|
||||
auto index = tagset->GetNextIndex ();
|
||||
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)
|
||||
|
@ -220,7 +220,6 @@ namespace garlic
|
||||
{
|
||||
int index;
|
||||
RatchetTagSetPtr tagset;
|
||||
uint64_t creationTime; // seconds since epoch
|
||||
};
|
||||
|
||||
class GarlicDestination: public i2p::data::LocalDestination
|
||||
@ -242,6 +241,7 @@ namespace garlic
|
||||
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
|
||||
|
||||
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
|
||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
||||
|
@ -171,7 +171,8 @@ namespace i2p
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||
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 ();
|
||||
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
||||
@ -180,7 +181,8 @@ namespace i2p
|
||||
buf += 32;
|
||||
memcpy (buf, replyTunnel->GetNextIdentHash (), 32); // reply tunnel GW
|
||||
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 ++;
|
||||
htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID
|
||||
buf += 4;
|
||||
@ -204,8 +206,16 @@ namespace i2p
|
||||
// encryption
|
||||
memcpy (buf, replyKey, 32);
|
||||
buf[32] = 1; // 1 tag
|
||||
memcpy (buf + 33, replyTag, 32);
|
||||
buf += 65;
|
||||
if (replyECIES)
|
||||
{
|
||||
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->FillI2NPMessageHeader (eI2NPDatabaseLookup);
|
||||
|
@ -251,8 +251,9 @@ namespace tunnel
|
||||
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);
|
||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag);
|
||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||
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> 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 timeout = NTCP_CONNECT_TIMEOUT * 5;
|
||||
auto timeout = NTCP2_CONNECT_TIMEOUT * 5;
|
||||
conn->SetTerminationTimeout(timeout * 2);
|
||||
timer->expires_from_now (boost::posix_time::seconds(timeout));
|
||||
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++;
|
||||
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
|
||||
if (it.second->UsesIntroducer ())
|
||||
{
|
||||
@ -575,7 +578,7 @@ namespace data
|
||||
// delete RI file
|
||||
m_Storage.Remove(ident);
|
||||
deletedCount++;
|
||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||
}
|
||||
} // 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
|
||||
if (!dest)
|
||||
@ -621,7 +624,23 @@ namespace data
|
||||
|
||||
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
|
||||
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
|
||||
{
|
||||
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found");
|
||||
@ -775,37 +794,21 @@ namespace data
|
||||
// reply to our destination. Try other floodfills
|
||||
if (outbound && inbound)
|
||||
{
|
||||
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||
auto count = dest->GetExcludedPeers ().size ();
|
||||
if (count < 7)
|
||||
{
|
||||
auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ());
|
||||
if (nextFloodfill)
|
||||
{
|
||||
// tell floodfill about us
|
||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||
{
|
||||
i2p::tunnel::eDeliveryTypeRouter,
|
||||
nextFloodfill->GetIdentHash (), 0,
|
||||
CreateDatabaseStoreMsg ()
|
||||
});
|
||||
|
||||
// request destination
|
||||
LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ());
|
||||
auto msg = dest->CreateRequestMessage (nextFloodfill, inbound);
|
||||
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||
{
|
||||
i2p::tunnel::eDeliveryTypeRouter,
|
||||
nextFloodfill->GetIdentHash (), 0, msg
|
||||
});
|
||||
outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0,
|
||||
dest->CreateRequestMessage (nextFloodfill, inbound));
|
||||
deleteDest = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
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<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 HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||
|
@ -63,7 +63,6 @@ namespace i2p
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool nat; i2p::config::GetOption("nat", nat);
|
||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||
@ -83,8 +82,6 @@ namespace i2p
|
||||
|
||||
if (ssu)
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
if (ntcp)
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
}
|
||||
if (ipv6)
|
||||
{
|
||||
@ -99,8 +96,6 @@ namespace i2p
|
||||
|
||||
if (ssu)
|
||||
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
|
||||
if (ntcp)
|
||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||
}
|
||||
|
||||
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
|
||||
@ -115,20 +110,17 @@ namespace i2p
|
||||
{
|
||||
if (!m_NTCP2Keys) NewNTCP2Keys ();
|
||||
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);
|
||||
if (published)
|
||||
PublishNTCP2Address (port, true);
|
||||
if (ipv6)
|
||||
{
|
||||
PublishNTCP2Address (port, true);
|
||||
if (ipv6)
|
||||
{
|
||||
// add NTCP2 ipv6 address
|
||||
std::string host = "::1";
|
||||
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);
|
||||
}
|
||||
// add NTCP2 ipv6 address
|
||||
std::string host = "::1";
|
||||
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;
|
||||
}
|
||||
|
||||
void RouterContext::PublishNTCPAddress (bool publish, bool v4only)
|
||||
void RouterContext::RemoveNTCPAddress (bool v4only)
|
||||
{
|
||||
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 &&
|
||||
addr->host.is_v4 ())
|
||||
{
|
||||
// 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;
|
||||
it = addresses.erase (it);
|
||||
if (v4only) break; // otherwise might be more than one address
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,16 +407,10 @@ namespace i2p
|
||||
addr->ssu->introducers.clear ();
|
||||
port = addr->port;
|
||||
}
|
||||
// remove NTCP or NTCP2 v4 address
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
if (ntcp)
|
||||
PublishNTCPAddress (false);
|
||||
else
|
||||
{
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
PublishNTCP2Address (port, false, true);
|
||||
}
|
||||
// remove NTCP2 v4 address
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
PublishNTCP2Address (port, false, true);
|
||||
// update
|
||||
UpdateRouterInfo ();
|
||||
}
|
||||
@ -477,23 +434,16 @@ namespace i2p
|
||||
addr->ssu->introducers.clear ();
|
||||
port = addr->port;
|
||||
}
|
||||
// insert NTCP or NTCP2 back
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
if (ntcp)
|
||||
PublishNTCPAddress (true);
|
||||
else
|
||||
// insert NTCP2 back
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
{
|
||||
// ntcp2
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
bool published; i2p::config::GetOption ("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
bool published; i2p::config::GetOption ("ntcp2.published", published);
|
||||
if (published)
|
||||
{
|
||||
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
|
||||
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
|
||||
@ -506,7 +456,7 @@ namespace i2p
|
||||
{
|
||||
m_RouterInfo.EnableV6 ();
|
||||
// insert v6 addresses if necessary
|
||||
bool foundSSU = false, foundNTCP = false, foundNTCP2 = false;
|
||||
bool foundSSU = false, foundNTCP2 = false;
|
||||
uint16_t port = 0;
|
||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||
for (auto& addr: addresses)
|
||||
@ -515,12 +465,8 @@ namespace i2p
|
||||
{
|
||||
if (addr->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
foundSSU = true;
|
||||
else if (addr->IsNTCP2 ())
|
||||
{
|
||||
if (addr->IsPublishedNTCP2 ()) foundNTCP2 = true;
|
||||
}
|
||||
else
|
||||
foundNTCP = true;
|
||||
else if (addr->IsPublishedNTCP2 ())
|
||||
foundNTCP2 = true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
// NTCP
|
||||
if (!foundNTCP)
|
||||
{
|
||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||
if (ntcp)
|
||||
{
|
||||
std::string host = "::1";
|
||||
m_RouterInfo.AddNTCPAddress (host.c_str (), port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_RouterInfo.DisableV6 ();
|
||||
|
@ -89,7 +89,7 @@ namespace i2p
|
||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||
void PublishNTCP2Address (int port, bool publish = true, bool v4only = false);
|
||||
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);
|
||||
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
||||
bool IsUnreachable () const;
|
||||
|
@ -316,7 +316,7 @@ namespace data
|
||||
}
|
||||
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
||||
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
||||
if (supportedTransports)
|
||||
if (supportedTransports & ~(eNTCPV4 | eNTCPV6)) // exclude NTCP only
|
||||
{
|
||||
addresses->push_back(address);
|
||||
m_SupportedTransports |= supportedTransports;
|
||||
@ -477,7 +477,12 @@ namespace data
|
||||
s.write ((const char *)&address.date, sizeof (address.date));
|
||||
std::stringstream properties;
|
||||
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)
|
||||
{
|
||||
WriteString ("SSU", s);
|
||||
@ -704,20 +709,6 @@ namespace data
|
||||
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)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
@ -817,14 +808,6 @@ namespace data
|
||||
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
|
||||
{
|
||||
if (v4only)
|
||||
@ -907,15 +890,6 @@ namespace data
|
||||
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
|
||||
{
|
||||
return GetAddress (
|
||||
|
@ -153,12 +153,10 @@ namespace data
|
||||
uint64_t GetTimestamp () const { return m_Timestamp; };
|
||||
int GetVersion () const { return m_Version; };
|
||||
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> GetSSUAddress (bool v4only = true) 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 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);
|
||||
@ -169,7 +167,6 @@ namespace data
|
||||
void ClearProperties () { m_Properties.clear (); };
|
||||
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
||||
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
||||
bool IsNTCP (bool v4only = true) const;
|
||||
bool IsSSU (bool v4only = true) const;
|
||||
bool IsSSUV6 () const;
|
||||
bool IsNTCP2 (bool v4only = true) const;
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "RouterContext.h"
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "NetDb.hpp"
|
||||
|
@ -6,7 +6,6 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include "version.h"
|
||||
#include "Crypto.h"
|
||||
#include "Log.h"
|
||||
|
@ -351,6 +351,28 @@ namespace stream
|
||||
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)
|
||||
{
|
||||
bool acknowledged = false;
|
||||
@ -609,6 +631,7 @@ namespace stream
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
}
|
||||
packet[size] = 0;
|
||||
size++; // resend delay
|
||||
htobuf16 (packet + size, 0); // no flags set
|
||||
size += 2; // flags
|
||||
@ -666,6 +689,7 @@ namespace stream
|
||||
size += 4; // ack Through
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
packet[size] = 0;
|
||||
size++; // resend delay
|
||||
htobe16buf (packet + size, PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
||||
size += 2; // flags
|
||||
@ -1016,6 +1040,13 @@ namespace stream
|
||||
auto it = m_Streams.find (sendStreamID);
|
||||
if (it != m_Streams.end ())
|
||||
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
|
||||
{
|
||||
LogPrint (eLogInfo, "Streaming: Unknown stream sSID=", sendStreamID);
|
||||
|
@ -87,6 +87,7 @@ namespace stream
|
||||
|
||||
bool IsSYN () const { return GetFlags () & PACKET_FLAG_SYNCHRONIZE; };
|
||||
bool IsNoAck () const { return GetFlags () & PACKET_FLAG_NO_ACK; };
|
||||
bool IsEcho () const { return GetFlags () & PACKET_FLAG_ECHO; };
|
||||
};
|
||||
|
||||
struct PacketCmp
|
||||
@ -168,6 +169,7 @@ namespace stream
|
||||
StreamingDestination& GetLocalDestination () { return m_LocalDestination; };
|
||||
|
||||
void HandleNextPacket (Packet * packet);
|
||||
void HandlePing (Packet * packet);
|
||||
size_t Send (const uint8_t * buf, size_t len);
|
||||
void AsyncSend (const uint8_t * buf, size_t len, SendHandler handler);
|
||||
|
||||
|
@ -133,7 +133,7 @@ namespace transport
|
||||
Transports::Transports ():
|
||||
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_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_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (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)
|
||||
{
|
||||
@ -169,50 +169,10 @@ namespace transport
|
||||
m_X25519KeysPairSupplier.Start ();
|
||||
m_IsRunning = true;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
i2p::http::URL proxyurl;
|
||||
// create NTCP2. TODO: move to acceptor
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
if (ntcp2)
|
||||
if (enableNTCP2)
|
||||
{
|
||||
if(!ntcp2proxy.empty())
|
||||
{
|
||||
@ -248,20 +208,6 @@ namespace transport
|
||||
for (const auto& address : addresses)
|
||||
{
|
||||
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 (m_SSUServer == nullptr && enableSSU)
|
||||
@ -306,13 +252,7 @@ namespace transport
|
||||
delete m_SSUServer;
|
||||
m_SSUServer = nullptr;
|
||||
}
|
||||
if (m_NTCPServer)
|
||||
{
|
||||
m_NTCPServer->Stop ();
|
||||
delete m_NTCPServer;
|
||||
m_NTCPServer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (m_NTCP2Server)
|
||||
{
|
||||
m_NTCP2Server->Stop ();
|
||||
@ -472,41 +412,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peer.numAttempts == 1) // NTCP1
|
||||
{
|
||||
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
|
||||
if (peer.numAttempts == 1)// SSU
|
||||
{
|
||||
peer.numAttempts++;
|
||||
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <atomic>
|
||||
#include <boost/asio.hpp>
|
||||
#include "TransportSession.h"
|
||||
#include "NTCPSession.h"
|
||||
#include "SSU.h"
|
||||
#include "NTCP2.h"
|
||||
#include "RouterInfo.h"
|
||||
@ -88,10 +87,9 @@ namespace transport
|
||||
Transports ();
|
||||
~Transports ();
|
||||
|
||||
void Start (bool enableNTCP=true, bool enableSSU=true);
|
||||
void Start (bool enableNTCP2=true, bool enableSSU=true);
|
||||
void Stop ();
|
||||
|
||||
bool IsBoundNTCP() const { return m_NTCPServer != nullptr; }
|
||||
bool IsBoundSSU() const { return m_SSUServer != nullptr; }
|
||||
bool IsBoundNTCP2() const { return m_NTCP2Server != nullptr; }
|
||||
|
||||
@ -159,7 +157,6 @@ namespace transport
|
||||
boost::asio::io_service::work * m_Work;
|
||||
boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer;
|
||||
|
||||
NTCPServer * m_NTCPServer;
|
||||
SSUServer * m_SSUServer;
|
||||
NTCP2Server * m_NTCP2Server;
|
||||
mutable std::mutex m_PeersMutex;
|
||||
@ -186,7 +183,6 @@ namespace transport
|
||||
public:
|
||||
|
||||
// for HTTP only
|
||||
const NTCPServer * GetNTCPServer () const { return m_NTCPServer; };
|
||||
const SSUServer * GetSSUServer () const { return m_SSUServer; };
|
||||
const NTCP2Server * GetNTCP2Server () const { return m_NTCP2Server; };
|
||||
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_RECREATION_THRESHOLD = 90; // 1.5 minutes
|
||||
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
|
||||
{
|
||||
|
@ -806,6 +806,7 @@ namespace client
|
||||
i2p::http::HTTPReq req;
|
||||
req.AddHeader("Host", dest_host);
|
||||
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("Connection", "close");
|
||||
if (!m_Etag.empty())
|
||||
@ -816,6 +817,7 @@ namespace client
|
||||
url.schema = "";
|
||||
url.host = "";
|
||||
req.uri = url.to_string();
|
||||
req.version = "HTTP/1.1";
|
||||
auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
|
||||
std::string request = req.to_string();
|
||||
stream->Send ((const uint8_t *) request.data(), request.length());
|
||||
@ -887,7 +889,7 @@ namespace client
|
||||
/* assert: res.code == 200 */
|
||||
auto it = res.headers.find("ETag");
|
||||
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 (res.is_chunked())
|
||||
{
|
||||
@ -895,7 +897,7 @@ namespace client
|
||||
i2p::http::MergeChunkedResponse (in, out);
|
||||
response = out.str();
|
||||
}
|
||||
else if (res.is_gzipped())
|
||||
if (res.is_gzipped())
|
||||
{
|
||||
std::stringstream out;
|
||||
i2p::data::GzipInflator inflator;
|
||||
|
@ -102,10 +102,11 @@ namespace client
|
||||
{
|
||||
std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
|
||||
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);
|
||||
try
|
||||
{
|
||||
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort);
|
||||
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort, singleThread);
|
||||
m_I2CPServer->Start ();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
@ -401,7 +402,14 @@ namespace client
|
||||
|
||||
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 ();
|
||||
}
|
||||
|
||||
@ -436,7 +444,7 @@ namespace client
|
||||
}
|
||||
|
||||
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_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_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_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);
|
||||
std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "");
|
||||
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);
|
||||
// I2CP
|
||||
std::map<std::string, std::string> options;
|
||||
ReadI2CPOptions (section, options);
|
||||
ReadI2CPOptions (section, false, options);
|
||||
|
||||
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
||||
if (keys.length () > 0)
|
||||
@ -685,7 +694,7 @@ namespace client
|
||||
|
||||
// I2CP
|
||||
std::map<std::string, std::string> options;
|
||||
ReadI2CPOptions (section, options);
|
||||
ReadI2CPOptions (section, true, options);
|
||||
|
||||
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
||||
auto it = destinations.find (keys);
|
||||
@ -837,6 +846,8 @@ namespace client
|
||||
bool socksproxy; i2p::config::GetOption("socksproxy.enabled", 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 socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr);
|
||||
uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort);
|
||||
@ -845,7 +856,12 @@ namespace client
|
||||
uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort);
|
||||
i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType);
|
||||
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;
|
||||
if (LoadPrivateKeys (keys, socksProxyKeys, sigType))
|
||||
|
@ -115,7 +115,7 @@ namespace client
|
||||
template<typename Section>
|
||||
void ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map<std::string, std::string>& options) const;
|
||||
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 CleanupUDP(const boost::system::error_code & ecode);
|
||||
|
@ -23,36 +23,13 @@ namespace i2p
|
||||
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):
|
||||
RunnableService ("I2CP"), LeaseSetDestination (GetIOService (), isPublic, ¶ms),
|
||||
I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
||||
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 ())
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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):
|
||||
m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
|
||||
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 (!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
|
||||
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created");
|
||||
m_Destination->Start ();
|
||||
@ -800,9 +810,9 @@ namespace client
|
||||
std::placeholders::_1, std::placeholders::_2, buf));
|
||||
}
|
||||
|
||||
I2CPServer::I2CPServer (const std::string& interface, int port):
|
||||
m_IsRunning (false), m_Thread (nullptr),
|
||||
m_Acceptor (m_Service,
|
||||
I2CPServer::I2CPServer (const std::string& interface, int port, bool isSingleThread):
|
||||
RunnableService ("I2CP"), m_IsSingleThread (isSingleThread),
|
||||
m_Acceptor (GetIOService (),
|
||||
#ifdef ANDROID
|
||||
I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
|
||||
#else
|
||||
@ -825,20 +835,18 @@ namespace client
|
||||
|
||||
I2CPServer::~I2CPServer ()
|
||||
{
|
||||
if (m_IsRunning)
|
||||
if (IsRunning ())
|
||||
Stop ();
|
||||
}
|
||||
|
||||
void I2CPServer::Start ()
|
||||
{
|
||||
Accept ();
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&I2CPServer::Run, this));
|
||||
StartIOService ();
|
||||
}
|
||||
|
||||
void I2CPServer::Stop ()
|
||||
{
|
||||
m_IsRunning = false;
|
||||
m_Acceptor.cancel ();
|
||||
{
|
||||
auto sessions = m_Sessions;
|
||||
@ -846,33 +854,12 @@ namespace client
|
||||
it.second->Stop ();
|
||||
}
|
||||
m_Sessions.clear ();
|
||||
m_Service.stop ();
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
StopIOService ();
|
||||
}
|
||||
|
||||
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,
|
||||
std::placeholders::_1, newSocket));
|
||||
}
|
||||
|
@ -63,16 +63,14 @@ namespace client
|
||||
const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability";
|
||||
|
||||
class I2CPSession;
|
||||
class I2CPDestination: private i2p::util::RunnableService, public LeaseSetDestination
|
||||
class I2CPDestination: public LeaseSetDestination
|
||||
{
|
||||
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 ();
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
||||
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params);
|
||||
~I2CPDestination () {};
|
||||
|
||||
void SetEncryptionPrivateKey (const uint8_t * key);
|
||||
void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; };
|
||||
void SetECIESx25519EncryptionPrivateKey (const uint8_t * key);
|
||||
@ -109,6 +107,18 @@ namespace client
|
||||
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 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);
|
||||
|
||||
class I2CPServer
|
||||
class I2CPServer: private i2p::util::RunnableService
|
||||
{
|
||||
public:
|
||||
|
||||
I2CPServer (const std::string& interface, int port);
|
||||
I2CPServer (const std::string& interface, int port, bool isSingleThread);
|
||||
~I2CPServer ();
|
||||
|
||||
void Start ();
|
||||
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);
|
||||
void RemoveSession (uint16_t sessionID);
|
||||
|
||||
@ -203,12 +214,10 @@ namespace client
|
||||
|
||||
private:
|
||||
|
||||
bool m_IsSingleThread;
|
||||
I2CPMessageHandler m_MessagesHandlers[256];
|
||||
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;
|
||||
|
||||
public:
|
||||
|
@ -139,22 +139,25 @@ namespace client
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 ();
|
||||
});
|
||||
}
|
||||
}
|
||||
WriteToStream (m_Buffer, bytes_transferred);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (ecode)
|
||||
@ -302,7 +305,8 @@ namespace client
|
||||
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
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;
|
||||
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
|
||||
else
|
||||
m_OutHeader << line << "\n";
|
||||
@ -333,12 +337,63 @@ namespace client
|
||||
else
|
||||
break;
|
||||
}
|
||||
// add X-I2P fields
|
||||
if (m_From)
|
||||
|
||||
if (endOfHeader)
|
||||
{
|
||||
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";
|
||||
// add X-I2P fields
|
||||
if (m_From)
|
||||
{
|
||||
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)
|
||||
@ -346,12 +401,15 @@ namespace client
|
||||
m_OutHeader << "\r\n"; // end of header
|
||||
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
||||
m_InHeader.str ("");
|
||||
m_HeaderSent = true;
|
||||
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||
}
|
||||
}
|
||||
m_ResponseHeaderSent = true;
|
||||
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,
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
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);
|
||||
virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
|
||||
void HandleWrite (const boost::system::error_code& ecode);
|
||||
|
||||
virtual void WriteToStream (const uint8_t * buf, size_t len); // can be overloaded
|
||||
|
||||
void StreamReceive ();
|
||||
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleConnect (const boost::system::error_code& ecode);
|
||||
@ -103,12 +104,13 @@ namespace client
|
||||
protected:
|
||||
|
||||
void Write (const uint8_t * buf, size_t len);
|
||||
void WriteToStream (const uint8_t * buf, size_t len);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Host;
|
||||
std::stringstream m_InHeader, m_OutHeader;
|
||||
bool m_HeaderSent;
|
||||
bool m_HeaderSent, m_ResponseHeaderSent;
|
||||
std::shared_ptr<const i2p::data::IdentityEx> m_From;
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
|
||||
../../libi2pd/NetDb.cpp \
|
||||
../../libi2pd/NetDbRequests.cpp \
|
||||
../../libi2pd/NTCP2.cpp \
|
||||
../../libi2pd/NTCPSession.cpp \
|
||||
../../libi2pd/Poly1305.cpp \
|
||||
../../libi2pd/Profiling.cpp \
|
||||
../../libi2pd/Reseed.cpp \
|
||||
@ -123,7 +122,6 @@ HEADERS += DaemonQT.h mainwindow.h \
|
||||
../../libi2pd/NetDb.hpp \
|
||||
../../libi2pd/NetDbRequests.h \
|
||||
../../libi2pd/NTCP2.h \
|
||||
../../libi2pd/NTCPSession.h \
|
||||
../../libi2pd/Poly1305.h \
|
||||
../../libi2pd/Profiling.h \
|
||||
../../libi2pd/Queue.h \
|
||||
|
Loading…
x
Reference in New Issue
Block a user