mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-13 04:46:38 +01:00
commit
040585bf3d
33 changed files with 795 additions and 503 deletions
4
Crypto.h
4
Crypto.h
|
@ -325,6 +325,10 @@ inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **pri
|
||||||
|
|
||||||
inline RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
|
inline RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
|
||||||
{ return pkey->pkey.rsa; }
|
{ return pkey->pkey.rsa; }
|
||||||
|
|
||||||
|
// ssl
|
||||||
|
#define TLS_method TLSv1_method
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,20 +21,23 @@ void handle_signal(int sig)
|
||||||
switch (sig)
|
switch (sig)
|
||||||
{
|
{
|
||||||
case SIGHUP:
|
case SIGHUP:
|
||||||
LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening logs and tunnel configuration...");
|
LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening tunnel configuration...");
|
||||||
i2p::log::Logger().Reopen ();
|
|
||||||
i2p::client::context.ReloadConfig();
|
i2p::client::context.ReloadConfig();
|
||||||
break;
|
break;
|
||||||
|
case SIGUSR1:
|
||||||
|
LogPrint(eLogInfo, "Daemon: Got SIGUSR1, reopening logs...");
|
||||||
|
i2p::log::Logger().Reopen ();
|
||||||
|
break;
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (i2p::context.AcceptsTunnels () && !Daemon.gracefulShutdownInterval)
|
if (i2p::context.AcceptsTunnels () && !Daemon.gracefulShutdownInterval)
|
||||||
{
|
{
|
||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
Daemon.gracefulShutdownInterval = 10*60; // 10 minutes
|
Daemon.gracefulShutdownInterval = 10*60; // 10 minutes
|
||||||
LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefulShutdownInterval, " seconds");
|
LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefulShutdownInterval, " seconds");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Daemon.running = 0;
|
Daemon.running = 0;
|
||||||
break;
|
break;
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
Daemon.running = 0; // Exit loop
|
Daemon.running = 0; // Exit loop
|
||||||
|
@ -77,7 +80,7 @@ namespace i2p
|
||||||
}
|
}
|
||||||
|
|
||||||
// point std{in,out,err} descriptors to /dev/null
|
// point std{in,out,err} descriptors to /dev/null
|
||||||
freopen("/dev/null", "r", stdin);
|
freopen("/dev/null", "r", stdin);
|
||||||
freopen("/dev/null", "w", stdout);
|
freopen("/dev/null", "w", stdout);
|
||||||
freopen("/dev/null", "w", stderr);
|
freopen("/dev/null", "w", stderr);
|
||||||
}
|
}
|
||||||
|
@ -101,8 +104,8 @@ namespace i2p
|
||||||
}
|
}
|
||||||
uint32_t cfsize; i2p::config::GetOption("limits.coresize", cfsize);
|
uint32_t cfsize; i2p::config::GetOption("limits.coresize", cfsize);
|
||||||
if (cfsize) // core file size set
|
if (cfsize) // core file size set
|
||||||
{
|
{
|
||||||
cfsize *= 1024;
|
cfsize *= 1024;
|
||||||
getrlimit(RLIMIT_CORE, &limit);
|
getrlimit(RLIMIT_CORE, &limit);
|
||||||
if (cfsize <= limit.rlim_max) {
|
if (cfsize <= limit.rlim_max) {
|
||||||
limit.rlim_cur = cfsize;
|
limit.rlim_cur = cfsize;
|
||||||
|
@ -116,7 +119,7 @@ namespace i2p
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max);
|
LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pidfile
|
// Pidfile
|
||||||
// this code is c-styled and a bit ugly, but we need fd for locking pidfile
|
// this code is c-styled and a bit ugly, but we need fd for locking pidfile
|
||||||
|
@ -153,6 +156,7 @@ namespace i2p
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = SA_RESTART;
|
sa.sa_flags = SA_RESTART;
|
||||||
sigaction(SIGHUP, &sa, 0);
|
sigaction(SIGHUP, &sa, 0);
|
||||||
|
sigaction(SIGUSR1, &sa, 0);
|
||||||
sigaction(SIGABRT, &sa, 0);
|
sigaction(SIGABRT, &sa, 0);
|
||||||
sigaction(SIGTERM, &sa, 0);
|
sigaction(SIGTERM, &sa, 0);
|
||||||
sigaction(SIGINT, &sa, 0);
|
sigaction(SIGINT, &sa, 0);
|
||||||
|
@ -164,7 +168,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
i2p::fs::Remove(pidfile);
|
i2p::fs::Remove(pidfile);
|
||||||
|
|
||||||
return Daemon_Singleton::stop();
|
return Daemon_Singleton::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonLinux::run ()
|
void DaemonLinux::run ()
|
||||||
|
@ -175,12 +179,12 @@ namespace i2p
|
||||||
if (gracefulShutdownInterval)
|
if (gracefulShutdownInterval)
|
||||||
{
|
{
|
||||||
gracefulShutdownInterval--; // - 1 second
|
gracefulShutdownInterval--; // - 1 second
|
||||||
if (gracefulShutdownInterval <= 0)
|
if (gracefulShutdownInterval <= 0)
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Graceful shutdown");
|
LogPrint(eLogInfo, "Graceful shutdown");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace data
|
||||||
|
|
||||||
void Families::LoadCertificate (const std::string& filename)
|
void Families::LoadCertificate (const std::string& filename)
|
||||||
{
|
{
|
||||||
SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ());
|
SSL_CTX * ctx = SSL_CTX_new (TLS_method ());
|
||||||
int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM);
|
int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +135,7 @@ namespace data
|
||||||
{
|
{
|
||||||
auto filename = i2p::fs::DataDirPath("family", (family + ".key"));
|
auto filename = i2p::fs::DataDirPath("family", (family + ".key"));
|
||||||
std::string sig;
|
std::string sig;
|
||||||
SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ());
|
SSL_CTX * ctx = SSL_CTX_new (TLS_method ());
|
||||||
int ret = SSL_CTX_use_PrivateKey_file (ctx, filename.c_str (), SSL_FILETYPE_PEM);
|
int ret = SSL_CTX_use_PrivateKey_file (ctx, filename.c_str (), SSL_FILETYPE_PEM);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
|
29
Gzip.cpp
29
Gzip.cpp
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, The PurpleI2P Project
|
* Copyright (c) 2013-2017, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -9,11 +9,13 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h> /* memset */
|
#include <string.h> /* memset */
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "Log.h"
|
||||||
#include "Gzip.h"
|
#include "Gzip.h"
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p
|
||||||
namespace data {
|
{
|
||||||
|
namespace data
|
||||||
|
{
|
||||||
const size_t GZIP_CHUNK_SIZE = 16384;
|
const size_t GZIP_CHUNK_SIZE = 16384;
|
||||||
|
|
||||||
GzipInflator::GzipInflator (): m_IsDirty (false)
|
GzipInflator::GzipInflator (): m_IsDirty (false)
|
||||||
|
@ -36,9 +38,10 @@ namespace data {
|
||||||
m_Inflator.next_out = out;
|
m_Inflator.next_out = out;
|
||||||
m_Inflator.avail_out = outLen;
|
m_Inflator.avail_out = outLen;
|
||||||
int err;
|
int err;
|
||||||
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) {
|
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END)
|
||||||
return outLen - m_Inflator.avail_out;
|
return outLen - m_Inflator.avail_out;
|
||||||
}
|
// else
|
||||||
|
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,17 +52,20 @@ namespace data {
|
||||||
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
||||||
m_Inflator.avail_in = inLen;
|
m_Inflator.avail_in = inLen;
|
||||||
int ret;
|
int ret;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
m_Inflator.next_out = out;
|
m_Inflator.next_out = out;
|
||||||
m_Inflator.avail_out = GZIP_CHUNK_SIZE;
|
m_Inflator.avail_out = GZIP_CHUNK_SIZE;
|
||||||
ret = inflate (&m_Inflator, Z_NO_FLUSH);
|
ret = inflate (&m_Inflator, Z_NO_FLUSH);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
|
{
|
||||||
inflateEnd (&m_Inflator);
|
inflateEnd (&m_Inflator);
|
||||||
os.setstate(std::ios_base::failbit);
|
os.setstate(std::ios_base::failbit);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
os.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out);
|
os.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out);
|
||||||
} while (!m_Inflator.avail_out); // more data to read
|
}
|
||||||
|
while (!m_Inflator.avail_out); // more data to read
|
||||||
delete[] out;
|
delete[] out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,9 +105,10 @@ namespace data {
|
||||||
m_Deflator.next_out = out;
|
m_Deflator.next_out = out;
|
||||||
m_Deflator.avail_out = outLen;
|
m_Deflator.avail_out = outLen;
|
||||||
int err;
|
int err;
|
||||||
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END) {
|
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END)
|
||||||
return outLen - m_Deflator.avail_out;
|
return outLen - m_Deflator.avail_out;
|
||||||
} /* else */
|
// else
|
||||||
|
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // data
|
} // data
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "ClientContext.h"
|
||||||
#include "I2PControl.h"
|
#include "I2PControl.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -78,6 +79,8 @@ namespace client
|
||||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||||
|
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
||||||
|
&I2PControlService::TunnelsSuccessRateHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.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;
|
||||||
|
|
||||||
|
@ -187,13 +190,16 @@ namespace client
|
||||||
size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
|
size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
|
||||||
std::shared_ptr<I2PControlBuffer> buf)
|
std::shared_ptr<I2PControlBuffer> buf)
|
||||||
{
|
{
|
||||||
if (ecode) {
|
if (ecode)
|
||||||
|
{
|
||||||
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
|
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool isHtml = !memcmp (buf->data (), "POST", 4);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool isHtml = !memcmp (buf->data (), "POST", 4);
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss.write (buf->data (), bytes_transferred);
|
ss.write (buf->data (), bytes_transferred);
|
||||||
if (isHtml)
|
if (isHtml)
|
||||||
|
@ -237,7 +243,9 @@ namespace client
|
||||||
response << "{\"id\":" << id << ",\"result\":{";
|
response << "{\"id\":" << id << ",\"result\":{";
|
||||||
(this->*(it->second))(pt.get_child ("params"), response);
|
(this->*(it->second))(pt.get_child ("params"), response);
|
||||||
response << "},\"jsonrpc\":\"2.0\"}";
|
response << "},\"jsonrpc\":\"2.0\"}";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
|
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
|
||||||
response << "{\"id\":null,\"error\":";
|
response << "{\"id\":null,\"error\":";
|
||||||
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
||||||
|
@ -249,6 +257,11 @@ namespace client
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ());
|
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ());
|
||||||
|
std::ostringstream response;
|
||||||
|
response << "{\"id\":null,\"error\":";
|
||||||
|
response << "{\"code\":-32700,\"message\":\"" << ex.what () << "\"},";
|
||||||
|
response << "\"jsonrpc\":\"2.0\"}";
|
||||||
|
SendResponse (socket, buf, response, isHtml);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
@ -391,7 +404,8 @@ namespace client
|
||||||
|
|
||||||
void I2PControlService::StatusHandler (std::ostringstream& results)
|
void I2PControlService::StatusHandler (std::ostringstream& results)
|
||||||
{
|
{
|
||||||
InsertParam (results, "i2p.router.status", "???"); // TODO:
|
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
||||||
|
InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results)
|
void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results)
|
||||||
|
@ -415,6 +429,12 @@ namespace client
|
||||||
InsertParam (results, "i2p.router.net.tunnels.participating", transit);
|
InsertParam (results, "i2p.router.net.tunnels.participating", transit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I2PControlService::TunnelsSuccessRateHandler (std::ostringstream& results)
|
||||||
|
{
|
||||||
|
int rate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate ();
|
||||||
|
InsertParam (results, "i2p.router.net.tunnels.successrate", rate);
|
||||||
|
}
|
||||||
|
|
||||||
void I2PControlService::InboundBandwidth1S (std::ostringstream& results)
|
void I2PControlService::InboundBandwidth1S (std::ostringstream& results)
|
||||||
{
|
{
|
||||||
double bw = i2p::transport::transports.GetInBandwidth ();
|
double bw = i2p::transport::transports.GetInBandwidth ();
|
||||||
|
|
|
@ -81,6 +81,7 @@ namespace client
|
||||||
void NetDbActivePeersHandler (std::ostringstream& results);
|
void NetDbActivePeersHandler (std::ostringstream& results);
|
||||||
void NetStatusHandler (std::ostringstream& results);
|
void NetStatusHandler (std::ostringstream& results);
|
||||||
void TunnelsParticipatingHandler (std::ostringstream& results);
|
void TunnelsParticipatingHandler (std::ostringstream& results);
|
||||||
|
void TunnelsSuccessRateHandler (std::ostringstream& results);
|
||||||
void InboundBandwidth1S (std::ostringstream& results);
|
void InboundBandwidth1S (std::ostringstream& results);
|
||||||
void OutboundBandwidth1S (std::ostringstream& results);
|
void OutboundBandwidth1S (std::ostringstream& results);
|
||||||
void NetTotalReceivedBytes (std::ostringstream& results);
|
void NetTotalReceivedBytes (std::ostringstream& results);
|
||||||
|
|
|
@ -302,7 +302,7 @@ namespace client
|
||||||
if (m_NeedsWebIrc)
|
if (m_NeedsWebIrc)
|
||||||
{
|
{
|
||||||
m_NeedsWebIrc = false;
|
m_NeedsWebIrc = false;
|
||||||
m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " 127.0.0.1\n";
|
m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_InPacket.clear ();
|
m_InPacket.clear ();
|
||||||
|
|
|
@ -53,6 +53,8 @@ namespace client
|
||||||
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleConnect (const boost::system::error_code& ecode);
|
void HandleConnect (const boost::system::error_code& ecode);
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# set defaults instead redefine
|
# set defaults instead redefine
|
||||||
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic
|
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation
|
||||||
INCFLAGS ?=
|
INCFLAGS ?=
|
||||||
|
|
||||||
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
||||||
|
|
14
Makefile.osx
14
Makefile.osx
|
@ -1,11 +1,11 @@
|
||||||
CXX = clang++
|
CXX = clang++
|
||||||
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX
|
CXXFLAGS = -Os -Wall -std=c++11 -DMAC_OSX
|
||||||
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
||||||
INCFLAGS = -I/usr/local/include -I/usr/local/ssl/include
|
INCFLAGS = -I/usr/local/include
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/ssl/lib
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||||
|
|
||||||
ifeq ($(USE_STATIC),yes)
|
ifeq ($(USE_STATIC),yes)
|
||||||
LDLIBS = -lz -lcrypto -lssl /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
||||||
else
|
else
|
||||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
endif
|
endif
|
||||||
|
@ -15,11 +15,13 @@ ifeq ($(USE_UPNP),yes)
|
||||||
CXXFLAGS += -DUSE_UPNP
|
CXXFLAGS += -DUSE_UPNP
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_AESNI),yes)
|
ifeq ($(USE_AESNI),1)
|
||||||
CXXFLAGS += -maes -DAESNI
|
CXXFLAGS += -maes -DAESNI
|
||||||
|
else
|
||||||
|
CXXFLAGS += -msse
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_AVX),yes)
|
ifeq ($(USE_AVX),1)
|
||||||
CXXFLAGS += -mavx
|
CXXFLAGS += -mavx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
@ -35,12 +36,12 @@ namespace transport
|
||||||
delete m_Establisher;
|
delete m_Establisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCPSession::CreateAESKey (uint8_t * pubKey, i2p::crypto::AESKey& key)
|
void NTCPSession::CreateAESKey (uint8_t * pubKey)
|
||||||
{
|
{
|
||||||
uint8_t sharedKey[256];
|
uint8_t sharedKey[256];
|
||||||
m_DHKeysPair->Agree (pubKey, sharedKey);
|
m_DHKeysPair->Agree (pubKey, sharedKey); // time consuming operation
|
||||||
|
|
||||||
uint8_t * aesKey = key;
|
i2p::crypto::AESKey aesKey;
|
||||||
if (sharedKey[0] & 0x80)
|
if (sharedKey[0] & 0x80)
|
||||||
{
|
{
|
||||||
aesKey[0] = 0;
|
aesKey[0] = 0;
|
||||||
|
@ -63,6 +64,9 @@ namespace transport
|
||||||
}
|
}
|
||||||
memcpy (aesKey, nonZero, 32);
|
memcpy (aesKey, nonZero, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_Decryption.SetKey (aesKey);
|
||||||
|
m_Encryption.SetKey (aesKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCPSession::Done ()
|
void NTCPSession::Done ()
|
||||||
|
@ -163,15 +167,25 @@ namespace transport
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SendPhase2 ();
|
// TODO: check for number of pending keys
|
||||||
|
auto s = shared_from_this ();
|
||||||
|
auto keyCreated = std::async (std::launch::async, [s] ()
|
||||||
|
{
|
||||||
|
if (!s->m_DHKeysPair)
|
||||||
|
s->m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||||
|
s->CreateAESKey (s->m_Establisher->phase1.pubKey);
|
||||||
|
}).share ();
|
||||||
|
m_Server.GetService ().post ([s, keyCreated]()
|
||||||
|
{
|
||||||
|
keyCreated.get ();
|
||||||
|
s->SendPhase2 ();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCPSession::SendPhase2 ()
|
void NTCPSession::SendPhase2 ()
|
||||||
{
|
{
|
||||||
if (!m_DHKeysPair)
|
|
||||||
m_DHKeysPair = transports.GetNextDHKeysPair ();
|
|
||||||
const uint8_t * y = m_DHKeysPair->GetPublicKey ();
|
const uint8_t * y = m_DHKeysPair->GetPublicKey ();
|
||||||
memcpy (m_Establisher->phase2.pubKey, y, 256);
|
memcpy (m_Establisher->phase2.pubKey, y, 256);
|
||||||
uint8_t xy[512];
|
uint8_t xy[512];
|
||||||
|
@ -182,11 +196,7 @@ namespace transport
|
||||||
memcpy (m_Establisher->phase2.encrypted.timestamp, &tsB, 4);
|
memcpy (m_Establisher->phase2.encrypted.timestamp, &tsB, 4);
|
||||||
RAND_bytes (m_Establisher->phase2.encrypted.filler, 12);
|
RAND_bytes (m_Establisher->phase2.encrypted.filler, 12);
|
||||||
|
|
||||||
i2p::crypto::AESKey aesKey;
|
|
||||||
CreateAESKey (m_Establisher->phase1.pubKey, aesKey);
|
|
||||||
m_Encryption.SetKey (aesKey);
|
|
||||||
m_Encryption.SetIV (y + 240);
|
m_Encryption.SetIV (y + 240);
|
||||||
m_Decryption.SetKey (aesKey);
|
|
||||||
m_Decryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
m_Decryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
||||||
|
|
||||||
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
||||||
|
@ -229,32 +239,44 @@ namespace transport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i2p::crypto::AESKey aesKey;
|
auto s = shared_from_this ();
|
||||||
CreateAESKey (m_Establisher->phase2.pubKey, aesKey);
|
// create AES key in separate thread
|
||||||
m_Decryption.SetKey (aesKey);
|
auto keyCreated = std::async (std::launch::async, [s] ()
|
||||||
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
|
{
|
||||||
m_Encryption.SetKey (aesKey);
|
s->CreateAESKey (s->m_Establisher->phase2.pubKey);
|
||||||
m_Encryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
}).share (); // TODO: use move capture in C++ 14 instead shared_future
|
||||||
|
// let other operations execute while a key gets created
|
||||||
m_Decryption.Decrypt((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
m_Server.GetService ().post ([s, keyCreated]()
|
||||||
// verify
|
{
|
||||||
uint8_t xy[512];
|
keyCreated.get (); // we might wait if no more pending operations
|
||||||
memcpy (xy, m_DHKeysPair->GetPublicKey (), 256);
|
s->HandlePhase2 ();
|
||||||
memcpy (xy + 256, m_Establisher->phase2.pubKey, 256);
|
});
|
||||||
uint8_t digest[32];
|
|
||||||
SHA256 (xy, 512, digest);
|
|
||||||
if (memcmp(m_Establisher->phase2.encrypted.hxy, digest, 32))
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "NTCP: Phase 2 process error: incorrect hash");
|
|
||||||
transports.ReuseDHKeysPair (m_DHKeysPair);
|
|
||||||
m_DHKeysPair = nullptr;
|
|
||||||
Terminate ();
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
SendPhase3 ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NTCPSession::HandlePhase2 ()
|
||||||
|
{
|
||||||
|
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
|
||||||
|
m_Encryption.SetIV (m_Establisher->phase1.HXxorHI + 16);
|
||||||
|
|
||||||
|
m_Decryption.Decrypt((uint8_t *)&m_Establisher->phase2.encrypted, sizeof(m_Establisher->phase2.encrypted), (uint8_t *)&m_Establisher->phase2.encrypted);
|
||||||
|
// verify
|
||||||
|
uint8_t xy[512];
|
||||||
|
memcpy (xy, m_DHKeysPair->GetPublicKey (), 256);
|
||||||
|
memcpy (xy + 256, m_Establisher->phase2.pubKey, 256);
|
||||||
|
uint8_t digest[32];
|
||||||
|
SHA256 (xy, 512, digest);
|
||||||
|
if (memcmp(m_Establisher->phase2.encrypted.hxy, digest, 32))
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "NTCP: Phase 2 process error: incorrect hash");
|
||||||
|
transports.ReuseDHKeysPair (m_DHKeysPair);
|
||||||
|
m_DHKeysPair = nullptr;
|
||||||
|
Terminate ();
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
SendPhase3 ();
|
||||||
|
}
|
||||||
|
|
||||||
void NTCPSession::SendPhase3 ()
|
void NTCPSession::SendPhase3 ()
|
||||||
{
|
{
|
||||||
auto& keys = i2p::context.GetPrivateKeys ();
|
auto& keys = i2p::context.GetPrivateKeys ();
|
||||||
|
|
|
@ -67,12 +67,13 @@ namespace transport
|
||||||
void SendTimeSyncMessage ();
|
void SendTimeSyncMessage ();
|
||||||
void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
|
void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
|
||||||
|
|
||||||
void CreateAESKey (uint8_t * pubKey, i2p::crypto::AESKey& key);
|
void CreateAESKey (uint8_t * pubKey);
|
||||||
|
|
||||||
// client
|
// client
|
||||||
void SendPhase3 ();
|
void SendPhase3 ();
|
||||||
void HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandlePhase2 ();
|
||||||
void HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
void HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
||||||
void HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
void HandlePhase4Received (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA);
|
||||||
|
|
||||||
|
|
|
@ -583,7 +583,7 @@ namespace data
|
||||||
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
|
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
|
||||||
if (ident.IsZero ())
|
if (ident.IsZero ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetDb: database store with zero ident, dropped");
|
LogPrint (eLogDebug, "NetDb: database store with zero ident, dropped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
|
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
|
||||||
|
@ -602,14 +602,14 @@ namespace data
|
||||||
if (outbound)
|
if (outbound)
|
||||||
outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus);
|
outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "NetDb: no outbound tunnels for DatabaseStore reply found");
|
LogPrint (eLogWarning, "NetDb: no outbound tunnels for DatabaseStore reply found");
|
||||||
}
|
}
|
||||||
offset += 32;
|
offset += 32;
|
||||||
}
|
}
|
||||||
// we must send reply back before this check
|
// we must send reply back before this check
|
||||||
if (ident == i2p::context.GetIdentHash ())
|
if (ident == i2p::context.GetIdentHash ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetDb: database store with own RouterInfo received, dropped");
|
LogPrint (eLogDebug, "NetDb: database store with own RouterInfo received, dropped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t payloadOffset = offset;
|
size_t payloadOffset = offset;
|
||||||
|
@ -636,7 +636,7 @@ namespace data
|
||||||
updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
|
updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetDb: decompression failed ", uncompressedSize);
|
LogPrint (eLogInfo, "NetDb: decompression failed ", uncompressedSize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
30
Reseed.cpp
30
Reseed.cpp
|
@ -83,10 +83,24 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Reseeder::ProcessZIPFile (const char * filename)
|
||||||
|
{
|
||||||
|
std::ifstream s(filename, std::ifstream::binary);
|
||||||
|
if (s.is_open ())
|
||||||
|
{
|
||||||
|
s.seekg (0, std::ios::end);
|
||||||
|
auto len = s.tellg ();
|
||||||
|
s.seekg (0, std::ios::beg);
|
||||||
|
return ProcessZIPStream (s, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Reseed: Can't open file ", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char SU3_MAGIC_NUMBER[]="I2Psu3";
|
const char SU3_MAGIC_NUMBER[]="I2Psu3";
|
||||||
const uint32_t ZIP_HEADER_SIGNATURE = 0x04034B50;
|
|
||||||
const uint32_t ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE = 0x02014B50;
|
|
||||||
const uint16_t ZIP_BIT_FLAG_DATA_DESCRIPTOR = 0x0008;
|
|
||||||
int Reseeder::ProcessSU3Stream (std::istream& s)
|
int Reseeder::ProcessSU3Stream (std::istream& s)
|
||||||
{
|
{
|
||||||
char magicNumber[7];
|
char magicNumber[7];
|
||||||
|
@ -194,6 +208,14 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle content
|
// handle content
|
||||||
|
return ProcessZIPStream (s, contentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t ZIP_HEADER_SIGNATURE = 0x04034B50;
|
||||||
|
const uint32_t ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE = 0x02014B50;
|
||||||
|
const uint16_t ZIP_BIT_FLAG_DATA_DESCRIPTOR = 0x0008;
|
||||||
|
int Reseeder::ProcessZIPStream (std::istream& s, uint64_t contentLength)
|
||||||
|
{
|
||||||
int numFiles = 0;
|
int numFiles = 0;
|
||||||
size_t contentPos = s.tellg ();
|
size_t contentPos = s.tellg ();
|
||||||
while (!s.eof ())
|
while (!s.eof ())
|
||||||
|
@ -362,7 +384,7 @@ namespace data
|
||||||
|
|
||||||
void Reseeder::LoadCertificate (const std::string& filename)
|
void Reseeder::LoadCertificate (const std::string& filename)
|
||||||
{
|
{
|
||||||
SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ());
|
SSL_CTX * ctx = SSL_CTX_new (TLS_method ());
|
||||||
int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM);
|
int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
|
4
Reseed.h
4
Reseed.h
|
@ -31,8 +31,10 @@ namespace data
|
||||||
|
|
||||||
int ReseedFromSU3 (const std::string& url);
|
int ReseedFromSU3 (const std::string& url);
|
||||||
int ProcessSU3File (const char * filename);
|
int ProcessSU3File (const char * filename);
|
||||||
|
int ProcessZIPFile (const char * filename);
|
||||||
int ProcessSU3Stream (std::istream& s);
|
int ProcessSU3Stream (std::istream& s);
|
||||||
|
int ProcessZIPStream (std::istream& s, uint64_t contentLength);
|
||||||
|
|
||||||
bool FindZipDataDescriptor (std::istream& s);
|
bool FindZipDataDescriptor (std::istream& s);
|
||||||
|
|
||||||
std::string HttpsRequest (const std::string& address);
|
std::string HttpsRequest (const std::string& address);
|
||||||
|
|
|
@ -205,7 +205,7 @@ namespace i2p
|
||||||
|
|
||||||
void RouterContext::SetBandwidth (char L) {
|
void RouterContext::SetBandwidth (char L) {
|
||||||
uint16_t limit = 0;
|
uint16_t limit = 0;
|
||||||
enum { low, high, extra } type = high;
|
enum { low, high, extra, unlim } type = high;
|
||||||
/* detect parameters */
|
/* detect parameters */
|
||||||
switch (L)
|
switch (L)
|
||||||
{
|
{
|
||||||
|
@ -215,7 +215,7 @@ namespace i2p
|
||||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
|
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
|
||||||
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break;
|
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break;
|
||||||
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break;
|
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break;
|
||||||
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 9999; type = extra; break;
|
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 9999; type = unlim; break;
|
||||||
default:
|
default:
|
||||||
limit = 48; type = low;
|
limit = 48; type = low;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,8 @@ namespace i2p
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case low : /* not set */; break;
|
case low : /* not set */; break;
|
||||||
case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; // no break here
|
case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P'
|
||||||
|
case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth; // no break here, extra + high means 'X'
|
||||||
case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break;
|
case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break;
|
||||||
}
|
}
|
||||||
m_RouterInfo.SetCaps (caps);
|
m_RouterInfo.SetCaps (caps);
|
||||||
|
@ -253,7 +254,12 @@ namespace i2p
|
||||||
void RouterContext::SetUnreachable ()
|
void RouterContext::SetUnreachable ()
|
||||||
{
|
{
|
||||||
// set caps
|
// set caps
|
||||||
m_RouterInfo.SetCaps (i2p::data::RouterInfo::eUnreachable | i2p::data::RouterInfo::eSSUTesting); // LU, B
|
uint8_t caps = m_RouterInfo.GetCaps ();
|
||||||
|
caps &= ~i2p::data::RouterInfo::eReachable;
|
||||||
|
caps |= i2p::data::RouterInfo::eUnreachable;
|
||||||
|
caps &= ~i2p::data::RouterInfo::eFloodfill; // can't be floodfill
|
||||||
|
caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
|
||||||
|
m_RouterInfo.SetCaps (caps);
|
||||||
// remove NTCP address
|
// remove NTCP address
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto& addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto it = addresses.begin (); it != addresses.end (); ++it)
|
for (auto it = addresses.begin (); it != addresses.end (); ++it)
|
||||||
|
|
|
@ -376,14 +376,21 @@ namespace data
|
||||||
std::string caps;
|
std::string caps;
|
||||||
if (m_Caps & eFloodfill)
|
if (m_Caps & eFloodfill)
|
||||||
{
|
{
|
||||||
if (m_Caps & eExtraBandwidth) caps += CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P'
|
if (m_Caps & eExtraBandwidth) caps += (m_Caps & eHighBandwidth) ?
|
||||||
|
CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X'
|
||||||
|
CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P'
|
||||||
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
|
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
|
||||||
caps += CAPS_FLAG_FLOODFILL; // floodfill
|
caps += CAPS_FLAG_FLOODFILL; // floodfill
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_Caps & eExtraBandwidth) caps += CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P'
|
if (m_Caps & eExtraBandwidth)
|
||||||
caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth
|
{
|
||||||
|
caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */
|
||||||
|
caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O'
|
||||||
|
}
|
||||||
|
else
|
||||||
|
caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth
|
||||||
}
|
}
|
||||||
if (m_Caps & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden
|
if (m_Caps & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden
|
||||||
if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable
|
if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable
|
||||||
|
|
316
SAM.cpp
316
SAM.cpp
|
@ -15,9 +15,9 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
SAMSocket::SAMSocket (SAMBridge& owner):
|
SAMSocket::SAMSocket (SAMBridge& owner):
|
||||||
m_Owner (owner), m_Socket (m_Owner.GetService ()), m_Timer (m_Owner.GetService ()),
|
m_Owner (owner), m_Socket (m_Owner.GetService ()), m_Timer (m_Owner.GetService ()),
|
||||||
m_BufferOffset (0), m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false),
|
m_BufferOffset (0), m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false),
|
||||||
m_Stream (nullptr), m_Session (nullptr)
|
m_Stream (nullptr), m_Session (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -25,21 +25,21 @@ namespace client
|
||||||
SAMSocket::~SAMSocket ()
|
SAMSocket::~SAMSocket ()
|
||||||
{
|
{
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::CloseStream ()
|
void SAMSocket::CloseStream ()
|
||||||
{
|
{
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
m_Stream->Close ();
|
m_Stream->Close ();
|
||||||
m_Stream.reset ();
|
m_Stream.reset ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::Terminate ()
|
void SAMSocket::Terminate ()
|
||||||
{
|
{
|
||||||
CloseStream ();
|
CloseStream ();
|
||||||
|
|
||||||
switch (m_SocketType)
|
switch (m_SocketType)
|
||||||
{
|
{
|
||||||
case eSAMSocketTypeSession:
|
case eSAMSocketTypeSession:
|
||||||
|
@ -47,14 +47,14 @@ namespace client
|
||||||
break;
|
break;
|
||||||
case eSAMSocketTypeStream:
|
case eSAMSocketTypeStream:
|
||||||
{
|
{
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
m_Session->DelSocket (shared_from_this ());
|
m_Session->DelSocket (shared_from_this ());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eSAMSocketTypeAcceptor:
|
case eSAMSocketTypeAcceptor:
|
||||||
{
|
{
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
{
|
{
|
||||||
m_Session->DelSocket (shared_from_this ());
|
m_Session->DelSocket (shared_from_this ());
|
||||||
if (m_Session->localDestination)
|
if (m_Session->localDestination)
|
||||||
m_Session->localDestination->StopAcceptingStreams ();
|
m_Session->localDestination->StopAcceptingStreams ();
|
||||||
|
@ -71,8 +71,8 @@ namespace client
|
||||||
|
|
||||||
void SAMSocket::ReceiveHandshake ()
|
void SAMSocket::ReceiveHandshake ()
|
||||||
{
|
{
|
||||||
m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE),
|
m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE),
|
||||||
std::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (),
|
std::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (),
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ namespace client
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Buffer[bytes_transferred] = 0;
|
m_Buffer[bytes_transferred] = 0;
|
||||||
char * eol = (char *)memchr (m_Buffer, '\n', bytes_transferred);
|
char * eol = (char *)memchr (m_Buffer, '\n', bytes_transferred);
|
||||||
if (eol)
|
if (eol)
|
||||||
|
@ -94,8 +94,8 @@ namespace client
|
||||||
char * separator = strchr (m_Buffer, ' ');
|
char * separator = strchr (m_Buffer, ' ');
|
||||||
if (separator)
|
if (separator)
|
||||||
{
|
{
|
||||||
separator = strchr (separator + 1, ' ');
|
separator = strchr (separator + 1, ' ');
|
||||||
if (separator)
|
if (separator)
|
||||||
*separator = 0;
|
*separator = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,13 +117,13 @@ namespace client
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||||
#else
|
#else
|
||||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||||
#endif
|
#endif
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (),
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (),
|
||||||
std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (),
|
std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (),
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendMessageReply (SAM_HANDSHAKE_I2P_ERROR, strlen (SAM_HANDSHAKE_I2P_ERROR), true);
|
SendMessageReply (SAM_HANDSHAKE_I2P_ERROR, strlen (SAM_HANDSHAKE_I2P_ERROR), true);
|
||||||
}
|
}
|
||||||
|
@ -145,25 +145,25 @@ namespace client
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE),
|
m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE),
|
||||||
std::bind(&SAMSocket::HandleMessage, shared_from_this (),
|
std::bind(&SAMSocket::HandleMessage, shared_from_this (),
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::SendMessageReply (const char * msg, size_t len, bool close)
|
void SAMSocket::SendMessageReply (const char * msg, size_t len, bool close)
|
||||||
{
|
{
|
||||||
if (!m_IsSilent)
|
if (!m_IsSilent)
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (),
|
boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (),
|
||||||
std::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (),
|
std::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (),
|
||||||
std::placeholders::_1, std::placeholders::_2, close));
|
std::placeholders::_1, std::placeholders::_2, close));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (close)
|
if (close)
|
||||||
Terminate ();
|
Terminate ();
|
||||||
else
|
else
|
||||||
Receive ();
|
Receive ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::HandleMessageReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred, bool close)
|
void SAMSocket::HandleMessageReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred, bool close)
|
||||||
|
@ -179,8 +179,8 @@ namespace client
|
||||||
if (close)
|
if (close)
|
||||||
Terminate ();
|
Terminate ();
|
||||||
else
|
else
|
||||||
Receive ();
|
Receive ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void SAMSocket::HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
|
@ -205,8 +205,8 @@ namespace client
|
||||||
char * separator = strchr (m_Buffer, ' ');
|
char * separator = strchr (m_Buffer, ' ');
|
||||||
if (separator)
|
if (separator)
|
||||||
{
|
{
|
||||||
separator = strchr (separator + 1, ' ');
|
separator = strchr (separator + 1, ' ');
|
||||||
if (separator)
|
if (separator)
|
||||||
*separator = 0;
|
*separator = 0;
|
||||||
else
|
else
|
||||||
separator = eol;
|
separator = eol;
|
||||||
|
@ -236,12 +236,12 @@ namespace client
|
||||||
*separator = ' ';
|
*separator = ' ';
|
||||||
*eol = '\n';
|
*eol = '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// since it's SAM v1 reply is not expected
|
// since it's SAM v1 reply is not expected
|
||||||
Receive ();
|
Receive ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SAM: unexpected message ", m_Buffer);
|
LogPrint (eLogError, "SAM: unexpected message ", m_Buffer);
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
|
@ -252,8 +252,9 @@ namespace client
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "SAM: incomplete message ", bytes_transferred);
|
LogPrint (eLogWarning, "SAM: incomplete message ", bytes_transferred);
|
||||||
m_BufferOffset = bytes_transferred;
|
m_BufferOffset = bytes_transferred;
|
||||||
// try to receive remaining message
|
// try to receive remaining message
|
||||||
|
@ -267,10 +268,10 @@ namespace client
|
||||||
LogPrint (eLogDebug, "SAM: session create: ", buf);
|
LogPrint (eLogDebug, "SAM: session create: ", buf);
|
||||||
std::map<std::string, std::string> params;
|
std::map<std::string, std::string> params;
|
||||||
ExtractParams (buf, params);
|
ExtractParams (buf, params);
|
||||||
std::string& style = params[SAM_PARAM_STYLE];
|
std::string& style = params[SAM_PARAM_STYLE];
|
||||||
std::string& id = params[SAM_PARAM_ID];
|
std::string& id = params[SAM_PARAM_ID];
|
||||||
std::string& destination = params[SAM_PARAM_DESTINATION];
|
std::string& destination = params[SAM_PARAM_DESTINATION];
|
||||||
m_ID = id;
|
m_ID = id;
|
||||||
if (m_Owner.FindSession (id))
|
if (m_Owner.FindSession (id))
|
||||||
{
|
{
|
||||||
// session exists
|
// session exists
|
||||||
|
@ -278,15 +279,39 @@ namespace client
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create destination
|
std::shared_ptr<boost::asio::ip::udp::endpoint> forward = nullptr;
|
||||||
m_Session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms);
|
if (style == SAM_VALUE_DATAGRAM && params.find(SAM_VALUE_HOST) != params.end() && params.find(SAM_VALUE_PORT) != params.end())
|
||||||
|
{
|
||||||
|
// udp forward selected
|
||||||
|
boost::system::error_code e;
|
||||||
|
// TODO: support hostnames in udp forward
|
||||||
|
auto addr = boost::asio::ip::address::from_string(params[SAM_VALUE_HOST], e);
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
// not an ip address
|
||||||
|
SendI2PError("Invalid IP Address in HOST");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto port = std::stoi(params[SAM_VALUE_PORT]);
|
||||||
|
if (port == -1)
|
||||||
|
{
|
||||||
|
SendI2PError("Invalid port");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
forward = std::make_shared<boost::asio::ip::udp::endpoint>(addr, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create destination
|
||||||
|
m_Session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms);
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
{
|
{
|
||||||
m_SocketType = eSAMSocketTypeSession;
|
m_SocketType = eSAMSocketTypeSession;
|
||||||
if (style == SAM_VALUE_DATAGRAM)
|
if (style == SAM_VALUE_DATAGRAM)
|
||||||
{
|
{
|
||||||
|
m_Session->UDPEndpoint = forward;
|
||||||
auto dest = m_Session->localDestination->CreateDatagramDestination ();
|
auto dest = m_Session->localDestination->CreateDatagramDestination ();
|
||||||
dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (),
|
dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (),
|
||||||
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +321,7 @@ namespace client
|
||||||
{
|
{
|
||||||
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
|
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
|
||||||
m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer,
|
m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -314,7 +339,7 @@ namespace client
|
||||||
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
|
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
|
||||||
m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer,
|
m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +352,7 @@ namespace client
|
||||||
priv[l1] = 0;
|
priv[l1] = 0;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||||
#else
|
#else
|
||||||
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, l2, false);
|
SendMessageReply (m_Buffer, l2, false);
|
||||||
|
@ -341,7 +366,7 @@ namespace client
|
||||||
std::string& id = params[SAM_PARAM_ID];
|
std::string& id = params[SAM_PARAM_ID];
|
||||||
std::string& destination = params[SAM_PARAM_DESTINATION];
|
std::string& destination = params[SAM_PARAM_DESTINATION];
|
||||||
std::string& silent = params[SAM_PARAM_SILENT];
|
std::string& silent = params[SAM_PARAM_SILENT];
|
||||||
if (silent == SAM_VALUE_TRUE) m_IsSilent = true;
|
if (silent == SAM_VALUE_TRUE) m_IsSilent = true;
|
||||||
m_ID = id;
|
m_ID = id;
|
||||||
m_Session = m_Owner.FindSession (id);
|
m_Session = m_Owner.FindSession (id);
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
|
@ -365,7 +390,7 @@ namespace client
|
||||||
SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true);
|
SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::Connect (std::shared_ptr<const i2p::data::LeaseSet> remote)
|
void SAMSocket::Connect (std::shared_ptr<const i2p::data::LeaseSet> remote)
|
||||||
|
@ -374,7 +399,7 @@ namespace client
|
||||||
m_Session->AddSocket (shared_from_this ());
|
m_Session->AddSocket (shared_from_this ());
|
||||||
m_Stream = m_Session->localDestination->CreateStream (remote);
|
m_Stream = m_Session->localDestination->CreateStream (remote);
|
||||||
m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect
|
m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect
|
||||||
I2PReceive ();
|
I2PReceive ();
|
||||||
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,17 +421,17 @@ namespace client
|
||||||
ExtractParams (buf, params);
|
ExtractParams (buf, params);
|
||||||
std::string& id = params[SAM_PARAM_ID];
|
std::string& id = params[SAM_PARAM_ID];
|
||||||
std::string& silent = params[SAM_PARAM_SILENT];
|
std::string& silent = params[SAM_PARAM_SILENT];
|
||||||
if (silent == SAM_VALUE_TRUE) m_IsSilent = true;
|
if (silent == SAM_VALUE_TRUE) m_IsSilent = true;
|
||||||
m_ID = id;
|
m_ID = id;
|
||||||
m_Session = m_Owner.FindSession (id);
|
m_Session = m_Owner.FindSession (id);
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
{
|
{
|
||||||
m_SocketType = eSAMSocketTypeAcceptor;
|
m_SocketType = eSAMSocketTypeAcceptor;
|
||||||
m_Session->AddSocket (shared_from_this ());
|
m_Session->AddSocket (shared_from_this ());
|
||||||
if (!m_Session->localDestination->IsAcceptingStreams ())
|
if (!m_Session->localDestination->IsAcceptingStreams ())
|
||||||
m_Session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1));
|
m_Session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1));
|
||||||
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true);
|
||||||
}
|
}
|
||||||
|
@ -418,9 +443,9 @@ namespace client
|
||||||
ExtractParams (buf, params);
|
ExtractParams (buf, params);
|
||||||
size_t size = std::stoi(params[SAM_PARAM_SIZE]), offset = data - buf;
|
size_t size = std::stoi(params[SAM_PARAM_SIZE]), offset = data - buf;
|
||||||
if (offset + size <= len)
|
if (offset + size <= len)
|
||||||
{
|
{
|
||||||
if (m_Session)
|
if (m_Session)
|
||||||
{
|
{
|
||||||
auto d = m_Session->localDestination->GetDatagramDestination ();
|
auto d = m_Session->localDestination->GetDatagramDestination ();
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
|
@ -433,24 +458,24 @@ namespace client
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "SAM: session is not created from DATAGRAM SEND");
|
LogPrint (eLogError, "SAM: session is not created from DATAGRAM SEND");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "SAM: sent datagram size ", size, " exceeds buffer ", len - offset);
|
LogPrint (eLogWarning, "SAM: sent datagram size ", size, " exceeds buffer ", len - offset);
|
||||||
return 0; // try to receive more
|
return 0; // try to receive more
|
||||||
}
|
}
|
||||||
return offset + size;
|
return offset + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::ProcessDestGenerate ()
|
void SAMSocket::ProcessDestGenerate ()
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "SAM: dest generate");
|
LogPrint (eLogDebug, "SAM: dest generate");
|
||||||
auto keys = i2p::data::PrivateKeys::CreateRandomKeys ();
|
auto keys = i2p::data::PrivateKeys::CreateRandomKeys ();
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
||||||
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
||||||
#else
|
#else
|
||||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
|
||||||
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, len, false);
|
SendMessageReply (m_Buffer, len, false);
|
||||||
|
@ -479,45 +504,56 @@ namespace client
|
||||||
std::bind (&SAMSocket::HandleNamingLookupLeaseSetRequestComplete,
|
std::bind (&SAMSocket::HandleNamingLookupLeaseSetRequestComplete,
|
||||||
shared_from_this (), std::placeholders::_1, ident));
|
shared_from_this (), std::placeholders::_1, ident));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SAM: naming failed, unknown address ", name);
|
LogPrint (eLogError, "SAM: naming failed, unknown address ", name);
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||||
#else
|
#else
|
||||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, len, false);
|
SendMessageReply (m_Buffer, len, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, i2p::data::IdentHash ident)
|
void SAMSocket::SendI2PError(const std::string & msg)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "SAM: i2p error ", msg);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
|
||||||
|
#else
|
||||||
|
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_STATUS_I2P_ERROR, msg.c_str());
|
||||||
|
#endif
|
||||||
|
SendMessageReply (m_Buffer, len, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SAMSocket::HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, i2p::data::IdentHash ident)
|
||||||
{
|
{
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
{
|
{
|
||||||
context.GetAddressBook ().InsertAddress (leaseSet->GetIdentity ());
|
context.GetAddressBook ().InsertAddress (leaseSet->GetIdentity ());
|
||||||
SendNamingLookupReply (leaseSet->GetIdentity ());
|
SendNamingLookupReply (leaseSet->GetIdentity ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SAM: naming lookup failed. LeaseSet for ", ident.ToBase32 (), " not found");
|
LogPrint (eLogError, "SAM: naming lookup failed. LeaseSet for ", ident.ToBase32 (), " not found");
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY,
|
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY,
|
||||||
context.GetAddressBook ().ToAddress (ident).c_str());
|
context.GetAddressBook ().ToAddress (ident).c_str());
|
||||||
#else
|
#else
|
||||||
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY,
|
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY,
|
||||||
context.GetAddressBook ().ToAddress (ident).c_str());
|
context.GetAddressBook ().ToAddress (ident).c_str());
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, len, false);
|
SendMessageReply (m_Buffer, len, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::SendNamingLookupReply (std::shared_ptr<const i2p::data::IdentityEx> identity)
|
void SAMSocket::SendNamingLookupReply (std::shared_ptr<const i2p::data::IdentityEx> identity)
|
||||||
{
|
{
|
||||||
auto base64 = identity->ToBase64 ();
|
auto base64 = identity->ToBase64 ();
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, base64.c_str ());
|
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, base64.c_str ());
|
||||||
#else
|
#else
|
||||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, base64.c_str ());
|
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, base64.c_str ());
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, l, false);
|
SendMessageReply (m_Buffer, l, false);
|
||||||
|
@ -525,7 +561,7 @@ namespace client
|
||||||
|
|
||||||
void SAMSocket::ExtractParams (char * buf, std::map<std::string, std::string>& params)
|
void SAMSocket::ExtractParams (char * buf, std::map<std::string, std::string>& params)
|
||||||
{
|
{
|
||||||
char * separator;
|
char * separator;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
separator = strchr (buf, ' ');
|
separator = strchr (buf, ' ');
|
||||||
|
@ -536,11 +572,11 @@ namespace client
|
||||||
*value = 0;
|
*value = 0;
|
||||||
value++;
|
value++;
|
||||||
params[buf] = value;
|
params[buf] = value;
|
||||||
}
|
}
|
||||||
buf = separator + 1;
|
buf = separator + 1;
|
||||||
}
|
}
|
||||||
while (separator);
|
while (separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::Receive ()
|
void SAMSocket::Receive ()
|
||||||
{
|
{
|
||||||
|
@ -550,7 +586,7 @@ namespace client
|
||||||
Terminate ();
|
Terminate ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_Socket.async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset),
|
m_Socket.async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset),
|
||||||
std::bind((m_SocketType == eSAMSocketTypeStream) ? &SAMSocket::HandleReceived : &SAMSocket::HandleMessage,
|
std::bind((m_SocketType == eSAMSocketTypeStream) ? &SAMSocket::HandleReceived : &SAMSocket::HandleMessage,
|
||||||
shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
@ -566,17 +602,17 @@ namespace client
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_Stream)
|
if (m_Stream)
|
||||||
{
|
{
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
m_Stream->AsyncSend ((uint8_t *)m_Buffer, bytes_transferred,
|
m_Stream->AsyncSend ((uint8_t *)m_Buffer, bytes_transferred,
|
||||||
[s](const boost::system::error_code& ecode)
|
[s](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
if (!ecode)
|
if (!ecode)
|
||||||
s->Receive ();
|
s->Receive ();
|
||||||
else
|
else
|
||||||
s->m_Owner.GetService ().post ([s] { s->Terminate (); });
|
s->m_Owner.GetService ().post ([s] { s->Terminate (); });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +622,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew ||
|
if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew ||
|
||||||
m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular
|
m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular
|
||||||
{
|
{
|
||||||
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE),
|
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE),
|
||||||
std::bind (&SAMSocket::HandleI2PReceive, shared_from_this (),
|
std::bind (&SAMSocket::HandleI2PReceive, shared_from_this (),
|
||||||
std::placeholders::_1, std::placeholders::_2),
|
std::placeholders::_1, std::placeholders::_2),
|
||||||
|
@ -602,10 +638,10 @@ namespace client
|
||||||
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
|
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
else // no more data
|
else // no more data
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void SAMSocket::HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
|
@ -617,17 +653,17 @@ namespace client
|
||||||
if (bytes_transferred > 0)
|
if (bytes_transferred > 0)
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred),
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred),
|
||||||
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); // postpone termination
|
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); // postpone termination
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
m_Owner.GetService ().post ([s] { s->Terminate (); });
|
m_Owner.GetService ().post ([s] { s->Terminate (); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
m_Owner.GetService ().post ([s] { s->Terminate (); });
|
m_Owner.GetService ().post ([s] { s->Terminate (); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -658,7 +694,7 @@ namespace client
|
||||||
context.GetAddressBook ().InsertAddress (stream->GetRemoteIdentity ());
|
context.GetAddressBook ().InsertAddress (stream->GetRemoteIdentity ());
|
||||||
auto session = m_Owner.FindSession (m_ID);
|
auto session = m_Owner.FindSession (m_ID);
|
||||||
if (session)
|
if (session)
|
||||||
{
|
{
|
||||||
// find more pending acceptors
|
// find more pending acceptors
|
||||||
for (auto it: session->ListSockets ())
|
for (auto it: session->ListSockets ())
|
||||||
if (it->m_SocketType == eSAMSocketTypeAcceptor)
|
if (it->m_SocketType == eSAMSocketTypeAcceptor)
|
||||||
|
@ -674,44 +710,66 @@ namespace client
|
||||||
const size_t ident_len = ident_ptr->GetFullLen();
|
const size_t ident_len = ident_ptr->GetFullLen();
|
||||||
uint8_t* ident = new uint8_t[ident_len];
|
uint8_t* ident = new uint8_t[ident_len];
|
||||||
|
|
||||||
// send remote peer address as base64
|
// send remote peer address as base64
|
||||||
const size_t l = ident_ptr->ToBuffer (ident, ident_len);
|
const size_t l = ident_ptr->ToBuffer (ident, ident_len);
|
||||||
const size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE);
|
const size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE);
|
||||||
delete[] ident;
|
delete[] ident;
|
||||||
m_StreamBuffer[l1] = '\n';
|
m_StreamBuffer[l1] = '\n';
|
||||||
HandleI2PReceive (boost::system::error_code (), l1 +1); // we send identity like it has been received from stream
|
HandleI2PReceive (boost::system::error_code (), l1 +1); // we send identity like it has been received from stream
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
I2PReceive ();
|
I2PReceive ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "SAM: I2P acceptor has been reset");
|
LogPrint (eLogWarning, "SAM: I2P acceptor has been reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
|
void SAMSocket::HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "SAM: datagram received ", len);
|
LogPrint (eLogDebug, "SAM: datagram received ", len);
|
||||||
auto base64 = from.ToBase64 ();
|
auto base64 = from.ToBase64 ();
|
||||||
#ifdef _MSC_VER
|
auto ep = m_Session->UDPEndpoint;
|
||||||
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
if (ep)
|
||||||
#else
|
{
|
||||||
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
// udp forward enabled
|
||||||
#endif
|
size_t bsz = base64.size();
|
||||||
if (len < SAM_SOCKET_BUFFER_SIZE - l)
|
size_t sz = bsz + 1 + len;
|
||||||
{
|
// build datagram body
|
||||||
memcpy (m_StreamBuffer + l, buf, len);
|
uint8_t * data = new uint8_t[sz];
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len + l),
|
// Destination
|
||||||
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
|
memcpy(data, base64.c_str(), bsz);
|
||||||
|
// linefeed
|
||||||
|
data[bsz] = '\n';
|
||||||
|
// Payload
|
||||||
|
memcpy(data+bsz+1, buf, len);
|
||||||
|
// send to remote endpoint
|
||||||
|
m_Owner.SendTo(data, sz, ep);
|
||||||
|
delete [] data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer");
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
||||||
|
#else
|
||||||
|
size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len);
|
||||||
|
#endif
|
||||||
|
if (len < SAM_SOCKET_BUFFER_SIZE - l)
|
||||||
|
{
|
||||||
|
memcpy (m_StreamBuffer + l, buf, len);
|
||||||
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len + l),
|
||||||
|
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SAMSession::SAMSession (std::shared_ptr<ClientDestination> dest):
|
SAMSession::SAMSession (std::shared_ptr<ClientDestination> dest):
|
||||||
localDestination (dest)
|
localDestination (dest),
|
||||||
|
UDPEndpoint(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SAMSession::~SAMSession ()
|
SAMSession::~SAMSession ()
|
||||||
{
|
{
|
||||||
CloseStreams();
|
CloseStreams();
|
||||||
|
@ -741,7 +799,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
Stop ();
|
Stop ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMBridge::Start ()
|
void SAMBridge::Start ()
|
||||||
{
|
{
|
||||||
|
@ -760,26 +818,26 @@ namespace client
|
||||||
m_Sessions.clear ();
|
m_Sessions.clear ();
|
||||||
m_Service.stop ();
|
m_Service.stop ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
{
|
{
|
||||||
m_Thread->join ();
|
m_Thread->join ();
|
||||||
delete m_Thread;
|
delete m_Thread;
|
||||||
m_Thread = nullptr;
|
m_Thread = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMBridge::Run ()
|
void SAMBridge::Run ()
|
||||||
{
|
{
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_Service.run ();
|
m_Service.run ();
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SAM: runtime exception: ", ex.what ());
|
LogPrint (eLogError, "SAM: runtime exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMBridge::Accept ()
|
void SAMBridge::Accept ()
|
||||||
|
@ -796,7 +854,7 @@ namespace client
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
auto ep = socket->GetSocket ().remote_endpoint (ec);
|
auto ep = socket->GetSocket ().remote_endpoint (ec);
|
||||||
if (!ec)
|
if (!ec)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "SAM: new connection from ", ep);
|
LogPrint (eLogDebug, "SAM: new connection from ", ep);
|
||||||
socket->ReceiveHandshake ();
|
socket->ReceiveHandshake ();
|
||||||
}
|
}
|
||||||
|
@ -810,10 +868,10 @@ namespace client
|
||||||
Accept ();
|
Accept ();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SAMSession> SAMBridge::CreateSession (const std::string& id, const std::string& destination,
|
std::shared_ptr<SAMSession> SAMBridge::CreateSession (const std::string& id, const std::string& destination,
|
||||||
const std::map<std::string, std::string> * params)
|
const std::map<std::string, std::string> * params)
|
||||||
{
|
{
|
||||||
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
std::shared_ptr<ClientDestination> localDestination = nullptr;
|
||||||
if (destination != "")
|
if (destination != "")
|
||||||
{
|
{
|
||||||
i2p::data::PrivateKeys keys;
|
i2p::data::PrivateKeys keys;
|
||||||
|
@ -828,10 +886,10 @@ namespace client
|
||||||
{
|
{
|
||||||
auto it = params->find (SAM_PARAM_SIGNATURE_TYPE);
|
auto it = params->find (SAM_PARAM_SIGNATURE_TYPE);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
// TODO: extract string values
|
// TODO: extract string values
|
||||||
signatureType = std::stoi(it->second);
|
signatureType = std::stoi(it->second);
|
||||||
}
|
}
|
||||||
localDestination = i2p::client::context.CreateNewLocalDestination (true, signatureType, params);
|
localDestination = i2p::client::context.CreateNewLocalDestination (true, signatureType, params);
|
||||||
}
|
}
|
||||||
if (localDestination)
|
if (localDestination)
|
||||||
{
|
{
|
||||||
|
@ -852,13 +910,13 @@ namespace client
|
||||||
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
||||||
auto it = m_Sessions.find (id);
|
auto it = m_Sessions.find (id);
|
||||||
if (it != m_Sessions.end ())
|
if (it != m_Sessions.end ())
|
||||||
{
|
{
|
||||||
session = it->second;
|
session = it->second;
|
||||||
m_Sessions.erase (it);
|
m_Sessions.erase (it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (session)
|
if (session)
|
||||||
{
|
{
|
||||||
session->localDestination->StopAcceptingStreams ();
|
session->localDestination->StopAcceptingStreams ();
|
||||||
session->CloseStreams ();
|
session->CloseStreams ();
|
||||||
}
|
}
|
||||||
|
@ -873,12 +931,20 @@ namespace client
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SAMBridge::SendTo(const uint8_t * buf, size_t len, std::shared_ptr<boost::asio::ip::udp::endpoint> remote)
|
||||||
|
{
|
||||||
|
if(remote)
|
||||||
|
{
|
||||||
|
m_DatagramSocket.send_to(boost::asio::buffer(buf, len), *remote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SAMBridge::ReceiveDatagram ()
|
void SAMBridge::ReceiveDatagram ()
|
||||||
{
|
{
|
||||||
m_DatagramSocket.async_receive_from (
|
m_DatagramSocket.async_receive_from (
|
||||||
boost::asio::buffer (m_DatagramReceiveBuffer, i2p::datagram::MAX_DATAGRAM_SIZE),
|
boost::asio::buffer (m_DatagramReceiveBuffer, i2p::datagram::MAX_DATAGRAM_SIZE),
|
||||||
m_SenderEndpoint,
|
m_SenderEndpoint,
|
||||||
std::bind (&SAMBridge::HandleReceivedDatagram, this, std::placeholders::_1, std::placeholders::_2));
|
std::bind (&SAMBridge::HandleReceivedDatagram, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMBridge::HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void SAMBridge::HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
|
@ -888,7 +954,7 @@ namespace client
|
||||||
m_DatagramReceiveBuffer[bytes_transferred] = 0;
|
m_DatagramReceiveBuffer[bytes_transferred] = 0;
|
||||||
char * eol = strchr ((char *)m_DatagramReceiveBuffer, '\n');
|
char * eol = strchr ((char *)m_DatagramReceiveBuffer, '\n');
|
||||||
*eol = 0; eol++;
|
*eol = 0; eol++;
|
||||||
size_t payloadLen = bytes_transferred - ((uint8_t *)eol - m_DatagramReceiveBuffer);
|
size_t payloadLen = bytes_transferred - ((uint8_t *)eol - m_DatagramReceiveBuffer);
|
||||||
LogPrint (eLogDebug, "SAM: datagram received ", m_DatagramReceiveBuffer," size=", payloadLen);
|
LogPrint (eLogDebug, "SAM: datagram received ", m_DatagramReceiveBuffer," size=", payloadLen);
|
||||||
char * sessionID = strchr ((char *)m_DatagramReceiveBuffer, ' ');
|
char * sessionID = strchr ((char *)m_DatagramReceiveBuffer, ' ');
|
||||||
if (sessionID)
|
if (sessionID)
|
||||||
|
@ -900,12 +966,12 @@ namespace client
|
||||||
*destination = 0; destination++;
|
*destination = 0; destination++;
|
||||||
auto session = FindSession (sessionID);
|
auto session = FindSession (sessionID);
|
||||||
if (session)
|
if (session)
|
||||||
{
|
{
|
||||||
i2p::data::IdentityEx dest;
|
i2p::data::IdentityEx dest;
|
||||||
dest.FromBase64 (destination);
|
dest.FromBase64 (destination);
|
||||||
session->localDestination->GetDatagramDestination ()->
|
session->localDestination->GetDatagramDestination ()->
|
||||||
SendDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ());
|
SendDatagramTo ((uint8_t *)eol, payloadLen, dest.GetIdentHash ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "SAM: Session ", sessionID, " not found");
|
LogPrint (eLogError, "SAM: Session ", sessionID, " not found");
|
||||||
}
|
}
|
||||||
|
|
63
SAM.h
63
SAM.h
|
@ -20,45 +20,48 @@ namespace client
|
||||||
{
|
{
|
||||||
const size_t SAM_SOCKET_BUFFER_SIZE = 8192;
|
const size_t SAM_SOCKET_BUFFER_SIZE = 8192;
|
||||||
const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds
|
const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds
|
||||||
const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds
|
const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds
|
||||||
const char SAM_HANDSHAKE[] = "HELLO VERSION";
|
const char SAM_HANDSHAKE[] = "HELLO VERSION";
|
||||||
const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n";
|
const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n";
|
||||||
const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n";
|
const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n";
|
||||||
const char SAM_SESSION_CREATE[] = "SESSION CREATE";
|
const char SAM_SESSION_CREATE[] = "SESSION CREATE";
|
||||||
const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n";
|
const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n";
|
||||||
const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n";
|
const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n";
|
||||||
const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n";
|
const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n";
|
||||||
const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n";
|
const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n";
|
||||||
|
const char SAM_SESSION_STATUS_I2P_ERROR[] = "SESSION STATUS RESULT=I2P_ERROR MESSAGE=%s\n";
|
||||||
const char SAM_STREAM_CONNECT[] = "STREAM CONNECT";
|
const char SAM_STREAM_CONNECT[] = "STREAM CONNECT";
|
||||||
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
|
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
|
||||||
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
|
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
|
||||||
const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n";
|
const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n";
|
||||||
const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR\n";
|
const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR\n";
|
||||||
const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT";
|
const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT";
|
||||||
const char SAM_DATAGRAM_SEND[] = "DATAGRAM SEND";
|
const char SAM_DATAGRAM_SEND[] = "DATAGRAM SEND";
|
||||||
const char SAM_DEST_GENERATE[] = "DEST GENERATE";
|
const char SAM_DEST_GENERATE[] = "DEST GENERATE";
|
||||||
const char SAM_DEST_REPLY[] = "DEST REPLY PUB=%s PRIV=%s\n";
|
const char SAM_DEST_REPLY[] = "DEST REPLY PUB=%s PRIV=%s\n";
|
||||||
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
|
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
|
||||||
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
|
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
|
||||||
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
|
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
|
||||||
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
|
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
|
||||||
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
|
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
|
||||||
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=INVALID_KEY_NOT_FOUND NAME=%s\n";
|
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=INVALID_KEY_NOT_FOUND NAME=%s\n";
|
||||||
const char SAM_PARAM_MIN[] = "MIN";
|
const char SAM_PARAM_MIN[] = "MIN";
|
||||||
const char SAM_PARAM_MAX[] = "MAX";
|
const char SAM_PARAM_MAX[] = "MAX";
|
||||||
const char SAM_PARAM_STYLE[] = "STYLE";
|
const char SAM_PARAM_STYLE[] = "STYLE";
|
||||||
const char SAM_PARAM_ID[] = "ID";
|
const char SAM_PARAM_ID[] = "ID";
|
||||||
const char SAM_PARAM_SILENT[] = "SILENT";
|
const char SAM_PARAM_SILENT[] = "SILENT";
|
||||||
const char SAM_PARAM_DESTINATION[] = "DESTINATION";
|
const char SAM_PARAM_DESTINATION[] = "DESTINATION";
|
||||||
const char SAM_PARAM_NAME[] = "NAME";
|
const char SAM_PARAM_NAME[] = "NAME";
|
||||||
const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE";
|
const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE";
|
||||||
const char SAM_PARAM_SIZE[] = "SIZE";
|
const char SAM_PARAM_SIZE[] = "SIZE";
|
||||||
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
|
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
|
||||||
const char SAM_VALUE_STREAM[] = "STREAM";
|
const char SAM_VALUE_STREAM[] = "STREAM";
|
||||||
const char SAM_VALUE_DATAGRAM[] = "DATAGRAM";
|
const char SAM_VALUE_DATAGRAM[] = "DATAGRAM";
|
||||||
const char SAM_VALUE_RAW[] = "RAW";
|
const char SAM_VALUE_RAW[] = "RAW";
|
||||||
const char SAM_VALUE_TRUE[] = "true";
|
const char SAM_VALUE_TRUE[] = "true";
|
||||||
const char SAM_VALUE_FALSE[] = "false";
|
const char SAM_VALUE_FALSE[] = "false";
|
||||||
|
const char SAM_VALUE_HOST[] = "HOST";
|
||||||
|
const char SAM_VALUE_PORT[] = "PORT";
|
||||||
|
|
||||||
enum SAMSocketType
|
enum SAMSocketType
|
||||||
{
|
{
|
||||||
|
@ -76,8 +79,8 @@ namespace client
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SAMSocket (SAMBridge& owner);
|
SAMSocket (SAMBridge& owner);
|
||||||
~SAMSocket ();
|
~SAMSocket ();
|
||||||
void CloseStream (); // TODO: implement it better
|
void CloseStream (); // TODO: implement it better
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||||
void ReceiveHandshake ();
|
void ReceiveHandshake ();
|
||||||
|
@ -86,16 +89,16 @@ namespace client
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Terminate ();
|
void Terminate ();
|
||||||
void HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void SendMessageReply (const char * msg, size_t len, bool close);
|
void SendMessageReply (const char * msg, size_t len, bool close);
|
||||||
void HandleMessageReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred, bool close);
|
void HandleMessageReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred, bool close);
|
||||||
void Receive ();
|
void Receive ();
|
||||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
|
||||||
void I2PReceive ();
|
void I2PReceive ();
|
||||||
void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleI2PAccept (std::shared_ptr<i2p::stream::Stream> stream);
|
void HandleI2PAccept (std::shared_ptr<i2p::stream::Stream> stream);
|
||||||
void HandleWriteI2PData (const boost::system::error_code& ecode);
|
void HandleWriteI2PData (const boost::system::error_code& ecode);
|
||||||
|
@ -106,7 +109,8 @@ namespace client
|
||||||
void ProcessStreamAccept (char * buf, size_t len);
|
void ProcessStreamAccept (char * buf, size_t len);
|
||||||
void ProcessDestGenerate ();
|
void ProcessDestGenerate ();
|
||||||
void ProcessNamingLookup (char * buf, size_t len);
|
void ProcessNamingLookup (char * buf, size_t len);
|
||||||
size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0
|
void SendI2PError(const std::string & msg);
|
||||||
|
size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0
|
||||||
void ExtractParams (char * buf, std::map<std::string, std::string>& params);
|
void ExtractParams (char * buf, std::map<std::string, std::string>& params);
|
||||||
|
|
||||||
void Connect (std::shared_ptr<const i2p::data::LeaseSet> remote);
|
void Connect (std::shared_ptr<const i2p::data::LeaseSet> remote);
|
||||||
|
@ -129,12 +133,13 @@ namespace client
|
||||||
bool m_IsSilent;
|
bool m_IsSilent;
|
||||||
std::shared_ptr<i2p::stream::Stream> m_Stream;
|
std::shared_ptr<i2p::stream::Stream> m_Stream;
|
||||||
std::shared_ptr<SAMSession> m_Session;
|
std::shared_ptr<SAMSession> m_Session;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SAMSession
|
struct SAMSession
|
||||||
{
|
{
|
||||||
std::shared_ptr<ClientDestination> localDestination;
|
std::shared_ptr<ClientDestination> localDestination;
|
||||||
std::list<std::shared_ptr<SAMSocket> > m_Sockets;
|
std::list<std::shared_ptr<SAMSocket> > m_Sockets;
|
||||||
|
std::shared_ptr<boost::asio::ip::udp::endpoint> UDPEndpoint;
|
||||||
std::mutex m_SocketsMutex;
|
std::mutex m_SocketsMutex;
|
||||||
|
|
||||||
/** safely add a socket to this session */
|
/** safely add a socket to this session */
|
||||||
|
@ -158,8 +163,8 @@ namespace client
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
SAMSession (std::shared_ptr<ClientDestination> dest);
|
SAMSession (std::shared_ptr<ClientDestination> dest);
|
||||||
~SAMSession ();
|
~SAMSession ();
|
||||||
|
|
||||||
void CloseStreams ();
|
void CloseStreams ();
|
||||||
|
@ -174,13 +179,16 @@ namespace client
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
std::shared_ptr<SAMSession> CreateSession (const std::string& id, const std::string& destination, // empty string means transient
|
std::shared_ptr<SAMSession> CreateSession (const std::string& id, const std::string& destination, // empty string means transient
|
||||||
const std::map<std::string, std::string> * params);
|
const std::map<std::string, std::string> * params);
|
||||||
void CloseSession (const std::string& id);
|
void CloseSession (const std::string& id);
|
||||||
std::shared_ptr<SAMSession> FindSession (const std::string& id) const;
|
std::shared_ptr<SAMSession> FindSession (const std::string& id) const;
|
||||||
|
|
||||||
|
/** send raw data to remote endpoint from our UDP Socket */
|
||||||
|
void SendTo(const uint8_t * buf, size_t len, std::shared_ptr<boost::asio::ip::udp::endpoint> remote);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
|
@ -194,7 +202,7 @@ namespace client
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::ip::tcp::acceptor m_Acceptor;
|
boost::asio::ip::tcp::acceptor m_Acceptor;
|
||||||
boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint;
|
boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint;
|
||||||
|
@ -207,9 +215,8 @@ namespace client
|
||||||
|
|
||||||
// for HTTP
|
// for HTTP
|
||||||
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
470
Streaming.cpp
470
Streaming.cpp
File diff suppressed because it is too large
Load diff
|
@ -158,6 +158,8 @@ namespace stream
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void CleanUp ();
|
||||||
|
|
||||||
void SendBuffer ();
|
void SendBuffer ();
|
||||||
void SendQuickAck ();
|
void SendQuickAck ();
|
||||||
void SendClose ();
|
void SendClose ();
|
||||||
|
|
|
@ -85,6 +85,8 @@ namespace tunnel
|
||||||
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
|
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
|
||||||
m_Endpoint (false) {}; // transit endpoint is always outbound
|
m_Endpoint (false) {}; // transit endpoint is always outbound
|
||||||
|
|
||||||
|
void Cleanup () { m_Endpoint.Cleanup (); }
|
||||||
|
|
||||||
void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg);
|
void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg);
|
||||||
size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }
|
size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }
|
||||||
|
|
||||||
|
|
|
@ -101,8 +101,9 @@ namespace transport
|
||||||
|
|
||||||
void DHKeysPairSupplier::Return (std::shared_ptr<i2p::crypto::DHKeys> pair)
|
void DHKeysPairSupplier::Return (std::shared_ptr<i2p::crypto::DHKeys> pair)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
std::unique_lock<std::mutex>l(m_AcquiredMutex);
|
||||||
m_Queue.push (pair);
|
if ((int)m_Queue.size () < 2*m_QueueSize)
|
||||||
|
m_Queue.push (pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transports transports;
|
Transports transports;
|
||||||
|
@ -417,7 +418,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Transports: RouterInfo not found, Failed to send messages");
|
LogPrint (eLogWarning, "Transports: RouterInfo not found, Failed to send messages");
|
||||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||||
m_Peers.erase (it);
|
m_Peers.erase (it);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ LOCAL_MODULE := i2pd
|
||||||
LOCAL_CPP_FEATURES := rtti exceptions
|
LOCAL_CPP_FEATURES := rtti exceptions
|
||||||
LOCAL_C_INCLUDES += $(IFADDRS_PATH) ../..
|
LOCAL_C_INCLUDES += $(IFADDRS_PATH) ../..
|
||||||
LOCAL_STATIC_LIBRARIES := \
|
LOCAL_STATIC_LIBRARIES := \
|
||||||
boost_system-gcc-mt-1_53 \
|
boost_system \
|
||||||
boost_date_time-gcc-mt-1_53 \
|
boost_date_time \
|
||||||
boost_filesystem-gcc-mt-1_53 \
|
boost_filesystem \
|
||||||
boost_program_options-gcc-mt-1_53 \
|
boost_program_options \
|
||||||
crypto ssl \
|
crypto ssl \
|
||||||
miniupnpc
|
miniupnpc
|
||||||
LOCAL_LDLIBS := -lz
|
LOCAL_LDLIBS := -lz
|
||||||
|
@ -68,44 +68,44 @@ include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_system-gcc-mt-1_53
|
LOCAL_MODULE := boost_system
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_system-gcc-mt-1_53.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_date_time-gcc-mt-1_53
|
LOCAL_MODULE := boost_date_time
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time-gcc-mt-1_53.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_filesystem-gcc-mt-1_53
|
LOCAL_MODULE := boost_filesystem
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem-gcc-mt-1_53.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := boost_program_options-gcc-mt-1_53
|
LOCAL_MODULE := boost_program_options
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_53_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options-gcc-mt-1_53.a
|
LOCAL_SRC_FILES := $(BOOST_PATH)/boost_1_62_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_53_0/include
|
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost_1_62_0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := crypto
|
LOCAL_MODULE := crypto
|
||||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.0.2/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.0.2/include
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0/include
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := ssl
|
LOCAL_MODULE := ssl
|
||||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.0.2/$(TARGET_ARCH_ABI)/lib/libssl.a
|
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.0/$(TARGET_ARCH_ABI)/lib/libssl.a
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.0.2/include
|
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.0/include
|
||||||
LOCAL_STATIC_LIBRARIES := crypto
|
LOCAL_STATIC_LIBRARIES := crypto
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 1.9 KiB |
2
contrib/.gitignore
vendored
Normal file
2
contrib/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
i2pd*.zip
|
||||||
|
build*.log
|
22
contrib/build_mingw.cmd
Normal file
22
contrib/build_mingw.cmd
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
@echo off
|
||||||
|
title ‘¡®àª i2pd
|
||||||
|
|
||||||
|
set "WD=C:\msys64"
|
||||||
|
set CHERE_INVOKING=enabled_from_arguments
|
||||||
|
set MSYSCON=mintty.exe
|
||||||
|
|
||||||
|
echo ‘¡®àª i2pd ¤«ï win32. <20> ¦¬¨â¥ Enter ¯®á«¥ ®ª®ç ¨ï ª®¬¯¨«ï樨...
|
||||||
|
set "MSYSTEM=MINGW32"
|
||||||
|
set "CONTITLE=MinGW x32"
|
||||||
|
start "%CONTITLE%" /WAIT C:\msys64\usr\bin\mintty.exe -i /msys2.ico /usr/bin/bash --login build_mingw.sh
|
||||||
|
pause
|
||||||
|
|
||||||
|
echo ‘¡®àª i2pd ¤«ï win64. <20> ¦¬¨â¥ Enter ¯®á«¥ ®ª®ç ¨ï ª®¬¯¨«ï樨...
|
||||||
|
set "MSYSTEM=MINGW64"
|
||||||
|
set "CONTITLE=MinGW x64"
|
||||||
|
start "%CONTITLE%" /WAIT C:\msys64\usr\bin\mintty.exe -i /msys2.ico /usr/bin/bash --login build_mingw.sh
|
||||||
|
pause
|
||||||
|
|
||||||
|
echo ‘¡®àª § ¢¥àè¥ ...
|
||||||
|
pause
|
||||||
|
exit /b 0
|
84
contrib/build_mingw.sh
Normal file
84
contrib/build_mingw.sh
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Определяем архитектуру.
|
||||||
|
if [ $MSYSTEM == MINGW64 ]; then
|
||||||
|
export arch="win64"
|
||||||
|
elif [ $MSYSTEM == MINGW32 ]; then
|
||||||
|
export arch="win32"
|
||||||
|
else
|
||||||
|
echo "Не могу понять, какая у вас архитектура, используемая для сборки.";
|
||||||
|
echo "Вы точно запустили скрипт в оболочке MSYS2 MinGW [64/32]-bit ?";
|
||||||
|
echo "Обычно её можно запустить выполнив c:\msys64\mingw64.exe или c:\msys64\mingw32.exe";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Задаём переменной contrib текущий путь и переходим на уровень выше.
|
||||||
|
export contrib=$PWD
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Очистка от предыдущей сборки (на всякий случай =) ).
|
||||||
|
make clean >> /dev/null
|
||||||
|
|
||||||
|
# Обновляем репозиторий, и получаем хеш последнего коммита.
|
||||||
|
echo "Получаем обновления из репозитория.";
|
||||||
|
git pull
|
||||||
|
if [ "$?" != 0 ]; then
|
||||||
|
echo "Не удалось обновить локальный репозиторий.";
|
||||||
|
echo "Вы точно запустили скрипт в папке репозитория?";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
export commit=$(git rev-parse --verify HEAD | cut -c -7)
|
||||||
|
if [ -z commit ]; then
|
||||||
|
echo "Не удалось получить хеш последнего коммита.";
|
||||||
|
echo "Вы точно запустили скрипт в папке репозитория?";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Получаем версию приложения
|
||||||
|
export version=$(grep -E "I2PD_VERSION_(MAJOR|MINOR|MICRO)\ " version.h | grep -oE '[^ ]+$' | tr '\n' '.'|head -c -1)
|
||||||
|
|
||||||
|
# Получаем количество ядер, и уменьшаем количество потоков на 1 от количества ядер (если их больше чем 1).
|
||||||
|
if [ $NUMBER_OF_PROCESSORS -ge 2 ]; then
|
||||||
|
export threads=$(( $NUMBER_OF_PROCESSORS - 1 ))
|
||||||
|
else
|
||||||
|
export threads=$NUMBER_OF_PROCESSORS
|
||||||
|
fi;
|
||||||
|
|
||||||
|
echo "Собираем i2pd ${version} (коммит ${commit}) для ${arch}.";
|
||||||
|
|
||||||
|
# Собираем приложение с разными параметрами, и архивируем в zip архивы.
|
||||||
|
make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j ${threads} > ${contrib}/build_avx_aesni.log 2>&1
|
||||||
|
if [ "$?" != 0 ]; then
|
||||||
|
echo "Сборка не удалась. Смотрите в build_avx_aesni.log";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw_avx_aesni.zip i2pd.exe >> /dev/null
|
||||||
|
make clean >> /dev/null
|
||||||
|
|
||||||
|
make USE_UPNP=yes USE_AVX=1 -j ${threads} > ${contrib}/build_avx.log 2>&1
|
||||||
|
if [ "$?" != 0 ]; then
|
||||||
|
echo "Сборка не удалась. Смотрите в build_avx.log.";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw_avx.zip i2pd.exe >> /dev/null
|
||||||
|
make clean >> /dev/null
|
||||||
|
|
||||||
|
make USE_UPNP=yes USE_AESNI=1 -j ${threads} > ${contrib}/build_aesni.log 2>&1
|
||||||
|
if [ "$?" != 0 ]; then
|
||||||
|
echo "Сборка не удалась. Смотрите в build_aesni.log";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw_aesni.zip i2pd.exe >> /dev/null
|
||||||
|
make clean >> /dev/null
|
||||||
|
|
||||||
|
make USE_UPNP=yes -j ${threads} > ${contrib}/build.log 2>&1
|
||||||
|
if [ "$?" != 0 ]; then
|
||||||
|
echo "Сборка не удалась. Смотрите в build.log";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
zip -9 ${contrib}/i2pd_${version}_${commit}_${arch}_mingw.zip i2pd.exe >> /dev/null
|
||||||
|
make clean >> /dev/null
|
||||||
|
|
||||||
|
echo "Сборка i2pd ${version} для ${arch} завершена.";
|
||||||
|
exit 0;
|
|
@ -1,2 +1,2 @@
|
||||||
This forder contain systemd unit files.
|
This forder contain systemd unit files.
|
||||||
To use systemd daemon control, place files from this directory to debian folder.
|
To use systemd daemon control, place files from this directory to debian folder before building package.
|
||||||
|
|
2
debian/i2pd.init
vendored
2
debian/i2pd.init
vendored
|
@ -53,7 +53,7 @@ do_start()
|
||||||
|| return 1
|
|| return 1
|
||||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
|
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
|
||||||
--service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \
|
--service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \
|
||||||
$DAEMON_OPTS > /dev/null 2>&1 \
|
--pidfile=$PIDFILE $DAEMON_OPTS > /dev/null 2>&1 \
|
||||||
|| return 2
|
|| return 2
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 36 KiB |
Binary file not shown.
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 1.9 KiB |
|
@ -36,7 +36,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
|
||||||
../../SSUData.cpp ../../SSUSession.cpp ../../Streaming.cpp ../../TransitTunnel.cpp \
|
../../SSUData.cpp ../../SSUSession.cpp ../../Streaming.cpp ../../TransitTunnel.cpp \
|
||||||
../../Transports.cpp ../../Tunnel.cpp ../../TunnelEndpoint.cpp ../../TunnelGateway.cpp \
|
../../Transports.cpp ../../Tunnel.cpp ../../TunnelEndpoint.cpp ../../TunnelGateway.cpp \
|
||||||
../../TunnelPool.cpp ../../UPnP.cpp ../../Gzip.cpp ../../Timestamp.cpp ../../util.cpp \
|
../../TunnelPool.cpp ../../UPnP.cpp ../../Gzip.cpp ../../Timestamp.cpp ../../util.cpp \
|
||||||
../../Event.cpp ../../BloomFiler.cpp ../../i2pd.cpp
|
../../Event.cpp ../../BloomFilter.cpp ../../WebSocks.cpp ../../i2pd.cpp
|
||||||
|
|
||||||
HEADERS += DaemonQT.h mainwindow.h \
|
HEADERS += DaemonQT.h mainwindow.h \
|
||||||
../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \
|
../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \
|
||||||
|
@ -51,7 +51,7 @@ HEADERS += DaemonQT.h mainwindow.h \
|
||||||
../../TransportSession.h ../../Tunnel.h ../../TunnelBase.h ../../TunnelConfig.h \
|
../../TransportSession.h ../../Tunnel.h ../../TunnelBase.h ../../TunnelConfig.h \
|
||||||
../../TunnelEndpoint.h ../../TunnelGateway.h ../../TunnelPool.h ../../UPnP.h \
|
../../TunnelEndpoint.h ../../TunnelGateway.h ../../TunnelPool.h ../../UPnP.h \
|
||||||
../../util.h ../../version.h ../../Gzip.h ../../Tag.h \
|
../../util.h ../../version.h ../../Gzip.h ../../Tag.h \
|
||||||
../../BloomFiler.h ../../Event.h
|
../../BloomFilter.h ../../Event.h ../../WebSocks.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui
|
FORMS += mainwindow.ui
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue