From 987688f196188cb209656324ca14302ce3f8fa93 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 7 Apr 2017 11:17:40 -0400 Subject: [PATCH 01/14] GOST hash of a Little Endian stream --- Gost.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Gost.h | 9 ++++++ 2 files changed, 96 insertions(+) diff --git a/Gost.cpp b/Gost.cpp index ba34c66c..688035eb 100644 --- a/Gost.cpp +++ b/Gost.cpp @@ -438,5 +438,92 @@ namespace crypto memset (iv, 0, 64); H (iv, buf, len, digest); } + + // reverse order + struct GOSTR3411_2012_CTX + { + GOST3411Block h, N, s, m; + size_t len; + bool is512; + }; + + GOSTR3411_2012_CTX * GOSTR3411_2012_CTX_new () + { + return new GOSTR3411_2012_CTX; + } + + void GOSTR3411_2012_CTX_free (GOSTR3411_2012_CTX * ctx) + { + delete ctx; + } + + void GOSTR3411_2012_CTX_Init (GOSTR3411_2012_CTX * ctx, bool is512) + { + uint8_t iv[64]; + memset (iv, is512 ? 0 : 1, 64); + memcpy (ctx->h.buf, iv, 64); + memset (ctx->N.buf, 0, 64); + memset (ctx->s.buf, 0, 64); + ctx->len = 0; + ctx->is512 = is512; + } + + void GOSTR3411_2012_CTX_Update (const uint8_t * buf, size_t len, GOSTR3411_2012_CTX * ctx) + { + if (!len) return; + if (ctx->len > 0) // something left from buffer + { + size_t l = 64 - ctx->len; + if (len < l) l = len; + for (size_t i = 0; i < l; i++) + ctx->m.buf[ctx->len + i] = buf[l-i-1]; // invert + ctx->len += l; len -= l; buf += l; + + ctx->h = gN (ctx->N, ctx->h, ctx->m); + ctx->N.Add (512); + ctx->s = ctx->m + ctx->s; + } + while (len >= 64) + { + for (size_t i = 0; i < 64; i++) + ctx->m.buf[i] = buf[63-i]; // invert + len -= 64; buf += 64; + ctx->h = gN (ctx->N, ctx->h, ctx->m); + ctx->N.Add (512); + ctx->s = ctx->m + ctx->s; + } + if (len > 0) // carry remaining + { + for (size_t i = 0; i < len; i++) + ctx->m.buf[i] = buf[len-i-1]; // invert + } + ctx->len = len; + } + + void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx) + { + GOST3411Block m; + size_t padding = 64 - ctx->len; + if (padding) + { + memset (m.buf, 0, padding - 1); + m.buf[padding - 1] = 1; + } + memcpy (m.buf + padding, ctx->m.buf, ctx->len); + + ctx->h = gN (ctx->N, ctx->h, m); + ctx->N.Add (ctx->len*8); + ctx->s = m + ctx->s; + + GOST3411Block N0; + memset (N0.buf, 0, 64); + ctx->h = gN (N0, ctx->h, ctx->N); + ctx->h = gN (N0, ctx->h, ctx->s); + + size_t sz = ctx->is512 ? 64 : 32; + for (size_t i = 0; i < sz; i++) + digest[i] = ctx->h.buf[sz - i - 1]; + } + } } diff --git a/Gost.h b/Gost.h index 4790f696..66e8bbe8 100644 --- a/Gost.h +++ b/Gost.h @@ -45,8 +45,17 @@ namespace crypto std::unique_ptr& GetGOSTR3410Curve (GOSTR3410ParamSet paramSet); +// Big Endian void GOSTR3411_2012_256 (const uint8_t * buf, size_t len, uint8_t * digest); void GOSTR3411_2012_512 (const uint8_t * buf, size_t len, uint8_t * digest); + +// Little Endian + struct GOSTR3411_2012_CTX; + GOSTR3411_2012_CTX * GOSTR3411_2012_CTX_new (); + void GOSTR3411_2012_CTX_Init (GOSTR3411_2012_CTX * ctx, bool is512 = true); + void GOSTR3411_2012_CTX_Update (const uint8_t * buf, size_t len, GOSTR3411_2012_CTX * ctx); + void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx); + void GOSTR3411_2012_CTX_free (GOSTR3411_2012_CTX * ctx); } } From 9b62f238ed88a5e801e90144d2053e06a2aef8b1 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 8 Apr 2017 12:51:35 -0400 Subject: [PATCH 02/14] add option for client tunnels to build tunnels such that OBEP==IBGW --- ClientContext.cpp | 178 ++++++++++++++++++++---------------- ClientContext.h | 37 ++++---- Datagram.h | 29 +++--- Destination.h | 90 +++++++++--------- I2PTunnel.h | 94 +++++++++---------- Makefile.linux | 2 +- MatchedDestination.cpp | 105 +++++++++++++++++++++ MatchedDestination.h | 35 +++++++ TunnelPool.cpp | 202 +++++++++++++++++++++-------------------- TunnelPool.h | 45 +++++---- build/CMakeLists.txt | 15 +-- filelist.mk | 3 +- 12 files changed, 502 insertions(+), 333 deletions(-) create mode 100644 MatchedDestination.cpp create mode 100644 MatchedDestination.h diff --git a/ClientContext.cpp b/ClientContext.cpp index 3edafd88..d516def8 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -10,20 +10,21 @@ #include "ClientContext.h" #include "SOCKS.h" #include "WebSocks.h" +#include "MatchedDestination.h" namespace i2p { namespace client { - ClientContext context; + ClientContext context; ClientContext::ClientContext (): m_SharedLocalDestination (nullptr), - m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr), + m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr), m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr) { } - - ClientContext::~ClientContext () + + ClientContext::~ClientContext () { delete m_HttpProxy; delete m_SocksProxy; @@ -31,20 +32,20 @@ namespace client delete m_BOBCommandChannel; delete m_I2CPServer; } - + void ClientContext::Start () { if (!m_SharedLocalDestination) - { + { m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination; m_SharedLocalDestination->Start (); } - - m_AddressBook.Start (); - - std::shared_ptr localDestination; + + m_AddressBook.Start (); + + std::shared_ptr localDestination; bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); if (httproxy) { std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); @@ -60,7 +61,7 @@ namespace client std::map params; ReadI2CPOptionsFromConfig ("httpproxy.", params); localDestination = CreateNewLocalDestination (keys, false, ¶ms); - } + } else LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); } @@ -71,10 +72,10 @@ namespace client LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); } } - + localDestination = nullptr; bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); - if (socksproxy) + if (socksproxy) { std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr); @@ -104,8 +105,8 @@ namespace client } // I2P tunnels - ReadTunnels (); - + ReadTunnels (); + // SAM bool sam; i2p::config::GetOption("sam.enabled", sam); if (sam) { @@ -118,7 +119,7 @@ namespace client } catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in SAM bridge: ", e.what()); } - } + } // BOB bool bob; i2p::config::GetOption("bob.enabled", bob); @@ -132,27 +133,27 @@ namespace client } catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in BOB bridge: ", e.what()); } - } + } // I2CP bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp); - if (i2cp) + if (i2cp) { std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr); uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort); LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort); - try + try { m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort); m_I2CPServer->Start (); - } - catch (std::exception& e) + } + catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what()); } - } + } - m_AddressBook.StartResolvers (); + m_AddressBook.StartResolvers (); // start UDP cleanup if (!m_ServerForwards.empty ()) @@ -161,7 +162,7 @@ namespace client ScheduleCleanupUDP(); } } - + void ClientContext::Stop () { if (m_HttpProxy) @@ -185,28 +186,28 @@ namespace client LogPrint(eLogInfo, "Clients: stopping I2P client tunnel on port ", it.first); it.second->Stop (); } - m_ClientTunnels.clear (); + m_ClientTunnels.clear (); for (auto& it: m_ServerTunnels) { LogPrint(eLogInfo, "Clients: stopping I2P server tunnel"); it.second->Stop (); } - m_ServerTunnels.clear (); + m_ServerTunnels.clear (); if (m_SamBridge) { LogPrint(eLogInfo, "Clients: stopping SAM bridge"); m_SamBridge->Stop (); - delete m_SamBridge; + delete m_SamBridge; m_SamBridge = nullptr; - } + } if (m_BOBCommandChannel) { LogPrint(eLogInfo, "Clients: stopping BOB command channel"); m_BOBCommandChannel->Stop (); - delete m_BOBCommandChannel; + delete m_BOBCommandChannel; m_BOBCommandChannel = nullptr; } @@ -214,7 +215,7 @@ namespace client { LogPrint(eLogInfo, "Clients: stopping I2CP"); m_I2CPServer->Stop (); - delete m_I2CPServer; + delete m_I2CPServer; m_I2CPServer = nullptr; } @@ -226,18 +227,18 @@ namespace client m_ServerForwards.clear(); m_ClientForwards.clear(); } - + if (m_CleanupUDPTimer) { - m_CleanupUDPTimer->cancel (); - m_CleanupUDPTimer = nullptr; + m_CleanupUDPTimer->cancel (); + m_CleanupUDPTimer = nullptr; } for (auto& it: m_Destinations) it.second->Stop (); m_Destinations.clear (); m_SharedLocalDestination = nullptr; - } + } void ClientContext::ReloadConfig () { @@ -246,14 +247,14 @@ namespace client Stop(); Start(); } - + bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType) { bool success = true; std::string fullPath = i2p::fs::DataDirPath (filename); std::ifstream s(fullPath, std::ifstream::binary); - if (s.is_open ()) - { + if (s.is_open ()) + { s.seekg (0, std::ios::end); size_t len = s.tellg(); s.seekg (0, std::ios::beg); @@ -267,18 +268,18 @@ namespace client else LogPrint (eLogInfo, "Clients: Local address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " loaded"); delete[] buf; - } + } else { LogPrint (eLogError, "Clients: can't open file ", fullPath, " Creating new one with signature type ", sigType); - keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); + keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out); size_t len = keys.GetFullLen (); uint8_t * buf = new uint8_t[len]; len = keys.ToBuffer (buf, len); f.write ((char *)buf, len); delete[] buf; - + LogPrint (eLogInfo, "Clients: New private keys file ", fullPath, " for ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " created"); } return success; @@ -306,9 +307,9 @@ namespace client } return infos; } - + std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, - const std::map * params) + const std::map * params) { i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); auto localDestination = std::make_shared (keys, isPublic, params); @@ -318,6 +319,16 @@ namespace client return localDestination; } + std::shared_ptr ClientContext::CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params) + { + MatchedTunnelDestination * cl = new MatchedTunnelDestination(keys, name, params); + auto localDestination = std::shared_ptr(cl); + std::unique_lock l(m_DestinationsMutex); + m_Destinations[localDestination->GetIdentHash ()] = localDestination; + localDestination->Start (); + return localDestination; + } + void ClientContext::DeleteLocalDestination (std::shared_ptr destination) { if (!destination) return; @@ -328,7 +339,7 @@ namespace client { std::unique_lock l(m_DestinationsMutex); m_Destinations.erase (it); - } + } d->Stop (); } } @@ -341,32 +352,32 @@ namespace client { LogPrint (eLogWarning, "Clients: Local destination ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " exists"); if (!it->second->IsRunning ()) - { + { it->second->Start (); return it->second; - } + } return nullptr; - } + } auto localDestination = std::make_shared (keys, isPublic, params); std::unique_lock l(m_DestinationsMutex); m_Destinations[keys.GetPublic ()->GetIdentHash ()] = localDestination; localDestination->Start (); return localDestination; } - + std::shared_ptr ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const { auto it = m_Destinations.find (destination); if (it != m_Destinations.end ()) return it->second; return nullptr; - } + } template std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const { return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value)); - } + } template void ClientContext::ReadI2CPOptions (const Section& section, std::map& options) const @@ -378,24 +389,24 @@ namespace client options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND); options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY); options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY); - } + } void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const { - std::string value; - if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNEL_LENGTH, value)) + std::string value; + if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNEL_LENGTH, value)) options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = value; - if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, value)) - options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = value; - if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, value)) + if (i2p::config::GetOption(prefix + I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, value)) + options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = value; + if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, value)) options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = value; - if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, value)) + if (i2p::config::GetOption(prefix + I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, value)) options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value)) options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value)) options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; - } + } void ClientContext::ReadTunnels () { @@ -411,20 +422,20 @@ namespace client } } LogPrint(eLogDebug, "FS: tunnels config file: ", tunConf); - try + try { boost::property_tree::read_ini (tunConf, pt); - } - catch (std::exception& ex) + } + catch (std::exception& ex) { LogPrint (eLogWarning, "Clients: Can't read ", tunConf, ": ", ex.what ()); return; } - + int numClientTunnels = 0, numServerTunnels = 0; for (auto& section: pt) { - std::string name = section.first; + std::string name = section.first; try { std::string type = section.second.get (I2P_TUNNELS_SECTION_TYPE); @@ -440,13 +451,14 @@ namespace client dest = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION); int port = section.second.get (I2P_CLIENT_TUNNEL_PORT); // optional params + bool matchTunnels = section.second.get(I2P_CLIENT_TUNNEL_MATCH_TUNNELS, false); std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, ""); std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); // I2CP - std::map options; - ReadI2CPOptions (section, options); + std::map options; + ReadI2CPOptions (section, options); std::shared_ptr localDestination = nullptr; if (keys.length () > 0) @@ -456,9 +468,15 @@ namespace client { localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); if (!localDestination) - localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options); + { + if(matchTunnels) + localDestination = CreateNewMatchedTunnelDestination(k, dest, &options); + else + localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options); + } } } + if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { // udp client // TODO: hostnames @@ -515,7 +533,7 @@ namespace client || type == I2P_TUNNELS_SECTION_TYPE_HTTP || type == I2P_TUNNELS_SECTION_TYPE_IRC || type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) - { + { // mandatory params std::string host = section.second.get (I2P_SERVER_TUNNEL_HOST); int port = section.second.get (I2P_SERVER_TUNNEL_PORT); @@ -532,15 +550,15 @@ namespace client bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true); // I2CP - std::map options; - ReadI2CPOptions (section, options); + std::map options; + ReadI2CPOptions (section, options); std::shared_ptr localDestination = nullptr; i2p::data::PrivateKeys k; if(!LoadPrivateKeys (k, keys, sigType)) continue; localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); - if (!localDestination) + if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) { @@ -549,7 +567,7 @@ namespace client auto localAddress = boost::asio::ip::address::from_string(address); boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::address::from_string(host), port); I2PUDPServerTunnel * serverTunnel = new I2PUDPServerTunnel(name, localDestination, localAddress, endpoint, port); - if(!isUniqueLocal) + if(!isUniqueLocal) { LogPrint(eLogInfo, "Clients: disabling loopback address mapping"); serverTunnel->SetUniqueLocal(isUniqueLocal); @@ -566,10 +584,10 @@ namespace client } else LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); - + continue; } - + I2PServerTunnel * serverTunnel; if (type == I2P_TUNNELS_SECTION_TYPE_HTTP) serverTunnel = new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort, gzip); @@ -594,7 +612,7 @@ namespace client { comma = accessList.find (',', pos); i2p::data::IdentHash ident; - ident.FromBase32 (accessList.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); + ident.FromBase32 (accessList.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos)); idents.insert (ident); pos = comma + 1; } @@ -602,7 +620,7 @@ namespace client serverTunnel->SetAccessList (idents); } if (m_ServerTunnels.insert (std::make_pair ( - std::make_pair (localDestination->GetIdentHash (), inPort), + std::make_pair (localDestination->GetIdentHash (), inPort), std::unique_ptr(serverTunnel))).second) { serverTunnel->Start (); @@ -610,21 +628,21 @@ namespace client } else LogPrint (eLogError, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists"); - + } else LogPrint (eLogWarning, "Clients: Unknown section type=", type, " of ", name, " in ", tunConf); - + } catch (std::exception& ex) { LogPrint (eLogError, "Clients: Can't read tunnel ", name, " params: ", ex.what ()); } - } + } LogPrint (eLogInfo, "Clients: ", numClientTunnels, " I2P client tunnels created"); LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created"); } - + void ClientContext::ScheduleCleanupUDP() { if (m_CleanupUDPTimer) @@ -644,5 +662,5 @@ namespace client ScheduleCleanupUDP(); } } -} -} +} +} diff --git a/ClientContext.h b/ClientContext.h index 1aa1e7f0..5fade60c 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -34,19 +34,21 @@ namespace client const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination"; const char I2P_CLIENT_TUNNEL_KEYS[] = "keys"; const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; - const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport"; - const char I2P_SERVER_TUNNEL_HOST[] = "host"; - const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride"; + const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport"; + const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels"; + const char I2P_SERVER_TUNNEL_HOST[] = "host"; + const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride"; const char I2P_SERVER_TUNNEL_PORT[] = "port"; const char I2P_SERVER_TUNNEL_KEYS[] = "keys"; const char I2P_SERVER_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; const char I2P_SERVER_TUNNEL_INPORT[] = "inport"; - const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist"; + const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist"; const char I2P_SERVER_TUNNEL_GZIP[] = "gzip"; const char I2P_SERVER_TUNNEL_WEBIRC_PASSWORD[] = "webircpassword"; const char I2P_SERVER_TUNNEL_ADDRESS[] = "address"; const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal"; + class ClientContext { public: @@ -62,10 +64,11 @@ namespace client std::shared_ptr GetSharedLocalDestination () const { return m_SharedLocalDestination; }; std::shared_ptr CreateNewLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1, const std::map * params = nullptr); // transient - std::shared_ptr CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); + std::shared_ptr CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, + const std::map * params = nullptr); + std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); - std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; + std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); AddressBook& GetAddressBook () { return m_AddressBook; }; @@ -81,16 +84,16 @@ namespace client std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const; template void ReadI2CPOptions (const Section& section, std::map& options) const; - void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; + void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; void CleanupUDP(const boost::system::error_code & ecode); void ScheduleCleanupUDP(); - + private: std::mutex m_DestinationsMutex; std::map > m_Destinations; - std::shared_ptr m_SharedLocalDestination; + std::shared_ptr m_SharedLocalDestination; AddressBook m_AddressBook; @@ -99,16 +102,16 @@ namespace client std::map > m_ClientTunnels; // local endpoint->tunnel std::map, std::unique_ptr > m_ServerTunnels; // ->tunnel - std::mutex m_ForwardsMutex; + std::mutex m_ForwardsMutex; std::map > m_ClientForwards; // local endpoint -> udp tunnel std::map, std::unique_ptr > m_ServerForwards; // -> udp tunnel - + SAMBridge * m_SamBridge; BOBCommandChannel * m_BOBCommandChannel; I2CPServer * m_I2CPServer; std::unique_ptr m_CleanupUDPTimer; - + public: // for HTTP const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; }; @@ -119,9 +122,9 @@ namespace client const i2p::proxy::HTTPProxy * GetHttpProxy () const { return m_HttpProxy; } const i2p::proxy::SOCKSProxy * GetSocksProxy () const { return m_SocksProxy; } }; - - extern ClientContext context; -} -} + + extern ClientContext context; +} +} #endif diff --git a/Datagram.h b/Datagram.h index b317d101..0ed31707 100644 --- a/Datagram.h +++ b/Datagram.h @@ -19,7 +19,7 @@ namespace client } namespace datagram { - // milliseconds for max session idle time + // milliseconds for max session idle time const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000; // milliseconds for how long we try sticking to a dead routing path before trying to switch const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 10 * 1000; @@ -33,14 +33,14 @@ namespace datagram const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000; // max 64 messages buffered in send queue for each datagram session const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64; - + class DatagramSession : public std::enable_shared_from_this { public: DatagramSession(i2p::client::ClientDestination * localDestination, const i2p::data::IdentHash & remoteIdent); void Start (); - void Stop (); + void Stop (); /** @brief ack the garlic routing path */ @@ -56,7 +56,7 @@ namespace datagram std::shared_ptr IBGW; std::shared_ptr OBEP; const uint64_t activity; - + Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {} Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) : activity(a) { @@ -77,7 +77,7 @@ namespace datagram void HandleSend(std::shared_ptr msg); std::shared_ptr GetSharedRoutingPath(); - + void HandleLeaseSetUpdated(std::shared_ptr ls); private: @@ -95,16 +95,16 @@ namespace datagram typedef std::shared_ptr DatagramSession_ptr; - const size_t MAX_DATAGRAM_SIZE = 32768; + const size_t MAX_DATAGRAM_SIZE = 32768; class DatagramDestination { typedef std::function Receiver; public: - - DatagramDestination (std::shared_ptr owner); - ~DatagramDestination (); + + DatagramDestination (std::shared_ptr owner); + ~DatagramDestination (); void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); @@ -116,21 +116,21 @@ namespace datagram void ResetReceiver (uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); }; std::shared_ptr GetInfoForRemote(const i2p::data::IdentHash & remote); - + // clean up stale sessions void CleanUp (); private: - + std::shared_ptr ObtainSession(const i2p::data::IdentHash & ident); - + std::shared_ptr CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort); void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len); /** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */ Receiver FindReceiver(uint16_t port); - + private: i2p::client::ClientDestination * m_Owner; i2p::data::IdentityEx m_Identity; @@ -142,9 +142,8 @@ namespace datagram i2p::data::GzipInflator m_Inflator; i2p::data::GzipDeflator m_Deflator; - }; + }; } } #endif - diff --git a/Destination.h b/Destination.h index e077c016..12acf56a 100644 --- a/Destination.h +++ b/Destination.h @@ -27,16 +27,16 @@ namespace client { const uint8_t PROTOCOL_TYPE_STREAMING = 6; const uint8_t PROTOCOL_TYPE_DATAGRAM = 17; - const uint8_t PROTOCOL_TYPE_RAW = 18; + const uint8_t PROTOCOL_TYPE_RAW = 18; const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds const int PUBLISH_VERIFICATION_TIMEOUT = 10; // in seconds after successfull publish - const int PUBLISH_MIN_INTERVAL = 20; // in seconds - const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically + const int PUBLISH_MIN_INTERVAL = 20; // in seconds + const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds - const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes + const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes const unsigned int MAX_NUM_FLOODFILLS_PER_REQUEST = 7; - + // I2CP const char I2CP_PARAM_INBOUND_TUNNEL_LENGTH[] = "inbound.length"; const int DEFAULT_INBOUND_TUNNEL_LENGTH = 3; @@ -56,7 +56,7 @@ namespace client const int DEFAULT_MIN_TUNNEL_LATENCY = 0; const char I2CP_PARAM_MAX_TUNNEL_LATENCY[] = "latency.max"; const int DEFAULT_MAX_TUNNEL_LATENCY = 0; - + typedef std::function stream)> StreamRequestComplete; class LeaseSetDestination: public i2p::garlic::GarlicDestination, @@ -78,24 +78,24 @@ namespace client { for (auto& it: requestComplete) it (ls); requestComplete.clear (); - } - }; - - + } + }; + + public: LeaseSetDestination (bool isPublic, const std::map * params = nullptr); - ~LeaseSetDestination (); + ~LeaseSetDestination (); virtual bool Start (); virtual bool Stop (); bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service& GetService () { return m_Service; }; - std::shared_ptr GetTunnelPool () { return m_Pool; }; + std::shared_ptr GetTunnelPool () { return m_Pool; }; bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; std::shared_ptr FindLeaseSet (const i2p::data::IdentHash& ident); bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); - void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true); + void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true); // implements GarlicDestination std::shared_ptr GetLeaseSet (); @@ -105,7 +105,7 @@ namespace client // override GarlicDestination bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); void ProcessGarlicMessage (std::shared_ptr msg); - void ProcessDeliveryStatusMessage (std::shared_ptr msg); + void ProcessDeliveryStatusMessage (std::shared_ptr msg); void SetLeaseSetUpdated (); protected: @@ -115,10 +115,10 @@ namespace client // I2CP virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; virtual void CreateNewLeaseSet (std::vector > tunnels) = 0; - + private: - - void Run (); + + void Run (); void UpdateLeaseSet (); void Publish (); void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); @@ -126,18 +126,18 @@ namespace client void HandlePublishDelayTimer (const boost::system::error_code& ecode); void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len); - void HandleDeliveryStatusMessage (std::shared_ptr msg); + void HandleDeliveryStatusMessage (std::shared_ptr msg); void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete); - bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); + bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleCleanupTimer (const boost::system::error_code& ecode); - void CleanupRemoteLeaseSets (); - + void CleanupRemoteLeaseSets (); + private: volatile bool m_IsRunning; - std::thread * m_Thread; + std::thread * m_Thread; boost::asio::io_service m_Service; mutable std::mutex m_RemoteLeaseSetsMutex; std::map > m_RemoteLeaseSets; @@ -150,16 +150,16 @@ namespace client uint32_t m_PublishReplyToken; uint64_t m_LastSubmissionTime; // in seconds std::set m_ExcludedFloodfills; // for publishing - - boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, + + boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_PublishDelayTimer, m_CleanupTimer; public: - + // for HTTP only int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); }; const decltype(m_RemoteLeaseSets)& GetLeaseSets () const { return m_RemoteLeaseSets; }; - }; + }; class ClientDestination: public LeaseSetDestination { @@ -171,16 +171,16 @@ namespace client // if cancelled before ready, informs promise with nullptr void Ready(ReadyPromise & p); #endif - + ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params = nullptr); ~ClientDestination (); - - bool Start (); - bool Stop (); - + + virtual bool Start (); + virtual bool Stop (); + const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; - void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; + // streaming std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional std::shared_ptr GetStreamingDestination (int port = 0) const; @@ -191,31 +191,31 @@ namespace client void StopAcceptingStreams (); bool IsAcceptingStreams () const; void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor); - + // datagram i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; i2p::datagram::DatagramDestination * CreateDatagramDestination (); - - // implements LocalDestination + + // implements LocalDestination const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; - std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; + std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; protected: - + void CleanupDestination (); // I2CP void HandleDataMessage (const uint8_t * buf, size_t len); void CreateNewLeaseSet (std::vector > tunnels); - + private: std::shared_ptr GetSharedFromThis () - { return std::static_pointer_cast(shared_from_this ()); } + { return std::static_pointer_cast(shared_from_this ()); } void PersistTemporaryKeys (); #ifdef I2LUA void ScheduleCheckForReady(ReadyPromise * p); void HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p); -#endif +#endif private: i2p::data::PrivateKeys m_Keys; @@ -226,13 +226,13 @@ namespace client i2p::datagram::DatagramDestination * m_DatagramDestination; boost::asio::deadline_timer m_ReadyChecker; - + public: // for HTTP only std::vector > GetAllStreams () const; - }; -} -} + }; +} +} #endif diff --git a/I2PTunnel.h b/I2PTunnel.h index f0580554..dd78d0fe 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -19,9 +19,9 @@ namespace i2p namespace client { const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 65536; - const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds + const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds - // for HTTP tunnels + // for HTTP tunnels const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64 const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64 const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address @@ -33,21 +33,21 @@ namespace client I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr leaseSet, int port = 0); // to I2P I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, - std::shared_ptr stream); // to I2P using simplified API - I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, + std::shared_ptr stream); // to I2P using simplified API + I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, bool quiet = true); // from I2P ~I2PTunnelConnection (); void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0); void Connect (bool isUniqueLocal = true); - + protected: - void Terminate (); + void Terminate (); 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); virtual void Write (const uint8_t * buf, size_t len); // can be overloaded - void HandleWrite (const boost::system::error_code& ecode); + void HandleWrite (const boost::system::error_code& ecode); void StreamReceive (); void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -75,28 +75,28 @@ namespace client protected: - void Write (const uint8_t * buf, size_t len); - - private: + void Write (const uint8_t * buf, size_t len); + + private: std::stringstream m_InHeader, m_OutHeader; bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent; - }; - + }; + class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection { public: - + I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, - std::shared_ptr socket, - const boost::asio::ip::tcp::endpoint& target, const std::string& host); + std::shared_ptr socket, + const boost::asio::ip::tcp::endpoint& target, const std::string& host); protected: void Write (const uint8_t * buf, size_t len); private: - + std::string m_Host; std::stringstream m_InHeader, m_OutHeader; bool m_HeaderSent; @@ -106,21 +106,21 @@ namespace client class I2PTunnelConnectionIRC: public I2PTunnelConnection { public: - + I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, - std::shared_ptr socket, - const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); + std::shared_ptr socket, + const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass); protected: void Write (const uint8_t * buf, size_t len); private: - + std::shared_ptr m_From; std::stringstream m_OutPacket, m_InPacket; bool m_NeedsWebIrc; - std::string m_WebircPass; + std::string m_WebircPass; }; @@ -133,24 +133,24 @@ namespace client public: - I2PClientTunnel (const std::string& name, const std::string& destination, + I2PClientTunnel (const std::string& name, const std::string& destination, const std::string& address, int port, std::shared_ptr localDestination, int destinationPort = 0); ~I2PClientTunnel () {} - + void Start (); void Stop (); - const char* GetName() { return m_Name.c_str (); } - + const char* GetName() { return m_Name.c_str (); } + private: const i2p::data::IdentHash * GetIdentHash (); private: - + std::string m_Name, m_Destination; const i2p::data::IdentHash * m_DestinationIdentHash; - int m_DestinationPort; + int m_DestinationPort; }; @@ -173,7 +173,7 @@ namespace client uint16_t RemotePort; uint8_t m_Buffer[I2P_UDP_MAX_MTU]; - + UDPSession(boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident, @@ -182,7 +182,7 @@ namespace client void Receive(); }; - + /** read only info about a datagram session */ struct DatagramSessionInfo { @@ -205,7 +205,7 @@ namespace client }; typedef std::shared_ptr UDPSessionPtr; - + /** server side udp tunnel, many i2p inbound to 1 ip outbound */ class I2PUDPServerTunnel { @@ -239,7 +239,7 @@ namespace client std::shared_ptr m_LocalDest; }; - class I2PUDPClientTunnel + class I2PUDPClientTunnel { public: I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, @@ -249,7 +249,7 @@ namespace client void Start(); const char * GetName() const { return m_Name.c_str(); } std::vector > GetSessions(); - + bool IsLocalDestination(const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); } std::shared_ptr GetLocalDestination () const { return m_LocalDest; } @@ -275,18 +275,18 @@ namespace client uint16_t RemotePort; bool m_cancel_resolve; }; - + class I2PServerTunnel: public I2PService { public: - I2PServerTunnel (const std::string& name, const std::string& address, int port, - std::shared_ptr localDestination, int inport = 0, bool gzip = true); + I2PServerTunnel (const std::string& name, const std::string& address, int port, + std::shared_ptr localDestination, int inport = 0, bool gzip = true); void Start (); void Stop (); - void SetAccessList (const std::set& accessList); + void SetAccessList (const std::set& accessList); void SetUniqueLocal (bool isUniqueLocal) { m_IsUniqueLocal = isUniqueLocal; } bool IsUniqueLocal () const { return m_IsUniqueLocal; } @@ -296,13 +296,13 @@ namespace client uint16_t GetLocalPort () const { return m_PortDestination->GetLocalPort (); }; const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; } - const char* GetName() { return m_Name.c_str (); } + const char* GetName() { return m_Name.c_str (); } void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); } private: - void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, + void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, std::shared_ptr resolver); void Accept (); @@ -310,11 +310,11 @@ namespace client virtual std::shared_ptr CreateI2PConnection (std::shared_ptr stream); private: - + bool m_IsUniqueLocal; std::string m_Name, m_Address; int m_Port; - boost::asio::ip::tcp::endpoint m_Endpoint; + boost::asio::ip::tcp::endpoint m_Endpoint; std::shared_ptr m_PortDestination; std::set m_AccessList; bool m_IsAccessList; @@ -324,9 +324,9 @@ namespace client { public: - I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, + I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, const std::string& host, - int inport = 0, bool gzip = true); + int inport = 0, bool gzip = true); private: @@ -336,14 +336,14 @@ namespace client std::string m_Host; }; - + class I2PServerTunnelIRC: public I2PServerTunnel { public: - I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, + I2PServerTunnelIRC (const std::string& name, const std::string& address, int port, std::shared_ptr localDestination, const std::string& webircpass, - int inport = 0, bool gzip = true); + int inport = 0, bool gzip = true); private: @@ -355,6 +355,6 @@ namespace client }; } -} +} #endif diff --git a/Makefile.linux b/Makefile.linux index c4d78447..8173b4a5 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -12,7 +12,7 @@ INCFLAGS ?= # detect proper flag for c++11 support by compilers CXXVER := $(shell $(CXX) -dumpversion) ifeq ($(shell expr match $(CXX) 'clang'),5) - NEEDED_CXXFLAGS += -std=c++11 + NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10 NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7 diff --git a/MatchedDestination.cpp b/MatchedDestination.cpp new file mode 100644 index 00000000..674a5f09 --- /dev/null +++ b/MatchedDestination.cpp @@ -0,0 +1,105 @@ +#include "MatchedDestination.h" +#include "Log.h" +#include "ClientContext.h" + + +namespace i2p +{ +namespace client +{ + MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys & keys, const std::string & remoteName, const std::map * params) + : ClientDestination(keys, false, params), + m_RemoteName(remoteName) {} + + void MatchedTunnelDestination::ResolveCurrentLeaseSet() + { + if(i2p::client::context.GetAddressBook().GetIdentHash(m_RemoteName, m_RemoteIdent)) + { + auto ls = FindLeaseSet(m_RemoteIdent); + if(ls) + { + HandleFoundCurrentLeaseSet(ls); + } + else + RequestDestination(m_RemoteIdent, std::bind(&MatchedTunnelDestination::HandleFoundCurrentLeaseSet, this, std::placeholders::_1)); + } + else + LogPrint(eLogWarning, "Destination: failed to resolve ", m_RemoteName); + } + + void MatchedTunnelDestination::HandleFoundCurrentLeaseSet(std::shared_ptr ls) + { + if(ls) + { + LogPrint(eLogDebug, "Destination: resolved remote lease set for ", m_RemoteName); + m_RemoteLeaseSet = ls; + } + else + ResolveCurrentLeaseSet(); + } + + + bool MatchedTunnelDestination::Start() + { + if(ClientDestination::Start()) + { + GetTunnelPool()->SetCustomPeerSelector(this); + ResolveCurrentLeaseSet(); + return true; + } + else + return false; + } + + bool MatchedTunnelDestination::Stop() + { + if(ClientDestination::Stop()) + { + + return true; + } + else + return false; + } + + + bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound) + { + auto pool = GetTunnelPool(); + if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound, std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1))) + return false; + // more here for outbound tunnels + if(!inbound && m_RemoteLeaseSet) + { + if(m_RemoteLeaseSet->IsExpired()) + { + ResolveCurrentLeaseSet(); + } + if(m_RemoteLeaseSet && !m_RemoteLeaseSet->IsExpired()) + { + // remote lease set is good + auto leases = m_RemoteLeaseSet->GetNonExpiredLeases(); + // pick lease + std::shared_ptr obep; + while(!obep && leases.size() > 0) { + auto idx = rand() % leases.size(); + auto lease = leases[idx]; + obep = i2p::data::netdb.FindRouter(lease->tunnelGateway); + leases.erase(leases.begin()+idx); + } + if(obep) { + path.push_back(obep->GetRouterIdentity()); + LogPrint(eLogDebug, "Destination: found OBEP matching IBGW"); + } else + LogPrint(eLogWarning, "Destination: could not find proper IBGW for matched outbound tunnel"); + } + } + return true; + } + + bool MatchedTunnelDestination::OnBuildResult(const i2p::tunnel::Path & path, bool inbound, i2p::tunnel::TunnelBuildResult result) + { + return true; + } +} +} diff --git a/MatchedDestination.h b/MatchedDestination.h new file mode 100644 index 00000000..daf55c2d --- /dev/null +++ b/MatchedDestination.h @@ -0,0 +1,35 @@ +#ifndef MATCHED_DESTINATION_H_ +#define MATCHED_DESTINATION_H_ +#include "Destination.h" +#include + +namespace i2p +{ +namespace client +{ + /** + client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination + */ + class MatchedTunnelDestination : public ClientDestination, public i2p::tunnel::ITunnelPeerSelector + { + public: + MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName, const std::map * params = nullptr); + bool Start(); + bool Stop(); + + bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound); + bool OnBuildResult(const i2p::tunnel::Path & peers, bool inbound, i2p::tunnel::TunnelBuildResult result); + + private: + void ResolveCurrentLeaseSet(); + void HandleFoundCurrentLeaseSet(std::shared_ptr ls); + + private: + std::string m_RemoteName; + i2p::data::IdentHash m_RemoteIdent; + std::shared_ptr m_RemoteLeaseSet; + }; +} +} + +#endif diff --git a/TunnelPool.cpp b/TunnelPool.cpp index dfdfbf58..60f81841 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -18,7 +18,7 @@ namespace i2p { namespace tunnel { - + TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels): m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true), @@ -37,25 +37,25 @@ namespace tunnel if (m_ExplicitPeers) { int size = m_ExplicitPeers->size (); - if (m_NumInboundHops > size) + if (m_NumInboundHops > size) { m_NumInboundHops = size; LogPrint (eLogInfo, "Tunnels: Inbound tunnel length has beed adjusted to ", size, " for explicit peers"); - } - if (m_NumOutboundHops > size) + } + if (m_NumOutboundHops > size) { m_NumOutboundHops = size; LogPrint (eLogInfo, "Tunnels: Outbound tunnel length has beed adjusted to ", size, " for explicit peers"); - } + } m_NumInboundTunnels = 1; m_NumOutboundTunnels = 1; - } + } } void TunnelPool::DetachTunnels () { { - std::unique_lock l(m_InboundTunnelsMutex); + std::unique_lock l(m_InboundTunnelsMutex); for (auto& it: m_InboundTunnels) it->SetTunnelPool (nullptr); m_InboundTunnels.clear (); @@ -67,21 +67,21 @@ namespace tunnel m_OutboundTunnels.clear (); } m_Tests.clear (); - } - + } + void TunnelPool::TunnelCreated (std::shared_ptr createdTunnel) { if (!m_IsActive) return; { -#ifdef WITH_EVENTS +#ifdef WITH_EVENTS EmitTunnelEvent("tunnels.created", createdTunnel); -#endif +#endif std::unique_lock l(m_InboundTunnelsMutex); m_InboundTunnels.insert (createdTunnel); } if (m_LocalDestination) m_LocalDestination->SetLeaseSetUpdated (); - + OnTunnelBuildResult(createdTunnel, eBuildResultOkay); } @@ -89,25 +89,25 @@ namespace tunnel { if (expiredTunnel) { -#ifdef WITH_EVENTS +#ifdef WITH_EVENTS EmitTunnelEvent("tunnels.expired", expiredTunnel); -#endif +#endif expiredTunnel->SetTunnelPool (nullptr); for (auto& it: m_Tests) if (it.second.second == expiredTunnel) it.second.second = nullptr; std::unique_lock l(m_InboundTunnelsMutex); m_InboundTunnels.erase (expiredTunnel); - } - } + } + } void TunnelPool::TunnelCreated (std::shared_ptr createdTunnel) { if (!m_IsActive) return; { -#ifdef WITH_EVENTS +#ifdef WITH_EVENTS EmitTunnelEvent("tunnels.created", createdTunnel); -#endif +#endif std::unique_lock l(m_OutboundTunnelsMutex); m_OutboundTunnels.insert (createdTunnel); } @@ -120,9 +120,9 @@ namespace tunnel { if (expiredTunnel) { -#ifdef WITH_EVENTS +#ifdef WITH_EVENTS EmitTunnelEvent("tunnels.expired", expiredTunnel); -#endif +#endif expiredTunnel->SetTunnelPool (nullptr); for (auto& it: m_Tests) if (it.second.first == expiredTunnel) it.second.first = nullptr; @@ -131,7 +131,7 @@ namespace tunnel m_OutboundTunnels.erase (expiredTunnel); } } - + std::vector > TunnelPool::GetInboundTunnels (int num) const { std::vector > v; @@ -144,8 +144,8 @@ namespace tunnel { v.push_back (it); i++; - } - } + } + } return v; } @@ -153,7 +153,7 @@ namespace tunnel { std::unique_lock l(m_OutboundTunnelsMutex); return GetNextTunnel (m_OutboundTunnels, excluded); - } + } std::shared_ptr TunnelPool::GetNextInboundTunnel (std::shared_ptr excluded) const { @@ -164,11 +164,11 @@ namespace tunnel template typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded) const { - if (tunnels.empty ()) return nullptr; + if (tunnels.empty ()) return nullptr; uint32_t ind = rand () % (tunnels.size ()/2 + 1), i = 0; typename TTunnels::value_type tunnel = nullptr; for (const auto& it: tunnels) - { + { if (it->IsEstablished () && it != excluded) { if(HasLatencyRequirement() && it->LatencyIsKnown() && !it->LatencyFitsRange(m_MinLatency, m_MaxLatency)) { @@ -183,7 +183,7 @@ namespace tunnel if(HasLatencyRequirement() && !tunnel) { ind = rand () % (tunnels.size ()/2 + 1), i = 0; for (const auto& it: tunnels) - { + { if (it->IsEstablished () && it != excluded) { tunnel = it; @@ -199,10 +199,10 @@ namespace tunnel std::shared_ptr TunnelPool::GetNewOutboundTunnel (std::shared_ptr old) const { if (old && old->IsEstablished ()) return old; - std::shared_ptr tunnel; + std::shared_ptr tunnel; if (old) { - std::unique_lock l(m_OutboundTunnelsMutex); + std::unique_lock l(m_OutboundTunnelsMutex); for (const auto& it: m_OutboundTunnels) if (it->IsEstablished () && old->GetEndpointIdentHash () == it->GetEndpointIdentHash ()) { @@ -210,9 +210,9 @@ namespace tunnel break; } } - + if (!tunnel) - tunnel = GetNextOutboundTunnel (); + tunnel = GetNextOutboundTunnel (); return tunnel; } @@ -220,12 +220,12 @@ namespace tunnel { int num = 0; { - std::unique_lock l(m_OutboundTunnelsMutex); + std::unique_lock l(m_OutboundTunnelsMutex); for (const auto& it : m_OutboundTunnels) if (it->IsEstablished ()) num++; } for (int i = num; i < m_NumOutboundTunnels; i++) - CreateOutboundTunnel (); + CreateOutboundTunnel (); num = 0; { @@ -253,20 +253,20 @@ namespace tunnel LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed"); // if test failed again with another tunnel we consider it failed if (it.second.first) - { + { if (it.second.first->GetState () == eTunnelStateTestFailed) - { + { it.second.first->SetState (eTunnelStateFailed); std::unique_lock l(m_OutboundTunnelsMutex); m_OutboundTunnels.erase (it.second.first); } else it.second.first->SetState (eTunnelStateTestFailed); - } + } if (it.second.second) { if (it.second.second->GetState () == eTunnelStateTestFailed) - { + { it.second.second->SetState (eTunnelStateFailed); { std::unique_lock l(m_InboundTunnelsMutex); @@ -274,25 +274,25 @@ namespace tunnel } if (m_LocalDestination) m_LocalDestination->SetLeaseSetUpdated (); - } + } else it.second.second->SetState (eTunnelStateTestFailed); - } + } } - - // new tests + + // new tests auto it1 = m_OutboundTunnels.begin (); auto it2 = m_InboundTunnels.begin (); while (it1 != m_OutboundTunnels.end () && it2 != m_InboundTunnels.end ()) { bool failed = false; if ((*it1)->IsFailed ()) - { + { failed = true; ++it1; } if ((*it2)->IsFailed ()) - { + { failed = true; ++it2; } @@ -307,7 +307,7 @@ namespace tunnel (*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), CreateDeliveryStatusMsg (msgID)); ++it1; ++it2; - } + } } } @@ -317,24 +317,24 @@ namespace tunnel m_LocalDestination->ProcessGarlicMessage (msg); else LogPrint (eLogWarning, "Tunnels: local destination doesn't exist, dropped"); - } - + } + void TunnelPool::ProcessDeliveryStatus (std::shared_ptr msg) { const uint8_t * buf = msg->GetPayload (); uint32_t msgID = bufbe32toh (buf); - buf += 4; + buf += 4; uint64_t timestamp = bufbe64toh (buf); decltype(m_Tests)::mapped_type test; - bool found = false; + bool found = false; { std::unique_lock l(m_TestsMutex); auto it = m_Tests.find (msgID); if (it != m_Tests.end ()) { found = true; - test = it->second; + test = it->second; m_Tests.erase (it); } } @@ -358,35 +358,23 @@ namespace tunnel m_LocalDestination->ProcessDeliveryStatusMessage (msg); else LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped"); - } + } } std::shared_ptr TunnelPool::SelectNextHop (std::shared_ptr prevHop) const { bool isExploratory = (i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ()); - auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop): + auto hop = isExploratory ? i2p::data::netdb.GetRandomRouter (prevHop): i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop); if (!hop || hop->GetProfile ()->IsBad ()) hop = i2p::data::netdb.GetRandomRouter (prevHop); - return hop; - } + return hop; + } - bool TunnelPool::SelectPeers (std::vector >& peers, bool isInbound) + bool StandardSelectPeers(Path & peers, int numHops, bool inbound, SelectHopFunc nextHop) { - int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; - // peers is empty - if (numHops <= 0) return true; - // custom peer selector in use ? - { - std::lock_guard lock(m_CustomPeerSelectorMutex); - if (m_CustomPeerSelector) - return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound); - } - // explicit peers in use - if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound); - - auto prevHop = i2p::context.GetSharedRouterInfo (); + auto prevHop = i2p::context.GetSharedRouterInfo (); if(i2p::transport::transports.RoutesRestricted()) { /** if routes are restricted prepend trusted first hop */ @@ -399,36 +387,52 @@ namespace tunnel { auto r = i2p::transport::transports.GetRandomPeer (); if (r && !r->GetProfile ()->IsBad ()) - { - prevHop = r; - peers.push_back (r->GetRouterIdentity ()); - numHops--; - } + { + prevHop = r; + peers.push_back (r->GetRouterIdentity ()); + numHops--; + } } - + for(int i = 0; i < numHops; i++ ) { - auto hop = SelectNextHop (prevHop); + auto hop = nextHop (prevHop); if (!hop) { LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); return false; - } + } prevHop = hop; peers.push_back (hop->GetRouterIdentity ()); } return true; - } - + } + + bool TunnelPool::SelectPeers (std::vector >& peers, bool isInbound) + { + int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; + // peers is empty + if (numHops <= 0) return true; + // custom peer selector in use ? + { + std::lock_guard lock(m_CustomPeerSelectorMutex); + if (m_CustomPeerSelector) + return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound); + } + // explicit peers in use + if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound); + return StandardSelectPeers(peers, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1)); + } + bool TunnelPool::SelectExplicitPeers (std::vector >& peers, bool isInbound) { int size = m_ExplicitPeers->size (); std::vector peerIndicies; for (int i = 0; i < size; i++) peerIndicies.push_back(i); std::random_shuffle (peerIndicies.begin(), peerIndicies.end()); - - int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; - for (int i = 0; i < numHops; i++) + + int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; + for (int i = 0; i < numHops; i++) { auto& ident = (*m_ExplicitPeers)[peerIndicies[i]]; auto r = i2p::data::netdb.FindRouter (ident); @@ -443,7 +447,7 @@ namespace tunnel } return true; } - + void TunnelPool::CreateInboundTunnel () { auto outboundTunnel = GetNextOutboundTunnel (); @@ -455,15 +459,15 @@ namespace tunnel { std::shared_ptr config; if (m_NumInboundHops > 0) - { - std::reverse (peers.begin (), peers.end ()); + { + std::reverse (peers.begin (), peers.end ()); config = std::make_shared (peers); - } + } auto tunnel = tunnels.CreateInboundTunnel (config, outboundTunnel); tunnel->SetTunnelPool (shared_from_this ()); if (tunnel->IsEstablished ()) // zero hops TunnelCreated (tunnel); - } + } else LogPrint (eLogError, "Tunnels: Can't create inbound tunnel, no peers available"); } @@ -480,41 +484,41 @@ namespace tunnel newTunnel->SetTunnelPool (shared_from_this()); if (newTunnel->IsEstablished ()) // zero hops TunnelCreated (newTunnel); - } - + } + void TunnelPool::CreateOutboundTunnel () { auto inboundTunnel = GetNextInboundTunnel (); if (!inboundTunnel) inboundTunnel = tunnels.GetNextInboundTunnel (); if (inboundTunnel) - { + { LogPrint (eLogDebug, "Tunnels: Creating destination outbound tunnel..."); std::vector > peers; if (SelectPeers (peers, false)) - { + { std::shared_ptr config; - if (m_NumOutboundHops > 0) + if (m_NumOutboundHops > 0) config = std::make_shared(peers, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()); auto tunnel = tunnels.CreateOutboundTunnel (config); tunnel->SetTunnelPool (shared_from_this ()); if (tunnel->IsEstablished ()) // zero hops TunnelCreated (tunnel); - } + } else LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no peers available"); - } + } else LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no inbound tunnels found"); - } - + } + void TunnelPool::RecreateOutboundTunnel (std::shared_ptr tunnel) { auto inboundTunnel = GetNextInboundTunnel (); if (!inboundTunnel) inboundTunnel = tunnels.GetNextInboundTunnel (); if (inboundTunnel) - { + { LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel..."); std::shared_ptr config; if (m_NumOutboundHops > 0) @@ -523,10 +527,10 @@ namespace tunnel newTunnel->SetTunnelPool (shared_from_this ()); if (newTunnel->IsEstablished ()) // zero hops TunnelCreated (newTunnel); - } + } else LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found"); - } + } void TunnelPool::CreatePairedInboundTunnel (std::shared_ptr outboundTunnel) { @@ -535,7 +539,7 @@ namespace tunnel tunnel->SetTunnelPool (shared_from_this ()); } - void TunnelPool::SetCustomPeerSelector(TunnelPeerSelector selector) + void TunnelPool::SetCustomPeerSelector(ITunnelPeerSelector * selector) { std::lock_guard lock(m_CustomPeerSelectorMutex); m_CustomPeerSelector = selector; @@ -567,7 +571,7 @@ namespace tunnel } return tun; } - + std::shared_ptr TunnelPool::GetLowestLatencyOutboundTunnel(std::shared_ptr exclude) const { std::shared_ptr tun = nullptr; diff --git a/TunnelPool.h b/TunnelPool.h index 9e2a3e24..d7e47876 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -30,25 +30,29 @@ namespace tunnel eBuildResultTimeout // tunnel build timed out }; + typedef std::shared_ptr Peer; + typedef std::vector Path; + /** interface for custom tunnel peer selection algorithm */ struct ITunnelPeerSelector { - typedef std::shared_ptr Peer; - typedef std::vector TunnelPath; - - virtual bool SelectPeers(TunnelPath & peers, int hops, bool isInbound) = 0; - virtual bool OnBuildResult(TunnelPath & peers, bool isInbound, TunnelBuildResult result) = 0; + virtual ~ITunnelPeerSelector() {}; + virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0; + virtual bool OnBuildResult(const Path & peers, bool isInbound, TunnelBuildResult result) = 0; }; - typedef std::shared_ptr TunnelPeerSelector; - + + typedef std::function(std::shared_ptr)> SelectHopFunc; + // standard peer selection algorithm + bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop); + class TunnelPool: public std::enable_shared_from_this // per local destination { public: TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels); ~TunnelPool (); - + std::shared_ptr GetLocalDestination () const { return m_LocalDestination; }; void SetLocalDestination (std::shared_ptr destination) { m_LocalDestination = destination; }; void SetExplicitPeers (std::shared_ptr > explicitPeers); @@ -62,7 +66,7 @@ namespace tunnel void RecreateOutboundTunnel (std::shared_ptr tunnel); std::vector > GetInboundTunnels (int num) const; std::shared_ptr GetNextOutboundTunnel (std::shared_ptr excluded = nullptr) const; - std::shared_ptr GetNextInboundTunnel (std::shared_ptr excluded = nullptr) const; + std::shared_ptr GetNextInboundTunnel (std::shared_ptr excluded = nullptr) const; std::shared_ptr GetNewOutboundTunnel (std::shared_ptr old) const; void TestTunnels (); void ProcessGarlicMessage (std::shared_ptr msg); @@ -75,7 +79,7 @@ namespace tunnel int GetNumInboundTunnels () const { return m_NumInboundTunnels; }; int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; }; - void SetCustomPeerSelector(TunnelPeerSelector selector); + void SetCustomPeerSelector(ITunnelPeerSelector * selector); void UnsetCustomPeerSelector(); bool HasCustomPeerSelector(); @@ -90,23 +94,25 @@ namespace tunnel std::shared_ptr GetLowestLatencyOutboundTunnel(std::shared_ptr exclude=nullptr) const; void OnTunnelBuildResult(std::shared_ptr tunnel, TunnelBuildResult result); - + + // for overriding tunnel peer selection + std::shared_ptr SelectNextHop (std::shared_ptr prevHop) const; + private: - - void CreateInboundTunnel (); + + void CreateInboundTunnel (); void CreateOutboundTunnel (); void CreatePairedInboundTunnel (std::shared_ptr outboundTunnel); template typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, typename TTunnels::value_type excluded) const; - std::shared_ptr SelectNextHop (std::shared_ptr prevHop) const; bool SelectPeers (std::vector >& hops, bool isInbound); - bool SelectExplicitPeers (std::vector >& hops, bool isInbound); + bool SelectExplicitPeers (std::vector >& hops, bool isInbound); private: std::shared_ptr m_LocalDestination; int m_NumInboundHops, m_NumOutboundHops, m_NumInboundTunnels, m_NumOutboundTunnels; - std::shared_ptr > m_ExplicitPeers; + std::shared_ptr > m_ExplicitPeers; mutable std::mutex m_InboundTunnelsMutex; std::set, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first mutable std::mutex m_OutboundTunnelsMutex; @@ -115,20 +121,19 @@ namespace tunnel std::map, std::shared_ptr > > m_Tests; bool m_IsActive; std::mutex m_CustomPeerSelectorMutex; - TunnelPeerSelector m_CustomPeerSelector; + ITunnelPeerSelector * m_CustomPeerSelector; uint64_t m_MinLatency=0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms uint64_t m_MaxLatency=0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms - + public: // for HTTP only const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; }; const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }; - }; + }; } } #endif - diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 32aff387..0acf54ca 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -37,7 +37,7 @@ set (LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/FS.cpp" "${CMAKE_SOURCE_DIR}/Log.cpp" "${CMAKE_SOURCE_DIR}/NTCPSession.cpp" - "${CMAKE_SOURCE_DIR}/NetDbRequests.cpp" + "${CMAKE_SOURCE_DIR}/NetDbRequests.cpp" "${CMAKE_SOURCE_DIR}/NetDb.cpp" "${CMAKE_SOURCE_DIR}/Profiling.cpp" "${CMAKE_SOURCE_DIR}/Reseed.cpp" @@ -47,7 +47,7 @@ set (LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/SSUData.cpp" "${CMAKE_SOURCE_DIR}/SSUSession.cpp" "${CMAKE_SOURCE_DIR}/Streaming.cpp" - "${CMAKE_SOURCE_DIR}/Destination.cpp" + "${CMAKE_SOURCE_DIR}/Destination.cpp" "${CMAKE_SOURCE_DIR}/TransitTunnel.cpp" "${CMAKE_SOURCE_DIR}/Tunnel.cpp" "${CMAKE_SOURCE_DIR}/TunnelGateway.cpp" @@ -59,16 +59,16 @@ set (LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/Datagram.cpp" "${CMAKE_SOURCE_DIR}/Family.cpp" "${CMAKE_SOURCE_DIR}/Signature.cpp" - "${CMAKE_SOURCE_DIR}/Timestamp.cpp" + "${CMAKE_SOURCE_DIR}/Timestamp.cpp" "${CMAKE_SOURCE_DIR}/api.cpp" "${CMAKE_SOURCE_DIR}/Event.cpp" - "${CMAKE_SOURCE_DIR}/Gost.cpp" + "${CMAKE_SOURCE_DIR}/Gost.cpp" ) if (WITH_WEBSOCKETS) add_definitions(-DWITH_EVENTS) find_package(websocketpp REQUIRED) -endif () +endif () if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS) list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp") @@ -90,8 +90,9 @@ install(TARGETS libi2pd set (CLIENT_SRC "${CMAKE_SOURCE_DIR}/AddressBook.cpp" - "${CMAKE_SOURCE_DIR}/BOB.cpp" + "${CMAKE_SOURCE_DIR}/BOB.cpp" "${CMAKE_SOURCE_DIR}/ClientContext.cpp" + "${CMAKE_SOURCE_DIR}/MatchedDestination.cpp" "${CMAKE_SOURCE_DIR}/I2PTunnel.cpp" "${CMAKE_SOURCE_DIR}/I2PService.cpp" "${CMAKE_SOURCE_DIR}/SAM.cpp" @@ -357,7 +358,7 @@ include_directories( SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_ # warn if for meshnet if (WITH_MESHNET) message(STATUS "Building for testnet") - message(WARNING "This build will NOT work on mainline i2p") + message(WARNING "This build will NOT work on mainline i2p") endif() diff --git a/filelist.mk b/filelist.mk index 9149eefa..5fb5ea1d 100644 --- a/filelist.mk +++ b/filelist.mk @@ -8,10 +8,9 @@ LIB_SRC = \ Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Event.cpp Gost.cpp LIB_CLIENT_SRC = \ - AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \ + AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp MatchedDestination.cpp \ SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp WebSocks.cpp # also: Daemon{Linux,Win32}.cpp will be added later DAEMON_SRC = \ HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp - From 89dfe2b763cb7596f78014fae9f640b6ce10ad83 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 8 Apr 2017 14:15:08 -0400 Subject: [PATCH 03/14] delay request --- MatchedDestination.cpp | 12 ++++++++++-- MatchedDestination.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/MatchedDestination.cpp b/MatchedDestination.cpp index 674a5f09..68f3759e 100644 --- a/MatchedDestination.cpp +++ b/MatchedDestination.cpp @@ -11,6 +11,7 @@ namespace client : ClientDestination(keys, false, params), m_RemoteName(remoteName) {} + void MatchedTunnelDestination::ResolveCurrentLeaseSet() { if(i2p::client::context.GetAddressBook().GetIdentHash(m_RemoteName, m_RemoteIdent)) @@ -35,7 +36,12 @@ namespace client m_RemoteLeaseSet = ls; } else - ResolveCurrentLeaseSet(); + { + m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1)); + m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) { + if(!ec) ResolveCurrentLeaseSet(); + }); + } } @@ -43,6 +49,7 @@ namespace client { if(ClientDestination::Start()) { + m_ResolveTimer = std::make_shared(GetService()); GetTunnelPool()->SetCustomPeerSelector(this); ResolveCurrentLeaseSet(); return true; @@ -55,7 +62,8 @@ namespace client { if(ClientDestination::Stop()) { - + if(m_ResolveTimer) + m_ResolveTimer->cancel(); return true; } else diff --git a/MatchedDestination.h b/MatchedDestination.h index daf55c2d..33c1e234 100644 --- a/MatchedDestination.h +++ b/MatchedDestination.h @@ -28,6 +28,7 @@ namespace client std::string m_RemoteName; i2p::data::IdentHash m_RemoteIdent; std::shared_ptr m_RemoteLeaseSet; + std::shared_ptr m_ResolveTimer; }; } } From 2fe71782a716977094a4312f50029fe46822c37c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 8 Apr 2017 15:14:47 -0400 Subject: [PATCH 04/14] tabify --- ClientContext.h | 2 +- MatchedDestination.h | 40 ++++++++++++++++++++-------------------- TunnelPool.h | 16 ++++++++-------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ClientContext.h b/ClientContext.h index 5fade60c..672770df 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -35,7 +35,7 @@ namespace client const char I2P_CLIENT_TUNNEL_KEYS[] = "keys"; const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport"; - const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels"; + const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels"; const char I2P_SERVER_TUNNEL_HOST[] = "host"; const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride"; const char I2P_SERVER_TUNNEL_PORT[] = "port"; diff --git a/MatchedDestination.h b/MatchedDestination.h index 33c1e234..bbeeb503 100644 --- a/MatchedDestination.h +++ b/MatchedDestination.h @@ -7,29 +7,29 @@ namespace i2p { namespace client { - /** - client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination - */ - class MatchedTunnelDestination : public ClientDestination, public i2p::tunnel::ITunnelPeerSelector - { - public: - MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName, const std::map * params = nullptr); - bool Start(); - bool Stop(); + /** + client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination + */ + class MatchedTunnelDestination : public ClientDestination, public i2p::tunnel::ITunnelPeerSelector + { + public: + MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName, const std::map * params = nullptr); + bool Start(); + bool Stop(); - bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound); - bool OnBuildResult(const i2p::tunnel::Path & peers, bool inbound, i2p::tunnel::TunnelBuildResult result); + bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound); + bool OnBuildResult(const i2p::tunnel::Path & peers, bool inbound, i2p::tunnel::TunnelBuildResult result); - private: - void ResolveCurrentLeaseSet(); - void HandleFoundCurrentLeaseSet(std::shared_ptr ls); + private: + void ResolveCurrentLeaseSet(); + void HandleFoundCurrentLeaseSet(std::shared_ptr ls); - private: - std::string m_RemoteName; - i2p::data::IdentHash m_RemoteIdent; - std::shared_ptr m_RemoteLeaseSet; - std::shared_ptr m_ResolveTimer; - }; + private: + std::string m_RemoteName; + i2p::data::IdentHash m_RemoteIdent; + std::shared_ptr m_RemoteLeaseSet; + std::shared_ptr m_ResolveTimer; + }; } } diff --git a/TunnelPool.h b/TunnelPool.h index d7e47876..07c3024e 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -30,21 +30,21 @@ namespace tunnel eBuildResultTimeout // tunnel build timed out }; - typedef std::shared_ptr Peer; - typedef std::vector Path; + typedef std::shared_ptr Peer; + typedef std::vector Path; /** interface for custom tunnel peer selection algorithm */ struct ITunnelPeerSelector { - virtual ~ITunnelPeerSelector() {}; + virtual ~ITunnelPeerSelector() {}; virtual bool SelectPeers(Path & peers, int hops, bool isInbound) = 0; virtual bool OnBuildResult(const Path & peers, bool isInbound, TunnelBuildResult result) = 0; }; - typedef std::function(std::shared_ptr)> SelectHopFunc; - // standard peer selection algorithm - bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop); + typedef std::function(std::shared_ptr)> SelectHopFunc; + // standard peer selection algorithm + bool StandardSelectPeers(Path & path, int hops, bool inbound, SelectHopFunc nextHop); class TunnelPool: public std::enable_shared_from_this // per local destination { @@ -95,8 +95,8 @@ namespace tunnel void OnTunnelBuildResult(std::shared_ptr tunnel, TunnelBuildResult result); - // for overriding tunnel peer selection - std::shared_ptr SelectNextHop (std::shared_ptr prevHop) const; + // for overriding tunnel peer selection + std::shared_ptr SelectNextHop (std::shared_ptr prevHop) const; private: From fdf4b3878f4f7f6139913c78a6719472f8b97733 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 8 Apr 2017 15:15:59 -0400 Subject: [PATCH 05/14] tabify --- TunnelPool.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 60f81841..a59b796e 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -387,11 +387,11 @@ namespace tunnel { auto r = i2p::transport::transports.GetRandomPeer (); if (r && !r->GetProfile ()->IsBad ()) - { - prevHop = r; - peers.push_back (r->GetRouterIdentity ()); - numHops--; - } + { + prevHop = r; + peers.push_back (r->GetRouterIdentity ()); + numHops--; + } } for(int i = 0; i < numHops; i++ ) From 3acb0aac989a5454176db575728ccbc3e8088e04 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 8 Apr 2017 15:16:51 -0400 Subject: [PATCH 06/14] tabify --- ClientContext.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ClientContext.h b/ClientContext.h index 672770df..50ea4755 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -65,8 +65,8 @@ namespace client std::shared_ptr CreateNewLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1, const std::map * params = nullptr); // transient std::shared_ptr CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); - std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params = nullptr); + const std::map * params = nullptr); + std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); From 4f1dfe2ef761ca36019edf7a9e468d1ca10269cc Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 8 Apr 2017 17:21:56 -0400 Subject: [PATCH 07/14] fixed android build --- android/jni/Android.mk | 3 ++- qt/i2pd_qt/i2pd_qt.pro | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 46e00896..ed1ed16a 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -61,7 +61,8 @@ LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \ ../../Event.cpp \ ../../Gost.cpp \ ../../WebSocks.cpp \ -../../BloomFilter.cpp \ + ../../BloomFilter.cpp \ + ../../MatchedDestination.cpp \ ../../util.cpp \ ../../i2pd.cpp ../../UPnP.cpp diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index dd3987d9..a55a01da 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -36,7 +36,8 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../SSUData.cpp ../../SSUSession.cpp ../../Streaming.cpp ../../TransitTunnel.cpp \ ../../Transports.cpp ../../Tunnel.cpp ../../TunnelEndpoint.cpp ../../TunnelGateway.cpp \ ../../TunnelPool.cpp ../../UPnP.cpp ../../Gzip.cpp ../../Timestamp.cpp ../../util.cpp \ - ../../Event.cpp ../../BloomFiler.cpp ../../Gost.cpp ../../i2pd.cpp + ../../Event.cpp ../../BloomFiler.cpp ../../Gost.cpp ../../MatchedDestination.cpp \ + ../../i2pd.cpp HEADERS += DaemonQT.h mainwindow.h \ ../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \ @@ -51,7 +52,7 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../TransportSession.h ../../Tunnel.h ../../TunnelBase.h ../../TunnelConfig.h \ ../../TunnelEndpoint.h ../../TunnelGateway.h ../../TunnelPool.h ../../UPnP.h \ ../../util.h ../../version.h ../../Gzip.h ../../Tag.h \ - ../../BloomFiler.h ../../Event.h ../../Gost.h + ../../BloomFiler.h ../../Event.h ../../Gost.h ../../MatchedDestination.h FORMS += mainwindow.ui From d91c7e5e79535b6638f77590a1b3de344e2427ec Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 9 Apr 2017 08:52:42 -0400 Subject: [PATCH 08/14] fix datagram bugs --- Datagram.cpp | 19 ++++++++++++++++--- Datagram.h | 2 +- LeaseSet.h | 3 ++- MatchedDestination.cpp | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index c501edf2..2af26771 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -255,9 +255,11 @@ namespace datagram } if(m_CurrentRemoteLease && m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { // bad lease, switch to next one + if(m_RemoteLeaseSet && m_RemoteLeaseSet->IsExpired()) + m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); if(m_RemoteLeaseSet) { auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding([&](const i2p::data::Lease& l) -> bool { - return l.tunnelGateway == m_CurrentRemoteLease->tunnelGateway; + return l.tunnelID == m_CurrentRemoteLease->tunnelID; }); auto sz = ls.size(); if (sz) { @@ -278,7 +280,7 @@ namespace datagram m_CurrentOutboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(m_CurrentOutboundTunnel); } // switch lease if bad - if(m_CurrentRemoteLease == nullptr || m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { + if(m_CurrentRemoteLease && m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { if(!m_RemoteLeaseSet) { m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); } @@ -299,6 +301,17 @@ namespace datagram LogPrint(eLogWarning, "DatagramSession: no remote lease set found for ", m_RemoteIdent.ToBase32()); return nullptr; } + } else if (!m_CurrentRemoteLease) { + if(!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); + if (m_RemoteLeaseSet) + { + auto ls = m_RemoteLeaseSet->GetNonExpiredLeases(); + auto sz = ls.size(); + if (sz) { + auto idx = rand() % sz; + m_CurrentRemoteLease = ls[idx]; + } + } } path->outboundTunnel = m_CurrentOutboundTunnel; path->remoteLease = m_CurrentRemoteLease; @@ -346,7 +359,7 @@ namespace datagram void DatagramSession::ScheduleFlushSendQueue() { - boost::posix_time::milliseconds dlt(100); + boost::posix_time::milliseconds dlt(10); m_SendQueueTimer.expires_from_now(dlt); auto self = shared_from_this(); m_SendQueueTimer.async_wait([self](const boost::system::error_code & ec) { if(ec) return; self->FlushSendQueue(); }); diff --git a/Datagram.h b/Datagram.h index 0ed31707..b72d3840 100644 --- a/Datagram.h +++ b/Datagram.h @@ -26,7 +26,7 @@ namespace datagram // milliseconds interval a routing path is used before switching const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 20 * 60 * 1000; // milliseconds before lease expire should we try switching leases - const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW = 10 * 1000; + const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW = 30 * 1000; // milliseconds fudge factor for leases handover const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; // milliseconds minimum time between path switches diff --git a/LeaseSet.h b/LeaseSet.h index 95d8bf90..3499884a 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -30,7 +30,8 @@ namespace data bool ExpiresWithin( const uint64_t t, const uint64_t fudge = 1000 ) const { auto expire = i2p::util::GetMillisecondsSinceEpoch (); if(fudge) expire += rand() % fudge; - return endDate - expire >= t; + if (endDate < expire) return true; + return (endDate - expire) < t; } }; diff --git a/MatchedDestination.cpp b/MatchedDestination.cpp index 68f3759e..85ab1530 100644 --- a/MatchedDestination.cpp +++ b/MatchedDestination.cpp @@ -52,7 +52,7 @@ namespace client m_ResolveTimer = std::make_shared(GetService()); GetTunnelPool()->SetCustomPeerSelector(this); ResolveCurrentLeaseSet(); - return true; + return true; } else return false; From ed67ce7f33af09bf29c9ea8371cfc4a0e10e3996 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 9 Apr 2017 08:53:47 -0400 Subject: [PATCH 09/14] tabifty --- MatchedDestination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatchedDestination.cpp b/MatchedDestination.cpp index 85ab1530..68f3759e 100644 --- a/MatchedDestination.cpp +++ b/MatchedDestination.cpp @@ -52,7 +52,7 @@ namespace client m_ResolveTimer = std::make_shared(GetService()); GetTunnelPool()->SetCustomPeerSelector(this); ResolveCurrentLeaseSet(); - return true; + return true; } else return false; From 7a67670e1a128bb33dec465cd8d5faefc7aedd99 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 11 Apr 2017 14:36:28 -0400 Subject: [PATCH 10/14] Fixed #846. httpproxy.addresshelper config parameter added --- Config.cpp | 1 + HTTPProxy.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Config.cpp b/Config.cpp index 7dada817..64b7a792 100644 --- a/Config.cpp +++ b/Config.cpp @@ -94,6 +94,7 @@ namespace config { ("httpproxy.latency.min", value()->default_value("0"), "HTTP proxy min latency for tunnels") ("httpproxy.latency.max", value()->default_value("0"), "HTTP proxy max latency for tunnels") ("httpproxy.outproxy", value()->default_value(""), "HTTP proxy upstream out proxy url") + ("httpproxy.addresshelper", value()->default_value(true), "Enable or disable addresshelper") ; options_description socksproxy("SOCKS Proxy options"); diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 5abd6112..55bd60fe 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -237,7 +237,15 @@ namespace proxy { LogPrint(eLogDebug, "HTTPProxy: requested: ", m_ClientRequest.uri); m_RequestURL.parse(m_ClientRequest.uri); - if (ExtractAddressHelper(m_RequestURL, b64)) { + if (ExtractAddressHelper(m_RequestURL, b64)) + { + bool addresshelper; i2p::config::GetOption("httpproxy.addresshelper", addresshelper); + if (!addresshelper) + { + LogPrint(eLogWarning, "HTTPProxy: addresshelper disabled"); + GenericProxyError("Invalid request", "adddresshelper is not supported"); + return true; + } i2p::client::context.GetAddressBook ().InsertAddress (m_RequestURL.host, b64); LogPrint (eLogInfo, "HTTPProxy: added b64 from addresshelper for ", m_RequestURL.host); std::string full_url = m_RequestURL.to_string(); From bd6ce7d4dabacd5f9dd5bee524c7042979d75181 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Apr 2017 10:19:26 -0400 Subject: [PATCH 11/14] reduced memory usage --- I2NPProtocol.h | 1 + TunnelEndpoint.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/I2NPProtocol.h b/I2NPProtocol.h index 76871114..2f8aac7b 100644 --- a/I2NPProtocol.h +++ b/I2NPProtocol.h @@ -209,6 +209,7 @@ namespace tunnel std::shared_ptr NewI2NPMessage (); std::shared_ptr NewI2NPShortMessage (); + std::shared_ptr NewI2NPTunnelMessage (); std::shared_ptr NewI2NPMessage (size_t len); std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index b4ddc109..dde7d0a6 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -99,7 +99,7 @@ namespace tunnel if (fragment + size < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) { // this is not last message. we have to copy it - m.data = NewI2NPShortMessage (); + m.data = NewI2NPTunnelMessage (); m.data->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header m.data->len += TUNNEL_GATEWAY_HEADER_SIZE; *(m.data) = *msg; @@ -154,7 +154,7 @@ namespace tunnel { if (msg.data->len + size > msg.data->maxLen) { - LogPrint (eLogWarning, "TunnelMessage: I2NP message size ", msg.data->maxLen, " is not enough"); + // LogPrint (eLogWarning, "TunnelMessage: I2NP message size ", msg.data->maxLen, " is not enough"); auto newMsg = NewI2NPMessage (); *newMsg = *(msg.data); msg.data = newMsg; From dd79348b356a2e74cceac3b2d3563909f4ba8058 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Apr 2017 22:08:43 -0400 Subject: [PATCH 12/14] delete used tag before update --- Garlic.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index 416b8f68..295fdd8a 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -437,17 +437,18 @@ namespace garlic if (it != m_Tags.end ()) { // tag found. Use AES + auto decryption = it->second; + m_Tags.erase (it); // tag might be used only once if (length >= 32) { uint8_t iv[32]; // IV is first 16 bytes SHA256(buf, 32, iv); - it->second->SetIV (iv); - it->second->Decrypt (buf + 32, length - 32, buf + 32); - HandleAESBlock (buf + 32, length - 32, it->second, msg->from); + decryption->SetIV (iv); + decryption->Decrypt (buf + 32, length - 32, buf + 32); + HandleAESBlock (buf + 32, length - 32, decryption, msg->from); } else LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes"); - m_Tags.erase (it); // tag might be used only once } else { From b2b320174b6969ccd9065f6aabb6743259978c27 Mon Sep 17 00:00:00 2001 From: v2e Date: Wed, 19 Apr 2017 11:36:19 +0300 Subject: [PATCH 13/14] kbps -- KBps in Config.cpp --- Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.cpp b/Config.cpp index 64b7a792..c2d35340 100644 --- a/Config.cpp +++ b/Config.cpp @@ -53,7 +53,7 @@ namespace config { ("service", value()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'") ("notransit", value()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup") ("floodfill", value()->zero_tokens()->default_value(false), "Router will be floodfill") - ("bandwidth", value()->default_value(""), "Bandwidth limit: integer in kbps or letters: L (32), O (256), P (2048), X (>9000)") + ("bandwidth", value()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)") ("ntcp", value()->zero_tokens()->default_value(true), "Enable NTCP transport") ("ssu", value()->zero_tokens()->default_value(true), "Enable SSU transport") #ifdef _WIN32 From 5550eabac1e0d78547b3643b7b8599b125a34ace Mon Sep 17 00:00:00 2001 From: v2e Date: Wed, 19 Apr 2017 11:39:01 +0300 Subject: [PATCH 14/14] kbs -- KBs in i2pd.conf --- contrib/i2pd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 0cdd0de8..c852e0c9 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -64,7 +64,7 @@ ipv6 = false # nat = true ## Bandwidth configuration -## L limit bandwidth to 32Kbs/sec, O - to 256Kbs/sec, P - to 2048Kbs/sec, +## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec, ## X - unlimited ## Default is X for floodfill, L for regular node # bandwidth = L