Compare commits

..

1 Commits

Author SHA1 Message Date
R4SAS
3ab5ac66b6 modulize client protocols
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-03 17:20:19 +03:00
88 changed files with 1213 additions and 1532 deletions

View File

@@ -1,11 +1,6 @@
name: Build containers name: Build containers
on: on: [push]
push:
branches:
- openssl
tags:
- '*'
jobs: jobs:
docker: docker:
@@ -63,8 +58,6 @@ jobs:
push: true push: true
tags: | tags: |
purplei2p/i2pd:latest purplei2p/i2pd:latest
purplei2p/i2pd:latest-release
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
ghcr.io/purplei2p/i2pd:latest ghcr.io/purplei2p/i2pd:latest
ghcr.io/purplei2p/i2pd:latest-release
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}

View File

@@ -1,36 +1,6 @@
# for this file format description, # for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog # 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 ## [2.41.0] - 2022-02-20
### Added ### Added
- Clock syncronization through SSU - Clock syncronization through SSU

View File

@@ -40,6 +40,12 @@ USE_GIT_VERSION := $(or $(USE_GIT_VERSION),no)
# for MacOS only, waiting for "1", not "yes" # for MacOS only, waiting for "1", not "yes"
HOMEBREW := $(or $(HOMEBREW),0) 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) ifeq ($(DEBUG),yes)
CXX_DEBUG = -g CXX_DEBUG = -g
else else
@@ -47,6 +53,19 @@ else
LD_DEBUG = -s LD_DEBUG = -s
endif 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))) ifneq (, $(findstring darwin, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
ifeq ($(HOMEBREW),1) ifeq ($(HOMEBREW),1)

View File

@@ -110,8 +110,8 @@ port = 7070
# user = i2pd # user = i2pd
# pass = changeme # pass = changeme
## Select webconsole language ## Select webconsole language
## Currently supported english (default), afrikaans, armenian, french, german, ## Currently supported english (default), afrikaans, armenian, german, russian,
## russian, turkmen, ukrainian and uzbek languages ## turkmen, ukrainian and uzbek languages
# lang = english # lang = english
[httpproxy] [httpproxy]

View File

@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7) %define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git Name: i2pd-git
Version: 2.42.0 Version: 2.41.0
Release: git%{git_hash}%{?dist} Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd Conflicts: i2pd
@@ -164,9 +164,6 @@ getent passwd i2pd >/dev/null || \
%changelog %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 * Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
- update to 2.41.0 - update to 2.41.0
- fixed build on Fedora Copr over openssl trunk code - fixed build on Fedora Copr over openssl trunk code

View File

@@ -1,5 +1,5 @@
Name: i2pd Name: i2pd
Version: 2.42.0 Version: 2.41.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd-git Conflicts: i2pd-git
@@ -161,9 +161,6 @@ getent passwd i2pd >/dev/null || \
%changelog %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 * Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
- update to 2.41.0 - update to 2.41.0

View File

@@ -26,7 +26,9 @@
#include "Streaming.h" #include "Streaming.h"
#include "Destination.h" #include "Destination.h"
#include "HTTPServer.h" #include "HTTPServer.h"
#ifdef WITH_I2PC
#include "I2PControl.h" #include "I2PControl.h"
#endif
#include "ClientContext.h" #include "ClientContext.h"
#include "Crypto.h" #include "Crypto.h"
#include "UPnP.h" #include "UPnP.h"
@@ -45,7 +47,9 @@ namespace util
~Daemon_Singleton_Private() {}; ~Daemon_Singleton_Private() {};
std::unique_ptr<i2p::http::HTTPServer> httpServer; std::unique_ptr<i2p::http::HTTPServer> httpServer;
#ifdef WITH_I2PC
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService; std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
#endif
std::unique_ptr<i2p::transport::UPnP> UPnP; std::unique_ptr<i2p::transport::UPnP> UPnP;
std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync; std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
}; };
@@ -441,6 +445,7 @@ namespace util
LogPrint(eLogInfo, "Daemon: Starting Client"); LogPrint(eLogInfo, "Daemon: Starting Client");
i2p::client::context.Start (); i2p::client::context.Start ();
#ifdef WITH_I2PC
// I2P Control Protocol // I2P Control Protocol
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
if (i2pcontrol) { if (i2pcontrol) {
@@ -458,6 +463,7 @@ namespace util
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ()); ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
} }
} }
#endif
return true; return true;
} }
@@ -490,12 +496,14 @@ namespace util
d.httpServer->Stop(); d.httpServer->Stop();
d.httpServer = nullptr; d.httpServer = nullptr;
} }
#ifdef WITH_I2PC
if (d.m_I2PControlService) if (d.m_I2PControlService)
{ {
LogPrint(eLogInfo, "Daemon: Stopping I2PControl"); LogPrint(eLogInfo, "Daemon: Stopping I2PControl");
d.m_I2PControlService->Stop (); d.m_I2PControlService->Stop ();
d.m_I2PControlService = nullptr; d.m_I2PControlService = nullptr;
} }
#endif
i2p::crypto::TerminateCrypto (); i2p::crypto::TerminateCrypto ();
i2p::log::Logger().Stop(); i2p::log::Logger().Stop();

View File

@@ -68,9 +68,13 @@ namespace http {
const char HTTP_PAGE_TRANSPORTS[] = "transports"; const char HTTP_PAGE_TRANSPORTS[] = "transports";
const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations"; const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations";
const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination"; const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination";
#ifdef WITH_I2CP
const char HTTP_PAGE_I2CP_LOCAL_DESTINATION[] = "i2cp_local_destination"; 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_SESSIONS[] = "sam_sessions";
const char HTTP_PAGE_SAM_SESSION[] = "sam_session"; const char HTTP_PAGE_SAM_SESSION[] = "sam_session";
#endif
const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels"; const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels";
const char HTTP_PAGE_COMMANDS[] = "commands"; const char HTTP_PAGE_COMMANDS[] = "commands";
const char HTTP_PAGE_LEASESETS[] = "leasesets"; 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_GET_REG_STRING[] = "get_reg_string";
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage"; const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css"; const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
#ifdef WITH_SAM
const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
#endif
const char HTTP_PARAM_ADDRESS[] = "address"; const char HTTP_PARAM_ADDRESS[] = "address";
static std::string ConvertTime (uint64_t time) static std::string ConvertTime (uint64_t time)
@@ -202,8 +208,10 @@ namespace http {
s << s <<
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr ("Transports") << "</a><br>\r\n" " <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"; " <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">" << tr("I2P tunnels") << "</a><br>\r\n";
#ifdef WITH_SAM
if (i2p::client::context.GetSAMBridge ()) if (i2p::client::context.GetSAMBridge ())
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">" << tr("SAM sessions") << "</a><br>\r\n"; s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">" << tr("SAM sessions") << "</a><br>\r\n";
#endif
s << s <<
"</div>\r\n" "</div>\r\n"
"<div class=\"content\">"; "<div class=\"content\">";
@@ -361,17 +369,25 @@ namespace http {
if (outputFormat==OutputFormatEnum::forWebConsole) { if (outputFormat==OutputFormatEnum::forWebConsole) {
bool httpproxy = i2p::client::context.GetHttpProxy () ? true : false; bool httpproxy = i2p::client::context.GetHttpProxy () ? true : false;
bool socksproxy = i2p::client::context.GetSocksProxy () ? 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 << "<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>" << "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"; 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"; 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"; 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"; 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"; 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"; s << "</tbody></table>\r\n";
} }
} }
@@ -388,6 +404,7 @@ namespace http {
} }
s << "</div>\r\n"; s << "</div>\r\n";
#ifdef WITH_I2CP
auto i2cpServer = i2p::client::context.GetI2CPServer (); auto i2cpServer = i2p::client::context.GetI2CPServer ();
if (i2cpServer && !(i2cpServer->GetSessions ().empty ())) if (i2cpServer && !(i2cpServer->GetSessions ().empty ()))
{ {
@@ -405,6 +422,7 @@ namespace http {
} }
s << "</div>\r\n"; s << "</div>\r\n";
} }
#endif
} }
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token) 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) void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
{ {
auto i2cpServer = i2p::client::context.GetI2CPServer (); auto i2cpServer = i2p::client::context.GetI2CPServer ();
@@ -587,6 +606,7 @@ namespace http {
else else
ShowError(s, tr("I2CP is not enabled")); ShowError(s, tr("I2CP is not enabled"));
} }
#endif
void ShowLeasesSets(std::stringstream& s) void ShowLeasesSets(std::stringstream& s)
{ {
@@ -879,6 +899,7 @@ namespace http {
} }
} }
#ifdef WITH_SAM
void ShowSAMSessions (std::stringstream& s) void ShowSAMSessions (std::stringstream& s)
{ {
std::string webroot; i2p::config::GetOption("http.webroot", webroot); std::string webroot; i2p::config::GetOption("http.webroot", webroot);
@@ -941,6 +962,7 @@ namespace http {
} }
s << "</div>\r\n"; s << "</div>\r\n";
} }
#endif
void ShowI2PTunnels (std::stringstream& s) void ShowI2PTunnels (std::stringstream& s)
{ {
@@ -1194,12 +1216,16 @@ namespace http {
uint32_t token = CreateToken (); uint32_t token = CreateToken ();
ShowLocalDestination (s, params["b32"], token); ShowLocalDestination (s, params["b32"], token);
} }
#ifdef WITH_I2CP
else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION) else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION)
ShowI2CPLocalDestination (s, params["i2cp_id"]); ShowI2CPLocalDestination (s, params["i2cp_id"]);
#endif
#ifdef WITH_SAM
else if (page == HTTP_PAGE_SAM_SESSIONS) else if (page == HTTP_PAGE_SAM_SESSIONS)
ShowSAMSessions (s); ShowSAMSessions (s);
else if (page == HTTP_PAGE_SAM_SESSION) else if (page == HTTP_PAGE_SAM_SESSION)
ShowSAMSession (s, params["sam_id"]); ShowSAMSession (s, params["sam_id"]);
#endif
else if (page == HTTP_PAGE_I2P_TUNNELS) else if (page == HTTP_PAGE_I2P_TUNNELS)
ShowI2PTunnels (s); ShowI2PTunnels (s);
else if (page == HTTP_PAGE_LEASESETS) else if (page == HTTP_PAGE_LEASESETS)

View File

@@ -95,11 +95,15 @@ namespace http
void ShowTunnels (std::stringstream& s); void ShowTunnels (std::stringstream& s);
void ShowTransitTunnels (std::stringstream& s); void ShowTransitTunnels (std::stringstream& s);
void ShowTransports (std::stringstream& s); void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s); void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token); 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); void ShowSAMSession (std::stringstream& s, const std::string& id);
#endif
#ifdef WITH_I2CP
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id); void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
#endif
} // http } // http
} // i2p } // i2p

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_I2PC
#include <stdio.h> #include <stdio.h>
#include <sstream> #include <sstream>
#include <openssl/x509.h> #include <openssl/x509.h>
@@ -104,9 +106,15 @@ namespace client
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler; m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler; m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler; m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
#ifdef WITH_SAM
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler; m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
#endif
#ifdef WITH_BOB
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler; m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
#endif
#ifdef WITH_I2CP
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler; m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
#endif
} }
I2PControlService::~I2PControlService () I2PControlService::~I2PControlService ()
@@ -346,7 +354,6 @@ namespace client
} }
// handlers // handlers
void I2PControlService::AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results) void I2PControlService::AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{ {
int api = params.get<int> ("API"); int api = params.get<int> ("API");
@@ -372,7 +379,6 @@ namespace client
// I2PControl // I2PControl
void I2PControlService::I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results) void I2PControlService::I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{ {
for (auto& it: params) for (auto& it: params)
@@ -613,7 +619,6 @@ namespace client
} }
// ClientServicesInfo // ClientServicesInfo
void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{ {
for (auto it = params.begin (); it != params.end (); it++) for (auto it = params.begin (); it != params.end (); it++)
@@ -719,6 +724,7 @@ namespace client
InsertParam (results, "SOCKS", pt); InsertParam (results, "SOCKS", pt);
} }
#ifdef WITH_SAM
void I2PControlService::SAMInfoHandler (std::ostringstream& results) void I2PControlService::SAMInfoHandler (std::ostringstream& results)
{ {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
@@ -754,7 +760,9 @@ namespace client
InsertParam (results, "SAM", pt); InsertParam (results, "SAM", pt);
} }
#endif // WITH_SAM
#ifdef WITH_BOB
void I2PControlService::BOBInfoHandler (std::ostringstream& results) void I2PControlService::BOBInfoHandler (std::ostringstream& results)
{ {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
@@ -769,7 +777,9 @@ namespace client
InsertParam (results, "BOB", pt); InsertParam (results, "BOB", pt);
} }
#endif // WITH_BOB
#ifdef WITH_I2CP
void I2PControlService::I2CPInfoHandler (std::ostringstream& results) void I2PControlService::I2CPInfoHandler (std::ostringstream& results)
{ {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
@@ -784,5 +794,7 @@ namespace client
InsertParam (results, "I2CP", pt); InsertParam (results, "I2CP", pt);
} }
#endif // WITH_I2CP
} }
} }
#endif // WITH_I2PC

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_I2PC
#ifndef I2P_CONTROL_H__ #ifndef I2P_CONTROL_H__
#define I2P_CONTROL_H__ #define I2P_CONTROL_H__
@@ -114,9 +116,15 @@ namespace client
void I2PTunnelInfoHandler (std::ostringstream& results); void I2PTunnelInfoHandler (std::ostringstream& results);
void HTTPProxyInfoHandler (std::ostringstream& results); void HTTPProxyInfoHandler (std::ostringstream& results);
void SOCKSInfoHandler (std::ostringstream& results); void SOCKSInfoHandler (std::ostringstream& results);
#ifdef WITH_SAM
void SAMInfoHandler (std::ostringstream& results); void SAMInfoHandler (std::ostringstream& results);
#endif
#ifdef WITH_BOB
void BOBInfoHandler (std::ostringstream& results); void BOBInfoHandler (std::ostringstream& results);
#endif
#ifdef WITH_I2CP
void I2CPInfoHandler (std::ostringstream& results); void I2CPInfoHandler (std::ostringstream& results);
#endif
private: private:
@@ -141,3 +149,4 @@ namespace client
} }
#endif #endif
#endif // WITH_I2PC

6
debian/changelog vendored
View File

@@ -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 i2pd (2.41.0-1) unstable; urgency=medium
* updated to version 2.41.0/0.9.53 * updated to version 2.41.0/0.9.53

View File

@@ -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

View File

@@ -74,7 +74,6 @@ namespace i18n
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace armenian { 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 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 german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace russian { 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 (); } namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
@@ -89,7 +88,6 @@ namespace i18n
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} }, { "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
{ "armenian", {"հայերէն", "hy", i2p::i18n::armenian::GetLocale} }, { "armenian", {"հայերէն", "hy", i2p::i18n::armenian::GetLocale} },
{ "english", {"English", "en", i2p::i18n::english::GetLocale} }, { "english", {"English", "en", i2p::i18n::english::GetLocale} },
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} }, { "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
{ "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} }, { "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} },
{ "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} }, { "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },

View File

@@ -24,7 +24,7 @@ namespace data {
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); 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); size_t Base64EncodingBufferSize(const size_t input_size);

View File

@@ -29,9 +29,7 @@
#include "CPU.h" #include "CPU.h"
// recognize openssl version and features // recognize openssl version and features
#if (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x3050200fL)) // LibreSSL 3.5.2 and above #if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# 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 LEGACY_OPENSSL 1
# define X509_getm_notBefore X509_get_notBefore # define X509_getm_notBefore X509_get_notBefore
# define X509_getm_notAfter X509_get_notAfter # define X509_getm_notAfter X509_get_notAfter
@@ -41,7 +39,7 @@
# define OPENSSL_HKDF 1 # define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1 # define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1 # define OPENSSL_X25519 1
# if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash # if (OPENSSL_VERSION_NUMBER < 0x030000000) // 3.0.0, regression in SipHash
# define OPENSSL_SIPHASH 1 # define OPENSSL_SIPHASH 1
# endif # endif
# endif # endif

View File

@@ -13,6 +13,7 @@
#include <vector> #include <vector>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include "Crypto.h" #include "Crypto.h"
#include "Config.h"
#include "Log.h" #include "Log.h"
#include "FS.h" #include "FS.h"
#include "Timestamp.h" #include "Timestamp.h"
@@ -93,7 +94,9 @@ namespace client
if (it != params->end ()) if (it != params->end ())
{ {
// oveeride isPublic // 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); it = params->find (I2CP_PARAM_LEASESET_TYPE);
if (it != params->end ()) if (it != params->end ())
@@ -951,7 +954,7 @@ namespace client
for (auto& it: encryptionKeyTypes) for (auto& it: encryptionKeyTypes)
{ {
auto encryptionKey = new EncryptionKey (it); auto encryptionKey = new EncryptionKey (it);
if (IsPublic ()) if (isPublic)
PersistTemporaryKeys (encryptionKey, isSingleKey); PersistTemporaryKeys (encryptionKey, isSingleKey);
else else
encryptionKey->GenerateKeys (); encryptionKey->GenerateKeys ();
@@ -966,7 +969,7 @@ namespace client
m_StandardEncryptionKey.reset (encryptionKey); m_StandardEncryptionKey.reset (encryptionKey);
} }
if (IsPublic ()) if (isPublic)
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
try try
@@ -979,7 +982,7 @@ namespace client
m_StreamingAckDelay = std::stoi(it->second); m_StreamingAckDelay = std::stoi(it->second);
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ()) 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) if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{ {

View File

@@ -319,5 +319,4 @@ namespace client
} }
} }
#endif #endif

View File

@@ -128,8 +128,8 @@ namespace data
}; };
/** /**
* validate lease set buffer signature and extract expiration timestamp validate lease set buffer signature and extract expiration timestamp
* @returns true if the leaseset is well formed and signature is valid @returns true if the leaseset is well formed and signature is valid
*/ */
bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires); bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires);

View File

@@ -107,10 +107,7 @@ namespace data
{ {
i2p::util::SetThreadName("NetDB"); i2p::util::SetThreadName("NetDB");
uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch ();
int16_t profilesCleanupVariance = 0;
while (m_IsRunning) while (m_IsRunning)
{ {
try try
@@ -158,7 +155,6 @@ namespace data
m_Requests.ManageRequests (); m_Requests.ManageRequests ();
lastManageRequest = ts; lastManageRequest = ts;
} }
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
{ {
if (lastSave) if (lastSave)
@@ -168,20 +164,12 @@ namespace data
} }
lastSave = ts; lastSave = ts;
} }
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
{ {
i2p::context.CleanupDestination (); i2p::context.CleanupDestination ();
lastDestinationCleanup = ts; 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 // publish
if (!m_HiddenMode && i2p::transport::transports.IsOnline ()) if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
{ {
@@ -207,7 +195,6 @@ namespace data
lastPublish = ts; lastPublish = ts;
} }
} }
if (ts - lastExploratory >= 30) // exploratory every 30 seconds if (ts - lastExploratory >= 30) // exploratory every 30 seconds
{ {
auto numRouters = m_RouterInfos.size (); auto numRouters = m_RouterInfos.size ();

View File

@@ -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" #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 #if !OPENSSL_AEAD_CHACHA20_POLY1305
namespace i2p namespace i2p

View File

@@ -5,7 +5,6 @@
* Kovri go write your own code * Kovri go write your own code
* *
*/ */
#ifndef LIBI2PD_POLY1305_H #ifndef LIBI2PD_POLY1305_H
#define LIBI2PD_POLY1305_H #define LIBI2PD_POLY1305_H
#include <cstdint> #include <cstdint>

View File

@@ -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 * 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 char PEER_PROFILE_USAGE_REJECTED[] = "rejected";
const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days) 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 class RouterProfile
{ {

View File

@@ -102,9 +102,6 @@ namespace transport
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize); payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize);
// send // send
m_RelaySessions.emplace (nonce, std::make_pair (session, ts)); 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); SendData (payload, payloadSize);
return true; return true;
@@ -391,7 +388,7 @@ namespace transport
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
size_t payloadSize = 7; size_t payloadSize = 7;
payloadSize += CreateAddressBlock (payload + payloadSize, 64 - payloadSize, m_RemoteEndpoint); payloadSize += CreateAddressBlock (m_RemoteEndpoint, payload + payloadSize, 64 - payloadSize);
if (m_RelayTag) if (m_RelayTag)
{ {
payload[payloadSize] = eSSU2BlkRelayTag; payload[payloadSize] = eSSU2BlkRelayTag;
@@ -473,12 +470,25 @@ namespace transport
memset (header.h.flags, 0, 3); memset (header.h.flags, 0, 3);
header.h.flags[0] = 1; // frag, total fragments always 1 header.h.flags[0] = 1; // frag, total fragments always 1
// payload // payload
const size_t maxPayloadSize = SSU2_MAX_PAYLOAD_SIZE - 48; // part 2 uint8_t payload[SSU2_MTU];
uint8_t payload[maxPayloadSize + 16]; size_t payloadSize = i2p::context.GetRouterInfo ().GetBufferLen ();
size_t payloadSize = CreateRouterInfoBlock (payload, maxPayloadSize, i2p::context.GetSharedRouterInfo ()); payload[0] = eSSU2BlkRouterInfo;
// TODO: check is RouterInfo doesn't fit and split by two fragments if (payloadSize < 1024)
if (payloadSize < maxPayloadSize) {
payloadSize += CreatePaddingBlock (payload + payloadSize, maxPayloadSize - payloadSize); 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 // KDF for Session Confirmed part 1
m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header) m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header)
// Encrypt part 1 // Encrypt part 1
@@ -698,7 +708,7 @@ namespace transport
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
size_t payloadSize = 7; 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); payloadSize += CreatePaddingBlock (payload + payloadSize, 64 - payloadSize);
// encrypt // encrypt
uint8_t nonce[12]; uint8_t nonce[12];
@@ -748,116 +758,6 @@ namespace transport
return true; 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) uint32_t SSU2Session::SendData (const uint8_t * buf, size_t len)
{ {
if (len < 8) if (len < 8)
@@ -977,12 +877,8 @@ namespace transport
HandleRelayResponse (buf + offset, size); HandleRelayResponse (buf + offset, size);
break; break;
case eSSU2BlkRelayIntro: case eSSU2BlkRelayIntro:
LogPrint (eLogDebug, "SSU2: RelayIntro");
HandleRelayIntro (buf + offset, size);
break; break;
case eSSU2BlkPeerTest: case eSSU2BlkPeerTest:
LogPrint (eLogDebug, "SSU2: PeerTest");
HandlePeerTest (buf + offset, size);
break; break;
case eSSU2BlkNextNonce: case eSSU2BlkNextNonce:
break; break;
@@ -1067,7 +963,7 @@ namespace transport
if (it == m_SentPackets.end ()) return; // not found if (it == m_SentPackets.end ()) return; // not found
auto it1 = it; auto it1 = it;
while (it1 != m_SentPackets.end () && it1->first <= lastPacketNum) it1++; 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); m_SentPackets.erase (it, it1);
} }
@@ -1183,14 +1079,9 @@ namespace transport
std::make_pair (shared_from_this (), i2p::util::GetSecondsSinceEpoch ()) ); std::make_pair (shared_from_this (), i2p::util::GetSecondsSinceEpoch ()) );
// send relay intro to Charlie // send relay intro to Charlie
auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ()); // Alice's RI uint8_t payload[SSU2_MTU];
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE]; size_t payloadSize = CreateRelayIntroBlock (payload, SSU2_MTU, buf + 1, len -1);
size_t payloadSize = r ? CreateRouterInfoBlock (payload, SSU2_MAX_PAYLOAD_SIZE - len - 32, r) : 0; payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MTU - payloadSize);
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);
session->SendData (payload, payloadSize); session->SendData (payload, payloadSize);
} }
@@ -1217,28 +1108,19 @@ namespace transport
} }
// send relay response to Bob // send relay response to Bob
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE]; uint8_t payload[SSU2_MTU];
size_t payloadSize = CreateRelayResponseBlock (payload, SSU2_MAX_PAYLOAD_SIZE, bufbe32toh (buf + 33)); size_t payloadSize = CreateRelayResponseBlock (payload, SSU2_MTU, bufbe32toh (buf + 33));
payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize); payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MTU - payloadSize);
SendData (payload, payloadSize); SendData (payload, payloadSize);
// send HolePunch // send HolePunch
boost::asio::ip::udp::endpoint ep; boost::asio::ip::udp::endpoint ep;
if (ExtractEndpoint (buf + 47, asz, ep)) if (ExtractEndpoint (buf + 47, asz, ep))
{ m_Server.SendHolePunch (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);
}
}
} }
void SSU2Session::HandleRelayResponse (const uint8_t * buf, size_t len) 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 auto it = m_RelaySessions.find (bufbe32toh (buf + 2)); // nonce
if (it != m_RelaySessions.end ()) if (it != m_RelaySessions.end ())
{ {
@@ -1259,8 +1141,7 @@ namespace transport
if (s.Verify (it->second.first->GetRemoteIdentity (), buf + 12 + csz)) if (s.Verify (it->second.first->GetRemoteIdentity (), buf + 12 + csz))
{ {
// update Charlie's endpoint and connect // update Charlie's endpoint and connect
if (it->second.first->m_State == eSSU2SessionStateIntroduced && if (ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint))
ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint))
{ {
it->second.first->m_State = eSSU2SessionStateUnknown; it->second.first->m_State = eSSU2SessionStateUnknown;
it->second.first->Connect (); it->second.first->Connect ();
@@ -1278,41 +1159,6 @@ namespace transport
LogPrint (eLogWarning, "SSU2: RelayResponse unknown nonce ", bufbe32toh (buf + 2)); 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) bool SSU2Session::ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep)
{ {
if (size < 2) return false; if (size < 2) return false;
@@ -1361,7 +1207,7 @@ namespace transport
return size; 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; if (len < 9) return 0;
buf[0] = eSSU2BlkAddress; buf[0] = eSSU2BlkAddress;
@@ -1371,28 +1217,6 @@ namespace transport
return size + 3; 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) size_t SSU2Session::CreateAckBlock (uint8_t * buf, size_t len)
{ {
if (len < 8) return 0; if (len < 8) return 0;
@@ -1541,21 +1365,6 @@ namespace transport
return payloadSize + 3; 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) std::shared_ptr<const i2p::data::RouterInfo> SSU2Session::ExtractRouterInfo (const uint8_t * buf, size_t size)
{ {
if (size < 2) return nullptr; if (size < 2) return nullptr;
@@ -1644,22 +1453,12 @@ namespace transport
{ {
if (ts > it->second.second + SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT) 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); it = m_RelaySessions.erase (it);
} }
else else
++it; ++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 () void SSU2Session::FlushData ()
@@ -1933,25 +1732,10 @@ namespace transport
} }
if (m_LastSession) if (m_LastSession)
{ {
switch (m_LastSession->GetState ()) if (m_LastSession->IsEstablished ())
{
case eSSU2SessionStateEstablished:
m_LastSession->ProcessData (buf, len); m_LastSession->ProcessData (buf, len);
break; else
case eSSU2SessionStateUnknown:
m_LastSession->ProcessSessionConfirmed (buf, len); 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 ());
}
} }
else else
{ {
@@ -2014,6 +1798,18 @@ namespace transport
LogPrint (eLogError, "SSU2: Send exception: ", ec.message (), " to ", to); 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, bool SSU2Server::CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address) std::shared_ptr<const i2p::data::RouterInfo::Address> address)
{ {
@@ -2055,7 +1851,7 @@ namespace transport
for (auto& it: address->ssu->introducers) for (auto& it: address->ssu->introducers)
{ {
r = i2p::data::netdb.FindRouter (it.iKey); r = i2p::data::netdb.FindRouter (it.iKey);
if (r && r->IsReachableFrom (i2p::context.GetRouterInfo ())) if (r)
{ {
relayTag = it.iTag; relayTag = it.iTag;
if (relayTag) break; if (relayTag) break;

View File

@@ -28,7 +28,6 @@ namespace transport
const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // in seconds const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // in seconds
const int SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT = 10; // 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_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K
const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K
const size_t SSU2_MTU = 1488; const size_t SSU2_MTU = 1488;
@@ -44,10 +43,8 @@ namespace transport
eSSU2SessionCreated = 1, eSSU2SessionCreated = 1,
eSSU2SessionConfirmed = 2, eSSU2SessionConfirmed = 2,
eSSU2Data = 6, eSSU2Data = 6,
eSSU2PeerTest = 7,
eSSU2Retry = 9, eSSU2Retry = 9,
eSSU2TokenRequest = 10, eSSU2TokenRequest = 10
eSSU2HolePunch = 11
}; };
enum SSU2BlockType enum SSU2BlockType
@@ -80,7 +77,6 @@ namespace transport
{ {
eSSU2SessionStateUnknown, eSSU2SessionStateUnknown,
eSSU2SessionStateIntroduced, eSSU2SessionStateIntroduced,
eSSU2SessionStatePeerTest,
eSSU2SessionStateEstablished, eSSU2SessionStateEstablished,
eSSU2SessionStateTerminated, eSSU2SessionStateTerminated,
eSSU2SessionStateFailed eSSU2SessionStateFailed
@@ -166,8 +162,6 @@ namespace transport
bool ProcessSessionCreated (uint8_t * buf, size_t len); bool ProcessSessionCreated (uint8_t * buf, size_t len);
bool ProcessSessionConfirmed (uint8_t * buf, size_t len); bool ProcessSessionConfirmed (uint8_t * buf, size_t len);
bool ProcessRetry (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); void ProcessData (uint8_t * buf, size_t len);
private: private:
@@ -189,7 +183,6 @@ namespace transport
uint32_t SendData (const uint8_t * buf, size_t len); // returns packet num uint32_t SendData (const uint8_t * buf, size_t len); // returns packet num
void SendQuickAck (); void SendQuickAck ();
void SendTermination (); 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 HandlePayload (const uint8_t * buf, size_t len);
void HandleAck (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 HandleRelayRequest (const uint8_t * buf, size_t len);
void HandleRelayIntro (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 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 CreateAddressBlock (const boost::asio::ip::udp::endpoint& ep, uint8_t * buf, size_t len);
size_t CreateRouterInfoBlock (uint8_t * buf, size_t len, std::shared_ptr<const i2p::data::RouterInfo> r);
size_t CreateAckBlock (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 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); 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 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 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 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: 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<SentPacket> > m_SentPackets; // packetNum -> packet
std::map<uint32_t, std::shared_ptr<SSU2IncompleteMessage> > m_IncompleteMessages; // I2NP 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_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; std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
i2p::I2NPMessagesHandler m_Handler; i2p::I2NPMessagesHandler m_Handler;
bool m_IsDataReceived; bool m_IsDataReceived;
@@ -284,6 +273,7 @@ namespace transport
const boost::asio::ip::udp::endpoint& to); const boost::asio::ip::udp::endpoint& to);
void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, 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); 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, bool CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address); std::shared_ptr<const i2p::data::RouterInfo::Address> address);

View File

@@ -1285,13 +1285,7 @@ namespace stream
auto it = m_Streams.find (recvStreamID); auto it = m_Streams.find (recvStreamID);
if (it == m_Streams.end ()) if (it == m_Streams.end ())
return false; return false;
auto s = it->second; DeleteStream (it->second);
m_Owner->GetService ().post ([this, s] ()
{
s->Close (); // try to send FIN
s->Terminate (false);
DeleteStream (s);
});
return true; return true;
} }

View File

@@ -32,6 +32,10 @@
#include <iphlpapi.h> #include <iphlpapi.h>
#include <shlobj.h> #include <shlobj.h>
#ifdef _MSC_VER
#pragma comment(lib, "IPHLPAPI.lib")
#endif // _MSC_VER
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

View File

@@ -16,7 +16,7 @@
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c) #define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
#define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 42 #define I2PD_VERSION_MINOR 41
#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0 #define I2PD_VERSION_PATCH 0
#ifdef GITVER #ifdef GITVER
@@ -31,7 +31,7 @@
#define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9 #define I2P_VERSION_MINOR 9
#define I2P_VERSION_MICRO 54 #define I2P_VERSION_MICRO 53
#define I2P_VERSION_PATCH 0 #define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #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) #define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_BOB
#include <string.h> #include <string.h>
#include "Log.h" #include "Log.h"
#include "ClientContext.h" #include "ClientContext.h"
@@ -704,7 +706,7 @@ namespace client
msg += operand; msg += operand;
*(const_cast<char *>(value)) = '='; *(const_cast<char *>(value)) = '=';
msg += " set to "; msg += " set to ";
msg += value + 1; msg += value;
SendReplyOK (msg.c_str ()); SendReplyOK (msg.c_str ());
} }
else else
@@ -884,3 +886,4 @@ namespace client
} }
} }
} }
#endif // WITH_BOB

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_BOB
#ifndef BOB_H__ #ifndef BOB_H__
#define BOB_H__ #define BOB_H__
@@ -277,5 +279,5 @@ namespace client
}; };
} }
} }
#endif #endif
#endif // WITH_BOB

View File

@@ -26,8 +26,16 @@ namespace client
ClientContext context; ClientContext context;
ClientContext::ClientContext (): m_SharedLocalDestination (nullptr), ClientContext::ClientContext (): m_SharedLocalDestination (nullptr),
m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr), m_HttpProxy (nullptr), m_SocksProxy (nullptr)
m_BOBCommandChannel (nullptr), m_I2CPServer (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_HttpProxy;
delete m_SocksProxy; delete m_SocksProxy;
#ifdef WITH_SAM
delete m_SamBridge; delete m_SamBridge;
#endif
#ifdef WITH_BOB
delete m_BOBCommandChannel; delete m_BOBCommandChannel;
#endif
#ifdef WITH_I2CP
delete m_I2CPServer; delete m_I2CPServer;
#endif
} }
void ClientContext::Start () void ClientContext::Start ()
@@ -58,6 +72,7 @@ namespace client
// I2P tunnels // I2P tunnels
ReadTunnels (); ReadTunnels ();
#ifdef WITH_SAM
// SAM // SAM
bool sam; i2p::config::GetOption("sam.enabled", sam); bool sam; i2p::config::GetOption("sam.enabled", sam);
if (sam) if (sam)
@@ -77,7 +92,9 @@ namespace client
ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ()); ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ());
} }
} }
#endif
#ifdef WITH_BOB
// BOB // BOB
bool bob; i2p::config::GetOption("bob.enabled", bob); bool bob; i2p::config::GetOption("bob.enabled", bob);
if (bob) { if (bob) {
@@ -95,7 +112,9 @@ namespace client
ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ()); ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ());
} }
} }
#endif
#ifdef WITH_I2CP
// I2CP // I2CP
bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp); bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp);
if (i2cp) if (i2cp)
@@ -115,6 +134,7 @@ namespace client
ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ()); ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ());
} }
} }
#endif
m_AddressBook.StartResolvers (); m_AddressBook.StartResolvers ();
@@ -158,6 +178,7 @@ namespace client
} }
m_ServerTunnels.clear (); m_ServerTunnels.clear ();
#ifdef WITH_SAM
if (m_SamBridge) if (m_SamBridge)
{ {
LogPrint(eLogInfo, "Clients: Stopping SAM bridge"); LogPrint(eLogInfo, "Clients: Stopping SAM bridge");
@@ -165,7 +186,9 @@ namespace client
delete m_SamBridge; delete m_SamBridge;
m_SamBridge = nullptr; m_SamBridge = nullptr;
} }
#endif
#ifdef WITH_BOB
if (m_BOBCommandChannel) if (m_BOBCommandChannel)
{ {
LogPrint(eLogInfo, "Clients: Stopping BOB command channel"); LogPrint(eLogInfo, "Clients: Stopping BOB command channel");
@@ -173,7 +196,9 @@ namespace client
delete m_BOBCommandChannel; delete m_BOBCommandChannel;
m_BOBCommandChannel = nullptr; m_BOBCommandChannel = nullptr;
} }
#endif
#ifdef WITH_I2CP
if (m_I2CPServer) if (m_I2CPServer)
{ {
LogPrint(eLogInfo, "Clients: Stopping I2CP"); LogPrint(eLogInfo, "Clients: Stopping I2CP");
@@ -181,6 +206,7 @@ namespace client
delete m_I2CPServer; delete m_I2CPServer;
m_I2CPServer = nullptr; m_I2CPServer = nullptr;
} }
#endif
LogPrint(eLogInfo, "Clients: Stopping AddressBook"); LogPrint(eLogInfo, "Clients: Stopping AddressBook");
m_AddressBook.Stop (); m_AddressBook.Stop ();
@@ -623,14 +649,6 @@ namespace client
} }
else 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; ins.first->second->isUpdated = true;
LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists");
} }
@@ -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 ();) for (auto it = m_ClientForwards.begin (); it != m_ClientForwards.end ();)
{ {
if(clean && !it->second->isUpdated) { if(clean && !it->second->isUpdated) {
it->second->Stop (); it->second = nullptr;
it = m_ClientForwards.erase(it); it = m_ClientForwards.erase(it);
} else { } else {
it->second->isUpdated = false; it->second->isUpdated = false;
@@ -999,13 +1017,13 @@ namespace client
for (auto it = m_ServerForwards.begin (); it != m_ServerForwards.end ();) for (auto it = m_ServerForwards.begin (); it != m_ServerForwards.end ();)
{ {
if(clean && !it->second->isUpdated) { if(clean && !it->second->isUpdated) {
it->second->Stop (); it->second = nullptr;
it = m_ServerForwards.erase(it); it = m_ServerForwards.erase(it);
} else { } else {
it->second->isUpdated = false; it->second->isUpdated = false;
it++; it++;
} }
} } */
} }
} }
} }

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -18,9 +18,19 @@
#include "HTTPProxy.h" #include "HTTPProxy.h"
#include "SOCKS.h" #include "SOCKS.h"
#include "I2PTunnel.h" #include "I2PTunnel.h"
#ifdef WITH_SAM
#include "SAM.h" #include "SAM.h"
#endif
#ifdef WITH_BOB
#include "BOB.h" #include "BOB.h"
#endif
#ifdef WITH_I2CP
#include "I2CP.h" #include "I2CP.h"
#endif
#include "AddressBook.h" #include "AddressBook.h"
#include "I18N_langs.h" #include "I18N_langs.h"
@@ -76,31 +86,45 @@ namespace client
void ReloadConfig (); void ReloadConfig ();
std::shared_ptr<ClientDestination> GetSharedLocalDestination () const { return m_SharedLocalDestination; }; 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::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
const std::map<std::string, std::string> * params = nullptr); // used by SAM only const std::map<std::string, std::string> * params = nullptr); // used by SAM only
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service, 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, 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, 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 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, std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
const std::map<std::string, std::string> * params = nullptr); const std::map<std::string, std::string> * params = nullptr);
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service, std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
const i2p::data::PrivateKeys& keys, bool isPublic = true, 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 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, std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
const std::string & name, const std::map<std::string, std::string> * params = nullptr); const std::string & name, const std::map<std::string, std::string> * params = nullptr);
void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination); void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const; std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
AddressBook& GetAddressBook () { return m_AddressBook; }; AddressBook& GetAddressBook () { return m_AddressBook; };
#ifdef WITH_BOB
const BOBCommandChannel * GetBOBCommandChannel () const { return m_BOBCommandChannel; }; const BOBCommandChannel * GetBOBCommandChannel () const { return m_BOBCommandChannel; };
#endif
#ifdef WITH_SAM
const SAMBridge * GetSAMBridge () const { return m_SamBridge; }; const SAMBridge * GetSAMBridge () const { return m_SamBridge; };
#endif
#ifdef WITH_I2CP
const I2CPServer * GetI2CPServer () const { return m_I2CPServer; }; const I2CPServer * GetI2CPServer () const { return m_I2CPServer; };
#endif
std::vector<std::shared_ptr<DatagramSessionInfo> > GetForwardInfosFor(const i2p::data::IdentHash & destination); std::vector<std::shared_ptr<DatagramSessionInfo> > GetForwardInfosFor(const i2p::data::IdentHash & destination);
@@ -149,9 +173,15 @@ namespace client
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel 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 std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PUDPServerTunnel> > m_ServerForwards; // <destination,port> -> udp tunnel
#ifdef WITH_SAM
SAMBridge * m_SamBridge; SAMBridge * m_SamBridge;
#endif
#ifdef WITH_BOB
BOBCommandChannel * m_BOBCommandChannel; BOBCommandChannel * m_BOBCommandChannel;
#endif
#ifdef WITH_I2CP
I2CPServer * m_I2CPServer; I2CPServer * m_I2CPServer;
#endif
std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer; std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer;

View File

@@ -32,13 +32,7 @@
namespace i2p { namespace i2p {
namespace proxy { namespace proxy {
static const std::vector<std::string> jumporder = { std::map<std::string, std::string> jumpservices = {
"reg.i2p",
"stats.i2p",
"identiguy.i2p",
};
static const std::map<std::string, std::string> jumpservices = {
{ "reg.i2p", "http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/jump/" }, { "reg.i2p", "http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/jump/" },
{ "identiguy.i2p", "http://3mzmrus2oron5fxptw7hw2puho3bnqmw2hqy7nw64dsrrjwdilva.b32.i2p/cgi-bin/query?hostname=" }, { "identiguy.i2p", "http://3mzmrus2oron5fxptw7hw2puho3bnqmw2hqy7nw64dsrrjwdilva.b32.i2p/cgi-bin/query?hostname=" },
{ "stats.i2p", "http://7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq.b32.i2p/cgi-bin/jump.cgi?a=" }, { "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("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" << "<p>" << tr("You may try to find this host on jump services below") << ":</p>\r\n"
<< "<ul>\r\n"; << "<ul>\r\n";
for (const auto& jump : jumporder) for (const auto& js : jumpservices) {
{ ss << " <li><a href=\"" << js.second << host << "\">" << js.first << "</a></li>\r\n";
auto js = jumpservices.find (jump);
if (js != jumpservices.end())
ss << " <li><a href=\"" << js->first << host << "\">" << js->second << "</a></li>\r\n";
} }
ss << "</ul>\r\n"; ss << "</ul>\r\n";
std::string content = ss.str(); std::string content = ss.str();

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_I2CP
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <openssl/rand.h> #include <openssl/rand.h>
@@ -524,21 +526,31 @@ namespace client
void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) 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); RAND_bytes ((uint8_t *)&m_SessionID, 2);
auto identity = std::make_shared<i2p::data::IdentityEx>(); auto identity = std::make_shared<i2p::data::IdentityEx>();
size_t offset = identity->FromBuffer (buf, len); size_t offset = identity->FromBuffer (buf, len);
if (!offset) if (!offset)
{ {
LogPrint (eLogError, "I2CP: Create session malformed identity"); LogPrint (eLogError, "I2CP: Create session malformed identity");
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
return; return;
} }
if (m_Owner.FindSessionByIdentHash (identity->GetIdentHash ())) if (m_Owner.FindSessionByIdentHash (identity->GetIdentHash ()))
{ {
LogPrint (eLogError, "I2CP: Create session duplicate address ", identity->GetIdentHash ().ToBase32 ()); LogPrint (eLogError, "I2CP: Create session duplicate address ", identity->GetIdentHash ().ToBase32 ());
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
return; return;
} }
uint16_t optionsSize = bufbe16toh (buf + offset); uint16_t optionsSize = bufbe16toh (buf + offset);
offset += 2; offset += 2;
if (optionsSize > len - offset) if (optionsSize > len - offset)
@@ -547,42 +559,27 @@ namespace client
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid
return; return;
} }
std::map<std::string, std::string> params; std::map<std::string, std::string> params;
ExtractMapping (buf + offset, optionsSize, params); ExtractMapping (buf + offset, optionsSize, params);
offset += optionsSize; // options offset += optionsSize; // options
if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false; if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false;
offset += 8; // date offset += 8; // date
if (identity->Verify (buf, offset, buf + offset)) // signature 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
{ {
LogPrint (eLogError, "I2CP: Create session signature verification failed"); LogPrint (eLogError, "I2CP: Create session signature verification failed");
SendSessionStatusMessage (eI2CPSessionStatusInvalid); // invalid 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) void I2CPSession::DestroySessionMessageHandler (const uint8_t * buf, size_t len)
@@ -1040,3 +1037,4 @@ namespace client
} }
} }
} }
#endif // WITH_I2CP

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_I2CP
#ifndef I2CP_H__ #ifndef I2CP_H__
#define I2CP_H__ #define I2CP_H__
@@ -249,3 +251,4 @@ namespace client
} }
#endif #endif
#endif // WITH_I2CP

View File

@@ -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); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
auto itr = m_Sessions.begin(); 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); std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
std::vector<uint16_t> removePorts; std::vector<uint16_t> removePorts;
@@ -866,8 +864,7 @@ namespace client
Receive(); Receive();
} }
void UDPSession::Receive() void UDPSession::Receive() {
{
LogPrint(eLogDebug, "UDPSession: Receive"); LogPrint(eLogDebug, "UDPSession: Receive");
IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), 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)); FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2));
@@ -906,28 +903,29 @@ namespace client
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) : 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(); 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));
}
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()
@@ -956,67 +954,38 @@ namespace client
boost::asio::ip::udp::endpoint localEndpoint, boost::asio::ip::udp::endpoint localEndpoint,
std::shared_ptr<i2p::client::ClientDestination> localDestination, std::shared_ptr<i2p::client::ClientDestination> localDestination,
uint16_t remotePort, bool gzip) : uint16_t remotePort, bool gzip) :
m_Name (name), m_RemoteDest (remoteDest), m_LocalDest (localDestination), m_LocalEndpoint (localEndpoint), m_Name(name),
m_RemoteIdent (nullptr), m_ResolveThread (nullptr), m_LocalSocket (nullptr), RemotePort (remotePort), m_RemoteDest(remoteDest),
m_LastPort (0), m_cancel_resolve (false), m_Gzip (gzip) 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 () auto dgram = m_LocalDest->CreateDatagramDestination(gzip);
{
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, dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4, std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5)); 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)); std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
}
void I2PUDPClientTunnel::Start() {
m_LocalDest->Start(); m_LocalDest->Start();
if (m_ResolveThread == nullptr) if (m_ResolveThread == nullptr)
m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this));
RecvFromLocal(); RecvFromLocal();
} }
void I2PUDPClientTunnel::Stop ()
{
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;
}
}
void I2PUDPClientTunnel::RecvFromLocal() void I2PUDPClientTunnel::RecvFromLocal()
{ {
m_LocalSocket->async_receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), 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)); m_RecvEndpoint, std::bind(&I2PUDPClientTunnel::HandleRecvFromLocal, this, std::placeholders::_1, std::placeholders::_2));
} }
@@ -1061,9 +1030,9 @@ namespace client
while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE) while (numPackets < i2p::datagram::DATAGRAM_SEND_QUEUE_MAX_SIZE)
{ {
boost::system::error_code ec; boost::system::error_code ec;
size_t moreBytes = m_LocalSocket->available (ec); size_t moreBytes = m_LocalSocket.available(ec);
if (ec || !moreBytes) break; if (ec || !moreBytes) break;
transferred = m_LocalSocket->receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec); transferred = m_LocalSocket.receive_from (boost::asio::buffer (m_RecvBuff, I2P_UDP_MAX_MTU), m_RecvEndpoint, 0, ec);
remotePort = m_RecvEndpoint.port(); remotePort = m_RecvEndpoint.port();
// TODO: check remotePort // TODO: check remotePort
m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort); m_LocalDest->GetDatagramDestination()->SendRawDatagram (session, m_RecvBuff, transferred, remotePort, RemotePort);
@@ -1086,8 +1055,7 @@ namespace client
return infos; return infos;
} }
void I2PUDPClientTunnel::TryResolving () void I2PUDPClientTunnel::TryResolving() {
{
i2p::util::SetThreadName("UDP Resolver"); i2p::util::SetThreadName("UDP Resolver");
LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest);
@@ -1130,7 +1098,7 @@ namespace client
if (len > 0) if (len > 0)
{ {
LogPrint(eLogDebug, "UDP Client: Got ", len, "B from ", m_RemoteIdent ? m_RemoteIdent->ToBase32() : ""); 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); m_LocalSocket.send_to(boost::asio::buffer(buf, len), itr->second->first);
// mark convo as active // mark convo as active
itr->second->second = i2p::util::GetMillisecondsSinceEpoch(); itr->second->second = i2p::util::GetMillisecondsSinceEpoch();
} }
@@ -1138,5 +1106,25 @@ namespace client
else 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;
}
} }
} }

View File

@@ -235,11 +235,9 @@ namespace client
boost::asio::ip::address localAddress, boost::asio::ip::address localAddress,
boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip); boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip);
~I2PUDPServerTunnel(); ~I2PUDPServerTunnel();
/** expire stale udp conversations */ /** expire stale udp conversations */
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
void Start(); void Start();
void Stop ();
const char * GetName() const { return m_Name.c_str(); } const char * GetName() const { return m_Name.c_str(); }
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions(); std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions();
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; } std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
@@ -262,7 +260,6 @@ namespace client
std::vector<UDPSessionPtr> m_Sessions; std::vector<UDPSessionPtr> m_Sessions;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest; std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
UDPSessionPtr m_LastSession; UDPSessionPtr m_LastSession;
bool m_Gzip;
public: public:
@@ -277,22 +274,13 @@ namespace client
boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination,
uint16_t remotePort, bool gzip); uint16_t remotePort, bool gzip);
~I2PUDPClientTunnel(); ~I2PUDPClientTunnel();
void Start(); void Start();
void Stop ();
const char * GetName() const { return m_Name.c_str(); } const char * GetName() const { return m_Name.c_str(); }
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions(); 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; } 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: private:
@@ -314,12 +302,11 @@ namespace client
const boost::asio::ip::udp::endpoint m_LocalEndpoint; const boost::asio::ip::udp::endpoint m_LocalEndpoint;
i2p::data::IdentHash * m_RemoteIdent; i2p::data::IdentHash * m_RemoteIdent;
std::thread * m_ResolveThread; 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; boost::asio::ip::udp::endpoint m_RecvEndpoint;
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU]; uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
uint16_t RemotePort, m_LastPort; uint16_t RemotePort, m_LastPort;
bool m_cancel_resolve; bool m_cancel_resolve;
bool m_Gzip;
std::shared_ptr<UDPConvo> m_LastSession; std::shared_ptr<UDPConvo> m_LastSession;
public: public:

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_SAM
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER #ifdef _MSC_VER
@@ -154,11 +156,7 @@ namespace client
if (SAMVersionAcceptable(version)) 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 ()); 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 (), boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (),
std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (), std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
@@ -465,11 +463,7 @@ namespace client
size_t l = session->GetLocalDestination ()->GetPrivateKeys ().ToBuffer (buf, 1024); size_t l = session->GetLocalDestination ()->GetPrivateKeys ().ToBuffer (buf, 1024);
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024);
priv[l1] = 0; 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); size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
#endif
SendMessageReply (m_Buffer, l2, false); SendMessageReply (m_Buffer, l2, false);
} }
} }
@@ -710,13 +704,8 @@ namespace client
} }
} }
auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType); 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, size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ()); keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
#endif
SendMessageReply (m_Buffer, l, false); SendMessageReply (m_Buffer, l, false);
} }
@@ -754,11 +743,7 @@ namespace client
else else
{ {
LogPrint (eLogError, "SAM: Naming failed, unknown address ", name); 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()); size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
#endif
SendMessageReply (m_Buffer, len, false); SendMessageReply (m_Buffer, len, false);
} }
} }
@@ -833,11 +818,7 @@ namespace client
void SAMSocket::SendI2PError(const std::string & msg) void SAMSocket::SendI2PError(const std::string & msg)
{ {
LogPrint (eLogError, "SAM: I2P error: ", 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()); size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
#endif
SendMessageReply (m_Buffer, len, true); SendMessageReply (m_Buffer, len, true);
} }
@@ -851,11 +832,7 @@ namespace client
else else
{ {
LogPrint (eLogError, "SAM: Naming lookup failed. LeaseSet for ", name, " not found"); 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()); size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
#endif
SendMessageReply (m_Buffer, len, false); 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) void SAMSocket::SendNamingLookupReply (const std::string& name, std::shared_ptr<const i2p::data::IdentityEx> identity)
{ {
auto base64 = identity->ToBase64 (); 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 ()); 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); SendMessageReply (m_Buffer, l, false);
} }
@@ -1121,11 +1094,7 @@ namespace client
} }
else 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); 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) if (len < SAM_SOCKET_BUFFER_SIZE - l)
{ {
memcpy (m_StreamBuffer + l, buf, len); memcpy (m_StreamBuffer + l, buf, len);
@@ -1149,11 +1118,7 @@ namespace client
m_Owner.SendTo({ {buf, len} }, *ep); m_Owner.SendTo({ {buf, len} }, *ep);
else 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); 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) if (len < SAM_SOCKET_BUFFER_SIZE - l)
{ {
memcpy (m_StreamBuffer + l, buf, len); memcpy (m_StreamBuffer + l, buf, len);
@@ -1528,3 +1493,4 @@ namespace client
} }
} }
} }
#endif // WITH_SAM

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#ifdef WITH_SAM
#ifndef SAM_H__ #ifndef SAM_H__
#define SAM_H__ #define SAM_H__
@@ -286,3 +288,4 @@ namespace client
} }
#endif #endif
#endif // WITH_SAM