fix code syle(spaces->tabs, tabulations)

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1525/head
R4SAS 4 years ago committed by R4SAS
parent 9633c247f0
commit 7a5146ea74

@ -26,48 +26,48 @@
class I2PService class I2PService
{ {
public: public:
I2PService(PSTR pszServiceName, I2PService(PSTR pszServiceName,
BOOL fCanStop = TRUE, BOOL fCanStop = TRUE,
BOOL fCanShutdown = TRUE, BOOL fCanShutdown = TRUE,
BOOL fCanPauseContinue = FALSE); BOOL fCanPauseContinue = FALSE);
virtual ~I2PService(void); virtual ~I2PService(void);
static BOOL isService(); static BOOL isService();
static BOOL Run(I2PService &service); static BOOL Run(I2PService &service);
void Stop(); void Stop();
protected: protected:
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv); virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
virtual void OnStop(); virtual void OnStop();
virtual void OnPause(); virtual void OnPause();
virtual void OnContinue(); virtual void OnContinue();
virtual void OnShutdown(); virtual void OnShutdown();
void SetServiceStatus(DWORD dwCurrentState, void SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode = NO_ERROR, DWORD dwWin32ExitCode = NO_ERROR,
DWORD dwWaitHint = 0); DWORD dwWaitHint = 0);
private: private:
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv); static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl); static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
void WorkerThread(); void WorkerThread();
void Start(DWORD dwArgc, PSTR *pszArgv); void Start(DWORD dwArgc, PSTR *pszArgv);
void Pause(); void Pause();
void Continue(); void Continue();
void Shutdown(); void Shutdown();
static I2PService* s_service; static I2PService* s_service;
PSTR m_name; PSTR m_name;
SERVICE_STATUS m_status; SERVICE_STATUS m_status;
SERVICE_STATUS_HANDLE m_statusHandle; SERVICE_STATUS_HANDLE m_statusHandle;
BOOL m_fStopping; BOOL m_fStopping;
HANDLE m_hStoppedEvent; HANDLE m_hStoppedEvent;
std::thread* _worker; std::thread* _worker;
}; };
void InstallService( void InstallService(
@ -77,7 +77,7 @@ void InstallService(
PCSTR pszDependencies, PCSTR pszDependencies,
PCSTR pszAccount, PCSTR pszAccount,
PCSTR pszPassword PCSTR pszPassword
); );
void UninstallService(PCSTR pszServiceName); void UninstallService(PCSTR pszServiceName);

@ -1,11 +1,11 @@
//{{NO_DEPENDENCIES}} //{{NO_DEPENDENCIES}}
#define MAINICON 101 #define MAINICON 101
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif

@ -127,8 +127,8 @@ namespace i2p
i2p::context.SetNetID (netID); i2p::context.SetNetID (netID);
i2p::context.Init (); i2p::context.Init ();
bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv4; i2p::config::GetOption("ipv4", ipv4);
#ifdef MESHNET #ifdef MESHNET
// manual override for meshnet // manual override for meshnet
ipv4 = false; ipv4 = false;
@ -143,7 +143,7 @@ namespace i2p
i2p::context.SetSupportsV6 (ipv6); i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4); i2p::context.SetSupportsV4 (ipv4);
bool ntcp; i2p::config::GetOption("ntcp", ntcp); bool ntcp; i2p::config::GetOption("ntcp", ntcp);
i2p::context.PublishNTCPAddress (ntcp, !ipv6); i2p::context.PublishNTCPAddress (ntcp, !ipv6);
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
if (ntcp2) if (ntcp2)
@ -172,10 +172,13 @@ namespace i2p
SetMaxNumTransitTunnels (transitTunnels); SetMaxNumTransitTunnels (transitTunnels);
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (isFloodfill) { if (isFloodfill)
{
LogPrint(eLogInfo, "Daemon: router will be floodfill"); LogPrint(eLogInfo, "Daemon: router will be floodfill");
i2p::context.SetFloodfill (true); i2p::context.SetFloodfill (true);
} else { }
else
{
i2p::context.SetFloodfill (false); i2p::context.SetFloodfill (false);
} }
@ -243,7 +246,8 @@ namespace i2p
i2p::transport::transports.RestrictRoutesToFamilies(fams); i2p::transport::transports.RestrictRoutesToFamilies(fams);
restricted = fams.size() > 0; restricted = fams.size() > 0;
} }
if (routers.length() > 0) { if (routers.length() > 0)
{
std::set<i2p::data::IdentHash> idents; std::set<i2p::data::IdentHash> idents;
size_t pos = 0, comma; size_t pos = 0, comma;
do do
@ -279,7 +283,8 @@ namespace i2p
i2p::data::netdb.Start(); i2p::data::netdb.Start();
bool upnp; i2p::config::GetOption("upnp.enabled", upnp); bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
if (upnp) { if (upnp)
{
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP); d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
d.UPnP->Start (); d.UPnP->Start ();
} }
@ -292,7 +297,7 @@ namespace i2p
} }
bool ntcp; i2p::config::GetOption("ntcp", ntcp); bool ntcp; i2p::config::GetOption("ntcp", ntcp);
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
LogPrint(eLogInfo, "Daemon: starting Transports"); LogPrint(eLogInfo, "Daemon: starting Transports");
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled"); if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
@ -310,7 +315,8 @@ namespace i2p
} }
bool http; i2p::config::GetOption("http.enabled", http); bool http; i2p::config::GetOption("http.enabled", http);
if (http) { if (http)
{
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort); LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
@ -326,7 +332,6 @@ namespace i2p
} }
} }
LogPrint(eLogInfo, "Daemon: starting Tunnels"); LogPrint(eLogInfo, "Daemon: starting Tunnels");
i2p::tunnel::tunnels.Start(); i2p::tunnel::tunnels.Start();

@ -13,9 +13,10 @@ namespace util
class Daemon_Singleton class Daemon_Singleton
{ {
public: public:
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
virtual bool init(int argc, char* argv[]); virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
virtual bool start(); virtual bool init(int argc, char* argv[]);
virtual bool start();
virtual bool stop(); virtual bool stop();
virtual void run () {}; virtual void run () {};
@ -23,6 +24,7 @@ namespace util
bool running; bool running;
protected: protected:
Daemon_Singleton(); Daemon_Singleton();
virtual ~Daemon_Singleton(); virtual ~Daemon_Singleton();
@ -39,6 +41,7 @@ namespace util
class DaemonQT: public i2p::util::Daemon_Singleton class DaemonQT: public i2p::util::Daemon_Singleton
{ {
public: public:
static DaemonQT& Instance() static DaemonQT& Instance()
{ {
static DaemonQT instance; static DaemonQT instance;
@ -51,6 +54,7 @@ namespace util
class DaemonWin32 : public Daemon_Singleton class DaemonWin32 : public Daemon_Singleton
{ {
public: public:
static DaemonWin32& Instance() static DaemonWin32& Instance()
{ {
static DaemonWin32 instance; static DaemonWin32 instance;
@ -72,6 +76,7 @@ namespace util
class DaemonAndroid: public i2p::util::Daemon_Singleton class DaemonAndroid: public i2p::util::Daemon_Singleton
{ {
public: public:
static DaemonAndroid& Instance() static DaemonAndroid& Instance()
{ {
static DaemonAndroid instance; static DaemonAndroid instance;
@ -83,6 +88,7 @@ namespace util
class DaemonLinux : public Daemon_Singleton class DaemonLinux : public Daemon_Singleton
{ {
public: public:
static DaemonLinux& Instance() static DaemonLinux& Instance()
{ {
static DaemonLinux instance; static DaemonLinux instance;
@ -94,10 +100,12 @@ namespace util
void run (); void run ();
private: private:
std::string pidfile; std::string pidfile;
int pidFH; int pidFH;
public: public:
int gracefulShutdownInterval; // in seconds int gracefulShutdownInterval; // in seconds
}; };
#endif #endif

@ -892,8 +892,8 @@ namespace http {
void HTTPConnection::Receive () void HTTPConnection::Receive ()
{ {
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE), m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE),
std::bind(&HTTPConnection::HandleReceive, shared_from_this (), std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
} }
void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)

@ -79,17 +79,17 @@ namespace http
std::string m_Hostname; std::string m_Hostname;
}; };
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml //all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
enum OutputFormatEnum { forWebConsole, forQtUi }; enum OutputFormatEnum { forWebConsole, forQtUi };
void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat); void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
void ShowLocalDestinations (std::stringstream& s); void ShowLocalDestinations (std::stringstream& s);
void ShowLeasesSets(std::stringstream& s); void ShowLeasesSets(std::stringstream& s);
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 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);
} // http } // http
} // i2p } // i2p

@ -59,29 +59,28 @@ namespace client
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem); m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
// handlers // handlers
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler; m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler; m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler; m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler; m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler; m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler; m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler; m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
// I2PControl // I2PControl
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler; m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
// RouterInfo // RouterInfo
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler; m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler; m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler; m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler; m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler; m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S; m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S; m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler; m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler; m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
&I2PControlService::TunnelsSuccessRateHandler;
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes; m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes; m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
@ -97,10 +96,10 @@ namespace client
// ClientServicesInfo // ClientServicesInfo
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler; m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler; m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler; m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler; m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler; m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler; m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
} }
I2PControlService::~I2PControlService () I2PControlService::~I2PControlService ()
@ -500,7 +499,7 @@ namespace client
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
m_ShutdownTimer.async_wait ( m_ShutdownTimer.async_wait (
[](const boost::system::error_code& ecode) [](const boost::system::error_code& ecode)
{ {
Daemon.running = 0; Daemon.running = 0;
}); });
} }
@ -514,7 +513,7 @@ namespace client
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
m_ShutdownTimer.async_wait ( m_ShutdownTimer.async_wait (
[](const boost::system::error_code& ecode) [](const boost::system::error_code& ecode)
{ {
Daemon.running = 0; Daemon.running = 0;
}); });
} }

@ -27,6 +27,7 @@ namespace client
class I2PControlService class I2PControlService
{ {
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket; typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
public: public:
I2PControlService (const std::string& address, int port); I2PControlService (const std::string& address, int port);

@ -80,10 +80,10 @@ namespace transport
void UPnP::Discover () void UPnP::Discover ()
{ {
bool isError; bool isError;
int err; int err;
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS)) #if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNPDISCOVER_SUCCESS; err = UPNPDISCOVER_SUCCESS;
#if (MINIUPNPC_API_VERSION >= 14) #if (MINIUPNPC_API_VERSION >= 14)
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err); m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
@ -92,9 +92,9 @@ namespace transport
#endif #endif
isError = err != UPNPDISCOVER_SUCCESS; isError = err != UPNPDISCOVER_SUCCESS;
#else // MINIUPNPC_API_VERSION >= 8 #else // MINIUPNPC_API_VERSION >= 8
err = 0; err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0); m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
isError = m_Devlist == NULL; isError = m_Devlist == NULL;
#endif // MINIUPNPC_API_VERSION >= 8 #endif // MINIUPNPC_API_VERSION >= 8
{ {
@ -105,15 +105,15 @@ namespace transport
if (isError) if (isError)
{ {
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err); LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
return; return;
} }
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr)); err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
m_upnpUrlsInitialized=err!=0; m_upnpUrlsInitialized = err != 0;
if (err == UPNP_IGD_VALID_CONNECTED) if (err == UPNP_IGD_VALID_CONNECTED)
{ {
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(err != UPNPCOMMAND_SUCCESS) if(err != UPNPCOMMAND_SUCCESS)
{ {
LogPrint (eLogError, "UPnP: unable to get external address: error ", err); LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
@ -124,14 +124,14 @@ namespace transport
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL); LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
if (!m_externalIPAddress[0]) if (!m_externalIPAddress[0])
{ {
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address"); LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
return; return;
} }
} }
} }
else else
{ {
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err); LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
return; return;
} }
@ -182,7 +182,7 @@ namespace transport
err = CheckMapping (strPort.c_str (), strType.c_str ()); err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
{ {
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err); LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS)) #if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL); err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
@ -202,7 +202,7 @@ namespace transport
} }
else else
{ {
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device"); LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
return; return;
} }
} }
@ -219,14 +219,14 @@ namespace transport
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address) void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{ {
if(!m_upnpUrlsInitialized) { if(!m_upnpUrlsInitialized) {
return; return;
} }
std::string strType (GetProto (address)), strPort (std::to_string (address->port)); std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int err = UPNPCOMMAND_SUCCESS; int err = UPNPCOMMAND_SUCCESS;
err = CheckMapping (strPort.c_str (), strType.c_str ()); err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err == UPNPCOMMAND_SUCCESS) if (err == UPNPCOMMAND_SUCCESS)
{ {
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL); err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err); LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
@ -237,11 +237,11 @@ namespace transport
{ {
freeUPNPDevlist (m_Devlist); freeUPNPDevlist (m_Devlist);
m_Devlist = 0; m_Devlist = 0;
if(m_upnpUrlsInitialized){ if(m_upnpUrlsInitialized){
FreeUPNPUrls (&m_upnpUrls); FreeUPNPUrls (&m_upnpUrls);
m_upnpUrlsInitialized=false; m_upnpUrlsInitialized=false;
} }
} }
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address) std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{ {

@ -33,41 +33,41 @@ namespace transport
{ {
public: public:
UPnP (); UPnP ();
~UPnP (); ~UPnP ();
void Close (); void Close ();
void Start (); void Start ();
void Stop (); void Stop ();
private: private:
void Discover (); void Discover ();
int CheckMapping (const char* port, const char* type); int CheckMapping (const char* port, const char* type);
void PortMapping (); void PortMapping ();
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address); void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void CloseMapping (); void CloseMapping ();
void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address); void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void Run (); void Run ();
std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address); std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
private: private:
bool m_IsRunning; bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread; std::unique_ptr<std::thread> m_Thread;
std::condition_variable m_Started; std::condition_variable m_Started;
std::mutex m_StartedMutex; std::mutex m_StartedMutex;
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer; boost::asio::deadline_timer m_Timer;
bool m_upnpUrlsInitialized=false; bool m_upnpUrlsInitialized = false;
struct UPNPUrls m_upnpUrls; struct UPNPUrls m_upnpUrls;
struct IGDdatas m_upnpData; struct IGDdatas m_upnpData;
// For miniupnpc // For miniupnpc
struct UPNPDev * m_Devlist = 0; struct UPNPDev * m_Devlist = 0;
char m_NetworkAddr[64]; char m_NetworkAddr[64];
char m_externalIPAddress[40]; char m_externalIPAddress[40];
}; };
} }
} }
@ -79,10 +79,10 @@ namespace transport {
class UPnP { class UPnP {
public: public:
UPnP () {}; UPnP () {};
~UPnP () {}; ~UPnP () {};
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); } void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
void Stop () {}; void Stop () {};
}; };
} }
} }

@ -196,5 +196,4 @@ namespace i2p
} }
} }
} }
#endif #endif

@ -2,7 +2,6 @@
#include "Daemon.h" #include "Daemon.h"
#if defined(QT_GUI_LIB) #if defined(QT_GUI_LIB)
namespace i2p namespace i2p
{ {
namespace qt namespace qt
@ -10,11 +9,11 @@ namespace qt
int RunQT (int argc, char* argv[]); int RunQT (int argc, char* argv[]);
} }
} }
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
return i2p::qt::RunQT (argc, argv); return i2p::qt::RunQT (argc, argv);
} }
#else #else
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {

@ -7,7 +7,8 @@ namespace i2p
{ {
namespace data namespace data
{ {
static const char T32[32] = { static const char T32[32] =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
@ -29,15 +30,16 @@ namespace data
* Direct Substitution Table * Direct Substitution Table
*/ */
static const char T64[64] = { static const char T64[64] =
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', {
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'w', 'x', 'y', 'z', '0', '1', '2', '3', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'4', '5', '6', '7', '8', '9', '-', '~' 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '-', '~'
}; };
const char * GetBase64SubstitutionTable () const char * GetBase64SubstitutionTable ()
@ -67,14 +69,12 @@ namespace data
* *
*/ */
size_t /* Number of bytes in the encoded buffer */ size_t ByteStreamToBase64 ( /* Number of bytes in the encoded buffer */
ByteStreamToBase64 ( const uint8_t * InBuffer, /* Input buffer, binary data */
const uint8_t * InBuffer, /* Input buffer, binary data */ size_t InCount, /* Number of bytes in the input buffer */
size_t InCount, /* Number of bytes in the input buffer */ char * OutBuffer, /* output buffer */
char * OutBuffer, /* output buffer */ size_t len /* length of output buffer */
size_t len /* length of output buffer */
) )
{ {
unsigned char * ps; unsigned char * ps;
unsigned char * pd; unsigned char * pd;
@ -83,55 +83,60 @@ namespace data
int i; int i;
int n; int n;
int m; int m;
size_t outCount; size_t outCount;
ps = (unsigned char *)InBuffer; ps = (unsigned char *)InBuffer;
n = InCount/3; n = InCount / 3;
m = InCount%3; m = InCount % 3;
if (!m) if (!m)
outCount = 4*n; outCount = 4 * n;
else else
outCount = 4*(n+1); outCount = 4 * (n + 1);
if (outCount > len) return 0; if (outCount > len) return 0;
pd = (unsigned char *)OutBuffer; pd = (unsigned char *)OutBuffer;
for ( i = 0; i<n; i++ ){ for ( i = 0; i < n; i++ )
acc_1 = *ps++; {
acc_2 = (acc_1<<4)&0x30; acc_1 = *ps++;
acc_1 >>= 2; /* base64 digit #1 */ acc_2 = (acc_1 << 4) & 0x30;
*pd++ = T64[acc_1]; acc_1 >>= 2; /* base64 digit #1 */
acc_1 = *ps++; *pd++ = T64[acc_1];
acc_2 |= acc_1 >> 4; /* base64 digit #2 */ acc_1 = *ps++;
*pd++ = T64[acc_2]; acc_2 |= acc_1 >> 4; /* base64 digit #2 */
acc_1 &= 0x0f; *pd++ = T64[acc_2];
acc_1 <<=2; acc_1 &= 0x0f;
acc_2 = *ps++; acc_1 <<= 2;
acc_1 |= acc_2>>6; /* base64 digit #3 */ acc_2 = *ps++;
*pd++ = T64[acc_1]; acc_1 |= acc_2 >> 6; /* base64 digit #3 */
acc_2 &= 0x3f; /* base64 digit #4 */ *pd++ = T64[acc_1];
*pd++ = T64[acc_2]; acc_2 &= 0x3f; /* base64 digit #4 */
*pd++ = T64[acc_2];
} }
if ( m == 1 ){ if ( m == 1 )
acc_1 = *ps++; {
acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */ acc_1 = *ps++;
acc_1 >>= 2; /* base64 digit #1 */ acc_2 = (acc_1 << 4) & 0x3f; /* base64 digit #2 */
*pd++ = T64[acc_1]; acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_2]; *pd++ = T64[acc_1];
*pd++ = P64; *pd++ = T64[acc_2];
*pd++ = P64; *pd++ = P64;
*pd++ = P64;
} }
else if ( m == 2 ){ else if ( m == 2 )
acc_1 = *ps++; {
acc_2 = (acc_1<<4)&0x3f; acc_1 = *ps++;
acc_1 >>= 2; /* base64 digit #1 */ acc_2 = (acc_1 << 4) & 0x3f;
*pd++ = T64[acc_1]; acc_1 >>= 2; /* base64 digit #1 */
acc_1 = *ps++; *pd++ = T64[acc_1];
acc_2 |= acc_1 >> 4; /* base64 digit #2 */ acc_1 = *ps++;
*pd++ = T64[acc_2]; acc_2 |= acc_1 >> 4; /* base64 digit #2 */
acc_1 &= 0x0f; *pd++ = T64[acc_2];
acc_1 <<=2; /* base64 digit #3 */ acc_1 &= 0x0f;
*pd++ = T64[acc_1]; acc_1 <<= 2; /* base64 digit #3 */
*pd++ = P64; *pd++ = T64[acc_1];
*pd++ = P64;
} }
return outCount; return outCount;
@ -147,12 +152,11 @@ namespace data
* *
*/ */
size_t /* Number of output bytes */ size_t Base64ToByteStream ( /* Number of output bytes */
Base64ToByteStream ( const char * InBuffer, /* BASE64 encoded buffer */
const char * InBuffer, /* BASE64 encoded buffer */ size_t InCount, /* Number of input bytes */
size_t InCount, /* Number of input bytes */ uint8_t * OutBuffer, /* output buffer length */
uint8_t * OutBuffer, /* output buffer length */ size_t len /* length of output buffer */
size_t len /* length of output buffer */
) )
{ {
unsigned char * ps; unsigned char * ps;
@ -162,42 +166,52 @@ namespace data
int i; int i;
int n; int n;
int m; int m;
size_t outCount; size_t outCount;
if (isFirstTime)
iT64Build();
n = InCount / 4;
m = InCount % 4;
if (isFirstTime) iT64Build();
n = InCount/4;
m = InCount%4;
if (InCount && !m) if (InCount && !m)
outCount = 3*n; outCount = 3 * n;
else { else
outCount = 0; {
return 0; outCount = 0;
return 0;
} }
ps = (unsigned char *)(InBuffer + InCount - 1); ps = (unsigned char *)(InBuffer + InCount - 1);
while ( *ps-- == P64 ) outCount--; while ( *ps-- == P64 )
outCount--;
ps = (unsigned char *)InBuffer; ps = (unsigned char *)InBuffer;
if (outCount > len) return -1; if (outCount > len)
return -1;
pd = OutBuffer; pd = OutBuffer;
auto endOfOutBuffer = OutBuffer + outCount; auto endOfOutBuffer = OutBuffer + outCount;
for ( i = 0; i < n; i++ ){ for ( i = 0; i < n; i++ )
acc_1 = iT64[*ps++]; {
acc_2 = iT64[*ps++]; acc_1 = iT64[*ps++];
acc_1 <<= 2; acc_2 = iT64[*ps++];
acc_1 |= acc_2>>4; acc_1 <<= 2;
*pd++ = acc_1; acc_1 |= acc_2 >> 4;
if (pd >= endOfOutBuffer) break; *pd++ = acc_1;
if (pd >= endOfOutBuffer)
acc_2 <<= 4; break;
acc_1 = iT64[*ps++];
acc_2 |= acc_1 >> 2; acc_2 <<= 4;
*pd++ = acc_2; acc_1 = iT64[*ps++];
if (pd >= endOfOutBuffer) break; acc_2 |= acc_1 >> 2;
*pd++ = acc_2;
acc_2 = iT64[*ps++]; if (pd >= endOfOutBuffer)
acc_2 |= acc_1 << 6; break;
*pd++ = acc_2;
acc_2 = iT64[*ps++];
acc_2 |= acc_1 << 6;
*pd++ = acc_2;
} }
return outCount; return outCount;
@ -206,20 +220,25 @@ namespace data
size_t Base64EncodingBufferSize (const size_t input_size) size_t Base64EncodingBufferSize (const size_t input_size)
{ {
auto d = div (input_size, 3); auto d = div (input_size, 3);
if (d.rem) d.quot++; if (d.rem)
return 4*d.quot; d.quot++;
return 4 * d.quot;
} }
std::string ToBase64Standard (const std::string& in) std::string ToBase64Standard (const std::string& in)
{ {
auto len = Base64EncodingBufferSize (in.length ()); auto len = Base64EncodingBufferSize (in.length ());
char * str = new char[len+1]; char * str = new char[len + 1];
auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len); auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
str[l] = 0; str[l] = 0;
// replace '-' by '+' and '~' by '/' // replace '-' by '+' and '~' by '/'
for (size_t i = 0; i < l; i++) for (size_t i = 0; i < l; i++)
if (str[i] == '-') str[i] = '+'; if (str[i] == '-')
else if (str[i] == '~') str[i] = '/'; str[i] = '+';
else if (str[i] == '~')
str[i] = '/';
std::string s(str); std::string s(str);
delete[] str; delete[] str;
return s; return s;
@ -236,10 +255,10 @@ namespace data
static void iT64Build() static void iT64Build()
{ {
int i; int i;
isFirstTime = 0; isFirstTime = 0;
for ( i=0; i<256; i++ ) iT64[i] = -1; for ( i = 0; i < 256; i++ ) iT64[i] = -1;
for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i; for ( i = 0; i < 64; i++ ) iT64[(int)T64[i]] = i;
iT64[(int)P64] = 0; iT64[(int)P64] = 0;
} }
@ -302,4 +321,3 @@ namespace data
} }
} }
} }

@ -15,9 +15,9 @@ namespace data {
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
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);
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization

@ -314,4 +314,3 @@ namespace data
} }
} }

@ -5,10 +5,10 @@ namespace i2p
{ {
namespace cpu namespace cpu
{ {
extern bool aesni; extern bool aesni;
extern bool avx; extern bool avx;
void Detect(); void Detect();
} }
} }

@ -21,34 +21,34 @@ namespace chacha
{ {
void u32t8le(uint32_t v, uint8_t * p) void u32t8le(uint32_t v, uint8_t * p)
{ {
p[0] = v & 0xff; p[0] = v & 0xff;
p[1] = (v >> 8) & 0xff; p[1] = (v >> 8) & 0xff;
p[2] = (v >> 16) & 0xff; p[2] = (v >> 16) & 0xff;
p[3] = (v >> 24) & 0xff; p[3] = (v >> 24) & 0xff;
} }
uint32_t u8t32le(const uint8_t * p) uint32_t u8t32le(const uint8_t * p)
{ {
uint32_t value = p[3]; uint32_t value = p[3];
value = (value << 8) | p[2]; value = (value << 8) | p[2];
value = (value << 8) | p[1]; value = (value << 8) | p[1];
value = (value << 8) | p[0]; value = (value << 8) | p[0];
return value; return value;
} }
uint32_t rotl32(uint32_t x, int n) uint32_t rotl32(uint32_t x, int n)
{ {
return x << n | (x >> (-n & 31)); return x << n | (x >> (-n & 31));
} }
void quarterround(uint32_t *x, int a, int b, int c, int d) void quarterround(uint32_t *x, int a, int b, int c, int d)
{ {
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8);
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
} }
@ -61,24 +61,23 @@ void Chacha20Block::operator << (const Chacha20State & st)
void block (Chacha20State &input, int rounds) void block (Chacha20State &input, int rounds)
{ {
int i; int i;
Chacha20State x; Chacha20State x;
x.Copy(input); x.Copy(input);
for (i = rounds; i > 0; i -= 2)
{
quarterround(x.data, 0, 4, 8, 12);
quarterround(x.data, 1, 5, 9, 13);
quarterround(x.data, 2, 6, 10, 14);
quarterround(x.data, 3, 7, 11, 15);
quarterround(x.data, 0, 5, 10, 15);
quarterround(x.data, 1, 6, 11, 12);
quarterround(x.data, 2, 7, 8, 13);
quarterround(x.data, 3, 4, 9, 14);
}
x += input;
input.block << x;
for (i = rounds; i > 0; i -= 2)
{
quarterround(x.data, 0, 4, 8, 12);
quarterround(x.data, 1, 5, 9, 13);
quarterround(x.data, 2, 6, 10, 14);
quarterround(x.data, 3, 7, 11, 15);
quarterround(x.data, 0, 5, 10, 15);
quarterround(x.data, 1, 6, 11, 12);
quarterround(x.data, 2, 7, 8, 13);
quarterround(x.data, 3, 4, 9, 14);
}
x += input;
input.block << x;
} }
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter) void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
@ -88,11 +87,11 @@ void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t *
state.data[2] = 0x79622d32; state.data[2] = 0x79622d32;
state.data[3] = 0x6b206574; state.data[3] = 0x6b206574;
for (size_t i = 0; i < 8; i++) for (size_t i = 0; i < 8; i++)
state.data[4 + i] = chacha::u8t32le(key + i * 4); state.data[4 + i] = chacha::u8t32le(key + i * 4);
state.data[12] = htole32 (counter); state.data[12] = htole32 (counter);
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
state.data[13 + i] = chacha::u8t32le(nonce + i * 4); state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
} }
void Chacha20SetCounter (Chacha20State& state, uint32_t counter) void Chacha20SetCounter (Chacha20State& state, uint32_t counter)
@ -117,22 +116,22 @@ void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
} }
for (size_t i = 0; i < sz; i += chacha::blocksize) for (size_t i = 0; i < sz; i += chacha::blocksize)
{ {
chacha::block(state, chacha::rounds); chacha::block(state, chacha::rounds);
state.data[12]++; state.data[12]++;
for (size_t j = i; j < i + chacha::blocksize; j++) for (size_t j = i; j < i + chacha::blocksize; j++)
{ {
if (j >= sz) if (j >= sz)
{ {
state.offset = j & 0x3F; // % 64 state.offset = j & 0x3F; // % 64
break; break;
} }
buf[j] ^= state.block.data[j - i]; buf[j] ^= state.block.data[j - i];
} }
} }
} }
} // namespace chacha } // namespace chacha
} // namespace crypto
} // namespace i2p
}
}
#endif #endif

@ -21,8 +21,8 @@ namespace i2p
{ {
namespace crypto namespace crypto
{ {
const std::size_t CHACHA20_KEY_BYTES = 32; const std::size_t CHACHA20_KEY_BYTES = 32;
const std::size_t CHACHA20_NOUNCE_BYTES = 12; const std::size_t CHACHA20_NOUNCE_BYTES = 12;
namespace chacha namespace chacha
{ {
@ -32,12 +32,12 @@ namespace chacha
struct Chacha20State; struct Chacha20State;
struct Chacha20Block struct Chacha20Block
{ {
Chacha20Block () {}; Chacha20Block () {};
Chacha20Block (Chacha20Block &&) = delete; Chacha20Block (Chacha20Block &&) = delete;
uint8_t data[blocksize]; uint8_t data[blocksize];
void operator << (const Chacha20State & st); void operator << (const Chacha20State & st);
}; };
struct Chacha20State struct Chacha20State
@ -54,7 +54,7 @@ namespace chacha
void Copy(const Chacha20State & other) void Copy(const Chacha20State & other)
{ {
memcpy(data, other.data, sizeof(uint32_t) * 16); memcpy(data, other.data, sizeof(uint32_t) * 16);
} }
uint32_t data[16]; uint32_t data[16];
Chacha20Block block; Chacha20Block block;
@ -64,9 +64,9 @@ namespace chacha
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter); void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
void Chacha20SetCounter (Chacha20State& state, uint32_t counter); void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
} } // namespace chacha
} } // namespace crypto
} } // namespace i2p
#endif
#endif #endif
#endif

@ -242,7 +242,7 @@ namespace config {
"1.pool.ntp.org," "1.pool.ntp.org,"
"2.pool.ntp.org," "2.pool.ntp.org,"
"3.pool.ntp.org" "3.pool.ntp.org"
), "Comma separated list of NTCP servers") ), "Comma separated list of NTCP servers")
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)") ("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
; ;

@ -18,98 +18,101 @@
namespace i2p { namespace i2p {
namespace config { namespace config {
extern boost::program_options::variables_map m_Options; extern boost::program_options::variables_map m_Options;
/** /**
* @brief Initialize list of acceptable parameters * @brief Initialize list of acceptable parameters
* *
* Should be called before any Parse* functions. * Should be called before any Parse* functions.
*/ */
void Init(); void Init();
/** /**
* @brief Parse cmdline parameters, and show help if requested * @brief Parse cmdline parameters, and show help if requested
* @param argc Cmdline arguments count, should be passed from main(). * @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main() * @param argv Cmdline parameters array, should be passed from main()
* *
* If --help is given in parameters, shows its list with description * If --help is given in parameters, shows its list with description
* and terminates the program with exitcode 0. * and terminates the program with exitcode 0.
* *
* In case of parameter misuse boost throws an exception. * In case of parameter misuse boost throws an exception.
* We internally handle type boost::program_options::unknown_option, * We internally handle type boost::program_options::unknown_option,
* and then terminate the program with exitcode 1. * and then terminate the program with exitcode 1.
* *
* Other exceptions will be passed to higher level. * Other exceptions will be passed to higher level.
*/ */
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false); void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
/** /**
* @brief Load and parse given config file * @brief Load and parse given config file
* @param path Path to config file * @param path Path to config file
* *
* If error occurred when opening file path is points to, * If error occurred when opening file path is points to,
* we show the error message and terminate program. * we show the error message and terminate program.
* *
* In case of parameter misuse boost throws an exception. * In case of parameter misuse boost throws an exception.
* We internally handle type boost::program_options::unknown_option, * We internally handle type boost::program_options::unknown_option,
* and then terminate program with exitcode 1. * and then terminate program with exitcode 1.
* *
* Other exceptions will be passed to higher level. * Other exceptions will be passed to higher level.
*/ */
void ParseConfig(const std::string& path); void ParseConfig(const std::string& path);
/** /**
* @brief Used to combine options from cmdline, config and default values * @brief Used to combine options from cmdline, config and default values
*/ */
void Finalize(); void Finalize();
/* @brief Accessor to parameters by name /**
* @param name Name of the requested parameter * @brief Accessor to parameters by name
* @param value Variable where to store option * @param name Name of the requested parameter
* @return this function returns false if parameter not found * @param value Variable where to store option
* * @return this function returns false if parameter not found
* Example: uint16_t port; GetOption("sam.port", port); *
*/ * Example: uint16_t port; GetOption("sam.port", port);
template<typename T> */
bool GetOption(const char *name, T& value) { template<typename T>
if (!m_Options.count(name)) bool GetOption(const char *name, T& value)
return false; {
value = m_Options[name].as<T>(); if (!m_Options.count(name))
return true; return false;
} value = m_Options[name].as<T>();
return true;
}
template<typename T> template<typename T>
bool GetOption(const std::string& name, T& value) bool GetOption(const std::string& name, T& value)
{ {
return GetOption (name.c_str (), value); return GetOption (name.c_str (), value);
} }
bool GetOptionAsAny(const char *name, boost::any& value); bool GetOptionAsAny(const char *name, boost::any& value);
bool GetOptionAsAny(const std::string& name, boost::any& value); bool GetOptionAsAny(const std::string& name, boost::any& value);
/** /**
* @brief Set value of given parameter * @brief Set value of given parameter
* @param name Name of settable parameter * @param name Name of settable parameter
* @param value New parameter value * @param value New parameter value
* @return true if value set up successful, false otherwise * @return true if value set up successful, false otherwise
* *
* Example: uint16_t port = 2827; SetOption("bob.port", port); * Example: uint16_t port = 2827; SetOption("bob.port", port);
*/ */
template<typename T> template<typename T>
bool SetOption(const char *name, const T& value) { bool SetOption(const char *name, const T& value)
if (!m_Options.count(name)) {
return false; if (!m_Options.count(name))
m_Options.at(name).value() = value; return false;
notify(m_Options); m_Options.at(name).value() = value;
return true; notify(m_Options);
} return true;
}
/** /**
* @brief Check is value explicitly given or default * @brief Check is value explicitly given or default
* @param name Name of checked parameter * @param name Name of checked parameter
* @return true if value set to default, false otherwise * @return true if value set to default, false otherwise
*/ */
bool IsDefault(const char *name); bool IsDefault(const char *name);
} }
} }

@ -681,12 +681,12 @@ namespace crypto
// AES // AES
#ifdef __AES__ #ifdef __AES__
#ifdef ARM64AES #ifdef ARM64AES
void init_aesenc(void){ void init_aesenc(void){
// TODO: Implementation // TODO: Implementation
} }
#endif #endif
#define KeyExpansion256(round0,round1) \ #define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \
@ -884,7 +884,6 @@ namespace crypto
} }
} }
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{ {
#ifdef __AES__ #ifdef __AES__
@ -1364,4 +1363,3 @@ namespace crypto
} }
} }
} }

@ -28,13 +28,13 @@
#else #else
# define LEGACY_OPENSSL 0 # define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1 # define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1 # define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1 # define OPENSSL_X25519 1
# define OPENSSL_SIPHASH 1 # define OPENSSL_SIPHASH 1
# endif # endif
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them # if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
# define OPENSSL_AEAD_CHACHA20_POLY1305 1 # define OPENSSL_AEAD_CHACHA20_POLY1305 1
# endif # endif
#endif #endif

@ -178,4 +178,3 @@ namespace crypto
} }
} }
} }

@ -126,7 +126,7 @@ namespace crypto
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub); ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
~ECIESX25519AEADRatchetEncryptor () {}; ~ECIESX25519AEADRatchetEncryptor () {};
void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool); void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool);
// copies m_PublicKey to pub // copies m_PublicKey to pub
private: private:
@ -153,4 +153,3 @@ namespace crypto
} }
#endif #endif

@ -77,5 +77,4 @@ namespace worker
} }
} }
#endif #endif

@ -114,16 +114,15 @@ namespace datagram
LogPrint (eLogWarning, "Datagram: decompression failed"); LogPrint (eLogWarning, "Datagram: decompression failed");
} }
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage ( std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (
const std::vector<std::pair<const uint8_t *, size_t> >& payloads, const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum) uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
{ {
auto msg = NewI2NPMessage (); auto msg = NewI2NPMessage ();
uint8_t * buf = msg->GetPayload (); uint8_t * buf = msg->GetPayload ();
buf += 4; // reserve for length buf += 4; // reserve for length
size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) : size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) :
i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len); i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
if (size) if (size)
{ {
htobe32buf (msg->GetPayload (), size); // length htobe32buf (msg->GetPayload (), size); // length
@ -186,7 +185,7 @@ namespace datagram
} }
DatagramSession::DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, DatagramSession::DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination,
const i2p::data::IdentHash & remoteIdent) : const i2p::data::IdentHash & remoteIdent) :
m_LocalDestination(localDestination), m_LocalDestination(localDestination),
m_RemoteIdent(remoteIdent), m_RemoteIdent(remoteIdent),
m_SendQueueTimer(localDestination->GetService()), m_SendQueueTimer(localDestination->GetService()),
@ -384,4 +383,3 @@ namespace datagram
} }
} }
} }

@ -32,25 +32,27 @@ namespace datagram
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
// milliseconds minimum time between path switches // milliseconds minimum time between path switches
const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000; const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
// max 64 messages buffered in send queue for each datagram session // max 64 messages buffered in send queue for each datagram session
const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64; const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
class DatagramSession : public std::enable_shared_from_this<DatagramSession> class DatagramSession : public std::enable_shared_from_this<DatagramSession>
{ {
public:
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
void Start (); public:
void Stop ();
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
void Start ();
void Stop ();
/** @brief ack the garlic routing path */
void Ack();
/** send an i2np message to remote endpoint for this session */ /** @brief ack the garlic routing path */
void SendMsg(std::shared_ptr<I2NPMessage> msg); void Ack();
/** get the last time in milliseconds for when we used this datagram session */
uint64_t LastActivity() const { return m_LastUse; } /** send an i2np message to remote endpoint for this session */
void SendMsg(std::shared_ptr<I2NPMessage> msg);
/** get the last time in milliseconds for when we used this datagram session */
uint64_t LastActivity() const { return m_LastUse; }
bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); } bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); }
@ -60,40 +62,41 @@ namespace datagram
std::shared_ptr<const i2p::data::IdentHash> OBEP; std::shared_ptr<const i2p::data::IdentHash> OBEP;
const uint64_t activity; const uint64_t activity;
Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {} Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) : Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
activity(a) { activity(a) {
if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw); if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
else IBGW = nullptr; else IBGW = nullptr;
if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep); if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
else OBEP = nullptr; else OBEP = nullptr;
} }
}; };
Info GetSessionInfo() const;
Info GetSessionInfo() const; private:
private: void FlushSendQueue();
void ScheduleFlushSendQueue();
void FlushSendQueue(); void HandleSend(std::shared_ptr<I2NPMessage> msg);
void ScheduleFlushSendQueue();
void HandleSend(std::shared_ptr<I2NPMessage> msg); std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath(); void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls); private:
private: std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination; i2p::data::IdentHash m_RemoteIdent;
i2p::data::IdentHash m_RemoteIdent; std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet; std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession; std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease; std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel; boost::asio::deadline_timer m_SendQueueTimer;
boost::asio::deadline_timer m_SendQueueTimer; std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue; uint64_t m_LastUse;
uint64_t m_LastUse; bool m_RequestingLS;
bool m_RequestingLS;
}; };
typedef std::shared_ptr<DatagramSession> DatagramSession_ptr; typedef std::shared_ptr<DatagramSession> DatagramSession_ptr;
@ -104,11 +107,9 @@ namespace datagram
typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver; typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver; typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
public: public:
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
~DatagramDestination (); ~DatagramDestination ();
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
@ -131,7 +132,7 @@ namespace datagram
private: private:
std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident); std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
std::shared_ptr<I2NPMessage> CreateDataMessage (const std::vector<std::pair<const uint8_t *, size_t> >& payloads, std::shared_ptr<I2NPMessage> CreateDataMessage (const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true); uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true);

@ -16,7 +16,7 @@ namespace i2p
namespace client namespace client
{ {
LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service, LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service,
bool isPublic, const std::map<std::string, std::string> * params): bool isPublic, const std::map<std::string, std::string> * params):
m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0), m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0),
m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service), m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
@ -160,7 +160,6 @@ namespace client
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params) bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
{ {
auto itr = params.find("i2cp.dontPublishLeaseSet"); auto itr = params.find("i2cp.dontPublishLeaseSet");
if (itr != params.end()) if (itr != params.end())
{ {
@ -565,12 +564,12 @@ namespace client
m_PublishReplyToken = 0; m_PublishReplyToken = 0;
if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
{ {
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
Publish (); Publish ();
} }
else else
{ {
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ()); LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
// Java floodfill never sends confirmation back for unknown crypto type // Java floodfill never sends confirmation back for unknown crypto type
// assume it successive and try to verify // assume it successive and try to verify
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
@ -720,7 +719,7 @@ namespace client
} }
bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request) std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
{ {
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ()) if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
request->replyTunnel = m_Pool->GetNextInboundTunnel (); request->replyTunnel = m_Pool->GetNextInboundTunnel ();
@ -783,7 +782,7 @@ namespace client
} }
else else
{ {
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds"); LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
done = true; done = true;
} }
@ -829,7 +828,7 @@ namespace client
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
{ {
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)) if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET; return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
} }
@ -846,7 +845,7 @@ namespace client
// extract encryption type params for LS2 // extract encryption type params for LS2
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes; std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 || if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params) GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
{ {
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE); auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
if (it != params->end ()) if (it != params->end ())
@ -1105,7 +1104,7 @@ namespace client
return dest; return dest;
} }
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip) i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
{ {
if (m_DatagramDestination == nullptr) if (m_DatagramDestination == nullptr)
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip); m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
@ -1147,7 +1146,7 @@ namespace client
// TODO:: persist crypto key type // TODO:: persist crypto key type
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
if (f1) { if (f1) {
f1.write ((char *)keys->pub, 256); f1.write ((char *)keys->pub, 256);
f1.write ((char *)keys->priv, 256); f1.write ((char *)keys->priv, 256);
return; return;
} }

@ -94,7 +94,6 @@ namespace client
} }
}; };
public: public:
LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr); LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
@ -112,7 +111,7 @@ namespace client
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
std::shared_ptr<i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident); std::shared_ptr<i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr); bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr);
void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true); void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify = true); void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify = true);
@ -155,7 +154,7 @@ namespace client
void HandleDeliveryStatusMessage (uint32_t msgID); void HandleDeliveryStatusMessage (uint32_t msgID);
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr); void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
void HandleCleanupTimer (const boost::system::error_code& ecode); void HandleCleanupTimer (const boost::system::error_code& ecode);
void CleanupRemoteLeaseSets (); void CleanupRemoteLeaseSets ();
@ -235,8 +234,8 @@ namespace client
int GetStreamingAckDelay () const { return m_StreamingAckDelay; } int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
// datagram // datagram
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true); i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
// implements LocalDestination // implements LocalDestination
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const; bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;

@ -15,36 +15,36 @@ namespace i2p
namespace garlic namespace garlic
{ {
void RatchetTagSet::DHInitialize (const uint8_t * rootKey, const uint8_t * k) void RatchetTagSet::DHInitialize (const uint8_t * rootKey, const uint8_t * k)
{ {
// DH_INITIALIZE(rootKey, k) // DH_INITIALIZE(rootKey, k)
uint8_t keydata[64]; uint8_t keydata[64];
i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64) i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31] memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31]
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf); i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf);
// [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64) // [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64)
memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32); memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32);
m_NextSymmKeyIndex = 0; m_NextSymmKeyIndex = 0;
} }
void RatchetTagSet::NextSessionTagRatchet () void RatchetTagSet::NextSessionTagRatchet ()
{ {
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64) i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64)
memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32); memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32);
m_NextIndex = 0; m_NextIndex = 0;
} }
uint64_t RatchetTagSet::GetNextSessionTag () uint64_t RatchetTagSet::GetNextSessionTag ()
{ {
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64) i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
m_NextIndex++; m_NextIndex++;
if (m_NextIndex >= 65535) if (m_NextIndex >= 65535)
{ {
LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty"); LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty");
return 0; return 0;
} }
return m_KeyData.GetTag (); return m_KeyData.GetTag ();
} }
void RatchetTagSet::GetSymmKey (int index, uint8_t * key) void RatchetTagSet::GetSymmKey (int index, uint8_t * key)
{ {
@ -85,15 +85,15 @@ namespace garlic
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT; m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
} }
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet): ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
GarlicRoutingSession (owner, attachLeaseSet) GarlicRoutingSession (owner, attachLeaseSet)
{ {
ResetKeys (); ResetKeys ();
} }
ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession () ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession ()
{ {
} }
void ECIESX25519AEADRatchetSession::ResetKeys () void ECIESX25519AEADRatchetSession::ResetKeys ()
{ {
@ -111,14 +111,14 @@ namespace garlic
memcpy (m_H, hh, 32); memcpy (m_H, hh, 32);
} }
void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len) void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len)
{ {
SHA256_CTX ctx; SHA256_CTX ctx;
SHA256_Init (&ctx); SHA256_Init (&ctx);
SHA256_Update (&ctx, m_H, 32); SHA256_Update (&ctx, m_H, 32);
SHA256_Update (&ctx, buf, len); SHA256_Update (&ctx, buf, len);
SHA256_Final (m_H, &ctx); SHA256_Final (m_H, &ctx);
} }
void ECIESX25519AEADRatchetSession::CreateNonce (uint64_t seqn, uint8_t * nonce) void ECIESX25519AEADRatchetSession::CreateNonce (uint64_t seqn, uint8_t * nonce)
{ {
@ -126,48 +126,48 @@ namespace garlic
htole64buf (nonce + 4, seqn); htole64buf (nonce + 4, seqn);
} }
bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf) bool ECIESX25519AEADRatchetSession::GenerateEphemeralKeysAndEncode (uint8_t * buf)
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
m_EphemeralKeys.GenerateKeys (); m_EphemeralKeys.GenerateKeys ();
if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf)) if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), buf))
return true; // success return true; // success
} }
return false; return false;
} }
std::shared_ptr<RatchetTagSet> ECIESX25519AEADRatchetSession::CreateNewSessionTagset () std::shared_ptr<RatchetTagSet> ECIESX25519AEADRatchetSession::CreateNewSessionTagset ()
{ {
uint8_t tagsetKey[32]; uint8_t tagsetKey[32];
i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32) i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
// Session Tag Ratchet // Session Tag Ratchet
auto tagsetNsr = std::make_shared<RatchetTagSet>(shared_from_this ()); auto tagsetNsr = std::make_shared<RatchetTagSet>(shared_from_this ());
tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey) tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
tagsetNsr->NextSessionTagRatchet (); tagsetNsr->NextSessionTagRatchet ();
return tagsetNsr; return tagsetNsr;
} }
bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len) bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
{ {
if (!GetOwner ()) return false; if (!GetOwner ()) return false;
// we are Bob // we are Bob
// KDF1 // KDF1
MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk) MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk)
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
{ {
LogPrint (eLogError, "Garlic: Can't decode elligator"); LogPrint (eLogError, "Garlic: Can't decode elligator");
return false; return false;
} }
buf += 32; len -= 32; buf += 32; len -= 32;
MixHash (m_Aepk, 32); // h = SHA256(h || aepk) MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, aepk) GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, aepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// decrypt flags/static // decrypt flags/static
uint8_t nonce[12], fs[32]; uint8_t nonce[12], fs[32];
CreateNonce (0, nonce); CreateNonce (0, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt
@ -183,7 +183,7 @@ namespace garlic
if (isStatic) if (isStatic)
{ {
// static key, fs is apk // static key, fs is apk
memcpy (m_RemoteStaticKey, fs, 32); memcpy (m_RemoteStaticKey, fs, 32);
GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, apk) GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, apk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
} }
@ -198,17 +198,17 @@ namespace garlic
return false; return false;
} }
if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext) if (isStatic) MixHash (buf, len); // h = SHA256(h || ciphertext)
m_State = eSessionStateNewSessionReceived; m_State = eSessionStateNewSessionReceived;
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
HandlePayload (payload.data (), len - 16, nullptr, 0); HandlePayload (payload.data (), len - 16, nullptr, 0);
return true; return true;
} }
void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index) void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index)
{ {
size_t offset = 0; size_t offset = 0;
while (offset < len) while (offset < len)
{ {
uint8_t blk = buf[offset]; uint8_t blk = buf[offset];
@ -269,7 +269,7 @@ namespace garlic
} }
offset += size; offset += size;
} }
} }
void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset) void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset)
{ {
@ -279,7 +279,7 @@ namespace garlic
if (!m_SendForwardKey || !m_NextSendRatchet) return; if (!m_SendForwardKey || !m_NextSendRatchet) return;
uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID
if (((!m_NextSendRatchet->newKey || !m_NextSendRatchet->keyID) && keyID == m_NextSendRatchet->keyID) || if (((!m_NextSendRatchet->newKey || !m_NextSendRatchet->keyID) && keyID == m_NextSendRatchet->keyID) ||
(m_NextSendRatchet->newKey && keyID == m_NextSendRatchet->keyID -1)) (m_NextSendRatchet->newKey && keyID == m_NextSendRatchet->keyID -1))
{ {
if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG) if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG)
memcpy (m_NextSendRatchet->remote, buf, 32); memcpy (m_NextSendRatchet->remote, buf, 32);
@ -359,36 +359,36 @@ namespace garlic
LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created"); LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
} }
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
ResetKeys (); ResetKeys ();
// we are Alice, bpk is m_RemoteStaticKey // we are Alice, bpk is m_RemoteStaticKey
size_t offset = 0; size_t offset = 0;
if (!GenerateEphemeralKeysAndEncode (out + offset)) if (!GenerateEphemeralKeysAndEncode (out + offset))
{ {
LogPrint (eLogError, "Garlic: Can't encode elligator"); LogPrint (eLogError, "Garlic: Can't encode elligator");
return false; return false;
} }
offset += 32; offset += 32;
// KDF1 // KDF1
MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk) MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk)
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk) MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk) m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// encrypt static key section // encrypt static key section
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
{ {
LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed "); LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
return false; return false;
} }
MixHash (out + offset, 48); // h = SHA256(h || ciphertext) MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
offset += 48; offset += 48;
// KDF2 // KDF2
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk) GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// encrypt payload // encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
@ -399,80 +399,80 @@ namespace garlic
MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext) MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)
m_State = eSessionStateNewSessionSent; m_State = eSessionStateNewSessionSent;
if (GetOwner ()) if (GetOwner ())
GenerateMoreReceiveTags (CreateNewSessionTagset (), ECIESX25519_NSR_NUM_GENERATED_TAGS); GenerateMoreReceiveTags (CreateNewSessionTagset (), ECIESX25519_NSR_NUM_GENERATED_TAGS);
return true; return true;
} }
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
// we are Bob // we are Bob
m_NSRTagset = CreateNewSessionTagset (); m_NSRTagset = CreateNewSessionTagset ();
uint64_t tag = m_NSRTagset->GetNextSessionTag (); uint64_t tag = m_NSRTagset->GetNextSessionTag ();
size_t offset = 0; size_t offset = 0;
memcpy (out + offset, &tag, 8); memcpy (out + offset, &tag, 8);
offset += 8; offset += 8;
if (!GenerateEphemeralKeysAndEncode (out + offset)) // bepk if (!GenerateEphemeralKeysAndEncode (out + offset)) // bepk
{ {
LogPrint (eLogError, "Garlic: Can't encode elligator"); LogPrint (eLogError, "Garlic: Can't encode elligator");
return false; return false;
} }
memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR
memcpy (m_NSRH, m_H, 32); memcpy (m_NSRH, m_H, 32);
offset += 32; offset += 32;
// KDF for Reply Key Section // KDF for Reply Key Section
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk) m_EphemeralKeys.Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk) m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
// calulate hash for zero length // calculate hash for zero length
if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
{ {
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
return false; return false;
} }
MixHash (out + offset, 16); // h = SHA256(h || ciphertext) MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
offset += 16; offset += 16;
// KDF for payload // KDF for payload
uint8_t keydata[64]; uint8_t keydata[64];
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
// k_ab = keydata[0:31], k_ba = keydata[32:63] // k_ab = keydata[0:31], k_ba = keydata[32:63]
auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
receiveTagset->NextSessionTagRatchet (); receiveTagset->NextSessionTagRatchet ();
m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
m_SendTagset->NextSessionTagRatchet (); m_SendTagset->NextSessionTagRatchet ();
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS); GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS);
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
// encrypt payload // encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
{ {
LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed");
return false; return false;
} }
m_State = eSessionStateNewSessionReplySent; m_State = eSessionStateNewSessionReplySent;
return true; return true;
} }
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
// we are Bob and sent NSR already // we are Bob and sent NSR already
uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag
memcpy (out, &tag, 8); memcpy (out, &tag, 8);
memcpy (out + 8, m_NSREncodedKey, 32); memcpy (out + 8, m_NSREncodedKey, 32);
// recalculte h with new tag // recalculate h with new tag
memcpy (m_H, m_NSRH, 32); memcpy (m_H, m_NSRH, 32);
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk) MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
@ -482,7 +482,7 @@ namespace garlic
} }
MixHash (out + 40, 16); // h = SHA256(h || ciphertext) MixHash (out + 40, 16); // h = SHA256(h || ciphertext)
// encrypt payload // encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
{ {
LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed");
return false; return false;
@ -490,36 +490,36 @@ namespace garlic
return true; return true;
} }
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len) bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
{ {
// we are Alice // we are Alice
LogPrint (eLogDebug, "Garlic: reply received"); LogPrint (eLogDebug, "Garlic: reply received");
const uint8_t * tag = buf; const uint8_t * tag = buf;
buf += 8; len -= 8; // tag buf += 8; len -= 8; // tag
uint8_t bepk[32]; // Bob's ephemeral key uint8_t bepk[32]; // Bob's ephemeral key
if (!i2p::crypto::GetElligator ()->Decode (buf, bepk)) if (!i2p::crypto::GetElligator ()->Decode (buf, bepk))
{ {
LogPrint (eLogError, "Garlic: Can't decode elligator"); LogPrint (eLogError, "Garlic: Can't decode elligator");
return false; return false;
} }
buf += 32; len -= 32; buf += 32; len -= 32;
// KDF for Reply Key Section // KDF for Reply Key Section
uint8_t h[32]; memcpy (h, m_H, 32); // save m_H uint8_t h[32]; memcpy (h, m_H, 32); // save m_H
MixHash (tag, 8); // h = SHA256(h || tag) MixHash (tag, 8); // h = SHA256(h || tag)
MixHash (bepk, 32); // h = SHA256(h || bepk) MixHash (bepk, 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
if (m_State == eSessionStateNewSessionSent) if (m_State == eSessionStateNewSessionSent)
{ {
// only fist time, we assume ephemeral keys the same // only fist time, we assume ephemeral keys the same
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk) GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
} }
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
// calulate hash for zero length // calculate hash for zero length
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anyting */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anything */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only
{ {
LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed"); LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed");
return false; return false;
@ -527,22 +527,22 @@ namespace garlic
MixHash (buf, 16); // h = SHA256(h || ciphertext) MixHash (buf, 16); // h = SHA256(h || ciphertext)
buf += 16; len -= 16; buf += 16; len -= 16;
// KDF for payload // KDF for payload
uint8_t keydata[64]; uint8_t keydata[64];
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64) i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
if (m_State == eSessionStateNewSessionSent) if (m_State == eSessionStateNewSessionSent)
{ {
// k_ab = keydata[0:31], k_ba = keydata[32:63] // k_ab = keydata[0:31], k_ba = keydata[32:63]
m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab) m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
m_SendTagset->NextSessionTagRatchet (); m_SendTagset->NextSessionTagRatchet ();
auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba) receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
receiveTagset->NextSessionTagRatchet (); receiveTagset->NextSessionTagRatchet ();
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS); GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS);
} }
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
// decrypt payload // decrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt
{ {
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
return false; return false;
@ -560,8 +560,8 @@ namespace garlic
SetLeaseSetUpdateStatus (eLeaseSetUpToDate); SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
SetLeaseSetUpdateMsgID (0); SetLeaseSetUpdateMsgID (0);
return true; return true;
} }
bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
@ -637,61 +637,61 @@ namespace garlic
return true; return true;
} }
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{ {
auto payload = CreatePayload (msg, m_State != eSessionStateEstablished); auto payload = CreatePayload (msg, m_State != eSessionStateEstablished);
size_t len = payload.size (); size_t len = payload.size ();
if (!len) return nullptr; if (!len) return nullptr;
auto m = NewI2NPMessage (len + 100); // 96 + 4 auto m = NewI2NPMessage (len + 100); // 96 + 4
m->Align (12); // in order to get buf aligned to 16 (12 + 4) m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
switch (m_State) switch (m_State)
{ {
case eSessionStateEstablished: case eSessionStateEstablished:
if (!NewExistingSessionMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NewExistingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr; return nullptr;
len += 24; len += 24;
break; break;
case eSessionStateNew: case eSessionStateNew:
if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr; return nullptr;
len += 96; len += 96;
break; break;
case eSessionStateNewSessionReceived: case eSessionStateNewSessionReceived:
if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr; return nullptr;
len += 72; len += 72;
break; break;
case eSessionStateNewSessionReplySent: case eSessionStateNewSessionReplySent:
if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen)) if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
return nullptr; return nullptr;
len += 72; len += 72;
break; break;
default: default:
return nullptr; return nullptr;
} }
htobe32buf (m->GetPayload (), len); htobe32buf (m->GetPayload (), len);
m->len += len + 4; m->len += len + 4;
m->FillI2NPMessageHeader (eI2NPGarlic); m->FillI2NPMessageHeader (eI2NPGarlic);
return m; return m;
} }
std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first) std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first)
{ {
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
size_t payloadLen = 0; size_t payloadLen = 0;
if (first) payloadLen += 7;// datatime if (first) payloadLen += 7;// datatime
if (msg && m_Destination) if (msg && m_Destination)
payloadLen += msg->GetPayloadLength () + 13 + 32; payloadLen += msg->GetPayloadLength () + 13 + 32;
auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated || auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated ||
(GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted &&
ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ? ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ?
GetOwner ()->GetLeaseSet () : nullptr; GetOwner ()->GetLeaseSet () : nullptr;
if (leaseSet) if (leaseSet)
{ {
payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13; payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13;
if (!first) if (!first)
{ {
// ack request // ack request
@ -730,19 +730,19 @@ namespace garlic
payloadLen += paddingSize + 3; payloadLen += paddingSize + 3;
} }
} }
std::vector<uint8_t> v(payloadLen); std::vector<uint8_t> v(payloadLen);
size_t offset = 0; size_t offset = 0;
// DateTime // DateTime
if (first) if (first)
{ {
v[offset] = eECIESx25519BlkDateTime; offset++; v[offset] = eECIESx25519BlkDateTime; offset++;
htobe16buf (v.data () + offset, 4); offset += 2; htobe16buf (v.data () + offset, 4); offset += 2;
htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds
} }
// LeaseSet // LeaseSet
if (leaseSet) if (leaseSet)
{ {
offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset); offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset);
if (!first) if (!first)
{ {
// ack request // ack request
@ -752,13 +752,13 @@ namespace garlic
} }
} }
// msg // msg
if (msg && m_Destination) if (msg && m_Destination)
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true); offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true);
// ack // ack
if (m_AckRequests.size () > 0) if (m_AckRequests.size () > 0)
{ {
v[offset] = eECIESx25519BlkAck; offset++; v[offset] = eECIESx25519BlkAck; offset++;
htobe16buf (v.data () + offset, m_AckRequests.size ()*4); offset += 2; htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2;
for (auto& it: m_AckRequests) for (auto& it: m_AckRequests)
{ {
htobe16buf (v.data () + offset, it.first); offset += 2; htobe16buf (v.data () + offset, it.first); offset += 2;
@ -801,24 +801,24 @@ namespace garlic
offset += 32; // public key offset += 32; // public key
} }
} }
// padding // padding
if (paddingSize) if (paddingSize)
{ {
v[offset] = eECIESx25519BlkPadding; offset++; v[offset] = eECIESx25519BlkPadding; offset++;
htobe16buf (v.data () + offset, paddingSize); offset += 2; htobe16buf (v.data () + offset, paddingSize); offset += 2;
memset (v.data () + offset, 0, paddingSize); offset += paddingSize; memset (v.data () + offset, 0, paddingSize); offset += paddingSize;
} }
return v; return v;
} }
size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination) size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination)
{ {
if (!msg) return 0; if (!msg) return 0;
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1; uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
if (isDestination) cloveSize += 32; if (isDestination) cloveSize += 32;
if ((int)len < cloveSize + 3) return 0; if ((int)len < cloveSize + 3) return 0;
buf[0] = eECIESx25519BlkGalicClove; // clove type buf[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (buf + 1, cloveSize); // size htobe16buf (buf + 1, cloveSize); // size
buf += 3; buf += 3;
if (isDestination) if (isDestination)
{ {
@ -828,15 +828,15 @@ namespace garlic
else else
*buf = 0; *buf = 0;
buf++; // flag and delivery instructions buf++; // flag and delivery instructions
*buf = msg->GetTypeID (); // I2NP msg type *buf = msg->GetTypeID (); // I2NP msg type
htobe32buf (buf + 1, msg->GetMsgID ()); // msgID htobe32buf (buf + 1, msg->GetMsgID ()); // msgID
htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds htobe32buf (buf + 5, msg->GetExpiration () / 1000); // expiration in seconds
memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ()); memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
return cloveSize + 3; return cloveSize + 3;
} }
size_t ECIESX25519AEADRatchetSession::CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len) size_t ECIESX25519AEADRatchetSession::CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len)
{ {
if (!ls || ls->GetStoreType () != i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) if (!ls || ls->GetStoreType () != i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2)
{ {
LogPrint (eLogError, "Garlic: Incorrect LeasetSet type to send"); LogPrint (eLogError, "Garlic: Incorrect LeasetSet type to send");
@ -845,7 +845,7 @@ namespace garlic
uint16_t cloveSize = 1 + 9 + DATABASE_STORE_HEADER_SIZE + ls->GetBufferLen (); // to local uint16_t cloveSize = 1 + 9 + DATABASE_STORE_HEADER_SIZE + ls->GetBufferLen (); // to local
if ((int)len < cloveSize + 3) return 0; if ((int)len < cloveSize + 3) return 0;
buf[0] = eECIESx25519BlkGalicClove; // clove type buf[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (buf + 1, cloveSize); // size htobe16buf (buf + 1, cloveSize); // size
buf += 3; buf += 3;
*buf = 0; buf++; // flag and delivery instructions *buf = 0; buf++; // flag and delivery instructions
*buf = eI2NPDatabaseStore; buf++; // I2NP msg type *buf = eI2NPDatabaseStore; buf++; // I2NP msg type
@ -885,14 +885,14 @@ namespace garlic
auto payload = buf + offset; auto payload = buf + offset;
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1; uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
size_t len = cloveSize + 3; size_t len = cloveSize + 3;
payload[0] = eECIESx25519BlkGalicClove; // clove type payload[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (payload + 1, cloveSize); // size htobe16buf (payload + 1, cloveSize); // size
payload += 3; payload += 3;
*payload = 0; payload++; // flag and delivery instructions *payload = 0; payload++; // flag and delivery instructions
*payload = msg->GetTypeID (); // I2NP msg type *payload = msg->GetTypeID (); // I2NP msg type
htobe32buf (payload + 1, msg->GetMsgID ()); // msgID htobe32buf (payload + 1, msg->GetMsgID ()); // msgID
htobe32buf (payload + 5, msg->GetExpiration ()/1000); // expiration in seconds htobe32buf (payload + 5, msg->GetExpiration () / 1000); // expiration in seconds
memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ()); memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt
{ {
@ -909,5 +909,3 @@ namespace garlic
} }
} }

@ -26,19 +26,19 @@ namespace garlic
const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160; const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160;
const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12; const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12;
const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */ const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */ // - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
class ECIESX25519AEADRatchetSession; class ECIESX25519AEADRatchetSession;
class RatchetTagSet class RatchetTagSet
{ {
public: public:
RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {}; RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
void DHInitialize (const uint8_t * rootKey, const uint8_t * k); void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
void NextSessionTagRatchet (); void NextSessionTagRatchet ();
uint64_t GetNextSessionTag (); uint64_t GetNextSessionTag ();
const uint8_t * GetNextRootKey () const { return m_NextRootKey; }; const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
int GetNextIndex () const { return m_NextIndex; }; int GetNextIndex () const { return m_NextIndex; };
void GetSymmKey (int index, uint8_t * key); void GetSymmKey (int index, uint8_t * key);
@ -52,51 +52,51 @@ namespace garlic
private: private:
union union
{ {
uint64_t ll[8]; uint64_t ll[8];
uint8_t buf[64]; uint8_t buf[64];
const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31] const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63] const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39] uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
} m_KeyData; } m_KeyData;
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32]; uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
int m_NextIndex, m_NextSymmKeyIndex; int m_NextIndex, m_NextSymmKeyIndex;
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys; std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session; std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
int m_TagSetID = 0; int m_TagSetID = 0;
uint64_t m_ExpirationTimestamp = 0; uint64_t m_ExpirationTimestamp = 0;
}; };
enum ECIESx25519BlockType enum ECIESx25519BlockType
{ {
eECIESx25519BlkDateTime = 0, eECIESx25519BlkDateTime = 0,
eECIESx25519BlkSessionID = 1, eECIESx25519BlkSessionID = 1,
eECIESx25519BlkTermination = 4, eECIESx25519BlkTermination = 4,
eECIESx25519BlkOptions = 5, eECIESx25519BlkOptions = 5,
eECIESx25519BlkNextKey = 7, eECIESx25519BlkNextKey = 7,
eECIESx25519BlkAck = 8, eECIESx25519BlkAck = 8,
eECIESx25519BlkAckRequest = 9, eECIESx25519BlkAckRequest = 9,
eECIESx25519BlkGalicClove = 11, eECIESx25519BlkGalicClove = 11,
eECIESx25519BlkPadding = 254 eECIESx25519BlkPadding = 254
}; };
const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01; const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01;
const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02; const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02;
const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04; const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04;
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession> class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
{ {
enum SessionState enum SessionState
{ {
eSessionStateNew =0, eSessionStateNew = 0,
eSessionStateNewSessionReceived, eSessionStateNewSessionReceived,
eSessionStateNewSessionSent, eSessionStateNewSessionSent,
eSessionStateNewSessionReplySent, eSessionStateNewSessionReplySent,
eSessionStateEstablished eSessionStateEstablished
}; };
struct DHRatchet struct DHRatchet
{ {
@ -106,15 +106,15 @@ namespace garlic
bool newKey = true; bool newKey = true;
}; };
public: public:
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet); ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
~ECIESX25519AEADRatchetSession (); ~ECIESX25519AEADRatchetSession ();
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0); bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg); std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); } void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
void SetDestination (const i2p::data::IdentHash& dest) // TODO: void SetDestination (const i2p::data::IdentHash& dest) // TODO:
@ -127,41 +127,41 @@ namespace garlic
bool IsRatchets () const { return true; }; bool IsRatchets () const { return true; };
private: private:
void ResetKeys (); void ResetKeys ();
void MixHash (const uint8_t * buf, size_t len); void MixHash (const uint8_t * buf, size_t len);
void CreateNonce (uint64_t seqn, uint8_t * nonce); void CreateNonce (uint64_t seqn, uint8_t * nonce);
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
std::shared_ptr<RatchetTagSet> CreateNewSessionTagset (); std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
bool HandleNewIncomingSession (const uint8_t * buf, size_t len); bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len); bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index); bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index);
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index); void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index);
void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset); void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset);
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen); bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first); std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false); size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len); size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
void GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags); void GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags);
void NewNextSendRatchet (); void NewNextSendRatchet ();
private: private:
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32]; uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
i2p::crypto::X25519Keys m_EphemeralKeys; i2p::crypto::X25519Keys m_EphemeralKeys;
SessionState m_State = eSessionStateNew; SessionState m_State = eSessionStateNew;
uint64_t m_LastActivityTimestamp = 0; // incoming uint64_t m_LastActivityTimestamp = 0; // incoming
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset; std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index) std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
bool m_SendReverseKey = false, m_SendForwardKey = false; bool m_SendReverseKey = false, m_SendForwardKey = false;
@ -175,7 +175,7 @@ namespace garlic
{ {
return m_Destination ? *m_Destination : i2p::data::IdentHash (); return m_Destination ? *m_Destination : i2p::data::IdentHash ();
} }
}; };
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag); std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
} }

@ -597,4 +597,3 @@ namespace crypto
} }
} }
} }

@ -128,6 +128,4 @@ namespace crypto
} }
} }
#endif #endif

@ -41,7 +41,7 @@ namespace crypto
} }
bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const
{ {
bool ret = true; bool ret = true;
BN_CTX * ctx = BN_CTX_new (); BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx); BN_CTX_start (ctx);
@ -63,11 +63,11 @@ namespace crypto
if (Legendre (uxxA, ctx) != -1) if (Legendre (uxxA, ctx) != -1)
{ {
uint8_t randByte = 0; // random highest bits and high y uint8_t randByte = 0; // random highest bits and high y
if (random) if (random)
{ {
RAND_bytes (&randByte, 1); RAND_bytes (&randByte, 1);
highY = randByte & 0x01; highY = randByte & 0x01;
} }
BIGNUM * r = BN_CTX_get (ctx); BIGNUM * r = BN_CTX_get (ctx);
@ -87,7 +87,7 @@ namespace crypto
bn2buf (r, encoded, 32); bn2buf (r, encoded, 32);
if (random) if (random)
encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
for (size_t i = 0; i < 16; i++) // To Little Endian for (size_t i = 0; i < 16; i++) // To Little Endian
{ {
uint8_t tmp = encoded[i]; uint8_t tmp = encoded[i];
@ -115,7 +115,7 @@ namespace crypto
encoded1[i] = encoded[31 - i]; encoded1[i] = encoded[31 - i];
encoded1[31 - i] = encoded[i]; encoded1[31 - i] = encoded[i];
} }
encoded1[0] &= 0x3F; // drop two highest bits encoded1[0] &= 0x3F; // drop two highest bits
BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r); BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r);
@ -184,7 +184,7 @@ namespace crypto
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
if (BN_is_word(r, 1)) if (BN_is_word(r, 1))
return 1; return 1;
else if (BN_is_zero(r)) else if (BN_is_zero(r))
return 0; return 0;
return -1; return -1;
} }
@ -204,4 +204,3 @@ namespace crypto
} }
} }
} }

@ -35,5 +35,3 @@ namespace crypto
} }
#endif #endif

@ -17,133 +17,136 @@
namespace i2p { namespace i2p {
namespace fs { namespace fs {
extern std::string dirSep; extern std::string dirSep;
/** /**
* @brief Class to work with NetDb & Router profiles * @brief Class to work with NetDb & Router profiles
* *
* Usage: * Usage:
* *
* const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; * const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
* auto h = HashedStorage("name", "y", "z-", ".txt"); * auto h = HashedStorage("name", "y", "z-", ".txt");
* h.SetPlace("/tmp/hs-test"); * h.SetPlace("/tmp/hs-test");
* h.GetName() -> gives "name" * h.GetName() -> gives "name"
* h.GetRoot() -> gives "/tmp/hs-test/name" * h.GetRoot() -> gives "/tmp/hs-test/name"
* h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet * h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet
* h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt * h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt
* h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists * h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists
* std::vector<std::string> files; * std::vector<std::string> files;
* h.Traverse(files); <- finds all files in storage and saves in given vector * h.Traverse(files); <- finds all files in storage and saves in given vector
*/ */
class HashedStorage { class HashedStorage
protected: {
std::string root; /**< path to storage with it's name included */ protected:
std::string name; /**< name of the storage */
std::string prefix1; /**< hashed directory prefix */ std::string root; /**< path to storage with it's name included */
std::string prefix2; /**< prefix of file in storage */ std::string name; /**< name of the storage */
std::string suffix; /**< suffix of file in storage (extension) */ std::string prefix1; /**< hashed directory prefix */
std::string prefix2; /**< prefix of file in storage */
public: std::string suffix; /**< suffix of file in storage (extension) */
typedef std::function<void(const std::string &)> FilenameVisitor;
HashedStorage(const char *n, const char *p1, const char *p2, const char *s): public:
name(n), prefix1(p1), prefix2(p2), suffix(s) {};
typedef std::function<void(const std::string &)> FilenameVisitor;
/** create subdirs in storage */ HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
bool Init(const char* chars, size_t cnt); name(n), prefix1(p1), prefix2(p2), suffix(s) {};
const std::string & GetRoot() const { return root; }
const std::string & GetName() const { return name; } /** create subdirs in storage */
/** set directory where to place storage directory */ bool Init(const char* chars, size_t cnt);
void SetPlace(const std::string & path); const std::string & GetRoot() const { return root; }
/** path to file with given ident */ const std::string & GetName() const { return name; }
std::string Path(const std::string & ident) const; /** set directory where to place storage directory */
/** remove file by ident */ void SetPlace(const std::string & path);
void Remove(const std::string & ident); /** path to file with given ident */
/** find all files in storage and store list in provided vector */ std::string Path(const std::string & ident) const;
void Traverse(std::vector<std::string> & files); /** remove file by ident */
/** visit every file in this storage with a visitor */ void Remove(const std::string & ident);
void Iterate(FilenameVisitor v); /** find all files in storage and store list in provided vector */
}; void Traverse(std::vector<std::string> & files);
/** visit every file in this storage with a visitor */
/** @brief Returns current application name, default 'i2pd' */ void Iterate(FilenameVisitor v);
};
/** @brief Returns current application name, default 'i2pd' */
const std::string & GetAppName (); const std::string & GetAppName ();
/** @brief Set application name, affects autodetection of datadir */ /** @brief Set application name, affects autodetection of datadir */
void SetAppName (const std::string& name); void SetAppName (const std::string& name);
/** @brief Returns datadir path */ /** @brief Returns datadir path */
const std::string & GetDataDir(); const std::string & GetDataDir();
/** /**
* @brief Set datadir either from cmdline option or using autodetection * @brief Set datadir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --datadir=<something> * @param cmdline_param Value of cmdline parameter --datadir=<something>
* @param isService Value of cmdline parameter --service * @param isService Value of cmdline parameter --service
* *
* Examples of autodetected paths: * Examples of autodetected paths:
* *
* Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\ * Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\
* Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\ * Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/ * Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/ * Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
*/ */
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false); void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
/** /**
* @brief Create subdirectories inside datadir * @brief Create subdirectories inside datadir
*/ */
bool Init(); bool Init();
/** /**
* @brief Get list of files in directory * @brief Get list of files in directory
* @param path Path to directory * @param path Path to directory
* @param files Vector to store found files * @param files Vector to store found files
* @return true on success and false if directory not exists * @return true on success and false if directory not exists
*/ */
bool ReadDir(const std::string & path, std::vector<std::string> & files); bool ReadDir(const std::string & path, std::vector<std::string> & files);
/** /**
* @brief Remove file with given path * @brief Remove file with given path
* @param path Absolute path to file * @param path Absolute path to file
* @return true on success, false if file not exists, throws exception on error * @return true on success, false if file not exists, throws exception on error
*/ */
bool Remove(const std::string & path); bool Remove(const std::string & path);
/** /**
* @brief Check existence of file * @brief Check existence of file
* @param path Absolute path to file * @param path Absolute path to file
* @return true if file exists, false otherwise * @return true if file exists, false otherwise
*/ */
bool Exists(const std::string & path); bool Exists(const std::string & path);
uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
bool CreateDirectory (const std::string& path); bool CreateDirectory (const std::string& path);
template<typename T> template<typename T>
void _ExpandPath(std::stringstream & path, T c) { void _ExpandPath(std::stringstream & path, T c) {
path << i2p::fs::dirSep << c; path << i2p::fs::dirSep << c;
} }
template<typename T, typename ... Other> template<typename T, typename ... Other>
void _ExpandPath(std::stringstream & path, T c, Other ... other) { void _ExpandPath(std::stringstream & path, T c, Other ... other) {
_ExpandPath(path, c); _ExpandPath(path, c);
_ExpandPath(path, other ...); _ExpandPath(path, other ...);
} }
/** /**
* @brief Get path relative to datadir * @brief Get path relative to datadir
* *
* Examples (with datadir = "/tmp/i2pd"): * Examples (with datadir = "/tmp/i2pd"):
* *
* i2p::fs::Path("test") -> '/tmp/i2pd/test' * i2p::fs::Path("test") -> '/tmp/i2pd/test'
* i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt' * i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt'
*/ */
template<typename ... Other> template<typename ... Other>
std::string DataDirPath(Other ... components) { std::string DataDirPath(Other ... components) {
std::stringstream s(""); std::stringstream s("");
s << i2p::fs::GetDataDir(); s << i2p::fs::GetDataDir();
_ExpandPath(s, components ...); _ExpandPath(s, components ...);
return s.str(); return s.str();
} }
template<typename Storage, typename... Filename> template<typename Storage, typename... Filename>
std::string StorageRootPath (const Storage& storage, Filename... filenames) std::string StorageRootPath (const Storage& storage, Filename... filenames)

@ -179,4 +179,3 @@ namespace data
} }
} }
} }

@ -38,9 +38,9 @@ namespace garlic
if (!m_SharedRoutingPath) return nullptr; if (!m_SharedRoutingPath) return nullptr;
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED || if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED ||
!m_SharedRoutingPath->outboundTunnel->IsEstablished () || !m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate || ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT) ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
m_SharedRoutingPath = nullptr; m_SharedRoutingPath = nullptr;
if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++; if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++;
return m_SharedRoutingPath; return m_SharedRoutingPath;
@ -96,10 +96,10 @@ namespace garlic
return msg; return msg;
} }
ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner, ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet): std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
GarlicRoutingSession (owner, attachLeaseSet), GarlicRoutingSession (owner, attachLeaseSet),
m_Destination (destination), m_NumTags (numTags) m_Destination (destination), m_NumTags (numTags)
{ {
// create new session tags and session key // create new session tags and session key
RAND_bytes (m_SessionKey, 32); RAND_bytes (m_SessionKey, 32);
@ -115,7 +115,7 @@ namespace garlic
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch (); m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
} }
std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{ {
auto m = NewI2NPMessage (); auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4) m->Align (12); // in order to get buf aligned to 16 (12 + 4)
@ -181,7 +181,7 @@ namespace garlic
return m; return m;
} }
size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg) size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
{ {
size_t blockSize = 0; size_t blockSize = 0;
bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3); bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3);
@ -353,7 +353,7 @@ namespace garlic
return size; return size;
} }
ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags () ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
{ {
auto tags = new UnconfirmedTags (m_NumTags); auto tags = new UnconfirmedTags (m_NumTags);
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch (); tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
@ -525,7 +525,7 @@ namespace garlic
// otherwise ECIESx25519 // otherwise ECIESx25519
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
if (!session->HandleNextMessage (buf, length, nullptr, 0)) if (!session->HandleNextMessage (buf, length, nullptr, 0))
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
} }
else else
LogPrint (eLogError, "Garlic: Failed to decrypt message"); LogPrint (eLogError, "Garlic: Failed to decrypt message");
@ -703,41 +703,41 @@ namespace garlic
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession ( std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet) std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
{ {
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET && if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)) SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
{ {
ECIESX25519AEADRatchetSessionPtr session; ECIESX25519AEADRatchetSessionPtr session;
uint8_t staticKey[32]; uint8_t staticKey[32];
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
auto it = m_ECIESx25519Sessions.find (staticKey); auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ()) if (it != m_ECIESx25519Sessions.end ())
session = it->second; session = it->second;
if (!session) if (!session)
{ {
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true); session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
session->SetRemoteStaticKey (staticKey); session->SetRemoteStaticKey (staticKey);
} }
session->SetDestination (destination->GetIdentHash ()); // TODO: remove session->SetDestination (destination->GetIdentHash ()); // TODO: remove
return session; return session;
} }
else else
{ {
ElGamalAESSessionPtr session; ElGamalAESSessionPtr session;
{ {
std::unique_lock<std::mutex> l(m_SessionsMutex); std::unique_lock<std::mutex> l(m_SessionsMutex);
auto it = m_Sessions.find (destination->GetIdentHash ()); auto it = m_Sessions.find (destination->GetIdentHash ());
if (it != m_Sessions.end ()) if (it != m_Sessions.end ())
session = it->second; session = it->second;
} }
if (!session) if (!session)
{ {
session = std::make_shared<ElGamalAESSession> (this, destination, session = std::make_shared<ElGamalAESSession> (this, destination,
attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
std::unique_lock<std::mutex> l(m_SessionsMutex); std::unique_lock<std::mutex> l(m_SessionsMutex);
m_Sessions[destination->GetIdentHash ()] = session; m_Sessions[destination->GetIdentHash ()] = session;
} }
return session; return session;
} }
} }
void GarlicDestination::CleanupExpiredTags () void GarlicDestination::CleanupExpiredTags ()
@ -925,20 +925,20 @@ namespace garlic
std::vector<std::string> files; std::vector<std::string> files;
i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files); i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it: files) for (auto it: files)
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT) if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
i2p::fs::Remove (it); i2p::fs::Remove (it);
} }
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len) void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
{ {
const uint8_t * buf1 = buf; const uint8_t * buf1 = buf;
uint8_t flag = buf[0]; buf++; // flag uint8_t flag = buf[0]; buf++; // flag
GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
switch (deliveryType) switch (deliveryType)
{ {
case eGarlicDeliveryTypeDestination: case eGarlicDeliveryTypeDestination:
LogPrint (eLogDebug, "Garlic: type destination"); LogPrint (eLogDebug, "Garlic: type destination");
buf += 32; // TODO: check destination buf += 32; // TODO: check destination
#if (__cplusplus >= 201703L) // C++ 17 or higher #if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]]; [[fallthrough]];
@ -946,7 +946,7 @@ namespace garlic
// no break here // no break here
case eGarlicDeliveryTypeLocal: case eGarlicDeliveryTypeLocal:
{ {
LogPrint (eLogDebug, "Garlic: type local"); LogPrint (eLogDebug, "Garlic: type local");
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
buf += (4 + 4); // msgID + expiration buf += (4 + 4); // msgID + expiration
ptrdiff_t offset = buf - buf1; ptrdiff_t offset = buf - buf1;
@ -957,8 +957,8 @@ namespace garlic
break; break;
} }
case eGarlicDeliveryTypeTunnel: case eGarlicDeliveryTypeTunnel:
{ {
LogPrint (eLogDebug, "Garlic: type tunnel"); LogPrint (eLogDebug, "Garlic: type tunnel");
// gwHash and gwTunnel sequence is reverted // gwHash and gwTunnel sequence is reverted
const uint8_t * gwHash = buf; const uint8_t * gwHash = buf;
buf += 32; buf += 32;
@ -969,32 +969,32 @@ namespace garlic
break; break;
} }
uint32_t gwTunnel = bufbe32toh (buf); buf += 4; uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
buf += (4 + 4); // msgID + expiration buf += (4 + 4); // msgID + expiration
offset += 13; offset += 13;
if (GetTunnelPool ()) if (GetTunnelPool ())
{ {
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel (); auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
if (tunnel) if (tunnel)
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset)); tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
else else
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove"); LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
} }
else else
LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel"); LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
break; break;
} }
default: default:
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
} }
} }
void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset) void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
{ {
auto index = tagset->GetNextIndex (); auto index = tagset->GetNextIndex ();
uint64_t tag = tagset->GetNextSessionTag (); uint64_t tag = tagset->GetNextSessionTag ();
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()}); m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
} }
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session) void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
{ {

@ -87,7 +87,7 @@ namespace garlic
class GarlicDestination; class GarlicDestination;
class GarlicRoutingSession class GarlicRoutingSession
{ {
protected: protected:
enum LeaseSetUpdateStatus enum LeaseSetUpdateStatus
{ {
@ -103,7 +103,7 @@ namespace garlic
GarlicRoutingSession (); GarlicRoutingSession ();
virtual ~GarlicRoutingSession (); virtual ~GarlicRoutingSession ();
virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0; virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0;
virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
virtual bool MessageConfirmed (uint32_t msgID); virtual bool MessageConfirmed (uint32_t msgID);
virtual bool IsRatchets () const { return false; }; virtual bool IsRatchets () const { return false; };
@ -122,13 +122,13 @@ namespace garlic
GarlicDestination * GetOwner () const { return m_Owner; } GarlicDestination * GetOwner () const { return m_Owner; }
void SetOwner (GarlicDestination * owner) { m_Owner = owner; } void SetOwner (GarlicDestination * owner) { m_Owner = owner; }
protected: protected:
LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; } LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; } void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; } uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; } void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; } void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
std::shared_ptr<I2NPMessage> CreateEncryptedDeliveryStatusMsg (uint32_t msgID); std::shared_ptr<I2NPMessage> CreateEncryptedDeliveryStatusMsg (uint32_t msgID);
@ -143,38 +143,39 @@ namespace garlic
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath; std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
public: public:
// for HTTP only // for HTTP only
virtual size_t GetNumOutgoingTags () const { return 0; }; virtual size_t GetNumOutgoingTags () const { return 0; };
}; };
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>; //using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this<ElGamalAESSession> class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this<ElGamalAESSession>
{ {
struct UnconfirmedTags struct UnconfirmedTags
{ {
UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; }; UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
~UnconfirmedTags () { delete[] sessionTags; }; ~UnconfirmedTags () { delete[] sessionTags; };
uint32_t msgID; uint32_t msgID;
int numTags; int numTags;
SessionTag * sessionTags; SessionTag * sessionTags;
uint32_t tagsCreationTime; uint32_t tagsCreationTime;
}; };
public: public:
ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination, ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
int numTags, bool attachLeaseSet); int numTags, bool attachLeaseSet);
ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption
~ElGamalAESSession () {}; ~ElGamalAESSession () {};
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg); std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
bool MessageConfirmed (uint32_t msgID); bool MessageConfirmed (uint32_t msgID);
bool CleanupExpiredTags (); // returns true if something left bool CleanupExpiredTags (); // returns true if something left
bool CleanupUnconfirmedTags (); // returns true if something has been deleted bool CleanupUnconfirmedTags (); // returns true if something has been deleted
private: private:
size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg); size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg);
size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags); size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags);
@ -184,25 +185,26 @@ namespace garlic
void TagsConfirmed (uint32_t msgID); void TagsConfirmed (uint32_t msgID);
UnconfirmedTags * GenerateSessionTags (); UnconfirmedTags * GenerateSessionTags ();
private: private:
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination; std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
i2p::crypto::AESKey m_SessionKey; i2p::crypto::AESKey m_SessionKey;
std::list<SessionTag> m_SessionTags; std::list<SessionTag> m_SessionTags;
int m_NumTags; int m_NumTags;
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
i2p::crypto::CBCEncryption m_Encryption; i2p::crypto::CBCEncryption m_Encryption;
public:
public:
// for HTTP only // for HTTP only
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
}; };
typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr; typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr;
class ECIESX25519AEADRatchetSession; class ECIESX25519AEADRatchetSession;
typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr; typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
class RatchetTagSet; class RatchetTagSet;
typedef std::shared_ptr<RatchetTagSet> RatchetTagSetPtr; typedef std::shared_ptr<RatchetTagSet> RatchetTagSetPtr;
struct ECIESX25519AEADRatchetIndexTagset struct ECIESX25519AEADRatchetIndexTagset
@ -226,12 +228,12 @@ namespace garlic
void CleanupExpiredTags (); void CleanupExpiredTags ();
void RemoveDeliveryStatusSession (uint32_t msgID); void RemoveDeliveryStatusSession (uint32_t msgID);
std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination, std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false); std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset); void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
void RemoveECIESx25519Session (const uint8_t * staticKey); void RemoveECIESx25519Session (const uint8_t * staticKey);
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
@ -266,10 +268,10 @@ namespace garlic
int m_NumTags; int m_NumTags;
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions; std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
// incoming // incoming
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags; std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
// DeliveryStatus // DeliveryStatus
std::mutex m_DeliveryStatusSessionsMutex; std::mutex m_DeliveryStatusSessionsMutex;
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session

@ -13,11 +13,11 @@ namespace crypto
enum GOSTR3410ParamSet enum GOSTR3410ParamSet
{ {
eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1 eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1
// XchA = A, XchB = C // XchA = A, XchB = C
//eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0 //eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0
//eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1
eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1 eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1
eGOSTR3410NumParamSets eGOSTR3410NumParamSets
}; };

@ -45,7 +45,6 @@ namespace data
size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen); // for < 64K size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen); // for < 64K
size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen); // for total size < 64K size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen); // for total size < 64K
} // data } // data
} // i2p } // i2p

@ -180,7 +180,7 @@ namespace i2p
// excluded // excluded
if (cnt > 512) if (cnt > 512)
{ {
LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup"); LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup");
cnt = 0; cnt = 0;
} }
htobe16buf (buf, cnt); htobe16buf (buf, cnt);
@ -205,7 +205,7 @@ namespace i2p
} }
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident,
std::vector<i2p::data::IdentHash> routers) std::vector<i2p::data::IdentHash> routers)
{ {
auto m = NewI2NPShortMessage (); auto m = NewI2NPShortMessage ();
uint8_t * buf = m->GetPayload (); uint8_t * buf = m->GetPayload ();
@ -268,7 +268,7 @@ namespace i2p
auto m = NewI2NPShortMessage (); auto m = NewI2NPShortMessage ();
uint8_t * payload = m->GetPayload (); uint8_t * payload = m->GetPayload ();
memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32); memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32);
payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0);
size_t size = DATABASE_STORE_HEADER_SIZE; size_t size = DATABASE_STORE_HEADER_SIZE;
memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
@ -278,7 +278,7 @@ namespace i2p
return m; return m;
} }
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel) std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
{ {
if (!leaseSet) return nullptr; if (!leaseSet) return nullptr;
auto m = NewI2NPShortMessage (); auto m = NewI2NPShortMessage ();
@ -347,11 +347,11 @@ namespace i2p
auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80, clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80,
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40); clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40);
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0; record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0;
} }
@ -386,7 +386,7 @@ namespace i2p
return; return;
} }
auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID); auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
if (tunnel) if (tunnel)
{ {
// endpoint of inbound tunnel // endpoint of inbound tunnel
@ -414,7 +414,7 @@ namespace i2p
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
eI2NPVariableTunnelBuildReply, buf, len, eI2NPVariableTunnelBuildReply, buf, len,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
} }
else else
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
@ -440,7 +440,7 @@ namespace i2p
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
eI2NPTunnelBuildReply, buf, len, eI2NPTunnelBuildReply, buf, len,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
} }
else else
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
@ -592,13 +592,13 @@ namespace i2p
switch (typeID) switch (typeID)
{ {
case eI2NPVariableTunnelBuild: case eI2NPVariableTunnelBuild:
HandleVariableTunnelBuildMsg (msgID, buf, size); HandleVariableTunnelBuildMsg (msgID, buf, size);
break; break;
case eI2NPVariableTunnelBuildReply: case eI2NPVariableTunnelBuildReply:
HandleVariableTunnelBuildReplyMsg (msgID, buf, size); HandleVariableTunnelBuildReplyMsg (msgID, buf, size);
break; break;
case eI2NPTunnelBuild: case eI2NPTunnelBuild:
HandleTunnelBuildMsg (buf, size); HandleTunnelBuildMsg (buf, size);
break; break;
case eI2NPTunnelBuildReply: case eI2NPTunnelBuildReply:
// TODO: // TODO:
@ -667,7 +667,7 @@ namespace i2p
Flush (); Flush ();
} }
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg) void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
{ {
if (msg) if (msg)
{ {

@ -148,7 +148,7 @@ namespace data
const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; }; const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; };
size_t GetSignatureLen () const; // might not match identity size_t GetSignatureLen () const; // might not match identity
bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; }; bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; };
uint8_t * GetPadding(); uint8_t * GetPadding();
void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); } void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
void Sign (const uint8_t * buf, int len, uint8_t * signature) const; void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
@ -204,7 +204,7 @@ namespace data
IdentHash CreateRoutingKey (const IdentHash& ident); IdentHash CreateRoutingKey (const IdentHash& ident);
XORMetric operator^(const IdentHash& key1, const IdentHash& key2); XORMetric operator^(const IdentHash& key1, const IdentHash& key2);
// destination for delivery instuctions // destination for delivery instructions
class RoutingDestination class RoutingDestination
{ {
public: public:
@ -235,5 +235,4 @@ namespace data
} }
} }
#endif #endif

@ -12,7 +12,6 @@ namespace i2p
{ {
namespace data namespace data
{ {
LeaseSet::LeaseSet (bool storeLeases): LeaseSet::LeaseSet (bool storeLeases):
m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr), m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr),
m_Buffer (nullptr), m_BufferLen (0) m_Buffer (nullptr), m_BufferLen (0)
@ -191,10 +190,10 @@ namespace data
return m_ExpirationTime - now <= dlt; return m_ExpirationTime - now <= dlt;
} }
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
{ {
return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold); return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold);
} }
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const
{ {
@ -423,7 +422,7 @@ namespace data
if (offset + 40 >= len) return 0; if (offset + 40 >= len) return 0;
offset += 32; // hash offset += 32; // hash
offset += 3; // flags offset += 3; // flags
offset += 1; // cost offset += 1; // cost
offset += 4; // expires offset += 4; // expires
} }
// revocations // revocations
@ -771,8 +770,7 @@ namespace data
} }
LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
const KeySections& encryptionKeys, const KeySections& encryptionKeys, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
bool isPublic, bool isPublishedEncrypted): bool isPublic, bool isPublishedEncrypted):
LocalLeaseSet (keys.GetPublic (), nullptr, 0) LocalLeaseSet (keys.GetPublic (), nullptr, 0)
{ {

@ -48,7 +48,7 @@ namespace data
}; };
}; };
typedef std::function<bool(const Lease & l)> LeaseInspectFunc; typedef std::function<bool(const Lease & l)> LeaseInspectFunc;
const size_t MAX_LS_BUFFER_SIZE = 3072; const size_t MAX_LS_BUFFER_SIZE = 3072;
const size_t LEASE_SIZE = 44; // 32 + 4 + 8 const size_t LEASE_SIZE = 44; // 32 + 4 + 8
@ -70,7 +70,7 @@ namespace data
size_t GetBufferLen () const { return m_BufferLen; }; size_t GetBufferLen () const { return m_BufferLen; };
bool IsValid () const { return m_IsValid; }; bool IsValid () const { return m_IsValid; };
const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeases (bool withThreshold = true) const; const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeases (bool withThreshold = true) const;
const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const; const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const;
bool HasExpiredLeases () const; bool HasExpiredLeases () const;
bool IsExpired () const; bool IsExpired () const;
bool IsEmpty () const { return m_Leases.empty (); }; bool IsEmpty () const { return m_Leases.empty (); };
@ -97,7 +97,7 @@ namespace data
// called from LeaseSet2 // called from LeaseSet2
LeaseSet (bool storeLeases); LeaseSet (bool storeLeases);
void SetBuffer (const uint8_t * buf, size_t len); void SetBuffer (const uint8_t * buf, size_t len);
void SetBufferLen (size_t len); void SetBufferLen (size_t len);
void SetIdentity (std::shared_ptr<const IdentityEx> identity) { m_Identity = identity; }; void SetIdentity (std::shared_ptr<const IdentityEx> identity) { m_Identity = identity; };
void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; }; void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; };
void SetIsValid (bool isValid) { m_IsValid = isValid; }; void SetIsValid (bool isValid) { m_IsValid = isValid; };
@ -245,7 +245,8 @@ namespace data
const KeySections& encryptionKeys, const KeySections& encryptionKeys,
std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
bool isPublic, bool isPublishedEncrypted = false); bool isPublic, bool isPublishedEncrypted = false);
LocalLeaseSet2 (uint8_t storeType, std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len); // from I2CP
LocalLeaseSet2 (uint8_t storeType, std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len); // from I2CP
virtual ~LocalLeaseSet2 () { delete[] m_Buffer; }; virtual ~LocalLeaseSet2 () { delete[] m_Buffer; };

@ -29,35 +29,35 @@ struct BigEndian;
template<typename T> template<typename T>
struct LittleEndian struct LittleEndian
{ {
union union
{ {
unsigned char bytes[sizeof(T)]; unsigned char bytes[sizeof(T)];
T raw_value; T raw_value;
}; };
LittleEndian(T t = T()) LittleEndian(T t = T())
{ {
operator =(t); operator =(t);
} }
LittleEndian(const LittleEndian<T> & t) LittleEndian(const LittleEndian<T> & t)
{ {
raw_value = t.raw_value; raw_value = t.raw_value;
} }
LittleEndian(const BigEndian<T> & t) LittleEndian(const BigEndian<T> & t)
{ {
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
bytes[i] = t.bytes[sizeof(T)-1-i]; bytes[i] = t.bytes[sizeof(T)-1-i];
} }
operator const T() const operator const T() const
{ {
T t = T(); T t = T();
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
t |= T(bytes[i]) << (i << 3); t |= T(bytes[i]) << (i << 3);
return t; return t;
} }
const T operator = (const T t) const T operator = (const T t)
{ {
@ -66,68 +66,68 @@ struct LittleEndian
return t; return t;
} }
// operators // operators
const T operator += (const T t) const T operator += (const T t)
{ {
return (*this = *this + t); return (*this = *this + t);
} }
const T operator -= (const T t) const T operator -= (const T t)
{ {
return (*this = *this - t); return (*this = *this - t);
} }
const T operator *= (const T t) const T operator *= (const T t)
{ {
return (*this = *this * t); return (*this = *this * t);
} }
const T operator /= (const T t) const T operator /= (const T t)
{ {
return (*this = *this / t); return (*this = *this / t);
} }
const T operator %= (const T t) const T operator %= (const T t)
{ {
return (*this = *this % t); return (*this = *this % t);
} }
LittleEndian<T> operator ++ (int) LittleEndian<T> operator ++ (int)
{ {
LittleEndian<T> tmp(*this); LittleEndian<T> tmp(*this);
operator ++ (); operator ++ ();
return tmp; return tmp;
} }
LittleEndian<T> & operator ++ () LittleEndian<T> & operator ++ ()
{ {
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
{ {
++bytes[i]; ++bytes[i];
if (bytes[i] != 0) if (bytes[i] != 0)
break; break;
} }
return (*this); return (*this);
} }
LittleEndian<T> operator -- (int) LittleEndian<T> operator -- (int)
{ {
LittleEndian<T> tmp(*this); LittleEndian<T> tmp(*this);
operator -- (); operator -- ();
return tmp; return tmp;
} }
LittleEndian<T> & operator -- () LittleEndian<T> & operator -- ()
{ {
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
{ {
--bytes[i]; --bytes[i];
if (bytes[i] != (T)(-1)) if (bytes[i] != (T)(-1))
break; break;
} }
return (*this); return (*this);
} }
}; };
#pragma pack(pop) #pragma pack(pop)
@ -137,105 +137,105 @@ struct LittleEndian
template<typename T> template<typename T>
struct BigEndian struct BigEndian
{ {
union union
{ {
unsigned char bytes[sizeof(T)]; unsigned char bytes[sizeof(T)];
T raw_value; T raw_value;
}; };
BigEndian(T t = T()) BigEndian(T t = T())
{ {
operator =(t); operator =(t);
} }
BigEndian(const BigEndian<T> & t) BigEndian(const BigEndian<T> & t)
{ {
raw_value = t.raw_value; raw_value = t.raw_value;
} }
BigEndian(const LittleEndian<T> & t) BigEndian(const LittleEndian<T> & t)
{ {
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
bytes[i] = t.bytes[sizeof(T)-1-i]; bytes[i] = t.bytes[sizeof(T)-1-i];
} }
operator const T() const operator const T() const
{ {
T t = T(); T t = T();
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3); t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3);
return t; return t;
} }
const T operator = (const T t) const T operator = (const T t)
{ {
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
bytes[sizeof(T) - 1 - i] = t >> (i << 3); bytes[sizeof(T) - 1 - i] = t >> (i << 3);
return t; return t;
} }
// operators // operators
const T operator += (const T t) const T operator += (const T t)
{ {
return (*this = *this + t); return (*this = *this + t);
} }
const T operator -= (const T t) const T operator -= (const T t)
{ {
return (*this = *this - t); return (*this = *this - t);
} }
const T operator *= (const T t) const T operator *= (const T t)
{ {
return (*this = *this * t); return (*this = *this * t);
} }
const T operator /= (const T t) const T operator /= (const T t)
{ {
return (*this = *this / t); return (*this = *this / t);
} }
const T operator %= (const T t) const T operator %= (const T t)
{ {
return (*this = *this % t); return (*this = *this % t);
} }
BigEndian<T> operator ++ (int) BigEndian<T> operator ++ (int)
{ {
BigEndian<T> tmp(*this); BigEndian<T> tmp(*this);
operator ++ (); operator ++ ();
return tmp; return tmp;
} }
BigEndian<T> & operator ++ () BigEndian<T> & operator ++ ()
{ {
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
{ {
++bytes[sizeof(T) - 1 - i]; ++bytes[sizeof(T) - 1 - i];
if (bytes[sizeof(T) - 1 - i] != 0) if (bytes[sizeof(T) - 1 - i] != 0)
break; break;
} }
return (*this); return (*this);
} }
BigEndian<T> operator -- (int) BigEndian<T> operator -- (int)
{ {
BigEndian<T> tmp(*this); BigEndian<T> tmp(*this);
operator -- (); operator -- ();
return tmp; return tmp;
} }
BigEndian<T> & operator -- () BigEndian<T> & operator -- ()
{ {
for (unsigned i = 0; i < sizeof(T); i++) for (unsigned i = 0; i < sizeof(T); i++)
{ {
--bytes[sizeof(T) - 1 - i]; --bytes[sizeof(T) - 1 - i];
if (bytes[sizeof(T) - 1 - i] != (T)(-1)) if (bytes[sizeof(T) - 1 - i] != (T)(-1))
break; break;
} }
return (*this); return (*this);
} }
}; };
#pragma pack(pop) #pragma pack(pop)

@ -110,18 +110,18 @@ namespace log {
} }
} }
std::string str_tolower(std::string s) { std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(), std::transform(s.begin(), s.end(), s.begin(),
// static_cast<int(*)(int)>(std::tolower) // wrong // static_cast<int(*)(int)>(std::tolower) // wrong
// [](int c){ return std::tolower(c); } // wrong // [](int c){ return std::tolower(c); } // wrong
// [](char c){ return std::tolower(c); } // wrong // [](char c){ return std::tolower(c); } // wrong
[](unsigned char c){ return std::tolower(c); } // correct [](unsigned char c){ return std::tolower(c); } // correct
); );
return s; return s;
} }
void Log::SetLogLevel (const std::string& level_) { void Log::SetLogLevel (const std::string& level_) {
std::string level=str_tolower(level_); std::string level=str_tolower(level_);
if (level == "none") { m_MinLevel = eLogNone; } if (level == "none") { m_MinLevel = eLogNone; }
else if (level == "error") { m_MinLevel = eLogError; } else if (level == "error") { m_MinLevel = eLogError; }
else if (level == "warn") { m_MinLevel = eLogWarning; } else if (level == "warn") { m_MinLevel = eLogWarning; }

@ -157,7 +157,7 @@ namespace log {
ThrowFunction GetThrowFunction (); ThrowFunction GetThrowFunction ();
void SetThrowFunction (ThrowFunction f); void SetThrowFunction (ThrowFunction f);
} // log } // log
} } // i2p
/** internal usage only -- folding args array to single string */ /** internal usage only -- folding args array to single string */
template<typename TValue> template<typename TValue>

@ -114,7 +114,7 @@ namespace transport
void NTCP2Establisher::KDF2Bob () void NTCP2Establisher::KDF2Bob ()
{ {
KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ()); KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ());
} }
void NTCP2Establisher::KDF3Alice () void NTCP2Establisher::KDF3Alice ()
@ -1200,7 +1200,7 @@ namespace transport
continue; continue;
} }
LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port); LogPrint (eLogInfo, "NTCP2: Start listening v4 TCP port ", address->port);
auto conn = std::make_shared<NTCP2Session>(*this); auto conn = std::make_shared<NTCP2Session>(*this);
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1));
} }

@ -126,7 +126,6 @@ namespace transport
{ {
public: public:
NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr); NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
~NTCP2Session (); ~NTCP2Session ();
void Terminate (); void Terminate ();

@ -468,7 +468,7 @@ namespace transport
LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock"); LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock");
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
// this router doesn't like us // this router doesn't like us
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true);
Terminate (); Terminate ();
} }
@ -736,13 +736,11 @@ namespace transport
} }
} }
void NTCPSession::SendTimeSyncMessage () void NTCPSession::SendTimeSyncMessage ()
{ {
Send (nullptr); Send (nullptr);
} }
void NTCPSession::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) void NTCPSession::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
{ {
m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessages, shared_from_this (), msgs)); m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessages, shared_from_this (), msgs));
@ -904,7 +902,6 @@ namespace transport
} }
} }
void NTCPServer::Run () void NTCPServer::Run ()
{ {
while (m_IsRunning) while (m_IsRunning)

@ -390,7 +390,7 @@ namespace data
} }
} }
m_Reseeder->Bootstrap (); m_Reseeder->Bootstrap ();
} }
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills) void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
@ -537,7 +537,7 @@ namespace data
bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
if (checkForExpiration && uptime > 3600) // 1 hour if (checkForExpiration && uptime > 3600) // 1 hour
expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
for (auto& it: m_RouterInfos) for (auto& it: m_RouterInfos)
{ {
@ -555,7 +555,7 @@ namespace data
// find & mark expired routers // find & mark expired routers
if (it.second->UsesIntroducer ()) if (it.second->UsesIntroducer ())
{ {
if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
// RouterInfo expires after 1 hour if uses introducer // RouterInfo expires after 1 hour if uses introducer
it.second->SetUnreachable (true); it.second->SetUnreachable (true);
} }
@ -873,7 +873,7 @@ namespace data
std::shared_ptr<I2NPMessage> replyMsg; std::shared_ptr<I2NPMessage> replyMsg;
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
{ {
LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded"); LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded");
std::set<IdentHash> excludedRouters; std::set<IdentHash> excludedRouters;
for (int i = 0; i < numExcluded; i++) for (int i = 0; i < numExcluded; i++)
{ {
@ -894,7 +894,7 @@ namespace data
} }
else else
{ {
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP || if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP) lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
{ {
auto router = FindRouter (ident); auto router = FindRouter (ident);
@ -907,7 +907,7 @@ namespace data
} }
} }
if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP || if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP ||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
{ {
auto leaseSet = FindLeaseSet (ident); auto leaseSet = FindLeaseSet (ident);

@ -28,12 +28,12 @@ namespace i2p
namespace data namespace data
{ {
const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_ROUTERS = 90;
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60; const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90*60; // 1.5 hours const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27*60*60; // 27 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
const int NETDB_PUBLISH_INTERVAL = 60*40; const int NETDB_PUBLISH_INTERVAL = 60 * 40;
const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0,9,36); // 0.9.36 const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36
/** function for visiting a leaseset stored in a floodfill */ /** function for visiting a leaseset stored in a floodfill */
typedef std::function<void(const IdentHash, std::shared_ptr<LeaseSet>)> LeaseSetVisitor; typedef std::function<void(const IdentHash, std::shared_ptr<LeaseSet>)> LeaseSetVisitor;
@ -63,7 +63,7 @@ namespace data
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const; std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr); void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr); void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg); void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg); void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
@ -80,13 +80,13 @@ namespace data
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num, std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const; std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const; std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const; std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
void SetUnreachable (const IdentHash& ident, bool unreachable); void SetUnreachable (const IdentHash& ident, bool unreachable);
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg); void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
/** set hidden mode, aka don't publish our RI to netdb and don't explore */ /** set hidden mode, aka don't publish our RI to netdb and don't explore */
void SetHidden(bool hide); void SetHidden(bool hide);
void Reseed (); void Reseed ();
Families& GetFamilies () { return m_Families; }; Families& GetFamilies () { return m_Families; };
@ -119,12 +119,13 @@ namespace data
void ManageLeaseSets (); void ManageLeaseSets ();
void ManageRequests (); void ManageRequests ();
void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20); void ReseedFromFloodfill(const RouterInfo & ri, int numRouters = 40, int numFloodfills = 20);
std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len, bool& updated); std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len, bool& updated);
std::shared_ptr<const RouterInfo> AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated); std::shared_ptr<const RouterInfo> AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated);
template<typename Filter>
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const; template<typename Filter>
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
private: private:
@ -150,12 +151,12 @@ namespace data
bool m_PersistProfiles; bool m_PersistProfiles;
/** router info we are bootstrapping from or nullptr if we are not currently doing that*/ /** router info we are bootstrapping from or nullptr if we are not currently doing that*/
std::shared_ptr<RouterInfo> m_FloodfillBootstrap; std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
/** true if in hidden mode */ /** true if in hidden mode */
bool m_HiddenMode; bool m_HiddenMode;
}; };
extern NetDb netdb; extern NetDb netdb;

@ -14,8 +14,8 @@ namespace data
std::shared_ptr<I2NPMessage> msg; std::shared_ptr<I2NPMessage> msg;
if(replyTunnel) if(replyTunnel)
msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory,
&m_ExcludedPeers); &m_ExcludedPeers);
else else
msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers); msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers);
if(router) if(router)
@ -158,4 +158,3 @@ namespace data
} }
} }
} }

@ -66,4 +66,3 @@ namespace data
} }
#endif #endif

@ -12,7 +12,6 @@ namespace i2p
{ {
namespace crypto namespace crypto
{ {
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz) void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz)
{ {
Poly1305 p(key); Poly1305 p(key);

@ -1,9 +1,9 @@
/** /**
This code is licensed under the MCGSI Public License * This code is licensed under the MCGSI Public License
Copyright 2018 Jeff Becker * Copyright 2018 Jeff Becker
*
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
@ -24,7 +24,6 @@ namespace crypto
namespace poly1305 namespace poly1305
{ {
struct LongBlock struct LongBlock
{ {
unsigned long data[17]; unsigned long data[17];
@ -252,8 +251,8 @@ namespace crypto
poly1305::LongBlock m_HR; poly1305::LongBlock m_HR;
uint8_t m_Final; uint8_t m_Final;
}; };
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
} }
} }
#endif #endif

@ -32,73 +32,76 @@ namespace data
{ {
} }
/** @brief tries to bootstrap into I2P network (from local files and servers, with respect of options) /**
*/ @brief tries to bootstrap into I2P network (from local files and servers, with respect of options)
void Reseeder::Bootstrap () */
{ void Reseeder::Bootstrap ()
std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName); {
std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName); std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName);
std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName);
if (su3FileName.length() > 0) // bootstrap from SU3 file or URL
{ if (su3FileName.length() > 0) // bootstrap from SU3 file or URL
int num; {
if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://") int num;
{ if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://")
num = ReseedFromSU3Url (su3FileName); // from https URL {
} num = ReseedFromSU3Url (su3FileName); // from https URL
else }
{ else
num = ProcessSU3File (su3FileName.c_str ()); {
} num = ProcessSU3File (su3FileName.c_str ());
if (num == 0) }
LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName); if (num == 0)
} LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName);
else if (zipFileName.length() > 0) // bootstrap from ZIP file }
{ else if (zipFileName.length() > 0) // bootstrap from ZIP file
int num = ProcessZIPFile (zipFileName.c_str ()); {
if (num == 0) int num = ProcessZIPFile (zipFileName.c_str ());
LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName); if (num == 0)
} LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName);
else // bootstrap from reseed servers }
{ else // bootstrap from reseed servers
int num = ReseedFromServers (); {
if (num == 0) int num = ReseedFromServers ();
LogPrint (eLogWarning, "Reseed: failed to reseed from servers"); if (num == 0)
} LogPrint (eLogWarning, "Reseed: failed to reseed from servers");
} }
}
/** @brief bootstrap from random server, retry 10 times
* @return number of entries added to netDb /**
*/ * @brief bootstrap from random server, retry 10 times
* @return number of entries added to netDb
*/
int Reseeder::ReseedFromServers () int Reseeder::ReseedFromServers ()
{ {
std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs); std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs);
std::vector<std::string> httpsReseedHostList; std::vector<std::string> httpsReseedHostList;
boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on); boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
if (reseedURLs.length () == 0) if (reseedURLs.length () == 0)
{ {
LogPrint (eLogWarning, "Reseed: No reseed servers specified"); LogPrint (eLogWarning, "Reseed: No reseed servers specified");
return 0; return 0;
} }
int reseedRetries = 0; int reseedRetries = 0;
while (reseedRetries < 10) while (reseedRetries < 10)
{ {
auto ind = rand () % httpsReseedHostList.size (); auto ind = rand () % httpsReseedHostList.size ();
std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3"; std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3";
auto num = ReseedFromSU3Url (reseedUrl); auto num = ReseedFromSU3Url (reseedUrl);
if (num > 0) return num; // success if (num > 0) return num; // success
reseedRetries++; reseedRetries++;
} }
LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts"); LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts");
return 0; return 0;
} }
/** @brief bootstrap from HTTPS URL with SU3 file /**
* @param url * @brief bootstrap from HTTPS URL with SU3 file
* @return number of entries added to netDb * @param url
*/ * @return number of entries added to netDb
*/
int Reseeder::ReseedFromSU3Url (const std::string& url) int Reseeder::ReseedFromSU3Url (const std::string& url)
{ {
LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url); LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url);
@ -702,4 +705,3 @@ namespace data
} }
} }
} }

@ -21,7 +21,7 @@ namespace data
Reseeder(); Reseeder();
~Reseeder(); ~Reseeder();
void Bootstrap (); void Bootstrap ();
int ReseedFromServers (); int ReseedFromServers ();
int ReseedFromSU3Url (const std::string& url); int ReseedFromSU3Url (const std::string& url);
int ProcessSU3File (const char * filename); int ProcessSU3File (const char * filename);

@ -339,9 +339,9 @@ namespace i2p
case low : /* not set */; break; case low : /* not set */; break;
case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P' case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P'
case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth;
#if (__cplusplus >= 201703L) // C++ 17 or higher #if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]]; [[fallthrough]];
#endif #endif
// no break here, extra + high means 'X' // no break here, extra + high means 'X'
case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break; case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break;
} }

@ -173,7 +173,6 @@ namespace data
LogPrint (eLogError, "RouterInfo: malformed message"); LogPrint (eLogError, "RouterInfo: malformed message");
m_IsUnreachable = true; m_IsUnreachable = true;
} }
} }
void RouterInfo::ReadFromStream (std::istream& s) void RouterInfo::ReadFromStream (std::istream& s)
@ -384,9 +383,10 @@ namespace data
SetUnreachable (true); SetUnreachable (true);
} }
bool RouterInfo::IsFamily(const std::string & fam) const { bool RouterInfo::IsFamily(const std::string & fam) const
return m_Family == fam; {
} return m_Family == fam;
}
void RouterInfo::ExtractCaps (const char * value) void RouterInfo::ExtractCaps (const char * value)
{ {
@ -854,7 +854,7 @@ namespace data
m_SupportedTransports |= eNTCPV6 | eSSUV6 | eNTCP2V6; m_SupportedTransports |= eNTCPV6 | eSSUV6 | eNTCP2V6;
} }
void RouterInfo::EnableV4 () void RouterInfo::EnableV4 ()
{ {
if (!IsV4 ()) if (!IsV4 ())
m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4; m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4;
@ -877,7 +877,7 @@ namespace data
} }
} }
void RouterInfo::DisableV4 () void RouterInfo::DisableV4 ()
{ {
if (IsV4 ()) if (IsV4 ())
{ {

@ -203,8 +203,8 @@ namespace data
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
bool IsNewer (const uint8_t * buf, size_t len) const; bool IsNewer (const uint8_t * buf, size_t len) const;
/** return true if we are in a router family and the signature is valid */ /** return true if we are in a router family and the signature is valid */
bool IsFamily(const std::string & fam) const; bool IsFamily(const std::string & fam) const;
// implements RoutingDestination // implements RoutingDestination
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; }; std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; };

@ -826,4 +826,3 @@ namespace transport
} }
} }
} }

@ -40,7 +40,7 @@ namespace transport
public: public:
SSUServer (int port); SSUServer (int port);
SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor
~SSUServer (); ~SSUServer ();
void Start (); void Start ();
void Stop (); void Stop ();
@ -135,4 +135,3 @@ namespace transport
} }
#endif #endif

@ -496,7 +496,7 @@ namespace transport
} }
// decay // decay
if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES || if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES ||
i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL) i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL)
m_ReceivedMessages.clear (); m_ReceivedMessages.clear ();
ScheduleIncompleteMessagesCleanup (); ScheduleIncompleteMessagesCleanup ();
@ -504,4 +504,3 @@ namespace transport
} }
} }
} }

@ -128,4 +128,3 @@ namespace transport
} }
#endif #endif

@ -336,7 +336,7 @@ namespace transport
m_SignedData->Insert (payload, 4); // insert Alice's signed on time m_SignedData->Insert (payload, 4); // insert Alice's signed on time
payload += 4; // signed-on time payload += 4; // signed-on time
size_t paddingSize = (payload - buf) + m_RemoteIdentity->GetSignatureLen (); size_t paddingSize = (payload - buf) + m_RemoteIdentity->GetSignatureLen ();
paddingSize &= 0x0F; // %16 paddingSize &= 0x0F; // %16
if (paddingSize > 0) paddingSize = 16 - paddingSize; if (paddingSize > 0) paddingSize = 16 - paddingSize;
payload += paddingSize; payload += paddingSize;
// verify signature // verify signature
@ -1206,4 +1206,3 @@ namespace transport
} }
} }
} }

@ -86,7 +86,7 @@ namespace transport
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs); void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
void SendPeerTest (); // Alice void SendPeerTest (); // Alice
SessionState GetState () const { return m_State; }; SessionState GetState () const { return m_State; };
size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumSentBytes () const { return m_NumSentBytes; };
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
@ -158,10 +158,7 @@ namespace transport
std::unique_ptr<SignedData> m_SignedData; // we need it for SessionConfirmed only std::unique_ptr<SignedData> m_SignedData; // we need it for SessionConfirmed only
std::map<uint32_t, std::shared_ptr<const i2p::data::RouterInfo> > m_RelayRequests; // nonce->Charlie std::map<uint32_t, std::shared_ptr<const i2p::data::RouterInfo> > m_RelayRequests; // nonce->Charlie
}; };
} }
} }
#endif #endif

@ -135,5 +135,3 @@ namespace crypto
#endif #endif
} }
} }

@ -527,4 +527,3 @@ namespace crypto
} }
#endif #endif

@ -1,9 +1,9 @@
/** /**
This code is licensed under the MCGSI Public License * This code is licensed under the MCGSI Public License
Copyright 2018 Jeff Becker * Copyright 2018 Jeff Becker
*
Kovri go write your own code * Kovri go write your own code
*
*/ */
#ifndef SIPHASH_H #ifndef SIPHASH_H
#define SIPHASH_H #define SIPHASH_H
@ -16,138 +16,138 @@ namespace i2p
{ {
namespace crypto namespace crypto
{ {
namespace siphash namespace siphash
{ {
constexpr int crounds = 2; constexpr int crounds = 2;
constexpr int drounds = 4; constexpr int drounds = 4;
inline uint64_t rotl(const uint64_t & x, int b) inline uint64_t rotl(const uint64_t & x, int b)
{ {
uint64_t ret = x << b; uint64_t ret = x << b;
ret |= x >> (64 - b); ret |= x >> (64 - b);
return ret; return ret;
} }
inline void u32to8le(const uint32_t & v, uint8_t * p) inline void u32to8le(const uint32_t & v, uint8_t * p)
{ {
p[0] = (uint8_t) v; p[0] = (uint8_t) v;
p[1] = (uint8_t) (v >> 8); p[1] = (uint8_t) (v >> 8);
p[2] = (uint8_t) (v >> 16); p[2] = (uint8_t) (v >> 16);
p[3] = (uint8_t) (v >> 24); p[3] = (uint8_t) (v >> 24);
} }
inline void u64to8le(const uint64_t & v, uint8_t * p) inline void u64to8le(const uint64_t & v, uint8_t * p)
{ {
p[0] = v & 0xff; p[0] = v & 0xff;
p[1] = (v >> 8) & 0xff; p[1] = (v >> 8) & 0xff;
p[2] = (v >> 16) & 0xff; p[2] = (v >> 16) & 0xff;
p[3] = (v >> 24) & 0xff; p[3] = (v >> 24) & 0xff;
p[4] = (v >> 32) & 0xff; p[4] = (v >> 32) & 0xff;
p[5] = (v >> 40) & 0xff; p[5] = (v >> 40) & 0xff;
p[6] = (v >> 48) & 0xff; p[6] = (v >> 48) & 0xff;
p[7] = (v >> 56) & 0xff; p[7] = (v >> 56) & 0xff;
} }
inline uint64_t u8to64le(const uint8_t * p) inline uint64_t u8to64le(const uint8_t * p)
{ {
uint64_t i = 0; uint64_t i = 0;
int idx = 0; int idx = 0;
while(idx < 8) while(idx < 8)
{ {
i |= ((uint64_t) p[idx]) << (idx * 8); i |= ((uint64_t) p[idx]) << (idx * 8);
++idx; ++idx;
} }
return i; return i;
} }
inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3) inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3)
{ {
_v0 += _v1; _v0 += _v1;
_v1 = rotl(_v1, 13); _v1 = rotl(_v1, 13);
_v1 ^= _v0; _v1 ^= _v0;
_v0 = rotl(_v0, 32); _v0 = rotl(_v0, 32);
_v2 += _v3; _v2 += _v3;
_v3 = rotl(_v3, 16); _v3 = rotl(_v3, 16);
_v3 ^= _v2; _v3 ^= _v2;
_v0 += _v3; _v0 += _v3;
_v3 = rotl(_v3, 21); _v3 = rotl(_v3, 21);
_v3 ^= _v0; _v3 ^= _v0;
_v2 += _v1; _v2 += _v1;
_v1 = rotl(_v1, 17); _v1 = rotl(_v1, 17);
_v1 ^= _v2; _v1 ^= _v2;
_v2 = rotl(_v2, 32); _v2 = rotl(_v2, 32);
} }
} }
/** hashsz must be 8 or 16 */ /** hashsz must be 8 or 16 */
template<std::size_t hashsz> template<std::size_t hashsz>
inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key) inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key)
{ {
uint64_t v0 = 0x736f6d6570736575ULL; uint64_t v0 = 0x736f6d6570736575ULL;
uint64_t v1 = 0x646f72616e646f6dULL; uint64_t v1 = 0x646f72616e646f6dULL;
uint64_t v2 = 0x6c7967656e657261ULL; uint64_t v2 = 0x6c7967656e657261ULL;
uint64_t v3 = 0x7465646279746573ULL; uint64_t v3 = 0x7465646279746573ULL;
const uint64_t k0 = siphash::u8to64le(key); const uint64_t k0 = siphash::u8to64le(key);
const uint64_t k1 = siphash::u8to64le(key + 8); const uint64_t k1 = siphash::u8to64le(key + 8);
uint64_t msg; uint64_t msg;
int i; int i;
const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t)); const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t));
auto left = bufsz & 7; auto left = bufsz & 7;
uint64_t b = ((uint64_t)bufsz) << 56; uint64_t b = ((uint64_t)bufsz) << 56;
v3 ^= k1; v3 ^= k1;
v2 ^= k0; v2 ^= k0;
v1 ^= k1; v1 ^= k1;
v0 ^= k0; v0 ^= k0;
if(hashsz == 16) v1 ^= 0xee; if(hashsz == 16) v1 ^= 0xee;
while(buf != end) while(buf != end)
{ {
msg = siphash::u8to64le(buf); msg = siphash::u8to64le(buf);
v3 ^= msg; v3 ^= msg;
for(i = 0; i < siphash::crounds; ++i) for(i = 0; i < siphash::crounds; ++i)
siphash::round(v0, v1, v2, v3); siphash::round(v0, v1, v2, v3);
v0 ^= msg; v0 ^= msg;
buf += 8; buf += 8;
} }
while(left) while(left)
{ {
--left; --left;
b |= ((uint64_t)(buf[left])) << (left * 8); b |= ((uint64_t)(buf[left])) << (left * 8);
} }
v3 ^= b; v3 ^= b;
for(i = 0; i < siphash::crounds; ++i) for(i = 0; i < siphash::crounds; ++i)
siphash::round(v0, v1, v2, v3); siphash::round(v0, v1, v2, v3);
v0 ^= b; v0 ^= b;
if(hashsz == 16) if(hashsz == 16)
v2 ^= 0xee; v2 ^= 0xee;
else else
v2 ^= 0xff; v2 ^= 0xff;
for(i = 0; i < siphash::drounds; ++i) for(i = 0; i < siphash::drounds; ++i)
siphash::round(v0, v1, v2, v3); siphash::round(v0, v1, v2, v3);
b = v0 ^ v1 ^ v2 ^ v3; b = v0 ^ v1 ^ v2 ^ v3;
siphash::u64to8le(b, h); siphash::u64to8le(b, h);
if(hashsz == 8) return; if(hashsz == 8) return;
v1 ^= 0xdd; v1 ^= 0xdd;
for (i = 0; i < siphash::drounds; ++i) for (i = 0; i < siphash::drounds; ++i)
siphash::round(v0, v1, v2, v3); siphash::round(v0, v1, v2, v3);
b = v0 ^ v1 ^ v2 ^ v3; b = v0 ^ v1 ^ v2 ^ v3;
siphash::u64to8le(b, h + 8); siphash::u64to8le(b, h + 8);
} }
} }
} }
#endif #endif

@ -34,7 +34,7 @@ namespace stream
else else
{ {
// partially // partially
rem = len - offset; rem = len - offset;
memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset); memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset);
nextBuffer->offset += (len - offset); nextBuffer->offset += (len - offset);
offset = len; // break offset = len; // break
@ -60,7 +60,7 @@ namespace stream
m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local), m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service),
m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO),
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU) m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
@ -73,7 +73,7 @@ namespace stream
m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local), m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE),
m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU) m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
{ {
@ -269,7 +269,7 @@ namespace stream
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, optionSize); m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, optionSize);
if (m_RemoteIdentity->IsRSA ()) if (m_RemoteIdentity->IsRSA ())
{ {
LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded"); LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded");
return false; return false;
} }
optionData += m_RemoteIdentity->GetFullLen (); optionData += m_RemoteIdentity->GetFullLen ();
@ -435,7 +435,7 @@ namespace stream
m_SendBuffer.Add (buf, len, handler); m_SendBuffer.Add (buf, len, handler);
} }
else if (handler) else if (handler)
handler(boost::system::error_code ()); handler(boost::system::error_code ());
m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ())); m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ()));
} }
@ -471,7 +471,7 @@ namespace stream
size++; // resend delay size++; // resend delay
if (m_Status == eStreamStatusNew) if (m_Status == eStreamStatusNew)
{ {
// initial packet // initial packet
m_Status = eStreamStatusOpen; m_Status = eStreamStatusOpen;
if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());; if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
if (m_RemoteLeaseSet) if (m_RemoteLeaseSet)
@ -654,7 +654,7 @@ namespace stream
size += 4; // receiveStreamID size += 4; // receiveStreamID
htobe32buf (packet + size, m_SequenceNumber++); htobe32buf (packet + size, m_SequenceNumber++);
size += 4; // sequenceNum size += 4; // sequenceNum
htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0); htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0);
size += 4; // ack Through size += 4; // ack Through
packet[size] = 0; packet[size] = 0;
size++; // NACK count size++; // NACK count
@ -748,7 +748,7 @@ namespace stream
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::GetMillisecondsSinceEpoch ();
if (!m_CurrentRemoteLease || !m_CurrentRemoteLease->endDate || // excluded from LeaseSet if (!m_CurrentRemoteLease || !m_CurrentRemoteLease->endDate || // excluded from LeaseSet
ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD) ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD)
UpdateCurrentRemoteLease (true); UpdateCurrentRemoteLease (true);
if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD) if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD)
{ {
@ -785,7 +785,7 @@ namespace stream
if (ts > m_RoutingSession->GetLeaseSetSubmissionTime () + i2p::garlic::LEASET_CONFIRMATION_TIMEOUT) if (ts > m_RoutingSession->GetLeaseSetSubmissionTime () + i2p::garlic::LEASET_CONFIRMATION_TIMEOUT)
{ {
// LeaseSet was not confirmed, should try other tunnels // LeaseSet was not confirmed, should try other tunnels
LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit"); LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit");
m_RoutingSession->SetSharedRoutingPath (nullptr); m_RoutingSession->SetSharedRoutingPath (nullptr);
m_CurrentOutboundTunnel = nullptr; m_CurrentOutboundTunnel = nullptr;
m_CurrentRemoteLease = nullptr; m_CurrentRemoteLease = nullptr;
@ -1164,7 +1164,7 @@ namespace stream
m_Owner->GetService ().post([acceptor, this](void) m_Owner->GetService ().post([acceptor, this](void)
{ {
if (!m_PendingIncomingStreams.empty ()) if (!m_PendingIncomingStreams.empty ())
{ {
acceptor (m_PendingIncomingStreams.front ()); acceptor (m_PendingIncomingStreams.front ());
m_PendingIncomingStreams.pop_front (); m_PendingIncomingStreams.pop_front ();
if (m_PendingIncomingStreams.empty ()) if (m_PendingIncomingStreams.empty ())

@ -16,93 +16,91 @@
namespace i2p { namespace i2p {
namespace data { namespace data {
template<size_t sz>
template<size_t sz> class Tag
class Tag
{
BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes");
public:
Tag () = default;
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
bool operator!= (const Tag& other) const { return !(*this == other); }
bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
uint8_t * operator()() { return m_Buf; }
const uint8_t * operator()() const { return m_Buf; }
operator uint8_t * () { return m_Buf; }
operator const uint8_t * () const { return m_Buf; }
const uint8_t * data() const { return m_Buf; }
const uint64_t * GetLL () const { return ll; }
bool IsZero () const
{
for (size_t i = 0; i < sz/8; ++i)
if (ll[i]) return false;
return true;
}
void Fill(uint8_t c)
{ {
memset(m_Buf, c, sz); BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes");
}
public:
void Randomize()
{ Tag () = default;
RAND_bytes(m_Buf, sz); Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
}
bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
std::string ToBase64 () const bool operator!= (const Tag& other) const { return !(*this == other); }
{ bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
char str[sz*2];
size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2); uint8_t * operator()() { return m_Buf; }
return std::string (str, str + l); const uint8_t * operator()() const { return m_Buf; }
}
operator uint8_t * () { return m_Buf; }
std::string ToBase32 () const operator const uint8_t * () const { return m_Buf; }
{
char str[sz*2]; const uint8_t * data() const { return m_Buf; }
size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2); const uint64_t * GetLL () const { return ll; }
return std::string (str, str + l);
} bool IsZero () const
{
size_t FromBase32 (const std::string& s) for (size_t i = 0; i < sz/8; ++i)
{ if (ll[i]) return false;
return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz); return true;
} }
size_t FromBase64 (const std::string& s) void Fill(uint8_t c)
{ {
return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); memset(m_Buf, c, sz);
} }
private: void Randomize()
{
union // 8 bytes aligned RAND_bytes(m_Buf, sz);
{ }
uint8_t m_Buf[sz];
uint64_t ll[sz/8]; std::string ToBase64 () const
{
char str[sz*2];
size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
return std::string (str, str + l);
}
std::string ToBase32 () const
{
char str[sz*2];
size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
return std::string (str, str + l);
}
size_t FromBase32 (const std::string& s)
{
return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
}
size_t FromBase64 (const std::string& s)
{
return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
}
private:
union // 8 bytes aligned
{
uint8_t m_Buf[sz];
uint64_t ll[sz/8];
};
}; };
};
} // data } // data
} // i2p } // i2p
namespace std namespace std
{ {
// hash for std::unordered_map // hash for std::unordered_map
template<size_t sz> struct hash<i2p::data::Tag<sz> > template<size_t sz> struct hash<i2p::data::Tag<sz> >
{ {
size_t operator()(const i2p::data::Tag<sz>& s) const size_t operator()(const i2p::data::Tag<sz>& s) const
{ {
return s.GetLL ()[0]; return s.GetLL ()[0];
} }
}; };
} }
#endif /* TAG_H__ */ #endif /* TAG_H__ */

@ -24,26 +24,26 @@ namespace util
static uint64_t GetLocalMillisecondsSinceEpoch () static uint64_t GetLocalMillisecondsSinceEpoch ()
{ {
return std::chrono::duration_cast<std::chrono::milliseconds>( return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count (); std::chrono::system_clock::now().time_since_epoch()).count ();
} }
static uint32_t GetLocalHoursSinceEpoch () static uint32_t GetLocalHoursSinceEpoch ()
{ {
return std::chrono::duration_cast<std::chrono::hours>( return std::chrono::duration_cast<std::chrono::hours>(
std::chrono::system_clock::now().time_since_epoch()).count (); std::chrono::system_clock::now().time_since_epoch()).count ();
} }
static uint64_t GetLocalSecondsSinceEpoch () static uint64_t GetLocalSecondsSinceEpoch ()
{ {
return std::chrono::duration_cast<std::chrono::seconds>( return std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()).count (); std::chrono::system_clock::now().time_since_epoch()).count ();
} }
static int64_t g_TimeOffset = 0; // in seconds static int64_t g_TimeOffset = 0; // in seconds
static void SyncTimeWithNTP (const std::string& address) static void SyncTimeWithNTP (const std::string& address)
{ {
LogPrint (eLogInfo, "Timestamp: NTP request to ", address); LogPrint (eLogInfo, "Timestamp: NTP request to ", address);
boost::asio::io_service service; boost::asio::io_service service;
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp"); boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp");
boost::system::error_code ec; boost::system::error_code ec;
@ -200,4 +200,3 @@ namespace util
} }
} }
} }

@ -26,7 +26,7 @@ namespace util
~NTPTimeSync (); ~NTPTimeSync ();
void Start (); void Start ();
void Stop (); void Stop ();
private: private:
@ -36,7 +36,7 @@ namespace util
private: private:
bool m_IsRunning; bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread; std::unique_ptr<std::thread> m_Thread;
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer; boost::asio::deadline_timer m_Timer;
int m_SyncInterval; int m_SyncInterval;
@ -46,4 +46,3 @@ namespace util
} }
#endif #endif

@ -12,7 +12,7 @@ namespace i2p
namespace tunnel namespace tunnel
{ {
TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey): const uint8_t * layerKey,const uint8_t * ivKey):
TunnelBase (receiveTunnelID, nextTunnelID, nextIdent) TunnelBase (receiveTunnelID, nextTunnelID, nextIdent)
{ {
@ -88,7 +88,7 @@ namespace tunnel
std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID, std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey, const uint8_t * layerKey,const uint8_t * ivKey,
bool isGateway, bool isEndpoint) bool isGateway, bool isEndpoint)
{ {
if (isEndpoint) if (isEndpoint)

@ -390,7 +390,7 @@ namespace transport
{ {
auto r = netdb.FindRouter (ident); auto r = netdb.FindRouter (ident);
{ {
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {}, it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {},
i2p::util::GetSecondsSinceEpoch (), {} })).first; i2p::util::GetSecondsSinceEpoch (), {} })).first;
} }
@ -553,13 +553,13 @@ namespace transport
{ {
auto router = i2p::data::netdb.GetRandomPeerTestRouter (isv4); // v4 only if v4 auto router = i2p::data::netdb.GetRandomPeerTestRouter (isv4); // v4 only if v4
if (router) if (router)
m_SSUServer->CreateSession (router, true, isv4); // peer test m_SSUServer->CreateSession (router, true, isv4); // peer test
else else
{ {
// if not peer test capable routers found pick any // if not peer test capable routers found pick any
router = i2p::data::netdb.GetRandomRouter (); router = i2p::data::netdb.GetRandomRouter ();
if (router && router->IsSSU ()) if (router && router->IsSSU ())
m_SSUServer->CreateSession (router); // no peer test m_SSUServer->CreateSession (router); // no peer test
} }
} }
if (i2p::context.SupportsV6 ()) if (i2p::context.SupportsV6 ())
@ -713,7 +713,7 @@ namespace transport
{ {
profile->TunnelNonReplied(); profile->TunnelNonReplied();
} }
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
it = m_Peers.erase (it); it = m_Peers.erase (it);
} }
else else

@ -103,7 +103,7 @@ namespace transport
uint64_t GetTotalReceivedBytes () const { return m_TotalReceivedBytes; }; uint64_t GetTotalReceivedBytes () const { return m_TotalReceivedBytes; };
uint64_t GetTotalTransitTransmittedBytes () const { return m_TotalTransitTransmittedBytes; } uint64_t GetTotalTransitTransmittedBytes () const { return m_TotalTransitTransmittedBytes; }
void UpdateTotalTransitTransmittedBytes (uint32_t add) { m_TotalTransitTransmittedBytes += add; }; void UpdateTotalTransitTransmittedBytes (uint32_t add) { m_TotalTransitTransmittedBytes += add; };
uint32_t GetInBandwidth () const { return m_InBandwidth; }; uint32_t GetInBandwidth () const { return m_InBandwidth; };
uint32_t GetOutBandwidth () const { return m_OutBandwidth; }; uint32_t GetOutBandwidth () const { return m_OutBandwidth; };
uint32_t GetTransitBandwidth () const { return m_TransitBandwidth; }; uint32_t GetTransitBandwidth () const { return m_TransitBandwidth; };
bool IsBandwidthExceeded () const; bool IsBandwidthExceeded () const;
@ -111,16 +111,16 @@ namespace transport
size_t GetNumPeers () const { return m_Peers.size (); }; size_t GetNumPeers () const { return m_Peers.size (); };
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer () const; std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer () const;
/** get a trusted first hop for restricted routes */ /** get a trusted first hop for restricted routes */
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const; std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
/** do we want to use restricted routes? */ /** do we want to use restricted routes? */
bool RoutesRestricted() const; bool RoutesRestricted() const;
/** restrict routes to use only these router families for first hops */ /** restrict routes to use only these router families for first hops */
void RestrictRoutesToFamilies(std::set<std::string> families); void RestrictRoutesToFamilies(std::set<std::string> families);
/** restrict routes to use only these routers for first hops */ /** restrict routes to use only these routers for first hops */
void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers); void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers);
bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const; bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const;
void PeerTest (); void PeerTest ();

@ -64,8 +64,7 @@ namespace tunnel
m.hash = i2p::data::IdentHash (fragment); m.hash = i2p::data::IdentHash (fragment);
fragment += 32; // to hash fragment += 32; // to hash
break; break;
default: default: ;
;
} }
bool isFragmented = flag & 0x08; bool isFragmented = flag & 0x08;

@ -172,7 +172,7 @@ namespace tunnel
SHA256(payload, size+16, hash); SHA256(payload, size+16, hash);
memcpy (buf+20, hash, 4); // checksum memcpy (buf+20, hash, 4); // checksum
payload[-1] = 0; // zero payload[-1] = 0; // zero
ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1 ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1
if (paddingSize > 0) if (paddingSize > 0)
{ {
// non-zero padding // non-zero padding
@ -219,4 +219,3 @@ namespace tunnel
} }
} }
} }

@ -16,7 +16,6 @@ namespace i2p
{ {
namespace tunnel namespace tunnel
{ {
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels): TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true),
@ -67,7 +66,8 @@ namespace tunnel
m_Tests.clear (); m_Tests.clear ();
} }
bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) { bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant)
{
if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0) if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0)
{ {
m_NumInboundHops = inHops; m_NumInboundHops = inHops;
@ -180,8 +180,8 @@ namespace tunnel
{ {
if (it->IsEstablished () && it != excluded) if (it->IsEstablished () && it != excluded)
{ {
tunnel = it; tunnel = it;
i++; i++;
} }
if (i > ind && tunnel) break; if (i > ind && tunnel) break;
} }
@ -411,7 +411,7 @@ namespace tunnel
{ {
std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex); std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
if (m_CustomPeerSelector) if (m_CustomPeerSelector)
return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound); return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
} }
// explicit peers in use // explicit peers in use
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound); if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);

@ -80,18 +80,18 @@ namespace tunnel
void UnsetCustomPeerSelector(); void UnsetCustomPeerSelector();
bool HasCustomPeerSelector(); bool HasCustomPeerSelector();
/** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */ /** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */
void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; } void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; }
/** @brief return true if this tunnel pool has a latency requirement */ /** @brief return true if this tunnel pool has a latency requirement */
bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; } bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; }
/** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */ /** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */
std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude=nullptr) const; std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude = nullptr) const;
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude=nullptr) const; std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude = nullptr) const;
// for overriding tunnel peer selection // for overriding tunnel peer selection
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const; std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
private: private:
@ -118,8 +118,8 @@ namespace tunnel
std::mutex m_CustomPeerSelectorMutex; std::mutex m_CustomPeerSelectorMutex;
ITunnelPeerSelector * m_CustomPeerSelector; ITunnelPeerSelector * m_CustomPeerSelector;
uint64_t m_MinLatency=0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms uint64_t m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
uint64_t m_MaxLatency=0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms uint64_t m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
public: public:

@ -31,8 +31,8 @@ namespace api
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
i2p::crypto::InitCrypto (precomputation); i2p::crypto::InitCrypto (precomputation);
int netID; i2p::config::GetOption("netid", netID); int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID); i2p::context.SetNetID (netID);
i2p::context.Init (); i2p::context.Init ();
} }
@ -133,4 +133,3 @@ namespace api
} }
} }
} }

@ -35,4 +35,3 @@ namespace api
} }
#endif #endif

@ -101,21 +101,21 @@ namespace net
#ifdef WIN32 #ifdef WIN32
bool IsWindowsXPorLater() bool IsWindowsXPorLater()
{ {
static bool isRequested = false; static bool isRequested = false;
static bool isXP = false; static bool isXP = false;
if (!isRequested) if (!isRequested)
{ {
// request // request
OSVERSIONINFO osvi; OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi); GetVersionEx(&osvi);
isXP = osvi.dwMajorVersion <= 5; isXP = osvi.dwMajorVersion <= 5;
isRequested = true; isRequested = true;
} }
return isXP; return isXP;
} }
int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback) int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
@ -246,22 +246,24 @@ namespace net
std::string localAddressUniversal = localAddress.to_string(); std::string localAddressUniversal = localAddress.to_string();
#endif #endif
typedef int (* IPN)(int af, const char *src, void *dst); typedef int (* IPN)(int af, const char *src, void *dst);
IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton"); IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
if(localAddress.is_v4()) if(localAddress.is_v4())
{ {
sockaddr_in inputAddress; sockaddr_in inputAddress;
inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr)); inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
return GetMTUWindowsIpv4(inputAddress, fallback); return GetMTUWindowsIpv4(inputAddress, fallback);
} }
else if(localAddress.is_v6()) else if(localAddress.is_v6())
{ {
sockaddr_in6 inputAddress; sockaddr_in6 inputAddress;
inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
return GetMTUWindowsIpv6(inputAddress, fallback); return GetMTUWindowsIpv6(inputAddress, fallback);
} else { }
else
{
LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported"); LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
return fallback; return fallback;
} }
@ -355,7 +357,7 @@ namespace net
if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af) if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
{ {
// match // match
char addr[INET6_ADDRSTRLEN]; char addr[INET6_ADDRSTRLEN];
memset (addr, 0, INET6_ADDRSTRLEN); memset (addr, 0, INET6_ADDRSTRLEN);
if(af == AF_INET) if(af == AF_INET)
inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN); inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
@ -379,7 +381,6 @@ namespace net
LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname); LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
} }
return boost::asio::ip::address::from_string(fallback); return boost::asio::ip::address::from_string(fallback);
#endif #endif
} }
} }

@ -487,18 +487,18 @@ namespace client
LogPrint (eLogWarning, "Addressbook: subscriptions.txt usage is deprecated, use config file instead"); LogPrint (eLogWarning, "Addressbook: subscriptions.txt usage is deprecated, use config file instead");
} }
else if (!i2p::config::IsDefault("addressbook.subscriptions")) else if (!i2p::config::IsDefault("addressbook.subscriptions"))
{ {
// using config file items // using config file items
std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs); std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs);
std::vector<std::string> subsList; std::vector<std::string> subsList;
boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on); boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on);
for (size_t i = 0; i < subsList.size (); i++) for (size_t i = 0; i < subsList.size (); i++)
{ {
m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, subsList[i])); m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, subsList[i]));
} }
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded"); LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
} }
} }
else else
LogPrint (eLogError, "Addressbook: subscriptions already loaded"); LogPrint (eLogError, "Addressbook: subscriptions already loaded");
@ -515,7 +515,7 @@ namespace client
if (dot != std::string::npos) if (dot != std::string::npos)
{ {
auto domain = it.first.substr (dot + 1); auto domain = it.first.substr (dot + 1);
auto it1 = m_Addresses.find (domain); // find domain in our addressbook auto it1 = m_Addresses.find (domain); // find domain in our addressbook
if (it1 != m_Addresses.end () && it1->second->IsIdentHash ()) if (it1 != m_Addresses.end () && it1->second->IsIdentHash ())
{ {
auto dest = context.FindLocalDestination (it1->second->identHash); auto dest = context.FindLocalDestination (it1->second->identHash);
@ -610,7 +610,7 @@ namespace client
{ {
// download it from default subscription // download it from default subscription
LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription."); LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription.");
std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL); std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
if (!m_DefaultSubscription) if (!m_DefaultSubscription)
m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL); m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL);
m_IsDownloading = true; m_IsDownloading = true;
@ -802,7 +802,7 @@ namespace client
/* convert url to relative */ /* convert url to relative */
url.schema = ""; url.schema = "";
url.host = ""; url.host = "";
req.uri = url.to_string(); req.uri = url.to_string();
auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port); auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
std::string request = req.to_string(); std::string request = req.to_string();
stream->Send ((const uint8_t *) request.data(), request.length()); stream->Send ((const uint8_t *) request.data(), request.length());
@ -920,7 +920,7 @@ namespace client
{ {
auto datagram = m_LocalDestination->GetDatagramDestination (); auto datagram = m_LocalDestination->GetDatagramDestination ();
if (datagram) if (datagram)
datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT); datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT);
} }
} }

@ -160,5 +160,3 @@ namespace client
} }
#endif #endif

@ -50,10 +50,10 @@ namespace client
void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr<AddressReceiver> receiver) void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr<AddressReceiver> receiver)
{ {
receiver->socket->async_read_some (boost::asio::buffer( receiver->socket->async_read_some (boost::asio::buffer(
receiver->buffer + receiver->bufferOffset, receiver->buffer + receiver->bufferOffset,
BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset), BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset),
std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this, std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this,
std::placeholders::_1, std::placeholders::_2, receiver)); std::placeholders::_1, std::placeholders::_2, receiver));
} }
void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred, void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred,
@ -437,7 +437,7 @@ namespace client
if (!m_CurrentDestination) if (!m_CurrentDestination)
{ {
m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command
m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet); m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet);
m_Owner.AddDestination (m_Nickname, m_CurrentDestination); m_Owner.AddDestination (m_Nickname, m_CurrentDestination);
} }
if (m_InPort) if (m_InPort)
@ -624,14 +624,13 @@ namespace client
} }
// trying to request // trying to request
auto s = shared_from_this (); auto s = shared_from_this ();
auto requstCallback = auto requstCallback = [s](std::shared_ptr<i2p::data::LeaseSet> ls)
[s](std::shared_ptr<i2p::data::LeaseSet> ls) {
{ if (ls)
if (ls) s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ());
s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ()); else
else s->SendReplyError ("LeaseSet Not found");
s->SendReplyError ("LeaseSet Not found"); };
};
if (addr->IsIdentHash ()) if (addr->IsIdentHash ())
localDestination->RequestDestination (addr->identHash, requstCallback); localDestination->RequestDestination (addr->identHash, requstCallback);
else else
@ -856,8 +855,7 @@ namespace client
session->SendVersion (); session->SendVersion ();
} }
else else
LogPrint (eLogError, "BOB: accept error: ", ecode.message ()); LogPrint (eLogError, "BOB: accept error: ", ecode.message ());
} }
} }
} }

@ -75,15 +75,15 @@ namespace client
class BOBI2PInboundTunnel: public BOBI2PTunnel class BOBI2PInboundTunnel: public BOBI2PTunnel
{ {
struct AddressReceiver struct AddressReceiver
{ {
std::shared_ptr<boost::asio::ip::tcp::socket> socket; std::shared_ptr<boost::asio::ip::tcp::socket> socket;
char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address
uint8_t * data; // pointer to buffer uint8_t * data; // pointer to buffer
size_t dataLen, bufferOffset; size_t dataLen, bufferOffset;
AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {}; AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {};
}; };
public: public:
@ -115,7 +115,7 @@ namespace client
{ {
public: public:
BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr<ClientDestination> localDestination, bool quiet); BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr<ClientDestination> localDestination, bool quiet);
void Start (); void Start ();
void Stop (); void Stop ();
@ -222,7 +222,7 @@ namespace client
BOBCommandChannel& m_Owner; BOBCommandChannel& m_Owner;
boost::asio::ip::tcp::socket m_Socket; boost::asio::ip::tcp::socket m_Socket;
boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer; boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer;
bool m_IsOpen, m_IsQuiet, m_IsActive; bool m_IsOpen, m_IsQuiet, m_IsActive;
std::string m_Nickname, m_InHost, m_OutHost; std::string m_Nickname, m_InHost, m_OutHost;
int m_InPort, m_OutPort; int m_InPort, m_OutPort;
@ -269,4 +269,3 @@ namespace client
} }
#endif #endif

@ -56,7 +56,7 @@ namespace client
{ {
std::string samAddr; i2p::config::GetOption("sam.address", samAddr); std::string samAddr; i2p::config::GetOption("sam.address", samAddr);
uint16_t samPort; i2p::config::GetOption("sam.port", samPort); uint16_t samPort; i2p::config::GetOption("sam.port", samPort);
bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread); bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread);
LogPrint(eLogInfo, "Clients: starting SAM bridge at ", samAddr, ":", samPort); LogPrint(eLogInfo, "Clients: starting SAM bridge at ", samAddr, ":", samPort);
try try
{ {
@ -407,13 +407,13 @@ namespace client
template<typename Section, typename Type> template<typename Section, typename Type>
std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
{ {
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value)); return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
} }
template<typename Section> template<typename Section>
std::string ClientContext::GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const std::string ClientContext::GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const
{ {
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value); return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value);
} }
template<typename Section> template<typename Section>
@ -429,7 +429,7 @@ namespace client
template<typename Section> template<typename Section>
void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const
{ {
options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH); options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH);
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH); options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY); options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY);
options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY); options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY);
@ -528,10 +528,10 @@ namespace client
{ {
std::string type = section.second.get<std::string> (I2P_TUNNELS_SECTION_TYPE); std::string type = section.second.get<std::string> (I2P_TUNNELS_SECTION_TYPE);
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT
|| type == I2P_TUNNELS_SECTION_TYPE_SOCKS || type == I2P_TUNNELS_SECTION_TYPE_SOCKS
|| type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS || type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS
|| type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY || type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY
|| type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT)
{ {
// mandatory params // mandatory params
std::string dest; std::string dest;
@ -640,9 +640,9 @@ namespace client
} }
} }
else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER
|| type == I2P_TUNNELS_SECTION_TYPE_HTTP || type == I2P_TUNNELS_SECTION_TYPE_HTTP
|| type == I2P_TUNNELS_SECTION_TYPE_IRC || type == I2P_TUNNELS_SECTION_TYPE_IRC
|| type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) || type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
{ {
// mandatory params // mandatory params
std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST); std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST);
@ -699,7 +699,7 @@ namespace client
continue; continue;
} }
std::shared_ptr<I2PServerTunnel> serverTunnel; std::shared_ptr<I2PServerTunnel> serverTunnel;
if (type == I2P_TUNNELS_SECTION_TYPE_HTTP) if (type == I2P_TUNNELS_SECTION_TYPE_HTTP)
serverTunnel = std::make_shared<I2PServerTunnelHTTP> (name, host, port, localDestination, hostOverride, inPort, gzip); serverTunnel = std::make_shared<I2PServerTunnelHTTP> (name, host, port, localDestination, hostOverride, inPort, gzip);
else if (type == I2P_TUNNELS_SECTION_TYPE_IRC) else if (type == I2P_TUNNELS_SECTION_TYPE_IRC)
@ -745,7 +745,7 @@ namespace client
ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ()); ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ());
} }
ins.first->second->isUpdated = true; ins.first->second->isUpdated = true;
LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
} }
} }
@ -769,9 +769,9 @@ namespace client
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL);
bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper); bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper);
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
if (httpProxyKeys.length () > 0) if (httpProxyKeys.length () > 0)
{ {

@ -78,7 +78,8 @@ namespace client
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, const std::string & name, const std::map<std::string, std::string> * params = nullptr); std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
const std::string & name, const std::map<std::string, std::string> * params = nullptr);
void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination); 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,
@ -141,6 +142,7 @@ namespace client
std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer; std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer;
public: public:
// for HTTP // for HTTP
const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; }; const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; };
const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; }; const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; };

@ -191,7 +191,7 @@ namespace proxy {
res.body = ss.str(); res.body = ss.str();
std::string response = res.to_string(); std::string response = res.to_string();
boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(), boost::asio::async_write(*m_sock, boost::asio::buffer(response), boost::asio::transfer_all(),
std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
} }
bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm) bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm)
@ -406,7 +406,7 @@ namespace proxy {
void HTTPReqHandler::ForwardToUpstreamProxy() void HTTPReqHandler::ForwardToUpstreamProxy()
{ {
LogPrint(eLogDebug, "HTTPProxy: forward to upstream"); LogPrint(eLogDebug, "HTTPProxy: forward to upstream");
// build http requset // build http request
m_ClientRequestURL = m_RequestURL; m_ClientRequestURL = m_RequestURL;
LogPrint(eLogDebug, "HTTPProxy: ", m_ClientRequestURL.host); LogPrint(eLogDebug, "HTTPProxy: ", m_ClientRequestURL.host);
@ -458,7 +458,7 @@ namespace proxy {
if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified
boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port)); boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port));
m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) { m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) {
m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamSocksProxyConnect, this, std::placeholders::_1)); m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamSocksProxyConnect, this, std::placeholders::_1));
})); }));
} }
else else
@ -562,14 +562,16 @@ namespace proxy {
if(m_ClientRequest.method == "CONNECT") { if(m_ClientRequest.method == "CONNECT") {
m_ClientResponse.code = 200; m_ClientResponse.code = 200;
m_send_buf = m_ClientResponse.to_string(); m_send_buf = m_ClientResponse.to_string();
boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred) { boost::asio::async_write(*m_sock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&] (const boost::system::error_code & ec, std::size_t transferred)
{
if(ec) GenericProxyError("socks proxy error", ec.message().c_str()); if(ec) GenericProxyError("socks proxy error", ec.message().c_str());
else HandoverToUpstreamProxy(); else HandoverToUpstreamProxy();
}); });
} else { } else {
m_send_buf = m_ClientRequestBuffer.str(); m_send_buf = m_ClientRequestBuffer.str();
LogPrint(eLogDebug, "HTTPProxy: send ", m_send_buf.size(), " bytes"); LogPrint(eLogDebug, "HTTPProxy: send ", m_send_buf.size(), " bytes");
boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred) { boost::asio::async_write(*m_proxysock, boost::asio::buffer(m_send_buf), boost::asio::transfer_all(), [&](const boost::system::error_code & ec, std::size_t transferred)
{
if(ec) GenericProxyError("failed to send request to upstream", ec.message().c_str()); if(ec) GenericProxyError("failed to send request to upstream", ec.message().c_str());
else HandoverToUpstreamProxy(); else HandoverToUpstreamProxy();
}); });

@ -6,6 +6,7 @@ namespace proxy {
class HTTPProxy: public i2p::client::TCPIPAcceptor class HTTPProxy: public i2p::client::TCPIPAcceptor
{ {
public: public:
HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr<i2p::client::ClientDestination> localDestination); HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr<i2p::client::ClientDestination> localDestination);
HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr) : HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr) :
HTTPProxy(name, address, port, "", true, localDestination) {} ; HTTPProxy(name, address, port, "", true, localDestination) {} ;
@ -15,11 +16,13 @@ namespace proxy {
bool GetHelperSupport() { return m_Addresshelper; } bool GetHelperSupport() { return m_Addresshelper; }
protected: protected:
// Implements TCPIPAcceptor // Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket); std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return m_Name.c_str (); } const char* GetName() { return m_Name.c_str (); }
private: private:
std::string m_Name; std::string m_Name;
std::string m_OutproxyUrl; std::string m_OutproxyUrl;
bool m_Addresshelper; bool m_Addresshelper;

@ -221,7 +221,7 @@ namespace client
auto s = shared_from_this (); auto s = shared_from_this ();
m_Socket->async_read_some (boost::asio::buffer (m_Header, 1), m_Socket->async_read_some (boost::asio::buffer (m_Header, 1),
[s](const boost::system::error_code& ecode, std::size_t bytes_transferred) [s](const boost::system::error_code& ecode, std::size_t bytes_transferred)
{ {
if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE) if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE)
s->ReceiveHeader (); s->ReceiveHeader ();
else else
@ -323,7 +323,7 @@ namespace client
memcpy (buf + I2CP_HEADER_SIZE, payload, len); memcpy (buf + I2CP_HEADER_SIZE, payload, len);
boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (),
std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (),
std::placeholders::_1, std::placeholders::_2, buf)); std::placeholders::_1, std::placeholders::_2, buf));
} }
else else
LogPrint (eLogError, "I2CP: Can't write to the socket"); LogPrint (eLogError, "I2CP: Can't write to the socket");
@ -779,14 +779,14 @@ namespace client
memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len); memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len);
boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (),
std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (),
std::placeholders::_1, std::placeholders::_2, buf)); std::placeholders::_1, std::placeholders::_2, buf));
} }
I2CPServer::I2CPServer (const std::string& interface, int port): I2CPServer::I2CPServer (const std::string& interface, int port):
m_IsRunning (false), m_Thread (nullptr), m_IsRunning (false), m_Thread (nullptr),
m_Acceptor (m_Service, m_Acceptor (m_Service,
#ifdef ANDROID #ifdef ANDROID
I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
#else #else
I2CPSession::proto::endpoint(boost::asio::ip::address::from_string(interface), port)) I2CPSession::proto::endpoint(boost::asio::ip::address::from_string(interface), port))
#endif #endif
@ -899,4 +899,3 @@ namespace client
} }
} }
} }

@ -220,4 +220,3 @@ namespace client
} }
#endif #endif

@ -115,14 +115,16 @@ namespace client
{ {
if(m_ConnectTimeout && !m_LocalDestination->IsReady()) if(m_ConnectTimeout && !m_LocalDestination->IsReady())
{ {
AddReadyCallback([this, streamRequestComplete, address, port] (const boost::system::error_code & ec) { AddReadyCallback([this, streamRequestComplete, address, port] (const boost::system::error_code & ec)
{
if(ec) if(ec)
{ {
LogPrint(eLogWarning, "I2PService::CreateStream() ", ec.message()); LogPrint(eLogWarning, "I2PService::CreateStream() ", ec.message());
streamRequestComplete(nullptr); streamRequestComplete(nullptr);
} }
else else
{ if (address->IsIdentHash ()) {
if (address->IsIdentHash ())
this->m_LocalDestination->CreateStream(streamRequestComplete, address->identHash, port); this->m_LocalDestination->CreateStream(streamRequestComplete, address->identHash, port);
else else
this->m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port); this->m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port);
@ -180,7 +182,7 @@ namespace client
{ {
m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE), m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
} }
else else
LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket"); LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
@ -191,7 +193,7 @@ namespace client
if (m_down) { if (m_down) {
m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE), m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
} }
else else
LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket"); LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
@ -205,8 +207,8 @@ namespace client
boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len), boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
boost::asio::transfer_all(), boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleUpstreamWrite, std::bind(&TCPIPPipe::HandleUpstreamWrite,
shared_from_this(), shared_from_this(),
std::placeholders::_1)); std::placeholders::_1));
} }
else else
LogPrint(eLogError, "TCPIPPipe: upstream write: no socket"); LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
@ -220,8 +222,8 @@ namespace client
boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len), boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
boost::asio::transfer_all(), boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleDownstreamWrite, std::bind(&TCPIPPipe::HandleDownstreamWrite,
shared_from_this(), shared_from_this(),
std::placeholders::_1)); std::placeholders::_1));
} }
else else
LogPrint(eLogError, "TCPIPPipe: downstream write: no socket"); LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");

@ -18,10 +18,12 @@ namespace client
class I2PService : public std::enable_shared_from_this<I2PService> class I2PService : public std::enable_shared_from_this<I2PService>
{ {
public: public:
typedef std::function<void(const boost::system::error_code &)> ReadyCallback; typedef std::function<void(const boost::system::error_code &)> ReadyCallback;
public: public:
I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr);
I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr);
I2PService (i2p::data::SigningKeyType kt); I2PService (i2p::data::SigningKeyType kt);
virtual ~I2PService (); virtual ~I2PService ();
@ -42,7 +44,7 @@ namespace client
void AddReadyCallback(ReadyCallback cb); void AddReadyCallback(ReadyCallback cb);
inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; } inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; }
inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; } inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; }
inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest) inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest)
{ {
if (m_LocalDestination) m_LocalDestination->Release (); if (m_LocalDestination) m_LocalDestination->Release ();
@ -59,21 +61,24 @@ namespace client
virtual const char* GetName() { return "Generic I2P Service"; } virtual const char* GetName() { return "Generic I2P Service"; }
private: private:
void TriggerReadyCheckTimer(); void TriggerReadyCheckTimer();
void HandleReadyCheckTimer(const boost::system::error_code & ec); void HandleReadyCheckTimer(const boost::system::error_code & ec);
private: private:
std::shared_ptr<ClientDestination> m_LocalDestination; std::shared_ptr<ClientDestination> m_LocalDestination;
std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers; std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers;
std::mutex m_HandlersMutex; std::mutex m_HandlersMutex;
std::vector<std::pair<ReadyCallback, uint32_t> > m_ReadyCallbacks; std::vector<std::pair<ReadyCallback, uint32_t> > m_ReadyCallbacks;
boost::asio::deadline_timer m_ReadyTimer; boost::asio::deadline_timer m_ReadyTimer;
bool m_ReadyTimerTriggered; bool m_ReadyTimerTriggered;
uint32_t m_ConnectTimeout; uint32_t m_ConnectTimeout;
const size_t NEVER_TIMES_OUT = 0; const size_t NEVER_TIMES_OUT = 0;
public: public:
bool isUpdated; // transient, used during reload only bool isUpdated; // transient, used during reload only
}; };
@ -81,6 +86,7 @@ namespace client
class I2PServiceHandler class I2PServiceHandler
{ {
public: public:
I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { } I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { }
virtual ~I2PServiceHandler() { } virtual ~I2PServiceHandler() { }
//If you override this make sure you call it from the children //If you override this make sure you call it from the children
@ -89,6 +95,7 @@ namespace client
void Terminate () { Kill (); }; void Terminate () { Kill (); };
protected: protected:
// Call when terminating or handing over to avoid race conditions // Call when terminating or handing over to avoid race conditions
inline bool Kill () { return m_Dead.exchange(true); } inline bool Kill () { return m_Dead.exchange(true); }
// Call to know if the handler is dead // Call to know if the handler is dead
@ -99,6 +106,7 @@ namespace client
inline I2PService * GetOwner() { return m_Service; } inline I2PService * GetOwner() { return m_Service; }
private: private:
I2PService *m_Service; I2PService *m_Service;
std::atomic<bool> m_Dead; //To avoid cleaning up multiple times std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
}; };
@ -109,11 +117,13 @@ namespace client
class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe> class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe>
{ {
public: public:
TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream); TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream);
~TCPIPPipe(); ~TCPIPPipe();
void Start(); void Start();
protected: protected:
void Terminate(); void Terminate();
void AsyncReceiveUpstream(); void AsyncReceiveUpstream();
void AsyncReceiveDownstream(); void AsyncReceiveDownstream();
@ -125,6 +135,7 @@ namespace client
void DownstreamWrite(size_t len); void DownstreamWrite(size_t len);
private: private:
uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE]; uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE]; uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down; std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down;
@ -135,6 +146,7 @@ namespace client
class TCPIPAcceptor: public I2PService class TCPIPAcceptor: public I2PService
{ {
public: public:
TCPIPAcceptor (const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination = nullptr) : TCPIPAcceptor (const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination = nullptr) :
I2PService(localDestination), I2PService(localDestination),
m_LocalEndpoint (boost::asio::ip::address::from_string(address), port), m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
@ -149,14 +161,16 @@ namespace client
//If you override this make sure you call it from the children //If you override this make sure you call it from the children
void Stop (); void Stop ();
const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; }; const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; } virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
protected: protected:
virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0; virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0;
private: private:
void Accept(); void Accept();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
boost::asio::ip::tcp::endpoint m_LocalEndpoint; boost::asio::ip::tcp::endpoint m_LocalEndpoint;

@ -168,7 +168,7 @@ namespace client
{ {
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2), std::placeholders::_1, std::placeholders::_2),
I2P_TUNNEL_CONNECTION_MAX_IDLE); I2P_TUNNEL_CONNECTION_MAX_IDLE);
} }
else // closed by peer else // closed by peer
@ -281,7 +281,7 @@ namespace client
if (endOfHeader) if (endOfHeader)
{ {
if (!m_ConnectionSent) m_OutHeader << "Connection: close\r\n"; if (!m_ConnectionSent) m_OutHeader << "Connection: close\r\n";
if (!m_ProxyConnectionSent) m_OutHeader << "Proxy-Connection: close\r\n"; if (!m_ProxyConnectionSent) m_OutHeader << "Proxy-Connection: close\r\n";
m_OutHeader << "\r\n"; // end of header m_OutHeader << "\r\n"; // end of header
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
m_InHeader.str (""); m_InHeader.str ("");
@ -477,7 +477,7 @@ namespace client
{ {
auto address = GetAddress (); auto address = GetAddress ();
if (address) if (address)
return std::make_shared<I2PClientTunnelHandler>(this, address, m_DestinationPort, socket); return std::make_shared<I2PClientTunnelHandler>(this, address, m_DestinationPort, socket);
else else
return nullptr; return nullptr;
} }

@ -30,6 +30,7 @@ namespace client
class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection> class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
{ {
public: public:
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
@ -41,6 +42,7 @@ namespace client
void Connect (bool isUniqueLocal = true); void Connect (bool isUniqueLocal = true);
protected: protected:
void Terminate (); void Terminate ();
void Receive (); void Receive ();
@ -55,6 +57,7 @@ namespace client
std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; }; std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; };
private: private:
uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE]; uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket; std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
std::shared_ptr<i2p::stream::Stream> m_Stream; std::shared_ptr<i2p::stream::Stream> m_Stream;
@ -65,15 +68,18 @@ namespace client
class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection
{ {
public: public:
I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket, I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<i2p::stream::Stream> stream): std::shared_ptr<i2p::stream::Stream> stream):
I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false), I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false),
m_ConnectionSent (false), m_ProxyConnectionSent (false) {}; m_ConnectionSent (false), m_ProxyConnectionSent (false) {};
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len);
private: private:
std::stringstream m_InHeader, m_OutHeader; std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent; bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
}; };
@ -81,14 +87,17 @@ namespace client
class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection
{ {
public: public:
I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& host); const boost::asio::ip::tcp::endpoint& target, const std::string& host);
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len);
private: private:
std::string m_Host; std::string m_Host;
std::stringstream m_InHeader, m_OutHeader; std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent; bool m_HeaderSent;
@ -98,14 +107,17 @@ namespace client
class I2PTunnelConnectionIRC: public I2PTunnelConnection class I2PTunnelConnectionIRC: public I2PTunnelConnection
{ {
public: public:
I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
protected: protected:
void Write (const uint8_t * buf, size_t len); void Write (const uint8_t * buf, size_t len);
private: private:
std::shared_ptr<const i2p::data::IdentityEx> m_From; std::shared_ptr<const i2p::data::IdentityEx> m_From;
std::stringstream m_OutPacket, m_InPacket; std::stringstream m_OutPacket, m_InPacket;
bool m_NeedsWebIrc; bool m_NeedsWebIrc;
@ -116,10 +128,12 @@ namespace client
class I2PClientTunnel: public TCPIPAcceptor class I2PClientTunnel: public TCPIPAcceptor
{ {
protected: protected:
// Implements TCPIPAcceptor // Implements TCPIPAcceptor
std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket); std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
public: public:
I2PClientTunnel (const std::string& name, const std::string& destination, I2PClientTunnel (const std::string& name, const std::string& destination,
const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0); const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0);
~I2PClientTunnel () {} ~I2PClientTunnel () {}
@ -130,9 +144,11 @@ namespace client
const char* GetName() { return m_Name.c_str (); } const char* GetName() { return m_Name.c_str (); }
private: private:
std::shared_ptr<const Address> GetAddress (); std::shared_ptr<const Address> GetAddress ();
private: private:
std::string m_Name, m_Destination; std::string m_Name, m_Destination;
std::shared_ptr<const Address> m_Address; std::shared_ptr<const Address> m_Address;
int m_DestinationPort; int m_DestinationPort;
@ -160,9 +176,9 @@ namespace client
uint8_t m_Buffer[I2P_UDP_MAX_MTU]; uint8_t m_Buffer[I2P_UDP_MAX_MTU];
UDPSession(boost::asio::ip::udp::endpoint localEndpoint, UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr<i2p::client::ClientDestination> & localDestination, const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident,
uint16_t ourPort, uint16_t theirPort); uint16_t ourPort, uint16_t theirPort);
void HandleReceived(const boost::system::error_code & ecode, std::size_t len); void HandleReceived(const boost::system::error_code & ecode, std::size_t len);
void Receive(); void Receive();
}; };
@ -195,6 +211,7 @@ namespace client
class I2PUDPServerTunnel class I2PUDPServerTunnel
{ {
public: public:
I2PUDPServerTunnel(const std::string & name, I2PUDPServerTunnel(const std::string & name,
std::shared_ptr<i2p::client::ClientDestination> localDestination, std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress, boost::asio::ip::address localAddress,
@ -210,10 +227,12 @@ namespace client
void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; } void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
private: private:
void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
private: private:
bool m_IsUniqueLocal; bool m_IsUniqueLocal;
const std::string m_Name; const std::string m_Name;
boost::asio::ip::address m_LocalAddress; boost::asio::ip::address m_LocalAddress;
@ -226,6 +245,7 @@ namespace client
class I2PUDPClientTunnel class I2PUDPClientTunnel
{ {
public: public:
I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest,
boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination,
uint16_t remotePort, bool gzip); uint16_t remotePort, bool gzip);
@ -240,6 +260,7 @@ namespace client
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
private: private:
typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo; typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
void RecvFromLocal(); void RecvFromLocal();
void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred); void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred);
@ -263,6 +284,7 @@ namespace client
class I2PServerTunnel: public I2PService class I2PServerTunnel: public I2PService
{ {
public: public:
I2PServerTunnel (const std::string& name, const std::string& address, int port, I2PServerTunnel (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true); std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);
@ -282,6 +304,7 @@ namespace client
const char* GetName() { return m_Name.c_str (); } const char* GetName() { return m_Name.c_str (); }
private: private:
void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
std::shared_ptr<boost::asio::ip::tcp::resolver> resolver); std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
@ -290,6 +313,7 @@ namespace client
virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream); virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private: private:
bool m_IsUniqueLocal; bool m_IsUniqueLocal;
std::string m_Name, m_Address; std::string m_Name, m_Address;
int m_Port; int m_Port;
@ -302,28 +326,34 @@ namespace client
class I2PServerTunnelHTTP: public I2PServerTunnel class I2PServerTunnelHTTP: public I2PServerTunnel
{ {
public: public:
I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& host, std::shared_ptr<ClientDestination> localDestination, const std::string& host,
int inport = 0, bool gzip = true); int inport = 0, bool gzip = true);
private: private:
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream); std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private: private:
std::string m_Host; std::string m_Host;
}; };
class I2PServerTunnelIRC: public I2PServerTunnel class I2PServerTunnelIRC: public I2PServerTunnel
{ {
public: public:
I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass, std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
int inport = 0, bool gzip = true); int inport = 0, bool gzip = true);
private: private:
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream); std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private: private:
std::string m_WebircPass; std::string m_WebircPass;
}; };
} }

@ -39,7 +39,7 @@ namespace client
{ {
m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1)); m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1));
m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) { m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) {
if(!ec) ResolveCurrentLeaseSet(); if(!ec) ResolveCurrentLeaseSet();
}); });
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save