From c908beade25cf53ae9ace75978e8f0a3d0a84814 Mon Sep 17 00:00:00 2001 From: /dev/null Date: Thu, 21 Jul 2016 17:57:43 -0600 Subject: [PATCH 001/141] Added client tunnel reload on SIGHUP for Linux --- ClientContext.cpp | 8 +++++++- DaemonLinux.cpp | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 2bc13969..788e6a46 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -202,7 +202,13 @@ namespace client void ClientContext::ReloadConfig () { - ReadTunnels (); // TODO: it reads new tunnels only, should be implemented better + /* + std::string config; i2p::config::GetOption("conf", config); + i2p::config::ParseConfig(config); + */ + //I don't think we can just reload the main config without making a mess of things, so holding off for now. + Stop(); + Start(); } void ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType) diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 118fc5f5..22d7dec8 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -13,14 +13,16 @@ #include "FS.h" #include "Log.h" #include "RouterContext.h" +#include "ClientContext.h" void handle_signal(int sig) { switch (sig) { case SIGHUP: - LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening log..."); + LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening logs and tunnel configuration..."); i2p::log::Logger().Reopen (); + i2p::client::context.ReloadConfig(); break; case SIGINT: if (i2p::context.AcceptsTunnels () && !Daemon.gracefullShutdownInterval) From eaac21cda10019d888325190c6f17e00217b2732 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 22 Jul 2016 09:56:17 -0400 Subject: [PATCH 002/141] * check router info addresses for nullptr * Request LS before expiration for smoother handover --- Destination.cpp | 27 +++++++++++++++++++++++++-- Destination.h | 1 + LeaseSet.cpp | 9 ++++++++- LeaseSet.h | 1 + NTCPSession.cpp | 1 + Transports.cpp | 1 + 6 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 2df14a9f..d115f1fa 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -171,11 +171,29 @@ namespace client std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { + std::lock_guard lock(m_RemoteLeaseSetsMutex); auto it = m_RemoteLeaseSets.find (ident); if (it != m_RemoteLeaseSets.end ()) - { + { if (!it->second->IsExpired ()) + { + if (it->second->ExpiresSoon()) + { + LogPrint(eLogDebug, "Destination: Lease Set expires soon, updating before expire"); + // update now before expiration for smooth handover + RequestDestination(ident, [this, ident] (std::shared_ptr ls) { + if(ls && !ls->IsExpired()) + { + ls->PopulateLeases(); + { + std::lock_guard _lock(m_RemoteLeaseSetsMutex); + m_RemoteLeaseSets[ident] = ls; + } + } + }); + } return it->second; + } else LogPrint (eLogWarning, "Destination: remote LeaseSet expired"); } @@ -185,7 +203,10 @@ namespace client if (ls && !ls->IsExpired ()) { ls->PopulateLeases (); // since we don't store them in netdb - m_RemoteLeaseSets[ident] = ls; + { + std::lock_guard lock(m_RemoteLeaseSetsMutex); + m_RemoteLeaseSets[ident] = ls; + } return ls; } } @@ -279,6 +300,7 @@ namespace client if (buf[DATABASE_STORE_TYPE_OFFSET] == 1) // LeaseSet { LogPrint (eLogDebug, "Remote LeaseSet"); + std::lock_guard lock(m_RemoteLeaseSetsMutex); auto it = m_RemoteLeaseSets.find (buf + DATABASE_STORE_KEY_OFFSET); if (it != m_RemoteLeaseSets.end ()) { @@ -627,6 +649,7 @@ namespace client void LeaseSetDestination::CleanupRemoteLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); + std::lock_guard lock(m_RemoteLeaseSetsMutex); for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();) { if (it->second->IsEmpty () || ts > it->second->GetExpirationTime ()) // leaseset expired diff --git a/Destination.h b/Destination.h index e64508c9..ad6318ef 100644 --- a/Destination.h +++ b/Destination.h @@ -122,6 +122,7 @@ namespace client std::thread * m_Thread; boost::asio::io_service m_Service; boost::asio::io_service::work m_Work; + mutable std::mutex m_RemoteLeaseSetsMutex; std::map > m_RemoteLeaseSets; std::map > m_LeaseSetRequests; diff --git a/LeaseSet.cpp b/LeaseSet.cpp index fafe14b7..a7fede01 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -162,7 +162,14 @@ namespace data { return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); } - + + bool LeaseSet::ExpiresSoon(const uint64_t dlt) const + { + auto now = i2p::util::GetMillisecondsSinceEpoch (); + if (now >= m_ExpirationTime) return true; + return m_ExpirationTime - now <= dlt; + } + const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/LeaseSet.h b/LeaseSet.h index c174ac39..d9e74bab 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -60,6 +60,7 @@ namespace data bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; + bool ExpiresSoon(const uint64_t dlt=1000 * 5) const ; bool operator== (const LeaseSet& other) const { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; diff --git a/NTCPSession.cpp b/NTCPSession.cpp index d2c03857..71cb21b3 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -768,6 +768,7 @@ namespace transport auto& addresses = context.GetRouterInfo ().GetAddresses (); for (auto address: addresses) { + if (!address) continue; if (address->transportStyle == i2p::data::RouterInfo::eTransportNTCP) { if (address->host.is_v4()) diff --git a/Transports.cpp b/Transports.cpp index a54455cc..f8af379f 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -114,6 +114,7 @@ namespace transport auto& addresses = context.GetRouterInfo ().GetAddresses (); for (auto address : addresses) { + if (!address) continue; if (m_NTCPServer == nullptr && enableNTCP) { m_NTCPServer = new NTCPServer (); From 4dc9f6948dd4aeaff0c62374ddfffd5ef7866d89 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 25 Jul 2016 09:57:35 -0400 Subject: [PATCH 003/141] bounds checks --- Identity.cpp | 15 ++++++++++----- Identity.h | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Identity.cpp b/Identity.cpp index 71ca007f..6d37d34e 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -200,7 +200,9 @@ namespace data } memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE); - delete[] m_ExtendedBuffer; m_ExtendedBuffer = nullptr; + if(m_ExtendedBuffer) delete[] m_ExtendedBuffer; + m_ExtendedBuffer = nullptr; + m_ExtendedLen = bufbe16toh (m_StandardIdentity.certificate + 1); if (m_ExtendedLen) { @@ -410,6 +412,7 @@ namespace data memcpy (m_PrivateKey, buf + ret, 256); // private key always 256 ret += 256; size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); + if(signingPrivateKeySize + ret > len) return 0; // overflow memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); ret += signingPrivateKeySize; m_Signer = nullptr; @@ -422,7 +425,8 @@ namespace data size_t ret = m_Public->ToBuffer (buf, len); memcpy (buf + ret, m_PrivateKey, 256); // private key always 256 ret += 256; - size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); + size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); + if(ret + signingPrivateKeySize > len) return 0; // overflow memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize); ret += signingPrivateKeySize; return ret; @@ -452,11 +456,12 @@ namespace data void PrivateKeys::Sign (const uint8_t * buf, int len, uint8_t * signature) const { - if (m_Signer) - m_Signer->Sign (buf, len, signature); + if (!m_Signer) + CreateSigner(); + m_Signer->Sign (buf, len, signature); } - void PrivateKeys::CreateSigner () + void PrivateKeys::CreateSigner () const { switch (m_Public->GetSigningKeyType ()) { diff --git a/Identity.h b/Identity.h index 841acf65..d9fb7761 100644 --- a/Identity.h +++ b/Identity.h @@ -133,14 +133,14 @@ namespace data private: - void CreateSigner (); + void CreateSigner () const; private: std::shared_ptr m_Public; uint8_t m_PrivateKey[256]; uint8_t m_SigningPrivateKey[1024]; // assume private key doesn't exceed 1024 bytes - std::unique_ptr m_Signer; + mutable std::unique_ptr m_Signer; }; // kademlia From 1e1c4d159b068940544b6982cf377fc6d42dc4f2 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 25 Jul 2016 10:28:20 -0400 Subject: [PATCH 004/141] do reload --- ClientContext.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 788e6a46..be059ae3 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -202,11 +202,8 @@ namespace client void ClientContext::ReloadConfig () { - /* - std::string config; i2p::config::GetOption("conf", config); - i2p::config::ParseConfig(config); - */ - //I don't think we can just reload the main config without making a mess of things, so holding off for now. + std::string config; i2p::config::GetOption("conf", config); + i2p::config::ParseConfig(config); Stop(); Start(); } From eeeae126390ba150555902e85fc59a6d4ec0b47c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 25 Jul 2016 11:13:54 -0400 Subject: [PATCH 005/141] check for correctly loaded privatekeys --- ClientContext.cpp | 34 +++++++++++++++++++++++----------- ClientContext.h | 2 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index be059ae3..bf0465e1 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -51,8 +51,10 @@ namespace client if (httpProxyKeys.length () > 0) { i2p::data::PrivateKeys keys; - LoadPrivateKeys (keys, httpProxyKeys); - localDestination = CreateNewLocalDestination (keys, false); + if(LoadPrivateKeys (keys, httpProxyKeys)) + localDestination = CreateNewLocalDestination (keys, false); + else + LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); } try { m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); @@ -208,8 +210,9 @@ namespace client Start(); } - void ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType) + 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 ()) @@ -219,9 +222,14 @@ namespace client s.seekg (0, std::ios::beg); uint8_t * buf = new uint8_t[len]; s.read ((char *)buf, len); - keys.FromBuffer (buf, len); + if(!keys.FromBuffer (buf, len)) + { + LogPrint (eLogError, "Clients: failed to load keyfile ", filename); + success = false; + } + else + LogPrint (eLogInfo, "Clients: Local address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " loaded"); delete[] buf; - LogPrint (eLogInfo, "Clients: Local address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " loaded"); } else { @@ -235,7 +243,8 @@ namespace client delete[] buf; LogPrint (eLogInfo, "Clients: New private keys file ", fullPath, " for ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " created"); - } + } + return success; } std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, @@ -358,10 +367,12 @@ namespace client if (keys.length () > 0) { i2p::data::PrivateKeys k; - LoadPrivateKeys (k, keys, sigType); - localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); - if (!localDestination) - localDestination = CreateNewLocalDestination (k, false, &options); + if(LoadPrivateKeys (k, keys, sigType)) + { + localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); + if (!localDestination) + localDestination = CreateNewLocalDestination (k, false, &options); + } } auto clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); if (m_ClientTunnels.insert (std::make_pair (clientTunnel->GetAcceptor ().local_endpoint (), @@ -392,7 +403,8 @@ namespace client std::shared_ptr localDestination = nullptr; i2p::data::PrivateKeys k; - LoadPrivateKeys (k, keys, sigType); + if(!LoadPrivateKeys (k, keys, sigType)) + continue; localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); diff --git a/ClientContext.h b/ClientContext.h index f5696902..55176b91 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -59,7 +59,7 @@ namespace client const std::map * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; - void LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); + 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; }; const SAMBridge * GetSAMBridge () const { return m_SamBridge; }; From f32510e10ab895a68a7e2a62d4ddb49d59d75073 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 09:25:05 -0400 Subject: [PATCH 006/141] set socket options --- I2PService.cpp | 7 ++++++- I2PTunnel.cpp | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/I2PService.cpp b/I2PService.cpp index 4f907f18..f5ebcb0c 100644 --- a/I2PService.cpp +++ b/I2PService.cpp @@ -32,7 +32,12 @@ namespace client } } - TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) {} + TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) + { + boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE); + upstream->set_option(option); + downstream->set_option(option); + } TCPIPPipe::~TCPIPPipe() { diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index ad06328b..aadc15b6 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -9,11 +9,20 @@ namespace i2p { namespace client { + + /** set standard socket options */ + static void I2PTunnelSetSocketOptions(std::shared_ptr socket) + { + boost::asio::socket_base::receive_buffer_size option(I2P_TUNNEL_CONNECTION_BUFFER_SIZE); + socket->set_option(option); + } + I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr leaseSet, int port): I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { + I2PTunnelSetSocketOptions(m_Socket); m_Stream = GetOwner()->GetLocalDestination ()->CreateStream (leaseSet, port); } @@ -22,6 +31,7 @@ namespace client I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { + I2PTunnelSetSocketOptions(m_Socket); } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, @@ -29,6 +39,7 @@ namespace client I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), m_RemoteEndpoint (target), m_IsQuiet (quiet) { + I2PTunnelSetSocketOptions(m_Socket); } I2PTunnelConnection::~I2PTunnelConnection () From f5684eba90a811559de12456b4db6263f52f1f89 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 09:49:43 -0400 Subject: [PATCH 007/141] color log messages for warn and error --- Log.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Log.h b/Log.h index 6762899f..bedc98f8 100644 --- a/Log.h +++ b/Log.h @@ -40,8 +40,20 @@ enum LogType { #endif }; +#ifdef _WIN32 + const char LOG_COLOR_ERROR[] = ""; + const char LOG_COLOR_WARNING[] = ""; + const char LOG_COLOR_RESET[] = ""; +#else + const char LOG_COLOR_ERROR[] = "\033[1;31m"; + const char LOG_COLOR_WARNING[] = "\033[1;33m"; + const char LOG_COLOR_RESET[] = "\033[0m"; +#endif + + namespace i2p { namespace log { + struct LogMsg; /* forward declaration */ class Log @@ -177,8 +189,16 @@ void LogPrint (LogLevel level, TArgs... args) // fold message to single string std::stringstream ss(""); - LogPrint (ss, args ...); + if(level == eLogError) // if log level is ERROR color log message red + ss << LOG_COLOR_ERROR; + else if (level == eLogWarning) // if log level is WARN color log message yellow + ss << LOG_COLOR_WARNING; + LogPrint (ss, args ...); + + // reset color + ss << LOG_COLOR_RESET; + auto msg = std::make_shared(level, std::time(nullptr), ss.str()); msg->tid = std::this_thread::get_id(); log.Append(msg); From 50b9eca34c98e09acffd132195c7341516e37f45 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 09:50:19 -0400 Subject: [PATCH 008/141] check for bogus times in packets --- Streaming.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index 3806d97d..316a3031 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -268,7 +268,12 @@ namespace stream } } auto sentPacket = *it; - uint64_t rtt = ts - sentPacket->sendTime; + uint64_t rtt = ts - sentPacket->sendTime; + if(ts < sentPacket->sendTime) + { + LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime); + rtt = 0; + } m_RTT = (m_RTT*seqn + rtt)/(seqn + 1); m_RTO = m_RTT*1.5; // TODO: implement it better LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt); From 61fe2923e4f3ae00efcde38212a9e4d7b447ea51 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 09:53:39 -0400 Subject: [PATCH 009/141] don't set socket option for closed sockets --- I2PTunnel.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index aadc15b6..d680fee9 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -13,8 +13,11 @@ namespace client /** set standard socket options */ static void I2PTunnelSetSocketOptions(std::shared_ptr socket) { - boost::asio::socket_base::receive_buffer_size option(I2P_TUNNEL_CONNECTION_BUFFER_SIZE); - socket->set_option(option); + if (socket && socket->is_open()) + { + boost::asio::socket_base::receive_buffer_size option(I2P_TUNNEL_CONNECTION_BUFFER_SIZE); + socket->set_option(option); + } } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, @@ -22,7 +25,6 @@ namespace client I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { - I2PTunnelSetSocketOptions(m_Socket); m_Stream = GetOwner()->GetLocalDestination ()->CreateStream (leaseSet, port); } @@ -31,7 +33,6 @@ namespace client I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { - I2PTunnelSetSocketOptions(m_Socket); } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr stream, @@ -39,7 +40,6 @@ namespace client I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream), m_RemoteEndpoint (target), m_IsQuiet (quiet) { - I2PTunnelSetSocketOptions(m_Socket); } I2PTunnelConnection::~I2PTunnelConnection () @@ -61,6 +61,7 @@ namespace client void I2PTunnelConnection::Connect () { + I2PTunnelSetSocketOptions(m_Socket); if (m_Socket) m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, shared_from_this (), std::placeholders::_1)); From 59797a5c9a5d4d2683c84a53ead5af5bf4ef72d3 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 10:01:20 -0400 Subject: [PATCH 010/141] streaming log tweaks and dont set RTT to 0 --- Streaming.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 316a3031..9dfef0fe 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -272,11 +272,11 @@ namespace stream if(ts < sentPacket->sendTime) { LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime); - rtt = 0; + rtt = 1; } m_RTT = (m_RTT*seqn + rtt)/(seqn + 1); m_RTO = m_RTT*1.5; // TODO: implement it better - LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt); + LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt, " sentTime=", sentPacket->sendTime); m_SentPackets.erase (it++); delete sentPacket; acknowledged = true; From 17bfa35f7791ca6276d3d546139935969a8bb087 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 10:02:26 -0400 Subject: [PATCH 011/141] don't use warning for no tags --- Garlic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Garlic.cpp b/Garlic.cpp index d48e9d94..aab3e9ab 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -178,7 +178,7 @@ namespace garlic // create message if (!tagFound) // new session { - LogPrint (eLogWarning, "Garlic: No tags available, will use ElGamal"); + LogPrint (eLogInfo, "Garlic: No tags available, will use ElGamal"); if (!m_Destination) { LogPrint (eLogError, "Garlic: Can't use ElGamal for unknown destination"); From aa3a93b6a09943596a7e28d2d5976d0e8c8477ce Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 11:16:29 -0400 Subject: [PATCH 012/141] implement streaming limiting (initial) --- ClientContext.cpp | 2 ++ I2PTunnel.cpp | 4 +-- I2PTunnel.h | 6 ++-- Streaming.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++--- Streaming.h | 37 ++++++++++++++++++- 5 files changed, 129 insertions(+), 10 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index bf0465e1..623abab8 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -437,6 +437,8 @@ namespace client std::unique_ptr(serverTunnel))).second) { serverTunnel->Start (); + auto maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); + serverTunnel->SetMaxConnsPerMinute(maxConns); numServerTunnels++; } else diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index d680fee9..87764a84 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -45,7 +45,7 @@ namespace client I2PTunnelConnection::~I2PTunnelConnection () { } - + void I2PTunnelConnection::I2PConnect (const uint8_t * msg, size_t len) { if (m_Stream) @@ -396,7 +396,7 @@ namespace client { m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port, gzip); } - + void I2PServerTunnel::Start () { m_Endpoint.port (m_Port); diff --git a/I2PTunnel.h b/I2PTunnel.h index bec0f9a4..f0332722 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -148,8 +148,10 @@ namespace client const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; } const char* GetName() { return m_Name.c_str (); } - - private: + + 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, std::shared_ptr resolver); diff --git a/Streaming.cpp b/Streaming.cpp index 9dfef0fe..887bdecc 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -797,7 +797,10 @@ namespace stream StreamingDestination::StreamingDestination (std::shared_ptr owner, uint16_t localPort, bool gzip): m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip), - m_PendingIncomingTimer (m_Owner->GetService ()) + m_PendingIncomingTimer (m_Owner->GetService ()), + m_ConnTrackTimer(m_Owner->GetService()), + m_ConnsPerMinute(DEFAULT_MAX_CONNS_PER_MIN), + m_LastBanClear(i2p::util::GetMillisecondsSinceEpoch()) { } @@ -812,17 +815,23 @@ namespace stream } void StreamingDestination::Start () - { + { + ScheduleConnTrack(); } void StreamingDestination::Stop () { ResetAcceptor (); m_PendingIncomingTimer.cancel (); + m_ConnTrackTimer.cancel(); { std::unique_lock l(m_StreamsMutex); m_Streams.clear (); - } + } + { + std::unique_lock l(m_ConnsMutex); + m_Conns.clear (); + } } void StreamingDestination::HandleNextPacket (Packet * packet) @@ -856,7 +865,22 @@ namespace stream incomingStream->HandleNextPacket (it1); m_SavedPackets.erase (it); } - } + } + auto ident = incomingStream->GetRemoteIdentity(); + if(ident) + { + auto ih = ident->GetIdentHash(); + if(DropNewStream(ih)) + { + // drop + LogPrint(eLogWarning, "Streaming: Too many inbound streams from ", ih.ToBase32()); + DeleteStream(incomingStream); + incomingStream = nullptr; + delete packet; + return; + } + } else + LogPrint(eLogWarning, "Streaming: Inbound stream has no identity"); // accept if (m_Acceptor != nullptr) m_Acceptor (incomingStream); @@ -1009,6 +1033,62 @@ namespace stream else msg = nullptr; return msg; - } + } + + void StreamingDestination::SetMaxConnsPerMinute(const uint32_t conns) + { + m_ConnsPerMinute = conns; + } + + bool StreamingDestination::DropNewStream(const i2p::data::IdentHash & ih) + { + std::lock_guard lock(m_ConnsMutex); + if (m_Banned.size() > MAX_BANNED_CONNS) return true; // overload + auto end = m_Banned.end(); + if ( std::find(m_Banned.begin(), end, ih) != end) return true; // already banned + auto itr = m_Conns.find(ih); + if (itr == m_Conns.end()) + m_Conns[ih] = 0; + + m_Conns[ih] = m_Conns[ih] + 1; + + bool ban = m_Conns[ih] <= m_ConnsPerMinute; + if (ban) + { + m_Banned.push_back(ih); + m_Conns.erase(ih); + } + return ban; + } + + void StreamingDestination::HandleConnTrack(const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + { // acquire lock + std::lock_guard lock(m_ConnsMutex); + // clear conn tracking + m_Conns.clear(); + // check for ban clear + auto ts = i2p::util::GetMillisecondsSinceEpoch(); + if (ts - m_LastBanClear >= DEFAULT_BAN_INTERVAL) + { + // clear bans + m_Banned.clear(); + m_LastBanClear = ts; + } + } + // reschedule timer + ScheduleConnTrack(); + } + } + + void StreamingDestination::ScheduleConnTrack() + { + m_ConnTrackTimer.expires_from_now (boost::posix_time::seconds(60)); + m_ConnTrackTimer.async_wait ( + std::bind (&StreamingDestination::HandleConnTrack, + shared_from_this (), std::placeholders::_1)); + } } } diff --git a/Streaming.h b/Streaming.h index c29b62f9..d21dc16b 100644 --- a/Streaming.h +++ b/Streaming.h @@ -51,6 +51,22 @@ namespace stream const int INITIAL_RTO = 9000; // in milliseconds const size_t MAX_PENDING_INCOMING_BACKLOG = 128; const int PENDING_INCOMING_TIMEOUT = 10; // in seconds + + /** i2cp option for limiting inbound stremaing connections */ + const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "i2p.streaming.maxConnsPerMinute"; + /** default maximum connections attempts per minute per destination */ + const uint32_t DEFAULT_MAX_CONNS_PER_MIN = 600; + + /** + * max banned destinations per local destination + * TODO: make configurable + */ + const uint16_t MAX_BANNED_CONNS = 9999; + /** + * length of a ban in ms + * TODO: make configurable + */ + const uint64_t DEFAULT_BAN_INTERVAL = 60 * 60 * 1000; struct Packet { @@ -210,12 +226,22 @@ namespace stream void HandleDataMessagePayload (const uint8_t * buf, size_t len); std::shared_ptr CreateDataMessage (const uint8_t * payload, size_t len, uint16_t toPort); + /** set max connections per minute per destination */ + void SetMaxConnsPerMinute(const uint32_t conns); + private: void HandleNextPacket (Packet * packet); std::shared_ptr CreateNewIncomingStream (); void HandlePendingIncomingTimer (const boost::system::error_code& ecode); + /** handle cleaning up connection tracking for ratelimits */ + void HandleConnTrack(const boost::system::error_code& ecode); + + bool DropNewStream(const i2p::data::IdentHash & ident); + + void ScheduleConnTrack(); + private: std::shared_ptr m_Owner; @@ -227,7 +253,16 @@ namespace stream std::list > m_PendingIncomingStreams; boost::asio::deadline_timer m_PendingIncomingTimer; std::map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN - + + std::mutex m_ConnsMutex; + /** how many connections per minute did each identity have */ + std::map m_Conns; + boost::asio::deadline_timer m_ConnTrackTimer; + uint32_t m_ConnsPerMinute; + /** banned identities */ + std::vector m_Banned; + uint64_t m_LastBanClear; + public: i2p::data::GzipInflator m_Inflator; From df8d73ae433c4b39fbd6985d38ec5f1d2c6106d3 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 11:20:24 -0400 Subject: [PATCH 013/141] typo --- Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index 887bdecc..06f2a18a 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -1052,7 +1052,7 @@ namespace stream m_Conns[ih] = m_Conns[ih] + 1; - bool ban = m_Conns[ih] <= m_ConnsPerMinute; + bool ban = m_Conns[ih] >= m_ConnsPerMinute; if (ban) { m_Banned.push_back(ih); From 34da9a9655a09ec33079a809e2998b22241d79b5 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 11:37:33 -0400 Subject: [PATCH 014/141] streaming limiting tweaks --- Streaming.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 06f2a18a..160388cc 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -853,6 +853,23 @@ namespace stream if (packet->IsSYN () && !packet->GetSeqn ()) // new incoming stream { auto incomingStream = CreateNewIncomingStream (); + auto ident = incomingStream->GetRemoteIdentity(); + if(ident) + { + auto ih = ident->GetIdentHash(); + if(DropNewStream(ih)) + { + // drop + LogPrint(eLogWarning, "Streaming: Too many inbound streams from ", ih.ToBase32()); + incomingStream->Close(); + DeleteStream(incomingStream); + incomingStream = nullptr; + delete packet; + return; + } + } else + LogPrint(eLogWarning, "Streaming: Inbound stream has no identity"); + uint32_t receiveStreamID = packet->GetReceiveStreamID (); incomingStream->HandleNextPacket (packet); // SYN // handle saved packets if any @@ -866,21 +883,6 @@ namespace stream m_SavedPackets.erase (it); } } - auto ident = incomingStream->GetRemoteIdentity(); - if(ident) - { - auto ih = ident->GetIdentHash(); - if(DropNewStream(ih)) - { - // drop - LogPrint(eLogWarning, "Streaming: Too many inbound streams from ", ih.ToBase32()); - DeleteStream(incomingStream); - incomingStream = nullptr; - delete packet; - return; - } - } else - LogPrint(eLogWarning, "Streaming: Inbound stream has no identity"); // accept if (m_Acceptor != nullptr) m_Acceptor (incomingStream); From a2e01f8a536c90749509de3a6ef8e377aba0d001 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 11:42:31 -0400 Subject: [PATCH 015/141] more tweaks --- Streaming.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 160388cc..5138498d 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -853,6 +853,8 @@ namespace stream if (packet->IsSYN () && !packet->GetSeqn ()) // new incoming stream { auto incomingStream = CreateNewIncomingStream (); + uint32_t receiveStreamID = packet->GetReceiveStreamID (); + incomingStream->HandleNextPacket (packet); // SYN auto ident = incomingStream->GetRemoteIdentity(); if(ident) { @@ -864,14 +866,14 @@ namespace stream incomingStream->Close(); DeleteStream(incomingStream); incomingStream = nullptr; + if(m_SavedPackets.find(receiveStreamID) != m_SavedPackets.end()) + m_SavedPackets.erase(receiveStreamID); delete packet; return; } } else LogPrint(eLogWarning, "Streaming: Inbound stream has no identity"); - uint32_t receiveStreamID = packet->GetReceiveStreamID (); - incomingStream->HandleNextPacket (packet); // SYN // handle saved packets if any { auto it = m_SavedPackets.find (receiveStreamID); From 3b66bba92e25e68d0999f5777ba2186ca6c7157f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 12:17:24 -0400 Subject: [PATCH 016/141] more fixes --- ClientContext.cpp | 3 ++- Streaming.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 623abab8..8fb8d927 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -436,9 +436,10 @@ namespace client std::make_pair (localDestination->GetIdentHash (), inPort), std::unique_ptr(serverTunnel))).second) { - serverTunnel->Start (); auto maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); + LogPrint(eLogInfo, "Clients: Set Max Conns To ", maxConns); serverTunnel->SetMaxConnsPerMinute(maxConns); + serverTunnel->Start (); numServerTunnels++; } else diff --git a/Streaming.cpp b/Streaming.cpp index 5138498d..a8d9bb71 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -1042,25 +1042,27 @@ namespace stream void StreamingDestination::SetMaxConnsPerMinute(const uint32_t conns) { m_ConnsPerMinute = conns; + LogPrint(eLogDebug, "Streaming: Set max conns per minute per destination to ", conns); } bool StreamingDestination::DropNewStream(const i2p::data::IdentHash & ih) { std::lock_guard lock(m_ConnsMutex); if (m_Banned.size() > MAX_BANNED_CONNS) return true; // overload - auto end = m_Banned.end(); - if ( std::find(m_Banned.begin(), end, ih) != end) return true; // already banned + auto end = std::end(m_Banned); + if ( std::find(std::begin(m_Banned), end, ih) != end) return true; // already banned auto itr = m_Conns.find(ih); if (itr == m_Conns.end()) m_Conns[ih] = 0; - m_Conns[ih] = m_Conns[ih] + 1; + m_Conns[ih] += 1; bool ban = m_Conns[ih] >= m_ConnsPerMinute; if (ban) { m_Banned.push_back(ih); m_Conns.erase(ih); + LogPrint(eLogWarning, "Streaming: ban ", ih.ToBase32()); } return ban; } From 6b3a783ce9bf98e724c446f403475877c170e33e Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 12:21:59 -0400 Subject: [PATCH 017/141] change type --- ClientContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 8fb8d927..0bf63ee1 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -436,7 +436,7 @@ namespace client std::make_pair (localDestination->GetIdentHash (), inPort), std::unique_ptr(serverTunnel))).second) { - auto maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); + auto maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); LogPrint(eLogInfo, "Clients: Set Max Conns To ", maxConns); serverTunnel->SetMaxConnsPerMinute(maxConns); serverTunnel->Start (); From 13735d04755009b62d8f007db812073fd6612b99 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 12:26:05 -0400 Subject: [PATCH 018/141] move setting --- ClientContext.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 0bf63ee1..0a5ce94f 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -417,6 +417,11 @@ namespace client else // regular server tunnel by default serverTunnel = new I2PServerTunnel (name, host, port, localDestination, inPort, gzip); + uint32_t maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); + LogPrint(eLogInfo, "Clients: Set Max Conns To ", maxConns); + serverTunnel->SetMaxConnsPerMinute(maxConns); + + if (accessList.length () > 0) { std::set idents; @@ -436,9 +441,6 @@ namespace client std::make_pair (localDestination->GetIdentHash (), inPort), std::unique_ptr(serverTunnel))).second) { - auto maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); - LogPrint(eLogInfo, "Clients: Set Max Conns To ", maxConns); - serverTunnel->SetMaxConnsPerMinute(maxConns); serverTunnel->Start (); numServerTunnels++; } From fc5b1ae3e2ed5b9075984a1cb4f0645122fad77f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 12:28:18 -0400 Subject: [PATCH 019/141] fug --- ClientContext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 0a5ce94f..25d3ce89 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -397,6 +397,8 @@ namespace client std::string webircpass = section.second.get (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, ""); bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, true); i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); + uint32_t maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); + // I2CP std::map options; ReadI2CPOptions (section, options); @@ -417,7 +419,6 @@ namespace client else // regular server tunnel by default serverTunnel = new I2PServerTunnel (name, host, port, localDestination, inPort, gzip); - uint32_t maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); LogPrint(eLogInfo, "Clients: Set Max Conns To ", maxConns); serverTunnel->SetMaxConnsPerMinute(maxConns); From 9447afe49ca17a2bcd046abceb719b947fe461cf Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 12:32:05 -0400 Subject: [PATCH 020/141] try changing i2cp option --- Streaming.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Streaming.h b/Streaming.h index d21dc16b..4e76e435 100644 --- a/Streaming.h +++ b/Streaming.h @@ -53,7 +53,7 @@ namespace stream const int PENDING_INCOMING_TIMEOUT = 10; // in seconds /** i2cp option for limiting inbound stremaing connections */ - const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "i2p.streaming.maxConnsPerMinute"; + const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "maxConnsPerMinute"; /** default maximum connections attempts per minute per destination */ const uint32_t DEFAULT_MAX_CONNS_PER_MIN = 600; From 87e1c45c053a358f37a668dba09eb00dae213809 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 12:34:33 -0400 Subject: [PATCH 021/141] fug --- Streaming.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Streaming.h b/Streaming.h index 4e76e435..5d995ec3 100644 --- a/Streaming.h +++ b/Streaming.h @@ -53,7 +53,7 @@ namespace stream const int PENDING_INCOMING_TIMEOUT = 10; // in seconds /** i2cp option for limiting inbound stremaing connections */ - const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "maxConnsPerMinute"; + const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "maxconns"; /** default maximum connections attempts per minute per destination */ const uint32_t DEFAULT_MAX_CONNS_PER_MIN = 600; From 584379b50284daf3a3a996664c282b2312d8ffaa Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 12:48:32 -0400 Subject: [PATCH 022/141] fix --- Streaming.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index a8d9bb71..3a1a972b 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -862,10 +862,8 @@ namespace stream if(DropNewStream(ih)) { // drop - LogPrint(eLogWarning, "Streaming: Too many inbound streams from ", ih.ToBase32()); + LogPrint(eLogWarning, "Streaming: Dropping connection, too many inbound streams from ", ih.ToBase32()); incomingStream->Close(); - DeleteStream(incomingStream); - incomingStream = nullptr; if(m_SavedPackets.find(receiveStreamID) != m_SavedPackets.end()) m_SavedPackets.erase(receiveStreamID); delete packet; From e8c3546433e4c3d372ed59b661441dff2504b2bd Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 13:27:51 -0400 Subject: [PATCH 023/141] try fixing --- Streaming.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 3a1a972b..a4cfb533 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -864,9 +864,6 @@ namespace stream // drop LogPrint(eLogWarning, "Streaming: Dropping connection, too many inbound streams from ", ih.ToBase32()); incomingStream->Close(); - if(m_SavedPackets.find(receiveStreamID) != m_SavedPackets.end()) - m_SavedPackets.erase(receiveStreamID); - delete packet; return; } } else From 570598f55624c50a9828d1e6be54ff66a6b8ab64 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 15:33:03 -0400 Subject: [PATCH 024/141] abruptly close --- Streaming.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index a4cfb533..87d669ca 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -863,12 +863,11 @@ namespace stream { // drop LogPrint(eLogWarning, "Streaming: Dropping connection, too many inbound streams from ", ih.ToBase32()); - incomingStream->Close(); + incomingStream->Terminate(); + delete incomingStream; return; } - } else - LogPrint(eLogWarning, "Streaming: Inbound stream has no identity"); - + } // handle saved packets if any { auto it = m_SavedPackets.find (receiveStreamID); From ee9dc789afce08b960c76f6b9b84da7dc517b7a4 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 15:34:32 -0400 Subject: [PATCH 025/141] change scope of Stream::Terminate --- Streaming.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Streaming.h b/Streaming.h index 5d995ec3..efa4d69e 100644 --- a/Streaming.h +++ b/Streaming.h @@ -150,10 +150,11 @@ namespace stream size_t GetSendBufferSize () const { return m_SendBuffer.rdbuf ()->in_avail (); }; int GetWindowSize () const { return m_WindowSize; }; int GetRTT () const { return m_RTT; }; - - private: + /** don't call me */ void Terminate (); + + private: void SendBuffer (); void SendQuickAck (); From cf8ff2cf861034a84e104c93e8c5679a0c8a1592 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 28 Jul 2016 15:35:13 -0400 Subject: [PATCH 026/141] make it compile --- Streaming.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index 87d669ca..8261a639 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -864,7 +864,6 @@ namespace stream // drop LogPrint(eLogWarning, "Streaming: Dropping connection, too many inbound streams from ", ih.ToBase32()); incomingStream->Terminate(); - delete incomingStream; return; } } From c8f5fb4d039c03adbad186593514d4162f832395 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 3 Aug 2016 10:40:30 -0400 Subject: [PATCH 027/141] close duplicate ntcp sessions --- NTCPSession.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 71cb21b3..144b947e 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -861,6 +861,7 @@ namespace transport if (it != m_NTCPSessions.end ()) { LogPrint (eLogWarning, "NTCP: session to ", ident.ToBase64 (), " already exists"); + session->Terminate(); return false; } m_NTCPSessions.insert (std::pair >(ident, session)); From 2d82c4ada44bef837228a48c20e31dac76cd6d90 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 16 Aug 2016 10:25:56 -0400 Subject: [PATCH 028/141] try fixing https://github.com/PurpleI2P/i2pd/issues/612 --- build/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 7f9b8c66..99d6a5ad 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -369,7 +369,10 @@ if (WITH_BINARY) if (MSYS OR MINGW) set (MINGW_EXTRA -lws2_32 -lmswsock -liphlpapi ) endif () - target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ) + if (WITH_STATIC) + set(DL_LIB ${CMAKE_DL_LIBS}) + endif() + target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB}) install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") From aa3723d2bdeb637554c4f7cb9376c5c0a1141a7c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 15:02:17 -0400 Subject: [PATCH 029/141] udp tunnels --- ClientContext.cpp | 105 +++++++++++++++++++++++++++----- ClientContext.h | 20 ++++++- I2PTunnel.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++ I2PTunnel.h | 78 +++++++++++++++++++++++- Identity.h | 2 + Tag.h | 5 ++ 6 files changed, 338 insertions(+), 20 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 2c917025..68115402 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -17,7 +17,8 @@ namespace client ClientContext::ClientContext (): m_SharedLocalDestination (nullptr), m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr), - m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr) + m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr), + m_CleanupUDPTimer(m_Service, boost::posix_time::seconds(1)) { } @@ -39,6 +40,13 @@ namespace client m_SharedLocalDestination->Start (); } + if ( m_ServiceThread == nullptr ) { + m_ServiceThread = new std::thread([&] () { + m_Service.run(); + }); + ScheduleCleanupUDP(); + } + m_AddressBook.Start (); std::shared_ptr localDestination; @@ -195,11 +203,26 @@ namespace client } LogPrint(eLogInfo, "Clients: stopping AddressBook"); - m_AddressBook.Stop (); + m_AddressBook.Stop (); + + { + std::lock_guard lock(m_ForwardsMutex); + m_ServerForwards.clear(); + m_ClientForwards.clear(); + } + + for (auto& it: m_Destinations) it.second->Stop (); m_Destinations.clear (); - m_SharedLocalDestination = nullptr; + m_SharedLocalDestination = nullptr; + // stop io service thread + if(m_ServiceThread) { + m_Service.stop(); + m_ServiceThread->join(); + delete m_ServiceThread; + m_ServiceThread = nullptr; + } } void ClientContext::ReloadConfig () @@ -349,7 +372,7 @@ namespace client try { std::string type = section.second.get (I2P_TUNNELS_SECTION_TYPE); - if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT) + if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { // mandatory params std::string dest = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION); @@ -374,17 +397,34 @@ namespace client localDestination = CreateNewLocalDestination (k, false, &options); } } - auto clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); - if (m_ClientTunnels.insert (std::make_pair (clientTunnel->GetAcceptor ().local_endpoint (), - std::unique_ptr(clientTunnel))).second) - { - clientTunnel->Start (); - numClientTunnels++; - } - else - LogPrint (eLogError, "Clients: I2P client tunnel for endpoint ", clientTunnel->GetAcceptor ().local_endpoint (), " already exists"); + if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { + // udp client + // TODO: ip6 and hostnames + boost::asio::ip::udp::endpoint end(boost::asio::ip::address::from_string(address), port); + if(destinationPort == 0) { + destinationPort = port; + } + auto clientTunnel = new I2PUDPClientTunnel(name, dest, end, localDestination, destinationPort, m_Service); + if(m_ClientForwards.insert(std::make_pair(end, std::unique_ptr(clientTunnel))).second) { + clientTunnel->Start(); + } else { + LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); + delete clientTunnel; + } + } else { + // tcp client + auto clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); + if (m_ClientTunnels.insert (std::make_pair (clientTunnel->GetAcceptor ().local_endpoint (), + std::unique_ptr(clientTunnel))).second) + { + clientTunnel->Start (); + numClientTunnels++; + } + else + LogPrint (eLogError, "Clients: I2P client tunnel for endpoint ", clientTunnel->GetAcceptor ().local_endpoint (), " already exists"); + } } - else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER || type == I2P_TUNNELS_SECTION_TYPE_HTTP || type == I2P_TUNNELS_SECTION_TYPE_IRC) + else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER || 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); @@ -411,6 +451,25 @@ namespace client if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); + if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) { + // udp server tunnel + // TODO: ipv6 and hostnames + boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::address::from_string(host), port); + I2PUDPServerTunnel * serverTunnel = new I2PUDPServerTunnel(name, localDestination, endpoint, port, m_Service); + std::lock_guard lock(m_ForwardsMutex); + if(m_ServerForwards.insert( + std::make_pair( + std::make_pair( + localDestination->GetIdentHash(), port), + std::unique_ptr(serverTunnel))).second) { + LogPrint(eLogInfo, "Cleints: I2P Server Forward created for UDP Endpoint ", host, ":", port); + } else { + LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); + delete serverTunnel; + } + continue; + } + I2PServerTunnel * serverTunnel; if (type == I2P_TUNNELS_SECTION_TYPE_HTTP) serverTunnel = new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort, gzip); @@ -460,6 +519,22 @@ namespace client } LogPrint (eLogInfo, "Clients: ", numClientTunnels, " I2P client tunnels created"); LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created"); - } + } + void ClientContext::ScheduleCleanupUDP() + { + // schedule cleanup in 1 second + m_CleanupUDPTimer.expires_at(m_CleanupUDPTimer.expires_at() + boost::posix_time::seconds(1)); + m_CleanupUDPTimer.async_wait(std::bind(&ClientContext::CleanupUDP, this, std::placeholders::_1)); + } + + void ClientContext::CleanupUDP(const boost::system::error_code & ecode) + { + if(!ecode) { + std::lock_guard lock(m_ForwardsMutex); + for ( auto & s : m_ServerForwards ) { + s.second->ExpireStale(); + } + } + } } } diff --git a/ClientContext.h b/ClientContext.h index 55176b91..5a054f29 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -24,6 +24,8 @@ namespace client const char I2P_TUNNELS_SECTION_TYPE_SERVER[] = "server"; const char I2P_TUNNELS_SECTION_TYPE_HTTP[] = "http"; const char I2P_TUNNELS_SECTION_TYPE_IRC[] = "irc"; + const char I2P_TUNNELS_SECTION_TYPE_UDPCLIENT[] = "udpclient"; + const char I2P_TUNNELS_SECTION_TYPE_UDPSERVER[] = "udpserver"; const char I2P_CLIENT_TUNNEL_PORT[] = "port"; const char I2P_CLIENT_TUNNEL_ADDRESS[] = "address"; const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination"; @@ -72,7 +74,10 @@ namespace client template void ReadI2CPOptions (const Section& section, std::map& options) const; - private: + void CleanupUDP(const boost::system::error_code & ecode); + void ScheduleCleanupUDP(); + + private: std::mutex m_DestinationsMutex; std::map > m_Destinations; @@ -84,10 +89,21 @@ namespace client i2p::proxy::SOCKSProxy * m_SocksProxy; std::map > m_ClientTunnels; // local endpoint->tunnel std::map, std::unique_ptr > m_ServerTunnels; // ->tunnel - SAMBridge * m_SamBridge; + + 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; + boost::asio::io_service m_Service; + std::thread * m_ServiceThread; + + boost::asio::deadline_timer m_CleanupUDPTimer; + public: // for HTTP const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; }; diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 87764a84..e639c12a 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -511,5 +511,153 @@ namespace client conn->Connect (); } + void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + { + std::lock_guard lock(m_SessionsMutex); + auto & session = ObtainUDPSession(from, toPort, fromPort); + + session.IPSocket.send_to(boost::asio::buffer(buf, len), m_Endpoint); + session.LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + + } + + void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { + std::lock_guard lock(m_SessionsMutex); + uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); + std::remove_if(m_Sessions.begin(), m_Sessions.end(), [now, delta](const UDPSession & u) -> bool { + return now - u.LastActivity >= delta; + }); + } + + UDPSession & I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) + { + auto ih = from.GetIdentHash(); + for ( UDPSession & s : m_Sessions ) { + if ( s.Identity == ih) { + /** found existing */ + return s; + } + } + /** create new */ + m_Sessions.push_back(UDPSession(m_Service, m_Destination, m_Endpoint, ih, localPort, remotePort)); + return m_Sessions.back(); + } + + UDPSession::UDPSession(boost::asio::io_service & ios, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash from, uint16_t ourPort, uint16_t theirPort) : + Destination(localDestination), + IPSocket(ios, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)), + Identity(from), + ExpectedEndpoint(endpoint), + LocalPort(ourPort), + RemotePort(theirPort) + { + Receive(); + } + + + void UDPSession::Receive() { + IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); + } + + void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) + { + if(!ecode) { + i2p::datagram::DatagramDestination * dgram = Destination->GetDatagramDestination(); + if(dgram) { + LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + dgram->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort); + } + Receive(); + } + } + + I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, boost::asio::io_service & service) : + LocalPort(port), + m_Endpoint(forwardTo), + m_Service(service), + m_Destination(localDestination) + { + i2p::datagram::DatagramDestination * dgram = m_Destination->CreateDatagramDestination(); + if(dgram) + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), LocalPort); + } + + I2PUDPServerTunnel::~I2PUDPServerTunnel() + { + i2p::datagram::DatagramDestination * dgram = m_Destination->GetDatagramDestination(); + if (dgram) { + dgram->ResetReceiver(LocalPort); + } + } + + I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, boost::asio::io_service & service) : + m_Session(nullptr), + m_RemoteDest(remoteDest), + m_RemoteIdent(nullptr), + m_LocalDest(localDestination), + m_LocalEndpoint(localEndpoint), + m_ResolveThread(nullptr), + m_Service(service), + LocalPort(localEndpoint.port()), + RemotePort(remotePort), + m_cancel_resolve(false) + { + + } + + + + void I2PUDPClientTunnel::Start() { + if (m_ResolveThread == nullptr) + m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); + } + + void I2PUDPClientTunnel::TryResolving() { + LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); + m_RemoteIdent = new i2p::data::IdentHash; + m_RemoteIdent->Fill(0); + while(!context.GetAddressBook().GetIdentHash(m_RemoteDest, *m_RemoteIdent) && !m_cancel_resolve) { + LogPrint(eLogWarning, "UDP Tunnel: failed to lookup ", m_RemoteDest); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if(m_cancel_resolve) { + LogPrint(eLogError, "UDP Tunnel: lookup of ", m_RemoteDest, " was cancelled"); + return; + } + // delete existing session + if(m_Session) delete m_Session; + m_Session = new UDPSession(m_Service, m_LocalDest, m_LocalEndpoint, *m_RemoteIdent, LocalPort, RemotePort); + auto dgram = m_LocalDest->CreateDatagramDestination(); + dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, + std::placeholders::_5), LocalPort); + } + + void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + { + if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) { + // address match + if(m_Session) { + // tell session + m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_LocalEndpoint); + } + } + } + + I2PUDPClientTunnel::~I2PUDPClientTunnel() { + auto dgram = m_LocalDest->GetDatagramDestination(); + if (dgram) { + dgram->ResetReceiver(LocalPort); + } + if (m_Session) delete m_Session; + m_cancel_resolve = true; + if(m_ResolveThread) { + m_ResolveThread->join(); + delete m_ResolveThread; + m_ResolveThread = nullptr; + } + if (m_RemoteIdent) delete m_RemoteIdent; + } } } diff --git a/I2PTunnel.h b/I2PTunnel.h index f0332722..232ed2ef 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -9,6 +9,7 @@ #include #include "Identity.h" #include "Destination.h" +#include "Datagram.h" #include "Streaming.h" #include "I2PService.h" @@ -128,8 +129,79 @@ namespace client std::string m_Name, m_Destination; const i2p::data::IdentHash * m_DestinationIdentHash; int m_DestinationPort; - }; + }; + + /** 2 minute timeout for udp sessions */ + const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; + + /** max size for i2p udp */ + const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; + + struct UDPSession + { + std::shared_ptr Destination; + boost::asio::ip::udp::socket IPSocket; + i2p::data::IdentHash Identity; + boost::asio::ip::udp::endpoint ExpectedEndpoint; + boost::asio::ip::udp::endpoint FromEndpoint; + uint64_t LastActivity; + + uint16_t LocalPort; + uint16_t RemotePort; + + uint8_t m_Buffer[I2P_UDP_MAX_MTU]; + + UDPSession(boost::asio::io_service & ios, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); + + void HandleReceived(const boost::system::error_code & ecode, std::size_t len); + void Receive(); + + }; + + /** server side udp tunnel, many i2p inbound to 1 ip outbound */ + class I2PUDPServerTunnel + { + public: + I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, boost::asio::io_service & service); + ~I2PUDPServerTunnel(); + /** expire stale udp conversations */ + void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); + + private: + void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + UDPSession & ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); + private: + const uint16_t LocalPort; + boost::asio::ip::udp::endpoint m_Endpoint; + std::mutex m_SessionsMutex; + std::vector m_Sessions; + boost::asio::io_service & m_Service; + std::shared_ptr m_Destination; + uint8_t m_Buffer[I2P_UDP_MAX_MTU]; + }; + + class I2PUDPClientTunnel + { + public: + I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, boost::asio::io_service & service); + ~I2PUDPClientTunnel(); + void Start(); + private: + void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void TryResolving(); + UDPSession * m_Session; + const std::string m_RemoteDest; + std::shared_ptr m_LocalDest; + i2p::data::IdentHash * m_RemoteIdent; + const boost::asio::ip::udp::endpoint m_LocalEndpoint; + std::thread * m_ResolveThread; + boost::asio::io_service & m_Service; + uint16_t LocalPort; + uint16_t RemotePort; + bool m_cancel_resolve; + }; + class I2PServerTunnel: public I2PService { public: @@ -150,7 +222,7 @@ namespace client 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, @@ -167,7 +239,7 @@ namespace client boost::asio::ip::tcp::endpoint m_Endpoint; std::shared_ptr m_PortDestination; std::set m_AccessList; - bool m_IsAccessList; + bool m_IsAccessList; }; class I2PServerTunnelHTTP: public I2PServerTunnel diff --git a/Identity.h b/Identity.h index d9fb7761..8f3e9e9d 100644 --- a/Identity.h +++ b/Identity.h @@ -92,6 +92,8 @@ namespace data CryptoKeyType GetCryptoKeyType () const; void DropVerifier () const; // to save memory + bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); } + private: void CreateVerifier () const; diff --git a/Tag.h b/Tag.h index b6f94de7..6e5638a4 100644 --- a/Tag.h +++ b/Tag.h @@ -50,6 +50,11 @@ namespace data { return true; } + /** fill with a value */ + void Fill(uint8_t c) { + memset(m_Buf, c, sz); + } + std::string ToBase64 () const { char str[sz*2]; From e8f9ecc7d902ecc05452649c40e1ef030faa9274 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 15:33:19 -0400 Subject: [PATCH 030/141] fixes --- ClientContext.cpp | 4 ++++ I2PTunnel.cpp | 12 +++++++----- I2PTunnel.h | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 68115402..4440cb44 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -404,6 +404,9 @@ namespace client if(destinationPort == 0) { destinationPort = port; } + if (!localDestination) { + localDestination = m_SharedLocalDestination; + } auto clientTunnel = new I2PUDPClientTunnel(name, dest, end, localDestination, destinationPort, m_Service); if(m_ClientForwards.insert(std::make_pair(end, std::unique_ptr(clientTunnel))).second) { clientTunnel->Start(); @@ -411,6 +414,7 @@ namespace client LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); delete clientTunnel; } + } else { // tcp client auto clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index e639c12a..55d40fad 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -539,19 +539,20 @@ namespace client } } /** create new */ - m_Sessions.push_back(UDPSession(m_Service, m_Destination, m_Endpoint, ih, localPort, remotePort)); + m_Sessions.push_back(UDPSession(m_Service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0), m_Destination, m_Endpoint, ih, localPort, remotePort)); return m_Sessions.back(); } - UDPSession::UDPSession(boost::asio::io_service & ios, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash from, uint16_t ourPort, uint16_t theirPort) : + UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash from, uint16_t ourPort, uint16_t theirPort) : Destination(localDestination), - IPSocket(ios, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)), + IPSocket(ios, localEndpoint), Identity(from), ExpectedEndpoint(endpoint), LocalPort(ourPort), RemotePort(theirPort) { Receive(); + LogPrint(eLogDebug, "UDPSession: bound to", IPSocket.local_endpoint()); } @@ -624,10 +625,11 @@ namespace client LogPrint(eLogError, "UDP Tunnel: lookup of ", m_RemoteDest, " was cancelled"); return; } + LogPrint(eLogInfo, "UDP Tunnel: resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); + auto dgram = m_LocalDest->CreateDatagramDestination(); // delete existing session if(m_Session) delete m_Session; - m_Session = new UDPSession(m_Service, m_LocalDest, m_LocalEndpoint, *m_RemoteIdent, LocalPort, RemotePort); - auto dgram = m_LocalDest->CreateDatagramDestination(); + m_Session = new UDPSession(m_Service, m_LocalEndpoint, m_LocalDest, m_LocalEndpoint, *m_RemoteIdent, LocalPort, RemotePort); dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, diff --git a/I2PTunnel.h b/I2PTunnel.h index 232ed2ef..d2b895df 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -152,7 +152,7 @@ namespace client uint8_t m_Buffer[I2P_UDP_MAX_MTU]; - UDPSession(boost::asio::io_service & ios, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); + UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); void HandleReceived(const boost::system::error_code & ecode, std::size_t len); void Receive(); From e529d3ecc9ef11cf2c29634232bd559e312c4bae Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 15:39:11 -0400 Subject: [PATCH 031/141] fixes --- ClientContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 4440cb44..5b4d28d1 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -466,7 +466,7 @@ namespace client std::make_pair( localDestination->GetIdentHash(), port), std::unique_ptr(serverTunnel))).second) { - LogPrint(eLogInfo, "Cleints: I2P Server Forward created for UDP Endpoint ", host, ":", port); + LogPrint(eLogInfo, "Cleints: I2P Server Forward created for UDP Endpoint ", host, ":", port, " via ",localDestination->GetIdentHash().ToBase32()); } else { LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); delete serverTunnel; From 2a5af370754b607ef061d9c4c2d76b43dee58441 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 15:47:00 -0400 Subject: [PATCH 032/141] retrgiger expiration --- ClientContext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ClientContext.cpp b/ClientContext.cpp index 5b4d28d1..dafb2789 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -538,6 +538,7 @@ namespace client for ( auto & s : m_ServerForwards ) { s.second->ExpireStale(); } + ScheduleCleanupUDP(); } } } From 2679c588921f3c9a47e3ed93285e47847c787243 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 15:51:39 -0400 Subject: [PATCH 033/141] logging and ip checks --- I2PTunnel.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 55d40fad..5e4c760b 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -552,7 +552,7 @@ namespace client RemotePort(theirPort) { Receive(); - LogPrint(eLogDebug, "UDPSession: bound to", IPSocket.local_endpoint()); + LogPrint(eLogDebug, "UDPSession: bound to ", IPSocket.local_endpoint()); } @@ -563,10 +563,12 @@ namespace client void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) { if(!ecode) { + LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); i2p::datagram::DatagramDestination * dgram = Destination->GetDatagramDestination(); - if(dgram) { + if(dgram && FromEndpoint == ExpectedEndpoint) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); dgram->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort); + LogPrint(eLogDebug, "UDPSession: forward to ", Identity.ToBase32()); } Receive(); } From 51783a45e618290d223bdc65bb9bde86b08f4e21 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 15:56:52 -0400 Subject: [PATCH 034/141] set last activity --- I2PTunnel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 5e4c760b..2e4b4fed 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -548,6 +548,7 @@ namespace client IPSocket(ios, localEndpoint), Identity(from), ExpectedEndpoint(endpoint), + LastActivity(i2p::util::GetMillisecondsSinceEpoch()), LocalPort(ourPort), RemotePort(theirPort) { From 46d640cd86ef94a4d5020e17dcf60b412bea68b1 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 18:46:34 -0400 Subject: [PATCH 035/141] fixes --- ClientContext.cpp | 7 +++---- I2PTunnel.cpp | 41 +++++++++++++++++++++++++++-------------- I2PTunnel.h | 4 ++-- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index dafb2789..3bc6a2d3 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -42,7 +42,9 @@ namespace client if ( m_ServiceThread == nullptr ) { m_ServiceThread = new std::thread([&] () { + LogPrint(eLogInfo, "ClientContext: starting service"); m_Service.run(); + LogPrint(eLogError, "ClientContext: service died"); }); ScheduleCleanupUDP(); } @@ -394,7 +396,7 @@ namespace client { localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); if (!localDestination) - localDestination = CreateNewLocalDestination (k, false, &options); + localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options); } } if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { @@ -412,7 +414,6 @@ namespace client clientTunnel->Start(); } else { LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); - delete clientTunnel; } } else { @@ -454,7 +455,6 @@ namespace client localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); - if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) { // udp server tunnel // TODO: ipv6 and hostnames @@ -469,7 +469,6 @@ namespace client LogPrint(eLogInfo, "Cleints: I2P Server Forward created for UDP Endpoint ", host, ":", port, " via ",localDestination->GetIdentHash().ToBase32()); } else { LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); - delete serverTunnel; } continue; } diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 2e4b4fed..c864fbc1 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -515,7 +515,6 @@ namespace client { std::lock_guard lock(m_SessionsMutex); auto & session = ObtainUDPSession(from, toPort, fromPort); - session.IPSocket.send_to(boost::asio::buffer(buf, len), m_Endpoint); session.LastActivity = i2p::util::GetMillisecondsSinceEpoch(); @@ -535,19 +534,21 @@ namespace client for ( UDPSession & s : m_Sessions ) { if ( s.Identity == ih) { /** found existing */ + LogPrint(eLogDebug, "UDP Server: found ", s.SendEndpoint); return s; } } /** create new */ - m_Sessions.push_back(UDPSession(m_Service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0), m_Destination, m_Endpoint, ih, localPort, remotePort)); + boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); + m_Sessions.push_back(UDPSession(m_Service, ep, m_Destination, ep, ih, localPort, remotePort)); return m_Sessions.back(); } - UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash from, uint16_t ourPort, uint16_t theirPort) : + UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : Destination(localDestination), IPSocket(ios, localEndpoint), - Identity(from), - ExpectedEndpoint(endpoint), + Identity(to), + SendEndpoint(endpoint), LastActivity(i2p::util::GetMillisecondsSinceEpoch()), LocalPort(ourPort), RemotePort(theirPort) @@ -558,18 +559,24 @@ namespace client void UDPSession::Receive() { + LogPrint(eLogDebug, "UDPSesssion: Recveive"); IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); } void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) { + LogPrint(eLogDebug, "UDPSesssion: HandleRecveived"); if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - i2p::datagram::DatagramDestination * dgram = Destination->GetDatagramDestination(); - if(dgram && FromEndpoint == ExpectedEndpoint) { - LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - dgram->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort); - LogPrint(eLogDebug, "UDPSession: forward to ", Identity.ToBase32()); + if (Destination) { + auto dgram = Destination->CreateDatagramDestination(); + if(dgram) { + LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + dgram->SendDatagramTo(m_Buffer, len, Identity, RemotePort, LocalPort); + LogPrint(eLogDebug, "UDPSession: forward ", len, "B to ", Identity.ToBase32()); + } + } else { + LogPrint(eLogWarning, "UDPSession: no Local Destination"); } Receive(); } @@ -583,7 +590,7 @@ namespace client { i2p::datagram::DatagramDestination * dgram = m_Destination->CreateDatagramDestination(); if(dgram) - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), LocalPort); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); } I2PUDPServerTunnel::~I2PUDPServerTunnel() @@ -632,11 +639,12 @@ namespace client auto dgram = m_LocalDest->CreateDatagramDestination(); // delete existing session if(m_Session) delete m_Session; - m_Session = new UDPSession(m_Service, m_LocalEndpoint, m_LocalDest, m_LocalEndpoint, *m_RemoteIdent, LocalPort, RemotePort); + boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); + m_Session = new UDPSession(m_Service, m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), LocalPort); + std::placeholders::_5)); } void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) @@ -645,8 +653,13 @@ namespace client // address match if(m_Session) { // tell session - m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_LocalEndpoint); + LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32(), " via ", m_Session->SendEndpoint); + m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Session->SendEndpoint); + } else { + LogPrint(eLogWarning, "UDP Client: no session"); } + } else { + LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); } } diff --git a/I2PTunnel.h b/I2PTunnel.h index d2b895df..e50c47f7 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -143,8 +143,8 @@ namespace client std::shared_ptr Destination; boost::asio::ip::udp::socket IPSocket; i2p::data::IdentHash Identity; - boost::asio::ip::udp::endpoint ExpectedEndpoint; boost::asio::ip::udp::endpoint FromEndpoint; + boost::asio::ip::udp::endpoint SendEndpoint; uint64_t LastActivity; uint16_t LocalPort; @@ -193,8 +193,8 @@ namespace client UDPSession * m_Session; const std::string m_RemoteDest; std::shared_ptr m_LocalDest; - i2p::data::IdentHash * m_RemoteIdent; const boost::asio::ip::udp::endpoint m_LocalEndpoint; + i2p::data::IdentHash * m_RemoteIdent; std::thread * m_ResolveThread; boost::asio::io_service & m_Service; uint16_t LocalPort; From 194d63acd81a9af274ea1198470e1669320de6c5 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 19:17:08 -0400 Subject: [PATCH 036/141] fixes --- I2PTunnel.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index c864fbc1..641c5795 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -534,7 +534,6 @@ namespace client for ( UDPSession & s : m_Sessions ) { if ( s.Identity == ih) { /** found existing */ - LogPrint(eLogDebug, "UDP Server: found ", s.SendEndpoint); return s; } } @@ -555,6 +554,7 @@ namespace client { Receive(); LogPrint(eLogDebug, "UDPSession: bound to ", IPSocket.local_endpoint()); + } @@ -569,11 +569,13 @@ namespace client if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); if (Destination) { - auto dgram = Destination->CreateDatagramDestination(); + auto dgram = Destination->GetDatagramDestination(); if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); dgram->SendDatagramTo(m_Buffer, len, Identity, RemotePort, LocalPort); LogPrint(eLogDebug, "UDPSession: forward ", len, "B to ", Identity.ToBase32()); + } else { + LogPrint(eLogWarning, "UDPSession: no datagram destination"); } } else { LogPrint(eLogWarning, "UDPSession: no Local Destination"); From aa11a5deb8b459325c0cae4d84c043e595129c2f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 19:27:01 -0400 Subject: [PATCH 037/141] fix --- I2PTunnel.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 641c5795..5f17dd9c 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -539,7 +539,7 @@ namespace client } /** create new */ boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); - m_Sessions.push_back(UDPSession(m_Service, ep, m_Destination, ep, ih, localPort, remotePort)); + m_Sessions.push_back(UDPSession(m_Service, ep, m_Destination, m_Endpoint, ih, localPort, remotePort)); return m_Sessions.back(); } @@ -554,7 +554,9 @@ namespace client { Receive(); LogPrint(eLogDebug, "UDPSession: bound to ", IPSocket.local_endpoint()); - + if (localEndpoint == endpoint) { + SendEndpoint = IPSocket.local_endpoint(); + } } From 287e32aaed3963e167f14d88eadc9f77bbcc05e2 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 19:33:33 -0400 Subject: [PATCH 038/141] logging --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 5f17dd9c..749890bf 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -575,7 +575,7 @@ namespace client if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); dgram->SendDatagramTo(m_Buffer, len, Identity, RemotePort, LocalPort); - LogPrint(eLogDebug, "UDPSession: forward ", len, "B to ", Identity.ToBase32()); + LogPrint(eLogDebug, "UDPSession: forward ", len, "B to ", Identity.ToBase32(), " from ", Destination->GetIdentHash().ToBase32()); } else { LogPrint(eLogWarning, "UDPSession: no datagram destination"); } From bf46c241d02b3306ccd5045f987a49c3516d3426 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 19:38:12 -0400 Subject: [PATCH 039/141] fixes --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 749890bf..7a2c9838 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -594,7 +594,7 @@ namespace client { i2p::datagram::DatagramDestination * dgram = m_Destination->CreateDatagramDestination(); if(dgram) - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), LocalPort); } I2PUDPServerTunnel::~I2PUDPServerTunnel() From bce0e3ebf6c93a7ce8faaf9cfe3df66b944890f5 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 19:45:32 -0400 Subject: [PATCH 040/141] fix --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 7a2c9838..4a5897c4 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -574,7 +574,7 @@ namespace client auto dgram = Destination->GetDatagramDestination(); if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - dgram->SendDatagramTo(m_Buffer, len, Identity, RemotePort, LocalPort); + dgram->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort); LogPrint(eLogDebug, "UDPSession: forward ", len, "B to ", Identity.ToBase32(), " from ", Destination->GetIdentHash().ToBase32()); } else { LogPrint(eLogWarning, "UDPSession: no datagram destination"); From bbfe6b66ef81775c3591906280d1232dcf3434ad Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 19:48:47 -0400 Subject: [PATCH 041/141] fix --- I2PTunnel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 4a5897c4..534086c8 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -574,7 +574,7 @@ namespace client auto dgram = Destination->GetDatagramDestination(); if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - dgram->SendDatagramTo(m_Buffer, len, Identity, LocalPort, RemotePort); + dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); LogPrint(eLogDebug, "UDPSession: forward ", len, "B to ", Identity.ToBase32(), " from ", Destination->GetIdentHash().ToBase32()); } else { LogPrint(eLogWarning, "UDPSession: no datagram destination"); @@ -594,14 +594,14 @@ namespace client { i2p::datagram::DatagramDestination * dgram = m_Destination->CreateDatagramDestination(); if(dgram) - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), LocalPort); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), 0); } I2PUDPServerTunnel::~I2PUDPServerTunnel() { i2p::datagram::DatagramDestination * dgram = m_Destination->GetDatagramDestination(); if (dgram) { - dgram->ResetReceiver(LocalPort); + dgram->ResetReceiver(0); } } From 28627a81dc0707e0fcd5b491c1ff49c382b3ff4d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 20:18:41 -0400 Subject: [PATCH 042/141] update --- I2PTunnel.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 534086c8..87370806 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -540,7 +540,9 @@ namespace client /** create new */ boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); m_Sessions.push_back(UDPSession(m_Service, ep, m_Destination, m_Endpoint, ih, localPort, remotePort)); - return m_Sessions.back(); + auto & s = m_Sessions.back(); + s.SendEndpoint = s.IPSocket.local_endpoint(); + return s; } UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : @@ -552,11 +554,8 @@ namespace client LocalPort(ourPort), RemotePort(theirPort) { + IPSocket.local_endpoint(); Receive(); - LogPrint(eLogDebug, "UDPSession: bound to ", IPSocket.local_endpoint()); - if (localEndpoint == endpoint) { - SendEndpoint = IPSocket.local_endpoint(); - } } @@ -583,6 +582,8 @@ namespace client LogPrint(eLogWarning, "UDPSession: no Local Destination"); } Receive(); + } else { + LogPrint(eLogError, "UDPSession: ", ecode.message()); } } From 72974c85c8bfd9541ca38ab711cbcdc3f85e8953 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 20:23:39 -0400 Subject: [PATCH 043/141] try fix --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 87370806..d5b1a25b 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -570,7 +570,7 @@ namespace client if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); if (Destination) { - auto dgram = Destination->GetDatagramDestination(); + auto dgram = Destination->CreateDatagramDestination(); if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); From 7b5e18d94b5bcf5b1483aa84159d4592262a9b48 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:17:09 -0400 Subject: [PATCH 044/141] changes --- ClientContext.cpp | 2 +- Destination.cpp | 17 +++++------------ Destination.h | 6 +++--- I2PTunnel.cpp | 32 ++++++++++++++------------------ I2PTunnel.h | 4 ++-- 5 files changed, 25 insertions(+), 36 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 3bc6a2d3..c031aae6 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -466,7 +466,7 @@ namespace client std::make_pair( localDestination->GetIdentHash(), port), std::unique_ptr(serverTunnel))).second) { - LogPrint(eLogInfo, "Cleints: I2P Server Forward created for UDP Endpoint ", host, ":", port, " via ",localDestination->GetIdentHash().ToBase32()); + LogPrint(eLogInfo, "Clients: I2P Server Forward created for UDP Endpoint ", host, ":", port, " via ",localDestination->GetIdentHash().ToBase32()); } else { LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); } diff --git a/Destination.cpp b/Destination.cpp index 6f26a84c..d48bee92 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -677,8 +677,6 @@ namespace client ClientDestination::~ClientDestination () { - if (m_DatagramDestination) - delete m_DatagramDestination; } bool ClientDestination::Start () @@ -703,13 +701,8 @@ namespace client m_StreamingDestination = nullptr; for (auto& it: m_StreamingDestinationsByPorts) it.second->Stop (); - if (m_DatagramDestination) - { - auto d = m_DatagramDestination; - m_DatagramDestination = nullptr; - delete d; - } - return true; + m_DatagramDestination = nullptr; + return true; } else return false; @@ -819,10 +812,10 @@ namespace client return dest; } - i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination () + std::shared_ptr ClientDestination::CreateDatagramDestination () { - if (!m_DatagramDestination) - m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ()); + if (m_DatagramDestination == nullptr) + m_DatagramDestination = std::make_shared (GetSharedFromThis ()); return m_DatagramDestination; } diff --git a/Destination.h b/Destination.h index 75c94efc..6cd4c19c 100644 --- a/Destination.h +++ b/Destination.h @@ -164,8 +164,8 @@ namespace client bool IsAcceptingStreams () const; // datagram - i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; - i2p::datagram::DatagramDestination * CreateDatagramDestination (); + std::shared_ptr GetDatagramDestination () const { return m_DatagramDestination; }; + std::shared_ptr CreateDatagramDestination (); // implements LocalDestination const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; @@ -190,7 +190,7 @@ namespace client std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; - i2p::datagram::DatagramDestination * m_DatagramDestination; + std::shared_ptr m_DatagramDestination; public: diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index d5b1a25b..068cbe37 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -539,14 +539,14 @@ namespace client } /** create new */ boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); - m_Sessions.push_back(UDPSession(m_Service, ep, m_Destination, m_Endpoint, ih, localPort, remotePort)); + m_Sessions.push_back(UDPSession(m_Service, ep, m_LocalDest, m_Endpoint, ih, localPort, remotePort)); auto & s = m_Sessions.back(); s.SendEndpoint = s.IPSocket.local_endpoint(); return s; } UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : - Destination(localDestination), + m_Destination(localDestination), IPSocket(ios, localEndpoint), Identity(to), SendEndpoint(endpoint), @@ -569,17 +569,12 @@ namespace client LogPrint(eLogDebug, "UDPSesssion: HandleRecveived"); if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - if (Destination) { - auto dgram = Destination->CreateDatagramDestination(); - if(dgram) { - LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); - LogPrint(eLogDebug, "UDPSession: forward ", len, "B to ", Identity.ToBase32(), " from ", Destination->GetIdentHash().ToBase32()); - } else { - LogPrint(eLogWarning, "UDPSession: no datagram destination"); - } + auto dgram = m_Destination->GetDatagramDestination(); + if(dgram) { + LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); } else { - LogPrint(eLogWarning, "UDPSession: no Local Destination"); + LogPrint(eLogWarning, "UDPSession: no datagram destination"); } Receive(); } else { @@ -590,20 +585,21 @@ namespace client I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, boost::asio::io_service & service) : LocalPort(port), m_Endpoint(forwardTo), - m_Service(service), - m_Destination(localDestination) + m_Service(service) { - i2p::datagram::DatagramDestination * dgram = m_Destination->CreateDatagramDestination(); - if(dgram) - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), 0); + m_LocalDest = localDestination; + m_LocalDest->Start(); + auto dgram = m_LocalDest->CreateDatagramDestination(); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), 0); } I2PUDPServerTunnel::~I2PUDPServerTunnel() { - i2p::datagram::DatagramDestination * dgram = m_Destination->GetDatagramDestination(); + auto dgram = m_LocalDest->GetDatagramDestination(); if (dgram) { dgram->ResetReceiver(0); } + LogPrint(eLogInfo, "UDPServer: done"); } I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, boost::asio::io_service & service) : diff --git a/I2PTunnel.h b/I2PTunnel.h index e50c47f7..54ea09e9 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -140,7 +140,7 @@ namespace client struct UDPSession { - std::shared_ptr Destination; + std::shared_ptr m_Destination; boost::asio::ip::udp::socket IPSocket; i2p::data::IdentHash Identity; boost::asio::ip::udp::endpoint FromEndpoint; @@ -177,7 +177,7 @@ namespace client std::mutex m_SessionsMutex; std::vector m_Sessions; boost::asio::io_service & m_Service; - std::shared_ptr m_Destination; + std::shared_ptr m_LocalDest; uint8_t m_Buffer[I2P_UDP_MAX_MTU]; }; From da82b14307d3df84b265f413b8deca324f95ed2d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:28:24 -0400 Subject: [PATCH 045/141] changes --- I2PTunnel.cpp | 2 +- I2PTunnel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 068cbe37..531eea87 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -569,7 +569,7 @@ namespace client LogPrint(eLogDebug, "UDPSesssion: HandleRecveived"); if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - auto dgram = m_Destination->GetDatagramDestination(); + auto dgram = m_Destination.get()->GetDatagramDestination(); if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); diff --git a/I2PTunnel.h b/I2PTunnel.h index 54ea09e9..cc78722c 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -136,7 +136,7 @@ namespace client const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; /** max size for i2p udp */ - const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; + const size_t I2P_UDP_MAX_MTU = 4000; struct UDPSession { From ff6d66b96ed3ba90c008a43b11e994e509b2a7ec Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:40:21 -0400 Subject: [PATCH 046/141] init addressbook first --- ClientContext.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index c031aae6..de06a465 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -40,6 +40,9 @@ namespace client m_SharedLocalDestination->Start (); } + + m_AddressBook.Start (); + if ( m_ServiceThread == nullptr ) { m_ServiceThread = new std::thread([&] () { LogPrint(eLogInfo, "ClientContext: starting service"); @@ -48,8 +51,6 @@ namespace client }); ScheduleCleanupUDP(); } - - m_AddressBook.Start (); std::shared_ptr localDestination; bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); From 808b758cd71d169966c6b9051bdde51cab7689ea Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:45:08 -0400 Subject: [PATCH 047/141] fix --- AddressBook.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index b3f0f1ce..bfb44be8 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -544,7 +544,7 @@ namespace client if (dest) { auto datagram = dest->GetDatagramDestination (); - if (!datagram) + if (datagram == nullptr) datagram = dest->CreateDatagramDestination (); datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), From 7ef7ef03dd62ca056ae6ee5d9c77ff6a19347cb1 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:47:56 -0400 Subject: [PATCH 048/141] fix --- AddressBook.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index bfb44be8..2c4fa1b5 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -543,9 +543,7 @@ namespace client auto dest = i2p::client::context.GetSharedLocalDestination (); if (dest) { - auto datagram = dest->GetDatagramDestination (); - if (datagram == nullptr) - datagram = dest->CreateDatagramDestination (); + auto datagram = dest->CreateDatagramDestination (); datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), ADDRESS_RESPONSE_DATAGRAM_PORT); From d159d497003e584ac2bfc6818fd7b586ff940a74 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:51:32 -0400 Subject: [PATCH 049/141] os x fix --- Datagram.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index 2015622c..b950d46b 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -22,29 +22,30 @@ namespace datagram void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) { + auto owner = m_Owner.get(); uint8_t buf[MAX_DATAGRAM_SIZE]; - auto identityLen = m_Owner->GetIdentity ()->ToBuffer (buf, MAX_DATAGRAM_SIZE); + auto identityLen = owner->GetIdentity ()->ToBuffer (buf, MAX_DATAGRAM_SIZE); uint8_t * signature = buf + identityLen; - auto signatureLen = m_Owner->GetIdentity ()->GetSignatureLen (); + auto signatureLen = owner->GetIdentity ()->GetSignatureLen (); uint8_t * buf1 = signature + signatureLen; size_t headerLen = identityLen + signatureLen; memcpy (buf1, payload, len); - if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + if (owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) { uint8_t hash[32]; SHA256(buf1, len, hash); - m_Owner->Sign (hash, 32, signature); + owner->Sign (hash, 32, signature); } else - m_Owner->Sign (buf1, len, signature); + owner->Sign (buf1, len, signature); auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort); - auto remote = m_Owner->FindLeaseSet (ident); + auto remote = owner->FindLeaseSet (ident); if (remote) - m_Owner->GetService ().post (std::bind (&DatagramDestination::SendMsg, this, msg, remote)); + owner->GetService ().post (std::bind (&DatagramDestination::SendMsg, this, msg, remote)); else - m_Owner->RequestDestination (ident, std::bind (&DatagramDestination::HandleLeaseSetRequestComplete, this, std::placeholders::_1, msg)); + owner->RequestDestination (ident, std::bind (&DatagramDestination::HandleLeaseSetRequestComplete, this, std::placeholders::_1, msg)); } void DatagramDestination::HandleLeaseSetRequestComplete (std::shared_ptr remote, std::shared_ptr msg) From 1bba5d5c9409998c45b45df797995a0d67db0078 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:55:00 -0400 Subject: [PATCH 050/141] osx fix --- Datagram.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index b950d46b..ebb5c993 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -23,15 +23,16 @@ namespace datagram void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) { auto owner = m_Owner.get(); + auto i = owner->GetIdentity().get(); uint8_t buf[MAX_DATAGRAM_SIZE]; - auto identityLen = owner->GetIdentity ()->ToBuffer (buf, MAX_DATAGRAM_SIZE); + auto identityLen = i->ToBuffer (buf, MAX_DATAGRAM_SIZE); uint8_t * signature = buf + identityLen; - auto signatureLen = owner->GetIdentity ()->GetSignatureLen (); + auto signatureLen = i->GetSignatureLen (); uint8_t * buf1 = signature + signatureLen; size_t headerLen = identityLen + signatureLen; memcpy (buf1, payload, len); - if (owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) + if (i->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) { uint8_t hash[32]; SHA256(buf1, len, hash); From bc439cc47fef983f27aa932ba702793cf0774daf Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 21:57:36 -0400 Subject: [PATCH 051/141] osx fix --- Datagram.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Datagram.cpp b/Datagram.cpp index ebb5c993..c877902b 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -23,7 +23,7 @@ namespace datagram void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) { auto owner = m_Owner.get(); - auto i = owner->GetIdentity().get(); + auto i = owner->GetIdentity(); uint8_t buf[MAX_DATAGRAM_SIZE]; auto identityLen = i->ToBuffer (buf, MAX_DATAGRAM_SIZE); uint8_t * signature = buf + identityLen; From b1e3f887047c08bef5b4b9dc73156796c8aec675 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:00:31 -0400 Subject: [PATCH 052/141] osx fix --- Datagram.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Datagram.cpp b/Datagram.cpp index c877902b..dbe4d978 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -22,7 +22,7 @@ namespace datagram void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) { - auto owner = m_Owner.get(); + auto owner = m_Owner; auto i = owner->GetIdentity(); uint8_t buf[MAX_DATAGRAM_SIZE]; auto identityLen = i->ToBuffer (buf, MAX_DATAGRAM_SIZE); From 47ebb6ae6c1692bf8d4e21ca79c08e03aab9e3eb Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:11:41 -0400 Subject: [PATCH 053/141] osx fix --- ClientContext.cpp | 21 +++++++++++---------- I2PTunnel.cpp | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index de06a465..0b9b1f60 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -43,15 +43,6 @@ namespace client m_AddressBook.Start (); - if ( m_ServiceThread == nullptr ) { - m_ServiceThread = new std::thread([&] () { - LogPrint(eLogInfo, "ClientContext: starting service"); - m_Service.run(); - LogPrint(eLogError, "ClientContext: service died"); - }); - ScheduleCleanupUDP(); - } - std::shared_ptr localDestination; bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); if (httproxy) { @@ -74,7 +65,7 @@ namespace client LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); } } - + bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); if (socksproxy) { std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); @@ -100,6 +91,16 @@ namespace client // I2P tunnels ReadTunnels (); + if ( m_ServiceThread == nullptr ) { + m_ServiceThread = new std::thread([&] () { + LogPrint(eLogInfo, "ClientContext: starting service"); + m_Service.run(); + LogPrint(eLogError, "ClientContext: service died"); + }); + ScheduleCleanupUDP(); + } + + // SAM bool sam; i2p::config::GetOption("sam.enabled", sam); if (sam) { diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 531eea87..a2811695 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -628,6 +628,7 @@ namespace client LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); m_RemoteIdent = new i2p::data::IdentHash; m_RemoteIdent->Fill(0); + while(!context.GetAddressBook().GetIdentHash(m_RemoteDest, *m_RemoteIdent) && !m_cancel_resolve) { LogPrint(eLogWarning, "UDP Tunnel: failed to lookup ", m_RemoteDest); std::this_thread::sleep_for(std::chrono::seconds(1)); From 9062bf14b69db802e379a9a8ce160377addb2540 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:16:35 -0400 Subject: [PATCH 054/141] osx fix --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index a2811695..0982c388 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -638,7 +638,7 @@ namespace client return; } LogPrint(eLogInfo, "UDP Tunnel: resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); - auto dgram = m_LocalDest->CreateDatagramDestination(); + auto dgram = m_LocalDest->CreateDatagramDestination().get(); // delete existing session if(m_Session) delete m_Session; boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); From 0c709f431f1e0fb20fbbdff1fbd731b1c35f5398 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:18:59 -0400 Subject: [PATCH 055/141] osx fix --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 0982c388..7f03311f 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -569,7 +569,7 @@ namespace client LogPrint(eLogDebug, "UDPSesssion: HandleRecveived"); if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - auto dgram = m_Destination.get()->GetDatagramDestination(); + auto dgram = m_Destination.get()->GetDatagramDestination().get(); if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); From 211660eb3d368e38fa4a4949a75130f4a679c4e0 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:23:27 -0400 Subject: [PATCH 056/141] osx fix --- I2PTunnel.cpp | 4 ++-- I2PTunnel.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 7f03311f..346baf29 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -545,7 +545,7 @@ namespace client return s; } - UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : + UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : m_Destination(localDestination), IPSocket(ios, localEndpoint), Identity(to), @@ -569,7 +569,7 @@ namespace client LogPrint(eLogDebug, "UDPSesssion: HandleRecveived"); if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - auto dgram = m_Destination.get()->GetDatagramDestination().get(); + auto dgram = m_Destination->GetDatagramDestination(); if(dgram) { LastActivity = i2p::util::GetMillisecondsSinceEpoch(); dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); diff --git a/I2PTunnel.h b/I2PTunnel.h index cc78722c..75eeaaef 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -152,7 +152,7 @@ namespace client uint8_t m_Buffer[I2P_UDP_MAX_MTU]; - UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); + UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); void HandleReceived(const boost::system::error_code & ecode, std::size_t len); void Receive(); From 3f63732c31bb42a9f7ebf2b26fcd879aded57341 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:26:30 -0400 Subject: [PATCH 057/141] osx fix --- I2PTunnel.cpp | 2 +- I2PTunnel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 346baf29..4cae9cb7 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -546,7 +546,7 @@ namespace client } UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : - m_Destination(localDestination), + m_Destination(localDestination.get()), IPSocket(ios, localEndpoint), Identity(to), SendEndpoint(endpoint), diff --git a/I2PTunnel.h b/I2PTunnel.h index 75eeaaef..ca5c8cc9 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -140,7 +140,7 @@ namespace client struct UDPSession { - std::shared_ptr m_Destination; + i2p::client::ClientDestination * m_Destination; boost::asio::ip::udp::socket IPSocket; i2p::data::IdentHash Identity; boost::asio::ip::udp::endpoint FromEndpoint; From b977050cafb324ebc2eabbcee3c2ecc78dd92e53 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:29:55 -0400 Subject: [PATCH 058/141] osx fix --- Destination.cpp | 4 ++-- Destination.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index d48bee92..56681884 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -812,10 +812,10 @@ namespace client return dest; } - std::shared_ptr ClientDestination::CreateDatagramDestination () + i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination () { if (m_DatagramDestination == nullptr) - m_DatagramDestination = std::make_shared (GetSharedFromThis ()); + m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ()); return m_DatagramDestination; } diff --git a/Destination.h b/Destination.h index 6cd4c19c..3faab9cc 100644 --- a/Destination.h +++ b/Destination.h @@ -164,8 +164,8 @@ namespace client bool IsAcceptingStreams () const; // datagram - std::shared_ptr GetDatagramDestination () const { return m_DatagramDestination; }; - std::shared_ptr CreateDatagramDestination (); + i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; + i2p::datagram::DatagramDestination * CreateDatagramDestination (); // implements LocalDestination const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; @@ -190,7 +190,7 @@ namespace client std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; - std::shared_ptr m_DatagramDestination; + i2p::datagram::DatagramDestination * m_DatagramDestination; public: From 6bb9de5a962ebfc706300ec58e948718b5462d4e Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:34:48 -0400 Subject: [PATCH 059/141] osx fix --- AddressBook.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 2c4fa1b5..78e9731f 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -543,7 +543,9 @@ namespace client auto dest = i2p::client::context.GetSharedLocalDestination (); if (dest) { - auto datagram = dest->CreateDatagramDestination (); + + auto datagram = dest->GetDatagramDestination (); + if(datagram == nullptr) datagram = dest->CreateDatagramDestination(); datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), ADDRESS_RESPONSE_DATAGRAM_PORT); From 5b00cb1e644deecb3e1e751a36f54ca85858e339 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:38:41 -0400 Subject: [PATCH 060/141] osx fix --- I2PTunnel.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 4cae9cb7..ac64186c 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -614,7 +614,11 @@ namespace client RemotePort(remotePort), m_cancel_resolve(false) { - + auto dgram = m_LocalDest->CreateDatagramDestination(); + dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, + std::placeholders::_5)); } @@ -638,15 +642,10 @@ namespace client return; } LogPrint(eLogInfo, "UDP Tunnel: resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); - auto dgram = m_LocalDest->CreateDatagramDestination().get(); // delete existing session if(m_Session) delete m_Session; boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); m_Session = new UDPSession(m_Service, m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); - dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5)); } void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) From bee34a3222c8ced5c58eb140e35017d9f7315c7c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 21 Aug 2016 22:54:06 -0400 Subject: [PATCH 061/141] fix --- Datagram.cpp | 2 +- Datagram.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index dbe4d978..aed831b7 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -12,7 +12,7 @@ namespace i2p namespace datagram { DatagramDestination::DatagramDestination (std::shared_ptr owner): - m_Owner (owner), m_Receiver (nullptr) + m_Owner (owner.get()), m_Receiver (nullptr) { } diff --git a/Datagram.h b/Datagram.h index c593fad2..51fd3553 100644 --- a/Datagram.h +++ b/Datagram.h @@ -47,7 +47,7 @@ namespace datagram private: - std::shared_ptr m_Owner; + i2p::client::ClientDestination * m_Owner; Receiver m_Receiver; // default std::map m_ReceiversByPorts; From f5e28992750a2d3497e8c761a3c4cf6d4ef1cd00 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 13:04:36 -0400 Subject: [PATCH 062/141] post work to io service --- ClientContext.cpp | 10 ++++++---- I2PTunnel.cpp | 19 ++++++++++++------- I2PTunnel.h | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 0b9b1f60..6b7e58bc 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -87,9 +87,6 @@ namespace client LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); } } - - // I2P tunnels - ReadTunnels (); if ( m_ServiceThread == nullptr ) { m_ServiceThread = new std::thread([&] () { @@ -99,7 +96,11 @@ namespace client }); ScheduleCleanupUDP(); } - + + + // I2P tunnels + ReadTunnels (); + // SAM bool sam; i2p::config::GetOption("sam.enabled", sam); @@ -468,6 +469,7 @@ namespace client std::make_pair( localDestination->GetIdentHash(), port), std::unique_ptr(serverTunnel))).second) { + serverTunnel->Start(); LogPrint(eLogInfo, "Clients: I2P Server Forward created for UDP Endpoint ", host, ":", port, " via ",localDestination->GetIdentHash().ToBase32()); } else { LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index ac64186c..ea0f6122 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -569,13 +569,13 @@ namespace client LogPrint(eLogDebug, "UDPSesssion: HandleRecveived"); if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - auto dgram = m_Destination->GetDatagramDestination(); - if(dgram) { - LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); - } else { - LogPrint(eLogWarning, "UDPSession: no datagram destination"); - } + LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + m_Destination->GetService().post([&, len] () { + auto dgram = m_Destination->GetDatagramDestination(); + if (dgram) { + dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); + } + }); Receive(); } else { LogPrint(eLogError, "UDPSession: ", ecode.message()); @@ -602,6 +602,10 @@ namespace client LogPrint(eLogInfo, "UDPServer: done"); } + void I2PUDPServerTunnel::Start() { + m_LocalDest->Start(); + } + I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, boost::asio::io_service & service) : m_Session(nullptr), m_RemoteDest(remoteDest), @@ -624,6 +628,7 @@ namespace client void I2PUDPClientTunnel::Start() { + m_LocalDest->Start(); if (m_ResolveThread == nullptr) m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); } diff --git a/I2PTunnel.h b/I2PTunnel.h index ca5c8cc9..64e68640 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -167,7 +167,7 @@ namespace client ~I2PUDPServerTunnel(); /** expire stale udp conversations */ void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); - + void Start(); private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSession & ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); From 7f7acd8bde75b1b0e561e9c01ee75ce9c470ee11 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 13:54:00 -0400 Subject: [PATCH 063/141] fixes --- ClientContext.cpp | 4 ++-- I2PTunnel.cpp | 53 +++++++++++++++++++++++------------------------ I2PTunnel.h | 17 +++++++-------- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 6b7e58bc..13c8690a 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -412,7 +412,7 @@ namespace client if (!localDestination) { localDestination = m_SharedLocalDestination; } - auto clientTunnel = new I2PUDPClientTunnel(name, dest, end, localDestination, destinationPort, m_Service); + auto clientTunnel = new I2PUDPClientTunnel(name, dest, end, localDestination, destinationPort); if(m_ClientForwards.insert(std::make_pair(end, std::unique_ptr(clientTunnel))).second) { clientTunnel->Start(); } else { @@ -462,7 +462,7 @@ namespace client // udp server tunnel // TODO: ipv6 and hostnames boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::address::from_string(host), port); - I2PUDPServerTunnel * serverTunnel = new I2PUDPServerTunnel(name, localDestination, endpoint, port, m_Service); + I2PUDPServerTunnel * serverTunnel = new I2PUDPServerTunnel(name, localDestination, endpoint, port); std::lock_guard lock(m_ForwardsMutex); if(m_ServerForwards.insert( std::make_pair( diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index ea0f6122..7dde2bdf 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -514,47 +514,45 @@ namespace client void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { std::lock_guard lock(m_SessionsMutex); - auto & session = ObtainUDPSession(from, toPort, fromPort); - session.IPSocket.send_to(boost::asio::buffer(buf, len), m_Endpoint); - session.LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + auto session = ObtainUDPSession(from, toPort, fromPort); + session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Endpoint); + session->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); } void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) { std::lock_guard lock(m_SessionsMutex); uint64_t now = i2p::util::GetMillisecondsSinceEpoch(); - std::remove_if(m_Sessions.begin(), m_Sessions.end(), [now, delta](const UDPSession & u) -> bool { - return now - u.LastActivity >= delta; + std::remove_if(m_Sessions.begin(), m_Sessions.end(), [now, delta](const UDPSession * u) -> bool { + return now - u->LastActivity >= delta; }); } - UDPSession & I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) + UDPSession * I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) { auto ih = from.GetIdentHash(); - for ( UDPSession & s : m_Sessions ) { - if ( s.Identity == ih) { + for ( UDPSession * s : m_Sessions ) { + if ( s->Identity == ih) { /** found existing */ return s; } } /** create new */ boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); - m_Sessions.push_back(UDPSession(m_Service, ep, m_LocalDest, m_Endpoint, ih, localPort, remotePort)); - auto & s = m_Sessions.back(); - s.SendEndpoint = s.IPSocket.local_endpoint(); - return s; + m_Sessions.push_back(new UDPSession(ep, m_LocalDest, m_Endpoint, ih, localPort, remotePort)); + return m_Sessions.back(); } - UDPSession::UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : - m_Destination(localDestination.get()), - IPSocket(ios, localEndpoint), + UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : + m_Destination(localDestination->GetDatagramDestination()), + m_Service(localDestination->GetService()), + IPSocket(localDestination->GetService(), localEndpoint), Identity(to), SendEndpoint(endpoint), LastActivity(i2p::util::GetMillisecondsSinceEpoch()), LocalPort(ourPort), RemotePort(theirPort) { - IPSocket.local_endpoint(); Receive(); } @@ -570,22 +568,24 @@ namespace client if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - m_Destination->GetService().post([&, len] () { - auto dgram = m_Destination->GetDatagramDestination(); - if (dgram) { - dgram->SendDatagramTo(m_Buffer, len, Identity, 0, 0); - } + uint8_t * data = new uint8_t[len]; + memcpy(data, m_Buffer, len); + m_Service.post([&,len, data] () { + m_Destination->SendDatagramTo(data, len, Identity, 0, 0); + delete data; }); + Receive(); } else { LogPrint(eLogError, "UDPSession: ", ecode.message()); } } + - I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, boost::asio::io_service & service) : + + I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : LocalPort(port), - m_Endpoint(forwardTo), - m_Service(service) + m_Endpoint(forwardTo) { m_LocalDest = localDestination; m_LocalDest->Start(); @@ -606,14 +606,13 @@ namespace client m_LocalDest->Start(); } - I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, boost::asio::io_service & service) : + I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort) : m_Session(nullptr), m_RemoteDest(remoteDest), m_RemoteIdent(nullptr), m_LocalDest(localDestination), m_LocalEndpoint(localEndpoint), m_ResolveThread(nullptr), - m_Service(service), LocalPort(localEndpoint.port()), RemotePort(remotePort), m_cancel_resolve(false) @@ -650,7 +649,7 @@ namespace client // delete existing session if(m_Session) delete m_Session; boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); - m_Session = new UDPSession(m_Service, m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); + m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); } void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) diff --git a/I2PTunnel.h b/I2PTunnel.h index 64e68640..dfd364f0 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -140,7 +140,8 @@ namespace client struct UDPSession { - i2p::client::ClientDestination * m_Destination; + i2p::datagram::DatagramDestination * m_Destination; + boost::asio::io_service & m_Service; boost::asio::ip::udp::socket IPSocket; i2p::data::IdentHash Identity; boost::asio::ip::udp::endpoint FromEndpoint; @@ -151,32 +152,31 @@ namespace client uint16_t RemotePort; uint8_t m_Buffer[I2P_UDP_MAX_MTU]; + uint8_t * m_Forward; - UDPSession(boost::asio::io_service & ios, boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); + UDPSession(boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); void HandleReceived(const boost::system::error_code & ecode, std::size_t len); void Receive(); - }; /** server side udp tunnel, many i2p inbound to 1 ip outbound */ class I2PUDPServerTunnel { public: - I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port, boost::asio::io_service & service); + I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port); ~I2PUDPServerTunnel(); /** expire stale udp conversations */ void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); void Start(); private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - UDPSession & ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); + UDPSession * ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); private: const uint16_t LocalPort; boost::asio::ip::udp::endpoint m_Endpoint; std::mutex m_SessionsMutex; - std::vector m_Sessions; - boost::asio::io_service & m_Service; + std::vector m_Sessions; std::shared_ptr m_LocalDest; uint8_t m_Buffer[I2P_UDP_MAX_MTU]; }; @@ -184,7 +184,7 @@ namespace client class I2PUDPClientTunnel { public: - I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort, boost::asio::io_service & service); + I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort); ~I2PUDPClientTunnel(); void Start(); private: @@ -196,7 +196,6 @@ namespace client const boost::asio::ip::udp::endpoint m_LocalEndpoint; i2p::data::IdentHash * m_RemoteIdent; std::thread * m_ResolveThread; - boost::asio::io_service & m_Service; uint16_t LocalPort; uint16_t RemotePort; bool m_cancel_resolve; From be12739342ad0945166070e59247251a201faf84 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 13:55:44 -0400 Subject: [PATCH 064/141] fix --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 7dde2bdf..93aa1cd6 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -572,7 +572,7 @@ namespace client memcpy(data, m_Buffer, len); m_Service.post([&,len, data] () { m_Destination->SendDatagramTo(data, len, Identity, 0, 0); - delete data; + delete [] data; }); Receive(); From 979575c311ea3391043a3e01a4fa11da15eceb4d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 13:59:51 -0400 Subject: [PATCH 065/141] fix --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 93aa1cd6..7172b23b 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -659,7 +659,7 @@ namespace client if(m_Session) { // tell session LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32(), " via ", m_Session->SendEndpoint); - m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Session->SendEndpoint); + m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Session->FromEndpoint); } else { LogPrint(eLogWarning, "UDP Client: no session"); } From 1d7d7cf9a02e1c889b912fb12cdd92af237f34af Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 17:19:22 -0400 Subject: [PATCH 066/141] more changes --- ClientContext.cpp | 3 --- I2PTunnel.cpp | 12 ++++++------ I2PTunnel.h | 3 +-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 13c8690a..3b814260 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -406,9 +406,6 @@ namespace client // udp client // TODO: ip6 and hostnames boost::asio::ip::udp::endpoint end(boost::asio::ip::address::from_string(address), port); - if(destinationPort == 0) { - destinationPort = port; - } if (!localDestination) { localDestination = m_SharedLocalDestination; } diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 7172b23b..6cbb3668 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -534,6 +534,7 @@ namespace client for ( UDPSession * s : m_Sessions ) { if ( s->Identity == ih) { /** found existing */ + LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint()); return s; } } @@ -558,20 +559,19 @@ namespace client void UDPSession::Receive() { - LogPrint(eLogDebug, "UDPSesssion: Recveive"); + LogPrint(eLogDebug, "UDPSession: Receive"); IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); } void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) { - LogPrint(eLogDebug, "UDPSesssion: HandleRecveived"); if(!ecode) { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); LastActivity = i2p::util::GetMillisecondsSinceEpoch(); uint8_t * data = new uint8_t[len]; memcpy(data, m_Buffer, len); m_Service.post([&,len, data] () { - m_Destination->SendDatagramTo(data, len, Identity, 0, 0); + m_Destination->SendDatagramTo(data, len, Identity, LocalPort, RemotePort); delete [] data; }); @@ -590,14 +590,14 @@ namespace client m_LocalDest = localDestination; m_LocalDest->Start(); auto dgram = m_LocalDest->CreateDatagramDestination(); - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), 0); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), LocalPort); } I2PUDPServerTunnel::~I2PUDPServerTunnel() { auto dgram = m_LocalDest->GetDatagramDestination(); if (dgram) { - dgram->ResetReceiver(0); + dgram->ResetReceiver(LocalPort); } LogPrint(eLogInfo, "UDPServer: done"); } @@ -658,7 +658,7 @@ namespace client // address match if(m_Session) { // tell session - LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32(), " via ", m_Session->SendEndpoint); + LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32()); m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Session->FromEndpoint); } else { LogPrint(eLogWarning, "UDP Client: no session"); diff --git a/I2PTunnel.h b/I2PTunnel.h index dfd364f0..63341679 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -136,7 +136,7 @@ namespace client const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; /** max size for i2p udp */ - const size_t I2P_UDP_MAX_MTU = 4000; + const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; struct UDPSession { @@ -152,7 +152,6 @@ namespace client uint16_t RemotePort; uint8_t m_Buffer[I2P_UDP_MAX_MTU]; - uint8_t * m_Forward; UDPSession(boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash ident, uint16_t ourPort, uint16_t theirPort); From e8195b78bad872411e73bcd598e1229eeaaa3c7e Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 17:26:43 -0400 Subject: [PATCH 067/141] fix --- I2PTunnel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 6cbb3668..146c6d7f 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -571,7 +571,7 @@ namespace client uint8_t * data = new uint8_t[len]; memcpy(data, m_Buffer, len); m_Service.post([&,len, data] () { - m_Destination->SendDatagramTo(data, len, Identity, LocalPort, RemotePort); + m_Destination->SendDatagramTo(data, len, Identity, 0, 0); delete [] data; }); @@ -597,7 +597,7 @@ namespace client { auto dgram = m_LocalDest->GetDatagramDestination(); if (dgram) { - dgram->ResetReceiver(LocalPort); + dgram->ResetReceiver(0); } LogPrint(eLogInfo, "UDPServer: done"); } From 42b15e8bbe3381a363e98433e01c542cf3ddf148 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 17:31:23 -0400 Subject: [PATCH 068/141] fix --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 146c6d7f..9c6ac89d 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -590,7 +590,7 @@ namespace client m_LocalDest = localDestination; m_LocalDest->Start(); auto dgram = m_LocalDest->CreateDatagramDestination(); - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), LocalPort); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), 0); } I2PUDPServerTunnel::~I2PUDPServerTunnel() From 065d01bcf6398049f91ca2d3e00a06e70bf47d55 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 22 Aug 2016 18:29:12 -0400 Subject: [PATCH 069/141] logging update --- I2PTunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 9c6ac89d..69360c2c 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -534,7 +534,7 @@ namespace client for ( UDPSession * s : m_Sessions ) { if ( s->Identity == ih) { /** found existing */ - LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint()); + LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); return s; } } From b02677ee2156797d5e23943e04f78b8e4b1d1125 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Aug 2016 11:21:49 -0400 Subject: [PATCH 070/141] common termination timer for all SSU sessions --- NTCPSession.cpp | 1 - NTCPSession.h | 5 +--- SSU.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++-- SSU.h | 10 +++++++- SSUSession.cpp | 44 ++++++++++------------------------ SSUSession.h | 7 ++---- TransportSession.h | 7 +++++- 7 files changed, 89 insertions(+), 45 deletions(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index a1b26aca..41252f97 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -22,7 +22,6 @@ namespace transport TransportSession (in_RemoteRouter, NTCP_TERMINATION_TIMEOUT), m_Server (server), m_Socket (m_Server.GetService ()), m_IsEstablished (false), m_IsTerminated (false), - m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()), m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_IsSending (false) { m_Establisher = new Establisher; diff --git a/NTCPSession.h b/NTCPSession.h index adf33553..a3d95c62 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -54,9 +54,7 @@ namespace transport void Done (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; - bool IsEstablished () const { return m_IsEstablished; }; - bool IsTerminationTimeoutExpired (uint64_t ts) const - { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; + bool IsEstablished () const { return m_IsEstablished; }; void ClientLogin (); void ServerLogin (); @@ -103,7 +101,6 @@ namespace transport NTCPServer& m_Server; boost::asio::ip::tcp::socket m_Socket; bool m_IsEstablished, m_IsTerminated; - uint64_t m_LastActivityTimestamp; i2p::crypto::CBCDecryption m_Decryption; i2p::crypto::CBCEncryption m_Encryption; diff --git a/SSU.cpp b/SSU.cpp index 0c3662d3..3d3fefdd 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -17,7 +17,8 @@ namespace transport m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint), m_SocketV6 (m_ReceiversService), - m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service) + m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), + m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) { m_SocketV6.open (boost::asio::ip::udp::v6()); m_SocketV6.set_option (boost::asio::ip::v6_only (true)); @@ -32,7 +33,8 @@ namespace transport m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), m_Socket (m_ReceiversService, m_Endpoint), m_SocketV6 (m_ReceiversService), - m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service) + m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), + m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) { m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (65535)); @@ -59,11 +61,13 @@ namespace transport { m_Thread = new std::thread (std::bind (&SSUServer::Run, this)); m_ReceiversService.post (std::bind (&SSUServer::Receive, this)); + ScheduleTermination (); } if (context.SupportsV6 ()) { m_ThreadV6 = new std::thread (std::bind (&SSUServer::RunV6, this)); m_ReceiversService.post (std::bind (&SSUServer::ReceiveV6, this)); + ScheduleTerminationV6 (); } SchedulePeerTestsCleanupTimer (); ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers @@ -640,6 +644,58 @@ namespace transport SchedulePeerTestsCleanupTimer (); } } + + void SSUServer::ScheduleTermination () + { + m_TerminationTimer.expires_from_now (boost::posix_time::seconds(SSU_TERMINATION_CHECK_TIMEOUT)); + m_TerminationTimer.async_wait (std::bind (&SSUServer::HandleTerminationTimer, + this, std::placeholders::_1)); + } + + void SSUServer::HandleTerminationTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + for (auto& it: m_Sessions) + if (it.second->IsTerminationTimeoutExpired (ts)) + { + auto session = it.second; + m_Service.post ([session] + { + LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); + session->Failed (); + }); + } + ScheduleTermination (); + } + } + + void SSUServer::ScheduleTerminationV6 () + { + m_TerminationTimerV6.expires_from_now (boost::posix_time::seconds(SSU_TERMINATION_CHECK_TIMEOUT)); + m_TerminationTimerV6.async_wait (std::bind (&SSUServer::HandleTerminationTimerV6, + this, std::placeholders::_1)); + } + + void SSUServer::HandleTerminationTimerV6 (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto ts = i2p::util::GetSecondsSinceEpoch (); + for (auto& it: m_SessionsV6) + if (it.second->IsTerminationTimeoutExpired (ts)) + { + auto session = it.second; + m_ServiceV6.post ([session] + { + LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); + session->Failed (); + }); + } + ScheduleTerminationV6 (); + } + } } } diff --git a/SSU.h b/SSU.h index d779c025..182fa0eb 100644 --- a/SSU.h +++ b/SSU.h @@ -23,6 +23,7 @@ namespace transport const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds const int SSU_PEER_TEST_TIMEOUT = 60; // 60 seconds const int SSU_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour + const int SSU_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds const size_t SSU_MAX_NUM_INTRODUCERS = 3; struct SSUPacket @@ -90,6 +91,12 @@ namespace transport void SchedulePeerTestsCleanupTimer (); void HandlePeerTestsCleanupTimer (const boost::system::error_code& ecode); + // timer + void ScheduleTermination (); + void HandleTerminationTimer (const boost::system::error_code& ecode); + void ScheduleTerminationV6 (); + void HandleTerminationTimerV6 (const boost::system::error_code& ecode); + private: struct PeerTest @@ -106,7 +113,8 @@ namespace transport boost::asio::io_service::work m_Work, m_WorkV6, m_ReceiversWork; boost::asio::ip::udp::endpoint m_Endpoint, m_EndpointV6; boost::asio::ip::udp::socket m_Socket, m_SocketV6; - boost::asio::deadline_timer m_IntroducersUpdateTimer, m_PeerTestsCleanupTimer; + boost::asio::deadline_timer m_IntroducersUpdateTimer, m_PeerTestsCleanupTimer, + m_TerminationTimer, m_TerminationTimerV6; std::list m_Introducers; // introducers we are connected to std::map > m_Sessions, m_SessionsV6; std::map m_Relays; // we are introducer diff --git a/SSUSession.cpp b/SSUSession.cpp index bf4058a5..9245f652 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -14,7 +14,7 @@ namespace transport SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, std::shared_ptr router, bool peerTest ): TransportSession (router, SSU_TERMINATION_TIMEOUT), - m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_Timer (GetService ()), + m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_ConnectTimer (GetService ()), m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0),m_Data (*this), m_IsDataReceived (false) { @@ -97,7 +97,7 @@ namespace transport { if (!len) return; // ignore zero-length packets if (m_State == eSessionStateEstablished) - ScheduleTermination (); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first DecryptSessionKey (buf, len); @@ -229,7 +229,7 @@ namespace transport } LogPrint (eLogDebug, "SSU message: session created"); - m_Timer.cancel (); // connect timer + m_ConnectTimer.cancel (); // connect timer SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time auto headerSize = GetSSUHeaderSize (buf); if (headerSize >= len) @@ -804,9 +804,9 @@ namespace transport void SSUSession::ScheduleConnectTimer () { - m_Timer.cancel (); - m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); - m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer, + m_ConnectTimer.cancel (); + m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); + m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, shared_from_this (), std::placeholders::_1)); } @@ -826,8 +826,8 @@ namespace transport if (m_State == eSessionStateUnknown) { // set connect timer - m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); - m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer, + m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); + m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, shared_from_this (), std::placeholders::_1)); } uint32_t nonce; @@ -840,8 +840,8 @@ namespace transport { m_State = eSessionStateIntroduced; // set connect timer - m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); - m_Timer.async_wait (std::bind (&SSUSession::HandleConnectTimer, + m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); + m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, shared_from_this (), std::placeholders::_1)); } @@ -851,7 +851,7 @@ namespace transport SendSesionDestroyed (); transports.PeerDisconnected (shared_from_this ()); m_Data.Stop (); - m_Timer.cancel (); + m_ConnectTimer.cancel (); } void SSUSession::Done () @@ -868,7 +868,7 @@ namespace transport transports.PeerConnected (shared_from_this ()); if (m_IsPeerTest) SendPeerTest (); - ScheduleTermination (); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); } void SSUSession::Failed () @@ -880,24 +880,6 @@ namespace transport } } - void SSUSession::ScheduleTermination () - { - m_Timer.cancel (); - m_Timer.expires_from_now (boost::posix_time::seconds(GetTerminationTimeout ())); - m_Timer.async_wait (std::bind (&SSUSession::HandleTerminationTimer, - shared_from_this (), std::placeholders::_1)); - } - - void SSUSession::HandleTerminationTimer (const boost::system::error_code& ecode) - { - if (ecode != boost::asio::error::operation_aborted) - { - LogPrint (eLogWarning, "SSU: no activity with ", m_RemoteEndpoint, " for ", GetTerminationTimeout (), " seconds"); - Failed (); - } - } - - void SSUSession::SendI2NPMessages (const std::vector >& msgs) { GetService ().post (std::bind (&SSUSession::PostI2NPMessages, shared_from_this (), msgs)); @@ -1126,7 +1108,7 @@ namespace transport FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); Send (buf, 48); LogPrint (eLogDebug, "SSU: keep-alive sent"); - ScheduleTermination (); + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); } } diff --git a/SSUSession.h b/SSUSession.h index c2f24ce3..69669187 100644 --- a/SSUSession.h +++ b/SSUSession.h @@ -77,6 +77,7 @@ namespace transport void WaitForIntroduction (); void Close (); void Done (); + void Failed (); boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); }; void SendI2NPMessages (const std::vector >& msgs); @@ -114,7 +115,6 @@ namespace transport void ProcessRelayResponse (const uint8_t * buf, size_t len); void ProcessRelayIntro (const uint8_t * buf, size_t len); void Established (); - void Failed (); void ScheduleConnectTimer (); void HandleConnectTimer (const boost::system::error_code& ecode); void ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); @@ -131,15 +131,12 @@ namespace transport void DecryptSessionKey (uint8_t * buf, size_t len); bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey); - void ScheduleTermination (); - void HandleTerminationTimer (const boost::system::error_code& ecode); - private: friend class SSUData; // TODO: change in later SSUServer& m_Server; boost::asio::ip::udp::endpoint m_RemoteEndpoint; - boost::asio::deadline_timer m_Timer; + boost::asio::deadline_timer m_ConnectTimer; bool m_IsPeerTest; SessionState m_State; bool m_IsSessionKey; diff --git a/TransportSession.h b/TransportSession.h index 1b057bc7..9c97d02e 100644 --- a/TransportSession.h +++ b/TransportSession.h @@ -9,6 +9,7 @@ #include "Crypto.h" #include "RouterInfo.h" #include "I2NPProtocol.h" +#include "Timestamp.h" namespace i2p { @@ -54,7 +55,8 @@ namespace transport public: TransportSession (std::shared_ptr router, int terminationTimeout): - m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout) + m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), + m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) { if (router) m_RemoteIdentity = router->GetRouterIdentity (); @@ -72,6 +74,8 @@ namespace transport int GetTerminationTimeout () const { return m_TerminationTimeout; }; void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; + bool IsTerminationTimeoutExpired (uint64_t ts) const + { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; @@ -82,6 +86,7 @@ namespace transport size_t m_NumSentBytes, m_NumReceivedBytes; bool m_IsOutgoing; int m_TerminationTimeout; + uint64_t m_LastActivityTimestamp; }; } } From 32669cb07fe112dea5d677f7e55729ee3918640d Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 24 Aug 2016 12:34:18 -0400 Subject: [PATCH 071/141] stop termination timer on shutdown --- SSU.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SSU.cpp b/SSU.cpp index 3d3fefdd..72091e00 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -77,6 +77,8 @@ namespace transport { DeleteAllSessions (); m_IsRunning = false; + m_TerminationTimer.cancel (); + m_TerminationTimerV6.cancel (); m_Service.stop (); m_Socket.close (); m_ServiceV6.stop (); From c4171a01bdd9e173bdc644665c2bc12eab31948b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Aug 2016 09:48:19 -0400 Subject: [PATCH 072/141] fix #622. extract correct CN --- Reseed.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Reseed.cpp b/Reseed.cpp index 48d7a53f..21635791 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -345,11 +345,21 @@ namespace data // extract issuer name char name[100]; X509_NAME_oneline (X509_get_issuer_name(cert), name, 100); + char * cn = strstr (name, "CN="); + if (cn) + { + cn += 3; + char * terminator = strchr (cn, '/'); + if (terminator) terminator[0] = 0; + } // extract RSA key (we need n only, e = 65537) RSA * key = X509_get_pubkey (cert)->pkey.rsa; PublicKey value; i2p::crypto::bn2buf (key->n, value, 512); - m_SigningKeys[name] = value; + if (cn) + m_SigningKeys[cn] = value; + else + LogPrint (eLogError, "Reseed: Can't find CN field in ", filename); } SSL_free (ssl); } From fc5fc5bbee016b41ab447b2a9960b0d96f5733f0 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Aug 2016 10:06:28 -0400 Subject: [PATCH 073/141] don't throw exception if connection failed --- NTCPSession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 41252f97..10af063d 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -952,7 +952,7 @@ namespace transport { if (ecode) { - LogPrint (eLogError, "NTCP: Can't connect to ", conn->GetSocket ().remote_endpoint (), ": ", ecode.message ()); + LogPrint (eLogError, "NTCP: Connect error ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true); conn->Terminate (); From 205b61e4cf334307ff38fcc7dafffc7ae616ba9c Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 26 Aug 2016 14:00:00 +0000 Subject: [PATCH 074/141] * HTTPServer : fix tag --- HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index fdc5b38f..52ef09e3 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -422,7 +422,7 @@ namespace http { s << " Accept transit tunnels
\r\n"; #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) if (Daemon.gracefullShutdownInterval) - s << " Cancel gracefull shutdown
"; + s << " Cancel gracefull shutdown
"; else s << " Start gracefull shutdown
\r\n"; #endif From 26440d94f1ea4c75cf9a450eeb9c7c2a70f8ec4e Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 26 Aug 2016 14:00:00 +0000 Subject: [PATCH 075/141] * HTTPServer : keep response data for async_write() --- HTTPServer.cpp | 4 ++-- HTTPServer.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 52ef09e3..309e3f6b 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -762,8 +762,8 @@ namespace http { reply.add_header("Content-Type", "text/html"); reply.body = content; - std::string res = reply.to_string(); - boost::asio::async_write (*m_Socket, boost::asio::buffer(res), + m_SendBuffer = reply.to_string(); + boost::asio::async_write (*m_Socket, boost::asio::buffer(m_SendBuffer), std::bind (&HTTPConnection::Terminate, shared_from_this (), std::placeholders::_1)); } diff --git a/HTTPServer.h b/HTTPServer.h index bf7f5c65..5246af8b 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -31,6 +31,7 @@ namespace http { boost::asio::deadline_timer m_Timer; char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1]; size_t m_BufferLen; + std::string m_SendBuffer; bool needAuth; std::string user; std::string pass; From abaf36a2de45c8b3dc2cf981455bd94492681896 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 27 Aug 2016 09:29:18 -0400 Subject: [PATCH 076/141] try unbreaking static build --- Makefile.linux | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile.linux b/Makefile.linux index b0549f43..ddff76a7 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -32,9 +32,14 @@ ifeq ($(USE_STATIC),yes) # Using 'getaddrinfo' in statically linked applications requires at runtime # the shared libraries from the glibc version used for linking LIBDIR := /usr/lib - LDLIBS = -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options - LDLIBS += -lssl -lcrypto -lz -ldl -lpthread -lrt - LDLIBS += -static-libstdc++ -static-libgcc -static + LDLIBS = $(LIBDIR)/libboost_system.a + LDLIBS += $(LIBDIR)/libboost_date_time.a + LDLIBS += $(LIBDIR)/libboost_filesystem.a + LDLIBS += $(LIBDIR)/libboost_program_options.a + LDLIBS += $(LIBDIR)/libssl.a + LDLIBS += $(LIBDIR)/libcrypto.a + LDLIBS += $(LIBDIR)/libz.a + LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt USE_AESNI := no else LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread From 0b21fce94efd7d4d7df2ded923aa6d95e49f68d0 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 27 Aug 2016 13:17:34 -0400 Subject: [PATCH 077/141] try adding garlic and session tags to datagram destination --- Datagram.cpp | 267 ++++++++++++++++++++++++++++++++++++++++-------- Datagram.h | 65 ++++++++++-- Destination.cpp | 2 + Garlic.h | 2 +- LeaseSet.cpp | 11 +- LeaseSet.h | 3 + TunnelPool.h | 1 - 7 files changed, 300 insertions(+), 51 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index aed831b7..72dfe67c 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -12,12 +12,17 @@ namespace i2p namespace datagram { DatagramDestination::DatagramDestination (std::shared_ptr owner): - m_Owner (owner.get()), m_Receiver (nullptr) + m_Owner (owner.get()), + m_CleanupTimer(owner->GetService()), + m_Receiver (nullptr) { + ScheduleCleanup(); } DatagramDestination::~DatagramDestination () { + m_CleanupTimer.cancel(); + m_Sessions.clear(); } void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) @@ -41,45 +46,11 @@ namespace datagram else owner->Sign (buf1, len, signature); - auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort); - auto remote = owner->FindLeaseSet (ident); - if (remote) - owner->GetService ().post (std::bind (&DatagramDestination::SendMsg, this, msg, remote)); - else - owner->RequestDestination (ident, std::bind (&DatagramDestination::HandleLeaseSetRequestComplete, this, std::placeholders::_1, msg)); - } + auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort); + auto session = ObtainSession(ident); + session->SendMsg(msg); + } - void DatagramDestination::HandleLeaseSetRequestComplete (std::shared_ptr remote, std::shared_ptr msg) - { - if (remote) - SendMsg (msg, remote); - } - - void DatagramDestination::SendMsg (std::shared_ptr msg, std::shared_ptr remote) - { - auto outboundTunnel = m_Owner->GetTunnelPool ()->GetNextOutboundTunnel (); - auto leases = remote->GetNonExpiredLeases (); - if (!leases.empty () && outboundTunnel) - { - std::vector msgs; - uint32_t i = rand () % leases.size (); - auto garlic = m_Owner->WrapMessage (remote, msg, true); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { - i2p::tunnel::eDeliveryTypeTunnel, - leases[i]->tunnelGateway, leases[i]->tunnelID, - garlic - }); - outboundTunnel->SendTunnelDataMsg (msgs); - } - else - { - if (outboundTunnel) - LogPrint (eLogWarning, "Failed to send datagram. All leases expired"); - else - LogPrint (eLogWarning, "Failed to send datagram. No outbound tunnels"); - } - } void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { @@ -139,7 +110,223 @@ namespace datagram else msg = nullptr; return msg; - } + } + + void DatagramDestination::ScheduleCleanup() + { + m_CleanupTimer.expires_from_now(boost::posix_time::seconds(DATAGRAM_SESSION_CLEANUP_INTERVAL)); + m_CleanupTimer.async_wait(std::bind(&DatagramDestination::HandleCleanUp, this, std::placeholders::_1)); + } + + void DatagramDestination::HandleCleanUp(const boost::system::error_code & ecode) + { + if(ecode) + return; + std::lock_guard lock(m_SessionsMutex); + auto now = i2p::util::GetMillisecondsSinceEpoch(); + LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); + std::vector expiredSessions; + // for each session ... + for (auto & e : m_Sessions) { + // check if expired + if(now - e.second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) + expiredSessions.push_back(e.first); // we are expired + } + // for each expired session ... + for (auto & ident : expiredSessions) { + // remove the expired session + LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); + m_Sessions.erase(ident); + } + } + + std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & ident) + { + std::shared_ptr session = nullptr; + std::lock_guard lock(m_SessionsMutex); + auto itr = m_Sessions.find(ident); + if (itr == m_Sessions.end()) { + // not found, create new session + session = std::make_shared(m_Owner, ident); + m_Sessions[ident] = session; + } else { + session = itr->second; + } + return session; + } + + DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, + const i2p::data::IdentHash & remoteIdent) : + m_LocalDestination(localDestination), + m_RemoteIdentity(remoteIdent), + m_LastUse(i2p::util::GetMillisecondsSinceEpoch()) + { + } + + void DatagramSession::SendMsg(std::shared_ptr msg) + { + // we used this session + m_LastUse = i2p::util::GetMillisecondsSinceEpoch(); + // schedule send + m_LocalDestination->GetService().post(std::bind(&DatagramSession::HandleSend, this, msg)); + } + + void DatagramSession::HandleSend(std::shared_ptr msg) + { + // do we have a routing session? + if(m_RoutingSession) + { + // do we have a routing path ? + auto routingPath = m_RoutingSession->GetSharedRoutingPath(); + if(!routingPath) + { + // no routing path, try getting one + routingPath = GetNextRoutingPath(); + if(routingPath) // remember the routing path if we got one + m_RoutingSession->SetSharedRoutingPath(routingPath); + } + // make sure we have a routing path + if (routingPath) + { + auto outboundTunnel = routingPath->outboundTunnel; + if (outboundTunnel) + { + if(outboundTunnel->IsEstablished()) + { + // we have a routing path and routing session and the outbound tunnel we are using is good + // wrap message with routing session and send down routing path's outbound tunnel wrapped for the IBGW + auto m = m_RoutingSession->WrapSingleMessage(msg); + routingPath->outboundTunnel->SendTunnelDataMsg({i2p::tunnel::TunnelMessageBlock{ + i2p::tunnel::eDeliveryTypeTunnel, + routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, + m + }}); + return; + } + } + } + } + // we couldn't send so let's try resetting the routing path and updating lease set + ResetRoutingPath(); + UpdateLeaseSet(msg); + + } + + std::shared_ptr DatagramSession::GetNextRoutingPath() + { + std::shared_ptr outboundTunnel = nullptr; + std::shared_ptr routingPath = nullptr; + // get existing routing path if we have one + if(m_RoutingSession) + routingPath = m_RoutingSession->GetSharedRoutingPath(); + // do we have an existing outbound tunnel and routing path? + if(routingPath && routingPath->outboundTunnel) + { + // is the outbound tunnel we are using good? + if (routingPath->outboundTunnel->IsEstablished()) + { + // ya so let's stick with it + outboundTunnel = routingPath->outboundTunnel; + } + else + outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(routingPath->outboundTunnel); // no so we'll switch outbound tunnels + // don't reuse the old path as we are making a new one + routingPath = nullptr; + } + // do we have an outbound tunnel that works already ? + if(!outboundTunnel) + outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(); // no, let's get a new outbound tunnel as we probably just started + + if(outboundTunnel) + { + // get next available lease + auto lease = GetNextLease(); + if(lease) + { + // we have a valid lease to use and an outbound tunnel + // create new routing path + uint32_t now = i2p::util::GetSecondsSinceEpoch(); + routingPath = std::make_shared(i2p::garlic::GarlicRoutingPath{ + outboundTunnel, + lease, + 0, + now, + 0 + }); + } + } + return routingPath; + } + + void DatagramSession::ResetRoutingPath() + { + if(m_RoutingSession) + { + auto routingPath = m_RoutingSession->GetSharedRoutingPath(); + if(routingPath && routingPath->remoteLease) // we have a remote lease already specified and a routing path + { + // get outbound tunnel on this path + auto outboundTunnel = routingPath->outboundTunnel; + // is this outbound tunnel there and established + if (outboundTunnel && outboundTunnel->IsEstablished()) + m_InvalidIBGW.push_back(routingPath->remoteLease->tunnelGateway); // yes, let's mark remote lease as dead because the outbound tunnel seems fine + } + // reset the routing path + m_RoutingSession->SetSharedRoutingPath(nullptr); + } + } + + std::shared_ptr DatagramSession::GetNextLease() + { + std::shared_ptr next = nullptr; + if(m_RemoteLeaseSet) + { + std::vector exclude; + for(const auto & ident : m_InvalidIBGW) + exclude.push_back(ident); + // find get all leases that are not in our ban list + auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude] (const i2p::data::Lease & l) -> bool { + if(exclude.size()) + { + auto end = std::end(exclude); + return std::find_if(exclude.begin(), end, [l] ( const i2p::data::IdentHash & ident) -> bool { + return ident == l.tunnelGateway; + }) != end; + } + else + return false; + }); + if(leases.size()) + { + // pick random valid next lease + uint32_t idx = rand() % leases.size(); + next = leases[idx]; + } + } + return next; + } + + void DatagramSession::UpdateLeaseSet(std::shared_ptr msg) + { + LogPrint(eLogInfo, "DatagramSession: updating lease set"); + m_LocalDestination->RequestDestination(m_RemoteIdentity, std::bind(&DatagramSession::HandleGotLeaseSet, this, std::placeholders::_1, msg)); + } + + void DatagramSession::HandleGotLeaseSet(std::shared_ptr remoteIdent, std::shared_ptr msg) + { + if(remoteIdent) { + // update routing session + if(m_RoutingSession) + m_RoutingSession = nullptr; + m_RoutingSession = m_LocalDestination->GetRoutingSession(remoteIdent, true); + // clear invalid IBGW as we have a new lease set + m_InvalidIBGW.clear(); + m_RemoteLeaseSet = remoteIdent; + // send the message that was queued if it was provided + if(msg) + HandleSend(msg); + } + } } } diff --git a/Datagram.h b/Datagram.h index 51fd3553..dd3ba3ed 100644 --- a/Datagram.h +++ b/Datagram.h @@ -9,6 +9,7 @@ #include "Identity.h" #include "LeaseSet.h" #include "I2NPProtocol.h" +#include "Garlic.h" namespace i2p { @@ -18,7 +19,52 @@ namespace client } namespace datagram { - const size_t MAX_DATAGRAM_SIZE = 32768; + + // seconds interval for cleanup timer + const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 30; + // milliseconds for max session idle time (10 minutes) + const uint64_t DATAGRAM_SESSION_MAX_IDLE = 3600 * 1000; + + + class DatagramSession + { + public: + DatagramSession(i2p::client::ClientDestination * localDestination, + const i2p::data::IdentHash & remoteIdent); + + /** send an i2np message to remote endpoint for this session */ + void SendMsg(std::shared_ptr msg); + /** get the last time in milliseconds for when we used this datagram session */ + uint64_t LastActivity() const { return m_LastUse; } + private: + + /** get next usable routing path, try reusing outbound tunnels */ + std::shared_ptr GetNextRoutingPath(); + /** + * mark current routing path as invalid and clear it + * if the outbound tunnel we were using was okay don't use the IBGW in the routing path's lease next time + */ + void ResetRoutingPath(); + + /** get next usable lease, does not fetch or update if expired or have no lease set */ + std::shared_ptr GetNextLease(); + + void HandleSend(std::shared_ptr msg); + void HandleGotLeaseSet(std::shared_ptr remoteIdent, + std::shared_ptr msg); + void UpdateLeaseSet(std::shared_ptr msg=nullptr); + + private: + i2p::client::ClientDestination * m_LocalDestination; + i2p::data::IdentHash m_RemoteIdentity; + std::shared_ptr m_RoutingSession; + // Ident hash of IBGW that are invalid + std::vector m_InvalidIBGW; + std::shared_ptr m_RemoteLeaseSet; + uint64_t m_LastUse; + }; + + const size_t MAX_DATAGRAM_SIZE = 32768; class DatagramDestination { typedef std::function Receiver; @@ -36,19 +82,26 @@ namespace datagram void SetReceiver (const Receiver& receiver, uint16_t port) { m_ReceiversByPorts[port] = receiver; }; void ResetReceiver (uint16_t port) { m_ReceiversByPorts.erase (port); }; - + private: - - void HandleLeaseSetRequestComplete (std::shared_ptr leaseSet, std::shared_ptr msg); + // clean up after next tick + void ScheduleCleanup(); + + // clean up stale sessions and expire tags + void HandleCleanUp(const boost::system::error_code & ecode); + + 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 SendMsg (std::shared_ptr msg, std::shared_ptr remote); + void HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); private: - i2p::client::ClientDestination * m_Owner; + boost::asio::deadline_timer m_CleanupTimer; Receiver m_Receiver; // default + std::mutex m_SessionsMutex; + std::map > m_Sessions; std::map m_ReceiversByPorts; i2p::data::GzipInflator m_Inflator; diff --git a/Destination.cpp b/Destination.cpp index 56681884..349c5785 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -701,6 +701,8 @@ namespace client m_StreamingDestination = nullptr; for (auto& it: m_StreamingDestinationsByPorts) it.second->Stop (); + if(m_DatagramDestination) + delete m_DatagramDestination; m_DatagramDestination = nullptr; return true; } diff --git a/Garlic.h b/Garlic.h index 6a92b94a..b37c20e8 100644 --- a/Garlic.h +++ b/Garlic.h @@ -107,7 +107,7 @@ namespace garlic std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); - + private: size_t CreateAESBlock (uint8_t * buf, std::shared_ptr msg); diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 72f236a5..ab0407cc 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -169,8 +169,13 @@ namespace data if (now >= m_ExpirationTime) return true; return m_ExpirationTime - now <= dlt; } - - const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const + + const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const + { + return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold); + } + + const std::vector > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); std::vector > leases; @@ -181,7 +186,7 @@ namespace data endDate += LEASE_ENDDATE_THRESHOLD; else endDate -= LEASE_ENDDATE_THRESHOLD; - if (ts < endDate) + if (ts < endDate && !exclude(*it)) leases.push_back (it); } return leases; diff --git a/LeaseSet.h b/LeaseSet.h index d9e74bab..9b6b7844 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -38,6 +38,8 @@ namespace data }; }; + typedef std::function LeaseInspectFunc; + const size_t MAX_LS_BUFFER_SIZE = 3072; const size_t LEASE_SIZE = 44; // 32 + 4 + 8 const uint8_t MAX_NUM_LEASES = 16; @@ -56,6 +58,7 @@ namespace data size_t GetBufferLen () const { return m_BufferLen; }; bool IsValid () const { return m_IsValid; }; const std::vector > GetNonExpiredLeases (bool withThreshold = true) const; + const std::vector > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const; bool HasExpiredLeases () const; bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; diff --git a/TunnelPool.h b/TunnelPool.h index 0cd2057d..b32a554f 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -45,7 +45,6 @@ namespace tunnel std::shared_ptr GetNextOutboundTunnel (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); void ProcessDeliveryStatus (std::shared_ptr msg); From 35b68db847e5e4eaada0ae0d2880ec19b38503e9 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 27 Aug 2016 15:45:56 -0400 Subject: [PATCH 078/141] schedule cleanup again and add logging --- Datagram.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Datagram.cpp b/Datagram.cpp index 72dfe67c..18a147b8 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -138,6 +138,7 @@ namespace datagram LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); m_Sessions.erase(ident); } + ScheduleCleanup(); } std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & ident) @@ -180,6 +181,7 @@ namespace datagram auto routingPath = m_RoutingSession->GetSharedRoutingPath(); if(!routingPath) { + LogPrint(eLogDebug, "DatagramSession: try getting new routing path"); // no routing path, try getting one routingPath = GetNextRoutingPath(); if(routingPath) // remember the routing path if we got one From 7d03a41e3e8a12913bb281cadc3fc67a399052cc Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 27 Aug 2016 16:09:02 -0400 Subject: [PATCH 079/141] try manual expiration of tags --- Datagram.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Datagram.cpp b/Datagram.cpp index 18a147b8..9a5724aa 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -138,6 +138,8 @@ namespace datagram LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); m_Sessions.erase(ident); } + m_LocalDestination->CleanupExpiredTags(); + m_LocalDestination->CleanupUnconfirmedTags(); ScheduleCleanup(); } From 2ce64e1bf5b45a829ade0d4ab9f759ee023ad54f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 27 Aug 2016 16:10:18 -0400 Subject: [PATCH 080/141] fix typo --- Datagram.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index 9a5724aa..b73cf647 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -138,8 +138,8 @@ namespace datagram LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); m_Sessions.erase(ident); } - m_LocalDestination->CleanupExpiredTags(); - m_LocalDestination->CleanupUnconfirmedTags(); + m_Owner->CleanupExpiredTags(); + m_Owner->CleanupUnconfirmedTags(); ScheduleCleanup(); } From 5685c376cb2b5cc6666e6d30bb222512a761fc1f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 27 Aug 2016 16:13:11 -0400 Subject: [PATCH 081/141] fix broken build --- Datagram.cpp | 1 - Datagram.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index b73cf647..13a4af96 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -139,7 +139,6 @@ namespace datagram m_Sessions.erase(ident); } m_Owner->CleanupExpiredTags(); - m_Owner->CleanupUnconfirmedTags(); ScheduleCleanup(); } diff --git a/Datagram.h b/Datagram.h index dd3ba3ed..bb1bc285 100644 --- a/Datagram.h +++ b/Datagram.h @@ -21,7 +21,7 @@ namespace datagram { // seconds interval for cleanup timer - const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 30; + const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 3; // milliseconds for max session idle time (10 minutes) const uint64_t DATAGRAM_SESSION_MAX_IDLE = 3600 * 1000; From c6556b8442e218e44025ce69281dec91ecd357d5 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 10:41:15 -0400 Subject: [PATCH 082/141] make sure m_RTO > 0 in Streaming.cpp so it doesn't hang --- Streaming.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Streaming.cpp b/Streaming.cpp index 6be2a98f..0908ff4a 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -663,6 +663,9 @@ namespace stream void Stream::ScheduleResend () { m_ResendTimer.cancel (); + // check for invalid value + if (m_RTO <= 0) + m_RTO = 1; m_ResendTimer.expires_from_now (boost::posix_time::milliseconds(m_RTO)); m_ResendTimer.async_wait (std::bind (&Stream::HandleResendTimer, shared_from_this (), std::placeholders::_1)); From 7d37b02cff9c846e20f387b48c87caaeaceca3a9 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 10:42:51 -0400 Subject: [PATCH 083/141] datagram fixes --- AddressBook.cpp | 5 ++--- I2PTunnel.cpp | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 78e9731f..9f1af809 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -547,8 +547,7 @@ namespace client auto datagram = dest->GetDatagramDestination (); if(datagram == nullptr) datagram = dest->CreateDatagramDestination(); datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), - ADDRESS_RESPONSE_DATAGRAM_PORT); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); } } @@ -559,7 +558,7 @@ namespace client { auto datagram = dest->GetDatagramDestination (); if (datagram) - datagram->ResetReceiver (ADDRESS_RESPONSE_DATAGRAM_PORT); + datagram->ResetReceiver (); } } diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 69360c2c..4c106d4d 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -590,14 +590,14 @@ namespace client m_LocalDest = localDestination; m_LocalDest->Start(); auto dgram = m_LocalDest->CreateDatagramDestination(); - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), 0); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); } I2PUDPServerTunnel::~I2PUDPServerTunnel() { auto dgram = m_LocalDest->GetDatagramDestination(); if (dgram) { - dgram->ResetReceiver(0); + dgram->ResetReceiver(); } LogPrint(eLogInfo, "UDPServer: done"); } @@ -671,7 +671,7 @@ namespace client I2PUDPClientTunnel::~I2PUDPClientTunnel() { auto dgram = m_LocalDest->GetDatagramDestination(); if (dgram) { - dgram->ResetReceiver(LocalPort); + dgram->ResetReceiver(); } if (m_Session) delete m_Session; m_cancel_resolve = true; From 37b80f0ce3fc6b867db2e1941b36f4eca41da0bf Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 10:41:15 -0400 Subject: [PATCH 084/141] make sure m_RTO > 0 in Streaming.cpp so it doesn't hang --- Streaming.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Streaming.cpp b/Streaming.cpp index 90c363ea..1103dba1 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -658,6 +658,9 @@ namespace stream void Stream::ScheduleResend () { m_ResendTimer.cancel (); + // check for invalid value + if (m_RTO <= 0) + m_RTO = 1; m_ResendTimer.expires_from_now (boost::posix_time::milliseconds(m_RTO)); m_ResendTimer.async_wait (std::bind (&Stream::HandleResendTimer, shared_from_this (), std::placeholders::_1)); From 28fdd992c99930f16d7f514084033845754db76a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 12:09:37 -0400 Subject: [PATCH 085/141] add hooks for custom peer selection --- TunnelPool.cpp | 12 +++++++++--- TunnelPool.h | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 119556aa..ba7a86a3 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -15,7 +15,8 @@ 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) + m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true), + m_CustomPeerSelector(nullptr) { } @@ -327,9 +328,14 @@ namespace tunnel bool TunnelPool::SelectPeers (std::vector >& peers, bool isInbound) { - if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound); int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; - if (numHops <= 0) return true; // peers is empty + // peers is empty + if (numHops <= 0) return true; + // custom peer selector in use + 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 (); if(i2p::transport::transports.RoutesRestricted()) { diff --git a/TunnelPool.h b/TunnelPool.h index b32a554f..bffecba5 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -23,6 +23,16 @@ namespace tunnel class InboundTunnel; class OutboundTunnel; + /** 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; + }; + + typedef std::shared_ptr TunnelPeerSelector; + class TunnelPool: public std::enable_shared_from_this // per local destination { public: @@ -55,7 +65,10 @@ namespace tunnel int GetNumInboundTunnels () const { return m_NumInboundTunnels; }; int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; }; - + + void SetCustomPeerSelector(TunnelPeerSelector selector); + TunnelPeerSelector GetCustomPeerSelector() const { return m_CustomPeerSelector; } + private: void CreateInboundTunnel (); @@ -79,7 +92,7 @@ namespace tunnel mutable std::mutex m_TestsMutex; std::map, std::shared_ptr > > m_Tests; bool m_IsActive; - + TunnelPeerSelector m_CustomPeerSelector; public: // for HTTP only From fec49e5609f282f6f275696ba2f5ad39af4e593d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 14:16:29 -0400 Subject: [PATCH 086/141] add hooks for visiting netdb --- FS.cpp | 9 ++++++++- FS.h | 4 ++++ NetDb.cpp | 15 +++++++++++++++ NetDb.h | 10 ++++++++-- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/FS.cpp b/FS.cpp index 663c1916..a809e8c4 100644 --- a/FS.cpp +++ b/FS.cpp @@ -158,6 +158,13 @@ namespace fs { } void HashedStorage::Traverse(std::vector & files) { + Iterate([&files] (const std::string & fname) { + files.push_back(fname); + }); + } + + void HashedStorage::Iterate(FilenameVisitor v) + { boost::filesystem::path p(root); boost::filesystem::recursive_directory_iterator it(p); boost::filesystem::recursive_directory_iterator end; @@ -166,7 +173,7 @@ namespace fs { if (!boost::filesystem::is_regular_file( it->status() )) continue; const std::string & t = it->path().string(); - files.push_back(t); + v(t); } } } // fs diff --git a/FS.h b/FS.h index 0437ccf9..c476aa63 100644 --- a/FS.h +++ b/FS.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace i2p { namespace fs { @@ -43,6 +44,7 @@ namespace fs { std::string suffix; /**< suffix of file in storage (extension) */ public: + typedef std::function FilenameVisitor; HashedStorage(const char *n, const char *p1, const char *p2, const char *s): name(n), prefix1(p1), prefix2(p2), suffix(s) {}; @@ -58,6 +60,8 @@ namespace fs { void Remove(const std::string & ident); /** find all files in storage and store list in provided vector */ void Traverse(std::vector & files); + /** visit every file in this storage with a visitor */ + void Iterate(FilenameVisitor v); }; /** @brief Returns current application name, default 'i2pd' */ diff --git a/NetDb.cpp b/NetDb.cpp index dc018326..80b36db5 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -329,6 +329,21 @@ namespace data for ( auto & entry : m_LeaseSets) v(entry.first, entry.second); } + + void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v) + { + m_Storage.Iterate([v] (const std::string & filename) { + const i2p::data::RouterInfo ri(filename); + v(ri); + }); + } + + void NetDb::VisitRouterInfos(RouterInfoVisitor v) + { + std::unique_lock lock(m_RouterInfosMutex); + for ( const auto & item : m_RouterInfos ) + v(*item.second); + } void NetDb::Load () { diff --git a/NetDb.h b/NetDb.h index 43b069b9..12d667d3 100644 --- a/NetDb.h +++ b/NetDb.h @@ -35,7 +35,10 @@ namespace data /** function for visiting a leaseset stored in a floodfill */ typedef std::function)> LeaseSetVisitor; - + + /** function for visiting a router info we have locally */ + typedef std::function RouterInfoVisitor; + class NetDb { public: @@ -86,7 +89,10 @@ namespace data /** visit all lease sets we currently store */ void VisitLeaseSets(LeaseSetVisitor v); - + /** visit all router infos we have currently on disk, usually insanely expensive, does not access in memory RI */ + void VisitStoredRouterInfos(RouterInfoVisitor v); + /** visit all router infos we have loaded in memory, cheaper than VisitLocalRouterInfos but locks access while visiting */ + void VisitRouterInfos(RouterInfoVisitor v); private: void Load (); From 10ffdb2766ca049f648ed8fcbdf662d081dc1068 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 15:26:19 -0400 Subject: [PATCH 087/141] add NetDb::WaitForReady --- NetDb.cpp | 14 +++++++++++--- NetDb.h | 8 ++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index 80b36db5..dca9900d 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -23,7 +23,7 @@ namespace data { NetDb netdb; - NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_HiddenMode(false) + NetDb::NetDb (): m_Ready(new std::promise()), m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_HiddenMode(false) { } @@ -38,13 +38,14 @@ namespace data m_Storage.SetPlace(i2p::fs::GetDataDir()); m_Storage.Init(i2p::data::GetBase64SubstitutionTable(), 64); InitProfilesStorage (); - m_Families.LoadCertificates (); + m_Families.LoadCertificates (); Load (); if (m_RouterInfos.size () < 25) // reseed if # of router less than 50 Reseed (); m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); + m_Ready->set_value(); } void NetDb::Stop () @@ -68,7 +69,14 @@ namespace data m_Requests.Stop (); } } - + + void NetDb::WaitForReady() + { + m_Ready->get_future().wait(); + delete m_Ready; + m_Ready = nullptr; + } + void NetDb::Run () { uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; diff --git a/NetDb.h b/NetDb.h index 12d667d3..7cf2730e 100644 --- a/NetDb.h +++ b/NetDb.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "Base.h" #include "Gzip.h" @@ -48,7 +49,9 @@ namespace data void Start (); void Stop (); - + /** block until netdb is ready, call only once*/ + void WaitForReady(); + bool AddRouterInfo (const uint8_t * buf, int len); bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); @@ -109,7 +112,8 @@ namespace data std::shared_ptr GetRandomRouter (Filter filter) const; private: - + std::promise * m_Ready; + mutable std::mutex m_LeaseSetsMutex; std::map > m_LeaseSets; mutable std::mutex m_RouterInfosMutex; From ce97fa87e773db809fca1441bd607345a7e30e48 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 15:34:59 -0400 Subject: [PATCH 088/141] don't use std::promise * --- NetDb.cpp | 10 ++++------ NetDb.h | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index dca9900d..16bd8229 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -23,7 +23,7 @@ namespace data { NetDb netdb; - NetDb::NetDb (): m_Ready(new std::promise()), m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_HiddenMode(false) + NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_HiddenMode(false) { } @@ -34,7 +34,7 @@ namespace data } void NetDb::Start () - { + { m_Storage.SetPlace(i2p::fs::GetDataDir()); m_Storage.Init(i2p::data::GetBase64SubstitutionTable(), 64); InitProfilesStorage (); @@ -45,7 +45,7 @@ namespace data m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); - m_Ready->set_value(); + m_Ready.set_value(); } void NetDb::Stop () @@ -72,9 +72,7 @@ namespace data void NetDb::WaitForReady() { - m_Ready->get_future().wait(); - delete m_Ready; - m_Ready = nullptr; + m_Ready.get_future().get(); } void NetDb::Run () diff --git a/NetDb.h b/NetDb.h index 7cf2730e..324feb87 100644 --- a/NetDb.h +++ b/NetDb.h @@ -112,7 +112,7 @@ namespace data std::shared_ptr GetRandomRouter (Filter filter) const; private: - std::promise * m_Ready; + std::promise m_Ready; mutable std::mutex m_LeaseSetsMutex; std::map > m_LeaseSets; From 85e65da4925ed77a3bd3ba5a9c8d16f27ddb6ad6 Mon Sep 17 00:00:00 2001 From: xcps Date: Tue, 30 Aug 2016 01:48:37 +0500 Subject: [PATCH 089/141] server tunnel on linux binds on 127.x.x.x --- I2PTunnel.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index ad06328b..fc4da719 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -50,9 +50,21 @@ namespace client void I2PTunnelConnection::Connect () { - if (m_Socket) + if (m_Socket) { +#ifdef __linux__ + // bind to 127.x.x.x address + // where x.x.x are first three bytes from ident + m_Socket->open (boost::asio::ip::tcp::v4 ()); + boost::asio::ip::address_v4::bytes_type bytes; + const uint8_t * ident = m_Stream->GetRemoteIdentity ()->GetIdentHash (); + bytes[0] = 127; + memcpy (bytes.data ()+1, ident, 3); + boost::asio::ip::address ourIP = boost::asio::ip::address_v4 (bytes); + m_Socket->bind (boost::asio::ip::tcp::endpoint (ourIP, 0)); +#endif m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, shared_from_this (), std::placeholders::_1)); + } } void I2PTunnelConnection::Terminate () From 87d1058de3b0436d4fa040c637ff53f1a34d96c0 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 16:57:34 -0400 Subject: [PATCH 090/141] fix --- NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index 16bd8229..7d761e2d 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -72,7 +72,7 @@ namespace data void NetDb::WaitForReady() { - m_Ready.get_future().get(); + m_Ready.get_future().wait(); } void NetDb::Run () From c0cba7b376ca36ae40c7ed669602c82fc47f46e6 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 29 Aug 2016 16:59:17 -0400 Subject: [PATCH 091/141] move ready to run --- NetDb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index 7d761e2d..a274908b 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -45,7 +45,6 @@ namespace data m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); - m_Ready.set_value(); } void NetDb::Stop () @@ -77,6 +76,11 @@ namespace data void NetDb::Run () { + try { + m_Ready.set_value(); + } catch( std::future_error & ex) { + (void) ex; + } uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; while (m_IsRunning) { From f2893097a7870c567ef33c92bf48896e194fcc51 Mon Sep 17 00:00:00 2001 From: xcps Date: Tue, 30 Aug 2016 02:53:26 +0500 Subject: [PATCH 092/141] check before bind to 127.x.x.x --- I2PTunnel.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index fc4da719..cca56120 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -54,13 +54,18 @@ namespace client #ifdef __linux__ // bind to 127.x.x.x address // where x.x.x are first three bytes from ident - m_Socket->open (boost::asio::ip::tcp::v4 ()); - boost::asio::ip::address_v4::bytes_type bytes; - const uint8_t * ident = m_Stream->GetRemoteIdentity ()->GetIdentHash (); - bytes[0] = 127; - memcpy (bytes.data ()+1, ident, 3); - boost::asio::ip::address ourIP = boost::asio::ip::address_v4 (bytes); - m_Socket->bind (boost::asio::ip::tcp::endpoint (ourIP, 0)); + + if (m_RemoteEndpoint.address ().is_v4 () && + m_RemoteEndpoint.address ().to_v4 ().to_bytes ()[0] == 127) + { + m_Socket->open (boost::asio::ip::tcp::v4 ()); + boost::asio::ip::address_v4::bytes_type bytes; + const uint8_t * ident = m_Stream->GetRemoteIdentity ()->GetIdentHash (); + bytes[0] = 127; + memcpy (bytes.data ()+1, ident, 3); + boost::asio::ip::address ourIP = boost::asio::ip::address_v4 (bytes); + m_Socket->bind (boost::asio::ip::tcp::endpoint (ourIP, 0)); + } #endif m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, shared_from_this (), std::placeholders::_1)); From ac88c1a8f1a640439a8f98338de04cd082211fe5 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 30 Aug 2016 13:27:57 -0400 Subject: [PATCH 093/141] add ClientDestination::Ready --- Destination.cpp | 30 ++++++++++++++++++++++++++++-- Destination.h | 16 ++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 349c5785..73fa7a0c 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -168,7 +168,7 @@ namespace client else return false; } - + std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { std::lock_guard lock(m_RemoteLeaseSetsMutex); @@ -665,7 +665,8 @@ namespace client ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): LeaseSetDestination (isPublic, params), - m_Keys (keys), m_DatagramDestination (nullptr) + m_Keys (keys), m_DatagramDestination (nullptr), + m_ReadyChecker(GetService()) { if (isPublic) PersistTemporaryKeys (); @@ -697,6 +698,7 @@ namespace client { if (LeaseSetDestination::Stop ()) { + m_ReadyChecker.cancel(); m_StreamingDestination->Stop (); m_StreamingDestination = nullptr; for (auto& it: m_StreamingDestinationsByPorts) @@ -710,6 +712,30 @@ namespace client return false; } + void ClientDestination::Ready(ReadyPromise & p) + { + ScheduleCheckForReady(&p); + } + + void ClientDestination::ScheduleCheckForReady(ReadyPromise * p) + { + // tick every 100ms + m_ReadyChecker.expires_from_now(boost::posix_time::milliseconds(100)); + m_ReadyChecker.async_wait([&, p] (const boost::system::error_code & ecode) { + HandleCheckForReady(ecode, p); + }); + } + + void ClientDestination::HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p) + { + if(ecode) // error happened + p->set_value(nullptr); + else if(IsReady()) // we are ready + p->set_value(std::shared_ptr(this)); + else // we are not ready + ScheduleCheckForReady(p); + } + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); diff --git a/Destination.h b/Destination.h index 3faab9cc..8150c72d 100644 --- a/Destination.h +++ b/Destination.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "Identity.h" #include "TunnelPool.h" @@ -143,13 +144,19 @@ namespace client class ClientDestination: public LeaseSetDestination { public: - + // type for informing that a client destination is ready + typedef std::promise > ReadyPromise; + ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params = nullptr); ~ClientDestination (); bool Start (); bool Stop (); - + + // informs promise with shared_from_this() when this destination is ready to use + // if cancelled before ready, informs promise with nullptr + void Ready(ReadyPromise & p); + 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); }; @@ -183,6 +190,9 @@ namespace client { return std::static_pointer_cast(shared_from_this ()); } void PersistTemporaryKeys (); + void ScheduleCheckForReady(ReadyPromise * p); + void HandleCheckForReady(const boost::system::error_code & ecode, ReadyPromise * p); + private: i2p::data::PrivateKeys m_Keys; @@ -192,6 +202,8 @@ namespace client std::map > m_StreamingDestinationsByPorts; i2p::datagram::DatagramDestination * m_DatagramDestination; + boost::asio::deadline_timer m_ReadyChecker; + public: // for HTTP only From fa8548fe341fd7d13d0bbbfd397135237c03c8a4 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 30 Aug 2016 15:11:39 -0400 Subject: [PATCH 094/141] implement SetCustomPeerSelector and ensure locking is good --- TunnelPool.cpp | 27 ++++++++++++++++++++++++--- TunnelPool.h | 7 ++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/TunnelPool.cpp b/TunnelPool.cpp index ba7a86a3..35272f2c 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -331,8 +331,12 @@ namespace tunnel int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; // peers is empty if (numHops <= 0) return true; - // custom peer selector in use - if (m_CustomPeerSelector) return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound); + // 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); @@ -483,6 +487,23 @@ namespace tunnel LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel..."); auto tunnel = tunnels.CreateInboundTunnel (std::make_shared(outboundTunnel->GetInvertedPeers ()), outboundTunnel); tunnel->SetTunnelPool (shared_from_this ()); - } + } + + void TunnelPool::SetCustomPeerSelector(TunnelPeerSelector selector) + { + std::lock_guard lock(m_CustomPeerSelectorMutex); + m_CustomPeerSelector = selector; + } + + void TunnelPool::UnsetCustomPeerSelector() + { + SetCustomPeerSelector(nullptr); + } + + bool TunnelPool::HasCustomPeerSelector() + { + std::lock_guard lock(m_CustomPeerSelectorMutex); + return m_CustomPeerSelector != nullptr; + } } } diff --git a/TunnelPool.h b/TunnelPool.h index bffecba5..d5bcf18f 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -67,10 +67,10 @@ namespace tunnel int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; }; void SetCustomPeerSelector(TunnelPeerSelector selector); - TunnelPeerSelector GetCustomPeerSelector() const { return m_CustomPeerSelector; } - + void UnsetCustomPeerSelector(); + bool HasCustomPeerSelector(); private: - + void CreateInboundTunnel (); void CreateOutboundTunnel (); void CreatePairedInboundTunnel (std::shared_ptr outboundTunnel); @@ -92,6 +92,7 @@ namespace tunnel mutable std::mutex m_TestsMutex; std::map, std::shared_ptr > > m_Tests; bool m_IsActive; + std::mutex m_CustomPeerSelectorMutex; TunnelPeerSelector m_CustomPeerSelector; public: From 970557660ee9b1bdd14ba9201bae5f2fc789332b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 30 Aug 2016 15:54:53 -0400 Subject: [PATCH 095/141] Add NetDb::VisitRandomRouterInfos --- NetDb.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- NetDb.h | 8 +++++--- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index a274908b..e1d49c5c 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -68,19 +68,9 @@ namespace data m_Requests.Stop (); } } - - void NetDb::WaitForReady() - { - m_Ready.get_future().wait(); - } void NetDb::Run () { - try { - m_Ready.set_value(); - } catch( std::future_error & ex) { - (void) ex; - } uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; while (m_IsRunning) { @@ -354,6 +344,50 @@ namespace data for ( const auto & item : m_RouterInfos ) v(*item.second); } + + size_t NetDb::VisitRandomRouterInfos(RouterInfoFilter filter, RouterInfoVisitor v, size_t n) + { + std::vector > found; + const size_t max_iters_per_cyle = 3; + size_t iters = max_iters_per_cyle; + while(n) + { + std::unique_lock lock(m_RouterInfosMutex); + uint32_t idx = rand () % m_RouterInfos.size (); + uint32_t i = 0; + for (const auto & it : m_RouterInfos) { + if(i >= idx) // are we at the random start point? + { + // yes, check if we want this one + if(filter(*it.second)) + { + // we have a match + --n; + found.push_back(it.second); + // reset max iterations per cycle + iters = max_iters_per_cyle; + break; + } + } + else // not there yet + ++i; + } + --iters; + // have we tried enough this cycle ? + if(!iters) { + // yes let's try the next cycle + --n; + iters = max_iters_per_cyle; + } + } + // visit the ones we found + size_t visited = 0; + for(const auto & ri : found ) { + v(*ri); + ++visited; + } + return visited; + } void NetDb::Load () { diff --git a/NetDb.h b/NetDb.h index 324feb87..294e1c83 100644 --- a/NetDb.h +++ b/NetDb.h @@ -39,6 +39,9 @@ namespace data /** function for visiting a router info we have locally */ typedef std::function RouterInfoVisitor; + + /** function for visiting a router info and determining if we want to use it */ + typedef std::function RouterInfoFilter; class NetDb { @@ -49,8 +52,6 @@ namespace data void Start (); void Stop (); - /** block until netdb is ready, call only once*/ - void WaitForReady(); bool AddRouterInfo (const uint8_t * buf, int len); bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); @@ -96,6 +97,8 @@ namespace data void VisitStoredRouterInfos(RouterInfoVisitor v); /** visit all router infos we have loaded in memory, cheaper than VisitLocalRouterInfos but locks access while visiting */ void VisitRouterInfos(RouterInfoVisitor v); + /** visit N random router that match using filter, then visit them with a visitor, return number of RouterInfos that were visited */ + size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n); private: void Load (); @@ -112,7 +115,6 @@ namespace data std::shared_ptr GetRandomRouter (Filter filter) const; private: - std::promise m_Ready; mutable std::mutex m_LeaseSetsMutex; std::map > m_LeaseSets; From ab763c38d9e7051612c7853e7452b86045a7fc1d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 30 Aug 2016 19:59:24 -0400 Subject: [PATCH 096/141] use shared pointers --- NetDb.cpp | 6 +++--- NetDb.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index e1d49c5c..d0a75c3a 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -342,7 +342,7 @@ namespace data { std::unique_lock lock(m_RouterInfosMutex); for ( const auto & item : m_RouterInfos ) - v(*item.second); + v(item.second); } size_t NetDb::VisitRandomRouterInfos(RouterInfoFilter filter, RouterInfoVisitor v, size_t n) @@ -359,7 +359,7 @@ namespace data if(i >= idx) // are we at the random start point? { // yes, check if we want this one - if(filter(*it.second)) + if(filter(it.second)) { // we have a match --n; @@ -383,7 +383,7 @@ namespace data // visit the ones we found size_t visited = 0; for(const auto & ri : found ) { - v(*ri); + v(ri); ++visited; } return visited; diff --git a/NetDb.h b/NetDb.h index 294e1c83..d8ee148a 100644 --- a/NetDb.h +++ b/NetDb.h @@ -38,10 +38,10 @@ namespace data typedef std::function)> LeaseSetVisitor; /** function for visiting a router info we have locally */ - typedef std::function RouterInfoVisitor; + typedef std::function)> RouterInfoVisitor; /** function for visiting a router info and determining if we want to use it */ - typedef std::function RouterInfoFilter; + typedef std::function)> RouterInfoFilter; class NetDb { From a68326490d7e9092ef64f14defed3281712a2b8e Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 30 Aug 2016 20:02:27 -0400 Subject: [PATCH 097/141] fix --- NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index d0a75c3a..367477a5 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -333,7 +333,7 @@ namespace data void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v) { m_Storage.Iterate([v] (const std::string & filename) { - const i2p::data::RouterInfo ri(filename); + auto ri = std::make_shared(filename); v(ri); }); } From 8cb69c14826ec2988afb6ca6367c3c8c3bf89d7a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 31 Aug 2016 22:47:32 -0400 Subject: [PATCH 098/141] fixed #624. correct v6 address size --- SSUSession.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SSUSession.cpp b/SSUSession.cpp index 9245f652..26c14570 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -991,7 +991,7 @@ namespace transport else // v6 { boost::asio::ip::address_v6::bytes_type bytes; - memcpy (bytes.data (), address, 6); + memcpy (bytes.data (), address, 16); addr = boost::asio::ip::address_v6 (bytes); } SendPeerTest (nonce, addr, be16toh (port), introKey); // to Alice with her address received from Bob @@ -1033,7 +1033,7 @@ namespace transport } else if (address.is_v6 ()) { - *payload = 6; + *payload = 16; memcpy (payload + 1, address.to_v6 ().to_bytes ().data (), 16); // our IP V6 } else From aa687afd37d244cedb0939daaa7bd1867f75f26a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 1 Sep 2016 09:48:04 -0400 Subject: [PATCH 099/141] updated LeaseSet must be sent after completion --- Destination.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 42351787..5842e26d 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -203,6 +203,7 @@ namespace client void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet) { m_LeaseSet.reset (newLeaseSet); + i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); if (m_IsPublic) { m_PublishVerificationTimer.cancel (); @@ -391,8 +392,7 @@ namespace client } void LeaseSetDestination::SetLeaseSetUpdated () - { - i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); + { UpdateLeaseSet (); } From 3ea624e1db30a72fc6e24e0ae0a1b06c39867996 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 1 Sep 2016 15:54:48 -0400 Subject: [PATCH 100/141] cosmetic fix --- NetDb.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index 367477a5..846f4b3c 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -350,7 +350,7 @@ namespace data std::vector > found; const size_t max_iters_per_cyle = 3; size_t iters = max_iters_per_cyle; - while(n) + while(n > 0) { std::unique_lock lock(m_RouterInfosMutex); uint32_t idx = rand () % m_RouterInfos.size (); @@ -372,6 +372,8 @@ namespace data else // not there yet ++i; } + // we have enough + if(n == 0) break; --iters; // have we tried enough this cycle ? if(!iters) { From c65dc44f205c545499f71c31a69a0f8ad0e4521f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 09:38:53 -0400 Subject: [PATCH 101/141] Fix up I2PTunnel UDP tunnels --- ClientContext.cpp | 33 ++++++----- ClientContext.h | 3 +- I2PTunnel.cpp | 84 +++++++++++++++++----------- I2PTunnel.h | 138 +++++++++++++++++++++++++--------------------- 4 files changed, 149 insertions(+), 109 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 3b814260..e89e7eb7 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -404,17 +404,19 @@ namespace client } if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { // udp client - // TODO: ip6 and hostnames + // TODO: hostnames boost::asio::ip::udp::endpoint end(boost::asio::ip::address::from_string(address), port); - if (!localDestination) { + if (!localDestination) + { localDestination = m_SharedLocalDestination; } auto clientTunnel = new I2PUDPClientTunnel(name, dest, end, localDestination, destinationPort); - if(m_ClientForwards.insert(std::make_pair(end, std::unique_ptr(clientTunnel))).second) { + if(m_ClientForwards.insert(std::make_pair(end, std::unique_ptr(clientTunnel))).second) + { clientTunnel->Start(); - } else { - LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); } + else + LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); } else { // tcp client @@ -443,7 +445,8 @@ namespace client bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, true); i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); uint32_t maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN); - + std::string address = section.second.get (I2P_SERVER_TUNNEL_ADDRESS, "127.0.0.1"); + // I2CP std::map options; ReadI2CPOptions (section, options); @@ -455,22 +458,26 @@ namespace client localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); - if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) { + if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) + { // udp server tunnel - // TODO: ipv6 and hostnames + // TODO: hostnames + 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, endpoint, port); + I2PUDPServerTunnel * serverTunnel = new I2PUDPServerTunnel(name, localDestination, localAddress, endpoint, port); std::lock_guard lock(m_ForwardsMutex); if(m_ServerForwards.insert( std::make_pair( std::make_pair( localDestination->GetIdentHash(), port), - std::unique_ptr(serverTunnel))).second) { + std::unique_ptr(serverTunnel))).second) + { serverTunnel->Start(); - LogPrint(eLogInfo, "Clients: I2P Server Forward created for UDP Endpoint ", host, ":", port, " via ",localDestination->GetIdentHash().ToBase32()); - } else { - LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); + LogPrint(eLogInfo, "Clients: I2P Server Forward created for UDP Endpoint ", host, ":", port, " bound on ", address, " for ",localDestination->GetIdentHash().ToBase32()); } + else + LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); + continue; } diff --git a/ClientContext.h b/ClientContext.h index 5a054f29..0ff7993f 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -41,7 +41,8 @@ namespace client 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"; + class ClientContext { public: diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 6cc21e85..db8831be 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -532,7 +532,7 @@ namespace client { std::lock_guard lock(m_SessionsMutex); auto session = ObtainUDPSession(from, toPort, fromPort); - session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Endpoint); + session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint); session->LastActivity = i2p::util::GetMillisecondsSinceEpoch(); } @@ -548,20 +548,25 @@ namespace client UDPSession * I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) { auto ih = from.GetIdentHash(); - for ( UDPSession * s : m_Sessions ) { - if ( s->Identity == ih) { - /** found existing */ + for ( UDPSession * s : m_Sessions ) + { + if ( s->Identity == ih) + { + /** found existing session */ LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32()); return s; } } - /** create new */ - boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); - m_Sessions.push_back(new UDPSession(ep, m_LocalDest, m_Endpoint, ih, localPort, remotePort)); + /** create new udp session */ + boost::asio::ip::udp::endpoint ep(m_LocalAddress, 0); + m_Sessions.push_back(new UDPSession(ep, m_LocalDest, m_RemoteEndpoint, ih, localPort, remotePort)); return m_Sessions.back(); } - UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, const std::shared_ptr & localDestination, boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, uint16_t ourPort, uint16_t theirPort) : + UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint, + const std::shared_ptr & localDestination, + boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash to, + uint16_t ourPort, uint16_t theirPort) : m_Destination(localDestination->GetDatagramDestination()), m_Service(localDestination->GetService()), IPSocket(localDestination->GetService(), localEndpoint), @@ -577,18 +582,20 @@ namespace client void UDPSession::Receive() { LogPrint(eLogDebug, "UDPSession: Receive"); - IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); + IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), + FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); } void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) { - if(!ecode) { + if(!ecode) + { LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); LastActivity = i2p::util::GetMillisecondsSinceEpoch(); uint8_t * data = new uint8_t[len]; memcpy(data, m_Buffer, len); m_Service.post([&,len, data] () { - m_Destination->SendDatagramTo(data, len, Identity, 0, 0); + m_Destination->SendDatagramTo(data, len, Identity, 0, 0); delete [] data; }); @@ -600,9 +607,12 @@ namespace client - I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : + I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, + const boost::asio::ip::address& localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : + m_LocalAddress(localAddress), + m_Name(name), LocalPort(port), - m_Endpoint(forwardTo) + m_RemoteEndpoint(forwardTo) { m_LocalDest = localDestination; m_LocalDest->Start(); @@ -613,9 +623,8 @@ namespace client I2PUDPServerTunnel::~I2PUDPServerTunnel() { auto dgram = m_LocalDest->GetDatagramDestination(); - if (dgram) { - dgram->ResetReceiver(); - } + if (dgram) dgram->ResetReceiver(); + LogPrint(eLogInfo, "UDPServer: done"); } @@ -623,7 +632,11 @@ namespace client m_LocalDest->Start(); } - I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort) : + I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, + boost::asio::ip::udp::endpoint localEndpoint, + std::shared_ptr localDestination, + uint16_t remotePort) : + m_Name(name), m_Session(nullptr), m_RemoteDest(remoteDest), m_RemoteIdent(nullptr), @@ -654,50 +667,57 @@ namespace client m_RemoteIdent = new i2p::data::IdentHash; m_RemoteIdent->Fill(0); - while(!context.GetAddressBook().GetIdentHash(m_RemoteDest, *m_RemoteIdent) && !m_cancel_resolve) { + while(!context.GetAddressBook().GetIdentHash(m_RemoteDest, *m_RemoteIdent) && !m_cancel_resolve) + { LogPrint(eLogWarning, "UDP Tunnel: failed to lookup ", m_RemoteDest); std::this_thread::sleep_for(std::chrono::seconds(1)); } - if(m_cancel_resolve) { + if(m_cancel_resolve) + { LogPrint(eLogError, "UDP Tunnel: lookup of ", m_RemoteDest, " was cancelled"); return; } LogPrint(eLogInfo, "UDP Tunnel: resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); // delete existing session if(m_Session) delete m_Session; + boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); } void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { - if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) { + if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) + { // address match - if(m_Session) { + if(m_Session) + { // tell session LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32()); m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Session->FromEndpoint); - } else { - LogPrint(eLogWarning, "UDP Client: no session"); } - } else { - LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); + else + LogPrint(eLogWarning, "UDP Client: no session"); } + else + LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); + } - + I2PUDPClientTunnel::~I2PUDPClientTunnel() { auto dgram = m_LocalDest->GetDatagramDestination(); - if (dgram) { - dgram->ResetReceiver(); - } + if (dgram) dgram->ResetReceiver(); + if (m_Session) delete m_Session; m_cancel_resolve = true; - if(m_ResolveThread) { + + if(m_ResolveThread) + { m_ResolveThread->join(); delete m_ResolveThread; m_ResolveThread = nullptr; } if (m_RemoteIdent) delete m_RemoteIdent; } -} -} +} +} diff --git a/I2PTunnel.h b/I2PTunnel.h index 63341679..76bfc36b 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -132,74 +132,86 @@ namespace client }; - /** 2 minute timeout for udp sessions */ - const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; + /** 2 minute timeout for udp sessions */ + const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2; - /** max size for i2p udp */ - const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; - - struct UDPSession - { - i2p::datagram::DatagramDestination * m_Destination; - boost::asio::io_service & m_Service; - boost::asio::ip::udp::socket IPSocket; - i2p::data::IdentHash Identity; - boost::asio::ip::udp::endpoint FromEndpoint; - boost::asio::ip::udp::endpoint SendEndpoint; - uint64_t LastActivity; + /** max size for i2p udp */ + const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; + + struct UDPSession + { + i2p::datagram::DatagramDestination * m_Destination; + boost::asio::io_service & m_Service; + boost::asio::ip::udp::socket IPSocket; + i2p::data::IdentHash Identity; + boost::asio::ip::udp::endpoint FromEndpoint; + boost::asio::ip::udp::endpoint SendEndpoint; + uint64_t LastActivity; - uint16_t LocalPort; - uint16_t RemotePort; + uint16_t LocalPort; + 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, uint16_t ourPort, uint16_t theirPort); + 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, + uint16_t ourPort, uint16_t theirPort); + void HandleReceived(const boost::system::error_code & ecode, std::size_t len); + void Receive(); + }; - void HandleReceived(const boost::system::error_code & ecode, std::size_t len); - void Receive(); - }; + /** server side udp tunnel, many i2p inbound to 1 ip outbound */ + class I2PUDPServerTunnel + { + public: + I2PUDPServerTunnel(const std::string & name, + std::shared_ptr localDestination, + const boost::asio::ip::address & localAddress, + boost::asio::ip::udp::endpoint forwardTo, uint16_t port); + ~I2PUDPServerTunnel(); + /** expire stale udp conversations */ + void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); + void Start(); + const char * GetName() const { return m_Name.c_str(); } + private: + void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + UDPSession * ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); + private: + const std::string m_Name; + const uint16_t LocalPort; + boost::asio::ip::address m_LocalAddress; + boost::asio::ip::udp::endpoint m_RemoteEndpoint; + std::mutex m_SessionsMutex; + std::vector m_Sessions; + std::shared_ptr m_LocalDest; + }; - /** server side udp tunnel, many i2p inbound to 1 ip outbound */ - class I2PUDPServerTunnel - { - public: - I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::udp::endpoint forwardTo, uint16_t port); - ~I2PUDPServerTunnel(); - /** expire stale udp conversations */ - void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); - void Start(); - private: - void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - UDPSession * ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); - private: - const uint16_t LocalPort; - boost::asio::ip::udp::endpoint m_Endpoint; - std::mutex m_SessionsMutex; - std::vector m_Sessions; - std::shared_ptr m_LocalDest; - uint8_t m_Buffer[I2P_UDP_MAX_MTU]; - }; - - class I2PUDPClientTunnel - { - public: - I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, uint16_t remotePort); - ~I2PUDPClientTunnel(); - void Start(); - private: - void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - void TryResolving(); - UDPSession * m_Session; - const std::string m_RemoteDest; - std::shared_ptr m_LocalDest; - const boost::asio::ip::udp::endpoint m_LocalEndpoint; - i2p::data::IdentHash * m_RemoteIdent; - std::thread * m_ResolveThread; - uint16_t LocalPort; - uint16_t RemotePort; - bool m_cancel_resolve; - }; - + class I2PUDPClientTunnel + { + public: + I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, + boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, + uint16_t remotePort); + ~I2PUDPClientTunnel(); + void Start(); + const char * GetName() const { return m_Name.c_str(); } + + private: + void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); + void TryResolving(); + const std::string m_Name; + UDPSession * m_Session; + const std::string m_RemoteDest; + std::shared_ptr m_LocalDest; + const boost::asio::ip::udp::endpoint m_LocalEndpoint; + i2p::data::IdentHash * m_RemoteIdent; + std::thread * m_ResolveThread; + uint16_t LocalPort; + uint16_t RemotePort; + bool m_cancel_resolve; + }; + class I2PServerTunnel: public I2PService { public: From caace05ba69ec8c364da16009520ed4cfdef1c7d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 10:01:23 -0400 Subject: [PATCH 102/141] fix up compiler warnings --- ClientContext.cpp | 8 ++++---- I2PTunnel.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index e89e7eb7..3e33ae07 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -531,6 +531,7 @@ namespace client LogPrint (eLogInfo, "Clients: ", numClientTunnels, " I2P client tunnels created"); LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created"); } + void ClientContext::ScheduleCleanupUDP() { // schedule cleanup in 1 second @@ -540,11 +541,10 @@ namespace client void ClientContext::CleanupUDP(const boost::system::error_code & ecode) { - if(!ecode) { + if(!ecode) + { std::lock_guard lock(m_ForwardsMutex); - for ( auto & s : m_ServerForwards ) { - s.second->ExpireStale(); - } + for ( auto & s : m_ServerForwards ) s.second->ExpireStale(); ScheduleCleanupUDP(); } } diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index db8831be..087221a3 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -609,9 +609,9 @@ namespace client I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, const boost::asio::ip::address& localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : - m_LocalAddress(localAddress), m_Name(name), LocalPort(port), + m_LocalAddress(localAddress), m_RemoteEndpoint(forwardTo) { m_LocalDest = localDestination; @@ -639,9 +639,9 @@ namespace client m_Name(name), m_Session(nullptr), m_RemoteDest(remoteDest), - m_RemoteIdent(nullptr), m_LocalDest(localDestination), m_LocalEndpoint(localEndpoint), + m_RemoteIdent(nullptr), m_ResolveThread(nullptr), LocalPort(localEndpoint.port()), RemotePort(remotePort), From c770bcbf9630a07e5420cbbc12814858c3b4a830 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 10:24:06 -0400 Subject: [PATCH 103/141] prevent race condition in datagram destination clean up style a bit --- AddressBook.cpp | 12 ++++++------ Datagram.cpp | 20 ++++++++++++++------ Datagram.h | 14 +++++++++----- Tag.h | 9 +++++---- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 9f1af809..b993f456 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -543,11 +543,12 @@ namespace client auto dest = i2p::client::context.GetSharedLocalDestination (); if (dest) { - auto datagram = dest->GetDatagramDestination (); - if(datagram == nullptr) datagram = dest->CreateDatagramDestination(); - datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + if (!datagram) + datagram = dest->CreateDatagramDestination (); + datagram->SetReceiver (std::bind (&AddressBook::HandleLookupResponse, this, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5), + ADDRESS_RESPONSE_DATAGRAM_PORT); } } @@ -557,8 +558,7 @@ namespace client if (dest) { auto datagram = dest->GetDatagramDestination (); - if (datagram) - datagram->ResetReceiver (); + if (datagram) datagram->ResetReceiver (ADDRESS_RESPONSE_DATAGRAM_PORT); } } diff --git a/Datagram.cpp b/Datagram.cpp index 13a4af96..cdd468b1 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -71,18 +71,26 @@ namespace datagram if (verified) { - auto it = m_ReceiversByPorts.find (toPort); - if (it != m_ReceiversByPorts.end ()) - it->second (identity, fromPort, toPort, buf + headerLen, len -headerLen); - else if (m_Receiver != nullptr) - m_Receiver (identity, fromPort, toPort, buf + headerLen, len -headerLen); + auto r = FindReceiver(toPort); + if(r) + r(identity, fromPort, toPort, buf + headerLen, len -headerLen); else - LogPrint (eLogWarning, "Receiver for datagram is not set"); + LogPrint (eLogWarning, "DatagramDestination: no receiver for port ", toPort); } else LogPrint (eLogWarning, "Datagram signature verification failed"); } + DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port) + { + std::lock_guard lock(m_ReceiversMutex); + Receiver r = m_Receiver; + auto itr = m_ReceiversByPorts.find(port); + if (itr != m_ReceiversByPorts.end()) + r = itr->second; + return r; + } + void DatagramDestination::HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) { // unzip it diff --git a/Datagram.h b/Datagram.h index bb1bc285..887c82d2 100644 --- a/Datagram.h +++ b/Datagram.h @@ -80,8 +80,8 @@ namespace datagram void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; void ResetReceiver () { m_Receiver = nullptr; }; - void SetReceiver (const Receiver& receiver, uint16_t port) { m_ReceiversByPorts[port] = receiver; }; - void ResetReceiver (uint16_t port) { m_ReceiversByPorts.erase (port); }; + void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; }; + void ResetReceiver (uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); }; private: // clean up after next tick @@ -96,12 +96,16 @@ namespace datagram void HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * 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; - boost::asio::deadline_timer m_CleanupTimer; + boost::asio::deadline_timer m_CleanupTimer; Receiver m_Receiver; // default - std::mutex m_SessionsMutex; - std::map > m_Sessions; + std::mutex m_SessionsMutex; + std::map > m_Sessions; + std::mutex m_ReceiversMutex; std::map m_ReceiversByPorts; i2p::data::GzipInflator m_Inflator; diff --git a/Tag.h b/Tag.h index 6e5638a4..4b393c57 100644 --- a/Tag.h +++ b/Tag.h @@ -51,10 +51,11 @@ namespace data { } /** fill with a value */ - void Fill(uint8_t c) { - memset(m_Buf, c, sz); - } - + void Fill(uint8_t c) + { + memset(m_Buf, c, sz); + } + std::string ToBase64 () const { char str[sz*2]; From 9acbb2203cca1c4e6c3de4e9abe1f22582a54523 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 11:46:47 -0400 Subject: [PATCH 104/141] Update Indentation and don't spam route changes in datagram sessions --- ClientContext.cpp | 177 ++++++++--------- ClientContext.h | 33 ++-- Datagram.cpp | 490 +++++++++++++++++++++++++--------------------- Datagram.h | 117 ++++++----- LeaseSet.cpp | 3 +- LeaseSet.h | 11 +- Streaming.cpp | 12 +- 7 files changed, 461 insertions(+), 382 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 3e33ae07..3c4d63c0 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -17,8 +17,8 @@ namespace client ClientContext::ClientContext (): m_SharedLocalDestination (nullptr), m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr), - m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr), - m_CleanupUDPTimer(m_Service, boost::posix_time::seconds(1)) + m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr), + m_CleanupUDPTimer(m_Service, boost::posix_time::seconds(1)) { } @@ -88,14 +88,14 @@ namespace client } } - if ( m_ServiceThread == nullptr ) { - m_ServiceThread = new std::thread([&] () { - LogPrint(eLogInfo, "ClientContext: starting service"); - m_Service.run(); - LogPrint(eLogError, "ClientContext: service died"); - }); - ScheduleCleanupUDP(); - } + if ( m_ServiceThread == nullptr ) { + m_ServiceThread = new std::thread([&] () { + LogPrint(eLogInfo, "ClientContext: starting service"); + m_Service.run(); + LogPrint(eLogError, "ClientContext: service died"); + }); + ScheduleCleanupUDP(); + } // I2P tunnels @@ -211,23 +211,24 @@ namespace client m_AddressBook.Stop (); { - std::lock_guard lock(m_ForwardsMutex); - m_ServerForwards.clear(); - m_ClientForwards.clear(); - } - - + std::lock_guard lock(m_ForwardsMutex); + m_ServerForwards.clear(); + m_ClientForwards.clear(); + } + + for (auto& it: m_Destinations) it.second->Stop (); m_Destinations.clear (); m_SharedLocalDestination = nullptr; - // stop io service thread - if(m_ServiceThread) { - m_Service.stop(); - m_ServiceThread->join(); - delete m_ServiceThread; - m_ServiceThread = nullptr; - } + // stop io service thread + if(m_ServiceThread) + { + m_Service.stop(); + m_ServiceThread->join(); + delete m_ServiceThread; + m_ServiceThread = nullptr; + } } void ClientContext::ReloadConfig () @@ -402,34 +403,34 @@ namespace client localDestination = CreateNewLocalDestination (k, type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT, &options); } } - if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { - // udp client - // TODO: hostnames - boost::asio::ip::udp::endpoint end(boost::asio::ip::address::from_string(address), port); - if (!localDestination) - { - localDestination = m_SharedLocalDestination; - } - auto clientTunnel = new I2PUDPClientTunnel(name, dest, end, localDestination, destinationPort); - if(m_ClientForwards.insert(std::make_pair(end, std::unique_ptr(clientTunnel))).second) - { - clientTunnel->Start(); - } - else - LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); + if (type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) { + // udp client + // TODO: hostnames + boost::asio::ip::udp::endpoint end(boost::asio::ip::address::from_string(address), port); + if (!localDestination) + { + localDestination = m_SharedLocalDestination; + } + auto clientTunnel = new I2PUDPClientTunnel(name, dest, end, localDestination, destinationPort); + if(m_ClientForwards.insert(std::make_pair(end, std::unique_ptr(clientTunnel))).second) + { + clientTunnel->Start(); + } + else + LogPrint(eLogError, "Clients: I2P Client forward for endpoint ", end, " already exists"); - } else { - // tcp client - auto clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); - if (m_ClientTunnels.insert (std::make_pair (clientTunnel->GetAcceptor ().local_endpoint (), - std::unique_ptr(clientTunnel))).second) - { - clientTunnel->Start (); - numClientTunnels++; - } - else - LogPrint (eLogError, "Clients: I2P client tunnel for endpoint ", clientTunnel->GetAcceptor ().local_endpoint (), " already exists"); - } + } else { + // tcp client + auto clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); + if (m_ClientTunnels.insert (std::make_pair (clientTunnel->GetAcceptor ().local_endpoint (), + std::unique_ptr(clientTunnel))).second) + { + clientTunnel->Start (); + numClientTunnels++; + } + else + LogPrint (eLogError, "Clients: I2P client tunnel for endpoint ", clientTunnel->GetAcceptor ().local_endpoint (), " already exists"); + } } else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER || type == I2P_TUNNELS_SECTION_TYPE_HTTP || type == I2P_TUNNELS_SECTION_TYPE_IRC || type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) { @@ -458,28 +459,28 @@ namespace client localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ()); if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); - if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) - { - // udp server tunnel - // TODO: hostnames - 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); - std::lock_guard lock(m_ForwardsMutex); - if(m_ServerForwards.insert( - std::make_pair( - std::make_pair( - localDestination->GetIdentHash(), port), - std::unique_ptr(serverTunnel))).second) - { - serverTunnel->Start(); - LogPrint(eLogInfo, "Clients: I2P Server Forward created for UDP Endpoint ", host, ":", port, " bound on ", address, " for ",localDestination->GetIdentHash().ToBase32()); - } - else - LogPrint(eLogError, "Clients: I2P Server Forward for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash()), "/", port, "already exists"); - - continue; - } + if (type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER) + { + // udp server tunnel + // TODO: hostnames + 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); + std::lock_guard lock(m_ForwardsMutex); + if(m_ServerForwards.insert( + std::make_pair( + std::make_pair( + localDestination->GetIdentHash(), port), + std::unique_ptr(serverTunnel))).second) + { + serverTunnel->Start(); + LogPrint(eLogInfo, "Clients: I2P Server Forward created for UDP Endpoint ", host, ":", port, " bound on ", address, " for ",localDestination->GetIdentHash().ToBase32()); + } + 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) @@ -512,7 +513,7 @@ namespace client std::make_pair (localDestination->GetIdentHash (), inPort), std::unique_ptr(serverTunnel))).second) { - serverTunnel->Start (); + serverTunnel->Start (); numServerTunnels++; } else @@ -532,21 +533,21 @@ namespace client LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created"); } - void ClientContext::ScheduleCleanupUDP() - { - // schedule cleanup in 1 second - m_CleanupUDPTimer.expires_at(m_CleanupUDPTimer.expires_at() + boost::posix_time::seconds(1)); - m_CleanupUDPTimer.async_wait(std::bind(&ClientContext::CleanupUDP, this, std::placeholders::_1)); - } + void ClientContext::ScheduleCleanupUDP() + { + // schedule cleanup in 1 second + m_CleanupUDPTimer.expires_at(m_CleanupUDPTimer.expires_at() + boost::posix_time::seconds(1)); + m_CleanupUDPTimer.async_wait(std::bind(&ClientContext::CleanupUDP, this, std::placeholders::_1)); + } - void ClientContext::CleanupUDP(const boost::system::error_code & ecode) - { - if(!ecode) - { - std::lock_guard lock(m_ForwardsMutex); - for ( auto & s : m_ServerForwards ) s.second->ExpireStale(); - ScheduleCleanupUDP(); - } - } + void ClientContext::CleanupUDP(const boost::system::error_code & ecode) + { + if(!ecode) + { + std::lock_guard lock(m_ForwardsMutex); + for ( auto & s : m_ServerForwards ) s.second->ExpireStale(); + ScheduleCleanupUDP(); + } + } } } diff --git a/ClientContext.h b/ClientContext.h index 0ff7993f..87dbec0f 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -24,8 +24,8 @@ namespace client const char I2P_TUNNELS_SECTION_TYPE_SERVER[] = "server"; const char I2P_TUNNELS_SECTION_TYPE_HTTP[] = "http"; const char I2P_TUNNELS_SECTION_TYPE_IRC[] = "irc"; - const char I2P_TUNNELS_SECTION_TYPE_UDPCLIENT[] = "udpclient"; - const char I2P_TUNNELS_SECTION_TYPE_UDPSERVER[] = "udpserver"; + const char I2P_TUNNELS_SECTION_TYPE_UDPCLIENT[] = "udpclient"; + const char I2P_TUNNELS_SECTION_TYPE_UDPSERVER[] = "udpserver"; const char I2P_CLIENT_TUNNEL_PORT[] = "port"; const char I2P_CLIENT_TUNNEL_ADDRESS[] = "address"; const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination"; @@ -75,10 +75,10 @@ namespace client template void ReadI2CPOptions (const Section& section, std::map& options) const; - void CleanupUDP(const boost::system::error_code & ecode); - void ScheduleCleanupUDP(); - - private: + void CleanupUDP(const boost::system::error_code & ecode); + void ScheduleCleanupUDP(); + + private: std::mutex m_DestinationsMutex; std::map > m_Destinations; @@ -91,25 +91,26 @@ namespace client std::map > m_ClientTunnels; // local endpoint->tunnel std::map, std::unique_ptr > m_ServerTunnels; // ->tunnel - std::mutex m_ForwardsMutex; - - std::map > m_ClientForwards; // local endpoint -> udp tunnel - std::map, std::unique_ptr > m_ServerForwards; // -> udp tunnel - - SAMBridge * m_SamBridge; + 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; - boost::asio::io_service m_Service; - std::thread * m_ServiceThread; + boost::asio::io_service m_Service; + std::thread * m_ServiceThread; - boost::asio::deadline_timer m_CleanupUDPTimer; - + boost::asio::deadline_timer m_CleanupUDPTimer; + public: // for HTTP const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; }; const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; }; const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; }; + const decltype(m_ClientForwards)& GetClientForwards () const { return m_ClientForwards; } + const decltype(m_ServerForwards)& GetServerForwards () const { return m_ServerForwards; } }; extern ClientContext context; diff --git a/Datagram.cpp b/Datagram.cpp index cdd468b1..37559922 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -13,22 +13,22 @@ namespace datagram { DatagramDestination::DatagramDestination (std::shared_ptr owner): m_Owner (owner.get()), - m_CleanupTimer(owner->GetService()), - m_Receiver (nullptr) + m_CleanupTimer(owner->GetService()), + m_Receiver (nullptr) { - ScheduleCleanup(); + ScheduleCleanup(); } DatagramDestination::~DatagramDestination () { - m_CleanupTimer.cancel(); - m_Sessions.clear(); + m_CleanupTimer.cancel(); + m_Sessions.clear(); } void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) { - auto owner = m_Owner; - auto i = owner->GetIdentity(); + auto owner = m_Owner; + auto i = owner->GetIdentity(); uint8_t buf[MAX_DATAGRAM_SIZE]; auto identityLen = i->ToBuffer (buf, MAX_DATAGRAM_SIZE); uint8_t * signature = buf + identityLen; @@ -41,15 +41,15 @@ namespace datagram { uint8_t hash[32]; SHA256(buf1, len, hash); - owner->Sign (hash, 32, signature); + owner->Sign (hash, 32, signature); } else owner->Sign (buf1, len, signature); auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort); - auto session = ObtainSession(ident); - session->SendMsg(msg); - } + auto session = ObtainSession(ident); + session->SendMsg(msg); + } void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) @@ -120,224 +120,274 @@ namespace datagram return msg; } - void DatagramDestination::ScheduleCleanup() - { - m_CleanupTimer.expires_from_now(boost::posix_time::seconds(DATAGRAM_SESSION_CLEANUP_INTERVAL)); - m_CleanupTimer.async_wait(std::bind(&DatagramDestination::HandleCleanUp, this, std::placeholders::_1)); - } + void DatagramDestination::ScheduleCleanup() + { + m_CleanupTimer.expires_from_now(boost::posix_time::seconds(DATAGRAM_SESSION_CLEANUP_INTERVAL)); + m_CleanupTimer.async_wait(std::bind(&DatagramDestination::HandleCleanUp, this, std::placeholders::_1)); + } - void DatagramDestination::HandleCleanUp(const boost::system::error_code & ecode) - { - if(ecode) - return; - std::lock_guard lock(m_SessionsMutex); - auto now = i2p::util::GetMillisecondsSinceEpoch(); - LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); - std::vector expiredSessions; - // for each session ... - for (auto & e : m_Sessions) { - // check if expired - if(now - e.second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) - expiredSessions.push_back(e.first); // we are expired - } - // for each expired session ... - for (auto & ident : expiredSessions) { - // remove the expired session - LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); - m_Sessions.erase(ident); - } - m_Owner->CleanupExpiredTags(); - ScheduleCleanup(); - } - - std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & ident) - { - std::shared_ptr session = nullptr; - std::lock_guard lock(m_SessionsMutex); - auto itr = m_Sessions.find(ident); - if (itr == m_Sessions.end()) { - // not found, create new session - session = std::make_shared(m_Owner, ident); - m_Sessions[ident] = session; - } else { - session = itr->second; - } - return session; - } + void DatagramDestination::HandleCleanUp(const boost::system::error_code & ecode) + { + if(ecode) + return; + std::lock_guard lock(m_SessionsMutex); + auto now = i2p::util::GetMillisecondsSinceEpoch(); + LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); + std::vector expiredSessions; + // for each session ... + for (auto & e : m_Sessions) { + // check if expired + if(now - e.second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) + expiredSessions.push_back(e.first); // we are expired + } + // for each expired session ... + for (auto & ident : expiredSessions) { + // remove the expired session + LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); + m_Sessions.erase(ident); + } + m_Owner->CleanupExpiredTags(); + ScheduleCleanup(); + } + + std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & ident) + { + std::shared_ptr session = nullptr; + std::lock_guard lock(m_SessionsMutex); + auto itr = m_Sessions.find(ident); + if (itr == m_Sessions.end()) { + // not found, create new session + session = std::make_shared(m_Owner, ident); + m_Sessions[ident] = session; + } else { + session = itr->second; + } + return session; + } - DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, - const i2p::data::IdentHash & remoteIdent) : - m_LocalDestination(localDestination), - m_RemoteIdentity(remoteIdent), - m_LastUse(i2p::util::GetMillisecondsSinceEpoch()) - { - } + DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, + const i2p::data::IdentHash & remoteIdent) : + m_LocalDestination(localDestination), + m_RemoteIdentity(remoteIdent), + m_LastUse(i2p::util::GetMillisecondsSinceEpoch ()), + m_LastPathChange(0), + m_LastSuccess(0) + { + } - void DatagramSession::SendMsg(std::shared_ptr msg) - { - // we used this session - m_LastUse = i2p::util::GetMillisecondsSinceEpoch(); - // schedule send - m_LocalDestination->GetService().post(std::bind(&DatagramSession::HandleSend, this, msg)); - } + void DatagramSession::SendMsg(std::shared_ptr msg) + { + // we used this session + m_LastUse = i2p::util::GetMillisecondsSinceEpoch(); + // schedule send + m_LocalDestination->GetService().post(std::bind(&DatagramSession::HandleSend, this, msg)); + } - void DatagramSession::HandleSend(std::shared_ptr msg) - { - // do we have a routing session? - if(m_RoutingSession) - { - // do we have a routing path ? - auto routingPath = m_RoutingSession->GetSharedRoutingPath(); - if(!routingPath) - { - LogPrint(eLogDebug, "DatagramSession: try getting new routing path"); - // no routing path, try getting one - routingPath = GetNextRoutingPath(); - if(routingPath) // remember the routing path if we got one - m_RoutingSession->SetSharedRoutingPath(routingPath); - } - // make sure we have a routing path - if (routingPath) - { - auto outboundTunnel = routingPath->outboundTunnel; - if (outboundTunnel) - { - if(outboundTunnel->IsEstablished()) - { - // we have a routing path and routing session and the outbound tunnel we are using is good - // wrap message with routing session and send down routing path's outbound tunnel wrapped for the IBGW - auto m = m_RoutingSession->WrapSingleMessage(msg); - routingPath->outboundTunnel->SendTunnelDataMsg({i2p::tunnel::TunnelMessageBlock{ - i2p::tunnel::eDeliveryTypeTunnel, - routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, - m - }}); - return; - } - } - } - } - // we couldn't send so let's try resetting the routing path and updating lease set - ResetRoutingPath(); - UpdateLeaseSet(msg); - - } + void DatagramSession::HandleSend(std::shared_ptr msg) + { + // do we have a routing session? + if(m_RoutingSession) + { + // should we switch paths? + if(ShouldUpdateRoutingPath ()) + { + LogPrint(eLogDebug, "DatagramSession: try getting new routing path"); + // try switching paths + UpdateRoutingPath (GetNextRoutingPath ()); + } + auto routingPath = m_RoutingSession->GetSharedRoutingPath (); + // make sure we have a routing path + if (routingPath) + { + auto outboundTunnel = routingPath->outboundTunnel; + if (outboundTunnel) + { + if(outboundTunnel->IsEstablished()) + { + m_LastSuccess = i2p::util::GetMillisecondsSinceEpoch (); + // we have a routing path and routing session and the outbound tunnel we are using is good + // wrap message with routing session and send down routing path's outbound tunnel wrapped for the IBGW + auto m = m_RoutingSession->WrapSingleMessage(msg); + routingPath->outboundTunnel->SendTunnelDataMsg({i2p::tunnel::TunnelMessageBlock{ + i2p::tunnel::eDeliveryTypeTunnel, + routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, + m + }}); + return; + } + } + } + } + auto now = i2p::util::GetMillisecondsSinceEpoch (); + // if this path looks dead reset the routing path since we didn't seem to be able to get a path in time + if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_TIMEOUT ) ResetRoutingPath(); + UpdateLeaseSet(msg); + + } - std::shared_ptr DatagramSession::GetNextRoutingPath() - { - std::shared_ptr outboundTunnel = nullptr; - std::shared_ptr routingPath = nullptr; - // get existing routing path if we have one - if(m_RoutingSession) - routingPath = m_RoutingSession->GetSharedRoutingPath(); - // do we have an existing outbound tunnel and routing path? - if(routingPath && routingPath->outboundTunnel) - { - // is the outbound tunnel we are using good? - if (routingPath->outboundTunnel->IsEstablished()) - { - // ya so let's stick with it - outboundTunnel = routingPath->outboundTunnel; - } - else - outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(routingPath->outboundTunnel); // no so we'll switch outbound tunnels - // don't reuse the old path as we are making a new one - routingPath = nullptr; - } - // do we have an outbound tunnel that works already ? - if(!outboundTunnel) - outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(); // no, let's get a new outbound tunnel as we probably just started + void DatagramSession::UpdateRoutingPath(const std::shared_ptr & path) + { + // we can't update routing path because we have no routing session + if(!m_RoutingSession) return; + // set routing path and update time we last updated the routing path + m_RoutingSession->SetSharedRoutingPath (path); + m_LastPathChange = i2p::util::GetMillisecondsSinceEpoch (); + } - if(outboundTunnel) - { - // get next available lease - auto lease = GetNextLease(); - if(lease) - { - // we have a valid lease to use and an outbound tunnel - // create new routing path - uint32_t now = i2p::util::GetSecondsSinceEpoch(); - routingPath = std::make_shared(i2p::garlic::GarlicRoutingPath{ - outboundTunnel, - lease, - 0, - now, - 0 - }); - } - } - return routingPath; - } + bool DatagramSession::ShouldUpdateRoutingPath() const + { + auto now = i2p::util::GetMillisecondsSinceEpoch (); + // we need to rotate paths becuase the routing path is too old + if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_SWITCH_INTERVAL) return true; + // our path looks dead so we need to rotate paths + if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return true; + // if we have a routing session and routing path we don't need to switch paths + return m_RoutingSession != nullptr && m_RoutingSession->GetSharedRoutingPath () != nullptr; + } - void DatagramSession::ResetRoutingPath() - { - if(m_RoutingSession) - { - auto routingPath = m_RoutingSession->GetSharedRoutingPath(); - if(routingPath && routingPath->remoteLease) // we have a remote lease already specified and a routing path - { - // get outbound tunnel on this path - auto outboundTunnel = routingPath->outboundTunnel; - // is this outbound tunnel there and established - if (outboundTunnel && outboundTunnel->IsEstablished()) - m_InvalidIBGW.push_back(routingPath->remoteLease->tunnelGateway); // yes, let's mark remote lease as dead because the outbound tunnel seems fine - } - // reset the routing path - m_RoutingSession->SetSharedRoutingPath(nullptr); - } - } - std::shared_ptr DatagramSession::GetNextLease() - { - std::shared_ptr next = nullptr; - if(m_RemoteLeaseSet) - { - std::vector exclude; - for(const auto & ident : m_InvalidIBGW) - exclude.push_back(ident); - // find get all leases that are not in our ban list - auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude] (const i2p::data::Lease & l) -> bool { - if(exclude.size()) - { - auto end = std::end(exclude); - return std::find_if(exclude.begin(), end, [l] ( const i2p::data::IdentHash & ident) -> bool { - return ident == l.tunnelGateway; - }) != end; - } - else - return false; - }); - if(leases.size()) - { - // pick random valid next lease - uint32_t idx = rand() % leases.size(); - next = leases[idx]; - } - } - return next; - } - - void DatagramSession::UpdateLeaseSet(std::shared_ptr msg) - { - LogPrint(eLogInfo, "DatagramSession: updating lease set"); - m_LocalDestination->RequestDestination(m_RemoteIdentity, std::bind(&DatagramSession::HandleGotLeaseSet, this, std::placeholders::_1, msg)); - } + bool DatagramSession::ShouldSwitchLease() const + { + auto now = i2p::util::GetMillisecondsSinceEpoch (); + std::shared_ptr routingPath = nullptr; + std::shared_ptr currentLease = nullptr; + if(m_RoutingSession) + routingPath = m_RoutingSession->GetSharedRoutingPath (); + if(routingPath) + currentLease = routingPath->remoteLease; + if(currentLease) // if we have a lease return true if it's about to expire otherwise return false + return now - currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE ); + // we have no current lease, we should switch + return true; + } + + std::shared_ptr DatagramSession::GetNextRoutingPath() + { + std::shared_ptr outboundTunnel = nullptr; + std::shared_ptr routingPath = nullptr; + // get existing routing path if we have one + if(m_RoutingSession) + routingPath = m_RoutingSession->GetSharedRoutingPath(); + // do we have an existing outbound tunnel and routing path? + if(routingPath && routingPath->outboundTunnel) + { + // is the outbound tunnel we are using good? + if (routingPath->outboundTunnel->IsEstablished()) + { + // ya so let's stick with it + outboundTunnel = routingPath->outboundTunnel; + } + else + outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(routingPath->outboundTunnel); // no so we'll switch outbound tunnels + } + // do we have an outbound tunnel that works already ? + if(!outboundTunnel) + outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(); // no, let's get a new outbound tunnel as we probably just started - void DatagramSession::HandleGotLeaseSet(std::shared_ptr remoteIdent, std::shared_ptr msg) - { - if(remoteIdent) { - // update routing session - if(m_RoutingSession) - m_RoutingSession = nullptr; - m_RoutingSession = m_LocalDestination->GetRoutingSession(remoteIdent, true); - // clear invalid IBGW as we have a new lease set - m_InvalidIBGW.clear(); - m_RemoteLeaseSet = remoteIdent; - // send the message that was queued if it was provided - if(msg) - HandleSend(msg); - } - } + if(outboundTunnel) + { + std::shared_ptr lease = nullptr; + // should we switch leases ? + if (ShouldSwitchLease ()) + { + // yes, get next available lease + lease = GetNextLease(); + } + else if (routingPath) + { + // stick with the lease we have if we have one + lease = routingPath->remoteLease; + } + if(lease) + { + // we have a valid lease to use and an outbound tunnel + // create new routing path + uint32_t now = i2p::util::GetSecondsSinceEpoch(); + routingPath = std::make_shared(i2p::garlic::GarlicRoutingPath{ + outboundTunnel, + lease, + 0, + now, + 0 + }); + } + else // we don't have a new routing path to give + routingPath = nullptr; + } + return routingPath; + } + + void DatagramSession::ResetRoutingPath() + { + if(m_RoutingSession) + { + auto routingPath = m_RoutingSession->GetSharedRoutingPath(); + if(routingPath && routingPath->remoteLease) // we have a remote lease already specified and a routing path + { + // get outbound tunnel on this path + auto outboundTunnel = routingPath->outboundTunnel; + // is this outbound tunnel there and established + if (outboundTunnel && outboundTunnel->IsEstablished()) + m_InvalidIBGW.push_back(routingPath->remoteLease->tunnelGateway); // yes, let's mark remote lease as dead because the outbound tunnel seems fine + } + // reset the routing path + UpdateRoutingPath(nullptr); + } + } + + std::shared_ptr DatagramSession::GetNextLease() + { + auto now = i2p::util::GetMillisecondsSinceEpoch (); + std::shared_ptr next = nullptr; + if(m_RemoteLeaseSet) + { + std::vector exclude; + for(const auto & ident : m_InvalidIBGW) + exclude.push_back(ident); + // find get all leases that are not in our ban list and are not going to expire within our lease set handover window + fudge + auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude, now] (const i2p::data::Lease & l) -> bool { + if(exclude.size()) + { + auto end = std::end(exclude); + return std::find_if(exclude.begin(), end, [l, now] ( const i2p::data::IdentHash & ident) -> bool { + return ident == l.tunnelGateway || l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); + }) != end; + } + else + return l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); + }); + if(leases.size()) + { + // pick random valid next lease + uint32_t idx = rand() % leases.size(); + next = leases[idx]; + } + } + return next; + } + + void DatagramSession::UpdateLeaseSet(std::shared_ptr msg) + { + LogPrint(eLogInfo, "DatagramSession: updating lease set"); + m_LocalDestination->RequestDestination(m_RemoteIdentity, std::bind(&DatagramSession::HandleGotLeaseSet, this, std::placeholders::_1, msg)); + } + + void DatagramSession::HandleGotLeaseSet(std::shared_ptr remoteIdent, std::shared_ptr msg) + { + if(remoteIdent) + { + // update routing session + if(m_RoutingSession) + m_RoutingSession = nullptr; + m_RoutingSession = m_LocalDestination->GetRoutingSession(remoteIdent, true); + // clear invalid IBGW as we have a new lease set + m_InvalidIBGW.clear(); + m_RemoteLeaseSet = remoteIdent; + // send the message that was queued if it was provided + if(msg) + HandleSend(msg); + } + } } } diff --git a/Datagram.h b/Datagram.h index 887c82d2..fd1f290d 100644 --- a/Datagram.h +++ b/Datagram.h @@ -20,51 +20,70 @@ namespace client namespace datagram { - // seconds interval for cleanup timer - const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 3; - // milliseconds for max session idle time (10 minutes) - const uint64_t DATAGRAM_SESSION_MAX_IDLE = 3600 * 1000; + // seconds interval for cleanup timer + const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 3; + // 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 = 5000; + // milliseconds interval a routing path is used before switching + const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 60 * 1000; + // milliseconds before lease expire should we try switching leases + const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW = 10 * 1000; + // milliseconds fudge factor for leases handover + const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; - - class DatagramSession - { - public: - DatagramSession(i2p::client::ClientDestination * localDestination, - const i2p::data::IdentHash & remoteIdent); + + class DatagramSession + { + public: + DatagramSession(i2p::client::ClientDestination * localDestination, + const i2p::data::IdentHash & remoteIdent); - /** send an i2np message to remote endpoint for this session */ - void SendMsg(std::shared_ptr msg); - /** get the last time in milliseconds for when we used this datagram session */ - uint64_t LastActivity() const { return m_LastUse; } - private: + /** send an i2np message to remote endpoint for this session */ + void SendMsg(std::shared_ptr msg); + /** get the last time in milliseconds for when we used this datagram session */ + uint64_t LastActivity() const { return m_LastUse; } + private: - /** get next usable routing path, try reusing outbound tunnels */ - std::shared_ptr GetNextRoutingPath(); - /** - * mark current routing path as invalid and clear it - * if the outbound tunnel we were using was okay don't use the IBGW in the routing path's lease next time - */ - void ResetRoutingPath(); + /** update our routing path we are using, mark that we have changed paths */ + void UpdateRoutingPath(const std::shared_ptr & path); - /** get next usable lease, does not fetch or update if expired or have no lease set */ - std::shared_ptr GetNextLease(); - - void HandleSend(std::shared_ptr msg); - void HandleGotLeaseSet(std::shared_ptr remoteIdent, - std::shared_ptr msg); - void UpdateLeaseSet(std::shared_ptr msg=nullptr); - - private: - i2p::client::ClientDestination * m_LocalDestination; - i2p::data::IdentHash m_RemoteIdentity; - std::shared_ptr m_RoutingSession; - // Ident hash of IBGW that are invalid - std::vector m_InvalidIBGW; - std::shared_ptr m_RemoteLeaseSet; - uint64_t m_LastUse; - }; - - const size_t MAX_DATAGRAM_SIZE = 32768; + /** return true if we should switch routing paths because of path lifetime or timeout otherwise false */ + bool ShouldUpdateRoutingPath() const; + + /** return true if we should switch the lease for out routing path otherwise return false */ + bool ShouldSwitchLease() const; + + /** get next usable routing path, try reusing outbound tunnels */ + std::shared_ptr GetNextRoutingPath(); + /** + * mark current routing path as invalid and clear it + * if the outbound tunnel we were using was okay don't use the IBGW in the routing path's lease next time + */ + void ResetRoutingPath(); + + /** get next usable lease, does not fetch or update if expired or have no lease set */ + std::shared_ptr GetNextLease(); + + void HandleSend(std::shared_ptr msg); + void HandleGotLeaseSet(std::shared_ptr remoteIdent, + std::shared_ptr msg); + void UpdateLeaseSet(std::shared_ptr msg=nullptr); + + private: + i2p::client::ClientDestination * m_LocalDestination; + i2p::data::IdentHash m_RemoteIdentity; + std::shared_ptr m_RoutingSession; + // Ident hash of IBGW that are invalid + std::vector m_InvalidIBGW; + std::shared_ptr m_RemoteLeaseSet; + uint64_t m_LastUse; + uint64_t m_LastPathChange; + uint64_t m_LastSuccess; + }; + + const size_t MAX_DATAGRAM_SIZE = 32768; class DatagramDestination { typedef std::function Receiver; @@ -82,15 +101,15 @@ namespace datagram void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; }; void ResetReceiver (uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); }; - + private: - // clean up after next tick - void ScheduleCleanup(); - - // clean up stale sessions and expire tags - void HandleCleanUp(const boost::system::error_code & ecode); - - std::shared_ptr ObtainSession(const i2p::data::IdentHash & ident); + // clean up after next tick + void ScheduleCleanup(); + + // clean up stale sessions and expire tags + void HandleCleanUp(const boost::system::error_code & ecode); + + 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); diff --git a/LeaseSet.cpp b/LeaseSet.cpp index ab0407cc..04dc77c5 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -163,9 +163,10 @@ namespace data return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); } - bool LeaseSet::ExpiresSoon(const uint64_t dlt) const + bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const { auto now = i2p::util::GetMillisecondsSinceEpoch (); + if (fudge) now += rand() % fudge; if (now >= m_ExpirationTime) return true; return m_ExpirationTime - now <= dlt; } diff --git a/LeaseSet.h b/LeaseSet.h index 9b6b7844..ed21eccd 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -7,6 +7,7 @@ #include #include #include "Identity.h" +#include "Timestamp.h" namespace i2p { @@ -24,7 +25,13 @@ namespace data IdentHash tunnelGateway; uint32_t tunnelID; uint64_t endDate; // 0 means invalid - bool isUpdated; // trasient + bool isUpdated; // trasient + /* return true if this lease expires within t millisecond + fudge factor */ + bool ExpiresWithin( const uint64_t t, const uint64_t fudge = 1000 ) const { + auto expire = i2p::util::GetMillisecondsSinceEpoch (); + if(fudge) expire += rand() % fudge; + return expire - endDate >= t; + } }; struct LeaseCmp @@ -63,7 +70,7 @@ namespace data bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; - bool ExpiresSoon(const uint64_t dlt=1000 * 5) const ; + bool ExpiresSoon(const uint64_t dlt=1000 * 5, const uint64_t fudge = 0) const ; bool operator== (const LeaseSet& other) const { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; diff --git a/Streaming.cpp b/Streaming.cpp index 0908ff4a..308ba02b 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -268,12 +268,12 @@ namespace stream } } auto sentPacket = *it; - uint64_t rtt = ts - sentPacket->sendTime; - if(ts < sentPacket->sendTime) - { - LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime); - rtt = 1; - } + uint64_t rtt = ts - sentPacket->sendTime; + if(ts < sentPacket->sendTime) + { + LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime); + rtt = 1; + } m_RTT = (m_RTT*seqn + rtt)/(seqn + 1); m_RTO = m_RTT*1.5; // TODO: implement it better LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt, " sentTime=", sentPacket->sendTime); From fa1021df5942c16108ce6bdf2d9b370617a0bfd6 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 13:58:34 -0400 Subject: [PATCH 105/141] add webui for udp tunnels --- ClientContext.cpp | 16 +++++++++++++++ ClientContext.h | 4 +++- Datagram.cpp | 33 ++++++++++++++++++++++++++++++ Datagram.h | 21 +++++++++++++++++++ HTTPServer.cpp | 31 ++++++++++++++++++++++++++++ I2PTunnel.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++ I2PTunnel.h | 27 ++++++++++++++++++++++-- 7 files changed, 181 insertions(+), 3 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 3c4d63c0..6ef7ec60 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -276,6 +276,22 @@ namespace client return success; } + std::vector ClientContext::GetForwardInfosFor(const i2p::data::IdentHash & destination) + { + std::lock_guard lock(m_ForwardsMutex); + for(auto & c : m_ClientForwards) + { + if (c.second->IsLocalDestination(destination)) + return c.second->GetSessions(); + } + for(auto & s : m_ServerForwards) + { + if(std::get<0>(s.first) == destination) + return s.second->GetSessions(); + } + return {}; + } + std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, const std::map * params) { diff --git a/ClientContext.h b/ClientContext.h index 87dbec0f..7faf04ca 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -66,7 +66,9 @@ namespace client AddressBook& GetAddressBook () { return m_AddressBook; }; const SAMBridge * GetSAMBridge () const { return m_SamBridge; }; - + + std::vector GetForwardInfosFor(const i2p::data::IdentHash & destination); + private: void ReadTunnels (); diff --git a/Datagram.cpp b/Datagram.cpp index 37559922..42354945 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -165,6 +165,16 @@ namespace datagram return session; } + std::shared_ptr DatagramDestination::GetInfoForRemote(const i2p::data::IdentHash & remote) + { + std::lock_guard lock(m_SessionsMutex); + for ( auto & item : m_Sessions) + { + if(item.first == remote) return std::make_shared(item.second->GetSessionInfo()); + } + return nullptr; + } + DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), @@ -183,6 +193,29 @@ namespace datagram m_LocalDestination->GetService().post(std::bind(&DatagramSession::HandleSend, this, msg)); } + DatagramSession::Info DatagramSession::GetSessionInfo() const + { + if(!m_RoutingSession) + return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; + + auto routingPath = m_RoutingSession->GetSharedRoutingPath(); + if (!routingPath) + return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; + auto lease = routingPath->remoteLease; + auto tunnel = routingPath->outboundTunnel; + if(lease) + { + if(tunnel) + return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway), new i2p::data::IdentHash(tunnel->GetEndpointIdentHash()), m_LastUse, m_LastSuccess}; + else + return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway), nullptr, m_LastUse, m_LastSuccess}; + } + else if(tunnel) + return DatagramSession::Info{nullptr, new i2p::data::IdentHash(tunnel->GetEndpointIdentHash()), m_LastUse, m_LastSuccess}; + else + return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; + } + void DatagramSession::HandleSend(std::shared_ptr msg) { // do we have a routing session? diff --git a/Datagram.h b/Datagram.h index fd1f290d..a44133f7 100644 --- a/Datagram.h +++ b/Datagram.h @@ -44,6 +44,24 @@ namespace datagram void SendMsg(std::shared_ptr msg); /** get the last time in milliseconds for when we used this datagram session */ uint64_t LastActivity() const { return m_LastUse; } + /** get the last time in milliseconds when we successfully sent data */ + uint64_t LastSuccess() const { return m_LastSuccess; } + struct Info + { + const i2p::data::IdentHash * IBGW; + const i2p::data::IdentHash * OBEP; + const uint64_t activity; + const uint64_t success; + ~Info() + { + if(IBGW) delete IBGW; + if(OBEP) delete OBEP; + } + }; + + Info GetSessionInfo() const; + + private: /** update our routing path we are using, mark that we have changed paths */ @@ -90,6 +108,7 @@ namespace datagram public: + DatagramDestination (std::shared_ptr owner); ~DatagramDestination (); @@ -101,6 +120,8 @@ namespace datagram void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; }; void ResetReceiver (uint16_t port) { std::lock_guard lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); }; + + std::shared_ptr GetInfoForRemote(const i2p::data::IdentHash & remote); private: // clean up after next tick diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 309e3f6b..56756277 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -337,7 +337,38 @@ namespace http { s << "" << it->GetWindowSize () << ""; s << "" << (int)it->GetStatus () << ""; s << "
\r\n" << std::endl; + } + s << "
\r\n"; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + auto forward = i2p::client::context.GetForwardInfosFor(dest->GetIdentHash()); + for (auto & info : forward) + { + s << ""; + s << ""; + s << ""; + + s << ""; + s << ""; + auto sec = std::chrono::duration >( std::chrono::milliseconds(info.idle) ); + s << ""; + s << "
\r\n"; } + s << "
Forwards
Remote DestinationIBGWOBEPUDP ConverstationIdle Time
" << info.RemoteIdent.ToBase32() << ""; + if(info.CurrentIBGW) + s << info.CurrentIBGW->ToBase64(); + else + s << "(none)"; + s << ""; + if(info.CurrentOBEP) + s << info.CurrentOBEP->ToBase64(); + else + s << "(none)"; + s << "" << info.LocalEndpoint << " ⇄ " << info.RemoteEndpoint << "" << sec.count() << " seconds
\r\n"; } } diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 087221a3..386c0cd2 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -631,6 +631,30 @@ namespace client void I2PUDPServerTunnel::Start() { m_LocalDest->Start(); } + + std::vector I2PUDPServerTunnel::GetSessions() + { + std::vector sessions; + auto localident = m_LocalDest->GetIdentHash(); + std::lock_guard lock(m_SessionsMutex); + for ( UDPSession * s : m_Sessions ) + { + if (!s->m_Destination) continue; + auto info = s->m_Destination->GetInfoForRemote(s->Identity); + if(!info) continue; + sessions.push_back(DatagramSessionInfo{ + m_Name, + localident, + s->Identity, + info->IBGW, + info->OBEP, + s->IPSocket.local_endpoint(), + s->SendEndpoint, + info->success + }); + } + return sessions; + } I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, @@ -662,6 +686,34 @@ namespace client m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); } + std::vector I2PUDPClientTunnel::GetSessions() + { + std::vector infos; + if(m_Session && m_LocalDest) + { + auto localident = m_LocalDest->GetIdentHash(); + auto s = m_Session; + if (s->m_Destination) + { + auto info = m_Session->m_Destination->GetInfoForRemote(s->Identity); + if(!info) + { + infos.push_back(DatagramSessionInfo{ + m_Name, + localident, + s->Identity, + info->IBGW, + info->OBEP, + s->IPSocket.local_endpoint(), + s->SendEndpoint, + info->success + }); + } + } + } + return infos; + } + void I2PUDPClientTunnel::TryResolving() { LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); m_RemoteIdent = new i2p::data::IdentHash; diff --git a/I2PTunnel.h b/I2PTunnel.h index 76bfc36b..7fe58574 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -137,7 +137,28 @@ namespace client /** max size for i2p udp */ const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; - + + /** read only info about a datagram session */ + struct DatagramSessionInfo + { + /** the name of this forward */ + const std::string Name; + /** ident hash of local destination */ + const i2p::data::IdentHash LocalIdent; + /** ident hash of remote destination */ + const i2p::data::IdentHash RemoteIdent; + /** ident hash of IBGW in use currently in this session or nullptr if none is set */ + const i2p::data::IdentHash * CurrentIBGW; + /** ident hash of OBEP in use for this session or nullptr if none is set */ + const i2p::data::IdentHash * CurrentOBEP; + /** i2p router's udp endpoint */ + const boost::asio::ip::udp::endpoint LocalEndpoint; + /** client's udp endpoint */ + const boost::asio::ip::udp::endpoint RemoteEndpoint; + /** how long has this converstation been idle in ms */ + const uint64_t idle; + }; + struct UDPSession { i2p::datagram::DatagramDestination * m_Destination; @@ -174,6 +195,7 @@ namespace client void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); void Start(); const char * GetName() const { return m_Name.c_str(); } + std::vector GetSessions(); private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSession * ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); @@ -196,7 +218,8 @@ namespace client ~I2PUDPClientTunnel(); 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(); } private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void TryResolving(); From 571c630d9360ddc7621c2e415f1f66c0ea78c8a2 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 14:37:36 -0400 Subject: [PATCH 106/141] try creating routing session if not present --- Datagram.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Datagram.cpp b/Datagram.cpp index 42354945..8b4c440b 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -260,7 +260,8 @@ namespace datagram void DatagramSession::UpdateRoutingPath(const std::shared_ptr & path) { - // we can't update routing path because we have no routing session + if(m_RoutingSession == nullptr && m_RemoteLeaseSet) + m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); if(!m_RoutingSession) return; // set routing path and update time we last updated the routing path m_RoutingSession->SetSharedRoutingPath (path); From 8cdd3a0abbf3fc779f772611e29f7755334be85a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 14:42:27 -0400 Subject: [PATCH 107/141] update routing path when we get a new lease set --- Datagram.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Datagram.cpp b/Datagram.cpp index 8b4c440b..1d1f5d2d 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -417,6 +417,8 @@ namespace datagram // clear invalid IBGW as we have a new lease set m_InvalidIBGW.clear(); m_RemoteLeaseSet = remoteIdent; + // update routing path + UpdateRoutingPath(GetNextRoutingPath()); // send the message that was queued if it was provided if(msg) HandleSend(msg); From 7cc805b2034a0b49904990051a397b0ff50f5aac Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 14:56:51 -0400 Subject: [PATCH 108/141] update datagram session logic --- Datagram.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index 1d1f5d2d..0802295a 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -146,7 +146,6 @@ namespace datagram LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); m_Sessions.erase(ident); } - m_Owner->CleanupExpiredTags(); ScheduleCleanup(); } @@ -174,7 +173,7 @@ namespace datagram } return nullptr; } - + DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), @@ -215,9 +214,14 @@ namespace datagram else return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; } - + void DatagramSession::HandleSend(std::shared_ptr msg) { + if(!m_RoutingSession) + { + // try to get one + if(m_RemoteLeaseSet) m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); + } // do we have a routing session? if(m_RoutingSession) { @@ -226,7 +230,11 @@ namespace datagram { LogPrint(eLogDebug, "DatagramSession: try getting new routing path"); // try switching paths - UpdateRoutingPath (GetNextRoutingPath ()); + auto path = GetNextRoutingPath(); + if(path) + UpdateRoutingPath (path); + else + ResetRoutingPath(); } auto routingPath = m_RoutingSession->GetSharedRoutingPath (); // make sure we have a routing path @@ -282,7 +290,6 @@ namespace datagram bool DatagramSession::ShouldSwitchLease() const { - auto now = i2p::util::GetMillisecondsSinceEpoch (); std::shared_ptr routingPath = nullptr; std::shared_ptr currentLease = nullptr; if(m_RoutingSession) @@ -290,7 +297,7 @@ namespace datagram if(routingPath) currentLease = routingPath->remoteLease; if(currentLease) // if we have a lease return true if it's about to expire otherwise return false - return now - currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE ); + return currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE ); // we have no current lease, we should switch return true; } @@ -418,7 +425,11 @@ namespace datagram m_InvalidIBGW.clear(); m_RemoteLeaseSet = remoteIdent; // update routing path - UpdateRoutingPath(GetNextRoutingPath()); + auto path = GetNextRoutingPath(); + if (path) + UpdateRoutingPath(path); + else + ResetRoutingPath(); // send the message that was queued if it was provided if(msg) HandleSend(msg); From 75981491a7b5a197d4730d54a94c97e481517806 Mon Sep 17 00:00:00 2001 From: libre-net-society Date: Sat, 3 Sep 2016 22:23:48 +0300 Subject: [PATCH 109/141] adding usage docs --- docs/index.rst | 1 + docs/usage.md | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 docs/usage.md diff --git a/docs/index.rst b/docs/index.rst index 13cd9edb..5507b075 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -35,5 +35,6 @@ Contents: build_notes_android configuration family + usage diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 00000000..cb678cb4 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,130 @@ +Usage and tutorials +=================== + + +i2pd can be used for: + +* [anonymous websites](#browsing-and-hosting-websites) +* [anonymous chats](#using-and-hosting-chat-servers) +* [anonymous file sharing](#file-sharing) + +and many more. + +## Browsing and hosting websites + +### Browse anonymous websites + +To browse anonymous websites inside Invisible Internet, configure your web browser to use HTTP proxy 127.0.0.1:4444 (available by default in i2pd). + +In Firefox: Preferences -> Advanced -> Network tab -> Connection Settings -> choose Manual proxy configuration, Enter HTTP proxy 127.0.0.1, Port 4444 + +In Chromium: run chromium executable with key + + chromium --proxy-server="http://127.0.0.1:4444" + +Note that if you wish to stay anonymous too you'll need to tune your browser for better privacy. Do your own research, [can start here](http://www.howtogeek.com/102032/how-to-optimize-mozilla-firefox-for-maximum-privacy/). + +Big list of Invisible Internet websites can be found at [identiguy.i2p](http://identiguy.i2p). + +### Host anonymous website + + +If you wish to run your own website in Invisible Internet, follow those steps: + +1) Run your webserver and find out which host:port it uses (for example, 127.0.0.1:8080). + +2) Configure i2pd to create HTTP server tunnel. Put in your ~/.i2pd/tunnels.conf file: + + [anon-website] + type = http + host = 127.0.0.1 + port = 8080 + keys = anon-website.dat + +3) Restart i2pd. + +4) Find b32 destination of your website. + +Go to webconsole -> [I2P tunnels page](http://127.0.0.1:7070/?page=i2p_tunnels). Look for Sever tunnels and you will see address like \.b32.i2p next to anon-website. + +Website is now available in Invisible Internet by visiting this address. + +5) (Optional) Register short and rememberable .i2p domain on [inr.i2p](http://inr.i2p). + + +## Using and hosting chat servers + +### Running anonymous IRC server + +1) Run your IRC server software and find out which host:port it uses (for example, 127.0.0.1:5555). + +For small private IRC servers you can use [miniircd](https://github.com/jrosdahl/miniircd), for large public networks [UnreadIRCd](https://www.unrealircd.org/). + +2) Configure i2pd to create IRC server tunnel. + +Simplest case, if your server does not support WebIRC, add this to ~/.i2pd/tunnels.conf: + + [anon-chatserver] + type = irc + host = 127.0.0.1 + port = 5555 + keys = chatserver-key.dat + +And that is it. + +Alternatively, if your IRC server supports WebIRC, for example, UnreadIRCd, put this into UnrealIRCd config: + + webirc { + mask 127.0.0.1; + password your_password; + }; + +Also change line: + + modes-on-connect "+ixw"; + +to + + modes-on-connect "+iw"; + +And this in ~/.i2pd/tunnels.conf: + + [anon-chatserver] + type = irc + host = 127.0.0.1 + port = 5555 + keys = chatserver-key.dat + webircpassword = your_password + +3) Restart i2pd. + +4) Find b32 destination of your anonymous IRC server. + +Go to webconsole -> [I2P tunnels page](http://127.0.0.1:7070/?page=i2p_tunnels). Look for Sever tunnels and you will see address like \.b32.i2p next to anon-chatserver. + +Clients will use this address to connect to your server anonymously. + +### Connect to anonymous IRC server + +To connect to IRC server at *walker.i2p*, add this to ~/.i2pd/tunnels.conf: + + [IRC2] + type = client + address = 127.0.0.1 + port = 6669 + destination = walker.i2p + #keys = walker-keys.dat + +Restart i2pd, then connect to irc://127.0.0.1:6669 with your IRC client. + +## File sharing + +You can share and download torrents with [Transmission-I2P](https://github.com/l-n-s/transmission-i2p). + +Alternative torrent-clients are [Robert](http://en.wikipedia.org/wiki/Robert_%28P2P_Software%29) and [Vuze](https://en.wikipedia.org/wiki/Vuze). + +Robert uses BOB protocol, i2pd must be run with parameter --bob.enabled=true. + +Vuze uses I2CP protocol, i2pd must be run with parameter --i2cp.enabled=true. + +Also, visit [postman tracker](http://tracker2.postman.i2p). From 682334d844205154add31dbc2afd1f3285c43013 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 15:35:32 -0400 Subject: [PATCH 110/141] fix typo --- LeaseSet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LeaseSet.h b/LeaseSet.h index ed21eccd..95d8bf90 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -30,7 +30,7 @@ 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 expire - endDate >= t; + return endDate - expire >= t; } }; From 68b0775e4bd431334a3975eb12929738d3566aff Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 15:35:42 -0400 Subject: [PATCH 111/141] update datagram path logic --- Datagram.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Datagram.cpp b/Datagram.cpp index 0802295a..1a97afc5 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -221,6 +221,11 @@ namespace datagram { // try to get one if(m_RemoteLeaseSet) m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); + else + { + UpdateLeaseSet(msg); + return; + } } // do we have a routing session? if(m_RoutingSession) @@ -261,7 +266,7 @@ namespace datagram } auto now = i2p::util::GetMillisecondsSinceEpoch (); // if this path looks dead reset the routing path since we didn't seem to be able to get a path in time - if (now - m_LastPathChange >= DATAGRAM_SESSION_PATH_TIMEOUT ) ResetRoutingPath(); + if (m_LastPathChange && now - m_LastPathChange >= DATAGRAM_SESSION_PATH_TIMEOUT ) ResetRoutingPath(); UpdateLeaseSet(msg); } From 783c0c7c7ba63db4b9773add67ed73c1754cc14e Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 15:53:28 -0400 Subject: [PATCH 112/141] update datagram lease selection --- Datagram.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index 1a97afc5..3d5dec8b 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -341,9 +341,16 @@ namespace datagram } else if (routingPath) { - // stick with the lease we have if we have one - lease = routingPath->remoteLease; + if(routingPath->remoteLease) + { + if(routingPath->remoteLease->ExpiresSoon()) + lease = GetNextLease(); + else + lease = routingPath->remoteLease; + } } + else + lease = GetNextLease(); if(lease) { // we have a valid lease to use and an outbound tunnel @@ -408,6 +415,8 @@ namespace datagram uint32_t idx = rand() % leases.size(); next = leases[idx]; } + else + LogPrint(eLogWarning, "DatagramDestination: no leases to use"); } return next; } From 7ea8509dfe1583bfa8834812791bb885f3c858b6 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 15:54:22 -0400 Subject: [PATCH 113/141] fix typo --- Datagram.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Datagram.cpp b/Datagram.cpp index 3d5dec8b..ba365cd5 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -343,7 +343,7 @@ namespace datagram { if(routingPath->remoteLease) { - if(routingPath->remoteLease->ExpiresSoon()) + if(routingPath->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE)) lease = GetNextLease(); else lease = routingPath->remoteLease; From d37a790b57aaa73191fafb8d014bb23d10e1be6c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 15:58:52 -0400 Subject: [PATCH 114/141] fix another typo --- Datagram.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index ba365cd5..ba010639 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -403,8 +403,8 @@ namespace datagram { auto end = std::end(exclude); return std::find_if(exclude.begin(), end, [l, now] ( const i2p::data::IdentHash & ident) -> bool { - return ident == l.tunnelGateway || l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); - }) != end; + return ident == l.tunnelGateway; + }) != end || l.ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); } else return l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); From 7e99be12b0c90ad30b8c103b7d8c56e2210f6e5a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 16:03:38 -0400 Subject: [PATCH 115/141] fix typo --- Datagram.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index ba010639..5fd12b28 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -399,15 +399,17 @@ namespace datagram exclude.push_back(ident); // find get all leases that are not in our ban list and are not going to expire within our lease set handover window + fudge auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude, now] (const i2p::data::Lease & l) -> bool { + if(l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE)) + return true; if(exclude.size()) { auto end = std::end(exclude); return std::find_if(exclude.begin(), end, [l, now] ( const i2p::data::IdentHash & ident) -> bool { return ident == l.tunnelGateway; - }) != end || l.ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); + }) != end; } else - return l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE); + return false; }); if(leases.size()) { From 10ffd5c1abd1168073e9c30b9a3205d4a3628ac4 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 16:06:14 -0400 Subject: [PATCH 116/141] don't check for expired lease --- Datagram.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index 5fd12b28..adecb41f 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -399,8 +399,6 @@ namespace datagram exclude.push_back(ident); // find get all leases that are not in our ban list and are not going to expire within our lease set handover window + fudge auto leases = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding( [&exclude, now] (const i2p::data::Lease & l) -> bool { - if(l.ExpiresWithin (DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE)) - return true; if(exclude.size()) { auto end = std::end(exclude); From 2f61dd1c41b768f82aec57ae0a468065d5f88e55 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 16:12:43 -0400 Subject: [PATCH 117/141] fix double free --- Datagram.cpp | 6 +++--- Tag.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index adecb41f..a3da6527 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -205,12 +205,12 @@ namespace datagram if(lease) { if(tunnel) - return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway), new i2p::data::IdentHash(tunnel->GetEndpointIdentHash()), m_LastUse, m_LastSuccess}; + return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway.data()), new i2p::data::IdentHash(tunnel->GetEndpointIdentHash().data()), m_LastUse, m_LastSuccess}; else - return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway), nullptr, m_LastUse, m_LastSuccess}; + return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway.data()), nullptr, m_LastUse, m_LastSuccess}; } else if(tunnel) - return DatagramSession::Info{nullptr, new i2p::data::IdentHash(tunnel->GetEndpointIdentHash()), m_LastUse, m_LastSuccess}; + return DatagramSession::Info{nullptr, new i2p::data::IdentHash(tunnel->GetEndpointIdentHash().data()), m_LastUse, m_LastSuccess}; else return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; } diff --git a/Tag.h b/Tag.h index 4b393c57..0861cb8e 100644 --- a/Tag.h +++ b/Tag.h @@ -50,6 +50,8 @@ namespace data { return true; } + const uint8_t * data() const { return m_Buf; } + /** fill with a value */ void Fill(uint8_t c) { From d336d920e8b8cdf5351df681f02bc5d2e25789c0 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 16:16:16 -0400 Subject: [PATCH 118/141] fix typo --- I2PTunnel.cpp | 2 +- Tag.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 386c0cd2..688866c8 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -696,7 +696,7 @@ namespace client if (s->m_Destination) { auto info = m_Session->m_Destination->GetInfoForRemote(s->Identity); - if(!info) + if(info) { infos.push_back(DatagramSessionInfo{ m_Name, diff --git a/Tag.h b/Tag.h index 0861cb8e..92e2f1a5 100644 --- a/Tag.h +++ b/Tag.h @@ -20,7 +20,7 @@ namespace data { { public: - Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }; + Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }; Tag (const Tag& ) = default; #ifndef _WIN32 // FIXME!!! msvs 2013 can't compile it Tag (Tag&& ) = default; From 82f46464f3afa7dde91a37677a1f23dbde9e2362 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 16:29:50 -0400 Subject: [PATCH 119/141] prevent double free --- Datagram.cpp | 6 +++--- Datagram.h | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index a3da6527..2247dff1 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -205,12 +205,12 @@ namespace datagram if(lease) { if(tunnel) - return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway.data()), new i2p::data::IdentHash(tunnel->GetEndpointIdentHash().data()), m_LastUse, m_LastSuccess}; + return DatagramSession::Info{lease->tunnelGateway, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess}; else - return DatagramSession::Info{new i2p::data::IdentHash(lease->tunnelGateway.data()), nullptr, m_LastUse, m_LastSuccess}; + return DatagramSession::Info{lease->tunnelGateway, nullptr, m_LastUse, m_LastSuccess}; } else if(tunnel) - return DatagramSession::Info{nullptr, new i2p::data::IdentHash(tunnel->GetEndpointIdentHash().data()), m_LastUse, m_LastSuccess}; + return DatagramSession::Info{nullptr, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess}; else return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; } diff --git a/Datagram.h b/Datagram.h index a44133f7..add946f0 100644 --- a/Datagram.h +++ b/Datagram.h @@ -52,6 +52,12 @@ namespace datagram const i2p::data::IdentHash * OBEP; const uint64_t activity; const uint64_t success; + Info() : IBGW(nullptr), OBEP(nullptr), activity(0), success(0) {} + Info(const i2p::data::IdentHash & ibgw, const i2p::data::IdentHash & obep, const uint64_t a, const uint64_t s) : + IBGW(new i2p::data::IdentHash(ibgw.data())), + OBEP(new i2p::data::IdentHash(obep.data())), + activity(a), + success(s) {} ~Info() { if(IBGW) delete IBGW; From f0bc2a3645466136483aee10f6df20710a08e872 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 16:43:02 -0400 Subject: [PATCH 120/141] add null checks --- Datagram.cpp | 12 ++++++------ Datagram.h | 11 +++++++---- HTTPServer.cpp | 4 ++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index 2247dff1..14f9f385 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -195,24 +195,24 @@ namespace datagram DatagramSession::Info DatagramSession::GetSessionInfo() const { if(!m_RoutingSession) - return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; + return DatagramSession::Info(nullptr, nullptr, m_LastUse, m_LastSuccess); auto routingPath = m_RoutingSession->GetSharedRoutingPath(); if (!routingPath) - return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; + return DatagramSession::Info(nullptr, nullptr, m_LastUse, m_LastSuccess); auto lease = routingPath->remoteLease; auto tunnel = routingPath->outboundTunnel; if(lease) { if(tunnel) - return DatagramSession::Info{lease->tunnelGateway, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess}; + return DatagramSession::Info(lease->tunnelGateway, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess); else - return DatagramSession::Info{lease->tunnelGateway, nullptr, m_LastUse, m_LastSuccess}; + return DatagramSession::Info(lease->tunnelGateway, nullptr, m_LastUse, m_LastSuccess); } else if(tunnel) - return DatagramSession::Info{nullptr, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess}; + return DatagramSession::Info(nullptr, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess); else - return DatagramSession::Info{nullptr, nullptr, m_LastUse, m_LastSuccess}; + return DatagramSession::Info(nullptr, nullptr, m_LastUse, m_LastSuccess); } void DatagramSession::HandleSend(std::shared_ptr msg) diff --git a/Datagram.h b/Datagram.h index add946f0..bc358a41 100644 --- a/Datagram.h +++ b/Datagram.h @@ -53,11 +53,14 @@ namespace datagram const uint64_t activity; const uint64_t success; Info() : IBGW(nullptr), OBEP(nullptr), activity(0), success(0) {} - Info(const i2p::data::IdentHash & ibgw, const i2p::data::IdentHash & obep, const uint64_t a, const uint64_t s) : - IBGW(new i2p::data::IdentHash(ibgw.data())), - OBEP(new i2p::data::IdentHash(obep.data())), + Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a, const uint64_t s) : activity(a), - success(s) {} + success(s) { + if(ibgw) IBGW = new i2p::data::IdentHash(ibgw); + else IBGW = nullptr; + if(obep) OBEP = new i2p::data::IdentHash(obep); + else OBEP = nullptr; + } ~Info() { if(IBGW) delete IBGW; diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 56756277..f1e1e453 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -352,14 +352,14 @@ namespace http { s << "" << info.RemoteIdent.ToBase32() << ""; s << ""; if(info.CurrentIBGW) - s << info.CurrentIBGW->ToBase64(); + s << info.CurrentIBGW->ToBase64().c_str(); else s << "(none)"; s << ""; s << ""; if(info.CurrentOBEP) - s << info.CurrentOBEP->ToBase64(); + s << info.CurrentOBEP->ToBase64().c_str(); else s << "(none)"; s << ""; From 1015188c4eb44787594f55994f88d2b32d04923e Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 16:54:39 -0400 Subject: [PATCH 121/141] use shared pointers --- Datagram.h | 13 ++++--------- HTTPServer.cpp | 6 +++--- I2PTunnel.h | 4 ++-- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Datagram.h b/Datagram.h index bc358a41..06b3048e 100644 --- a/Datagram.h +++ b/Datagram.h @@ -48,24 +48,19 @@ namespace datagram uint64_t LastSuccess() const { return m_LastSuccess; } struct Info { - const i2p::data::IdentHash * IBGW; - const i2p::data::IdentHash * OBEP; + std::shared_ptr IBGW; + std::shared_ptr OBEP; const uint64_t activity; const uint64_t success; Info() : IBGW(nullptr), OBEP(nullptr), activity(0), success(0) {} Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a, const uint64_t s) : activity(a), success(s) { - if(ibgw) IBGW = new i2p::data::IdentHash(ibgw); + if(ibgw) IBGW = std::make_shared(ibgw); else IBGW = nullptr; - if(obep) OBEP = new i2p::data::IdentHash(obep); + if(obep) OBEP = std::make_shared(obep); else OBEP = nullptr; } - ~Info() - { - if(IBGW) delete IBGW; - if(OBEP) delete OBEP; - } }; Info GetSessionInfo() const; diff --git a/HTTPServer.cpp b/HTTPServer.cpp index f1e1e453..01338ff2 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -346,20 +346,20 @@ namespace http { s << "Idle Time"; s << ""; auto forward = i2p::client::context.GetForwardInfosFor(dest->GetIdentHash()); - for (auto & info : forward) + for (auto info : forward) { s << ""; s << "" << info.RemoteIdent.ToBase32() << ""; s << ""; if(info.CurrentIBGW) - s << info.CurrentIBGW->ToBase64().c_str(); + s << std::string(info.CurrentIBGW->ToBase64()); else s << "(none)"; s << ""; s << ""; if(info.CurrentOBEP) - s << info.CurrentOBEP->ToBase64().c_str(); + s << std::string(info.CurrentOBEP->ToBase64()); else s << "(none)"; s << ""; diff --git a/I2PTunnel.h b/I2PTunnel.h index 7fe58574..0d4d85a1 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -148,9 +148,9 @@ namespace client /** ident hash of remote destination */ const i2p::data::IdentHash RemoteIdent; /** ident hash of IBGW in use currently in this session or nullptr if none is set */ - const i2p::data::IdentHash * CurrentIBGW; + std::shared_ptr CurrentIBGW; /** ident hash of OBEP in use for this session or nullptr if none is set */ - const i2p::data::IdentHash * CurrentOBEP; + std::shared_ptr CurrentOBEP; /** i2p router's udp endpoint */ const boost::asio::ip::udp::endpoint LocalEndpoint; /** client's udp endpoint */ From 8a29dfc3fa433b5eac1fb133b2553fa1cc4ae239 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 17:53:46 -0400 Subject: [PATCH 122/141] tabify and use shared pointers --- ClientContext.cpp | 19 ++- ClientContext.h | 2 +- HTTPServer.cpp | 15 +-- I2PTunnel.cpp | 337 +++++++++++++++++++++++----------------------- I2PTunnel.h | 51 +++---- 5 files changed, 211 insertions(+), 213 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 6ef7ec60..3eee42b2 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -276,20 +276,27 @@ namespace client return success; } - std::vector ClientContext::GetForwardInfosFor(const i2p::data::IdentHash & destination) + std::vector > ClientContext::GetForwardInfosFor(const i2p::data::IdentHash & destination) { + std::vector > infos; std::lock_guard lock(m_ForwardsMutex); - for(auto & c : m_ClientForwards) + for(const auto & c : m_ClientForwards) { if (c.second->IsLocalDestination(destination)) - return c.second->GetSessions(); + { + for (auto & i : c.second->GetSessions()) infos.push_back(i); + break; + } } - for(auto & s : m_ServerForwards) + for(const auto & s : m_ServerForwards) { if(std::get<0>(s.first) == destination) - return s.second->GetSessions(); + { + for( auto & i : s.second->GetSessions()) infos.push_back(i); + break; + } } - return {}; + return infos; } std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, diff --git a/ClientContext.h b/ClientContext.h index 7faf04ca..581ff466 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -67,7 +67,7 @@ namespace client AddressBook& GetAddressBook () { return m_AddressBook; }; const SAMBridge * GetSAMBridge () const { return m_SamBridge; }; - std::vector GetForwardInfosFor(const i2p::data::IdentHash & destination); + std::vector > GetForwardInfosFor(const i2p::data::IdentHash & destination); private: diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 01338ff2..a8434bef 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -343,29 +343,26 @@ namespace http { s << "IBGW"; s << "OBEP"; s << "UDP Converstation"; - s << "Idle Time"; s << ""; auto forward = i2p::client::context.GetForwardInfosFor(dest->GetIdentHash()); for (auto info : forward) { s << ""; - s << "" << info.RemoteIdent.ToBase32() << ""; + s << "" << info->RemoteIdent->ToBase32() << ""; s << ""; - if(info.CurrentIBGW) - s << std::string(info.CurrentIBGW->ToBase64()); + if(info->CurrentIBGW) + s << info->CurrentIBGW->ToBase64(); else s << "(none)"; s << ""; s << ""; - if(info.CurrentOBEP) - s << std::string(info.CurrentOBEP->ToBase64()); + if(info->CurrentOBEP) + s << info->CurrentOBEP->ToBase64(); else s << "(none)"; s << ""; - s << "" << info.LocalEndpoint << " ⇄ " << info.RemoteEndpoint << ""; - auto sec = std::chrono::duration >( std::chrono::milliseconds(info.idle) ); - s << "" << sec.count() << " seconds "; + s << "" << info->LocalEndpoint << " ⇄ " << info->RemoteEndpoint << ""; s << "
\r\n"; } s << "\r\n"; diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 688866c8..0c58ba9d 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -569,207 +569,200 @@ namespace client uint16_t ourPort, uint16_t theirPort) : m_Destination(localDestination->GetDatagramDestination()), m_Service(localDestination->GetService()), - IPSocket(localDestination->GetService(), localEndpoint), - Identity(to), - SendEndpoint(endpoint), - LastActivity(i2p::util::GetMillisecondsSinceEpoch()), - LocalPort(ourPort), - RemotePort(theirPort) - { - Receive(); - } - - - void UDPSession::Receive() { - LogPrint(eLogDebug, "UDPSession: Receive"); - IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), - FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); - } - - void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) - { - if(!ecode) - { - LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); - LastActivity = i2p::util::GetMillisecondsSinceEpoch(); - uint8_t * data = new uint8_t[len]; - memcpy(data, m_Buffer, len); - m_Service.post([&,len, data] () { - m_Destination->SendDatagramTo(data, len, Identity, 0, 0); - delete [] data; - }); - - Receive(); - } else { - LogPrint(eLogError, "UDPSession: ", ecode.message()); - } - } - - - - I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, - const boost::asio::ip::address& localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : - m_Name(name), - LocalPort(port), - m_LocalAddress(localAddress), - m_RemoteEndpoint(forwardTo) - { - m_LocalDest = localDestination; - m_LocalDest->Start(); - auto dgram = m_LocalDest->CreateDatagramDestination(); - dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); - } - - I2PUDPServerTunnel::~I2PUDPServerTunnel() - { - auto dgram = m_LocalDest->GetDatagramDestination(); - if (dgram) dgram->ResetReceiver(); - - LogPrint(eLogInfo, "UDPServer: done"); - } - - void I2PUDPServerTunnel::Start() { - m_LocalDest->Start(); - } - - std::vector I2PUDPServerTunnel::GetSessions() + IPSocket(localDestination->GetService(), localEndpoint), + Identity(to), + SendEndpoint(endpoint), + LastActivity(i2p::util::GetMillisecondsSinceEpoch()), + LocalPort(ourPort), + RemotePort(theirPort) { - std::vector sessions; - auto localident = m_LocalDest->GetIdentHash(); + Receive(); + } + + + void UDPSession::Receive() { + LogPrint(eLogDebug, "UDPSession: Receive"); + IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), + FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); + } + + void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) + { + if(!ecode) + { + LogPrint(eLogDebug, "UDPSession: forward ", len, "B from ", FromEndpoint); + LastActivity = i2p::util::GetMillisecondsSinceEpoch(); + uint8_t * data = new uint8_t[len]; + memcpy(data, m_Buffer, len); + m_Service.post([&,len, data] () { + m_Destination->SendDatagramTo(data, len, Identity, 0, 0); + delete [] data; + }); + + Receive(); + } else { + LogPrint(eLogError, "UDPSession: ", ecode.message()); + } + } + + + + I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, + const boost::asio::ip::address& localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : + m_Name(name), + LocalPort(port), + m_LocalAddress(localAddress), + m_RemoteEndpoint(forwardTo) + { + m_LocalDest = localDestination; + m_LocalDest->Start(); + auto dgram = m_LocalDest->CreateDatagramDestination(); + dgram->SetReceiver(std::bind(&I2PUDPServerTunnel::HandleRecvFromI2P, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + } + + I2PUDPServerTunnel::~I2PUDPServerTunnel() + { + auto dgram = m_LocalDest->GetDatagramDestination(); + if (dgram) dgram->ResetReceiver(); + + LogPrint(eLogInfo, "UDPServer: done"); + } + + void I2PUDPServerTunnel::Start() { + m_LocalDest->Start(); + } + + std::vector > I2PUDPServerTunnel::GetSessions() + { + std::vector > sessions; std::lock_guard lock(m_SessionsMutex); for ( UDPSession * s : m_Sessions ) { if (!s->m_Destination) continue; auto info = s->m_Destination->GetInfoForRemote(s->Identity); if(!info) continue; - sessions.push_back(DatagramSessionInfo{ - m_Name, - localident, - s->Identity, - info->IBGW, - info->OBEP, - s->IPSocket.local_endpoint(), - s->SendEndpoint, - info->success - }); + + auto sinfo = std::make_shared(); + sinfo->Name = m_Name; + sinfo->LocalIdent = std::make_shared(m_LocalDest->GetIdentHash().data()); + sinfo->RemoteIdent = std::make_shared(s->Identity.data()); + sinfo->CurrentIBGW = info->IBGW; + sinfo->CurrentOBEP = info->OBEP; + sessions.push_back(sinfo); } return sessions; } - - I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, - boost::asio::ip::udp::endpoint localEndpoint, - std::shared_ptr localDestination, - uint16_t remotePort) : - m_Name(name), - m_Session(nullptr), - m_RemoteDest(remoteDest), - m_LocalDest(localDestination), - m_LocalEndpoint(localEndpoint), - m_RemoteIdent(nullptr), - m_ResolveThread(nullptr), - LocalPort(localEndpoint.port()), - RemotePort(remotePort), - m_cancel_resolve(false) - { - auto dgram = m_LocalDest->CreateDatagramDestination(); - dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5)); - } - - - - void I2PUDPClientTunnel::Start() { - m_LocalDest->Start(); - if (m_ResolveThread == nullptr) - m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); - } - - std::vector I2PUDPClientTunnel::GetSessions() + + I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, + boost::asio::ip::udp::endpoint localEndpoint, + std::shared_ptr localDestination, + uint16_t remotePort) : + m_Name(name), + m_Session(nullptr), + m_RemoteDest(remoteDest), + m_LocalDest(localDestination), + m_LocalEndpoint(localEndpoint), + m_RemoteIdent(nullptr), + m_ResolveThread(nullptr), + LocalPort(localEndpoint.port()), + RemotePort(remotePort), + m_cancel_resolve(false) { - std::vector infos; + auto dgram = m_LocalDest->CreateDatagramDestination(); + dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, + std::placeholders::_5)); + } + + + + void I2PUDPClientTunnel::Start() { + m_LocalDest->Start(); + if (m_ResolveThread == nullptr) + m_ResolveThread = new std::thread(std::bind(&I2PUDPClientTunnel::TryResolving, this)); + } + + std::vector > I2PUDPClientTunnel::GetSessions() + { + std::vector > infos; if(m_Session && m_LocalDest) { - auto localident = m_LocalDest->GetIdentHash(); auto s = m_Session; if (s->m_Destination) { auto info = m_Session->m_Destination->GetInfoForRemote(s->Identity); if(info) { - infos.push_back(DatagramSessionInfo{ - m_Name, - localident, - s->Identity, - info->IBGW, - info->OBEP, - s->IPSocket.local_endpoint(), - s->SendEndpoint, - info->success - }); + auto sinfo = std::make_shared(); + sinfo->Name = m_Name; + sinfo->LocalIdent = std::make_shared(m_LocalDest->GetIdentHash().data()); + sinfo->RemoteIdent = std::make_shared(s->Identity.data()); + sinfo->CurrentIBGW = info->IBGW; + sinfo->CurrentOBEP = info->OBEP; + infos.push_back(sinfo); } } } return infos; } - void I2PUDPClientTunnel::TryResolving() { - LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); - m_RemoteIdent = new i2p::data::IdentHash; - m_RemoteIdent->Fill(0); + void I2PUDPClientTunnel::TryResolving() { + LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); + m_RemoteIdent = new i2p::data::IdentHash; + m_RemoteIdent->Fill(0); - while(!context.GetAddressBook().GetIdentHash(m_RemoteDest, *m_RemoteIdent) && !m_cancel_resolve) - { - LogPrint(eLogWarning, "UDP Tunnel: failed to lookup ", m_RemoteDest); - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - if(m_cancel_resolve) - { - LogPrint(eLogError, "UDP Tunnel: lookup of ", m_RemoteDest, " was cancelled"); - return; - } - LogPrint(eLogInfo, "UDP Tunnel: resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); - // delete existing session - if(m_Session) delete m_Session; - - boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); - m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); - } + while(!context.GetAddressBook().GetIdentHash(m_RemoteDest, *m_RemoteIdent) && !m_cancel_resolve) + { + LogPrint(eLogWarning, "UDP Tunnel: failed to lookup ", m_RemoteDest); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if(m_cancel_resolve) + { + LogPrint(eLogError, "UDP Tunnel: lookup of ", m_RemoteDest, " was cancelled"); + return; + } + LogPrint(eLogInfo, "UDP Tunnel: resolved ", m_RemoteDest, " to ", m_RemoteIdent->ToBase32()); + // delete existing session + if(m_Session) delete m_Session; + + boost::asio::ip::udp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 0); + m_Session = new UDPSession(m_LocalEndpoint, m_LocalDest, ep, *m_RemoteIdent, LocalPort, RemotePort); + } - void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) - { - if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) - { - // address match - if(m_Session) - { - // tell session - LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32()); - m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Session->FromEndpoint); - } - else - LogPrint(eLogWarning, "UDP Client: no session"); - } - else - LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); - - } + void I2PUDPClientTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len) + { + if(m_RemoteIdent && from.GetIdentHash() == *m_RemoteIdent) + { + // address match + if(m_Session) + { + // tell session + LogPrint(eLogDebug, "UDP Client: got ", len, "B from ", from.GetIdentHash().ToBase32()); + m_Session->IPSocket.send_to(boost::asio::buffer(buf, len), m_Session->FromEndpoint); + } + else + LogPrint(eLogWarning, "UDP Client: no session"); + } + else + LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); + + } - I2PUDPClientTunnel::~I2PUDPClientTunnel() { - auto dgram = m_LocalDest->GetDatagramDestination(); - if (dgram) dgram->ResetReceiver(); + I2PUDPClientTunnel::~I2PUDPClientTunnel() { + auto dgram = m_LocalDest->GetDatagramDestination(); + if (dgram) dgram->ResetReceiver(); - if (m_Session) delete m_Session; - m_cancel_resolve = true; + if (m_Session) delete m_Session; + m_cancel_resolve = true; - if(m_ResolveThread) - { - m_ResolveThread->join(); - delete m_ResolveThread; - m_ResolveThread = nullptr; - } - if (m_RemoteIdent) delete m_RemoteIdent; - } + if(m_ResolveThread) + { + m_ResolveThread->join(); + delete m_ResolveThread; + m_ResolveThread = nullptr; + } + if (m_RemoteIdent) delete m_RemoteIdent; + } } } diff --git a/I2PTunnel.h b/I2PTunnel.h index 0d4d85a1..2418da30 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -138,27 +138,6 @@ namespace client /** max size for i2p udp */ const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE; - /** read only info about a datagram session */ - struct DatagramSessionInfo - { - /** the name of this forward */ - const std::string Name; - /** ident hash of local destination */ - const i2p::data::IdentHash LocalIdent; - /** ident hash of remote destination */ - const i2p::data::IdentHash RemoteIdent; - /** ident hash of IBGW in use currently in this session or nullptr if none is set */ - std::shared_ptr CurrentIBGW; - /** ident hash of OBEP in use for this session or nullptr if none is set */ - std::shared_ptr CurrentOBEP; - /** i2p router's udp endpoint */ - const boost::asio::ip::udp::endpoint LocalEndpoint; - /** client's udp endpoint */ - const boost::asio::ip::udp::endpoint RemoteEndpoint; - /** how long has this converstation been idle in ms */ - const uint64_t idle; - }; - struct UDPSession { i2p::datagram::DatagramDestination * m_Destination; @@ -182,9 +161,31 @@ namespace client void Receive(); }; + + /** read only info about a datagram session */ + struct DatagramSessionInfo + { + /** the name of this forward */ + std::string Name; + /** ident hash of local destination */ + std::shared_ptr LocalIdent; + /** ident hash of remote destination */ + std::shared_ptr RemoteIdent; + /** ident hash of IBGW in use currently in this session or nullptr if none is set */ + std::shared_ptr CurrentIBGW; + /** ident hash of OBEP in use for this session or nullptr if none is set */ + std::shared_ptr CurrentOBEP; + /** i2p router's udp endpoint */ + boost::asio::ip::udp::endpoint LocalEndpoint; + /** client's udp endpoint */ + boost::asio::ip::udp::endpoint RemoteEndpoint; + /** how long has this converstation been idle in ms */ + uint64_t idle; + }; + /** server side udp tunnel, many i2p inbound to 1 ip outbound */ class I2PUDPServerTunnel - { + { public: I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, @@ -195,7 +196,7 @@ namespace client void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT); void Start(); const char * GetName() const { return m_Name.c_str(); } - std::vector GetSessions(); + std::vector > GetSessions(); private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSession * ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); @@ -209,7 +210,7 @@ namespace client std::shared_ptr m_LocalDest; }; - class I2PUDPClientTunnel + class I2PUDPClientTunnel { public: I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, @@ -218,7 +219,7 @@ namespace client ~I2PUDPClientTunnel(); void Start(); const char * GetName() const { return m_Name.c_str(); } - std::vector GetSessions(); + std::vector > GetSessions(); bool IsLocalDestination(const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); } private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); From 7ae09fa1fe47ff4b2ced4c5cec6ca7de08e6efc3 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 17:58:16 -0400 Subject: [PATCH 123/141] try fixing memory errors --- HTTPServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index a8434bef..3fdfcca5 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -351,14 +351,14 @@ namespace http { s << "" << info->RemoteIdent->ToBase32() << ""; s << ""; if(info->CurrentIBGW) - s << info->CurrentIBGW->ToBase64(); + s << info->CurrentIBGW->ToBase64().c_str(); else s << "(none)"; s << ""; s << ""; if(info->CurrentOBEP) - s << info->CurrentOBEP->ToBase64(); + s << info->CurrentOBEP->ToBase64().c_str(); else s << "(none)"; s << ""; From f64f8758064cf7aacf58a49925767184bf6ac363 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 18:04:54 -0400 Subject: [PATCH 124/141] don't show udp tunnels in ui yet --- HTTPServer.cpp | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 3fdfcca5..759c8ba3 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -338,34 +338,7 @@ namespace http { s << "" << (int)it->GetStatus () << ""; s << "
\r\n" << std::endl; } - s << "
\r\n"; - s << ""; - s << ""; - s << ""; - s << ""; - s << ""; - auto forward = i2p::client::context.GetForwardInfosFor(dest->GetIdentHash()); - for (auto info : forward) - { - s << ""; - s << ""; - s << ""; - - s << ""; - s << ""; - s << "
\r\n"; - } - s << "
Forwards
Remote DestinationIBGWOBEPUDP Converstation
" << info->RemoteIdent->ToBase32() << ""; - if(info->CurrentIBGW) - s << info->CurrentIBGW->ToBase64().c_str(); - else - s << "(none)"; - s << ""; - if(info->CurrentOBEP) - s << info->CurrentOBEP->ToBase64().c_str(); - else - s << "(none)"; - s << "" << info->LocalEndpoint << " ⇄ " << info->RemoteEndpoint << "
\r\n"; + s << ""; } } From f4d1b87f736c10e0c6bfacffeb4de1f561494b34 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Sep 2016 18:34:18 -0400 Subject: [PATCH 125/141] expire tags --- Datagram.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Datagram.cpp b/Datagram.cpp index 14f9f385..cecbcc40 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -146,6 +146,7 @@ namespace datagram LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); m_Sessions.erase(ident); } + m_Owner->CleanupExpiredTags(); ScheduleCleanup(); } From 722f1c4430c30ed2643c3dd2e3dc60c1782c5009 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 4 Sep 2016 16:42:48 -0400 Subject: [PATCH 126/141] try fixing webui freeze --- HTTPServer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 309e3f6b..db46404f 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -828,7 +828,13 @@ namespace http { std::shared_ptr newSocket) { if (ecode) + { + if(newSocket) newSocket->close(); + LogPrint(eLogError, "HTTP Server: error handling accept ", ecode.message()); + if(ecode != boost::asio::error::operation_aborted) + Accept(); return; + } CreateConnection(newSocket); Accept (); } From f3a61007a7094841e9137a393474f355e0bbeafe Mon Sep 17 00:00:00 2001 From: "Solomenchuk, Vlad" Date: Tue, 6 Sep 2016 12:26:59 -0700 Subject: [PATCH 127/141] build instruction for iOS --- build/CMakeLists.txt | 9 ++++- docs/build_notes_ios.md | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 docs/build_notes_ios.md diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index f9f21fd4..dda0a67c 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -187,7 +187,14 @@ endif() # TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826 # use imported Threads::Threads instead set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package ( Threads REQUIRED ) +if (IOS) + set(CMAKE_THREAD_LIBS_INIT "-lpthread") + set(CMAKE_HAVE_THREADS_LIBRARY 1) + set(CMAKE_USE_WIN32_THREADS_INIT 0) + set(CMAKE_USE_PTHREADS_INIT 1) +else() + find_package ( Threads REQUIRED ) +endif() if(THREADS_HAVE_PTHREAD_ARG) # compile time flag set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") endif() diff --git a/docs/build_notes_ios.md b/docs/build_notes_ios.md new file mode 100644 index 00000000..26688d21 --- /dev/null +++ b/docs/build_notes_ios.md @@ -0,0 +1,85 @@ +Building on iOS +=================== + +How to build i2pd for iOS 9 and iOS Simulator 386/x64 + +Prerequisites +-------------- + +XCode7+, cmake 3.2+ + +Dependencies +-------------- +- precompiled openssl +- precompiled boost with modules `filesystem`, `program_options`, `date_time` and `system` +- ios-cmake toolchain from https://github.com/vovasty/ios-cmake.git + +Building +------------------------ +Assume you have folder structure + +``` +lib + libboost_date_time.a + libboost_filesystem.a + libboost_program_options.a + libboost_system.a + libboost.a + libcrypto.a + libssl.a +include + boost + openssl +ios-cmake +i2pd +``` + + +```bash +mkdir -p build/simulator/lib build/ios/lib include/i2pd + +pushd build/simulator && \ +cmake -DIOS_PLATFORM=SIMULATOR \ + -DPATCH=/usr/bin/patch \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=../../ios-cmake/toolchain/iOS.cmake \ + -DWITH_STATIC=yes \ + -DWITH_BINARY=no \ + -DBoost_INCLUDE_DIR=../../include \ + -DOPENSSL_INCLUDE_DIR=../../include \ + -DBoost_LIBRARY_DIR=../../lib \ + -DOPENSSL_SSL_LIBRARY=../../lib/libssl.a \ + -DOPENSSL_CRYPTO_LIBRARY=../../lib/libcrypto.a \ + ../../i2pd/build && \ +make -j16 VERBOSE=1 && \ +popd + +pushd build/ios +cmake -DIOS_PLATFORM=OS \ + -DPATCH=/usr/bin/patch \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=../../ios-cmake/toolchain/iOS.cmake \ + -DWITH_STATIC=yes \ + -DWITH_BINARY=no \ + -DBoost_INCLUDE_DIR=../../include \ + -DOPENSSL_INCLUDE_DIR=../../include \ + -DBoost_LIBRARY_DIR=../../lib \ + -DOPENSSL_SSL_LIBRARY=../../lib/libssl.a \ + -DOPENSSL_CRYPTO_LIBRARY=../../lib/libcrypto.a \ + ../../i2pd/build && \ +make -j16 VERBOSE=1 && \ +popd + +libtool -static -o lib/libi2pdclient.a build/*/libi2pdclient.a +libtool -static -o lib/libi2pd.a build/*/libi2pd.a + +cp i2pd/*.h include/i2pd +``` + +Include into project +--------------------------- +1. add all libraries in `lib` folder to `Project linked frameworks`. +2. add `libc++` and `libz` libraries from system libraries to `Project linked frameworks`. +3. add path to i2p headers to your `Headers search paths` + +Alternatively you may use swift wrapper https://github.com/vovasty/SwiftyI2P.git \ No newline at end of file From 6e0d6dcac59012dffa8fea713af838491d863fdb Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 Sep 2016 13:25:11 -0400 Subject: [PATCH 128/141] reselect tunnels if LeaseSet delivery was not confirmed --- Garlic.cpp | 14 ++++++++------ Garlic.h | 1 + Streaming.cpp | 8 ++++++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index c3c0e045..3521ffcf 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -247,7 +247,7 @@ namespace garlic size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr msg, UnconfirmedTags * newTags) { - uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec + uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); uint32_t msgID; RAND_bytes ((uint8_t *)&msgID, 4); size_t size = 0; @@ -258,9 +258,11 @@ namespace garlic if (m_Owner) { // resubmit non-confirmed LeaseSet - if (m_LeaseSetUpdateStatus == eLeaseSetSubmitted && - i2p::util::GetMillisecondsSinceEpoch () > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT) - m_LeaseSetUpdateStatus = eLeaseSetUpdated; + if (m_LeaseSetUpdateStatus == eLeaseSetSubmitted && ts > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT) + { + m_LeaseSetUpdateStatus = eLeaseSetUpdated; + SetSharedRoutingPath (nullptr); // invalidate path since leaseset was not confirmed + } // attach DeviveryStatus if necessary if (newTags || m_LeaseSetUpdateStatus == eLeaseSetUpdated) // new tags created or leaseset updated @@ -286,7 +288,7 @@ namespace garlic { m_LeaseSetUpdateStatus = eLeaseSetSubmitted; m_LeaseSetUpdateMsgID = msgID; - m_LeaseSetSubmissionTime = i2p::util::GetMillisecondsSinceEpoch (); + m_LeaseSetSubmissionTime = ts; // clove if our leaseSet must be attached auto leaseSet = CreateDatabaseStoreMsg (m_Owner->GetLeaseSet ()); size += CreateGarlicClove (payload + size, leaseSet, false); @@ -303,7 +305,7 @@ namespace garlic size += 3; htobe32buf (payload + size, msgID); // MessageID size += 4; - htobe64buf (payload + size, ts); // Expiration of message + htobe64buf (payload + size, ts + 8000); // Expiration of message, 8 sec size += 8; return size; } diff --git a/Garlic.h b/Garlic.h index 6a92b94a..8d2e850a 100644 --- a/Garlic.h +++ b/Garlic.h @@ -104,6 +104,7 @@ namespace garlic { if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; }; + bool IsLeaseSetNonConfirmed () const { return m_LeaseSetUpdateStatus == eLeaseSetSubmitted; }; std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); diff --git a/Streaming.cpp b/Streaming.cpp index 1103dba1..e6f5b32f 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -736,7 +736,15 @@ namespace stream return; } if (m_Status == eStreamStatusOpen) + { + if (m_RoutingSession && m_RoutingSession->IsLeaseSetNonConfirmed ()) + { + // seems something went wrong and we should re-select tunnels + m_CurrentOutboundTunnel = nullptr; + m_CurrentRemoteLease = nullptr; + } SendQuickAck (); + } m_IsAckSendScheduled = false; } } From db716737227dd9044def5d9ca4c9c4e05f7fce65 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Sep 2016 09:19:30 -0400 Subject: [PATCH 129/141] fixed #629. catch HTTPServer exceptions --- HTTPServer.cpp | 19 ++++++++++++++++--- HTTPServer.h | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index bffe8614..1bb558e3 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -769,7 +769,7 @@ namespace http { } HTTPServer::HTTPServer (const std::string& address, int port): - m_Thread (nullptr), m_Work (m_Service), + m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port)) { } @@ -798,6 +798,7 @@ namespace http { i2p::config::SetOption("http.pass", pass); LogPrint(eLogInfo, "HTTPServer: password set to ", pass); } + m_IsRunning = true; m_Thread = std::unique_ptr(new std::thread (std::bind (&HTTPServer::Run, this))); m_Acceptor.listen (); Accept (); @@ -805,9 +806,11 @@ namespace http { void HTTPServer::Stop () { + m_IsRunning = false; m_Acceptor.close(); m_Service.stop (); - if (m_Thread) { + if (m_Thread) + { m_Thread->join (); m_Thread = nullptr; } @@ -815,7 +818,17 @@ namespace http { void HTTPServer::Run () { - m_Service.run (); + while (m_IsRunning) + { + try + { + m_Service.run (); + } + catch (std::exception& ex) + { + LogPrint (eLogError, "HTTPServer: runtime exception: ", ex.what ()); + } + } } void HTTPServer::Accept () diff --git a/HTTPServer.h b/HTTPServer.h index 5246af8b..4a32702d 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -57,6 +57,7 @@ namespace http { private: + bool m_IsRunning; std::unique_ptr m_Thread; boost::asio::io_service m_Service; boost::asio::io_service::work m_Work; From bee407ea34edc1fe7f0939396267d7dac5131402 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Sep 2016 10:16:42 -0400 Subject: [PATCH 130/141] clean-up datagram session toghters with leasesets and tags --- Datagram.cpp | 40 +++++++++++++++------------------------- Datagram.h | 14 ++++---------- Destination.cpp | 7 +++++++ Destination.h | 2 ++ 4 files changed, 28 insertions(+), 35 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index cecbcc40..fa05f5a9 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -12,16 +12,12 @@ namespace i2p namespace datagram { DatagramDestination::DatagramDestination (std::shared_ptr owner): - m_Owner (owner.get()), - m_CleanupTimer(owner->GetService()), - m_Receiver (nullptr) + m_Owner (owner.get()), m_Receiver (nullptr) { - ScheduleCleanup(); } DatagramDestination::~DatagramDestination () { - m_CleanupTimer.cancel(); m_Sessions.clear(); } @@ -120,34 +116,28 @@ namespace datagram return msg; } - void DatagramDestination::ScheduleCleanup() + void DatagramDestination::CleanUp () { - m_CleanupTimer.expires_from_now(boost::posix_time::seconds(DATAGRAM_SESSION_CLEANUP_INTERVAL)); - m_CleanupTimer.async_wait(std::bind(&DatagramDestination::HandleCleanUp, this, std::placeholders::_1)); - } - - void DatagramDestination::HandleCleanUp(const boost::system::error_code & ecode) - { - if(ecode) - return; - std::lock_guard lock(m_SessionsMutex); - auto now = i2p::util::GetMillisecondsSinceEpoch(); - LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); std::vector expiredSessions; - // for each session ... - for (auto & e : m_Sessions) { - // check if expired - if(now - e.second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) - expiredSessions.push_back(e.first); // we are expired + { + std::lock_guard lock(m_SessionsMutex); + auto now = i2p::util::GetMillisecondsSinceEpoch(); + LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); + // for each session ... + for (auto & e : m_Sessions) + { + // check if expired + if(now - e.second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) + expiredSessions.push_back(e.first); // we are expired + } } // for each expired session ... - for (auto & ident : expiredSessions) { + for (auto & ident : expiredSessions) + { // remove the expired session LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); m_Sessions.erase(ident); } - m_Owner->CleanupExpiredTags(); - ScheduleCleanup(); } std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & ident) diff --git a/Datagram.h b/Datagram.h index 06b3048e..f3aae6f9 100644 --- a/Datagram.h +++ b/Datagram.h @@ -19,9 +19,6 @@ namespace client } namespace datagram { - - // seconds interval for cleanup timer - const int DATAGRAM_SESSION_CLEANUP_INTERVAL = 3; // 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 @@ -127,13 +124,11 @@ namespace datagram std::shared_ptr GetInfoForRemote(const i2p::data::IdentHash & remote); + // clean up stale sessions + void CleanUp (); + private: - // clean up after next tick - void ScheduleCleanup(); - - // clean up stale sessions and expire tags - void HandleCleanUp(const boost::system::error_code & ecode); - + 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); @@ -145,7 +140,6 @@ namespace datagram private: i2p::client::ClientDestination * m_Owner; - boost::asio::deadline_timer m_CleanupTimer; Receiver m_Receiver; // default std::mutex m_SessionsMutex; std::map > m_Sessions; diff --git a/Destination.cpp b/Destination.cpp index 03d0dd69..48717f5f 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -641,6 +641,7 @@ namespace client { CleanupExpiredTags (); CleanupRemoteLeaseSets (); + CleanupDestination (); m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT)); m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, shared_from_this (), std::placeholders::_1)); @@ -892,5 +893,11 @@ namespace client Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO SetLeaseSet (leaseSet); } + + void ClientDestination::CleanupDestination () + { + if (m_DatagramDestination) m_DatagramDestination->CleanUp (); + } + } } diff --git a/Destination.h b/Destination.h index 8150c72d..22ffa603 100644 --- a/Destination.h +++ b/Destination.h @@ -96,6 +96,7 @@ namespace client protected: void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet); + virtual void CleanupDestination () {}; // additional clean up in derived classes // I2CP virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; virtual void CreateNewLeaseSet (std::vector > tunnels) = 0; @@ -180,6 +181,7 @@ namespace client protected: + void CleanupDestination (); // I2CP void HandleDataMessage (const uint8_t * buf, size_t len); void CreateNewLeaseSet (std::vector > tunnels); From a4762fe65cf6e7b760ef7c3fdb90bb4d0f29004b Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Sep 2016 10:46:13 -0400 Subject: [PATCH 131/141] remove expired session through one pass --- Datagram.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index fa05f5a9..53b13d50 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -117,26 +117,21 @@ namespace datagram } void DatagramDestination::CleanUp () - { - std::vector expiredSessions; + { + auto now = i2p::util::GetMillisecondsSinceEpoch(); + LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); + std::lock_guard lock(m_SessionsMutex); + // for each session ... + for (auto it = m_Sessions.begin (); it != m_Sessions.end (); ) { - std::lock_guard lock(m_SessionsMutex); - auto now = i2p::util::GetMillisecondsSinceEpoch(); - LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); - // for each session ... - for (auto & e : m_Sessions) + // check if expired + if (now - it->second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) { - // check if expired - if(now - e.second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) - expiredSessions.push_back(e.first); // we are expired + LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", it->first.ToBase32()); + it = m_Sessions.erase (it); // we are expired } - } - // for each expired session ... - for (auto & ident : expiredSessions) - { - // remove the expired session - LogPrint(eLogInfo, "DatagramDestination: expiring idle session with ", ident.ToBase32()); - m_Sessions.erase(ident); + else + it++; } } From 6885761f87f4378260331427a4d6f8fe61408fcc Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Sep 2016 10:56:22 -0400 Subject: [PATCH 132/141] check if sessions list is empty --- Datagram.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Datagram.cpp b/Datagram.cpp index 53b13d50..b9188864 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -118,6 +118,7 @@ namespace datagram void DatagramDestination::CleanUp () { + if (m_Sessions.empty ()) return; auto now = i2p::util::GetMillisecondsSinceEpoch(); LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); std::lock_guard lock(m_SessionsMutex); From ed874fe3ea57e46fcbcd4a48b63c30d783b121ae Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Sep 2016 21:36:17 -0400 Subject: [PATCH 133/141] check if RouterInfo has been decompressed completely --- NetDb.cpp | 7 ++++++- RouterInfo.cpp | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index 846f4b3c..2c9c4395 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -556,8 +556,13 @@ namespace data } uint8_t uncompressed[2048]; size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048); - if (uncompressedSize) + if (uncompressedSize && uncompressedSize < 2048) updated = AddRouterInfo (ident, uncompressed, uncompressedSize); + else + { + LogPrint (eLogError, "NetDb: decompression failed ", uncompressedSize); + return; + } } if (replyToken && context.IsFloodfill () && updated) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 130355b8..2aefab31 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -125,7 +125,8 @@ namespace data m_IsUnreachable = true; return; } - std::stringstream str (std::string ((char *)m_Buffer + identityLen, m_BufferLen - identityLen)); + std::stringstream str; + str.write ((const char *)m_Buffer + identityLen, m_BufferLen - identityLen); ReadFromStream (str); if (!str) { From 75065f29f78e452afa1a9e5f6a12f0f49412535a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Sep 2016 11:39:33 -0400 Subject: [PATCH 134/141] check if field is incomplete --- RouterInfo.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 2aefab31..d672d669 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -183,6 +183,7 @@ namespace data s.seekg (1, std::ios_base::cur); r++; // = r += ReadString (value, 255, s); s.seekg (1, std::ios_base::cur); r++; // ; + if (!s) return; if (!strcmp (key, "host")) { boost::system::error_code ecode; @@ -224,6 +225,11 @@ namespace data size_t l = strlen(key); unsigned char index = key[l-1] - '0'; // TODO: key[l-1] = 0; + if (index > 9) + { + LogPrint (eLogError, "RouterInfo: Unexpected introducer's index ", index, " skipped"); + if (s) continue; else return; + } if (index >= address.introducers.size ()) address.introducers.resize (index + 1); Introducer& introducer = address.introducers.at (index); @@ -263,6 +269,7 @@ namespace data s.seekg (1, std::ios_base::cur); r++; // = r += ReadString (value, 255, s); s.seekg (1, std::ios_base::cur); r++; // ; + if (!s) return; m_Properties[key] = value; // extract caps @@ -271,7 +278,7 @@ namespace data // check netId else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != I2PD_NET_ID) { - LogPrint (eLogError, "Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); + LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); m_IsUnreachable = true; } // family @@ -544,6 +551,7 @@ namespace data if (l < len) { s.read (str, l); + if (!s) l = 0; // failed, return empty string str[l] = 0; } else From 325b36272739992a6a7c165cbc29b92c0890e24d Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Sep 2016 12:05:01 -0400 Subject: [PATCH 135/141] show UDP tunnels --- HTTPServer.cpp | 26 ++++++++++++++++++++++++++ I2PTunnel.h | 8 ++++++++ 2 files changed, 34 insertions(+) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 1bb558e3..2e9a02ca 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -565,6 +565,32 @@ namespace http { s << ":" << it.second->GetLocalPort (); s << "
\r\n"<< std::endl; } + auto& clientForwards = i2p::client::context.GetClientForwards (); + if (!clientForwards.empty ()) + { + s << "
\r\nClient Forwards:
\r\n
\r\n"; + for (auto& it: clientForwards) + { + auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); + s << ""; + s << it.second->GetName () << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + } + auto& serverForwards = i2p::client::context.GetServerForwards (); + if (!serverForwards.empty ()) + { + s << "
\r\nServer Forwards:
\r\n
\r\n"; + for (auto& it: serverForwards) + { + auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); + s << ""; + s << it.second->GetName () << " ⇐ "; + s << i2p::client::context.GetAddressBook ().ToAddress(ident); + s << "
\r\n"<< std::endl; + } + } } HTTPConnection::HTTPConnection (std::shared_ptr socket): diff --git a/I2PTunnel.h b/I2PTunnel.h index 2418da30..dce9f812 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -197,9 +197,13 @@ namespace client void Start(); const char * GetName() const { return m_Name.c_str(); } std::vector > GetSessions(); + std::shared_ptr GetLocalDestination () const { return m_LocalDest; } + private: + void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); UDPSession * ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort); + private: const std::string m_Name; const uint16_t LocalPort; @@ -220,7 +224,11 @@ 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; } + private: void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void TryResolving(); From f9a5f4955c959081ac6e5bbf4d1952a825da99e5 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Sep 2016 21:37:43 -0400 Subject: [PATCH 136/141] check RI signture before processing --- RouterInfo.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index d672d669..9b2a4195 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -125,15 +125,6 @@ namespace data m_IsUnreachable = true; return; } - std::stringstream str; - str.write ((const char *)m_Buffer + identityLen, m_BufferLen - identityLen); - ReadFromStream (str); - if (!str) - { - LogPrint (eLogError, "RouterInfo: malformed message"); - m_IsUnreachable = true; - return; - } if (verifySignature) { // verify signature @@ -142,9 +133,20 @@ namespace data { LogPrint (eLogError, "RouterInfo: signature verification failed"); m_IsUnreachable = true; + return; } m_RouterIdentity->DropVerifier (); } + // parse RI + std::stringstream str; + str.write ((const char *)m_Buffer + identityLen, m_BufferLen - identityLen); + ReadFromStream (str); + if (!str) + { + LogPrint (eLogError, "RouterInfo: malformed message"); + m_IsUnreachable = true; + } + } void RouterInfo::ReadFromStream (std::istream& s) From fee5f959fd075ec20eafe7f09263855b47687340 Mon Sep 17 00:00:00 2001 From: brain5lug Date: Fri, 16 Sep 2016 01:47:38 +0300 Subject: [PATCH 137/141] perfect forwarding for logging arguments --- Log.cpp | 2 +- Log.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Log.cpp b/Log.cpp index 590f3d0f..5660821f 100644 --- a/Log.cpp +++ b/Log.cpp @@ -10,7 +10,7 @@ namespace i2p { namespace log { - Log logger; + static Log logger; /** * @brief Maps our loglevel to their symbolic name */ diff --git a/Log.h b/Log.h index bedc98f8..79bbeb3f 100644 --- a/Log.h +++ b/Log.h @@ -162,17 +162,17 @@ namespace log { /** internal usage only -- folding args array to single string */ template -void LogPrint (std::stringstream& s, TValue arg) +void LogPrint (std::stringstream& s, TValue&& arg) noexcept { - s << arg; + s << std::forward(arg); } /** internal usage only -- folding args array to single string */ template -void LogPrint (std::stringstream& s, TValue arg, TArgs... args) +void LogPrint (std::stringstream& s, TValue&& arg, TArgs&&... args) noexcept { - LogPrint (s, arg); - LogPrint (s, args...); + LogPrint (s, std::forward(arg)); + LogPrint (s, std::forward(args)...); } /** @@ -181,7 +181,7 @@ void LogPrint (std::stringstream& s, TValue arg, TArgs... args) * @param args Array of message parts */ template -void LogPrint (LogLevel level, TArgs... args) +void LogPrint (LogLevel level, TArgs&&... args) noexcept { i2p::log::Log &log = i2p::log::Logger(); if (level > log.GetLogLevel ()) @@ -194,7 +194,7 @@ void LogPrint (LogLevel level, TArgs... args) ss << LOG_COLOR_ERROR; else if (level == eLogWarning) // if log level is WARN color log message yellow ss << LOG_COLOR_WARNING; - LogPrint (ss, args ...); + LogPrint (ss, std::forward(args)...); // reset color ss << LOG_COLOR_RESET; From fbb5bb2f05de11cd15ed66677f16490253b6dc70 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Sep 2016 10:31:11 -0400 Subject: [PATCH 138/141] fix #634.don't create timer in constructor --- ClientContext.cpp | 51 +++++++++++++++++++++-------------------------- ClientContext.h | 5 +---- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index 3eee42b2..b7300ad2 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -17,8 +17,7 @@ namespace client ClientContext::ClientContext (): m_SharedLocalDestination (nullptr), m_HttpProxy (nullptr), m_SocksProxy (nullptr), m_SamBridge (nullptr), - m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr), - m_CleanupUDPTimer(m_Service, boost::posix_time::seconds(1)) + m_BOBCommandChannel (nullptr), m_I2CPServer (nullptr) { } @@ -88,19 +87,8 @@ namespace client } } - if ( m_ServiceThread == nullptr ) { - m_ServiceThread = new std::thread([&] () { - LogPrint(eLogInfo, "ClientContext: starting service"); - m_Service.run(); - LogPrint(eLogError, "ClientContext: service died"); - }); - ScheduleCleanupUDP(); - } - - // I2P tunnels - ReadTunnels (); - + ReadTunnels (); // SAM bool sam; i2p::config::GetOption("sam.enabled", sam); @@ -149,6 +137,13 @@ namespace client } m_AddressBook.StartResolvers (); + + // start UDP cleanup + if (!m_ServerForwards.empty ()) + { + m_CleanupUDPTimer.reset (new boost::asio::deadline_timer(m_SharedLocalDestination->GetService ())); + ScheduleCleanupUDP(); + } } void ClientContext::Stop () @@ -210,25 +205,22 @@ namespace client LogPrint(eLogInfo, "Clients: stopping AddressBook"); m_AddressBook.Stop (); - { + { std::lock_guard lock(m_ForwardsMutex); m_ServerForwards.clear(); m_ClientForwards.clear(); } - + if (m_CleanupUDPTimer) + { + m_CleanupUDPTimer->cancel (); + m_CleanupUDPTimer = nullptr; + } + for (auto& it: m_Destinations) it.second->Stop (); m_Destinations.clear (); m_SharedLocalDestination = nullptr; - // stop io service thread - if(m_ServiceThread) - { - m_Service.stop(); - m_ServiceThread->join(); - delete m_ServiceThread; - m_ServiceThread = nullptr; - } } void ClientContext::ReloadConfig () @@ -558,9 +550,12 @@ namespace client void ClientContext::ScheduleCleanupUDP() { - // schedule cleanup in 1 second - m_CleanupUDPTimer.expires_at(m_CleanupUDPTimer.expires_at() + boost::posix_time::seconds(1)); - m_CleanupUDPTimer.async_wait(std::bind(&ClientContext::CleanupUDP, this, std::placeholders::_1)); + if (m_CleanupUDPTimer) + { + // schedule cleanup in 17 seconds + m_CleanupUDPTimer->expires_from_now (boost::posix_time::seconds (17)); + m_CleanupUDPTimer->async_wait(std::bind(&ClientContext::CleanupUDP, this, std::placeholders::_1)); + } } void ClientContext::CleanupUDP(const boost::system::error_code & ecode) @@ -568,7 +563,7 @@ namespace client if(!ecode) { std::lock_guard lock(m_ForwardsMutex); - for ( auto & s : m_ServerForwards ) s.second->ExpireStale(); + for (auto & s : m_ServerForwards ) s.second->ExpireStale(); ScheduleCleanupUDP(); } } diff --git a/ClientContext.h b/ClientContext.h index 581ff466..1a41acfc 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -101,10 +101,7 @@ namespace client BOBCommandChannel * m_BOBCommandChannel; I2CPServer * m_I2CPServer; - boost::asio::io_service m_Service; - std::thread * m_ServiceThread; - - boost::asio::deadline_timer m_CleanupUDPTimer; + std::unique_ptr m_CleanupUDPTimer; public: // for HTTP From cb91891f2209aa66afa72e055b2efd5aef496eb4 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Sep 2016 16:18:50 -0400 Subject: [PATCH 139/141] check buffer size --- Family.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Family.cpp b/Family.cpp index ff09f2f5..c1840e51 100644 --- a/Family.cpp +++ b/Family.cpp @@ -114,6 +114,12 @@ namespace data { uint8_t buf[50], signatureBuf[64]; size_t len = family.length (), signatureLen = strlen (signature); + if (len + 32 > 50) + { + LogPrint (eLogError, "Family: ", family, " is too long"); + return false; + } + memcpy (buf, family.c_str (), len); memcpy (buf + len, (const uint8_t *)ident, 32); len += 32; From 949be436a60dd8369d982a0527c6b010a7be159a Mon Sep 17 00:00:00 2001 From: l-n-s Date: Fri, 16 Sep 2016 22:56:51 +0000 Subject: [PATCH 140/141] Adding option to configure reseed URLs --- Config.cpp | 17 +++++++++++++++++ Reseed.cpp | 25 +++++-------------------- docs/configuration.md | 1 + 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Config.cpp b/Config.cpp index a629f2d4..33231aa4 100644 --- a/Config.cpp +++ b/Config.cpp @@ -151,6 +151,23 @@ namespace config { options_description reseed("Reseed options"); reseed.add_options() ("reseed.file", value()->default_value(""), "Path to .su3 file") +#ifdef MESHNET + ("reseed.urls", value()->default_value("https://reseed.i2p.rocks:8443/"), "Reseed URLs, separated by comma") +#else + ("reseed.urls", value()->default_value( + "https://reseed.i2p-projekt.de/," + "https://i2p.mooo.com/netDb/," + "https://netdb.i2p2.no/," + "https://us.reseed.i2p2.no:444/," + "https://uk.reseed.i2p2.no:444/," + "https://i2p.manas.ca:8443/," + "https://i2p-0.manas.ca:8443/," + "https://reseed.i2p.vzaws.com:8443/," + "https://user.mx24.eu/," + "https://download.xxlspeed.com/," + "https://reseed-ru.lngserv.ru/" + ), "Reseed URLs, separated by comma") +#endif ; options_description trust("Trust options"); diff --git a/Reseed.cpp b/Reseed.cpp index 21635791..a51dcad4 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -22,26 +23,6 @@ namespace i2p { namespace data { - static std::vector httpsReseedHostList = - { -#ifdef MESHNET - // meshnet i2p reseeds - "https://reseed.i2p.rocks:8443/" -#else - // mainline i2p reseeds - "https://reseed.i2p-projekt.de/", // Only HTTPS - "https://i2p.mooo.com/netDb/", - "https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required - "https://us.reseed.i2p2.no:444/", - "https://uk.reseed.i2p2.no:444/", - "https://i2p.manas.ca:8443/", - "https://i2p-0.manas.ca:8443/", - "https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support - "https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support - "https://download.xxlspeed.com/", // Only HTTPS and SU3 (v3) support - "https://reseed-ru.lngserv.ru/" -#endif - }; Reseeder::Reseeder() { @@ -53,6 +34,10 @@ namespace data int Reseeder::ReseedNowSU3 () { + std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs); + std::vector httpsReseedHostList; + boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on); + std::string filename; i2p::config::GetOption("reseed.file", filename); if (filename.length() > 0) // reseed file is specified { diff --git a/docs/configuration.md b/docs/configuration.md index 32cd7f49..31082dc2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -73,6 +73,7 @@ All options below still possible in cmdline, but better write it in config file: * --precomputation.elgamal= - Use ElGamal precomputated tables. false for x64 and true for other platforms by default * --reseed.file - Full path to SU3 file to reseed from +* --reseed.urls - Reseed URLs, separated by comma * --limits.transittunnels= - Override maximum number of transit tunnels. 2500 by default From 6c7316408bf0b16adbbb152a3e3275a3995fa4e1 Mon Sep 17 00:00:00 2001 From: brain5lug Date: Sat, 17 Sep 2016 11:00:21 +0300 Subject: [PATCH 141/141] address sanitizer configuration option have been added --- build/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index dda0a67c..61b8fdf9 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -16,6 +16,7 @@ option(WITH_UPNP "Include support for UPnP client" OFF) option(WITH_PCH "Use precompiled header" OFF) option(WITH_GUI "Include GUI (currently MS Windows only)" ON) option(WITH_MESHNET "Build for cjdns test network" OFF) +option(WITH_ADDRSANITIZER "Build with address sanitizer (linux only)" OFF) # paths set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" ) @@ -183,6 +184,15 @@ if (WITH_AESNI) add_definitions ( -DAESNI ) endif() +if (WITH_ADDRSANITIZER) + if (NOT MSVC) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer" ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address" ) + else () + error ("MSVC does not support address sanitizer option") + endif() +endif() + # libraries # TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826 # use imported Threads::Threads instead @@ -335,6 +345,7 @@ message(STATUS " STATIC BUILD : ${WITH_STATIC}") message(STATUS " UPnP : ${WITH_UPNP}") message(STATUS " PCH : ${WITH_PCH}") message(STATUS " MESHNET : ${WITH_MESHNET}") +message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") message(STATUS "---------------------------------------") #Handle paths nicely