Merge pull request #791 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2017-02-01 14:18:41 -05:00 committed by GitHub
commit 040585bf3d
33 changed files with 795 additions and 503 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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 ();

View file

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

View file

@ -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 ();

View file

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

View file

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

View file

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

View file

@ -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 ();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

@ -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, &params); 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, &params);
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
View file

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

File diff suppressed because it is too large Load diff

View file

@ -158,6 +158,8 @@ namespace stream
private: private:
void CleanUp ();
void SendBuffer (); void SendBuffer ();
void SendQuickAck (); void SendQuickAck ();
void SendClose (); void SendClose ();

View file

@ -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 (); }

View file

@ -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);
} }

View file

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

@ -0,0 +1,2 @@
i2pd*.zip
build*.log

22
contrib/build_mingw.cmd Normal file
View 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
View 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;

View file

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

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

View file

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