mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ab5ac66b6 |
9
.github/workflows/docker.yml
vendored
9
.github/workflows/docker.yml
vendored
@@ -1,11 +1,6 @@
|
||||
name: Build containers
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- openssl
|
||||
tags:
|
||||
- '*'
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
@@ -63,8 +58,6 @@ jobs:
|
||||
push: true
|
||||
tags: |
|
||||
purplei2p/i2pd:latest
|
||||
purplei2p/i2pd:latest-release
|
||||
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||
ghcr.io/purplei2p/i2pd:latest
|
||||
ghcr.io/purplei2p/i2pd:latest-release
|
||||
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||
|
||||
30
ChangeLog
30
ChangeLog
@@ -1,36 +1,6 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.42.0] - 2022-05-22
|
||||
### Added
|
||||
- Preliminary SSU2 implementation
|
||||
- Tunnel length variance
|
||||
- Localization to French
|
||||
- Daily cleanup of obsolete peer profiles
|
||||
- Ordered jump services list in HTTP proxy
|
||||
- Win32 service
|
||||
- Show port for local non-published SSU addresses in web console
|
||||
### Changed
|
||||
- Maximum RouterInfo length increased to 3K
|
||||
- Skip unknown addresses in RouterInfo
|
||||
- Don't pick own router for peer test
|
||||
- Reseeds list
|
||||
- Internal numeric id for families
|
||||
- Use ipv6 preference only when netinet headers not used
|
||||
- Close stream if delete requested
|
||||
- Remove version from title in web console
|
||||
- Drop MESHNET build option
|
||||
- Set data path before initialization
|
||||
- Don't show registration block in web console if token is not provided
|
||||
### Fixed
|
||||
- Encrypted LeaseSet for EdDSA signature
|
||||
- Clients tunnels are not built if clock is not synced on start
|
||||
- Incorrect processing of i2cp.dontPublishLeaseSet param
|
||||
- UDP tunnels reload
|
||||
- Build for LibreSSL 3.5.2
|
||||
- Race condition in short tunnel build message
|
||||
- Race condition in local RouterInfo buffer allocation
|
||||
|
||||
## [2.41.0] - 2022-02-20
|
||||
### Added
|
||||
- Clock syncronization through SSU
|
||||
|
||||
19
Makefile
19
Makefile
@@ -40,6 +40,12 @@ USE_GIT_VERSION := $(or $(USE_GIT_VERSION),no)
|
||||
# for MacOS only, waiting for "1", not "yes"
|
||||
HOMEBREW := $(or $(HOMEBREW),0)
|
||||
|
||||
# Client protocols
|
||||
USE_I2PC := $(or $(USE_I2PC),yes)
|
||||
USE_I2CP := $(or $(USE_I2CP),yes)
|
||||
USE_SAM := $(or $(USE_SAM),yes)
|
||||
USE_BOB := $(or $(USE_BOB),yes)
|
||||
|
||||
ifeq ($(DEBUG),yes)
|
||||
CXX_DEBUG = -g
|
||||
else
|
||||
@@ -47,6 +53,19 @@ else
|
||||
LD_DEBUG = -s
|
||||
endif
|
||||
|
||||
ifeq ($(USE_I2PC),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_I2PC
|
||||
endif
|
||||
ifeq ($(USE_I2CP),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_I2CP
|
||||
endif
|
||||
ifeq ($(USE_SAM),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_SAM
|
||||
endif
|
||||
ifeq ($(USE_BOB),yes)
|
||||
NEEDED_CXXFLAGS += -DWITH_BOB
|
||||
endif
|
||||
|
||||
ifneq (, $(findstring darwin, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
ifeq ($(HOMEBREW),1)
|
||||
|
||||
@@ -110,8 +110,8 @@ port = 7070
|
||||
# user = i2pd
|
||||
# pass = changeme
|
||||
## Select webconsole language
|
||||
## Currently supported english (default), afrikaans, armenian, french, german,
|
||||
## russian, turkmen, ukrainian and uzbek languages
|
||||
## Currently supported english (default), afrikaans, armenian, german, russian,
|
||||
## turkmen, ukrainian and uzbek languages
|
||||
# lang = english
|
||||
|
||||
[httpproxy]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.42.0
|
||||
Version: 2.41.0
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
@@ -164,9 +164,6 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Sun May 22 2022 orignal <orignal@i2pmail.org> - 2.42.0
|
||||
- update to 2.42.0
|
||||
|
||||
* Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
|
||||
- update to 2.41.0
|
||||
- fixed build on Fedora Copr over openssl trunk code
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: i2pd
|
||||
Version: 2.42.0
|
||||
Version: 2.41.0
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
@@ -161,9 +161,6 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Sun May 22 2022 orignal <orignal@i2pmail.org> - 2.42.0
|
||||
- update to 2.42.0
|
||||
|
||||
* Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
|
||||
- update to 2.41.0
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
#include "Streaming.h"
|
||||
#include "Destination.h"
|
||||
#include "HTTPServer.h"
|
||||
#ifdef WITH_I2PC
|
||||
#include "I2PControl.h"
|
||||
#endif
|
||||
#include "ClientContext.h"
|
||||
#include "Crypto.h"
|
||||
#include "UPnP.h"
|
||||
@@ -45,7 +47,9 @@ namespace util
|
||||
~Daemon_Singleton_Private() {};
|
||||
|
||||
std::unique_ptr<i2p::http::HTTPServer> httpServer;
|
||||
#ifdef WITH_I2PC
|
||||
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
|
||||
#endif
|
||||
std::unique_ptr<i2p::transport::UPnP> UPnP;
|
||||
std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
|
||||
};
|
||||
@@ -79,7 +83,7 @@ namespace util
|
||||
i2p::config::Init();
|
||||
i2p::config::ParseCmdline(argc, argv);
|
||||
|
||||
std::string config; i2p::config::GetOption("conf", config);
|
||||
std::string config; i2p::config::GetOption("conf", config);
|
||||
std::string datadir;
|
||||
if(DaemonDataDir != "") {
|
||||
datadir = DaemonDataDir;
|
||||
@@ -111,9 +115,9 @@ namespace util
|
||||
|
||||
certsdir = i2p::fs::GetCertsDir();
|
||||
|
||||
std::string logs = ""; i2p::config::GetOption("log", logs);
|
||||
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
|
||||
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
|
||||
std::string logs = ""; i2p::config::GetOption("log", logs);
|
||||
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
|
||||
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
|
||||
bool logclftime; i2p::config::GetOption("logclftime", logclftime);
|
||||
|
||||
/* setup logging */
|
||||
@@ -441,6 +445,7 @@ namespace util
|
||||
LogPrint(eLogInfo, "Daemon: Starting Client");
|
||||
i2p::client::context.Start ();
|
||||
|
||||
#ifdef WITH_I2PC
|
||||
// I2P Control Protocol
|
||||
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
||||
if (i2pcontrol) {
|
||||
@@ -458,6 +463,7 @@ namespace util
|
||||
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -490,12 +496,14 @@ namespace util
|
||||
d.httpServer->Stop();
|
||||
d.httpServer = nullptr;
|
||||
}
|
||||
#ifdef WITH_I2PC
|
||||
if (d.m_I2PControlService)
|
||||
{
|
||||
LogPrint(eLogInfo, "Daemon: Stopping I2PControl");
|
||||
d.m_I2PControlService->Stop ();
|
||||
d.m_I2PControlService = nullptr;
|
||||
}
|
||||
#endif
|
||||
i2p::crypto::TerminateCrypto ();
|
||||
i2p::log::Logger().Stop();
|
||||
|
||||
|
||||
@@ -68,9 +68,13 @@ namespace http {
|
||||
const char HTTP_PAGE_TRANSPORTS[] = "transports";
|
||||
const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations";
|
||||
const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination";
|
||||
#ifdef WITH_I2CP
|
||||
const char HTTP_PAGE_I2CP_LOCAL_DESTINATION[] = "i2cp_local_destination";
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions";
|
||||
const char HTTP_PAGE_SAM_SESSION[] = "sam_session";
|
||||
#endif
|
||||
const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels";
|
||||
const char HTTP_PAGE_COMMANDS[] = "commands";
|
||||
const char HTTP_PAGE_LEASESETS[] = "leasesets";
|
||||
@@ -87,7 +91,9 @@ namespace http {
|
||||
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
|
||||
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
|
||||
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
|
||||
#ifdef WITH_SAM
|
||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||
#endif
|
||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||
|
||||
static std::string ConvertTime (uint64_t time)
|
||||
@@ -202,8 +208,10 @@ namespace http {
|
||||
s <<
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr ("Transports") << "</a><br>\r\n"
|
||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">" << tr("I2P tunnels") << "</a><br>\r\n";
|
||||
#ifdef WITH_SAM
|
||||
if (i2p::client::context.GetSAMBridge ())
|
||||
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">" << tr("SAM sessions") << "</a><br>\r\n";
|
||||
#endif
|
||||
s <<
|
||||
"</div>\r\n"
|
||||
"<div class=\"content\">";
|
||||
@@ -361,17 +369,25 @@ namespace http {
|
||||
if (outputFormat==OutputFormatEnum::forWebConsole) {
|
||||
bool httpproxy = i2p::client::context.GetHttpProxy () ? true : false;
|
||||
bool socksproxy = i2p::client::context.GetSocksProxy () ? true : false;
|
||||
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
|
||||
bool sam = i2p::client::context.GetSAMBridge () ? true : false;
|
||||
bool i2cp = i2p::client::context.GetI2CPServer () ? true : false;
|
||||
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
||||
s << "<table class=\"services\"><caption>" << tr("Services") << "</caption><tbody>\r\n";
|
||||
s << "<tr><td>" << "HTTP " << tr("Proxy") << "</td><td class='" << (httpproxy ? "enabled" : "disabled") << "'>" << (httpproxy ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
s << "<tr><td>" << "SOCKS " << tr("Proxy") << "</td><td class='" << (socksproxy ? "enabled" : "disabled") << "'>" << (socksproxy ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#ifdef WITH_BOB
|
||||
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
|
||||
s << "<tr><td>" << "BOB" << "</td><td class='" << (bob ? "enabled" : "disabled") << "'>" << (bob ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
bool sam = i2p::client::context.GetSAMBridge () ? true : false;
|
||||
s << "<tr><td>" << "SAM" << "</td><td class='" << (sam ? "enabled" : "disabled") << "'>" << (sam ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
bool i2cp = i2p::client::context.GetI2CPServer () ? true : false;
|
||||
s << "<tr><td>" << "I2CP" << "</td><td class='" << (i2cp ? "enabled" : "disabled") << "'>" << (i2cp ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
#ifdef WITH_I2PC
|
||||
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
|
||||
s << "<tr><td>" << "I2PControl" << "</td><td class='" << (i2pcontrol ? "enabled" : "disabled") << "'>" << (i2pcontrol ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
|
||||
#endif
|
||||
s << "</tbody></table>\r\n";
|
||||
}
|
||||
}
|
||||
@@ -388,6 +404,7 @@ namespace http {
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
||||
if (i2cpServer && !(i2cpServer->GetSessions ().empty ()))
|
||||
{
|
||||
@@ -405,6 +422,7 @@ namespace http {
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token)
|
||||
@@ -572,6 +590,7 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
|
||||
{
|
||||
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
||||
@@ -587,6 +606,7 @@ namespace http {
|
||||
else
|
||||
ShowError(s, tr("I2CP is not enabled"));
|
||||
}
|
||||
#endif
|
||||
|
||||
void ShowLeasesSets(std::stringstream& s)
|
||||
{
|
||||
@@ -879,6 +899,7 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_SAM
|
||||
void ShowSAMSessions (std::stringstream& s)
|
||||
{
|
||||
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||
@@ -941,6 +962,7 @@ namespace http {
|
||||
}
|
||||
s << "</div>\r\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
void ShowI2PTunnels (std::stringstream& s)
|
||||
{
|
||||
@@ -1194,12 +1216,16 @@ namespace http {
|
||||
uint32_t token = CreateToken ();
|
||||
ShowLocalDestination (s, params["b32"], token);
|
||||
}
|
||||
#ifdef WITH_I2CP
|
||||
else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION)
|
||||
ShowI2CPLocalDestination (s, params["i2cp_id"]);
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
else if (page == HTTP_PAGE_SAM_SESSIONS)
|
||||
ShowSAMSessions (s);
|
||||
else if (page == HTTP_PAGE_SAM_SESSION)
|
||||
ShowSAMSession (s, params["sam_id"]);
|
||||
#endif
|
||||
else if (page == HTTP_PAGE_I2P_TUNNELS)
|
||||
ShowI2PTunnels (s);
|
||||
else if (page == HTTP_PAGE_LEASESETS)
|
||||
|
||||
@@ -95,11 +95,15 @@ namespace http
|
||||
void ShowTunnels (std::stringstream& s);
|
||||
void ShowTransitTunnels (std::stringstream& s);
|
||||
void ShowTransports (std::stringstream& s);
|
||||
void ShowSAMSessions (std::stringstream& s);
|
||||
void ShowI2PTunnels (std::stringstream& s);
|
||||
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
||||
#ifdef WITH_SAM
|
||||
void ShowSAMSessions (std::stringstream& s);
|
||||
void ShowSAMSession (std::stringstream& s, const std::string& id);
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
|
||||
#endif
|
||||
} // http
|
||||
} // i2p
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2PC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <openssl/x509.h>
|
||||
@@ -66,28 +68,28 @@ 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;
|
||||
|
||||
@@ -103,10 +105,16 @@ 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;
|
||||
#ifdef WITH_SAM
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
#endif
|
||||
}
|
||||
|
||||
I2PControlService::~I2PControlService ()
|
||||
@@ -167,7 +175,7 @@ namespace client
|
||||
Accept ();
|
||||
|
||||
if (ecode) {
|
||||
LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
|
||||
LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
|
||||
return;
|
||||
}
|
||||
LogPrint (eLogDebug, "I2PControl: New request from ", socket->lowest_layer ().remote_endpoint ());
|
||||
@@ -345,8 +353,7 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
// handlers
|
||||
|
||||
// handlers
|
||||
void I2PControlService::AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
int api = params.get<int> ("API");
|
||||
@@ -371,8 +378,7 @@ namespace client
|
||||
}
|
||||
|
||||
|
||||
// I2PControl
|
||||
|
||||
// I2PControl
|
||||
void I2PControlService::I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto& it: params)
|
||||
@@ -478,7 +484,7 @@ namespace client
|
||||
|
||||
void I2PControlService::NetTotalSentBytes (std::ostringstream& results)
|
||||
{
|
||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||
}
|
||||
|
||||
|
||||
@@ -532,7 +538,7 @@ namespace client
|
||||
i2p::data::netdb.Reseed ();
|
||||
}
|
||||
|
||||
// network setting
|
||||
// network setting
|
||||
void I2PControlService::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
@@ -612,8 +618,7 @@ namespace client
|
||||
EVP_PKEY_free (pkey);
|
||||
}
|
||||
|
||||
// ClientServicesInfo
|
||||
|
||||
// ClientServicesInfo
|
||||
void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
@@ -719,6 +724,7 @@ namespace client
|
||||
InsertParam (results, "SOCKS", pt);
|
||||
}
|
||||
|
||||
#ifdef WITH_SAM
|
||||
void I2PControlService::SAMInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
@@ -754,7 +760,9 @@ namespace client
|
||||
|
||||
InsertParam (results, "SAM", pt);
|
||||
}
|
||||
#endif // WITH_SAM
|
||||
|
||||
#ifdef WITH_BOB
|
||||
void I2PControlService::BOBInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
@@ -769,7 +777,9 @@ namespace client
|
||||
|
||||
InsertParam (results, "BOB", pt);
|
||||
}
|
||||
#endif // WITH_BOB
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
void I2PControlService::I2CPInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
@@ -784,5 +794,7 @@ namespace client
|
||||
|
||||
InsertParam (results, "I2CP", pt);
|
||||
}
|
||||
#endif // WITH_I2CP
|
||||
}
|
||||
}
|
||||
#endif // WITH_I2PC
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2PC
|
||||
|
||||
#ifndef I2P_CONTROL_H__
|
||||
#define I2P_CONTROL_H__
|
||||
|
||||
@@ -114,9 +116,15 @@ namespace client
|
||||
void I2PTunnelInfoHandler (std::ostringstream& results);
|
||||
void HTTPProxyInfoHandler (std::ostringstream& results);
|
||||
void SOCKSInfoHandler (std::ostringstream& results);
|
||||
#ifdef WITH_SAM
|
||||
void SAMInfoHandler (std::ostringstream& results);
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
void BOBInfoHandler (std::ostringstream& results);
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
void I2CPInfoHandler (std::ostringstream& results);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
@@ -141,3 +149,4 @@ namespace client
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_I2PC
|
||||
@@ -93,7 +93,7 @@ namespace transport
|
||||
#endif
|
||||
|
||||
isError = err != UPNPDISCOVER_SUCCESS;
|
||||
#else // MINIUPNPC_API_VERSION >= 8
|
||||
#else // MINIUPNPC_API_VERSION >= 8
|
||||
err = 0;
|
||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||
isError = m_Devlist == NULL;
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace transport
|
||||
private:
|
||||
|
||||
void Discover ();
|
||||
int CheckMapping (const char* port, const char* type);
|
||||
int CheckMapping (const char* port, const char* type);
|
||||
void PortMapping ();
|
||||
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
||||
void CloseMapping ();
|
||||
@@ -80,7 +80,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
#else // USE_UPNP
|
||||
#else // USE_UPNP
|
||||
namespace i2p {
|
||||
namespace transport {
|
||||
/* class stub */
|
||||
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,9 +1,3 @@
|
||||
i2pd (2.42.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.42.0/0.9.54
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Sun, 22 May 2022 16:00:00 +0000
|
||||
|
||||
i2pd (2.41.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.41.0/0.9.53
|
||||
|
||||
102
i18n/French.cpp
102
i18n/French.cpp
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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 <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "I18N.h"
|
||||
|
||||
// French localization file
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace i18n
|
||||
{
|
||||
namespace french // language namespace
|
||||
{
|
||||
// language name in lowercase
|
||||
static std::string language = "french";
|
||||
|
||||
// See for language plural forms here:
|
||||
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
||||
static int plural (int n) {
|
||||
return n != 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> strings
|
||||
{
|
||||
{"KiB", "Kio"},
|
||||
{"MiB", "Mio"},
|
||||
{"GiB", "Gio"},
|
||||
{"building", "En construction"},
|
||||
{"failed", "echoué"},
|
||||
{"expiring", "expiré"},
|
||||
{"established", "établi"},
|
||||
{"unknown", "inconnu"},
|
||||
{"exploratory", "exploratoire"},
|
||||
{"<b>i2pd</b> webconsole", "Console web <b>i2pd</b>"},
|
||||
{"Main page", "Page principale"},
|
||||
{"Router commands", "Commandes du routeur"},
|
||||
{"Local Destinations", "Destinations locales"},
|
||||
{"Tunnels", "Tunnels"},
|
||||
{"Transit Tunnels", "Tunnels transitoires"},
|
||||
{"I2P tunnels", "Tunnels I2P"},
|
||||
{"SAM sessions", "Sessions SAM"},
|
||||
{"ERROR", "ERREUR"},
|
||||
{"OK", "OK"},
|
||||
{"Firewalled", "Derrière un pare-feu"},
|
||||
{"Error", "Erreur"},
|
||||
{"Offline", "Hors ligne"},
|
||||
{"Uptime", "Temps de fonctionnement"},
|
||||
{"Network status", "État du réseau"},
|
||||
{"Network status v6", "État du réseau v6"},
|
||||
{"Stopping in", "Arrêt dans"},
|
||||
{"Family", "Famille"},
|
||||
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
|
||||
{"Received", "Reçu"},
|
||||
{"KiB/s", "kio/s"},
|
||||
{"Sent", "Envoyé"},
|
||||
{"Transit", "Transit"},
|
||||
{"Hidden content. Press on text to see.", "Contenu caché. Cliquez sur le texte pour regarder."},
|
||||
{"Router Ident", "Identifiant du routeur"},
|
||||
{"Router Family", "Famille du routeur"},
|
||||
{"Version", "Version"},
|
||||
{"Our external address", "Notre adresse externe"},
|
||||
{"Client Tunnels", "Tunnels clients"},
|
||||
{"Services", "Services"},
|
||||
{"Enabled", "Activé"},
|
||||
{"Disabled", "Désactivé"},
|
||||
{"Encrypted B33 address", "Adresse B33 chiffrée"},
|
||||
{"Domain", "Domaine"},
|
||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note:</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
|
||||
{"Address", "Adresse"},
|
||||
{"ms", "ms"},
|
||||
{"Outbound tunnels", "Tunnels sortants"},
|
||||
{"Destination", "Destination"},
|
||||
{"Local Destination", "Destination locale"},
|
||||
{"", ""},
|
||||
};
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> plurals
|
||||
{
|
||||
{"days", {"jour", "jours"}},
|
||||
{"hours", {"heure", "heures"}},
|
||||
{"minutes", {"minute", "minutes"}},
|
||||
{"seconds", {"seconde", "secondes"}},
|
||||
{"", {"", ""}},
|
||||
};
|
||||
|
||||
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
|
||||
{
|
||||
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
|
||||
}
|
||||
|
||||
} // language
|
||||
} // i18n
|
||||
} // i2p
|
||||
@@ -74,7 +74,6 @@ namespace i18n
|
||||
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||
@@ -89,7 +88,6 @@ namespace i18n
|
||||
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
|
||||
{ "armenian", {"հայերէն", "hy", i2p::i18n::armenian::GetLocale} },
|
||||
{ "english", {"English", "en", i2p::i18n::english::GetLocale} },
|
||||
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
|
||||
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
|
||||
{ "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} },
|
||||
{ "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
|
||||
|
||||
@@ -24,8 +24,8 @@ namespace data {
|
||||
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
|
||||
|
||||
/**
|
||||
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
||||
*/
|
||||
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
||||
*/
|
||||
size_t Base64EncodingBufferSize(const size_t input_size);
|
||||
|
||||
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace data
|
||||
static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args)
|
||||
// blind is BlindEncodedPublicKeyECDSA or BlindEncodedPrivateKeyECDSA
|
||||
{
|
||||
size_t publicKeyLength = 0;
|
||||
size_t publicKeyLength = 0;
|
||||
EC_GROUP * group = nullptr;
|
||||
switch (sigType)
|
||||
{
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace data
|
||||
|
||||
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
|
||||
size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
|
||||
SigningKeyType GetSigType () const { return m_SigType; };
|
||||
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
|
||||
SigningKeyType GetSigType () const { return m_SigType; };
|
||||
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
|
||||
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
|
||||
|
||||
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes
|
||||
|
||||
@@ -29,16 +29,16 @@ namespace config {
|
||||
extern boost::program_options::variables_map m_Options;
|
||||
|
||||
/**
|
||||
* @brief Initialize list of acceptable parameters
|
||||
* @brief Initialize list of acceptable parameters
|
||||
*
|
||||
* Should be called before any Parse* functions.
|
||||
*/
|
||||
void Init();
|
||||
|
||||
/**
|
||||
* @brief Parse cmdline parameters, and show help if requested
|
||||
* @param argc Cmdline arguments count, should be passed from main().
|
||||
* @param argv Cmdline parameters array, should be passed from main()
|
||||
* @brief Parse cmdline parameters, and show help if requested
|
||||
* @param argc Cmdline arguments count, should be passed from main().
|
||||
* @param argv Cmdline parameters array, should be passed from main()
|
||||
*
|
||||
* If --help is given in parameters, shows its list with description
|
||||
* and terminates the program with exitcode 0.
|
||||
@@ -52,8 +52,8 @@ namespace config {
|
||||
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
|
||||
|
||||
/**
|
||||
* @brief Load and parse given config file
|
||||
* @param path Path to config file
|
||||
* @brief Load and parse given config file
|
||||
* @param path Path to config file
|
||||
*
|
||||
* If error occurred when opening file path is points to,
|
||||
* we show the error message and terminate program.
|
||||
@@ -67,14 +67,14 @@ namespace config {
|
||||
void ParseConfig(const std::string& path);
|
||||
|
||||
/**
|
||||
* @brief Used to combine options from cmdline, config and default values
|
||||
* @brief Used to combine options from cmdline, config and default values
|
||||
*/
|
||||
void Finalize();
|
||||
|
||||
/**
|
||||
* @brief Accessor to parameters by name
|
||||
* @param name Name of the requested parameter
|
||||
* @param value Variable where to store option
|
||||
* @brief Accessor to parameters by name
|
||||
* @param name Name of the requested parameter
|
||||
* @param value Variable where to store option
|
||||
* @return this function returns false if parameter not found
|
||||
*
|
||||
* Example: uint16_t port; GetOption("sam.port", port);
|
||||
@@ -98,9 +98,9 @@ namespace config {
|
||||
bool GetOptionAsAny(const std::string& name, boost::any& value);
|
||||
|
||||
/**
|
||||
* @brief Set value of given parameter
|
||||
* @param name Name of settable parameter
|
||||
* @param value New parameter value
|
||||
* @brief Set value of given parameter
|
||||
* @param name Name of settable parameter
|
||||
* @param value New parameter value
|
||||
* @return true if value set up successful, false otherwise
|
||||
*
|
||||
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
||||
@@ -116,8 +116,8 @@ namespace config {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check is value explicitly given or default
|
||||
* @param name Name of checked parameter
|
||||
* @brief Check is value explicitly given or default
|
||||
* @param name Name of checked parameter
|
||||
* @return true if value set to default, false otherwise
|
||||
*/
|
||||
bool IsDefault(const char *name);
|
||||
|
||||
@@ -1330,7 +1330,7 @@ namespace crypto
|
||||
SHA256_Init (&ctx);
|
||||
SHA256_Update (&ctx, hh, 32);
|
||||
SHA256_Update (&ctx, pub, 32);
|
||||
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
|
||||
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
|
||||
}
|
||||
|
||||
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
|
||||
|
||||
@@ -29,25 +29,23 @@
|
||||
#include "CPU.h"
|
||||
|
||||
// recognize openssl version and features
|
||||
#if (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x3050200fL)) // LibreSSL 3.5.2 and above
|
||||
# define LEGACY_OPENSSL 0
|
||||
#elif ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
|
||||
# define LEGACY_OPENSSL 1
|
||||
# define X509_getm_notBefore X509_get_notBefore
|
||||
# define X509_getm_notAfter X509_get_notAfter
|
||||
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
|
||||
# define LEGACY_OPENSSL 1
|
||||
# define X509_getm_notBefore X509_get_notBefore
|
||||
# define X509_getm_notAfter X509_get_notAfter
|
||||
#else
|
||||
# define LEGACY_OPENSSL 0
|
||||
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||
# define OPENSSL_HKDF 1
|
||||
# define OPENSSL_EDDSA 1
|
||||
# define OPENSSL_X25519 1
|
||||
# if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash
|
||||
# define OPENSSL_SIPHASH 1
|
||||
# define LEGACY_OPENSSL 0
|
||||
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||
# define OPENSSL_HKDF 1
|
||||
# define OPENSSL_EDDSA 1
|
||||
# define OPENSSL_X25519 1
|
||||
# if (OPENSSL_VERSION_NUMBER < 0x030000000) // 3.0.0, regression in SipHash
|
||||
# define OPENSSL_SIPHASH 1
|
||||
# endif
|
||||
# endif
|
||||
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
|
||||
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
|
||||
# endif
|
||||
# endif
|
||||
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
|
||||
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace i2p
|
||||
@@ -385,7 +383,7 @@ inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||
if (dh->p) BN_free (dh->p);
|
||||
if (dh->q) BN_free (dh->q);
|
||||
if (dh->g) BN_free (dh->g);
|
||||
dh->p = p; dh->q = q; dh->g = g; return 1;
|
||||
dh->p = p; dh->q = q; dh->g = g; return 1;
|
||||
}
|
||||
inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
||||
{
|
||||
|
||||
@@ -324,7 +324,7 @@ namespace datagram
|
||||
|
||||
auto path = m_RoutingSession->GetSharedRoutingPath();
|
||||
if (path && m_RoutingSession->IsRatchets () &&
|
||||
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT)
|
||||
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT)
|
||||
{
|
||||
m_RoutingSession->SetSharedRoutingPath (nullptr);
|
||||
path = nullptr;
|
||||
|
||||
@@ -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"
|
||||
@@ -93,7 +94,9 @@ namespace client
|
||||
if (it != params->end ())
|
||||
{
|
||||
// oveeride isPublic
|
||||
m_IsPublic = (it->second != "true");
|
||||
bool dontpublish = false;
|
||||
i2p::config::GetOption (it->second, dontpublish);
|
||||
m_IsPublic = !dontpublish;
|
||||
}
|
||||
it = params->find (I2CP_PARAM_LEASESET_TYPE);
|
||||
if (it != params->end ())
|
||||
@@ -417,7 +420,7 @@ namespace client
|
||||
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
||||
auto it = m_RemoteLeaseSets.find (key);
|
||||
if (it != m_RemoteLeaseSets.end () &&
|
||||
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
|
||||
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
|
||||
{
|
||||
leaseSet = it->second;
|
||||
if (leaseSet->IsNewer (buf + offset, len - offset))
|
||||
@@ -951,7 +954,7 @@ namespace client
|
||||
for (auto& it: encryptionKeyTypes)
|
||||
{
|
||||
auto encryptionKey = new EncryptionKey (it);
|
||||
if (IsPublic ())
|
||||
if (isPublic)
|
||||
PersistTemporaryKeys (encryptionKey, isSingleKey);
|
||||
else
|
||||
encryptionKey->GenerateKeys ();
|
||||
@@ -966,7 +969,7 @@ namespace client
|
||||
m_StandardEncryptionKey.reset (encryptionKey);
|
||||
}
|
||||
|
||||
if (IsPublic ())
|
||||
if (isPublic)
|
||||
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
||||
|
||||
try
|
||||
@@ -979,7 +982,7 @@ namespace client
|
||||
m_StreamingAckDelay = std::stoi(it->second);
|
||||
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
|
||||
if (it != params->end ())
|
||||
m_IsStreamingAnswerPings = (it->second == "true");
|
||||
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
|
||||
|
||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||
{
|
||||
|
||||
@@ -319,5 +319,4 @@ namespace client
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace garlic
|
||||
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
|
||||
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
|
||||
SessionState m_State = eSessionStateNew;
|
||||
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
|
||||
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
|
||||
m_LastSentTimestamp = 0; // in milliseconds
|
||||
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRSendTagset;
|
||||
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
||||
@@ -229,7 +229,7 @@ namespace garlic
|
||||
{
|
||||
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// single session for all incoming messages
|
||||
class RouterIncomingRatchetSession: public ECIESX25519AEADRatchetSession
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace crypto
|
||||
BN_add (l, l, tmp);
|
||||
BN_sub_word (two_252_2, 2); // 2^252 - 2
|
||||
|
||||
// -121665*inv(121666)
|
||||
// -121665*inv(121666)
|
||||
d = BN_new ();
|
||||
BN_set_word (tmp, 121666);
|
||||
BN_mod_inverse (tmp, tmp, q, ctx);
|
||||
@@ -61,7 +61,7 @@ namespace crypto
|
||||
BN_mod (By, By, q, ctx); // % q
|
||||
|
||||
// precalculate Bi256 table
|
||||
Bi256Carry = { Bx, By }; // B
|
||||
Bi256Carry = { Bx, By }; // B
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
Bi256[i][0] = Bi256Carry; // first point
|
||||
@@ -215,7 +215,7 @@ namespace crypto
|
||||
if (!t1) { t1 = BN_CTX_get (ctx); BN_mul (t1, p1.x, p1.y, ctx); }
|
||||
if (!t2) { t2 = BN_CTX_get (ctx); BN_mul (t2, p2.x, p2.y, ctx); }
|
||||
BN_mul (t3, t1, t2, ctx);
|
||||
BN_mul (t3, t3, d, ctx); // C = d*t1*t2
|
||||
BN_mul (t3, t3, d, ctx); // C = d*t1*t2
|
||||
|
||||
if (p1.z)
|
||||
{
|
||||
@@ -264,9 +264,9 @@ namespace crypto
|
||||
else
|
||||
{
|
||||
BN_mul (t2, p.x, p.y, ctx); // t = x*y
|
||||
BN_sqr (t2, t2, ctx); // t2 = t^2
|
||||
BN_sqr (t2, t2, ctx); // t2 = t^2
|
||||
}
|
||||
BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2
|
||||
BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2
|
||||
if (p.z)
|
||||
BN_sqr (z2, p.z, ctx); // z2 = D = z^2
|
||||
else
|
||||
@@ -349,7 +349,7 @@ namespace crypto
|
||||
BN_mod_inverse (y, p.z, q, ctx);
|
||||
BN_mod_mul (x, p.x, y, q, ctx); // x = x/z
|
||||
BN_mod_mul (y, p.y, y, q, ctx); // y = y/z
|
||||
return EDDSAPoint{x, y};
|
||||
return EDDSAPoint{x, y};
|
||||
}
|
||||
else
|
||||
return EDDSAPoint{BN_dup (p.x), BN_dup (p.y)};
|
||||
@@ -506,13 +506,13 @@ namespace crypto
|
||||
std::swap (z2, z3);
|
||||
}
|
||||
BN_mod_inverse (z2, z2, q, ctx);
|
||||
BIGNUM * res = BN_new (); // not from ctx
|
||||
BIGNUM * res = BN_new (); // not from ctx
|
||||
BN_mod_mul(res, x2, z2, q, ctx);
|
||||
BN_CTX_end (ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
|
||||
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
|
||||
{
|
||||
BIGNUM * p1 = DecodeBN<32> (p);
|
||||
uint8_t k[32];
|
||||
@@ -524,7 +524,7 @@ namespace crypto
|
||||
BN_free (p1); BN_free (n); BN_free (q1);
|
||||
}
|
||||
|
||||
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
|
||||
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
|
||||
{
|
||||
BIGNUM *p1 = BN_new (); BN_set_word (p1, 9);
|
||||
uint8_t k[32];
|
||||
|
||||
@@ -85,8 +85,8 @@ namespace crypto
|
||||
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
|
||||
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
|
||||
#if !OPENSSL_X25519
|
||||
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
|
||||
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
|
||||
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
|
||||
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
|
||||
#endif
|
||||
void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
|
||||
void BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace crypto
|
||||
// assume a < p, so don't check for a % p = 0, but a = 0 only
|
||||
if (BN_is_zero(a)) return 0;
|
||||
BIGNUM * r = BN_CTX_get (ctx);
|
||||
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
|
||||
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
|
||||
if (BN_is_word(r, 1))
|
||||
return 1;
|
||||
else if (BN_is_zero(r))
|
||||
|
||||
12
libi2pd/FS.h
12
libi2pd/FS.h
@@ -83,8 +83,8 @@ namespace fs {
|
||||
|
||||
/**
|
||||
* @brief Set datadir either from cmdline option or using autodetection
|
||||
* @param cmdline_param Value of cmdline parameter --datadir=<something>
|
||||
* @param isService Value of cmdline parameter --service
|
||||
* @param cmdline_param Value of cmdline parameter --datadir=<something>
|
||||
* @param isService Value of cmdline parameter --service
|
||||
*
|
||||
* Examples of autodetected paths:
|
||||
*
|
||||
@@ -93,11 +93,11 @@ namespace fs {
|
||||
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
|
||||
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
|
||||
*/
|
||||
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
|
||||
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
|
||||
|
||||
/**
|
||||
* @brief Set certsdir either from cmdline option or using autodetection
|
||||
* @param cmdline_param Value of cmdline parameter --certsdir=<something>
|
||||
* @param cmdline_param Value of cmdline parameter --certsdir=<something>
|
||||
*
|
||||
* Examples of autodetected paths:
|
||||
*
|
||||
@@ -106,7 +106,7 @@ namespace fs {
|
||||
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/certificates
|
||||
* Unix: /var/lib/i2pd/certificates (system=1) >> ~/.i2pd/ or /tmp/i2pd/certificates
|
||||
*/
|
||||
void SetCertsDir(const std::string & cmdline_certsdir);
|
||||
void SetCertsDir(const std::string & cmdline_certsdir);
|
||||
|
||||
/**
|
||||
* @brief Create subdirectories inside datadir
|
||||
@@ -115,7 +115,7 @@ namespace fs {
|
||||
|
||||
/**
|
||||
* @brief Get list of files in directory
|
||||
* @param path Path to directory
|
||||
* @param path Path to directory
|
||||
* @param files Vector to store found files
|
||||
* @return true on success and false if directory not exists
|
||||
*/
|
||||
|
||||
@@ -293,14 +293,14 @@ namespace garlic
|
||||
size_t size = 0;
|
||||
if (isDestination)
|
||||
{
|
||||
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
|
||||
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
|
||||
size++;
|
||||
memcpy (buf + size, m_Destination->GetIdentHash (), 32);
|
||||
size += 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[size] = 0;// delivery instructions flag local
|
||||
buf[size] = 0;// delivery instructions flag local
|
||||
size++;
|
||||
}
|
||||
|
||||
@@ -744,7 +744,7 @@ namespace garlic
|
||||
LogPrint (eLogError, "Garlic: Message is too short");
|
||||
break;
|
||||
}
|
||||
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
|
||||
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
|
||||
buf += 4; // CloveID
|
||||
buf += 8; // Date
|
||||
buf += 3; // Certificate
|
||||
@@ -1024,7 +1024,7 @@ namespace garlic
|
||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
for (auto it: files)
|
||||
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||
i2p::fs::Remove (it);
|
||||
i2p::fs::Remove (it);
|
||||
}
|
||||
|
||||
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace crypto
|
||||
EC_POINT * C = EC_POINT_new (m_Group);
|
||||
EC_POINT_mul (m_Group, C, z1, pub, z2, ctx); // z1*P + z2*pub
|
||||
BIGNUM * x = BN_CTX_get (ctx);
|
||||
GetXY (C, x, nullptr); // Cx
|
||||
GetXY (C, x, nullptr); // Cx
|
||||
BN_mod (x, x, q, ctx); // Cx % q
|
||||
bool ret = !BN_cmp (x, r); // Cx = r ?
|
||||
EC_POINT_free (C);
|
||||
@@ -111,8 +111,8 @@ namespace crypto
|
||||
BN_CTX * ctx = BN_CTX_new ();
|
||||
BN_CTX_start (ctx);
|
||||
EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry)
|
||||
EC_POINT * Q = nullptr;
|
||||
if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx))
|
||||
EC_POINT * Q = nullptr;
|
||||
if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx))
|
||||
{
|
||||
EC_POINT * S = EC_POINT_new (m_Group); // S = s*P
|
||||
EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx);
|
||||
|
||||
@@ -279,7 +279,7 @@ namespace http
|
||||
method = tokens[0];
|
||||
uri = tokens[1];
|
||||
version = tokens[2];
|
||||
expect = HEADER_LINE;
|
||||
expect = HEADER_LINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -363,7 +363,7 @@ namespace http
|
||||
return false; /* no header */
|
||||
if (it->second.find("gzip") != std::string::npos)
|
||||
return true; /* gotcha! */
|
||||
if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos)
|
||||
if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -409,7 +409,7 @@ namespace http
|
||||
/* all ok */
|
||||
version = tokens[0];
|
||||
status = tokens[2];
|
||||
expect = HEADER_LINE;
|
||||
expect = HEADER_LINE;
|
||||
} else {
|
||||
std::string line = str.substr(pos, eol - pos);
|
||||
auto p = parse_header_line(line);
|
||||
@@ -460,7 +460,7 @@ namespace http
|
||||
case 304: ptr = "Not Modified"; break;
|
||||
case 307: ptr = "Temporary Redirect"; break;
|
||||
/* client error */
|
||||
case 400: ptr = "Bad Request"; break;
|
||||
case 400: ptr = "Bad Request"; break;
|
||||
case 401: ptr = "Unauthorized"; break;
|
||||
case 403: ptr = "Forbidden"; break;
|
||||
case 404: ptr = "Not Found"; break;
|
||||
@@ -471,7 +471,7 @@ namespace http
|
||||
case 502: ptr = "Bad Gateway"; break;
|
||||
case 503: ptr = "Not Implemented"; break;
|
||||
case 504: ptr = "Gateway Timeout"; break;
|
||||
default: ptr = "Unknown Status"; break;
|
||||
default: ptr = "Unknown Status"; break;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace http
|
||||
|
||||
/**
|
||||
* @brief Merge HTTP response content with Transfer-Encoding: chunked
|
||||
* @param in Input stream
|
||||
* @param in Input stream
|
||||
* @param out Output stream
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
|
||||
@@ -171,7 +171,7 @@ 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, bool replyECIES)
|
||||
const uint8_t * replyTag, bool replyECIES)
|
||||
{
|
||||
int cnt = excludedFloodfills.size ();
|
||||
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
||||
@@ -244,7 +244,7 @@ namespace i2p
|
||||
}
|
||||
|
||||
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router,
|
||||
uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
|
||||
uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
|
||||
{
|
||||
if (!router) // we send own RouterInfo
|
||||
router = context.GetSharedRouterInfo ();
|
||||
@@ -629,7 +629,7 @@ namespace i2p
|
||||
// we send it to reply tunnel
|
||||
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
|
||||
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace tunnel
|
||||
std::shared_ptr<i2p::tunnel::InboundTunnel> from;
|
||||
|
||||
I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2),
|
||||
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
|
||||
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
|
||||
|
||||
// header accessors
|
||||
uint8_t * GetHeader () { return GetBuffer (); };
|
||||
@@ -274,8 +274,8 @@ namespace tunnel
|
||||
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, bool replyECIES = false);
|
||||
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, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel = nullptr);
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace data
|
||||
{
|
||||
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
|
||||
{
|
||||
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
|
||||
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
|
||||
RAND_bytes (m_StandardIdentity.signingKey, padding);
|
||||
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH);
|
||||
break;
|
||||
@@ -788,7 +788,7 @@ namespace data
|
||||
keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6);
|
||||
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
|
||||
htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
|
||||
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
|
||||
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
|
||||
Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
|
||||
// recreate signer
|
||||
keys.m_Signer = nullptr;
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace data
|
||||
CryptoKeyType GetCryptoKeyType () const;
|
||||
void DropVerifier () const; // to save memory
|
||||
|
||||
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
|
||||
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
|
||||
void RecalculateIdentHash(uint8_t * buff=nullptr);
|
||||
|
||||
static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType);
|
||||
@@ -222,7 +222,7 @@ namespace data
|
||||
RoutingDestination () {};
|
||||
virtual ~RoutingDestination () {};
|
||||
|
||||
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
|
||||
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
|
||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted) const = 0; // encrypt data for
|
||||
virtual bool IsDestination () const = 0; // for garlic
|
||||
|
||||
|
||||
@@ -582,7 +582,7 @@ namespace data
|
||||
// helper for ExtractClientAuthData
|
||||
static inline bool GetAuthCookie (const uint8_t * authClients, int numClients, const uint8_t * okm, uint8_t * authCookie)
|
||||
{
|
||||
// try to find clientCookie_i for clientID_i = okm[44:51]
|
||||
// try to find clientCookie_i for clientID_i = okm[44:51]
|
||||
for (int i = 0; i < numClients; i++)
|
||||
{
|
||||
if (!memcmp (okm + 44, authClients + i*40, 8)) // clientID_i
|
||||
@@ -606,7 +606,7 @@ namespace data
|
||||
{
|
||||
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
|
||||
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
||||
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
||||
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
||||
if (offset > len)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data");
|
||||
@@ -632,7 +632,7 @@ namespace data
|
||||
{
|
||||
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
|
||||
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
||||
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
||||
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
||||
if (offset > len)
|
||||
{
|
||||
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data");
|
||||
@@ -737,7 +737,7 @@ namespace data
|
||||
htobe64buf (m_Buffer + offset, ts);
|
||||
offset += 8; // end date
|
||||
}
|
||||
// we don't sign it yet. must be signed later on
|
||||
// we don't sign it yet. must be signed later on
|
||||
}
|
||||
|
||||
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len):
|
||||
@@ -995,7 +995,7 @@ namespace data
|
||||
ek.GenerateKeys (); // esk and epk
|
||||
memcpy (authData, ek.GetPublicKey (), 32); authData += 32; // epk
|
||||
htobe16buf (authData, authKeys->size ()); authData += 2; // num clients
|
||||
uint8_t authInput[100]; // sharedSecret || cpk_i || subcredential || publishedTimestamp
|
||||
uint8_t authInput[100]; // sharedSecret || cpk_i || subcredential || publishedTimestamp
|
||||
memcpy (authInput + 64, subcredential, 36);
|
||||
for (auto& it: *authKeys)
|
||||
{
|
||||
|
||||
@@ -128,8 +128,8 @@ namespace data
|
||||
};
|
||||
|
||||
/**
|
||||
* validate lease set buffer signature and extract expiration timestamp
|
||||
* @returns true if the leaseset is well formed and signature is valid
|
||||
validate lease set buffer signature and extract expiration timestamp
|
||||
@returns true if the leaseset is well formed and signature is valid
|
||||
*/
|
||||
bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace log {
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* @brief Maps our log levels to syslog one
|
||||
* @brief Maps our log levels to syslog one
|
||||
* @return syslog priority LOG_*, as defined in syslog.h
|
||||
*/
|
||||
static inline int GetSyslogPrio (enum LogLevel l) {
|
||||
@@ -113,11 +113,11 @@ namespace log {
|
||||
|
||||
std::string str_tolower(std::string s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(),
|
||||
// static_cast<int(*)(int)>(std::tolower) // wrong
|
||||
// [](int c){ return std::tolower(c); } // wrong
|
||||
// [](char c){ return std::tolower(c); } // wrong
|
||||
[](unsigned char c){ return std::tolower(c); } // correct
|
||||
);
|
||||
// static_cast<int(*)(int)>(std::tolower) // wrong
|
||||
// [](int c){ return std::tolower(c); } // wrong
|
||||
// [](char c){ return std::tolower(c); } // wrong
|
||||
[](unsigned char c){ return std::tolower(c); } // correct
|
||||
);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace log {
|
||||
break;
|
||||
case eLogStdout:
|
||||
default:
|
||||
std::cout << TimeAsString(msg->timestamp)
|
||||
std::cout << TimeAsString(msg->timestamp)
|
||||
<< "@" << short_tid
|
||||
<< "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels]
|
||||
<< " - " << msg->text << std::endl;
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace log {
|
||||
{
|
||||
private:
|
||||
|
||||
enum LogType m_Destination;
|
||||
enum LogType m_Destination;
|
||||
enum LogLevel m_MinLevel;
|
||||
std::shared_ptr<std::ostream> m_LogStream;
|
||||
std::string m_Logfile;
|
||||
@@ -75,7 +75,7 @@ namespace log {
|
||||
|
||||
/**
|
||||
* @brief Makes formatted string from unix timestamp
|
||||
* @param ts Second since epoch
|
||||
* @param ts Second since epoch
|
||||
*
|
||||
* This function internally caches the result for last provided value
|
||||
*/
|
||||
@@ -86,52 +86,52 @@ namespace log {
|
||||
Log ();
|
||||
~Log ();
|
||||
|
||||
LogType GetLogType () { return m_Destination; };
|
||||
LogType GetLogType () { return m_Destination; };
|
||||
LogLevel GetLogLevel () { return m_MinLevel; };
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
/**
|
||||
* @brief Sets minimal allowed level for log messages
|
||||
* @param level String with wanted minimal msg level
|
||||
* @brief Sets minimal allowed level for log messages
|
||||
* @param level String with wanted minimal msg level
|
||||
*/
|
||||
void SetLogLevel (const std::string& level);
|
||||
void SetLogLevel (const std::string& level);
|
||||
|
||||
/**
|
||||
* @brief Sets log destination to logfile
|
||||
* @param path Path to logfile
|
||||
* @param path Path to logfile
|
||||
*/
|
||||
void SendTo (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Sets log destination to given output stream
|
||||
* @param os Output stream
|
||||
* @param os Output stream
|
||||
*/
|
||||
void SendTo (std::shared_ptr<std::ostream> os);
|
||||
|
||||
/**
|
||||
* @brief Sets format for timestamps in log
|
||||
* @param format String with timestamp format
|
||||
* @brief Sets format for timestamps in log
|
||||
* @param format String with timestamp format
|
||||
*/
|
||||
void SetTimeFormat (std::string format) { m_TimeFormat = format; };
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* @brief Sets log destination to syslog
|
||||
* @param name Wanted program name
|
||||
* @param name Wanted program name
|
||||
* @param facility Wanted log category
|
||||
*/
|
||||
void SendTo (const char *name, int facility);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Format log message and write to output stream/syslog
|
||||
* @param msg Pointer to processed message
|
||||
* @brief Format log message and write to output stream/syslog
|
||||
* @param msg Pointer to processed message
|
||||
*/
|
||||
void Append(std::shared_ptr<i2p::log::LogMsg> &);
|
||||
|
||||
/** @brief Reopen log file */
|
||||
/** @brief Reopen log file */
|
||||
void Reopen();
|
||||
};
|
||||
|
||||
@@ -144,8 +144,8 @@ namespace log {
|
||||
*/
|
||||
struct LogMsg {
|
||||
std::time_t timestamp;
|
||||
std::string text; /**< message text as single string */
|
||||
LogLevel level; /**< message level */
|
||||
std::string text; /**< message text as single string */
|
||||
LogLevel level; /**< message level */
|
||||
std::thread::id tid; /**< id of thread that generated message */
|
||||
|
||||
LogMsg (LogLevel lvl, std::time_t ts, std::string&& txt): timestamp(ts), text(std::move(txt)), level(lvl) {}
|
||||
@@ -153,7 +153,7 @@ namespace log {
|
||||
|
||||
Log & Logger();
|
||||
|
||||
typedef std::function<void (const std::string&)> ThrowFunction;
|
||||
typedef std::function<void (const std::string&)> ThrowFunction;
|
||||
ThrowFunction GetThrowFunction ();
|
||||
void SetThrowFunction (ThrowFunction f);
|
||||
} // log
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace transport
|
||||
{
|
||||
MixHash (sessionRequest + 32, 32); // encrypted payload
|
||||
|
||||
int paddingLength = sessionRequestLen - 64;
|
||||
int paddingLength = sessionRequestLen - 64;
|
||||
if (paddingLength > 0)
|
||||
MixHash (sessionRequest + 64, paddingLength);
|
||||
MixHash (epub, 32);
|
||||
@@ -130,7 +130,7 @@ namespace transport
|
||||
// m3p2Len
|
||||
auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen ();
|
||||
m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options
|
||||
htobe16buf (options + 4, m3p2Len);
|
||||
htobe16buf (options + 4, m3p2Len);
|
||||
// fill m3p2 payload (RouterInfo block)
|
||||
m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes
|
||||
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
|
||||
@@ -320,7 +320,7 @@ namespace transport
|
||||
}
|
||||
|
||||
NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter,
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> addr):
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> addr):
|
||||
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
|
||||
m_Server (server), m_Socket (m_Server.GetService ()),
|
||||
m_IsEstablished (false), m_IsTerminated (false),
|
||||
@@ -418,7 +418,7 @@ namespace transport
|
||||
void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts)
|
||||
{
|
||||
if (m_NextReceivedBuffer && !m_IsReceiving &&
|
||||
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
|
||||
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
|
||||
{
|
||||
delete[] m_NextReceivedBuffer;
|
||||
m_NextReceivedBuffer = nullptr;
|
||||
@@ -496,7 +496,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
@@ -549,7 +549,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
|
||||
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
@@ -1126,11 +1126,11 @@ namespace transport
|
||||
{
|
||||
if (!m_SendKey ||
|
||||
#if OPENSSL_SIPHASH
|
||||
!m_SendMDCtx
|
||||
!m_SendMDCtx
|
||||
#else
|
||||
!m_SendSipKey
|
||||
!m_SendSipKey
|
||||
#endif
|
||||
) return;
|
||||
) return;
|
||||
m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block
|
||||
// termination block
|
||||
m_NextSendBuffer[2] = eNTCP2BlkTermination;
|
||||
@@ -1164,7 +1164,7 @@ namespace transport
|
||||
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: Outgoing messages queue size to ",
|
||||
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
|
||||
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
@@ -1177,7 +1177,7 @@ namespace transport
|
||||
|
||||
NTCP2Server::NTCP2Server ():
|
||||
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
|
||||
m_ProxyType(eNoProxy), m_Resolver(GetService ())
|
||||
m_ProxyType(eNoProxy), m_Resolver(GetService ())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -107,10 +107,7 @@ namespace data
|
||||
{
|
||||
i2p::util::SetThreadName("NetDB");
|
||||
|
||||
uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
||||
uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch ();
|
||||
int16_t profilesCleanupVariance = 0;
|
||||
|
||||
uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
||||
while (m_IsRunning)
|
||||
{
|
||||
try
|
||||
@@ -158,7 +155,6 @@ namespace data
|
||||
m_Requests.ManageRequests ();
|
||||
lastManageRequest = ts;
|
||||
}
|
||||
|
||||
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
|
||||
{
|
||||
if (lastSave)
|
||||
@@ -168,20 +164,12 @@ namespace data
|
||||
}
|
||||
lastSave = ts;
|
||||
}
|
||||
|
||||
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
i2p::context.CleanupDestination ();
|
||||
lastDestinationCleanup = ts;
|
||||
}
|
||||
|
||||
if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance))
|
||||
{
|
||||
DeleteObsoleteProfiles ();
|
||||
lastProfilesCleanup = ts;
|
||||
profilesCleanupVariance = (rand () % (2 * i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE) - i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE);
|
||||
}
|
||||
|
||||
// publish
|
||||
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
|
||||
{
|
||||
@@ -207,7 +195,6 @@ namespace data
|
||||
lastPublish = ts;
|
||||
}
|
||||
}
|
||||
|
||||
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
|
||||
{
|
||||
auto numRouters = m_RouterInfos.size ();
|
||||
@@ -489,7 +476,7 @@ namespace data
|
||||
{
|
||||
auto r = std::make_shared<RouterInfo>(path);
|
||||
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () &&
|
||||
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
|
||||
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
|
||||
{
|
||||
r->DeleteBuffer ();
|
||||
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
|
||||
@@ -620,7 +607,7 @@ namespace data
|
||||
}
|
||||
// make router reachable back if too few routers or floodfills
|
||||
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS ||
|
||||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
|
||||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
|
||||
it.second->SetUnreachable (false);
|
||||
// find & mark expired routers
|
||||
if (!it.second->IsReachable () && it.second->IsSSU (false))
|
||||
@@ -688,7 +675,7 @@ namespace data
|
||||
if (floodfill)
|
||||
{
|
||||
if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) &&
|
||||
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
|
||||
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
|
||||
direct = false; // floodfill can't be reached directly
|
||||
if (direct)
|
||||
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||
@@ -971,7 +958,7 @@ namespace data
|
||||
else
|
||||
{
|
||||
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
|
||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
|
||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
|
||||
{
|
||||
auto router = FindRouter (ident);
|
||||
if (router)
|
||||
@@ -1136,7 +1123,7 @@ namespace data
|
||||
m_PublishExcluded.insert (floodfill->GetIdentHash ());
|
||||
m_PublishReplyToken = replyToken;
|
||||
if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect?
|
||||
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
|
||||
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
|
||||
// send directly
|
||||
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
|
||||
else
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace data
|
||||
void Start ();
|
||||
void Stop ();
|
||||
|
||||
std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||
std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||
void RequestComplete (const IdentHash& ident, std::shared_ptr<RouterInfo> r);
|
||||
std::shared_ptr<RequestedDestination> FindRequest (const IdentHash& ident) const;
|
||||
void ManageRequests ();
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/**
|
||||
* This code is licensed under the MCGSI Public License
|
||||
* Copyright 2018 Jeff Becker
|
||||
*
|
||||
*Kovri go write your own code
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Poly1305.h"
|
||||
/**
|
||||
This code is licensed under the MCGSI Public License
|
||||
Copyright 2018 Jeff Becker
|
||||
|
||||
Kovri go write your own code
|
||||
|
||||
*/
|
||||
|
||||
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
||||
namespace i2p
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* Kovri go write your own code
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIBI2PD_POLY1305_H
|
||||
#define LIBI2PD_POLY1305_H
|
||||
#include <cstdint>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -29,8 +29,6 @@ namespace data
|
||||
const char PEER_PROFILE_USAGE_REJECTED[] = "rejected";
|
||||
|
||||
const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days)
|
||||
const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 24 * 3600; // in seconds (1 day)
|
||||
const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3 * 3600; // in seconds (3 hours)
|
||||
|
||||
class RouterProfile
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace util
|
||||
|
||||
void Put (Element e)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
m_Queue.push (std::move(e));
|
||||
m_NonEmpty.notify_one ();
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace util
|
||||
{
|
||||
if (!vec.empty ())
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
std::unique_lock<std::mutex> l(m_QueueMutex);
|
||||
for (const auto& it: vec)
|
||||
m_Queue.push (std::move(it));
|
||||
m_NonEmpty.notify_one ();
|
||||
|
||||
@@ -187,31 +187,31 @@ namespace data
|
||||
}
|
||||
s.seekg (1, std::ios::cur); // su3 file format version
|
||||
SigningKeyType signatureType;
|
||||
s.read ((char *)&signatureType, 2); // signature type
|
||||
s.read ((char *)&signatureType, 2); // signature type
|
||||
signatureType = be16toh (signatureType);
|
||||
uint16_t signatureLength;
|
||||
s.read ((char *)&signatureLength, 2); // signature length
|
||||
s.read ((char *)&signatureLength, 2); // signature length
|
||||
signatureLength = be16toh (signatureLength);
|
||||
s.seekg (1, std::ios::cur); // unused
|
||||
uint8_t versionLength;
|
||||
s.read ((char *)&versionLength, 1); // version length
|
||||
s.read ((char *)&versionLength, 1); // version length
|
||||
s.seekg (1, std::ios::cur); // unused
|
||||
uint8_t signerIDLength;
|
||||
s.read ((char *)&signerIDLength, 1); // signer ID length
|
||||
s.read ((char *)&signerIDLength, 1); // signer ID length
|
||||
uint64_t contentLength;
|
||||
s.read ((char *)&contentLength, 8); // content length
|
||||
s.read ((char *)&contentLength, 8); // content length
|
||||
contentLength = be64toh (contentLength);
|
||||
s.seekg (1, std::ios::cur); // unused
|
||||
uint8_t fileType;
|
||||
s.read ((char *)&fileType, 1); // file type
|
||||
if (fileType != 0x00) // zip file
|
||||
s.read ((char *)&fileType, 1); // file type
|
||||
if (fileType != 0x00) // zip file
|
||||
{
|
||||
LogPrint (eLogError, "Reseed: Can't handle file type ", (int)fileType);
|
||||
return 0;
|
||||
}
|
||||
s.seekg (1, std::ios::cur); // unused
|
||||
uint8_t contentType;
|
||||
s.read ((char *)&contentType, 1); // content type
|
||||
s.read ((char *)&contentType, 1); // content type
|
||||
if (contentType != 0x03) // reseed data
|
||||
{
|
||||
LogPrint (eLogError, "Reseed: Unexpected content type ", (int)contentType);
|
||||
@@ -688,7 +688,7 @@ namespace data
|
||||
{
|
||||
boost::asio::ip::tcp::endpoint ep = *it;
|
||||
if ((ep.address ().is_v4 () && i2p::context.SupportsV4 ()) ||
|
||||
(ep.address ().is_v6 () && i2p::context.SupportsV6 ()))
|
||||
(ep.address ().is_v6 () && i2p::context.SupportsV6 ()))
|
||||
{
|
||||
s.lowest_layer().connect (ep, ecode);
|
||||
if (!ecode)
|
||||
|
||||
@@ -65,13 +65,13 @@ namespace i2p
|
||||
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
|
||||
if (port == 9150) port = 9151; // Tor browser
|
||||
}
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
||||
bool nat; i2p::config::GetOption("nat", nat);
|
||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
|
||||
bool nat; i2p::config::GetOption("nat", nat);
|
||||
|
||||
if ((ntcp2 || ygg) && !m_NTCP2Keys)
|
||||
NewNTCP2Keys ();
|
||||
@@ -399,7 +399,7 @@ namespace i2p
|
||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
||||
{
|
||||
if (address->host != host && address->IsCompatible (host) &&
|
||||
!i2p::util::net::IsYggdrasilAddress (address->host))
|
||||
!i2p::util::net::IsYggdrasilAddress (address->host))
|
||||
{
|
||||
address->host = host;
|
||||
if (host.is_v6 () && address->transportStyle == i2p::data::RouterInfo::eTransportSSU)
|
||||
@@ -883,7 +883,7 @@ namespace i2p
|
||||
}
|
||||
std::shared_ptr<const i2p::data::IdentityEx> oldIdentity;
|
||||
if (m_Keys.GetPublic ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1 ||
|
||||
m_Keys.GetPublic ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
|
||||
m_Keys.GetPublic ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
|
||||
{
|
||||
// update keys
|
||||
LogPrint (eLogInfo, "Router: router keys are obsolete. Creating new");
|
||||
@@ -935,7 +935,7 @@ namespace i2p
|
||||
UpdateNTCP2Address (true); // enable NTCP2
|
||||
}
|
||||
else
|
||||
UpdateNTCP2Address (false); // disable NTCP2
|
||||
UpdateNTCP2Address (false); // disable NTCP2
|
||||
|
||||
// read SSU2
|
||||
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||
|
||||
@@ -344,7 +344,7 @@ namespace data
|
||||
if (isHost)
|
||||
{
|
||||
if (address->host.is_v6 ())
|
||||
supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6);
|
||||
supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6);
|
||||
else
|
||||
supportedTransports |= eNTCP2V4;
|
||||
m_ReachableTransports |= supportedTransports;
|
||||
@@ -366,7 +366,7 @@ namespace data
|
||||
if (isIntroKey)
|
||||
{
|
||||
if (isHost)
|
||||
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
|
||||
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
|
||||
else if (address->caps & AddressCaps::eV6)
|
||||
{
|
||||
supportedTransports |= eSSUV6;
|
||||
@@ -383,7 +383,7 @@ namespace data
|
||||
{
|
||||
if (!it.iExp) it.iExp = m_Timestamp/1000 + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT;
|
||||
if (ts <= it.iExp && it.iPort > 0 &&
|
||||
((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ())))
|
||||
((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ())))
|
||||
numValid++;
|
||||
else
|
||||
it.iPort = 0;
|
||||
@@ -723,7 +723,7 @@ namespace data
|
||||
for (auto& addr : *m_Addresses)
|
||||
{
|
||||
if (addr->transportStyle == eTransportSSU &&
|
||||
((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ())))
|
||||
((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ())))
|
||||
{
|
||||
for (auto& intro: addr->ssu->introducers)
|
||||
if (intro.iTag == introducer.iTag) return false; // already presented
|
||||
@@ -740,7 +740,7 @@ namespace data
|
||||
for (auto& addr: *m_Addresses)
|
||||
{
|
||||
if (addr->transportStyle == eTransportSSU &&
|
||||
((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ())))
|
||||
((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ())))
|
||||
{
|
||||
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
|
||||
if (boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e)
|
||||
@@ -1153,7 +1153,7 @@ namespace data
|
||||
{
|
||||
WriteString ("NTCP2", s);
|
||||
if (address.IsPublishedNTCP2 () && !address.host.is_unspecified () && address.port)
|
||||
isPublished = true;
|
||||
isPublished = true;
|
||||
else
|
||||
{
|
||||
WriteString ("caps", properties);
|
||||
|
||||
@@ -146,11 +146,11 @@ namespace data
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool IsNTCP2 () const { return transportStyle == eTransportNTCP; };
|
||||
bool IsSSU2 () const { return transportStyle == eTransportSSU2; };
|
||||
bool IsNTCP2 () const { return transportStyle == eTransportNTCP; };
|
||||
bool IsSSU2 () const { return transportStyle == eTransportSSU2; };
|
||||
bool IsPublishedNTCP2 () const { return IsNTCP2 () && published; };
|
||||
bool IsReachableSSU () const { return (bool)ssu && (published || UsesIntroducer ()); };
|
||||
bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); };
|
||||
bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); };
|
||||
|
||||
bool IsIntroducer () const { return caps & eSSUIntroducer; };
|
||||
bool IsPeerTesting () const { return caps & eSSUTesting; };
|
||||
|
||||
@@ -273,14 +273,14 @@ namespace transport
|
||||
void SSUServer::HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet)
|
||||
{
|
||||
if (!ecode
|
||||
|| ecode == boost::asio::error::connection_refused
|
||||
|| ecode == boost::asio::error::connection_reset
|
||||
|| ecode == boost::asio::error::network_unreachable
|
||||
|| ecode == boost::asio::error::host_unreachable
|
||||
|| ecode == boost::asio::error::connection_refused
|
||||
|| ecode == boost::asio::error::connection_reset
|
||||
|| ecode == boost::asio::error::network_unreachable
|
||||
|| ecode == boost::asio::error::host_unreachable
|
||||
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|
||||
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|
||||
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|
||||
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
|
||||
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|
||||
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|
||||
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
|
||||
#endif
|
||||
)
|
||||
// just try continue reading when received ICMP response otherwise socket can crash,
|
||||
@@ -332,14 +332,14 @@ namespace transport
|
||||
void SSUServer::HandleReceivedFromV6 (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet)
|
||||
{
|
||||
if (!ecode
|
||||
|| ecode == boost::asio::error::connection_refused
|
||||
|| ecode == boost::asio::error::connection_reset
|
||||
|| ecode == boost::asio::error::network_unreachable
|
||||
|| ecode == boost::asio::error::host_unreachable
|
||||
|| ecode == boost::asio::error::connection_refused
|
||||
|| ecode == boost::asio::error::connection_reset
|
||||
|| ecode == boost::asio::error::network_unreachable
|
||||
|| ecode == boost::asio::error::host_unreachable
|
||||
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|
||||
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|
||||
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|
||||
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
|
||||
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|
||||
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|
||||
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
|
||||
#endif
|
||||
)
|
||||
// just try continue reading when received ICMP response otherwise socket can crash,
|
||||
@@ -582,7 +582,7 @@ namespace transport
|
||||
"] through introducer ", introducer->iHost, ":", introducer->iPort);
|
||||
session->WaitForIntroduction ();
|
||||
if ((address->host.is_v4 () && i2p::context.GetStatus () == eRouterStatusFirewalled) ||
|
||||
(address->host.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled))
|
||||
(address->host.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled))
|
||||
{
|
||||
uint8_t buf[1];
|
||||
Send (buf, 0, remoteEndpoint); // send HolePunch
|
||||
@@ -676,7 +676,7 @@ namespace transport
|
||||
for (const auto& s : sessions)
|
||||
{
|
||||
if (s.second->GetRelayTag () && s.second->GetState () == eSessionStateEstablished &&
|
||||
ts < s.second->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION)
|
||||
ts < s.second->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION)
|
||||
ret.push_back (s.second);
|
||||
else if (s.second->GetRemoteIdentity ())
|
||||
excluded.insert (s.second->GetRemoteIdentity ()->GetIdentHash ());
|
||||
|
||||
324
libi2pd/SSU2.cpp
324
libi2pd/SSU2.cpp
@@ -102,9 +102,6 @@ namespace transport
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize);
|
||||
// send
|
||||
m_RelaySessions.emplace (nonce, std::make_pair (session, ts));
|
||||
session->m_SourceConnID = htobe64 (((uint64_t)nonce << 32) | nonce);
|
||||
session->m_DestConnID = ~session->m_SourceConnID;
|
||||
m_Server.AddSession (session);
|
||||
SendData (payload, payloadSize);
|
||||
|
||||
return true;
|
||||
@@ -280,7 +277,7 @@ namespace transport
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -391,7 +388,7 @@ namespace transport
|
||||
htobe16buf (payload + 1, 4);
|
||||
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
|
||||
size_t payloadSize = 7;
|
||||
payloadSize += CreateAddressBlock (payload + payloadSize, 64 - payloadSize, m_RemoteEndpoint);
|
||||
payloadSize += CreateAddressBlock (m_RemoteEndpoint, payload + payloadSize, 64 - payloadSize);
|
||||
if (m_RelayTag)
|
||||
{
|
||||
payload[payloadSize] = eSSU2BlkRelayTag;
|
||||
@@ -473,12 +470,25 @@ namespace transport
|
||||
memset (header.h.flags, 0, 3);
|
||||
header.h.flags[0] = 1; // frag, total fragments always 1
|
||||
// payload
|
||||
const size_t maxPayloadSize = SSU2_MAX_PAYLOAD_SIZE - 48; // part 2
|
||||
uint8_t payload[maxPayloadSize + 16];
|
||||
size_t payloadSize = CreateRouterInfoBlock (payload, maxPayloadSize, i2p::context.GetSharedRouterInfo ());
|
||||
// TODO: check is RouterInfo doesn't fit and split by two fragments
|
||||
if (payloadSize < maxPayloadSize)
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, maxPayloadSize - payloadSize);
|
||||
uint8_t payload[SSU2_MTU];
|
||||
size_t payloadSize = i2p::context.GetRouterInfo ().GetBufferLen ();
|
||||
payload[0] = eSSU2BlkRouterInfo;
|
||||
if (payloadSize < 1024)
|
||||
{
|
||||
memcpy (payload + 5, i2p::context.GetRouterInfo ().GetBuffer (), payloadSize);
|
||||
payload[3] = 0; // flag
|
||||
}
|
||||
else
|
||||
{
|
||||
i2p::data::GzipDeflator deflator;
|
||||
payloadSize = deflator.Deflate (i2p::context.GetRouterInfo ().GetBuffer (),
|
||||
i2p::context.GetRouterInfo ().GetBufferLen (), payload + 5, SSU2_MTU -5);
|
||||
payload[3] = SSU2_ROUTER_INFO_FLAG_GZIP; // flag
|
||||
}
|
||||
htobe16buf (payload + 1, payloadSize + 2);
|
||||
payload[4] = 1; // frag
|
||||
payloadSize += 5;
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MTU - payloadSize);
|
||||
// KDF for Session Confirmed part 1
|
||||
m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header)
|
||||
// Encrypt part 1
|
||||
@@ -515,7 +525,7 @@ namespace transport
|
||||
header.ll[1] ^= CreateHeaderMask (kh2, buf + (len - 12));
|
||||
if (header.h.type != eSSU2SessionConfirmed)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
return false;
|
||||
}
|
||||
// check if fragmented
|
||||
@@ -698,7 +708,7 @@ namespace transport
|
||||
htobe16buf (payload + 1, 4);
|
||||
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
|
||||
size_t payloadSize = 7;
|
||||
payloadSize += CreateAddressBlock (payload + payloadSize, 64 - payloadSize, m_RemoteEndpoint);
|
||||
payloadSize += CreateAddressBlock (m_RemoteEndpoint, payload + payloadSize, 64 - payloadSize);
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, 64 - payloadSize);
|
||||
// encrypt
|
||||
uint8_t nonce[12];
|
||||
@@ -722,7 +732,7 @@ namespace transport
|
||||
header.ll[1] ^= CreateHeaderMask (m_Address->i, buf + (len - 12));
|
||||
if (header.h.type != eSSU2Retry)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
return false;
|
||||
}
|
||||
uint8_t nonce[12] = {0};
|
||||
@@ -748,116 +758,6 @@ namespace transport
|
||||
return true;
|
||||
}
|
||||
|
||||
void SSU2Session::SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey)
|
||||
{
|
||||
// we are Charlie
|
||||
Header header;
|
||||
uint8_t h[32], payload[SSU2_MAX_PAYLOAD_SIZE];
|
||||
// fill packet
|
||||
header.h.connID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id
|
||||
RAND_bytes (header.buf + 8, 4); // random packet num
|
||||
header.h.type = eSSU2HolePunch;
|
||||
header.h.flags[0] = 2; // ver
|
||||
header.h.flags[1] = (uint8_t)i2p::context.GetNetID (); // netID
|
||||
header.h.flags[2] = 0; // flag
|
||||
memcpy (h, header.buf, 16);
|
||||
uint64_t c = !header.h.connID;
|
||||
memcpy (h + 16, &c, 8); // source id
|
||||
uint64_t token = m_Server.GetIncomingToken (ep);
|
||||
memcpy (h + 24, &token, 8); // token
|
||||
// payload
|
||||
payload[0] = eSSU2BlkDateTime;
|
||||
htobe16buf (payload + 1, 4);
|
||||
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
|
||||
size_t payloadSize = 7;
|
||||
payloadSize += CreateAddressBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize, ep);
|
||||
payloadSize += CreateRelayResponseBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize, nonce);
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize);
|
||||
// encrypt
|
||||
uint8_t n[12];
|
||||
CreateNonce (be32toh (header.h.packetNum), n);
|
||||
i2p::crypto::AEADChaCha20Poly1305 (payload, payloadSize, h, 32, introKey, n, payload, payloadSize + 16, true);
|
||||
payloadSize += 16;
|
||||
header.ll[0] ^= CreateHeaderMask (introKey, payload + (payloadSize - 24));
|
||||
header.ll[1] ^= CreateHeaderMask (introKey, payload + (payloadSize - 12));
|
||||
memset (n, 0, 12);
|
||||
i2p::crypto::ChaCha20 (h + 16, 16, introKey, n, h + 16);
|
||||
// send
|
||||
m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep);
|
||||
}
|
||||
|
||||
bool SSU2Session::ProcessHolePunch (uint8_t * buf, size_t len)
|
||||
{
|
||||
// we are Alice
|
||||
Header header;
|
||||
memcpy (header.buf, buf, 16);
|
||||
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 24));
|
||||
header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 12));
|
||||
if (header.h.type != eSSU2HolePunch)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
return false;
|
||||
}
|
||||
uint8_t nonce[12] = {0};
|
||||
uint64_t headerX[2]; // sourceConnID, token
|
||||
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
||||
m_DestConnID = headerX[0];
|
||||
// decrypt and handle payload
|
||||
uint8_t * payload = buf + 32;
|
||||
CreateNonce (be32toh (header.h.packetNum), nonce);
|
||||
uint8_t h[32];
|
||||
memcpy (h, header.buf, 16);
|
||||
memcpy (h + 16, &headerX, 16);
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len - 48, h, 32,
|
||||
i2p::context.GetSSU2IntroKey (), nonce, payload, len - 48, false))
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: HolePunch AEAD verification failed ");
|
||||
return false;
|
||||
}
|
||||
m_Server.UpdateOutgoingToken (m_RemoteEndpoint, headerX[1], i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT);
|
||||
HandlePayload (payload, len - 48);
|
||||
// connect to Charlie
|
||||
if (m_State == eSSU2SessionStateIntroduced)
|
||||
{
|
||||
m_State = eSSU2SessionStateUnknown;
|
||||
Connect ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SSU2Session::ProcessPeerTest (uint8_t * buf, size_t len)
|
||||
{
|
||||
// we are Alice or Charlie
|
||||
Header header;
|
||||
memcpy (header.buf, buf, 16);
|
||||
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 24));
|
||||
header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 12));
|
||||
if (header.h.type != eSSU2PeerTest)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
return false;
|
||||
}
|
||||
uint8_t nonce[12] = {0};
|
||||
uint64_t headerX[2]; // sourceConnID, token
|
||||
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
||||
m_DestConnID = headerX[0];
|
||||
// decrypt and handle payload
|
||||
uint8_t * payload = buf + 32;
|
||||
CreateNonce (be32toh (header.h.packetNum), nonce);
|
||||
uint8_t h[32];
|
||||
memcpy (h, header.buf, 16);
|
||||
memcpy (h + 16, &headerX, 16);
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len - 48, h, 32,
|
||||
i2p::context.GetSSU2IntroKey (), nonce, payload, len - 48, false))
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: PeerTest AEAD verification failed ");
|
||||
return false;
|
||||
}
|
||||
HandlePayload (payload, len - 48);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t SSU2Session::SendData (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (len < 8)
|
||||
@@ -891,7 +791,7 @@ namespace transport
|
||||
header.ll[1] ^= CreateHeaderMask (m_KeyDataReceive + 32, buf + (len - 12));
|
||||
if (header.h.type != eSSU2Data)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type);
|
||||
return;
|
||||
}
|
||||
uint8_t payload[SSU2_MTU];
|
||||
@@ -977,12 +877,8 @@ namespace transport
|
||||
HandleRelayResponse (buf + offset, size);
|
||||
break;
|
||||
case eSSU2BlkRelayIntro:
|
||||
LogPrint (eLogDebug, "SSU2: RelayIntro");
|
||||
HandleRelayIntro (buf + offset, size);
|
||||
break;
|
||||
case eSSU2BlkPeerTest:
|
||||
LogPrint (eLogDebug, "SSU2: PeerTest");
|
||||
HandlePeerTest (buf + offset, size);
|
||||
break;
|
||||
case eSSU2BlkNextNonce:
|
||||
break;
|
||||
@@ -1067,7 +963,7 @@ namespace transport
|
||||
if (it == m_SentPackets.end ()) return; // not found
|
||||
auto it1 = it;
|
||||
while (it1 != m_SentPackets.end () && it1->first <= lastPacketNum) it1++;
|
||||
if (it1 != m_SentPackets.end () && it1 != m_SentPackets.begin ()) it1--;
|
||||
if (it1 != m_SentPackets.end ()) it1--;
|
||||
m_SentPackets.erase (it, it1);
|
||||
}
|
||||
|
||||
@@ -1183,14 +1079,9 @@ namespace transport
|
||||
std::make_pair (shared_from_this (), i2p::util::GetSecondsSinceEpoch ()) );
|
||||
|
||||
// send relay intro to Charlie
|
||||
auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); // Alice's RI
|
||||
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE];
|
||||
size_t payloadSize = r ? CreateRouterInfoBlock (payload, SSU2_MAX_PAYLOAD_SIZE - len - 32, r) : 0;
|
||||
if (!payloadSize && r)
|
||||
SendFragmentedMessage (CreateDatabaseStoreMsg (r));
|
||||
payloadSize += CreateRelayIntroBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize, buf + 1, len -1);
|
||||
if (payloadSize < SSU2_MAX_PAYLOAD_SIZE)
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize);
|
||||
uint8_t payload[SSU2_MTU];
|
||||
size_t payloadSize = CreateRelayIntroBlock (payload, SSU2_MTU, buf + 1, len -1);
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MTU - payloadSize);
|
||||
session->SendData (payload, payloadSize);
|
||||
}
|
||||
|
||||
@@ -1217,28 +1108,19 @@ namespace transport
|
||||
}
|
||||
|
||||
// send relay response to Bob
|
||||
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE];
|
||||
size_t payloadSize = CreateRelayResponseBlock (payload, SSU2_MAX_PAYLOAD_SIZE, bufbe32toh (buf + 33));
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize);
|
||||
uint8_t payload[SSU2_MTU];
|
||||
size_t payloadSize = CreateRelayResponseBlock (payload, SSU2_MTU, bufbe32toh (buf + 33));
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MTU - payloadSize);
|
||||
SendData (payload, payloadSize);
|
||||
|
||||
// send HolePunch
|
||||
boost::asio::ip::udp::endpoint ep;
|
||||
if (ExtractEndpoint (buf + 47, asz, ep))
|
||||
{
|
||||
auto r = i2p::data::netdb.FindRouter (buf + 1); // Alice
|
||||
if (r)
|
||||
{
|
||||
auto addr = ep.address ().is_v6 () ? r->GetSSU2V6Address () : r->GetSSU2V4Address ();
|
||||
if (addr)
|
||||
SendHolePunch (bufbe32toh (buf + 33), ep, addr->i);
|
||||
}
|
||||
}
|
||||
m_Server.SendHolePunch (ep);
|
||||
}
|
||||
|
||||
void SSU2Session::HandleRelayResponse (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_State == eSSU2SessionStateIntroduced) return; // HolePunch from Charlie, TODO: verify address and signature
|
||||
auto it = m_RelaySessions.find (bufbe32toh (buf + 2)); // nonce
|
||||
if (it != m_RelaySessions.end ())
|
||||
{
|
||||
@@ -1259,8 +1141,7 @@ namespace transport
|
||||
if (s.Verify (it->second.first->GetRemoteIdentity (), buf + 12 + csz))
|
||||
{
|
||||
// update Charlie's endpoint and connect
|
||||
if (it->second.first->m_State == eSSU2SessionStateIntroduced &&
|
||||
ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint))
|
||||
if (ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint))
|
||||
{
|
||||
it->second.first->m_State = eSSU2SessionStateUnknown;
|
||||
it->second.first->Connect ();
|
||||
@@ -1278,41 +1159,6 @@ namespace transport
|
||||
LogPrint (eLogWarning, "SSU2: RelayResponse unknown nonce ", bufbe32toh (buf + 2));
|
||||
}
|
||||
|
||||
void SSU2Session::HandlePeerTest (const uint8_t * buf, size_t len)
|
||||
{
|
||||
uint32_t nonce = bufbe32toh (buf + 37);
|
||||
switch (buf[0]) // msg
|
||||
{
|
||||
case 1: // Bob for Alice
|
||||
break;
|
||||
case 2: // Charlie from Bob
|
||||
break;
|
||||
case 3: // Bob from Charlie
|
||||
{
|
||||
auto it = m_PeerTests.find (nonce);
|
||||
if (it != m_PeerTests.end () && it->second.first)
|
||||
{
|
||||
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE];
|
||||
size_t payloadSize = CreatePeerTestBlock (payload, SSU2_MAX_PAYLOAD_SIZE, 4, buf + 3, buf + 35, len -35);
|
||||
if (payloadSize < SSU2_MAX_PAYLOAD_SIZE)
|
||||
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize);
|
||||
it->second.first->SendData (payload, payloadSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: // Alice from Bob
|
||||
break;
|
||||
case 5: // Alice from Chralie 1
|
||||
break;
|
||||
case 6: // Chralie from Alice
|
||||
break;
|
||||
case 7: // Alice from Charlie 2
|
||||
break;
|
||||
default:
|
||||
LogPrint (eLogWarning, "SSU2: PeerTest unexpected msg num ", buf[0]);
|
||||
}
|
||||
}
|
||||
|
||||
bool SSU2Session::ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep)
|
||||
{
|
||||
if (size < 2) return false;
|
||||
@@ -1361,7 +1207,7 @@ namespace transport
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep)
|
||||
size_t SSU2Session::CreateAddressBlock (const boost::asio::ip::udp::endpoint& ep, uint8_t * buf, size_t len)
|
||||
{
|
||||
if (len < 9) return 0;
|
||||
buf[0] = eSSU2BlkAddress;
|
||||
@@ -1371,28 +1217,6 @@ namespace transport
|
||||
return size + 3;
|
||||
}
|
||||
|
||||
size_t SSU2Session::CreateRouterInfoBlock (uint8_t * buf, size_t len, std::shared_ptr<const i2p::data::RouterInfo> r)
|
||||
{
|
||||
if (!r || len < 5) return 0;
|
||||
buf[0] = eSSU2BlkRouterInfo;
|
||||
size_t size = r->GetBufferLen ();
|
||||
if (size + 5 < len)
|
||||
{
|
||||
memcpy (buf + 5, r->GetBuffer (), size);
|
||||
buf[3] = 0; // flag
|
||||
}
|
||||
else
|
||||
{
|
||||
i2p::data::GzipDeflator deflator;
|
||||
size = deflator.Deflate (r->GetBuffer (), r->GetBufferLen (), buf + 5, len - 5);
|
||||
if (!size) return 0; // doesn't fit
|
||||
buf[3] = SSU2_ROUTER_INFO_FLAG_GZIP; // flag
|
||||
}
|
||||
htobe16buf (buf + 1, size + 2); // size
|
||||
buf[4] = 1; // frag
|
||||
return size + 5;
|
||||
}
|
||||
|
||||
size_t SSU2Session::CreateAckBlock (uint8_t * buf, size_t len)
|
||||
{
|
||||
if (len < 8) return 0;
|
||||
@@ -1523,7 +1347,7 @@ namespace transport
|
||||
{
|
||||
buf[0] = eSSU2BlkRelayResponse;
|
||||
buf[3] = 0; // flag
|
||||
buf[4] = 0; // code, accept
|
||||
buf[4] = 0; // code, accept
|
||||
htobe32buf (buf + 5, nonce); // nonce
|
||||
htobe32buf (buf + 9, i2p::util::GetSecondsSinceEpoch ()); // timestamp
|
||||
buf[13] = 2; // ver
|
||||
@@ -1541,21 +1365,6 @@ namespace transport
|
||||
return payloadSize + 3;
|
||||
}
|
||||
|
||||
size_t SSU2Session::CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg,
|
||||
const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen)
|
||||
{
|
||||
buf[0] = eSSU2BlkPeerTest;
|
||||
size_t payloadSize = 3/* msg, code, flag */ + 32/* router hash */ + signedDataLen;
|
||||
if (payloadSize + 3 > len) return 0;
|
||||
htobe16buf (buf + 1, payloadSize); // size
|
||||
buf[3] = msg; // msg
|
||||
buf[4] = 0; // code, TODO:
|
||||
buf[5] = 0; //flag
|
||||
memcpy (buf + 6, routerHash, 32); // router hash
|
||||
memcpy (buf + 38, signedData, signedDataLen);
|
||||
return payloadSize + 3;
|
||||
}
|
||||
|
||||
std::shared_ptr<const i2p::data::RouterInfo> SSU2Session::ExtractRouterInfo (const uint8_t * buf, size_t size)
|
||||
{
|
||||
if (size < 2) return nullptr;
|
||||
@@ -1644,22 +1453,12 @@ namespace transport
|
||||
{
|
||||
if (ts > it->second.second + SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Relay nonce ", it->first, " was not responded in ", SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT, " seconds, deleted");
|
||||
LogPrint (eLogWarning, "SSU2: noce ", it->first, " was not responded in ", SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT, " seconds, deleted");
|
||||
it = m_RelaySessions.erase (it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
for (auto it = m_PeerTests.begin (); it != m_PeerTests.end ();)
|
||||
{
|
||||
if (ts > it->second.second + SSU2_PEER_TEST_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
LogPrint (eLogWarning, "SSU2: Peer test nonce ", it->first, " was not responded in ", SSU2_PEER_TEST_EXPIRATION_TIMEOUT, " seconds, deleted");
|
||||
it = m_PeerTests.erase (it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void SSU2Session::FlushData ()
|
||||
@@ -1710,7 +1509,7 @@ namespace transport
|
||||
found = true;
|
||||
OpenSocket (boost::asio::ip::udp::endpoint (boost::asio::ip::udp::v4(), port));
|
||||
m_ReceiveService.GetService ().post(
|
||||
[this]()
|
||||
[this]()
|
||||
{
|
||||
Receive (m_SocketV4);
|
||||
});
|
||||
@@ -1720,7 +1519,7 @@ namespace transport
|
||||
found = true;
|
||||
OpenSocket (boost::asio::ip::udp::endpoint (boost::asio::ip::udp::v6(), port));
|
||||
m_ReceiveService.GetService ().post(
|
||||
[this]()
|
||||
[this]()
|
||||
{
|
||||
Receive (m_SocketV6);
|
||||
});
|
||||
@@ -1762,7 +1561,7 @@ namespace transport
|
||||
}
|
||||
catch (std::exception& ex )
|
||||
{
|
||||
LogPrint (eLogError, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what());
|
||||
LogPrint (eLogError, "SSU2: Failed to bind to ", localEndpoint, ": ", ex.what());
|
||||
ThrowFatal ("Unable to start SSU2 transport on ", localEndpoint, ": ", ex.what ());
|
||||
}
|
||||
return socket;
|
||||
@@ -1866,7 +1665,7 @@ namespace transport
|
||||
}
|
||||
}
|
||||
|
||||
void SSU2Server::AddSessionByRouterHash (std::shared_ptr<SSU2Session> session)
|
||||
void SSU2Server::AddSessionByRouterHash (std::shared_ptr<SSU2Session> session)
|
||||
{
|
||||
if (session)
|
||||
{
|
||||
@@ -1933,25 +1732,10 @@ namespace transport
|
||||
}
|
||||
if (m_LastSession)
|
||||
{
|
||||
switch (m_LastSession->GetState ())
|
||||
{
|
||||
case eSSU2SessionStateEstablished:
|
||||
m_LastSession->ProcessData (buf, len);
|
||||
break;
|
||||
case eSSU2SessionStateUnknown:
|
||||
m_LastSession->ProcessSessionConfirmed (buf, len);
|
||||
break;
|
||||
case eSSU2SessionStateIntroduced:
|
||||
m_LastSession->SetRemoteEndpoint (senderEndpoint);
|
||||
m_LastSession->ProcessHolePunch (buf, len);
|
||||
break;
|
||||
case eSSU2SessionStatePeerTest:
|
||||
m_LastSession->SetRemoteEndpoint (senderEndpoint);
|
||||
m_LastSession->ProcessPeerTest (buf, len);
|
||||
break;
|
||||
default:
|
||||
LogPrint (eLogWarning, "SSU2: Invalid session state ", (int)m_LastSession->GetState ());
|
||||
}
|
||||
if (m_LastSession->IsEstablished ())
|
||||
m_LastSession->ProcessData (buf, len);
|
||||
else
|
||||
m_LastSession->ProcessSessionConfirmed (buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2014,6 +1798,18 @@ namespace transport
|
||||
LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to);
|
||||
}
|
||||
|
||||
void SSU2Server::SendHolePunch (const boost::asio::ip::udp::endpoint& to)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
if (to.address ().is_v6 ())
|
||||
m_SocketV6.send_to (boost::asio::buffer ((uint8_t *)nullptr, 0), to, 0, ec);
|
||||
else
|
||||
m_SocketV4.send_to (boost::asio::buffer ((uint8_t *)nullptr, 0), to, 0, ec);
|
||||
|
||||
if (ec)
|
||||
LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to);
|
||||
}
|
||||
|
||||
bool SSU2Server::CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> address)
|
||||
{
|
||||
@@ -2055,7 +1851,7 @@ namespace transport
|
||||
for (auto& it: address->ssu->introducers)
|
||||
{
|
||||
r = i2p::data::netdb.FindRouter (it.iKey);
|
||||
if (r && r->IsReachableFrom (i2p::context.GetRouterInfo ()))
|
||||
if (r)
|
||||
{
|
||||
relayTag = it.iTag;
|
||||
if (relayTag) break;
|
||||
@@ -2065,7 +1861,7 @@ namespace transport
|
||||
{
|
||||
if (relayTag)
|
||||
{
|
||||
// introducer and tag found connect to it through SSU2
|
||||
// introducer and tag found connect to it through SSU2
|
||||
auto addr = address->IsV6 () ? r->GetSSU2V6Address () : r->GetSSU2V4Address ();
|
||||
if (addr)
|
||||
{
|
||||
@@ -2117,7 +1913,7 @@ namespace transport
|
||||
if (it->second->IsEstablished ())
|
||||
it->second->TerminateByTimeout ();
|
||||
if (it->second == m_LastSession)
|
||||
m_LastSession = nullptr;
|
||||
m_LastSession = nullptr;
|
||||
it = m_Sessions.erase (it);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace transport
|
||||
const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
||||
const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // in seconds
|
||||
const int SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT = 10; // in seconds
|
||||
const int SSU2_PEER_TEST_EXPIRATION_TIMEOUT = 60; // 60 seconds
|
||||
const size_t SSU2_SOCKET_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K
|
||||
const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K
|
||||
const size_t SSU2_MTU = 1488;
|
||||
@@ -44,10 +43,8 @@ namespace transport
|
||||
eSSU2SessionCreated = 1,
|
||||
eSSU2SessionConfirmed = 2,
|
||||
eSSU2Data = 6,
|
||||
eSSU2PeerTest = 7,
|
||||
eSSU2Retry = 9,
|
||||
eSSU2TokenRequest = 10,
|
||||
eSSU2HolePunch = 11
|
||||
eSSU2TokenRequest = 10
|
||||
};
|
||||
|
||||
enum SSU2BlockType
|
||||
@@ -80,7 +77,6 @@ namespace transport
|
||||
{
|
||||
eSSU2SessionStateUnknown,
|
||||
eSSU2SessionStateIntroduced,
|
||||
eSSU2SessionStatePeerTest,
|
||||
eSSU2SessionStateEstablished,
|
||||
eSSU2SessionStateTerminated,
|
||||
eSSU2SessionStateFailed
|
||||
@@ -166,8 +162,6 @@ namespace transport
|
||||
bool ProcessSessionCreated (uint8_t * buf, size_t len);
|
||||
bool ProcessSessionConfirmed (uint8_t * buf, size_t len);
|
||||
bool ProcessRetry (uint8_t * buf, size_t len);
|
||||
bool ProcessHolePunch (uint8_t * buf, size_t len);
|
||||
bool ProcessPeerTest (uint8_t * buf, size_t len);
|
||||
void ProcessData (uint8_t * buf, size_t len);
|
||||
|
||||
private:
|
||||
@@ -189,7 +183,6 @@ namespace transport
|
||||
uint32_t SendData (const uint8_t * buf, size_t len); // returns packet num
|
||||
void SendQuickAck ();
|
||||
void SendTermination ();
|
||||
void SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey);
|
||||
|
||||
void HandlePayload (const uint8_t * buf, size_t len);
|
||||
void HandleAck (const uint8_t * buf, size_t len);
|
||||
@@ -205,10 +198,8 @@ namespace transport
|
||||
void HandleRelayRequest (const uint8_t * buf, size_t len);
|
||||
void HandleRelayIntro (const uint8_t * buf, size_t len);
|
||||
void HandleRelayResponse (const uint8_t * buf, size_t len);
|
||||
void HandlePeerTest (const uint8_t * buf, size_t len);
|
||||
|
||||
size_t CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep);
|
||||
size_t CreateRouterInfoBlock (uint8_t * buf, size_t len, std::shared_ptr<const i2p::data::RouterInfo> r);
|
||||
size_t CreateAddressBlock (const boost::asio::ip::udp::endpoint& ep, uint8_t * buf, size_t len);
|
||||
size_t CreateAckBlock (uint8_t * buf, size_t len);
|
||||
size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0);
|
||||
size_t CreateI2NPBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage>&& msg);
|
||||
@@ -216,7 +207,6 @@ namespace transport
|
||||
size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID);
|
||||
size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen);
|
||||
size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, uint32_t nonce); // Charlie
|
||||
size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen);
|
||||
|
||||
private:
|
||||
|
||||
@@ -234,7 +224,6 @@ namespace transport
|
||||
std::map<uint32_t, std::shared_ptr<SentPacket> > m_SentPackets; // packetNum -> packet
|
||||
std::map<uint32_t, std::shared_ptr<SSU2IncompleteMessage> > m_IncompleteMessages; // I2NP
|
||||
std::map<uint32_t, std::pair <std::shared_ptr<SSU2Session>, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice
|
||||
std::map<uint32_t, std::pair <std::shared_ptr<SSU2Session>, uint64_t > > m_PeerTests; // same as for relay sessions
|
||||
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
||||
i2p::I2NPMessagesHandler m_Handler;
|
||||
bool m_IsDataReceived;
|
||||
@@ -243,7 +232,7 @@ namespace transport
|
||||
OnEstablished m_OnEstablished; // callback from Established
|
||||
};
|
||||
|
||||
class SSU2Server: private i2p::util::RunnableServiceWithWork
|
||||
class SSU2Server: private i2p::util::RunnableServiceWithWork
|
||||
{
|
||||
struct Packet
|
||||
{
|
||||
@@ -284,6 +273,7 @@ namespace transport
|
||||
const boost::asio::ip::udp::endpoint& to);
|
||||
void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
|
||||
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to);
|
||||
void SendHolePunch (const boost::asio::ip::udp::endpoint& to);
|
||||
|
||||
bool CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
|
||||
std::shared_ptr<const i2p::data::RouterInfo::Address> address);
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace transport
|
||||
return;
|
||||
}
|
||||
|
||||
// find message with msgID
|
||||
// find message with msgID
|
||||
auto it = m_IncompleteMessages.find (msgID);
|
||||
if (it == m_IncompleteMessages.end ())
|
||||
{
|
||||
@@ -318,7 +318,7 @@ namespace transport
|
||||
sentMessage->numResends = 0;
|
||||
}
|
||||
auto& fragments = sentMessage->fragments;
|
||||
size_t payloadSize = m_PacketSize - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3)
|
||||
size_t payloadSize = m_PacketSize - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3)
|
||||
size_t len = msg->GetLength ();
|
||||
uint8_t * msgBuf = msg->GetSSUHeader ();
|
||||
|
||||
|
||||
@@ -388,11 +388,11 @@ namespace transport
|
||||
// fill extended options, 3 bytes extended options don't change message size
|
||||
bool isV4 = m_RemoteEndpoint.address ().is_v4 ();
|
||||
if ((isV4 && i2p::context.GetStatus () == eRouterStatusOK) ||
|
||||
(!isV4 && i2p::context.GetStatusV6 () == eRouterStatusOK)) // we don't need relays
|
||||
(!isV4 && i2p::context.GetStatusV6 () == eRouterStatusOK)) // we don't need relays
|
||||
{
|
||||
// tell out peer to now assign relay tag
|
||||
flag = SSU_HEADER_EXTENDED_OPTIONS_INCLUDED;
|
||||
*payload = 2; payload++; // 1 byte length
|
||||
*payload = 2; payload++; // 1 byte length
|
||||
uint16_t flags = 0; // clear EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG
|
||||
htobe16buf (payload, flags);
|
||||
payload += 2;
|
||||
@@ -1020,7 +1020,7 @@ namespace transport
|
||||
for (auto it = m_RelayRequests.begin (); it != m_RelayRequests.end ();)
|
||||
{
|
||||
if (ts > it->second.second + SSU_CONNECT_TIMEOUT)
|
||||
it = m_RelayRequests.erase (it);
|
||||
it = m_RelayRequests.erase (it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace crypto
|
||||
else
|
||||
{
|
||||
size_t l = 64;
|
||||
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
|
||||
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
|
||||
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
|
||||
memcpy (signature, sig, 64);
|
||||
}
|
||||
|
||||
@@ -1249,7 +1249,7 @@ namespace stream
|
||||
return s;
|
||||
}
|
||||
|
||||
void StreamingDestination::SendPing (std::shared_ptr<const i2p::data::LeaseSet> remote)
|
||||
void StreamingDestination::SendPing (std::shared_ptr<const i2p::data::LeaseSet> remote)
|
||||
{
|
||||
auto s = std::make_shared<Stream> (m_Owner->GetService (), *this, remote, 0);
|
||||
s->SendPing ();
|
||||
@@ -1285,13 +1285,7 @@ namespace stream
|
||||
auto it = m_Streams.find (recvStreamID);
|
||||
if (it == m_Streams.end ())
|
||||
return false;
|
||||
auto s = it->second;
|
||||
m_Owner->GetService ().post ([this, s] ()
|
||||
{
|
||||
s->Close (); // try to send FIN
|
||||
s->Terminate (false);
|
||||
DeleteStream (s);
|
||||
});
|
||||
DeleteStream (it->second);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace tunnel
|
||||
else
|
||||
{
|
||||
if (m_Config->IsShort () && m_Config->GetLastHop () &&
|
||||
m_Config->GetLastHop ()->ident->GetIdentHash () != m_Config->GetLastHop ()->nextIdent)
|
||||
m_Config->GetLastHop ()->ident->GetIdentHash () != m_Config->GetLastHop ()->nextIdent)
|
||||
{
|
||||
// add garlic key/tag for reply
|
||||
uint8_t key[32];
|
||||
@@ -822,7 +822,7 @@ namespace tunnel
|
||||
|
||||
template<class TTunnel>
|
||||
std::shared_ptr<TTunnel> Tunnels::CreateTunnel (std::shared_ptr<TunnelConfig> config,
|
||||
std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
||||
std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
||||
{
|
||||
auto newTunnel = std::make_shared<TTunnel> (config);
|
||||
newTunnel->SetTunnelPool (pool);
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace tunnel
|
||||
|
||||
template<class TTunnel>
|
||||
std::shared_ptr<TTunnel> CreateTunnel (std::shared_ptr<TunnelConfig> config,
|
||||
std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
||||
std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
||||
|
||||
template<class TTunnel>
|
||||
std::shared_ptr<TTunnel> GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels);
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace tunnel
|
||||
memset (clearText + SHORT_REQUEST_RECORD_MORE_FLAGS_OFFSET, 0, 2);
|
||||
clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE] = 0; // AES
|
||||
htobe32buf (clearText + SHORT_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetMinutesSinceEpoch ());
|
||||
htobe32buf (clearText + SHORT_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET , 600); // +10 minutes
|
||||
htobe32buf (clearText + SHORT_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET , 600); // +10 minutes
|
||||
htobe32buf (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID);
|
||||
memset (clearText + SHORT_REQUEST_RECORD_PADDING_OFFSET, 0, SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE - SHORT_REQUEST_RECORD_PADDING_OFFSET);
|
||||
// encrypt
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace tunnel
|
||||
|
||||
TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
|
||||
uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent, bool isShort,
|
||||
i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // outbound
|
||||
i2p::data::RouterInfo::CompatibleTransports farEndTransports = i2p::data::RouterInfo::eAllTransports): // outbound
|
||||
m_IsShort (isShort), m_FarEndTransports (farEndTransports)
|
||||
{
|
||||
CreatePeers (peers);
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace tunnel
|
||||
{
|
||||
peers.push_back (r->GetRouterIdentity ());
|
||||
if (r->GetVersion () < i2p::data::NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION ||
|
||||
r->GetRouterIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
||||
r->GetRouterIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
||||
isShort = false;
|
||||
}
|
||||
}
|
||||
@@ -227,7 +227,7 @@ namespace tunnel
|
||||
if (it->IsEstablished () && it != excluded && (compatible & it->GetFarEndTransports ()))
|
||||
{
|
||||
if (it->IsSlow () || (HasLatencyRequirement() && it->LatencyIsKnown() &&
|
||||
!it->LatencyFitsRange(m_MinLatency, m_MaxLatency)))
|
||||
!it->LatencyFitsRange(m_MinLatency, m_MaxLatency)))
|
||||
{
|
||||
i++; skipped = true;
|
||||
continue;
|
||||
@@ -511,7 +511,7 @@ namespace tunnel
|
||||
return false;
|
||||
}
|
||||
if ((i == numHops - 1) && (!hop->IsV4 () || // doesn't support ipv4
|
||||
(inbound && !hop->IsReachable ()))) // IBGW is not reachable
|
||||
(inbound && !hop->IsReachable ()))) // IBGW is not reachable
|
||||
{
|
||||
auto hop1 = nextHop (prevHop, true);
|
||||
if (hop1) hop = hop1;
|
||||
@@ -715,7 +715,7 @@ namespace tunnel
|
||||
auto tunnel = tunnels.CreateInboundTunnel (
|
||||
m_NumOutboundHops > 0 ? std::make_shared<TunnelConfig>(outboundTunnel->GetInvertedPeers (),
|
||||
outboundTunnel->IsShortBuildMessage ()) : nullptr,
|
||||
shared_from_this (), outboundTunnel);
|
||||
shared_from_this (), outboundTunnel);
|
||||
if (tunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (tunnel);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
#include <iphlpapi.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "IPHLPAPI.lib")
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
||||
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
||||
|
||||
@@ -517,7 +521,7 @@ namespace net
|
||||
|
||||
bool IsLocalAddress (const boost::asio::ip::address& addr)
|
||||
{
|
||||
auto mtu = // TODO: implement better
|
||||
auto mtu = // TODO: implement better
|
||||
#ifdef _WIN32
|
||||
GetMTUWindows(addr, 0);
|
||||
#else
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
|
||||
|
||||
#define I2PD_VERSION_MAJOR 2
|
||||
#define I2PD_VERSION_MINOR 42
|
||||
#define I2PD_VERSION_MINOR 41
|
||||
#define I2PD_VERSION_MICRO 0
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#ifdef GITVER
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
#define I2P_VERSION_MICRO 54
|
||||
#define I2P_VERSION_MICRO 53
|
||||
#define I2P_VERSION_PATCH 0
|
||||
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
#define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace client
|
||||
{
|
||||
auto addr = FindAddress (address);
|
||||
if (!addr)
|
||||
LookupAddress (address); // TODO:
|
||||
LookupAddress (address); // TODO:
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
@@ -494,7 +494,7 @@ namespace client
|
||||
auto it = m_Addresses.find (name);
|
||||
if (it != m_Addresses.end ()) // already exists ?
|
||||
{
|
||||
if (it->second->IsIdentHash () && it->second->identHash != ident->GetIdentHash () && // address changed?
|
||||
if (it->second->IsIdentHash () && it->second->identHash != ident->GetIdentHash () && // address changed?
|
||||
ident->GetSigningKeyType () != i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) // don't replace by DSA
|
||||
{
|
||||
it->second->identHash = ident->GetIdentHash ();
|
||||
@@ -858,9 +858,9 @@ namespace client
|
||||
if (!m_LastModified.empty())
|
||||
req.AddHeader("If-Modified-Since", m_LastModified);
|
||||
/* convert url to relative */
|
||||
url.schema = "";
|
||||
url.host = "";
|
||||
req.uri = url.to_string();
|
||||
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();
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace client
|
||||
private:
|
||||
|
||||
std::mutex m_AddressBookMutex;
|
||||
std::map<std::string, std::shared_ptr<Address> > m_Addresses;
|
||||
std::map<std::string, std::shared_ptr<Address> > m_Addresses;
|
||||
std::map<i2p::data::IdentHash, std::shared_ptr<AddressResolver> > m_Resolvers; // local destination->resolver
|
||||
std::mutex m_LookupsMutex;
|
||||
std::map<uint32_t, std::string> m_Lookups; // nonce -> address
|
||||
@@ -162,7 +162,7 @@ namespace client
|
||||
private:
|
||||
|
||||
std::shared_ptr<ClientDestination> m_LocalDestination;
|
||||
std::map<std::string, i2p::data::IdentHash> m_LocalAddresses;
|
||||
std::map<std::string, i2p::data::IdentHash> m_LocalAddresses;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
* 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 WITH_BOB
|
||||
|
||||
#include <string.h>
|
||||
#include "Log.h"
|
||||
#include "ClientContext.h"
|
||||
@@ -704,7 +706,7 @@ namespace client
|
||||
msg += operand;
|
||||
*(const_cast<char *>(value)) = '=';
|
||||
msg += " set to ";
|
||||
msg += value + 1;
|
||||
msg += value;
|
||||
SendReplyOK (msg.c_str ());
|
||||
}
|
||||
else
|
||||
@@ -884,3 +886,4 @@ namespace client
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WITH_BOB
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_BOB
|
||||
|
||||
#ifndef BOB_H__
|
||||
#define BOB_H__
|
||||
|
||||
@@ -277,5 +279,5 @@ namespace client
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_BOB
|
||||
|
||||
@@ -26,8 +26,16 @@ namespace client
|
||||
ClientContext context;
|
||||
|
||||
ClientContext::ClientContext (): m_SharedLocalDestination (nullptr),
|
||||
m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr),
|
||||
m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr)
|
||||
m_HttpProxy (nullptr), m_SocksProxy (nullptr)
|
||||
#ifdef WITH_SAM
|
||||
, m_SamBridge (nullptr)
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
, m_BOBCommandChannel (nullptr)
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
, m_I2CPServer (nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,9 +43,15 @@ namespace client
|
||||
{
|
||||
delete m_HttpProxy;
|
||||
delete m_SocksProxy;
|
||||
#ifdef WITH_SAM
|
||||
delete m_SamBridge;
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
delete m_BOBCommandChannel;
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
delete m_I2CPServer;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClientContext::Start ()
|
||||
@@ -58,6 +72,7 @@ namespace client
|
||||
// I2P tunnels
|
||||
ReadTunnels ();
|
||||
|
||||
#ifdef WITH_SAM
|
||||
// SAM
|
||||
bool sam; i2p::config::GetOption("sam.enabled", sam);
|
||||
if (sam)
|
||||
@@ -77,7 +92,9 @@ namespace client
|
||||
ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOB
|
||||
// BOB
|
||||
bool bob; i2p::config::GetOption("bob.enabled", bob);
|
||||
if (bob) {
|
||||
@@ -95,7 +112,9 @@ namespace client
|
||||
ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
// I2CP
|
||||
bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp);
|
||||
if (i2cp)
|
||||
@@ -115,6 +134,7 @@ namespace client
|
||||
ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_AddressBook.StartResolvers ();
|
||||
|
||||
@@ -158,6 +178,7 @@ namespace client
|
||||
}
|
||||
m_ServerTunnels.clear ();
|
||||
|
||||
#ifdef WITH_SAM
|
||||
if (m_SamBridge)
|
||||
{
|
||||
LogPrint(eLogInfo, "Clients: Stopping SAM bridge");
|
||||
@@ -165,7 +186,9 @@ namespace client
|
||||
delete m_SamBridge;
|
||||
m_SamBridge = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOB
|
||||
if (m_BOBCommandChannel)
|
||||
{
|
||||
LogPrint(eLogInfo, "Clients: Stopping BOB command channel");
|
||||
@@ -173,7 +196,9 @@ namespace client
|
||||
delete m_BOBCommandChannel;
|
||||
m_BOBCommandChannel = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
if (m_I2CPServer)
|
||||
{
|
||||
LogPrint(eLogInfo, "Clients: Stopping I2CP");
|
||||
@@ -181,6 +206,7 @@ namespace client
|
||||
delete m_I2CPServer;
|
||||
m_I2CPServer = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
LogPrint(eLogInfo, "Clients: Stopping AddressBook");
|
||||
m_AddressBook.Stop ();
|
||||
@@ -608,29 +634,21 @@ namespace client
|
||||
if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
|
||||
// udp client
|
||||
// TODO: hostnames
|
||||
boost::asio::ip::udp::endpoint end (boost::asio::ip::address::from_string(address), port);
|
||||
boost::asio::ip::udp::endpoint end(boost::asio::ip::address::from_string(address), port);
|
||||
if (!localDestination)
|
||||
localDestination = m_SharedLocalDestination;
|
||||
|
||||
bool gzip = section.second.get (I2P_CLIENT_TUNNEL_GZIP, true);
|
||||
auto clientTunnel = std::make_shared<I2PUDPClientTunnel> (name, dest, end, localDestination, destinationPort, gzip);
|
||||
auto clientTunnel = std::make_shared<I2PUDPClientTunnel>(name, dest, end, localDestination, destinationPort, gzip);
|
||||
|
||||
auto ins = m_ClientForwards.insert (std::make_pair (end, clientTunnel));
|
||||
auto ins = m_ClientForwards.insert(std::make_pair(end, clientTunnel));
|
||||
if (ins.second)
|
||||
{
|
||||
clientTunnel->Start ();
|
||||
clientTunnel->Start();
|
||||
numClientTunnels++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: update
|
||||
if (ins.first->second->GetLocalDestination () != clientTunnel->GetLocalDestination ())
|
||||
{
|
||||
LogPrint (eLogInfo, "Clients: I2P UDP client tunnel destination updated");
|
||||
ins.first->second->Stop ();
|
||||
ins.first->second->SetLocalDestination (clientTunnel->GetLocalDestination ());
|
||||
ins.first->second->Start ();
|
||||
}
|
||||
ins.first->second->isUpdated = true;
|
||||
LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists");
|
||||
}
|
||||
@@ -898,7 +916,7 @@ namespace client
|
||||
bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy);
|
||||
if (socksproxy)
|
||||
{
|
||||
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
|
||||
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);
|
||||
@@ -984,11 +1002,11 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Write correct UDP tunnels stop
|
||||
/* // TODO: Write correct UDP tunnels stop
|
||||
for (auto it = m_ClientForwards.begin (); it != m_ClientForwards.end ();)
|
||||
{
|
||||
if(clean && !it->second->isUpdated) {
|
||||
it->second->Stop ();
|
||||
it->second = nullptr;
|
||||
it = m_ClientForwards.erase(it);
|
||||
} else {
|
||||
it->second->isUpdated = false;
|
||||
@@ -999,13 +1017,13 @@ namespace client
|
||||
for (auto it = m_ServerForwards.begin (); it != m_ServerForwards.end ();)
|
||||
{
|
||||
if(clean && !it->second->isUpdated) {
|
||||
it->second->Stop ();
|
||||
it->second = nullptr;
|
||||
it = m_ServerForwards.erase(it);
|
||||
} else {
|
||||
it->second->isUpdated = false;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
} */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -18,9 +18,19 @@
|
||||
#include "HTTPProxy.h"
|
||||
#include "SOCKS.h"
|
||||
#include "I2PTunnel.h"
|
||||
|
||||
#ifdef WITH_SAM
|
||||
#include "SAM.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOB
|
||||
#include "BOB.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
#include "I2CP.h"
|
||||
#endif
|
||||
|
||||
#include "AddressBook.h"
|
||||
#include "I18N_langs.h"
|
||||
|
||||
@@ -76,31 +86,45 @@ namespace client
|
||||
void ReloadConfig ();
|
||||
|
||||
std::shared_ptr<ClientDestination> GetSharedLocalDestination () const { return m_SharedLocalDestination; };
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (bool isPublic = false, // transient
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (
|
||||
bool isPublic = false, // transient
|
||||
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
|
||||
const std::map<std::string, std::string> * params = nullptr); // used by SAM only
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
|
||||
bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
|
||||
const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
|
||||
const std::map<std::string, std::string> * params = nullptr);
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
|
||||
const i2p::data::PrivateKeys& keys, bool isPublic = true,
|
||||
const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
|
||||
|
||||
std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
|
||||
const std::string & name, const std::map<std::string, std::string> * params = nullptr);
|
||||
|
||||
void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
|
||||
std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
|
||||
|
||||
bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
|
||||
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
|
||||
|
||||
AddressBook& GetAddressBook () { return m_AddressBook; };
|
||||
#ifdef WITH_BOB
|
||||
const BOBCommandChannel * GetBOBCommandChannel () const { return m_BOBCommandChannel; };
|
||||
#endif
|
||||
#ifdef WITH_SAM
|
||||
const SAMBridge * GetSAMBridge () const { return m_SamBridge; };
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
const I2CPServer * GetI2CPServer () const { return m_I2CPServer; };
|
||||
#endif
|
||||
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > GetForwardInfosFor(const i2p::data::IdentHash & destination);
|
||||
|
||||
@@ -142,16 +166,22 @@ namespace client
|
||||
|
||||
i2p::proxy::HTTPProxy * m_HttpProxy;
|
||||
i2p::proxy::SOCKSProxy * m_SocksProxy;
|
||||
std::map<boost::asio::ip::tcp::endpoint, std::shared_ptr<I2PService> > m_ClientTunnels; // local endpoint -> tunnel
|
||||
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port> -> tunnel
|
||||
std::map<boost::asio::ip::tcp::endpoint, std::shared_ptr<I2PService> > m_ClientTunnels; // local endpoint->tunnel
|
||||
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port>->tunnel
|
||||
|
||||
std::mutex m_ForwardsMutex;
|
||||
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel
|
||||
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PUDPServerTunnel> > m_ServerForwards; // <destination,port> -> udp tunnel
|
||||
|
||||
#ifdef WITH_SAM
|
||||
SAMBridge * m_SamBridge;
|
||||
#endif
|
||||
#ifdef WITH_BOB
|
||||
BOBCommandChannel * m_BOBCommandChannel;
|
||||
#endif
|
||||
#ifdef WITH_I2CP
|
||||
I2CPServer * m_I2CPServer;
|
||||
#endif
|
||||
|
||||
std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer;
|
||||
|
||||
|
||||
@@ -32,13 +32,7 @@
|
||||
|
||||
namespace i2p {
|
||||
namespace proxy {
|
||||
static const std::vector<std::string> jumporder = {
|
||||
"reg.i2p",
|
||||
"stats.i2p",
|
||||
"identiguy.i2p",
|
||||
};
|
||||
|
||||
static const std::map<std::string, std::string> jumpservices = {
|
||||
std::map<std::string, std::string> jumpservices = {
|
||||
{ "reg.i2p", "http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/jump/" },
|
||||
{ "identiguy.i2p", "http://3mzmrus2oron5fxptw7hw2puho3bnqmw2hqy7nw64dsrrjwdilva.b32.i2p/cgi-bin/query?hostname=" },
|
||||
{ "stats.i2p", "http://7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq.b32.i2p/cgi-bin/jump.cgi?a=" },
|
||||
@@ -180,11 +174,8 @@ namespace proxy {
|
||||
<< "<p>" << tr("Remote host not found in router's addressbook") << "</p>\r\n"
|
||||
<< "<p>" << tr("You may try to find this host on jump services below") << ":</p>\r\n"
|
||||
<< "<ul>\r\n";
|
||||
for (const auto& jump : jumporder)
|
||||
{
|
||||
auto js = jumpservices.find (jump);
|
||||
if (js != jumpservices.end())
|
||||
ss << " <li><a href=\"" << js->first << host << "\">" << js->second << "</a></li>\r\n";
|
||||
for (const auto& js : jumpservices) {
|
||||
ss << " <li><a href=\"" << js.second << host << "\">" << js.first << "</a></li>\r\n";
|
||||
}
|
||||
ss << "</ul>\r\n";
|
||||
std::string content = ss.str();
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/rand.h>
|
||||
@@ -24,7 +26,7 @@ namespace client
|
||||
{
|
||||
|
||||
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):
|
||||
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||
LeaseSetDestination (service, isPublic, ¶ms),
|
||||
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()),
|
||||
m_IsCreatingLeaseSet (false), m_LeaseSetCreationTimer (service)
|
||||
@@ -453,8 +455,8 @@ namespace client
|
||||
{
|
||||
auto len = m_SendQueue.Get (m_SendBuffer, I2CP_MAX_MESSAGE_LENGTH);
|
||||
boost::asio::async_write (*socket, boost::asio::buffer (m_SendBuffer, len),
|
||||
boost::asio::transfer_all (),std::bind(&I2CPSession::HandleI2CPMessageSent,
|
||||
shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||
boost::asio::transfer_all (),std::bind(&I2CPSession::HandleI2CPMessageSent,
|
||||
shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
else
|
||||
m_IsSending = false;
|
||||
@@ -524,21 +526,31 @@ namespace client
|
||||
|
||||
void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_Destination || !m_Owner.InsertSession (shared_from_this ()))
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Session already exists");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusRefused); // refused
|
||||
return;
|
||||
}
|
||||
|
||||
RAND_bytes ((uint8_t *)&m_SessionID, 2);
|
||||
auto identity = std::make_shared<i2p::data::IdentityEx>();
|
||||
size_t offset = identity->FromBuffer (buf, len);
|
||||
|
||||
if (!offset)
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Create session malformed identity");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Owner.FindSessionByIdentHash (identity->GetIdentHash ()))
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Create session duplicate address ", identity->GetIdentHash ().ToBase32 ());
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t optionsSize = bufbe16toh (buf + offset);
|
||||
offset += 2;
|
||||
if (optionsSize > len - offset)
|
||||
@@ -547,42 +559,27 @@ namespace client
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> params;
|
||||
ExtractMapping (buf + offset, optionsSize, params);
|
||||
offset += optionsSize; // options
|
||||
if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false;
|
||||
|
||||
offset += 8; // date
|
||||
if (identity->Verify (buf, offset, buf + offset)) // signature
|
||||
{
|
||||
if (!m_Destination)
|
||||
{
|
||||
m_Destination = m_Owner.IsSingleThread () ?
|
||||
std::make_shared<I2CPDestination>(m_Owner.GetService (), shared_from_this (), identity, true, params):
|
||||
std::make_shared<RunnableI2CPDestination>(shared_from_this (), identity, true, params);
|
||||
if (m_Owner.InsertSession (shared_from_this ()))
|
||||
{
|
||||
SendSessionStatusMessage (eI2CPSessionStatusCreated); // created
|
||||
LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " created");
|
||||
m_Destination->Start ();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Session already exists");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusRefused);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Session already exists");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusRefused); // refused
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!identity->Verify (buf, offset, buf + offset)) // signature
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: Create session signature verification failed");
|
||||
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
|
||||
return;
|
||||
}
|
||||
|
||||
m_Destination = m_Owner.IsSingleThread () ?
|
||||
std::make_shared<I2CPDestination>(m_Owner.GetService (), shared_from_this (), identity, true, params):
|
||||
std::make_shared<RunnableI2CPDestination>(shared_from_this (), identity, true, params);
|
||||
|
||||
SendSessionStatusMessage (eI2CPSessionStatusCreated); // created
|
||||
LogPrint (eLogDebug, "I2CP: Session ", m_SessionID, " created");
|
||||
m_Destination->Start ();
|
||||
}
|
||||
|
||||
void I2CPSession::DestroySessionMessageHandler (const uint8_t * buf, size_t len)
|
||||
@@ -712,7 +709,7 @@ namespace client
|
||||
{
|
||||
if (offset + 4 > len) return;
|
||||
uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption type
|
||||
uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length
|
||||
uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length
|
||||
if (offset + keyLen > len) return;
|
||||
if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
|
||||
m_Destination->SetECIESx25519EncryptionPrivateKey (buf + offset);
|
||||
@@ -1040,3 +1037,4 @@ namespace client
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WITH_I2CP
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_I2CP
|
||||
|
||||
#ifndef I2CP_H__
|
||||
#define I2CP_H__
|
||||
|
||||
@@ -249,3 +251,4 @@ namespace client
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_I2CP
|
||||
|
||||
@@ -583,7 +583,7 @@ namespace client
|
||||
{
|
||||
if (m_KeepAliveTimer)
|
||||
{
|
||||
m_KeepAliveTimer->expires_from_now (boost::posix_time::seconds (m_KeepAliveInterval));
|
||||
m_KeepAliveTimer->expires_from_now (boost::posix_time::seconds(m_KeepAliveInterval));
|
||||
m_KeepAliveTimer->async_wait (std::bind (&I2PClientTunnel::HandleKeepAliveTimer,
|
||||
this, std::placeholders::_1));
|
||||
}
|
||||
@@ -796,8 +796,7 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void I2PUDPServerTunnel::ExpireStale(const uint64_t delta)
|
||||
{
|
||||
void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) {
|
||||
std::lock_guard<std::mutex> lock(m_SessionsMutex);
|
||||
uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
|
||||
auto itr = m_Sessions.begin();
|
||||
@@ -809,8 +808,7 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::ExpireStale(const uint64_t delta)
|
||||
{
|
||||
void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) {
|
||||
std::lock_guard<std::mutex> lock(m_SessionsMutex);
|
||||
uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
|
||||
std::vector<uint16_t> removePorts;
|
||||
@@ -866,8 +864,7 @@ namespace client
|
||||
Receive();
|
||||
}
|
||||
|
||||
void UDPSession::Receive()
|
||||
{
|
||||
void UDPSession::Receive() {
|
||||
LogPrint(eLogDebug, "UDPSession: Receive");
|
||||
IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU),
|
||||
FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2));
|
||||
@@ -904,239 +901,230 @@ namespace client
|
||||
LogPrint(eLogError, "UDPSession: ", ecode.message());
|
||||
}
|
||||
|
||||
I2PUDPServerTunnel::I2PUDPServerTunnel (const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
||||
I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
||||
boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip) :
|
||||
m_IsUniqueLocal (true), m_Name (name), m_LocalAddress (localAddress), m_LocalDest (localDestination), m_RemoteEndpoint (forwardTo), m_Gzip (gzip)
|
||||
m_IsUniqueLocal(true),
|
||||
m_Name(name),
|
||||
m_LocalAddress(localAddress),
|
||||
m_RemoteEndpoint(forwardTo)
|
||||
{
|
||||
m_LocalDest = localDestination;
|
||||
m_LocalDest->Start();
|
||||
auto dgram = m_LocalDest->CreateDatagramDestination(gzip);
|
||||
dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||
dgram->SetRawReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
}
|
||||
|
||||
I2PUDPServerTunnel::~I2PUDPServerTunnel ()
|
||||
I2PUDPServerTunnel::~I2PUDPServerTunnel()
|
||||
{
|
||||
Stop ();
|
||||
auto dgram = m_LocalDest->GetDatagramDestination();
|
||||
if (dgram) dgram->ResetReceiver();
|
||||
|
||||
LogPrint(eLogInfo, "UDPServer: Done");
|
||||
}
|
||||
|
||||
void I2PUDPServerTunnel::Start ()
|
||||
void I2PUDPServerTunnel::Start()
|
||||
{
|
||||
m_LocalDest->Start ();
|
||||
|
||||
auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip);
|
||||
dgram->SetReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||
dgram->SetRawReceiver (std::bind (&I2PUDPServerTunnel::HandleRecvFromI2PRaw, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
m_LocalDest->Start();
|
||||
}
|
||||
|
||||
void I2PUDPServerTunnel::Stop ()
|
||||
{
|
||||
auto dgram = m_LocalDest->GetDatagramDestination ();
|
||||
if (dgram) dgram->ResetReceiver ();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPServerTunnel::GetSessions ()
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPServerTunnel::GetSessions()
|
||||
{
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > sessions;
|
||||
std::lock_guard<std::mutex> lock (m_SessionsMutex);
|
||||
std::lock_guard<std::mutex> lock(m_SessionsMutex);
|
||||
|
||||
for (UDPSessionPtr s: m_Sessions)
|
||||
for ( UDPSessionPtr s : m_Sessions )
|
||||
{
|
||||
if (!s->m_Destination) continue;
|
||||
auto info = s->m_Destination->GetInfoForRemote (s->Identity);
|
||||
if (!info) continue;
|
||||
auto info = s->m_Destination->GetInfoForRemote(s->Identity);
|
||||
if(!info) continue;
|
||||
|
||||
auto sinfo = std::make_shared<DatagramSessionInfo> ();
|
||||
auto sinfo = std::make_shared<DatagramSessionInfo>();
|
||||
sinfo->Name = m_Name;
|
||||
sinfo->LocalIdent = std::make_shared<i2p::data::IdentHash> (m_LocalDest->GetIdentHash ().data ());
|
||||
sinfo->RemoteIdent = std::make_shared<i2p::data::IdentHash> (s->Identity.data ());
|
||||
sinfo->LocalIdent = std::make_shared<i2p::data::IdentHash>(m_LocalDest->GetIdentHash().data());
|
||||
sinfo->RemoteIdent = std::make_shared<i2p::data::IdentHash>(s->Identity.data());
|
||||
sinfo->CurrentIBGW = info->IBGW;
|
||||
sinfo->CurrentOBEP = info->OBEP;
|
||||
sessions.push_back (sinfo);
|
||||
sessions.push_back(sinfo);
|
||||
}
|
||||
return sessions;
|
||||
}
|
||||
|
||||
I2PUDPClientTunnel::I2PUDPClientTunnel (const std::string & name, const std::string &remoteDest,
|
||||
I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest,
|
||||
boost::asio::ip::udp::endpoint localEndpoint,
|
||||
std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
||||
uint16_t remotePort, bool gzip) :
|
||||
m_Name (name), m_RemoteDest (remoteDest), m_LocalDest (localDestination), m_LocalEndpoint (localEndpoint),
|
||||
m_RemoteIdent (nullptr), m_ResolveThread (nullptr), m_LocalSocket (nullptr), RemotePort (remotePort),
|
||||
m_LastPort (0), m_cancel_resolve (false), m_Gzip (gzip)
|
||||
m_Name(name),
|
||||
m_RemoteDest(remoteDest),
|
||||
m_LocalDest(localDestination),
|
||||
m_LocalEndpoint(localEndpoint),
|
||||
m_RemoteIdent(nullptr),
|
||||
m_ResolveThread(nullptr),
|
||||
m_LocalSocket(localDestination->GetService(), localEndpoint),
|
||||
RemotePort(remotePort), m_LastPort (0),
|
||||
m_cancel_resolve(false)
|
||||
{
|
||||
}
|
||||
m_LocalSocket.set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU));
|
||||
m_LocalSocket.set_option (boost::asio::socket_base::reuse_address (true));
|
||||
|
||||
I2PUDPClientTunnel::~I2PUDPClientTunnel ()
|
||||
{
|
||||
Stop ();
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::Start ()
|
||||
{
|
||||
// Reset flag in case of tunnel reload
|
||||
if (m_cancel_resolve) m_cancel_resolve = false;
|
||||
|
||||
m_LocalSocket.reset (new boost::asio::ip::udp::socket (m_LocalDest->GetService (), m_LocalEndpoint));
|
||||
m_LocalSocket->set_option (boost::asio::socket_base::receive_buffer_size (I2P_UDP_MAX_MTU));
|
||||
m_LocalSocket->set_option (boost::asio::socket_base::reuse_address (true));
|
||||
|
||||
auto dgram = m_LocalDest->CreateDatagramDestination (m_Gzip);
|
||||
dgram->SetReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2P, this,
|
||||
auto dgram = m_LocalDest->CreateDatagramDestination(gzip);
|
||||
dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3, std::placeholders::_4,
|
||||
std::placeholders::_5));
|
||||
dgram->SetRawReceiver (std::bind (&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this,
|
||||
dgram->SetRawReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this,
|
||||
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
}
|
||||
|
||||
m_LocalDest->Start ();
|
||||
void I2PUDPClientTunnel::Start() {
|
||||
m_LocalDest->Start();
|
||||
if (m_ResolveThread == nullptr)
|
||||
m_ResolveThread = new std::thread (std::bind (&I2PUDPClientTunnel::TryResolving, this));
|
||||
RecvFromLocal ();
|
||||
m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this));
|
||||
RecvFromLocal();
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::Stop ()
|
||||
void I2PUDPClientTunnel::RecvFromLocal()
|
||||
{
|
||||
auto dgram = m_LocalDest->GetDatagramDestination ();
|
||||
if (dgram) dgram->ResetReceiver ();
|
||||
m_cancel_resolve = true;
|
||||
|
||||
m_Sessions.clear();
|
||||
|
||||
if(m_LocalSocket && m_LocalSocket->is_open ())
|
||||
m_LocalSocket->close ();
|
||||
|
||||
if(m_ResolveThread)
|
||||
{
|
||||
m_ResolveThread->join ();
|
||||
delete m_ResolveThread;
|
||||
m_ResolveThread = nullptr;
|
||||
}
|
||||
if (m_RemoteIdent)
|
||||
{
|
||||
delete m_RemoteIdent;
|
||||
m_RemoteIdent = nullptr;
|
||||
}
|
||||
m_LocalSocket.async_receive_from(boost::asio::buffer(m_RecvBuff, I2P_UDP_MAX_MTU),
|
||||
m_RecvEndpoint, std::bind(&I2PUDPClientTunnel::HandleRecvFromLocal, this, std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::RecvFromLocal ()
|
||||
void I2PUDPClientTunnel::HandleRecvFromLocal(const boost::system::error_code & ec, std::size_t transferred)
|
||||
{
|
||||
m_LocalSocket->async_receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU),
|
||||
m_RecvEndpoint, std::bind (&I2PUDPClientTunnel::HandleRecvFromLocal, this, std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::HandleRecvFromLocal (const boost::system::error_code & ec, std::size_t transferred)
|
||||
{
|
||||
if (m_cancel_resolve) {
|
||||
LogPrint (eLogDebug, "UDP Client: Ignoring incomming data: stopping");
|
||||
if(m_cancel_resolve) {
|
||||
LogPrint(eLogDebug, "UDP Client: Ignoring incomming data: stopping");
|
||||
return;
|
||||
}
|
||||
if (ec) {
|
||||
LogPrint (eLogError, "UDP Client: Reading from socket error: ", ec.message (), ". Restarting listener...");
|
||||
RecvFromLocal (); // Restart listener and continue work
|
||||
if(ec) {
|
||||
LogPrint(eLogError, "UDP Client: Reading from socket error: ", ec.message(), ". Restarting listener...");
|
||||
RecvFromLocal(); // Restart listener and continue work
|
||||
return;
|
||||
}
|
||||
if (!m_RemoteIdent) {
|
||||
LogPrint (eLogWarning, "UDP Client: Remote endpoint not resolved yet");
|
||||
RecvFromLocal ();
|
||||
if(!m_RemoteIdent) {
|
||||
LogPrint(eLogWarning, "UDP Client: Remote endpoint not resolved yet");
|
||||
RecvFromLocal();
|
||||
return; // drop, remote not resolved
|
||||
}
|
||||
auto remotePort = m_RecvEndpoint.port ();
|
||||
auto remotePort = m_RecvEndpoint.port();
|
||||
if (!m_LastPort || m_LastPort != remotePort)
|
||||
{
|
||||
auto itr = m_Sessions.find (remotePort);
|
||||
if (itr != m_Sessions.end ())
|
||||
auto itr = m_Sessions.find(remotePort);
|
||||
if (itr != m_Sessions.end())
|
||||
m_LastSession = itr->second;
|
||||
else
|
||||
{
|
||||
m_LastSession = std::make_shared<UDPConvo> (boost::asio::ip::udp::endpoint (m_RecvEndpoint), 0);
|
||||
m_LastSession = std::make_shared<UDPConvo>(boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0);
|
||||
m_Sessions.emplace (remotePort, m_LastSession);
|
||||
}
|
||||
m_LastPort = remotePort;
|
||||
}
|
||||
// send off to remote i2p destination
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
LogPrint (eLogDebug, "UDP Client: Send ", transferred, " to ", m_RemoteIdent->ToBase32 (), ":", RemotePort);
|
||||
auto session = m_LocalDest->GetDatagramDestination ()->GetSession (*m_RemoteIdent);
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||
LogPrint(eLogDebug, "UDP Client: Send ", transferred, " to ", m_RemoteIdent->ToBase32(), ":", RemotePort);
|
||||
auto session = m_LocalDest->GetDatagramDestination()->GetSession (*m_RemoteIdent);
|
||||
if (ts > m_LastSession->second + I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL)
|
||||
m_LocalDest->GetDatagramDestination ()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
m_LocalDest->GetDatagramDestination()->SendDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
else
|
||||
m_LocalDest->GetDatagramDestination ()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
size_t numPackets = 0;
|
||||
while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
size_t moreBytes = m_LocalSocket->available (ec);
|
||||
size_t moreBytes = m_LocalSocket.available(ec);
|
||||
if (ec || !moreBytes) break;
|
||||
transferred = m_LocalSocket->receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec);
|
||||
remotePort = m_RecvEndpoint.port ();
|
||||
transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec);
|
||||
remotePort = m_RecvEndpoint.port();
|
||||
// TODO: check remotePort
|
||||
m_LocalDest->GetDatagramDestination ()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
|
||||
numPackets++;
|
||||
}
|
||||
if (numPackets)
|
||||
LogPrint (eLogDebug, "UDP Client: Sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32 ());
|
||||
m_LocalDest->GetDatagramDestination ()->FlushSendQueue (session);
|
||||
LogPrint(eLogDebug, "UDP Client: Sent ", numPackets, " more packets to ", m_RemoteIdent->ToBase32());
|
||||
m_LocalDest->GetDatagramDestination()->FlushSendQueue (session);
|
||||
|
||||
// mark convo as active
|
||||
if (m_LastSession)
|
||||
m_LastSession->second = ts;
|
||||
RecvFromLocal ();
|
||||
RecvFromLocal();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPClientTunnel::GetSessions ()
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPClientTunnel::GetSessions()
|
||||
{
|
||||
// TODO: implement
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > infos;
|
||||
return infos;
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::TryResolving ()
|
||||
{
|
||||
i2p::util::SetThreadName ("UDP Resolver");
|
||||
LogPrint (eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest);
|
||||
void I2PUDPClientTunnel::TryResolving() {
|
||||
i2p::util::SetThreadName("UDP Resolver");
|
||||
LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest);
|
||||
|
||||
std::shared_ptr<const Address> addr;
|
||||
while (!(addr = context.GetAddressBook().GetAddress(m_RemoteDest)) && !m_cancel_resolve)
|
||||
while(!(addr = context.GetAddressBook().GetAddress(m_RemoteDest)) && !m_cancel_resolve)
|
||||
{
|
||||
LogPrint (eLogWarning, "UDP Tunnel: Failed to lookup ", m_RemoteDest);
|
||||
std::this_thread::sleep_for (std::chrono::seconds (1));
|
||||
LogPrint(eLogWarning, "UDP Tunnel: Failed to lookup ", m_RemoteDest);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
if (m_cancel_resolve)
|
||||
if(m_cancel_resolve)
|
||||
{
|
||||
LogPrint(eLogError, "UDP Tunnel: Lookup of ", m_RemoteDest, " was cancelled");
|
||||
return;
|
||||
}
|
||||
if (!addr || !addr->IsIdentHash ())
|
||||
{
|
||||
LogPrint (eLogError, "UDP Tunnel: ", m_RemoteDest, " not found");
|
||||
LogPrint(eLogError, "UDP Tunnel: ", m_RemoteDest, " not found");
|
||||
return;
|
||||
}
|
||||
m_RemoteIdent = new i2p::data::IdentHash;
|
||||
*m_RemoteIdent = addr->identHash;
|
||||
LogPrint(eLogInfo, "UDP Tunnel: Resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32 ());
|
||||
LogPrint(eLogInfo, "UDP Tunnel: Resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32());
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
|
||||
void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent)
|
||||
if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent)
|
||||
HandleRecvFromI2PRaw (fromPort, toPort, buf, len);
|
||||
else
|
||||
LogPrint(eLogWarning, "UDP Client: Unwarranted traffic from ", from.GetIdentHash().ToBase32 ());
|
||||
LogPrint(eLogWarning, "UDP Client: Unwarranted traffic from ", from.GetIdentHash().ToBase32());
|
||||
}
|
||||
|
||||
void I2PUDPClientTunnel::HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
|
||||
void I2PUDPClientTunnel::HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
|
||||
{
|
||||
auto itr = m_Sessions.find (toPort);
|
||||
auto itr = m_Sessions.find(toPort);
|
||||
// found convo ?
|
||||
if (itr != m_Sessions.end ())
|
||||
if(itr != m_Sessions.end())
|
||||
{
|
||||
// found convo
|
||||
if (len > 0)
|
||||
{
|
||||
LogPrint (eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32 () : "");
|
||||
m_LocalSocket->send_to (boost::asio::buffer (buf, len), itr->second->first);
|
||||
LogPrint(eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32() : "");
|
||||
m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second->first);
|
||||
// mark convo as active
|
||||
itr->second->second = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
itr->second->second = i2p::util::GetMillisecondsSinceEpoch();
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort);
|
||||
LogPrint(eLogWarning, "UDP Client: Not tracking udp session using port ", (int) toPort);
|
||||
}
|
||||
|
||||
I2PUDPClientTunnel::~I2PUDPClientTunnel()
|
||||
{
|
||||
auto dgram = m_LocalDest->GetDatagramDestination();
|
||||
if (dgram) dgram->ResetReceiver();
|
||||
m_cancel_resolve = true;
|
||||
|
||||
m_Sessions.clear();
|
||||
|
||||
if(m_LocalSocket.is_open())
|
||||
m_LocalSocket.close();
|
||||
|
||||
if(m_ResolveThread)
|
||||
{
|
||||
m_ResolveThread->join();
|
||||
delete m_ResolveThread;
|
||||
m_ResolveThread = nullptr;
|
||||
}
|
||||
if (m_RemoteIdent) delete m_RemoteIdent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace client
|
||||
const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
|
||||
const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
|
||||
// for HTTP tunnels
|
||||
const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64
|
||||
const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64
|
||||
const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
|
||||
const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace client
|
||||
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
|
||||
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API
|
||||
I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
|
||||
I2PTunnelConnection (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, bool quiet = true); // from I2P
|
||||
~I2PTunnelConnection ();
|
||||
void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0);
|
||||
@@ -230,27 +230,25 @@ namespace client
|
||||
{
|
||||
public:
|
||||
|
||||
I2PUDPServerTunnel (const std::string & name,
|
||||
I2PUDPServerTunnel(const std::string & name,
|
||||
std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
||||
boost::asio::ip::address localAddress,
|
||||
boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip);
|
||||
~I2PUDPServerTunnel ();
|
||||
|
||||
~I2PUDPServerTunnel();
|
||||
/** expire stale udp conversations */
|
||||
void ExpireStale (const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
|
||||
void Start ();
|
||||
void Stop ();
|
||||
const char * GetName () const { return m_Name.c_str(); }
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions ();
|
||||
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
|
||||
void Start();
|
||||
const char * GetName() const { return m_Name.c_str(); }
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions();
|
||||
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
|
||||
|
||||
void SetUniqueLocal (bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
|
||||
void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
|
||||
|
||||
private:
|
||||
|
||||
void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
|
||||
UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
|
||||
|
||||
private:
|
||||
|
||||
@@ -262,7 +260,6 @@ namespace client
|
||||
std::vector<UDPSessionPtr> m_Sessions;
|
||||
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
|
||||
UDPSessionPtr m_LastSession;
|
||||
bool m_Gzip;
|
||||
|
||||
public:
|
||||
|
||||
@@ -273,36 +270,27 @@ namespace client
|
||||
{
|
||||
public:
|
||||
|
||||
I2PUDPClientTunnel (const std::string & name, const std::string &remoteDest,
|
||||
I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest,
|
||||
boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
||||
uint16_t remotePort, bool gzip);
|
||||
~I2PUDPClientTunnel ();
|
||||
~I2PUDPClientTunnel();
|
||||
void Start();
|
||||
const char * GetName() const { return m_Name.c_str(); }
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions();
|
||||
|
||||
void Start ();
|
||||
void Stop ();
|
||||
const char * GetName () const { return m_Name.c_str(); }
|
||||
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions ();
|
||||
|
||||
bool IsLocalDestination (const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); }
|
||||
bool IsLocalDestination(const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); }
|
||||
|
||||
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
|
||||
inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest)
|
||||
{
|
||||
if (m_LocalDest) m_LocalDest->Release ();
|
||||
if (dest) dest->Acquire ();
|
||||
m_LocalDest = dest;
|
||||
}
|
||||
|
||||
void ExpireStale (const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
|
||||
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
|
||||
|
||||
private:
|
||||
|
||||
typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
|
||||
void RecvFromLocal ();
|
||||
void HandleRecvFromLocal (const boost::system::error_code & e, std::size_t transferred);
|
||||
void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
void TryResolving ();
|
||||
void RecvFromLocal();
|
||||
void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred);
|
||||
void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
void HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
void TryResolving();
|
||||
|
||||
private:
|
||||
|
||||
@@ -314,12 +302,11 @@ namespace client
|
||||
const boost::asio::ip::udp::endpoint m_LocalEndpoint;
|
||||
i2p::data::IdentHash * m_RemoteIdent;
|
||||
std::thread * m_ResolveThread;
|
||||
std::unique_ptr<boost::asio::ip::udp::socket> m_LocalSocket;
|
||||
boost::asio::ip::udp::socket m_LocalSocket;
|
||||
boost::asio::ip::udp::endpoint m_RecvEndpoint;
|
||||
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
|
||||
uint16_t RemotePort, m_LastPort;
|
||||
bool m_cancel_resolve;
|
||||
bool m_Gzip;
|
||||
std::shared_ptr<UDPConvo> m_LastSession;
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2022, 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 WITH_SAM
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _MSC_VER
|
||||
@@ -154,11 +156,7 @@ namespace client
|
||||
|
||||
if (SAMVersionAcceptable(version))
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||
#endif
|
||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (),
|
||||
std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (),
|
||||
std::placeholders::_1, std::placeholders::_2));
|
||||
@@ -465,11 +463,7 @@ namespace client
|
||||
size_t l = session->GetLocalDestination ()->GetPrivateKeys ().ToBuffer (buf, 1024);
|
||||
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024);
|
||||
priv[l1] = 0;
|
||||
#ifdef _MSC_VER
|
||||
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||
#else
|
||||
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l2, false);
|
||||
}
|
||||
}
|
||||
@@ -710,13 +704,8 @@ namespace client
|
||||
}
|
||||
}
|
||||
auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType);
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
||||
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
||||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
||||
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l, false);
|
||||
}
|
||||
|
||||
@@ -754,11 +743,7 @@ namespace client
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "SAM: Naming failed, unknown address ", name);
|
||||
#ifdef _MSC_VER
|
||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, false);
|
||||
}
|
||||
}
|
||||
@@ -833,11 +818,7 @@ namespace client
|
||||
void SAMSocket::SendI2PError(const std::string & msg)
|
||||
{
|
||||
LogPrint (eLogError, "SAM: I2P error: ", msg);
|
||||
#ifdef _MSC_VER
|
||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
|
||||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, true);
|
||||
}
|
||||
|
||||
@@ -851,11 +832,7 @@ namespace client
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "SAM: Naming lookup failed. LeaseSet for ", name, " not found");
|
||||
#ifdef _MSC_VER
|
||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#else
|
||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, len, false);
|
||||
}
|
||||
}
|
||||
@@ -863,11 +840,7 @@ namespace client
|
||||
void SAMSocket::SendNamingLookupReply (const std::string& name, std::shared_ptr<const i2p::data::IdentityEx> identity)
|
||||
{
|
||||
auto base64 = identity->ToBase64 ();
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ());
|
||||
#else
|
||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ());
|
||||
#endif
|
||||
SendMessageReply (m_Buffer, l, false);
|
||||
}
|
||||
|
||||
@@ -1078,7 +1051,7 @@ namespace client
|
||||
auto s = shared_from_this ();
|
||||
newSocket->GetSocket ().async_connect (ep,
|
||||
[s, newSocket, stream](const boost::system::error_code& ecode)
|
||||
{
|
||||
{
|
||||
if (!ecode)
|
||||
{
|
||||
s->m_Owner.AddSocket (newSocket);
|
||||
@@ -1121,11 +1094,7 @@ namespace client
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
||||
#else
|
||||
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
||||
#endif
|
||||
if (len < SAM_SOCKET_BUFFER_SIZE - l)
|
||||
{
|
||||
memcpy (m_StreamBuffer + l, buf, len);
|
||||
@@ -1149,11 +1118,7 @@ namespace client
|
||||
m_Owner.SendTo({ {buf, len} }, *ep);
|
||||
else
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len);
|
||||
#else
|
||||
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_RAW_RECEIVED, (long unsigned int)len);
|
||||
#endif
|
||||
if (len < SAM_SOCKET_BUFFER_SIZE - l)
|
||||
{
|
||||
memcpy (m_StreamBuffer + l, buf, len);
|
||||
@@ -1528,3 +1493,4 @@ namespace client
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WITH_SAM
|
||||
@@ -6,6 +6,8 @@
|
||||
* See full license text in LICENSE file at top of project tree
|
||||
*/
|
||||
|
||||
#ifdef WITH_SAM
|
||||
|
||||
#ifndef SAM_H__
|
||||
#define SAM_H__
|
||||
|
||||
@@ -286,3 +288,4 @@ namespace client
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // WITH_SAM
|
||||
Reference in New Issue
Block a user