From 436621f79f9beead905d5baec39bfd0af4637f38 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 Dec 2016 14:38:57 -0500 Subject: [PATCH 01/53] 2.10.2 --- android/AndroidManifest.xml | 2 +- version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index afe7e118..9ffb1c13 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.10.2"> diff --git a/version.h b/version.h index 9aadf505..ef88cbcb 100644 --- a/version.h +++ b/version.h @@ -8,7 +8,7 @@ #define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MINOR 10 -#define I2PD_VERSION_MICRO 1 +#define I2PD_VERSION_MICRO 2 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) #define VERSION I2PD_VERSION From 5b8d637f6a3db06e9eed5f72f77bb263bbb7c7ff Mon Sep 17 00:00:00 2001 From: MXPLRS | Kirill Date: Mon, 5 Dec 2016 00:21:18 +0300 Subject: [PATCH 02/53] 2.10.2 --- Win32/installer.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Win32/installer.iss b/Win32/installer.iss index d51ae7f2..047263cc 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.10.1" +#define I2Pd_ver "2.10.2" #define I2Pd_Publisher "PurpleI2P" [Setup] From 3704a4ff470f783960602a8e47bc83891209a039 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 5 Dec 2016 00:31:41 +0300 Subject: [PATCH 03/53] 2.10.2 --- ChangeLog | 5 +++++ debian/changelog | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index dd1bac57..67f076fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.10.2] - 2016-12-04 +### Fixed +- Fixes UPnP discovery bug, producing excessive CPU usage +- Fixes sudden SSU thread stop for Windows. + ## [2.10.1] - 2016-11-07 ### Fixed - Fixed some performance issues for Windows and Android diff --git a/debian/changelog b/debian/changelog index f71b2e4a..6e6a4c09 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.10.2-1) unstable; urgency=low + + * updated to version 2.10.2 + + -- orignal Sun, 4 Dec 2016 19:38:30 +0000 + i2pd (2.10.1-1) unstable; urgency=low * updated to version 2.10.1 From 42f70cd55dacc08fc3e8ca03ca5dc78cf7f01c6b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Dec 2016 15:45:04 -0500 Subject: [PATCH 04/53] request destination after frist lookup --- NetDb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index e75cf217..dc745bbc 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -882,7 +882,11 @@ namespace data } closestFloodfills = GetClosestFloodfills (ident, 3, excludedRouters, true); if (!numExcluded) // save if no excluded + { m_LookupResponses[ident] = std::make_pair(closestFloodfills, i2p::util::GetSecondsSinceEpoch ()); + if (lookupType != DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) + RequestDestination (ident); // try to request for first time only + } } replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills); } @@ -1197,7 +1201,7 @@ namespace data auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto it = m_LookupResponses.begin (); it != m_LookupResponses.end ();) { - if (ts > it->second.second + 180) // 3 minutes + if (ts > it->second.second + 120) // 2 minutes it = m_LookupResponses.erase (it); else ++it; From adf887a06b733b203709683971adb4063c8d9a6b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Dec 2016 16:36:51 -0500 Subject: [PATCH 05/53] request destination if we are not closest --- NetDb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index dc745bbc..53c6f61d 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -884,7 +884,7 @@ namespace data if (!numExcluded) // save if no excluded { m_LookupResponses[ident] = std::make_pair(closestFloodfills, i2p::util::GetSecondsSinceEpoch ()); - if (lookupType != DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) + if (lookupType != DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP && !closestFloodfills.empty ()) // we are not closest RequestDestination (ident); // try to request for first time only } } From 59681398cbcef1fcfb48736c7fb3f01ff92f8122 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Dec 2016 18:39:01 -0500 Subject: [PATCH 06/53] don't store lookup replies anymore --- NetDb.cpp | 53 ++++++++++------------------------------------------- NetDb.h | 4 +--- 2 files changed, 11 insertions(+), 46 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index 53c6f61d..a1f0fcb7 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -118,7 +118,6 @@ namespace data { SaveUpdated (); ManageLeaseSets (); - ManageLookupResponses (); } lastSave = ts; } @@ -857,37 +856,17 @@ namespace data } if (!replyMsg) - { - LogPrint (eLogWarning, "NetDb: Requested ", key, " not found, ", numExcluded, " peers excluded"); - // find or cleate response - std::vector closestFloodfills; - bool found = false; - if (!numExcluded) - { - auto it = m_LookupResponses.find (ident); - if (it != m_LookupResponses.end ()) - { - closestFloodfills = it->second.first; - found = true; - } - } - if (!found) - { - std::set excludedRouters; - const uint8_t * exclude_ident = excluded; - for (int i = 0; i < numExcluded; i++) - { - excludedRouters.insert (exclude_ident); - exclude_ident += 32; - } - closestFloodfills = GetClosestFloodfills (ident, 3, excludedRouters, true); - if (!numExcluded) // save if no excluded - { - m_LookupResponses[ident] = std::make_pair(closestFloodfills, i2p::util::GetSecondsSinceEpoch ()); - if (lookupType != DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP && !closestFloodfills.empty ()) // we are not closest - RequestDestination (ident); // try to request for first time only - } + { + std::set excludedRouters; + const uint8_t * exclude_ident = excluded; + for (int i = 0; i < numExcluded; i++) + { + excludedRouters.insert (exclude_ident); + exclude_ident += 32; } + auto closestFloodfills = GetClosestFloodfills (ident, 3, excludedRouters, true); + if (closestFloodfills.empty ()) + LogPrint (eLogWarning, "NetDb: Requested ", key, " not found, ", numExcluded, " peers excluded"); replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills); } } @@ -1195,17 +1174,5 @@ namespace data ++it; } } - - void NetDb::ManageLookupResponses () - { - auto ts = i2p::util::GetSecondsSinceEpoch (); - for (auto it = m_LookupResponses.begin (); it != m_LookupResponses.end ();) - { - if (ts > it->second.second + 120) // 2 minutes - it = m_LookupResponses.erase (it); - else - ++it; - } - } } } diff --git a/NetDb.h b/NetDb.h index 954cc74e..0a05c143 100644 --- a/NetDb.h +++ b/NetDb.h @@ -112,7 +112,6 @@ namespace data void Publish (); void ManageLeaseSets (); void ManageRequests (); - void ManageLookupResponses (); void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20); @@ -143,8 +142,7 @@ namespace data /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ std::shared_ptr m_FloodfillBootstrap; - - std::map, uint64_t> > m_LookupResponses; // ident->(closest FFs, timestamp) + /** true if in hidden mode */ bool m_HiddenMode; From 381f6b184e6ad3e71270d3465518c01956720df9 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 Dec 2016 16:23:52 -0500 Subject: [PATCH 07/53] clean up incomplete messages --- TunnelEndpoint.cpp | 9 +++++++++ TunnelEndpoint.h | 1 + 2 files changed, 10 insertions(+) diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index 23cf16f3..b4ddc109 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -116,6 +116,7 @@ namespace tunnel if (!isFollowOnFragment) // create new incomlete message { m.nextFragmentNum = 1; + m.receiveTime = i2p::util::GetMillisecondsSinceEpoch (); auto ret = m_IncompleteMessages.insert (std::pair(msgID, m)); if (ret.second) HandleOutOfSequenceFragments (msgID, ret.first->second); @@ -284,6 +285,14 @@ namespace tunnel else ++it; } + // incomplete messages + for (auto it = m_IncompleteMessages.begin (); it != m_IncompleteMessages.end ();) + { + if (ts > it->second.receiveTime + i2p::I2NP_MESSAGE_EXPIRATION_TIMEOUT) + it = m_IncompleteMessages.erase (it); + else + ++it; + } } } } diff --git a/TunnelEndpoint.h b/TunnelEndpoint.h index 60c4fc0a..e13ced34 100644 --- a/TunnelEndpoint.h +++ b/TunnelEndpoint.h @@ -15,6 +15,7 @@ namespace tunnel { struct TunnelMessageBlockEx: public TunnelMessageBlock { + uint64_t receiveTime; // milliseconds since epoch uint8_t nextFragmentNum; }; From e08a26d0156215c22f2752536d6ae3d650b6a2dc Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Dec 2016 12:59:19 -0500 Subject: [PATCH 08/53] AVX instructions support --- Makefile.linux | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile.linux b/Makefile.linux index 8def8299..6d4762b1 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -60,7 +60,12 @@ ifeq ($(USE_AESNI),yes) ifeq ($(IS_64),1) #check if AES-NI is supported by CPU ifneq ($(shell $(GREP) -c aes /proc/cpuinfo),0) - CPU_FLAGS = -maes -DAESNI + CPU_FLAGS += -maes -DAESNI endif endif endif + +#check if AVX supported by CPU +ifneq ($(shell $(GREP) -c avx /proc/cpuinfo),0) + CPU_FLAGS += -mavx +endif From 447f5f69c9067663dce5bb33ccf3389c94c89078 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 Dec 2016 15:23:40 -0500 Subject: [PATCH 09/53] use AVX for DHT --- Identity.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Identity.cpp b/Identity.cpp index f39e9bd8..19c1a240 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -593,11 +593,25 @@ namespace data XORMetric operator^(const IdentHash& key1, const IdentHash& key2) { XORMetric m; +#if defined(__AVX__) // for AVX + __asm__ + ( + "vmovups %1, %%ymm0 \n" + "vmovups %2, %%ymm1 \n" + "vxorps %%ymm0, %%ymm1, %%ymm1 \n" + "vmovups %%ymm1, %0 \n" + : "=m"(*m.metric) + : "m"(*key1), "m"(*key2) + : "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler + ); +#else const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL (); m.metric_ll[0] = hash1[0] ^ hash2[0]; m.metric_ll[1] = hash1[1] ^ hash2[1]; m.metric_ll[2] = hash1[2] ^ hash2[2]; m.metric_ll[3] = hash1[3] ^ hash2[3]; +#endif + return m; } } From 79e1d54e4c5da5c8aac758d3a1484800234dbd6a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 9 Dec 2016 09:08:03 -0500 Subject: [PATCH 10/53] implement simple bloom filter --- BloomFilter.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++ BloomFilter.h | 31 ++++++++++++++++++++ build/CMakeLists.txt | 1 + filelist.mk | 2 +- 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 BloomFilter.cpp create mode 100644 BloomFilter.h diff --git a/BloomFilter.cpp b/BloomFilter.cpp new file mode 100644 index 00000000..eac931db --- /dev/null +++ b/BloomFilter.cpp @@ -0,0 +1,69 @@ +#include "BloomFilter.h" +#include "I2PEndian.h" +#include +#include + +namespace i2p +{ +namespace util +{ + + /** @brief decaying bloom filter implementation */ + class DecayingBloomFilter : public IBloomFilter + { + public: + + DecayingBloomFilter(const std::size_t size) + { + m_Size = size; + m_Data = new uint8_t[size]; + } + + /** @brief implements IBloomFilter::~IBloomFilter */ + ~DecayingBloomFilter() + { + delete [] m_Data; + } + + /** @brief implements IBloomFilter::Add */ + bool Add(const uint8_t * data, std::size_t len) + { + std::size_t idx; + uint8_t mask; + Get(data, len, idx, mask); + if(m_Data[idx] & mask) return false; // filter hit + m_Data[idx] |= mask; + return true; + } + + /** @brief implements IBloomFilter::Decay */ + void Decay() + { + // reset bloom filter buffer + memset(m_Data, 0, m_Size); + } + + private: + /** @brief get bit index for for data */ + void Get(const uint8_t * data, std::size_t len, std::size_t & idx, uint8_t & bm) + { + bm = 1; + uint8_t digest[32]; + // TODO: use blake2 because it's faster + SHA256(data, len, digest); + uint64_t i = buf64toh(digest); + idx = i % m_Size; + bm <<= (i % 8); + } + + uint8_t * m_Data; + std::size_t m_Size; + }; + + + BloomFilterPtr BloomFilter(std::size_t capacity) + { + return std::make_shared(capacity); + } +} +} diff --git a/BloomFilter.h b/BloomFilter.h new file mode 100644 index 00000000..7d4b28fa --- /dev/null +++ b/BloomFilter.h @@ -0,0 +1,31 @@ +#ifndef BLOOM_FILTER_H_ +#define BLOOM_FILTER_H_ +#include +#include + +namespace i2p +{ +namespace util +{ + + /** @brief interface for bloom filter */ + struct IBloomFilter + { + + /** @brief destructor */ + virtual ~IBloomFilter(); + /** @brief add entry to bloom filter, return false if filter hit otherwise return true */ + virtual bool Add(const uint8_t * data, std::size_t len) = 0; + /** @brief optionally decay old entries */ + virtual void Decay(); + }; + + typedef std::shared_ptr BloomFilterPtr; + + /** @brief create bloom filter */ + BloomFilterPtr BloomFilter(std::size_t capacity = 1024 * 8); + +} +} + +#endif diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 8b42c063..a1fd19c2 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -26,6 +26,7 @@ set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" ) set ( CMAKE_SOURCE_DIR ".." ) set (LIBI2PD_SRC + "${CMAKE_SOURCE_DIR}/BloomFilter.cpp" "${CMAKE_SOURCE_DIR}/Config.cpp" "${CMAKE_SOURCE_DIR}/Crypto.cpp" "${CMAKE_SOURCE_DIR}/Garlic.cpp" diff --git a/filelist.mk b/filelist.mk index 94ce2f22..76f58785 100644 --- a/filelist.mk +++ b/filelist.mk @@ -1,5 +1,5 @@ LIB_SRC = \ - Gzip.cpp Crypto.cpp Datagram.cpp Garlic.cpp I2NPProtocol.cpp LeaseSet.cpp \ + BloomFilter.cpp Gzip.cpp Crypto.cpp Datagram.cpp Garlic.cpp I2NPProtocol.cpp LeaseSet.cpp \ Log.cpp NTCPSession.cpp NetDb.cpp NetDbRequests.cpp Profiling.cpp \ Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \ SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \ From 12371650f9999d624cef376feb788d44f4e1d082 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 9 Dec 2016 09:09:35 -0500 Subject: [PATCH 11/53] tabify --- BloomFilter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BloomFilter.cpp b/BloomFilter.cpp index eac931db..b92039df 100644 --- a/BloomFilter.cpp +++ b/BloomFilter.cpp @@ -30,7 +30,7 @@ namespace util { std::size_t idx; uint8_t mask; - Get(data, len, idx, mask); + Get(data, len, idx, mask); if(m_Data[idx] & mask) return false; // filter hit m_Data[idx] |= mask; return true; From 6d8a23ec16ad92b8ab12754213978cf22af80973 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 9 Dec 2016 09:10:08 -0500 Subject: [PATCH 12/53] tabify --- BloomFilter.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/BloomFilter.h b/BloomFilter.h index 7d4b28fa..1c451454 100644 --- a/BloomFilter.h +++ b/BloomFilter.h @@ -8,22 +8,22 @@ namespace i2p namespace util { - /** @brief interface for bloom filter */ - struct IBloomFilter - { + /** @brief interface for bloom filter */ + struct IBloomFilter + { - /** @brief destructor */ - virtual ~IBloomFilter(); - /** @brief add entry to bloom filter, return false if filter hit otherwise return true */ - virtual bool Add(const uint8_t * data, std::size_t len) = 0; - /** @brief optionally decay old entries */ - virtual void Decay(); - }; + /** @brief destructor */ + virtual ~IBloomFilter(); + /** @brief add entry to bloom filter, return false if filter hit otherwise return true */ + virtual bool Add(const uint8_t * data, std::size_t len) = 0; + /** @brief optionally decay old entries */ + virtual void Decay(); + }; - typedef std::shared_ptr BloomFilterPtr; + typedef std::shared_ptr BloomFilterPtr; - /** @brief create bloom filter */ - BloomFilterPtr BloomFilter(std::size_t capacity = 1024 * 8); + /** @brief create bloom filter */ + BloomFilterPtr BloomFilter(std::size_t capacity = 1024 * 8); } } From fa191e29285aec3c5f169d2aa9b89f9387a10d07 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 9 Dec 2016 09:27:19 -0500 Subject: [PATCH 13/53] fixes issue 732 and wave hi to ISPG --- HTTPServer.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index b358ccec..5deb7c60 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -709,11 +709,15 @@ namespace http { char b64_creds[64]; std::size_t len = 0; len = i2p::data::ByteStreamToBase64((unsigned char *)expected.c_str(), expected.length(), b64_creds, sizeof(b64_creds)); - b64_creds[len] = '\0'; - expected = "Basic "; - expected += b64_creds; - if (provided == expected) - return true; + /* if we decoded properly then check credentials */ + if(len) { + b64_creds[len] = '\0'; + expected = "Basic "; + expected += b64_creds; + return expected == provided; + } + /** we decoded wrong so it's not a correct login credential */ + return false; } LogPrint(eLogWarning, "HTTPServer: auth failure from ", m_Socket->remote_endpoint().address ()); From 2b7bab04ddc6563a815e8cd7343b481e21eb90cf Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Dec 2016 09:50:42 -0500 Subject: [PATCH 14/53] add BloomFilter to QT android --- android/jni/Android.mk | 1 + qt/i2pd_qt/i2pd_qt.pro | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/android/jni/Android.mk b/android/jni/Android.mk index a3d58ce6..cc070984 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -59,6 +59,7 @@ LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \ ../../TunnelPool.cpp \ ../../Timestamp.cpp \ ../../Event.cpp \ + ../../BloomFiler.cpp \ ../../util.cpp \ ../../i2pd.cpp ../../UPnP.cpp diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 143c7b8d..e51eb963 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -36,7 +36,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../SSUData.cpp ../../SSUSession.cpp ../../Streaming.cpp ../../TransitTunnel.cpp \ ../../Transports.cpp ../../Tunnel.cpp ../../TunnelEndpoint.cpp ../../TunnelGateway.cpp \ ../../TunnelPool.cpp ../../UPnP.cpp ../../Gzip.cpp ../../Timestamp.cpp ../../util.cpp \ - ../../Event.cpp ../../i2pd.cpp + ../../Event.cpp ../../BloomFiler.cpp ../../i2pd.cpp HEADERS += DaemonQT.h mainwindow.h \ ../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \ @@ -50,7 +50,8 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../Streaming.h ../../Timestamp.h ../../TransitTunnel.h ../../Transports.h \ ../../TransportSession.h ../../Tunnel.h ../../TunnelBase.h ../../TunnelConfig.h \ ../../TunnelEndpoint.h ../../TunnelGateway.h ../../TunnelPool.h ../../UPnP.h \ - ../../util.h ../../version.h ../../Gzip.h ../../Tag.h ../../Event.h + ../../util.h ../../version.h ../../Gzip.h ../../Tag.h \ + ../../BloomFiler.h ../../Event.h FORMS += mainwindow.ui From 7386b0a5234dc2f632eb0b6eee51ef031d7c500b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Dec 2016 13:42:00 -0500 Subject: [PATCH 15/53] fixed android build --- BloomFilter.h | 4 ++-- android/jni/Android.mk | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BloomFilter.h b/BloomFilter.h index 1c451454..2745fbf5 100644 --- a/BloomFilter.h +++ b/BloomFilter.h @@ -13,11 +13,11 @@ namespace util { /** @brief destructor */ - virtual ~IBloomFilter(); + virtual ~IBloomFilter() {}; /** @brief add entry to bloom filter, return false if filter hit otherwise return true */ virtual bool Add(const uint8_t * data, std::size_t len) = 0; /** @brief optionally decay old entries */ - virtual void Decay(); + virtual void Decay() = 0; }; typedef std::shared_ptr BloomFilterPtr; diff --git a/android/jni/Android.mk b/android/jni/Android.mk index cc070984..c44594f0 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -59,7 +59,7 @@ LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp \ ../../TunnelPool.cpp \ ../../Timestamp.cpp \ ../../Event.cpp \ - ../../BloomFiler.cpp \ + ../../BloomFilter.cpp \ ../../util.cpp \ ../../i2pd.cpp ../../UPnP.cpp From dca48c7eec1ed27e2feeb3c73adbe9ecd57100eb Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Dec 2016 15:46:21 -0500 Subject: [PATCH 16/53] use AVX for HMAC --- Crypto.cpp | 56 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/Crypto.cpp b/Crypto.cpp index 91b0ad08..b87afbc8 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -386,44 +386,58 @@ namespace crypto // HMAC const uint64_t IPAD = 0x3636363636363636; const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C; - + + static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD }; + static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD }; + void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest) // key is 32 bytes // digest is 16 bytes // block size is 64 bytes { uint64_t buf[256]; + uint64_t hash[12]; // 96 bytes +#if defined(__AVX__) // for AVX + __asm__ + ( + "vmovups %[key], %%ymm0 \n" + "vmovups %[ipad], %%ymm1 \n" + "vmovups %%ymm1, 32%[buf] \n" + "vxorps %%ymm0, %%ymm1, %%ymm1 \n" + "vmovups %%ymm1, %[buf] \n" + "vmovups %[opad], %%ymm1 \n" + "vmovups %%ymm1, 32%[hash] \n" + "vxorps %%ymm0, %%ymm1, %%ymm1 \n" + "vmovups %%ymm1, %[hash] \n" + : [buf]"=m"(*buf), [hash]"=m"(*hash) + : [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads) + : "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler + ); +#else // ikeypad buf[0] = key.GetLL ()[0] ^ IPAD; buf[1] = key.GetLL ()[1] ^ IPAD; buf[2] = key.GetLL ()[2] ^ IPAD; buf[3] = key.GetLL ()[3] ^ IPAD; - buf[4] = IPAD; - buf[5] = IPAD; - buf[6] = IPAD; - buf[7] = IPAD; + memcpy (buf + 4, ipads, 32); + // okeypad + hash[0] = key.GetLL ()[0] ^ OPAD; + hash[1] = key.GetLL ()[1] ^ OPAD; + hash[2] = key.GetLL ()[2] ^ OPAD; + hash[3] = key.GetLL ()[3] ^ OPAD; + memcpy (hash + 4, opads, 32); +#endif + // concatenate with msg memcpy (buf + 8, msg, len); // calculate first hash - uint8_t hash[16]; // MD5 - MD5((uint8_t *)buf, len + 64, hash); + MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes - // okeypad - buf[0] = key.GetLL ()[0] ^ OPAD; - buf[1] = key.GetLL ()[1] ^ OPAD; - buf[2] = key.GetLL ()[2] ^ OPAD; - buf[3] = key.GetLL ()[3] ^ OPAD; - buf[4] = OPAD; - buf[5] = OPAD; - buf[6] = OPAD; - buf[7] = OPAD; - // copy first hash after okeypad - memcpy (buf + 8, hash, 16); - // fill next 16 bytes with zeros (first hash size assumed 32 bytes in I2P) - memset (buf + 10, 0, 16); + // fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P) + memset (hash + 10, 0, 16); // calculate digest - MD5((uint8_t *)buf, 96, digest); + MD5((uint8_t *)hash, 96, digest); } // AES From 259baa0e840c7ddbea1925bb06b98b344aae1001 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 10 Dec 2016 20:41:42 -0500 Subject: [PATCH 17/53] use vzeroall to complete AVX mode --- Crypto.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Crypto.cpp b/Crypto.cpp index b87afbc8..5de3a4ee 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -409,9 +409,11 @@ namespace crypto "vmovups %%ymm1, 32%[hash] \n" "vxorps %%ymm0, %%ymm1, %%ymm1 \n" "vmovups %%ymm1, %[hash] \n" + "vzeroall \n" // end of AVX + "movups %%xmm0, 80%[hash] \n" // zero last 16 bytes : [buf]"=m"(*buf), [hash]"=m"(*hash) : [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads) - : "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler + : "memory" ); #else // ikeypad @@ -426,15 +428,14 @@ namespace crypto hash[2] = key.GetLL ()[2] ^ OPAD; hash[3] = key.GetLL ()[3] ^ OPAD; memcpy (hash + 4, opads, 32); + // fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P) + memset (hash + 10, 0, 16); #endif // concatenate with msg memcpy (buf + 8, msg, len); // calculate first hash - MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes - - // fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P) - memset (hash + 10, 0, 16); + MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes // calculate digest MD5((uint8_t *)hash, 96, digest); From 67492bf024601b0434725a38f00256ac263d74b2 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Dec 2016 09:53:43 -0500 Subject: [PATCH 18/53] send v4 address for peer test --- SSUSession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SSUSession.cpp b/SSUSession.cpp index 696d367f..0e277432 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -1101,7 +1101,7 @@ namespace transport { // we are Alice LogPrint (eLogDebug, "SSU: sending peer test"); - auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false); + auto address = i2p::context.GetRouterInfo ().GetSSUAddress (i2p::context.SupportsV4 ()); if (!address) { LogPrint (eLogInfo, "SSU is not supported. Can't send peer test"); From 4b9de0777b2355db46ef3c15c4cab6c60ac2c486 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Dec 2016 14:17:09 -0500 Subject: [PATCH 19/53] queue up LeaseSet requests --- Destination.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 61960464..491a9f29 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -544,11 +544,14 @@ namespace client else // duplicate { LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already"); - // TODO: implement it properly - //ret.first->second->requestComplete.push_back (requestComplete); if (ts > ret.first->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT) + { + // something went wrong m_LeaseSetRequests.erase (ret.first); - if (requestComplete) requestComplete (nullptr); + if (requestComplete) requestComplete (nullptr); + } + else if (requestComplete) + ret.first->second->requestComplete.push_back (requestComplete); } } else From 5405876d846f136363686baf19966ce0cec22554 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 Dec 2016 20:38:19 -0500 Subject: [PATCH 20/53] temporary exlude mamoth's shit from reseeds --- Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.cpp b/Config.cpp index 6f4014ba..20036b83 100644 --- a/Config.cpp +++ b/Config.cpp @@ -171,7 +171,7 @@ namespace config { "https://i2p.mooo.com/netDb/," "https://netdb.i2p2.no/," "https://us.reseed.i2p2.no:444/," - "https://uk.reseed.i2p2.no:444/," +// "https://uk.reseed.i2p2.no:444/," // mamoth's shit "https://i2p-0.manas.ca:8443/," "https://reseed.i2p.vzaws.com:8443/," "https://download.xxlspeed.com/," From ac2caf27877b34c9802413fcd120f72f78da211a Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 Dec 2016 14:45:37 -0500 Subject: [PATCH 21/53] make sure all incoming data gets sent before closing a socket --- Streaming.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Streaming.h b/Streaming.h index 65a8d8b4..bf19f92a 100644 --- a/Streaming.h +++ b/Streaming.h @@ -285,7 +285,7 @@ namespace stream auto s = shared_from_this(); m_Service.post ([=](void) { - if (!m_ReceiveQueue.empty () || m_Status == eStreamStatusReset) + if (!m_ReceiveQueue.empty () || m_Status == eStreamStatusReset || m_Status == eStreamStatusClosed) s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler, 0); else { @@ -306,7 +306,7 @@ namespace stream else if (ecode == boost::asio::error::operation_aborted) { // timeout not expired - if (m_Status == eStreamStatusReset) + if (m_Status == eStreamStatusReset || m_Status == eStreamStatusClosed) handler (boost::asio::error::make_error_code (boost::asio::error::connection_reset), 0); else handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), 0); From 75690598e368cf8e541e0d68ccd4cfd443ccd92c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 12 Dec 2016 13:40:24 -0500 Subject: [PATCH 22/53] try fixing datagram --- AddressBook.cpp | 2 +- Datagram.cpp | 353 +++++++++++++++++------------------------------- Datagram.h | 74 +++++----- 3 files changed, 153 insertions(+), 276 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index db424308..685acbc2 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -842,7 +842,7 @@ namespace client else memset (response + 8, 0, 32); // not found memset (response + 40, 0, 4); // set expiration time to zero - m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 44, from.GetIdentHash (), toPort, fromPort); + m_LocalDestination->GetDatagramDestination ()->SendDatagramTo (response, 44, from.GetIdentHash(), toPort, fromPort); } void AddressResolver::AddAddress (const std::string& name, const i2p::data::IdentHash& ident) diff --git a/Datagram.cpp b/Datagram.cpp index d0b0737a..a06a8e5d 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -22,9 +22,9 @@ namespace datagram { m_Sessions.clear(); } - - void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort, uint16_t toPort) - { + + void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) + { auto owner = m_Owner; std::vector v(MAX_DATAGRAM_SIZE); uint8_t * buf = v.data(); @@ -45,8 +45,7 @@ namespace datagram owner->Sign (buf1, len, signature); auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort); - auto session = ObtainSession(ident); - session->SendMsg(msg); + ObtainSession(identity)->SendMsg(msg); } @@ -69,6 +68,8 @@ namespace datagram if (verified) { + auto h = identity.GetIdentHash(); + ObtainSession(h)->Ack(); auto r = FindReceiver(toPort); if(r) r(identity, fromPort, toPort, buf + headerLen, len -headerLen); @@ -138,15 +139,15 @@ namespace datagram } } - std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & ident) + std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & identity) { std::shared_ptr session = nullptr; std::lock_guard lock(m_SessionsMutex); - auto itr = m_Sessions.find(ident); + auto itr = m_Sessions.find(identity); if (itr == m_Sessions.end()) { // not found, create new session - session = std::make_shared(m_Owner, ident); - m_Sessions[ident] = session; + session = std::make_shared(m_Owner, identity); + m_Sessions[identity] = session; } else { session = itr->second; } @@ -164,13 +165,13 @@ namespace datagram } DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, - const i2p::data::IdentHash & remoteIdent) : + const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), - m_RemoteIdentity(remoteIdent), - m_LastUse(i2p::util::GetMillisecondsSinceEpoch ()), - m_LastPathChange(0), - m_LastSuccess(0) + m_RemoteIdent(remoteIdent), + m_SendQueueTimer(localDestination->GetService()) { + m_LastUse = i2p::util::GetMillisecondsSinceEpoch (); + ScheduleFlushSendQueue(); } void DatagramSession::SendMsg(std::shared_ptr msg) @@ -184,262 +185,150 @@ 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); auto routingPath = m_RoutingSession->GetSharedRoutingPath(); if (!routingPath) - return DatagramSession::Info(nullptr, nullptr, m_LastUse, m_LastSuccess); + return DatagramSession::Info(nullptr, nullptr, m_LastUse); 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); else - return DatagramSession::Info(lease->tunnelGateway, nullptr, m_LastUse, m_LastSuccess); + return DatagramSession::Info(lease->tunnelGateway, nullptr, m_LastUse); } else if(tunnel) - return DatagramSession::Info(nullptr, tunnel->GetEndpointIdentHash(), m_LastUse, m_LastSuccess); + return DatagramSession::Info(nullptr, tunnel->GetEndpointIdentHash(), m_LastUse); 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); - else - { - UpdateLeaseSet(msg); - return; - } - } - // 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 - auto path = GetNextRoutingPath(); - if(path) - UpdateRoutingPath (path); - else - ResetRoutingPath(); - } - 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 (m_LastPathChange && now - m_LastPathChange >= DATAGRAM_SESSION_PATH_TIMEOUT ) ResetRoutingPath(); - UpdateLeaseSet(msg); - - } - - void DatagramSession::UpdateRoutingPath(const std::shared_ptr & path) - { - 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); - m_LastPathChange = i2p::util::GetMillisecondsSinceEpoch (); + return DatagramSession::Info(nullptr, nullptr, m_LastUse); } - bool DatagramSession::ShouldUpdateRoutingPath() const + void DatagramSession::Ack() { - bool dead = m_RoutingSession == nullptr || m_RoutingSession->GetSharedRoutingPath () == nullptr; - 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; - // too fast switching paths - if (now - m_LastPathChange < DATAGRAM_SESSION_PATH_MIN_LIFETIME ) return false; - // our path looks dead so we need to rotate paths - if (now - m_LastSuccess >= DATAGRAM_SESSION_PATH_TIMEOUT) return !dead; - // if we have a routing session and routing path we don't need to switch paths - return dead; + m_LastUse = i2p::util::GetMillisecondsSinceEpoch(); + auto path = GetSharedRoutingPath(); + if(path) + path->updateTime = i2p::util::GetSecondsSinceEpoch (); } - - bool DatagramSession::ShouldSwitchLease() const - { - 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 currentLease->ExpiresWithin( DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE ); - // we have no current lease, we should switch - return currentLease == nullptr; - } - - std::shared_ptr DatagramSession::GetNextRoutingPath() + std::shared_ptr DatagramSession::GetSharedRoutingPath () { - 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; + if(!m_RoutingSession) { + if(!m_RemoteLeaseSet) { + m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); } - else - outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(routingPath->outboundTunnel); // no so we'll switch outbound tunnels + if(!m_RemoteLeaseSet) { + // no remote lease set + return nullptr; + } + m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); } - // 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) - { - std::shared_ptr lease = nullptr; - // should we switch leases ? - if (ShouldSwitchLease ()) - { - // yes, get next available lease - lease = GetNextLease(); + auto path = m_RoutingSession->GetSharedRoutingPath(); + if(path) { + if (m_CurrentOutboundTunnel && !m_CurrentOutboundTunnel->IsEstablished()) { + // bad outbound tunnel, switch outbound tunnel + m_CurrentOutboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(m_CurrentOutboundTunnel); + path->outboundTunnel = m_CurrentOutboundTunnel; } - else if (routingPath) - { - if(routingPath->remoteLease) - { - if(routingPath->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW, DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE)) - lease = GetNextLease(); - else - lease = routingPath->remoteLease; + if(m_CurrentRemoteLease && ! m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { + // bad lease, switch to next one + if(m_RemoteLeaseSet) { + auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding([&](const i2p::data::Lease& l) -> bool { + return l.tunnelGateway == m_CurrentRemoteLease->tunnelGateway || l.endDate <= m_CurrentRemoteLease->endDate; + }); + auto sz = ls.size(); + if (sz) { + auto idx = rand() % sz; + m_CurrentRemoteLease = ls[idx]; + } else { + // no more leases, bail + LogPrint(eLogWarning, "DatagramSession: no more valid remote leases to ", m_RemoteIdent.ToBase32()); + } + } else { + // no remote lease set? + LogPrint(eLogWarning, "DatagramSession: no cached remote lease set for ", m_RemoteIdent.ToBase32()); } + path->remoteLease = m_CurrentRemoteLease; } - else - 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 - }); + } else { + // no current path, make one + path = std::make_shared(); + // switch outbound tunnel if bad + if(m_CurrentOutboundTunnel == nullptr || ! m_CurrentOutboundTunnel->IsEstablished()) { + m_CurrentOutboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(m_CurrentOutboundTunnel); + } + // switch lease if bad + if(m_CurrentRemoteLease == nullptr || m_CurrentRemoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW)) { + if(!m_RemoteLeaseSet) { + m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent); + } + if(m_RemoteLeaseSet) { + // pick random next good lease + auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding([&] (const i2p::data::Lease & l) -> bool { + if(m_CurrentRemoteLease) + return l.tunnelGateway == m_CurrentRemoteLease->tunnelGateway; + return false; + }); + auto sz = ls.size(); + if(sz) { + auto idx = rand() % sz; + m_CurrentRemoteLease = ls[idx]; + } + } else { + // no remote lease set currently, bail + LogPrint(eLogWarning, "DatagramSession: no remote lease set found for ", m_RemoteIdent.ToBase32()); + return nullptr; + } } - else // we don't have a new routing path to give - routingPath = nullptr; + path->outboundTunnel = m_CurrentOutboundTunnel; + path->remoteLease = m_CurrentRemoteLease; + m_RoutingSession->SetSharedRoutingPath(path); } - return routingPath; + return path; + } - void DatagramSession::ResetRoutingPath() + void DatagramSession::HandleLeaseSetUpdated(std::shared_ptr ls) { - 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); - } + // only update lease set if found and newer than previous lease set + uint64_t oldExpire = 0; + if(m_RemoteLeaseSet) oldExpire = m_RemoteLeaseSet->GetExpirationTime(); + if(ls && ls->GetExpirationTime() > oldExpire) m_RemoteLeaseSet = ls; } - std::shared_ptr DatagramSession::GetNextLease() + void DatagramSession::HandleSend(std::shared_ptr msg) { - auto now = i2p::util::GetMillisecondsSinceEpoch (); - std::shared_ptr next = nullptr; - if(m_RemoteLeaseSet) + m_SendQueue.push_back(msg); + // flush queue right away if full + if(m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue(); + } + + void DatagramSession::FlushSendQueue () + { + + std::vector send; + auto routingPath = GetSharedRoutingPath(); + // if we don't have a routing path we will drop all queued messages + if(routingPath) { - 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; - }) != end; - } - else - return false; - }); - if(leases.size()) + for (const auto & msg : m_SendQueue) { - // pick random valid next lease - uint32_t idx = rand() % leases.size(); - next = leases[idx]; + auto m = m_RoutingSession->WrapSingleMessage(msg); + send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m}); } - else - LogPrint(eLogWarning, "DatagramDestination: no leases to use"); + routingPath->outboundTunnel->SendTunnelDataMsg(send); } - 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)); + m_SendQueue.clear(); + ScheduleFlushSendQueue(); } - void DatagramSession::HandleGotLeaseSet(std::shared_ptr remoteIdent, std::shared_ptr msg) + void DatagramSession::ScheduleFlushSendQueue() { - 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; - // update routing path - auto path = GetNextRoutingPath(); - if (path) - UpdateRoutingPath(path); - else - ResetRoutingPath(); - // send the message that was queued if it was provided - if(msg) - HandleSend(msg); - } + boost::posix_time::milliseconds dlt(100); + m_SendQueueTimer.expires_from_now(dlt); + m_SendQueueTimer.async_wait([&](const boost::system::error_code & ec) { if(ec) return; FlushSendQueue(); }); } } } diff --git a/Datagram.h b/Datagram.h index dc63cccb..8891f0cc 100644 --- a/Datagram.h +++ b/Datagram.h @@ -31,29 +31,33 @@ namespace datagram const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000; // milliseconds minimum time between path switches const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000; + // max 64 messages buffered in send queue for each datagram session + const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64; class DatagramSession { public: DatagramSession(i2p::client::ClientDestination * localDestination, - const i2p::data::IdentHash & remoteIdent); + const i2p::data::IdentHash & remoteIdent); + + + /** @brief ack the garlic routing path */ + void Ack(); /** 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; } - /** get the last time in milliseconds when we successfully sent data */ - uint64_t LastSuccess() const { return m_LastSuccess; } + struct Info { 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) { + + Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {} + Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) : + activity(a) { if(ibgw) IBGW = std::make_shared(ibgw); else IBGW = nullptr; if(obep) OBEP = std::make_shared(obep); @@ -63,44 +67,28 @@ namespace datagram Info GetSessionInfo() const; - private: - /** update our routing path we are using, mark that we have changed paths */ - void UpdateRoutingPath(const std::shared_ptr & path); + void FlushSendQueue(); + void ScheduleFlushSendQueue(); - /** return true if we should switch routing paths because of path lifetime or timeout otherwise false */ - bool ShouldUpdateRoutingPath() const; + void HandleSend(std::shared_ptr msg); + + std::shared_ptr GetSharedRoutingPath(); + + void HandleLeaseSetUpdated(std::shared_ptr ls); - /** 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; + i2p::data::IdentHash m_RemoteIdent; + std::shared_ptr m_RemoteLeaseSet; + std::shared_ptr m_RoutingSession; + std::shared_ptr m_CurrentRemoteLease; + std::shared_ptr m_CurrentOutboundTunnel; + boost::asio::deadline_timer m_SendQueueTimer; + std::vector > m_SendQueue; + uint64_t m_LastUse; + }; const size_t MAX_DATAGRAM_SIZE = 32768; @@ -112,9 +100,9 @@ namespace datagram DatagramDestination (std::shared_ptr owner); - ~DatagramDestination (); + ~DatagramDestination (); - void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint16_t fromPort = 0, uint16_t toPort = 0); + void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; @@ -130,7 +118,7 @@ namespace datagram private: - std::shared_ptr ObtainSession(const i2p::data::IdentHash & ident); + 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); From 919aa2895a3775c317babb9b731ea5983ee485ff Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 12 Dec 2016 14:39:05 -0500 Subject: [PATCH 23/53] request lease set --- Datagram.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Datagram.cpp b/Datagram.cpp index a06a8e5d..ca13863e 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -221,6 +221,7 @@ namespace datagram } if(!m_RemoteLeaseSet) { // no remote lease set + m_LocalDestination->RequestDestination(m_RemoteIdent, std::bind(&DatagramSession::HandleLeaseSetUpdated, this, std::placeholders::_1)); return nullptr; } m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); From 9a19b5994b9e412aab723888bfb69ff40cf99092 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 12 Dec 2016 15:50:36 -0500 Subject: [PATCH 24/53] fix --- I2PTunnel.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 93bcff0c..0f9188b6 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -540,9 +540,13 @@ namespace client 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; - }); + auto itr = m_Sessions.begin(); + while(itr != m_Sessions.end()) { + if(now - (*itr)->LastActivity >= delta ) + itr = m_Sessions.erase(itr); + else + ++itr; + } } UDPSession * I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) From e1d9eca7bd4df3abdf5c9a1a0b4e6b75f6f01c90 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 Dec 2016 09:49:42 -0500 Subject: [PATCH 25/53] 0.9.28 --- version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.h b/version.h index ef88cbcb..ed84efd1 100644 --- a/version.h +++ b/version.h @@ -21,7 +21,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 27 +#define I2P_VERSION_MICRO 28 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From c45f72a63e08a551797cd4e47f654d322d1d0f80 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 Dec 2016 11:01:13 -0500 Subject: [PATCH 26/53] make sure all outstading data got sent before closing socket --- I2PTunnel.cpp | 11 +++++++++-- Streaming.h | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 0f9188b6..fdc5bc52 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -92,8 +92,15 @@ namespace client m_Stream->Close (); m_Stream.reset (); } - m_Socket->close (); - Done(shared_from_this ()); + auto s = shared_from_this (); + // make sure all outstading jobs finished before close + m_Socket->get_io_service ().post( + [s]() + { + s->m_Socket->close (); + }); + + Done(s); } void I2PTunnelConnection::Receive () diff --git a/Streaming.h b/Streaming.h index bf19f92a..65a8d8b4 100644 --- a/Streaming.h +++ b/Streaming.h @@ -285,7 +285,7 @@ namespace stream auto s = shared_from_this(); m_Service.post ([=](void) { - if (!m_ReceiveQueue.empty () || m_Status == eStreamStatusReset || m_Status == eStreamStatusClosed) + if (!m_ReceiveQueue.empty () || m_Status == eStreamStatusReset) s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler, 0); else { @@ -306,7 +306,7 @@ namespace stream else if (ecode == boost::asio::error::operation_aborted) { // timeout not expired - if (m_Status == eStreamStatusReset || m_Status == eStreamStatusClosed) + if (m_Status == eStreamStatusReset) handler (boost::asio::error::make_error_code (boost::asio::error::connection_reset), 0); else handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), 0); From cfde1f8c2716644932d14c19ff75dbfb2d090b30 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 Dec 2016 12:44:05 -0500 Subject: [PATCH 27/53] rollback --- I2PTunnel.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index fdc5bc52..c98fb8c8 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -92,15 +92,9 @@ namespace client m_Stream->Close (); m_Stream.reset (); } - auto s = shared_from_this (); - // make sure all outstading jobs finished before close - m_Socket->get_io_service ().post( - [s]() - { - s->m_Socket->close (); - }); + m_Socket->close (); - Done(s); + Done(shared_from_this ()); } void I2PTunnelConnection::Receive () From c065fae4221f9d9a296a8636d67466c0c7f074e2 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 Dec 2016 12:45:18 -0500 Subject: [PATCH 28/53] store remote IdentHash only --- Garlic.cpp | 14 ++++++++------ Garlic.h | 4 +++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index ab20ac8f..192d47a0 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -18,7 +18,7 @@ namespace garlic { GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet): - m_Owner (owner), m_Destination (destination), m_NumTags (numTags), + m_Owner (owner), m_IsDestination (destination->IsDestination ()), m_NumTags (numTags), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0), m_ElGamalEncryption (new i2p::crypto::ElGamalEncryption (destination->GetEncryptionPublicKey ())) @@ -26,10 +26,12 @@ namespace garlic // create new session tags and session key RAND_bytes (m_SessionKey, 32); m_Encryption.SetKey (m_SessionKey); + if (m_IsDestination) + m_DestinationIdent = destination->GetIdentHash (); } GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): - m_Owner (nullptr), m_Destination (nullptr), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) + m_Owner (nullptr), m_IsDestination (false), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) { memcpy (m_SessionKey, sessionKey, 32); m_Encryption.SetKey (m_SessionKey); @@ -177,7 +179,7 @@ namespace garlic if (!tagFound) // new session { LogPrint (eLogInfo, "Garlic: No tags available, will use ElGamal"); - if (!m_Destination) + if (!m_ElGamalEncryption) { LogPrint (eLogError, "Garlic: Can't use ElGamal for unknown destination"); return nullptr; @@ -297,7 +299,7 @@ namespace garlic } if (msg) // clove message ifself if presented { - size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false); + size += CreateGarlicClove (payload + size, msg, m_IsDestination); (*numCloves)++; } memset (payload + size, 0, 3); // certificate of message @@ -315,11 +317,11 @@ namespace garlic { uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec size_t size = 0; - if (isDestination && m_Destination) + if (isDestination) { buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination size++; - memcpy (buf + size, m_Destination->GetIdentHash (), 32); + memcpy (buf + size, m_DestinationIdent, 32); size += 32; } else diff --git a/Garlic.h b/Garlic.h index a7e2d264..523399cc 100644 --- a/Garlic.h +++ b/Garlic.h @@ -127,7 +127,9 @@ namespace garlic private: GarlicDestination * m_Owner; - std::shared_ptr m_Destination; + bool m_IsDestination; // destination or RouterInfo ? + i2p::data::IdentHash m_DestinationIdent; + i2p::crypto::AESKey m_SessionKey; std::list m_SessionTags; int m_NumTags; From 9c7de5ad032165d9cc29c6569281209ab0d0f9fa Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 Dec 2016 14:54:48 -0500 Subject: [PATCH 29/53] avoid sending RST instead FIN --- I2PTunnel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index c98fb8c8..2b7ccc0e 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -92,6 +92,7 @@ namespace client m_Stream->Close (); m_Stream.reset (); } + m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_send); // avoid RST m_Socket->close (); Done(shared_from_this ()); @@ -108,9 +109,11 @@ namespace client { if (ecode) { - LogPrint (eLogError, "I2PTunnel: read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) + { + LogPrint (eLogError, "I2PTunnel: read error: ", ecode.message ()); Terminate (); + } } else { From b57a62fece6995c32022159abee3aeaedc167905 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Dec 2016 09:35:15 -0500 Subject: [PATCH 30/53] static and AVX support for OSX --- Makefile.osx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Makefile.osx b/Makefile.osx index f40ce1af..c8a7de2a 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -3,21 +3,26 @@ CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX #CXXFLAGS = -g -O2 -Wall -std=c++11 INCFLAGS = -I/usr/local/include -I/usr/local/ssl/include LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/ssl/lib + +ifeq ($(USE_STATIC),yes) +LDLIBS = -lz -lcrypto -lssl /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread +else LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread +endif ifeq ($(USE_UPNP),yes) LDFLAGS += -ldl CXXFLAGS += -DUSE_UPNP endif -# OSX Notes -# http://www.hutsby.net/2011/08/macs-with-aes-ni.html -# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2 -# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic ifeq ($(USE_AESNI),yes) CXXFLAGS += -maes -DAESNI endif +ifeq ($(USE_AVX),yes) + CXXFLAGS += -mavx +endif + # Disabled, since it will be the default make rule. I think its better # to define the default rule in Makefile and not Makefile. - torkel #install: all From 15b7284a8f63fe122f1d57f8cc4364fa63770e9e Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Dec 2016 09:48:05 -0500 Subject: [PATCH 31/53] AVX support for Windows --- Makefile.mingw | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile.mingw b/Makefile.mingw index e2dae747..40cf14b3 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -39,9 +39,13 @@ endif # don't change following line to ifeq ($(USE_AESNI),yes) !!! ifeq ($(USE_AESNI),1) - CPU_FLAGS = -maes -DAESNI + CPU_FLAGS += -maes -DAESNI else - CPU_FLAGS = -msse + CPU_FLAGS += -msse +endif + +ifeq ($(USE_AVX),1) + CPU_FLAGS += -mavx endif ifeq ($(USE_ASLR),yes) From 37e4dfc5d58d939fc9250c88becdce160689b7c7 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Dec 2016 10:59:36 -0500 Subject: [PATCH 32/53] cleanup from some overhead --- NetDb.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index a1f0fcb7..88d5483f 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -912,7 +912,6 @@ namespace data uint8_t randomHash[32]; std::vector msgs; - std::set floodfills; LogPrint (eLogInfo, "NetDb: exploring new ", numDestinations, " routers ..."); for (int i = 0; i < numDestinations; i++) { @@ -924,9 +923,8 @@ namespace data return; } auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); - if (floodfill && !floodfills.count (floodfill.get ())) // request floodfill only once + if (floodfill) { - floodfills.insert (floodfill.get ()); if (i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) throughTunnels = false; if (throughTunnels) From b9552c42f1966b757101d00fcb2cf31bc73f864e Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Dec 2016 11:32:20 -0500 Subject: [PATCH 33/53] don't overwrite whole lease --- LeaseSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 04dc77c5..bddb517e 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -91,7 +91,7 @@ namespace data if (m_StoreLeases) { auto ret = m_Leases.insert (std::make_shared(lease)); - if (!ret.second) *(*ret.first) = lease; // update existing + if (!ret.second) (*ret.first)->endDate = lease.endDate; // update existing (*ret.first)->isUpdated = true; // check if lease's gateway is in our netDb if (!netdb.FindRouter (lease.tunnelGateway)) From 992603496e95b27870a80ba854b9b024805f6886 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 Dec 2016 13:54:16 -0500 Subject: [PATCH 34/53] don't copy address --- RouterInfo.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/RouterInfo.cpp b/RouterInfo.cpp index b570d6c2..4ae2f9e5 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -167,19 +167,19 @@ namespace data { uint8_t supportedTransports = 0; bool isValidAddress = true; - Address address; - s.read ((char *)&address.cost, sizeof (address.cost)); - s.read ((char *)&address.date, sizeof (address.date)); + auto address = std::make_shared
(); + s.read ((char *)&address->cost, sizeof (address->cost)); + s.read ((char *)&address->date, sizeof (address->date)); char transportStyle[5]; ReadString (transportStyle, 5, s); if (!strcmp (transportStyle, "NTCP")) - address.transportStyle = eTransportNTCP; + address->transportStyle = eTransportNTCP; else if (!strcmp (transportStyle, "SSU")) - address.transportStyle = eTransportSSU; + address->transportStyle = eTransportSSU; else - address.transportStyle = eTransportUnknown; - address.port = 0; - address.mtu = 0; + address->transportStyle = eTransportUnknown; + address->port = 0; + address->mtu = 0; uint16_t size, r = 0; s.read ((char *)&size, sizeof (size)); if (!s) return; size = be16toh (size); @@ -194,35 +194,35 @@ namespace data if (!strcmp (key, "host")) { boost::system::error_code ecode; - address.host = boost::asio::ip::address::from_string (value, ecode); + address->host = boost::asio::ip::address::from_string (value, ecode); if (ecode) { - if (address.transportStyle == eTransportNTCP) + if (address->transportStyle == eTransportNTCP) { supportedTransports |= eNTCPV4; // TODO: - address.addressString = value; + address->addressString = value; } else { supportedTransports |= eSSUV4; // TODO: - address.addressString = value; + address->addressString = value; } } else { // add supported protocol - if (address.host.is_v4 ()) - supportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; + if (address->host.is_v4 ()) + supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; else - supportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6; + supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6; } } else if (!strcmp (key, "port")) - address.port = boost::lexical_cast(value); + address->port = boost::lexical_cast(value); else if (!strcmp (key, "mtu")) - address.mtu = boost::lexical_cast(value); + address->mtu = boost::lexical_cast(value); else if (!strcmp (key, "key")) - Base64ToByteStream (value, strlen (value), address.key, 32); + Base64ToByteStream (value, strlen (value), address->key, 32); else if (!strcmp (key, "caps")) ExtractCaps (value); else if (key[0] == 'i') @@ -237,9 +237,9 @@ namespace data 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); + if (index >= address->introducers.size ()) + address->introducers.resize (index + 1); + Introducer& introducer = address->introducers.at (index); if (!strcmp (key, "ihost")) { boost::system::error_code ecode; @@ -256,7 +256,7 @@ namespace data } if (isValidAddress) { - addresses->push_back(std::make_shared
(address)); + addresses->push_back(address); m_SupportedTransports |= supportedTransports; } } From 34df1b16461dc260114d7a6469fe02cedb36bc11 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 Dec 2016 07:21:34 -0500 Subject: [PATCH 35/53] add AVX to clobber list --- Crypto.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Crypto.cpp b/Crypto.cpp index 5de3a4ee..67c1f226 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -386,9 +386,11 @@ namespace crypto // HMAC const uint64_t IPAD = 0x3636363636363636; const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C; - + +#if defined(__AVX__) static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD }; static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD }; +#endif void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest) // key is 32 bytes @@ -413,7 +415,7 @@ namespace crypto "movups %%xmm0, 80%[hash] \n" // zero last 16 bytes : [buf]"=m"(*buf), [hash]"=m"(*hash) : [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads) - : "memory" + : "memory", "%xmm0" // TODO: change to %ymm0 later ); #else // ikeypad @@ -421,13 +423,19 @@ namespace crypto buf[1] = key.GetLL ()[1] ^ IPAD; buf[2] = key.GetLL ()[2] ^ IPAD; buf[3] = key.GetLL ()[3] ^ IPAD; - memcpy (buf + 4, ipads, 32); + buf[4] = IPAD; + buf[5] = IPAD; + buf[6] = IPAD; + buf[7] = IPAD; // okeypad hash[0] = key.GetLL ()[0] ^ OPAD; hash[1] = key.GetLL ()[1] ^ OPAD; hash[2] = key.GetLL ()[2] ^ OPAD; hash[3] = key.GetLL ()[3] ^ OPAD; - memcpy (hash + 4, opads, 32); + hash[4] = OPAD; + hash[5] = OPAD; + hash[6] = OPAD; + hash[7] = OPAD; // fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P) memset (hash + 10, 0, 16); #endif From 6913da7efa4834ab0f0459ad3f206518df6b8a3e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 Dec 2016 10:43:48 -0500 Subject: [PATCH 36/53] fixed AVX crash for mingw build --- Crypto.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Crypto.cpp b/Crypto.cpp index 67c1f226..a4a794ac 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -404,17 +404,18 @@ namespace crypto ( "vmovups %[key], %%ymm0 \n" "vmovups %[ipad], %%ymm1 \n" - "vmovups %%ymm1, 32%[buf] \n" + "vmovups %%ymm1, 32(%[buf]) \n" "vxorps %%ymm0, %%ymm1, %%ymm1 \n" - "vmovups %%ymm1, %[buf] \n" + "vmovups %%ymm1, (%[buf]) \n" "vmovups %[opad], %%ymm1 \n" - "vmovups %%ymm1, 32%[hash] \n" + "vmovups %%ymm1, 32(%[hash]) \n" "vxorps %%ymm0, %%ymm1, %%ymm1 \n" - "vmovups %%ymm1, %[hash] \n" + "vmovups %%ymm1, (%[hash]) \n" "vzeroall \n" // end of AVX - "movups %%xmm0, 80%[hash] \n" // zero last 16 bytes - : [buf]"=m"(*buf), [hash]"=m"(*hash) - : [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads) + "movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes + : + : [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads), + [buf]"r"(buf), [hash]"r"(hash) : "memory", "%xmm0" // TODO: change to %ymm0 later ); #else From 10d6cd989608d85dd80ec19433ca66f817a73bbf Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 Dec 2016 13:10:12 -0500 Subject: [PATCH 37/53] use token for commands --- HTTPServer.cpp | 42 +++++++++++++++++++++++++++++++----------- HTTPServer.h | 20 ++++++++++++++++---- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 5deb7c60..368c5e21 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -451,26 +451,26 @@ namespace http { s << "
\r\n"; } - static void ShowCommands (std::stringstream& s) + static void ShowCommands (std::stringstream& s, uint32_t token) { /* commands */ s << "Router Commands
\r\n"; - s << " Run peer test
\r\n"; + s << " Run peer test
\r\n"; //s << " Reload config
\r\n"; if (i2p::context.AcceptsTunnels ()) - s << " Decline transit tunnels
\r\n"; + s << " Decline transit tunnels
\r\n"; else - s << " Accept transit tunnels
\r\n"; + s << " Accept transit tunnels
\r\n"; #if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) if (Daemon.gracefulShutdownInterval) - s << " Cancel graceful shutdown
"; + s << " Cancel graceful shutdown
"; else - s << " Start graceful shutdown
\r\n"; + s << " Start graceful shutdown
\r\n"; #endif #ifdef WIN32_APP - s << " Graceful shutdown
\r\n"; + s << " Graceful shutdown
\r\n"; #endif - s << " Force shutdown
\r\n"; + s << " Force shutdown
\r\n"; } static void ShowTransitTunnels (std::stringstream& s) @@ -756,6 +756,7 @@ namespace http { SendReply (res, content); } + std::map HTTPConnection::m_Tokens; void HTTPConnection::HandlePage (const HTTPReq& req, HTTPRes& res, std::stringstream& s) { std::map params; @@ -771,7 +772,20 @@ namespace http { else if (page == HTTP_PAGE_TUNNELS) ShowTunnels (s); else if (page == HTTP_PAGE_COMMANDS) - ShowCommands (s); + { + uint32_t token; + RAND_bytes ((uint8_t *)&token, 4); + auto ts = i2p::util::GetSecondsSinceEpoch (); + for (auto it = m_Tokens.begin (); it != m_Tokens.end (); ) + { + if (ts > it->second + TOKEN_EXPIRATION_TIMEOUT) + it = m_Tokens.erase (it); + else + ++it; + } + m_Tokens[token] = ts; + ShowCommands (s, token); + } else if (page == HTTP_PAGE_TRANSIT_TUNNELS) ShowTransitTunnels (s); else if (page == HTTP_PAGE_LOCAL_DESTINATIONS) @@ -798,13 +812,19 @@ namespace http { void HTTPConnection::HandleCommand (const HTTPReq& req, HTTPRes& res, std::stringstream& s) { std::map params; - std::string cmd(""); URL url; url.parse(req.uri); url.parse_query(params); - cmd = params["cmd"]; + std::string token = params["token"]; + if (!token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) + { + ShowError(s, "Invalid token"); + return; + } + + std::string cmd = params["cmd"]; if (cmd == HTTP_COMMAND_RUN_PEER_TEST) i2p::transport::transports.PeerTest (); else if (cmd == HTTP_COMMAND_RELOAD_CONFIG) diff --git a/HTTPServer.h b/HTTPServer.h index 4a32702d..ec56e08a 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -1,10 +1,20 @@ #ifndef HTTP_SERVER_H__ #define HTTP_SERVER_H__ -namespace i2p { -namespace http { - extern const char *itoopieFavicon; - const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; +#include +#include +#include +#include +#include +#include +#include "HTTP.h" + +namespace i2p +{ +namespace http +{ + const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; + const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds class HTTPConnection: public std::enable_shared_from_this { @@ -35,6 +45,8 @@ namespace http { bool needAuth; std::string user; std::string pass; + + static std::map m_Tokens; // token->timestamp in seconds }; class HTTPServer From 0edc149ecca68670e4b378d71a0a1d52815f3ce8 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 Dec 2016 13:36:52 -0500 Subject: [PATCH 38/53] fixed typo --- HTTPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 368c5e21..84818e8e 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -818,7 +818,7 @@ namespace http { url.parse_query(params); std::string token = params["token"]; - if (!token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) + if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) { ShowError(s, "Invalid token"); return; From 38d85a49e721c65fb6ceb9acb34a1c8816261e60 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 Dec 2016 14:42:26 -0500 Subject: [PATCH 39/53] use AVX instructions for XOR in AES-CBC if applicable --- Crypto.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Crypto.h b/Crypto.h index a04a93da..9e35f073 100644 --- a/Crypto.h +++ b/Crypto.h @@ -76,7 +76,18 @@ namespace crypto void operator^=(const ChipherBlock& other) // XOR { -#if defined(__x86_64__) || defined(__SSE__) // for Intel x84 or with SSE +#if defined(__AVX__) // AVX + __asm__ + ( + "vmovups (%[buf]), %%xmm0 \n" + "vmovups (%[other]), %%xmm1 \n" + "vxorps %%xmm0, %%xmm1, %%xmm0 \n" + "vmovups %%xmm0, (%[buf]) \n" + : + : [buf]"r"(buf), [other]"r"(other.buf) + : "%xmm0", "%xmm1", "memory" + ); +#elif defined(__SSE__) // SSE __asm__ ( "movups (%[buf]), %%xmm0 \n" From 63d6b2334404c262af00ce10fba8e360f7ef67f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 16 Dec 2016 21:23:04 -0500 Subject: [PATCH 40/53] use correct encryption key for ElGamal --- Garlic.cpp | 18 ++++++++---------- Garlic.h | 4 +--- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index 192d47a0..81941cfc 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -18,20 +18,17 @@ namespace garlic { GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet): - m_Owner (owner), m_IsDestination (destination->IsDestination ()), m_NumTags (numTags), + m_Owner (owner), m_Destination (destination), m_NumTags (numTags), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), - m_LeaseSetUpdateMsgID (0), - m_ElGamalEncryption (new i2p::crypto::ElGamalEncryption (destination->GetEncryptionPublicKey ())) + m_LeaseSetUpdateMsgID (0) { // create new session tags and session key RAND_bytes (m_SessionKey, 32); m_Encryption.SetKey (m_SessionKey); - if (m_IsDestination) - m_DestinationIdent = destination->GetIdentHash (); } GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): - m_Owner (nullptr), m_IsDestination (false), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) + m_Owner (nullptr), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) { memcpy (m_SessionKey, sessionKey, 32); m_Encryption.SetKey (m_SessionKey); @@ -179,7 +176,7 @@ namespace garlic if (!tagFound) // new session { LogPrint (eLogInfo, "Garlic: No tags available, will use ElGamal"); - if (!m_ElGamalEncryption) + if (!m_Destination) { LogPrint (eLogError, "Garlic: Can't use ElGamal for unknown destination"); return nullptr; @@ -190,7 +187,8 @@ namespace garlic RAND_bytes (elGamal.preIV, 32); // Pre-IV uint8_t iv[32]; // IV is first 16 bytes SHA256(elGamal.preIV, 32, iv); - m_ElGamalEncryption->Encrypt ((uint8_t *)&elGamal, buf, true); + i2p::crypto::ElGamalEncryption elGamalEncryption (m_Destination->GetEncryptionPublicKey ()); + elGamalEncryption.Encrypt ((uint8_t *)&elGamal, buf, true); m_Encryption.SetIV (iv); buf += 514; len += 514; @@ -299,7 +297,7 @@ namespace garlic } if (msg) // clove message ifself if presented { - size += CreateGarlicClove (payload + size, msg, m_IsDestination); + size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false); (*numCloves)++; } memset (payload + size, 0, 3); // certificate of message @@ -321,7 +319,7 @@ namespace garlic { buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination size++; - memcpy (buf + size, m_DestinationIdent, 32); + memcpy (buf + size, m_Destination->GetIdentHash (), 32); size += 32; } else diff --git a/Garlic.h b/Garlic.h index 523399cc..b5dcd1eb 100644 --- a/Garlic.h +++ b/Garlic.h @@ -127,8 +127,7 @@ namespace garlic private: GarlicDestination * m_Owner; - bool m_IsDestination; // destination or RouterInfo ? - i2p::data::IdentHash m_DestinationIdent; + std::shared_ptr m_Destination; i2p::crypto::AESKey m_SessionKey; std::list m_SessionTags; @@ -140,7 +139,6 @@ namespace garlic uint64_t m_LeaseSetSubmissionTime; // in milliseconds i2p::crypto::CBCEncryption m_Encryption; - std::unique_ptr m_ElGamalEncryption; std::shared_ptr m_SharedRoutingPath; From 8071df0e68046fcc1a46034e79eb2142f0e9e3cb Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 17 Dec 2016 06:35:38 -0500 Subject: [PATCH 41/53] don't crash on os x when no lease set found for udp tunnel --- Datagram.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Datagram.cpp b/Datagram.cpp index ca13863e..b19047f0 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -293,6 +293,7 @@ namespace datagram void DatagramSession::HandleLeaseSetUpdated(std::shared_ptr ls) { + if(!ls) return; // only update lease set if found and newer than previous lease set uint64_t oldExpire = 0; if(m_RemoteLeaseSet) oldExpire = m_RemoteLeaseSet->GetExpirationTime(); From 99b5f1b7b89e75b5748b86020e633b9e0c21a67b Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 17 Dec 2016 06:37:34 -0500 Subject: [PATCH 42/53] remove pedantic log entry --- Datagram.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index b19047f0..9e314b8d 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -243,9 +243,6 @@ namespace datagram if (sz) { auto idx = rand() % sz; m_CurrentRemoteLease = ls[idx]; - } else { - // no more leases, bail - LogPrint(eLogWarning, "DatagramSession: no more valid remote leases to ", m_RemoteIdent.ToBase32()); } } else { // no remote lease set? From 8b8007695c272b233337a25e1a12b972f3246033 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 17 Dec 2016 22:49:51 +0300 Subject: [PATCH 43/53] don't close streams after 1 hour --- I2PTunnel.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 2b7ccc0e..ff3e06a3 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -177,11 +177,13 @@ namespace client { if (bytes_transferred > 0) Write (m_StreamBuffer, bytes_transferred); // postpone termination - else + else if (ecode == boost::asio::error::timed_out && m_Stream->IsOpen ()) + StreamReceive (); + else Terminate (); } else - Terminate (); + Terminate (); } else Write (m_StreamBuffer, bytes_transferred); From f69884d57341c7c8c76e9bc619b93bd4ecfa1cf4 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sun, 18 Dec 2016 16:20:53 +0300 Subject: [PATCH 44/53] AVX disabled for debuild by patch --- Makefile | 9 +++++---- Makefile.linux | 2 ++ debian/patches/01-tune-build-opts.patch | 16 +++++++++------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 61220efd..acdc56d4 100644 --- a/Makefile +++ b/Makefile @@ -9,10 +9,11 @@ DEPS := obj/make.dep include filelist.mk -USE_AESNI := yes -USE_STATIC := no -USE_MESHNET := no -USE_UPNP := no +USE_AESNI := yes +USE_AVX := yes +USE_STATIC := no +USE_MESHNET := no +USE_UPNP := no ifeq ($(WEBSOCKETS),1) NEEDED_CXXFLAGS += -DWITH_EVENTS diff --git a/Makefile.linux b/Makefile.linux index 6d4762b1..02f099d2 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -65,7 +65,9 @@ endif endif endif +ifeq ($(USE_AVX),yes) #check if AVX supported by CPU ifneq ($(shell $(GREP) -c avx /proc/cpuinfo),0) CPU_FLAGS += -mavx endif +endif diff --git a/debian/patches/01-tune-build-opts.patch b/debian/patches/01-tune-build-opts.patch index fba12f4e..4420d387 100644 --- a/debian/patches/01-tune-build-opts.patch +++ b/debian/patches/01-tune-build-opts.patch @@ -1,16 +1,18 @@ diff --git a/Makefile b/Makefile -index b6fc795..abc3ace 100644 +index bdadfe0..2f71eec 100644 + --- a/Makefile +++ b/Makefile @@ -9,10 +9,10 @@ DEPS := obj/make.dep include filelist.mk --USE_AESNI := yes -+USE_AESNI := no - USE_STATIC := no - USE_MESHNET := no - USE_UPNP := no +-USE_AESNI := yes ++USE_AESNI := no +-USE_AVX := yes ++USE_AVX := no + USE_STATIC := no + USE_MESHNET := no + USE_UPNP := no ifeq ($(WEBSOCKETS),1) - NEEDED_CXXFLAGS += -DWITH_EVENTS From 05c914156a572d2983b60863400267ccdfa6b100 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 18 Dec 2016 09:40:52 -0500 Subject: [PATCH 45/53] fixed session termination crash --- SAM.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/SAM.cpp b/SAM.cpp index 84f8dbf6..1fc1227a 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -622,10 +622,16 @@ namespace client boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred), std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); // postpone termination else - Terminate (); + { + auto s = shared_from_this (); + m_Owner.GetService ().post ([s] { s->Terminate (); }); + } } else - Terminate (); + { + auto s = shared_from_this (); + m_Owner.GetService ().post ([s] { s->Terminate (); }); + } } else { From 259a63e61237b0222b4096a73e3bda8a5a4dfa8b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 18 Dec 2016 10:11:40 -0500 Subject: [PATCH 46/53] fixed session termination crash --- SAM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SAM.cpp b/SAM.cpp index 1fc1227a..cb843685 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -577,8 +577,8 @@ namespace client { if (!ecode) s->Receive (); - else - s->Terminate (); + else + s->m_Owner.GetService ().post ([s] { s->Terminate (); }); }); } } From 8f8b928cc49f002b3c05a71d6b1d216e3e09eb76 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 18 Dec 2016 11:49:50 -0500 Subject: [PATCH 47/53] enable multiple acceptors in sam (initial) --- SAM.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++------------- SAM.h | 16 ++++++++--- 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/SAM.cpp b/SAM.cpp index 1fc1227a..ebb90aeb 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -54,11 +54,7 @@ namespace client case eSAMSocketTypeAcceptor: { if (m_Session) - { m_Session->DelSocket (shared_from_this ()); - if (m_Session->localDestination) - m_Session->localDestination->StopAcceptingStreams (); - } break; } default: @@ -289,6 +285,11 @@ namespace client dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); } + else + { + // start accepting streams because we're not a datagram session + m_Session->localDestination->AcceptStreams (std::bind (&SAMSession::AcceptI2P, m_Session, std::placeholders::_1)); + } if (m_Session->localDestination->IsReady ()) SendSessionCreateReplyOk (); @@ -401,20 +402,24 @@ namespace client m_Session = m_Owner.FindSession (id); if (m_Session) { - if (!m_Session->localDestination->IsAcceptingStreams ()) - { - m_SocketType = eSAMSocketTypeAcceptor; - m_Session->AddSocket (shared_from_this ()); - m_Session->localDestination->AcceptStreams (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); - } - else - SendMessageReply (SAM_STREAM_STATUS_I2P_ERROR, strlen(SAM_STREAM_STATUS_I2P_ERROR), true); + m_SocketType = eSAMSocketTypeAcceptor; + m_Session->AddSocket (shared_from_this ()); } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); } + void SAMSocket::Accept(std::shared_ptr stream) + { + if(stream) { + m_SocketType = eSAMSocketTypeStream; + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + HandleI2PAccept(stream); + } else { + SendMessageReply (SAM_STREAM_STATUS_I2P_ERROR, strlen(SAM_STREAM_STATUS_I2P_ERROR), true); + Terminate(); + } + } size_t SAMSocket::ProcessDatagramSend (char * buf, size_t len, const char * data) { LogPrint (eLogDebug, "SAM: datagram send: ", buf, " ", len); @@ -659,10 +664,6 @@ namespace client LogPrint (eLogDebug, "SAM: incoming I2P connection for session ", m_ID); m_Stream = stream; context.GetAddressBook ().InsertAddress (stream->GetRemoteIdentity ()); - auto session = m_Owner.FindSession (m_ID); - if (session) - session->localDestination->StopAcceptingStreams (); - m_SocketType = eSAMSocketTypeStream; if (!m_IsSilent) { // get remote peer address @@ -704,8 +705,10 @@ namespace client } SAMSession::SAMSession (std::shared_ptr dest): - localDestination (dest) + localDestination (dest), + m_BacklogPumper(dest->GetService()) { + PumpBacklog(); } SAMSession::~SAMSession () @@ -714,6 +717,42 @@ namespace client i2p::client::context.DeleteLocalDestination (localDestination); } + void SAMSession::AcceptI2P(std::shared_ptr stream) + { + if(!stream) return; // fail + std::unique_lock lock(m_SocketsMutex); + if(m_Backlog.size() > SAM_MAX_ACCEPT_BACKLOG) { + stream->Close(); + return; + } + m_Backlog.push_back(stream); + } + + void SAMSession::PumpBacklog() + { + // pump backlog every 100ms + boost::posix_time::milliseconds dlt(100); + m_BacklogPumper.expires_from_now(dlt); + m_BacklogPumper.async_wait(std::bind(&SAMSession::HandlePumpBacklog, this, std::placeholders::_1)); + } + + void SAMSession::HandlePumpBacklog(const boost::system::error_code & ec) + { + if(ec) return; + + std::unique_lock lock(m_SocketsMutex); + for(auto & stream : m_Backlog) { + for (auto & sock : m_Sockets) { + auto t = sock->GetSocketType(); + if(t == eSAMSocketTypeAcceptor) { + sock->Accept(stream); + break; + } + } + } + PumpBacklog(); + } + void SAMSession::CloseStreams () { { @@ -721,9 +760,13 @@ namespace client for (auto& sock : m_Sockets) { sock->CloseStream(); } + for(auto & stream : m_Backlog) { + stream->Close(); + } } // XXX: should this be done inside locked parts? m_Sockets.clear(); + m_Backlog.clear(); } SAMBridge::SAMBridge (const std::string& address, int port): @@ -834,8 +877,9 @@ namespace client auto session = std::make_shared(localDestination); std::unique_lock l(m_SessionsMutex); auto ret = m_Sessions.insert (std::make_pair(id, session)); - if (!ret.second) + if (!ret.second) { LogPrint (eLogWarning, "SAM: Session ", id, " already exists"); + } return ret.first->second; } return nullptr; diff --git a/SAM.h b/SAM.h index db08c5a0..26c6ea29 100644 --- a/SAM.h +++ b/SAM.h @@ -20,7 +20,8 @@ namespace client { const size_t SAM_SOCKET_BUFFER_SIZE = 8192; const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds - const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds + const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds + const int SAM_MAX_ACCEPT_BACKLOG = 50; const char SAM_HANDSHAKE[] = "HELLO VERSION"; const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n"; const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n"; @@ -84,6 +85,8 @@ namespace client void SetSocketType (SAMSocketType socketType) { m_SocketType = socketType; }; SAMSocketType GetSocketType () const { return m_SocketType; }; + void Accept(std::shared_ptr stream); + private: void Terminate (); @@ -134,6 +137,8 @@ namespace client struct SAMSession { std::shared_ptr localDestination; + boost::asio::deadline_timer m_BacklogPumper; + std::list > m_Backlog; std::list > m_Sockets; std::mutex m_SocketsMutex; @@ -158,10 +163,15 @@ namespace client } return l; } - - SAMSession (std::shared_ptr dest); + + SAMSession (std::shared_ptr dest); ~SAMSession (); + void AcceptI2P(std::shared_ptr stream); + + void PumpBacklog(); + void HandlePumpBacklog(const boost::system::error_code & ec); + void CloseStreams (); }; From d5f27ecb0ea61a85da5dcb9178ea589bdd65c174 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 18 Dec 2016 12:28:32 -0500 Subject: [PATCH 48/53] fix termination crash --- SAM.cpp | 56 ++++++++++++++++++++++++++++++++++---------------------- SAM.h | 2 ++ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/SAM.cpp b/SAM.cpp index ebb90aeb..5b21af51 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -404,6 +404,7 @@ namespace client { m_SocketType = eSAMSocketTypeAcceptor; m_Session->AddSocket (shared_from_this ()); + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } else SendMessageReply (SAM_STREAM_STATUS_INVALID_ID, strlen(SAM_STREAM_STATUS_INVALID_ID), true); @@ -413,7 +414,6 @@ namespace client { if(stream) { m_SocketType = eSAMSocketTypeStream; - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); HandleI2PAccept(stream); } else { SendMessageReply (SAM_STREAM_STATUS_I2P_ERROR, strlen(SAM_STREAM_STATUS_I2P_ERROR), true); @@ -713,7 +713,6 @@ namespace client SAMSession::~SAMSession () { - CloseStreams(); i2p::client::context.DeleteLocalDestination (localDestination); } @@ -736,17 +735,30 @@ namespace client m_BacklogPumper.async_wait(std::bind(&SAMSession::HandlePumpBacklog, this, std::placeholders::_1)); } + std::shared_ptr SAMSession::FindAcceptor() + { + for (auto & sock : m_Sockets) { + auto t = sock->GetSocketType(); + if(t == eSAMSocketTypeAcceptor) { + return sock; + } + } + return nullptr; + } + void SAMSession::HandlePumpBacklog(const boost::system::error_code & ec) { if(ec) return; - - std::unique_lock lock(m_SocketsMutex); - for(auto & stream : m_Backlog) { - for (auto & sock : m_Sockets) { - auto t = sock->GetSocketType(); - if(t == eSAMSocketTypeAcceptor) { - sock->Accept(stream); - break; + { + std::unique_lock lock(m_SocketsMutex); + auto itr = m_Backlog.begin(); + while(itr != m_Backlog.end()) { + auto sock = FindAcceptor(); + if (sock) { + sock->Accept(*itr); + itr = m_Backlog.erase(itr); + } else { + ++itr; } } } @@ -755,18 +767,18 @@ namespace client void SAMSession::CloseStreams () { - { - std::lock_guard lock(m_SocketsMutex); - for (auto& sock : m_Sockets) { - sock->CloseStream(); - } - for(auto & stream : m_Backlog) { - stream->Close(); - } - } - // XXX: should this be done inside locked parts? - m_Sockets.clear(); - m_Backlog.clear(); + localDestination->GetService().post([&] () { + std::lock_guard lock(m_SocketsMutex); + for (auto& sock : m_Sockets) { + sock->CloseStream(); + } + for(auto & stream : m_Backlog) { + stream->Close(); + } + // XXX: should this be done inside locked parts? + m_Sockets.clear(); + m_Backlog.clear(); + }); } SAMBridge::SAMBridge (const std::string& address, int port): diff --git a/SAM.h b/SAM.h index 26c6ea29..810a1bb0 100644 --- a/SAM.h +++ b/SAM.h @@ -169,6 +169,8 @@ namespace client void AcceptI2P(std::shared_ptr stream); + std::shared_ptr FindAcceptor(); + void PumpBacklog(); void HandlePumpBacklog(const boost::system::error_code & ec); From 673b7a95b7ca6cca2a138f36649191a1b34b4779 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 18 Dec 2016 12:56:34 -0500 Subject: [PATCH 49/53] fix sam crash on exit and datagram crash with no outbound tunnel --- Datagram.cpp | 2 +- SAM.cpp | 28 ++++++++++++---------------- SAM.h | 1 - 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/Datagram.cpp b/Datagram.cpp index 9e314b8d..852e54f6 100644 --- a/Datagram.cpp +++ b/Datagram.cpp @@ -310,7 +310,7 @@ namespace datagram std::vector send; auto routingPath = GetSharedRoutingPath(); // if we don't have a routing path we will drop all queued messages - if(routingPath) + if(routingPath && routingPath->outboundTunnel && routingPath->remoteLease) { for (const auto & msg : m_SendQueue) { diff --git a/SAM.cpp b/SAM.cpp index 5b21af51..5bf9a74b 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -710,11 +710,6 @@ namespace client { PumpBacklog(); } - - SAMSession::~SAMSession () - { - i2p::client::context.DeleteLocalDestination (localDestination); - } void SAMSession::AcceptI2P(std::shared_ptr stream) { @@ -767,18 +762,19 @@ namespace client void SAMSession::CloseStreams () { + m_BacklogPumper.cancel(); localDestination->GetService().post([&] () { - std::lock_guard lock(m_SocketsMutex); - for (auto& sock : m_Sockets) { - sock->CloseStream(); - } - for(auto & stream : m_Backlog) { - stream->Close(); - } - // XXX: should this be done inside locked parts? - m_Sockets.clear(); - m_Backlog.clear(); - }); + std::lock_guard lock(m_SocketsMutex); + for (auto& sock : m_Sockets) { + sock->CloseStream(); + } + for(auto & stream : m_Backlog) { + stream->Close(); + } + m_Sockets.clear(); + m_Backlog.clear(); + i2p::client::context.DeleteLocalDestination (localDestination); + }); } SAMBridge::SAMBridge (const std::string& address, int port): diff --git a/SAM.h b/SAM.h index 810a1bb0..7d7d6d3a 100644 --- a/SAM.h +++ b/SAM.h @@ -165,7 +165,6 @@ namespace client } SAMSession (std::shared_ptr dest); - ~SAMSession (); void AcceptI2P(std::shared_ptr stream); From eb9ea97e2158b3fc2ff51c9d4b40adc13839604b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 18 Dec 2016 13:01:28 -0500 Subject: [PATCH 50/53] don't crash --- SAM.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SAM.cpp b/SAM.cpp index 5bf9a74b..e109e3ab 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -417,7 +417,8 @@ namespace client HandleI2PAccept(stream); } else { SendMessageReply (SAM_STREAM_STATUS_I2P_ERROR, strlen(SAM_STREAM_STATUS_I2P_ERROR), true); - Terminate(); + auto s = shared_from_this (); + m_Owner.GetService ().post ([s] { s->Terminate (); }); } } size_t SAMSocket::ProcessDatagramSend (char * buf, size_t len, const char * data) From c9dc010c0b9c82ac1bef83a777c402b1d94f2603 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 18 Dec 2016 16:02:19 -0500 Subject: [PATCH 51/53] 2.11.0 --- Win32/installer.iss | 2 +- android/AndroidManifest.xml | 2 +- debian/changelog | 6 ++++++ qt/i2pd_qt/android/AndroidManifest.xml | 2 +- version.h | 4 ++-- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Win32/installer.iss b/Win32/installer.iss index 047263cc..2408efdb 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.10.2" +#define I2Pd_ver "2.11.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 9ffb1c13..40688197 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.11.0"> diff --git a/debian/changelog b/debian/changelog index 6e6a4c09..750a6f83 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.11.0-1) unstable; urgency=low + + * updated to version 2.11.0 + + -- orignal Sun, 18 Dec 2016 16:01:30 +0000 + i2pd (2.10.2-1) unstable; urgency=low * updated to version 2.10.2 diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index 37a736fd..b1f71567 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/version.h b/version.h index ed84efd1..501f7272 100644 --- a/version.h +++ b/version.h @@ -7,8 +7,8 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 10 -#define I2PD_VERSION_MICRO 2 +#define I2PD_VERSION_MINOR 11 +#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) #define VERSION I2PD_VERSION From 0233ab4debdc919d13b61e238d1d8068d9402ef1 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 19 Dec 2016 00:27:46 +0300 Subject: [PATCH 52/53] added info, modifyed timestamp --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 750a6f83..67af8310 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ i2pd (2.11.0-1) unstable; urgency=low - * updated to version 2.11.0 + * updated to version 2.11.0/0.9.28 - -- orignal Sun, 18 Dec 2016 16:01:30 +0000 + -- orignal Sun, 18 Dec 2016 21:01:30 +0000 i2pd (2.10.2-1) unstable; urgency=low From ffaabe86745a8166b7effef0be1019a94d71b028 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 18 Dec 2016 18:07:06 -0500 Subject: [PATCH 53/53] update ChangeLog --- ChangeLog | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 67f076fe..3b7bacd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,24 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.11.0] - 2016-12-18 +### Added +- Websockets support +- Reseed through a floodfill +- Tunnel configuration for HTTP and SOCKS proxy +- Zero-hops tunnels for destinations +- Multiple acceptors for SAM +### Changed +- Reseed servers list +- DHT uses AVX if applicable +- New logo +- LeaseSet lookups +### Fixed +- HTTP Proxy connection reset for Windows +- Crash upon SAM session termination +- Can't connect to a destination for a longer time after restart +- Mass packet loss for UDP tunnels + ## [2.10.2] - 2016-12-04 ### Fixed - Fixes UPnP discovery bug, producing excessive CPU usage