From 2e7ce385525cae267693d4b0c6efca989b8aaeee Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 Feb 2016 12:36:54 -0500 Subject: [PATCH 01/18] compatibility with gcc 4.6 --- Garlic.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Garlic.h b/Garlic.h index 67e9b027..73231d10 100644 --- a/Garlic.h +++ b/Garlic.h @@ -119,7 +119,8 @@ namespace garlic // for HTTP only size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; }; - using GarlicRoutingSessionPtr = std::shared_ptr; + //using GarlicRoutingSessionPtr = std::shared_ptr; + typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 class GarlicDestination: public i2p::data::LocalDestination { From 7ca1cfab1a3b1731dcda9c10c2e1aba941bdff96 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 Feb 2016 12:36:58 -0500 Subject: [PATCH 02/18] use shared_ptr for log's stream --- Log.cpp | 12 +++++------- Log.h | 13 +++++++------ api.cpp | 2 +- api.h | 2 +- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Log.cpp b/Log.cpp index 837abac8..d507b7dc 100644 --- a/Log.cpp +++ b/Log.cpp @@ -13,7 +13,8 @@ static const char * g_LogLevelStr[eNumLogLevels] = void LogMsg::Process() { - auto& output = (log && log->GetLogStream ()) ? *log->GetLogStream () : std::cerr; + auto stream = log ? log->GetLogStream () : nullptr; + auto& output = stream ? *stream : std::cout; if (log) output << log->GetTimestamp (); else @@ -45,14 +46,12 @@ void Log::Flush () void Log::SetLogFile (const std::string& fullFilePath) { - auto logFile = new std::ofstream (fullFilePath, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); + auto logFile = std::make_shared (fullFilePath, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); if (logFile->is_open ()) { SetLogStream (logFile); LogPrint(eLogInfo, "Log: will send messages to ", fullFilePath); } - else - delete logFile; } void Log::SetLogLevel (const std::string& level) @@ -65,11 +64,10 @@ void Log::SetLogLevel (const std::string& level) LogPrint(eLogError, "Log: Unknown loglevel: ", level); return; } - LogPrint(eLogInfo, "Log: min messages level set to ", level); + LogPrint(eLogInfo, "Log: min msg level set to ", level); } -void Log::SetLogStream (std::ostream * logStream) +void Log::SetLogStream (std::shared_ptr logStream) { - if (m_LogStream) delete m_LogStream; m_LogStream = logStream; } diff --git a/Log.h b/Log.h index f941e6a7..ec1dc015 100644 --- a/Log.h +++ b/Log.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "Queue.h" enum LogLevel @@ -34,13 +35,13 @@ class Log: public i2p::util::MsgQueue { public: - Log (): m_LogStream (nullptr) { SetOnEmpty (std::bind (&Log::Flush, this)); }; - ~Log () { delete m_LogStream; }; + Log () { SetOnEmpty (std::bind (&Log::Flush, this)); }; + ~Log () {}; void SetLogFile (const std::string& fullFilePath); void SetLogLevel (const std::string& level); - void SetLogStream (std::ostream * logStream); - std::ostream * GetLogStream () const { return m_LogStream; }; + void SetLogStream (std::shared_ptr logStream); + std::shared_ptr GetLogStream () const { return m_LogStream; }; const std::string& GetTimestamp (); LogLevel GetLogLevel () { return m_MinLevel; }; @@ -50,7 +51,7 @@ class Log: public i2p::util::MsgQueue private: - std::ostream * m_LogStream; + std::shared_ptr m_LogStream; enum LogLevel m_MinLevel; std::string m_Timestamp; #if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 6) && !defined(__clang__) // gcc 4.6 @@ -73,7 +74,7 @@ inline void StartLog (const std::string& fullFilePath) } } -inline void StartLog (std::ostream * s) +inline void StartLog (std::shared_ptr s) { if (!g_Log) { diff --git a/api.cpp b/api.cpp index cd527550..0f4e1799 100644 --- a/api.cpp +++ b/api.cpp @@ -31,7 +31,7 @@ namespace api i2p::crypto::TerminateCrypto (); } - void StartI2P (std::ostream * logStream) + void StartI2P (std::shared_ptr logStream) { if (logStream) StartLog (logStream); diff --git a/api.h b/api.h index 05552249..c010d82f 100644 --- a/api.h +++ b/api.h @@ -14,7 +14,7 @@ namespace api // initialization start and stop void InitI2P (int argc, char* argv[], const char * appName); void TerminateI2P (); - void StartI2P (std::ostream * logStream = nullptr); + void StartI2P (std::shared_ptr logStream = nullptr); // write system log to logStream, if not specified to .log in application's folder void StopI2P (); void RunPeerTest (); // should be called after UPnP From 98d5e0b56d321b72340212564a662aa2e6d6a06e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 4 Feb 2016 13:53:38 -0500 Subject: [PATCH 03/18] #355. reopen log file by SIGHUP --- DaemonLinux.cpp | 6 +++--- Log.cpp | 11 +++++++++++ Log.h | 8 ++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 89df5306..9382a878 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -17,9 +17,9 @@ void handle_signal(int sig) switch (sig) { case SIGHUP: - LogPrint(eLogInfo, "Daemon: Got SIGHUP, doing nothing"); - // TODO: - break; + LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening log..."); + ReopenLogFile (); + break; case SIGABRT: case SIGTERM: case SIGINT: diff --git a/Log.cpp b/Log.cpp index d507b7dc..6391bcae 100644 --- a/Log.cpp +++ b/Log.cpp @@ -46,6 +46,7 @@ void Log::Flush () void Log::SetLogFile (const std::string& fullFilePath) { + m_FullFilePath = fullFilePath; auto logFile = std::make_shared (fullFilePath, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); if (logFile->is_open ()) { @@ -54,6 +55,16 @@ void Log::SetLogFile (const std::string& fullFilePath) } } +void Log::ReopenLogFile () +{ + if (m_FullFilePath.length () > 0) + { + SetLogFile (m_FullFilePath); + LogPrint(eLogInfo, "Log: file ", m_FullFilePath, " reopen"); + } +} + + void Log::SetLogLevel (const std::string& level) { if (level == "error") { m_MinLevel = eLogError; } diff --git a/Log.h b/Log.h index ec1dc015..05bae7d9 100644 --- a/Log.h +++ b/Log.h @@ -39,6 +39,7 @@ class Log: public i2p::util::MsgQueue ~Log () {}; void SetLogFile (const std::string& fullFilePath); + void ReopenLogFile (); void SetLogLevel (const std::string& level); void SetLogStream (std::shared_ptr logStream); std::shared_ptr GetLogStream () const { return m_LogStream; }; @@ -51,6 +52,7 @@ class Log: public i2p::util::MsgQueue private: + std::string m_FullFilePath; // empty if stream std::shared_ptr m_LogStream; enum LogLevel m_MinLevel; std::string m_Timestamp; @@ -102,6 +104,12 @@ inline void SetLogLevel (const std::string& level) g_Log->SetLogLevel(level); } +inline void ReopenLogFile () +{ + if (g_Log) + g_Log->ReopenLogFile (); +} + template void LogPrint (std::stringstream& s, TValue arg) { From a292bc77ba3bd3d649c4faf3a03fa7902555627a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 07:55:28 -0500 Subject: [PATCH 04/18] fix issue #362 , add bounds check to su3 fileNameLength --- Reseed.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Reseed.cpp b/Reseed.cpp index 6d7c7901..80cc6a45 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -208,6 +208,11 @@ namespace data uint16_t fileNameLength, extraFieldLength; s.read ((char *)&fileNameLength, 2); fileNameLength = le16toh (fileNameLength); + if ( fileNameLength > 255 ) { + // too big + LogPrint(eLogError, "Reseed: SU3 fileNameLength too large: ", fileNameLength); + return numFiles; + } s.read ((char *)&extraFieldLength, 2); extraFieldLength = le16toh (extraFieldLength); char localFileName[255]; From d0ea59c5682e9d3bb0d78015998ed732d9ce7a35 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 08:44:09 -0500 Subject: [PATCH 05/18] add base64 buffer encoding bounds checking --- Base.h | 5 +++++ Identity.cpp | 25 +++++++++++++++++-------- SAM.cpp | 11 ++++++++--- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Base.h b/Base.h index 0c59ef03..d598542b 100644 --- a/Base.h +++ b/Base.h @@ -17,6 +17,11 @@ namespace data size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); + /** + Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes + */ + size_t Base64EncodingBufferSize(const size_t input_size); + template class Tag { diff --git a/Identity.cpp b/Identity.cpp index ac49b711..648c996d 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -228,26 +228,35 @@ namespace data } size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const - { + { + size_t fullLen = GetFullLen(); + if (fullLen > len) { + // buffer is too small and may overflow somewhere else + return 0; + } memcpy (buf, &m_StandardIdentity, DEFAULT_IDENTITY_SIZE); if (m_ExtendedLen > 0 && m_ExtendedBuffer) memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBuffer, m_ExtendedLen); - return GetFullLen (); + return fullLen; } size_t IdentityEx::FromBase64(const std::string& s) { - uint8_t buf[1024]; - auto len = Base64ToByteStream (s.c_str(), s.length(), buf, 1024); + const size_t slen = s.length(); + const size_t bufLen = Base64EncodingBufferSize(slen); + uint8_t buf[bufLen]; + auto len = Base64ToByteStream (s.c_str(), slen, buf, 1024); return FromBuffer (buf, len); } std::string IdentityEx::ToBase64 () const { - uint8_t buf[1024]; - char str[1536]; - size_t l = ToBuffer (buf, 1024); - size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, str, 1536); + const size_t bufLen = GetFullLen(); + const size_t strLen = Base64EncodingBufferSize(bufLen); + uint8_t buf[bufLen]; + char str[strLen]; + size_t l = ToBuffer (buf, bufLen); + size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, str, strLen); str[l1] = 0; return std::string (str); } diff --git a/SAM.cpp b/SAM.cpp index a20de13d..d331a035 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -631,10 +631,15 @@ namespace client m_SocketType = eSAMSocketTypeStream; if (!m_IsSilent) { - // send remote peer address - uint8_t ident[1024]; - size_t l = stream->GetRemoteIdentity ()->ToBuffer (ident, 1024); + // get remote peer address + auto ident_ptr = stream->GetRemoteIdentity(); + size_t ident_len = ident_ptr->GetFullLen(); + uint8_t* ident = new uint8_t[ident_len]; + + // send remote peer address as base64 + size_t l = ident_ptr->ToBuffer (ident, ident_len); size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE); + delete[] ident; m_StreamBuffer[l1] = '\n'; HandleI2PReceive (boost::system::error_code (), l1 +1); // we send identity like it has been received from stream } From 21090eaa39aefebc7214b39b2aa19d69dca54e39 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 08:46:08 -0500 Subject: [PATCH 06/18] forgot to commit Base.cpp changes --- Base.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Base.cpp b/Base.cpp index c9ba407a..f5144eda 100644 --- a/Base.cpp +++ b/Base.cpp @@ -327,7 +327,14 @@ namespace data LogPrint (eLogError, "Compression error ", err); return 0; } - } + } + + // from https://stackoverflow.com/questions/1533113/calculate-the-size-to-a-base-64-encoded-message + size_t Base64EncodingBufferSize(const size_t input_size) { + const size_t code_size = ((input_size * 4) / 3); + const size_t padding_size = (input_size % 3) ? (3 - (input_size % 3)) : 0; + return code_size + padding_size; + } } } From d4febb4e84fd1c45fa5f7dc95ddeaa566eb893ce Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 08:52:07 -0500 Subject: [PATCH 07/18] * bounds check on Identity::FromBuffer * properly indet last commits --- Identity.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Identity.cpp b/Identity.cpp index 648c996d..932d215f 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -22,6 +22,10 @@ namespace data size_t Identity::FromBuffer (const uint8_t * buf, size_t len) { + if ( len < DEFAULT_IDENTITY_SIZE ) { + // buffer too small, don't overflow + return 0; + } memcpy (publicKey, buf, DEFAULT_IDENTITY_SIZE); return DEFAULT_IDENTITY_SIZE; } @@ -242,17 +246,17 @@ namespace data size_t IdentityEx::FromBase64(const std::string& s) { - const size_t slen = s.length(); - const size_t bufLen = Base64EncodingBufferSize(slen); + const size_t slen = s.length(); + const size_t bufLen = Base64EncodingBufferSize(slen); uint8_t buf[bufLen]; - auto len = Base64ToByteStream (s.c_str(), slen, buf, 1024); + const size_t len = Base64ToByteStream (s.c_str(), slen, buf, bufLen); return FromBuffer (buf, len); } std::string IdentityEx::ToBase64 () const { - const size_t bufLen = GetFullLen(); - const size_t strLen = Base64EncodingBufferSize(bufLen); + const size_t bufLen = GetFullLen(); + const size_t strLen = Base64EncodingBufferSize(bufLen); uint8_t buf[bufLen]; char str[strLen]; size_t l = ToBuffer (buf, bufLen); From bf38bd5a1d25766c16cddd6d9ed17ba9b552ca4a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 10:40:23 -0500 Subject: [PATCH 08/18] * Fill padding with random in NTCP phase3 * Fill padding with random in NTCPSession::CreateMsgBuffer * Silence unused variable warnings in NTCPSession.cpp --- NTCPSession.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 2b745059..ed987bb9 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -134,6 +134,7 @@ namespace transport void NTCPSession::HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred) { + (void) bytes_transferred; if (ecode) { LogPrint (eLogInfo, "NTCP: couldn't send Phase 1 message: ", ecode.message ()); @@ -150,6 +151,7 @@ namespace transport void NTCPSession::HandlePhase1Received (const boost::system::error_code& ecode, std::size_t bytes_transferred) { + (void) bytes_transferred; if (ecode) { LogPrint (eLogInfo, "NTCP: phase 1 read error: ", ecode.message ()); @@ -205,6 +207,7 @@ namespace transport void NTCPSession::HandlePhase2Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB) { + (void) bytes_transferred; if (ecode) { LogPrint (eLogInfo, "NTCP: Couldn't send Phase 2 message: ", ecode.message ()); @@ -221,6 +224,7 @@ namespace transport void NTCPSession::HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred) { + (void) bytes_transferred; if (ecode) { LogPrint (eLogInfo, "NTCP: Phase 2 read error: ", ecode.message (), ". Wrong ident assumed"); @@ -277,7 +281,8 @@ namespace transport if (paddingSize > 0) { paddingSize = 16 - paddingSize; - // TODO: fill padding with random data + // fill padding with random data + RAND_bytes(buf, paddingSize); buf += paddingSize; len += paddingSize; } @@ -297,6 +302,7 @@ namespace transport void NTCPSession::HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA) { + (void) bytes_transferred; if (ecode) { LogPrint (eLogInfo, "NTCP: Couldn't send Phase 3 message: ", ecode.message ()); @@ -420,6 +426,7 @@ namespace transport void NTCPSession::HandlePhase4Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred) { + (void) bytes_transferred; if (ecode) { LogPrint (eLogWarning, "NTCP: Couldn't send Phase 4 message: ", ecode.message ()); @@ -645,8 +652,11 @@ namespace transport } int rem = (len + 6) & 0x0F; // %16 int padding = 0; - if (rem > 0) padding = 16 - rem; - // TODO: fill padding + if (rem > 0) { + padding = 16 - rem; + // fill with random padding + RAND_bytes(sendBuffer + len + 2, padding); + } htobe32buf (sendBuffer + len + 2 + padding, adler32 (adler32 (0, Z_NULL, 0), sendBuffer, len + 2+ padding)); int l = len + padding + 6; @@ -667,6 +677,7 @@ namespace transport void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector > msgs) { + (void) msgs; m_IsSending = false; if (ecode) { From f034aef2ae456fa13bf2b61926f017a33c819446 Mon Sep 17 00:00:00 2001 From: 0niichan Date: Fri, 5 Feb 2016 22:58:04 +0700 Subject: [PATCH 09/18] Added instructions for a 64-bit OS --- docs/build_notes_windows.md | 59 ++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/docs/build_notes_windows.md b/docs/build_notes_windows.md index c72b8989..81e0dfc2 100644 --- a/docs/build_notes_windows.md +++ b/docs/build_notes_windows.md @@ -20,11 +20,15 @@ development location for the sake of convenience. Adjust paths accordingly if it is not the case. Note that msys uses unix-alike paths like /c/dev/ for C:\dev\. + + msys2 ----- +### x86 (32-bit architecture) + Get install file msys2-i686-20150916.exe from https://msys2.github.io. -open MSys2Shell (from Start menu). +open MSYS2 Shell (from Start menu). Install all prerequisites and download i2pd source: ```bash @@ -37,14 +41,23 @@ export PATH=/mingw32/bin:/usr/bin # we need compiler on PATH which is usually he make ``` -If your processor has -[AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set), -you use `make USE_AESNI=1`. No check is done however, it -will compile, but it might crash with `Illegal instruction` if not supported. -You should be able to run ./i2pd . If you need to start from the new -shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as -it adds`/minw32/bin` to the PATH. +### x64 (64-bit architecture) + +Get install file msys2-x86_64-20150916.exe from https://msys2.github.io. +open MSYS2 Shell (from Start menu). +Install all prerequisites and download i2pd source: + +```bash +pacman -S mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-gcc git make +mkdir -p /c/dev/i2pd +cd /c/dev/i2pd +git clone https://github.com/PurpleI2P/i2pd.git +cd i2pd +export PATH=/mingw64/bin:/usr/bin # we need compiler on PATH which is usually heavily cluttered on Windows +make +``` + ### Caveats @@ -63,6 +76,19 @@ home page, otherwise you might end up with DLLs incompatibility problems. +### AES-NI + +If your processor has +[AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set), +you use `make USE_AESNI=1`. No check is done however, it +will compile, but it might crash with `Illegal instruction` if not supported. + +You should be able to run ./i2pd . If you need to start from the new +shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as +it adds`/minw32/bin` to the PATH. + + + Using Visual Studio ------------------- @@ -77,7 +103,7 @@ Requirements for building: * Strawberry Perl or ActiveState Perl, do NOT try msys2 perl, it won't work -## Building Boost +### Building Boost Open a Command Prompt (there is no need to start Visual Studio command prompt to build Boost) and run the following: @@ -98,8 +124,8 @@ only and static linking, and/or you are out of space/time, you might consider `--build-type=minimal`. Take a look at [appveyor.yml](../appveyor.yml) for details on how test builds are done. -Building OpenSSL ------------------ + +### Building OpenSSL Download OpenSSL, e.g. with git @@ -123,8 +149,8 @@ maintaining multiple versions, e.g. 64 bit and/or static/shared. Consult `C:\Program Files (x86)\CMake\share\cmake-3.3\Modules\FindOpenSSL.cmake` for details. -Get miniupnpc -------------- + +### Get miniupnpc If you are behind a UPnP enabled router and don't feel like manually configuring port forwarding, you should consider using @@ -139,8 +165,7 @@ Note that you might need to build DLL yourself for 64-bit systems using msys2 as 64-bit DLLs are not provided by the project. -Creating Visual Studio project ------------------------------- +### Creating Visual Studio project Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./out, and configure options. @@ -155,8 +180,8 @@ cmake ..\build -G "Visual Studio 12 2013" -DWITH_UPNP=ON -DWITH_PCH=ON -DCMAKE_I WITH_UPNP will stay off, if necessary files are not found. -Building i2pd -------------- + +### Building i2pd You can open generated solution/project with Visual Studio and build from there, alternatively you can use `cmake --build . --config Release --target install` or From babcbcbceacb4e284402d27be43ff8f872f218af Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 12:32:50 -0500 Subject: [PATCH 10/18] use const size_t instead of size_t --- Identity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Identity.cpp b/Identity.cpp index 932d215f..e32c3a59 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -233,7 +233,7 @@ namespace data size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const { - size_t fullLen = GetFullLen(); + const size_t fullLen = GetFullLen(); if (fullLen > len) { // buffer is too small and may overflow somewhere else return 0; From 9f1b84d6f21f37c99f68740a95df989243ac6d56 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 12:39:17 -0500 Subject: [PATCH 11/18] use const size_t instead of size_t --- SAM.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SAM.cpp b/SAM.cpp index d331a035..7b493eb3 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -633,12 +633,12 @@ namespace client { // get remote peer address auto ident_ptr = stream->GetRemoteIdentity(); - size_t ident_len = ident_ptr->GetFullLen(); + const size_t ident_len = ident_ptr->GetFullLen(); uint8_t* ident = new uint8_t[ident_len]; // send remote peer address as base64 - size_t l = ident_ptr->ToBuffer (ident, ident_len); - size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE); + const size_t l = ident_ptr->ToBuffer (ident, ident_len); + const size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE); delete[] ident; m_StreamBuffer[l1] = '\n'; HandleI2PReceive (boost::system::error_code (), l1 +1); // we send identity like it has been received from stream From 4c72d43a8af73705005b57f5671c4ee1721f50f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 Feb 2016 15:58:14 -0500 Subject: [PATCH 12/18] use more efficient XOR over ChipherBlocks for win32 --- Crypto.h | 2 +- Makefile.mingw | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Crypto.h b/Crypto.h index dfe0da0e..e633f8bf 100644 --- a/Crypto.h +++ b/Crypto.h @@ -70,7 +70,7 @@ namespace crypto void operator^=(const ChipherBlock& other) // XOR { -#if defined(__x86_64__) // for Intel x64 +#if defined(__x86_64__) || defined(__SSE__) // for Intel x84 or with SSE __asm__ ( "movups (%[buf]), %%xmm0 \n" diff --git a/Makefile.mingw b/Makefile.mingw index 591a1256..24f33a11 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -8,4 +8,6 @@ LDLIBS = -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_date_ti ifeq ($(USE_AESNI),1) CPU_FLAGS = -maes -DAESNI +else + CPU_FLAGS = -msse endif From 3b268fe3ccd30469ad9c94fc1245fe94f1e06bf1 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 16:17:53 -0500 Subject: [PATCH 13/18] allow resolving of .b32.i2p addresses in SAM name lookup --- SAM.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SAM.cpp b/SAM.cpp index 7b493eb3..3c3364b4 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -468,6 +468,8 @@ namespace client i2p::data::IdentHash ident; if (name == "ME") SendNamingLookupReply (m_Session->localDestination->GetIdentity ()); + else if (name.rfind(".b32.i2p") == 52) + ident.FromBase32(name.substr(0, 52)); else if ((identity = context.GetAddressBook ().GetAddress (name)) != nullptr) SendNamingLookupReply (identity); else if (m_Session && m_Session->localDestination && From a8e12e624d89457e375f69c314f5ec524cd1aca5 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 5 Feb 2016 21:38:03 -0500 Subject: [PATCH 14/18] fixed hanging connection --- SAM.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/SAM.cpp b/SAM.cpp index 3c3364b4..7b493eb3 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -468,8 +468,6 @@ namespace client i2p::data::IdentHash ident; if (name == "ME") SendNamingLookupReply (m_Session->localDestination->GetIdentity ()); - else if (name.rfind(".b32.i2p") == 52) - ident.FromBase32(name.substr(0, 52)); else if ((identity = context.GetAddressBook ().GetAddress (name)) != nullptr) SendNamingLookupReply (identity); else if (m_Session && m_Session->localDestination && From 4c6ef32d72cec5673d2cbf7b67ea25fd5528717b Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 6 Feb 2016 08:52:02 -0500 Subject: [PATCH 15/18] fixed #369 --- NetDb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NetDb.cpp b/NetDb.cpp index 0cbdce30..70b33f7f 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -316,7 +316,8 @@ namespace data const std::string& fullPath = it1->path(); #endif auto r = std::make_shared(fullPath); - if (!r->IsUnreachable () && (!r->UsesIntroducer () || ts < r->GetTimestamp () + 3600*1000LL)) // 1 hour + if (r->GetRouterIdentity () && !r->IsUnreachable () && + (!r->UsesIntroducer () || ts < r->GetTimestamp () + 3600*1000LL)) // 1 hour { r->DeleteBuffer (); r->ClearProperties (); // properties are not used for regular routers From 76096747b68011b2b5c82088a5be7230a8e3eb0b Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 7 Feb 2016 17:45:11 -0500 Subject: [PATCH 16/18] cleanup incoming and outgoing tags together --- Destination.cpp | 2 +- Garlic.cpp | 41 ++++++++++++++++++----------------------- Garlic.h | 5 ++--- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 233946ad..f2dac631 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -664,7 +664,7 @@ namespace client { if (ecode != boost::asio::error::operation_aborted) { - CleanupRoutingSessions (); + CleanupExpiredTags (); CleanupRemoteLeaseSets (); m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT)); m_CleanupTimer.async_wait (std::bind (&ClientDestination::HandleCleanupTimer, diff --git a/Garlic.cpp b/Garlic.cpp index d62b6fe3..88e255ff 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -409,28 +409,6 @@ namespace garlic else LogPrint (eLogError, "Garlic: Failed to decrypt message"); } - - // cleanup expired tags - uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts > m_LastTagsCleanupTime + INCOMING_TAGS_EXPIRATION_TIMEOUT) - { - if (m_LastTagsCleanupTime) - { - int numExpiredTags = 0; - for (auto it = m_Tags.begin (); it != m_Tags.end ();) - { - if (ts > it->first.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT) - { - numExpiredTags++; - it = m_Tags.erase (it); - } - else - it++; - } - LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ()); - } - m_LastTagsCleanupTime = ts; - } } void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, @@ -570,8 +548,25 @@ namespace garlic return session; } - void GarlicDestination::CleanupRoutingSessions () + void GarlicDestination::CleanupExpiredTags () { + // incoming + uint32_t ts = i2p::util::GetSecondsSinceEpoch (); + int numExpiredTags = 0; + for (auto it = m_Tags.begin (); it != m_Tags.end ();) + { + if (ts > it->first.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT) + { + numExpiredTags++; + it = m_Tags.erase (it); + } + else + it++; + } + if (numExpiredTags > 0) + LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ()); + + // outgoing std::unique_lock l(m_SessionsMutex); for (auto it = m_Sessions.begin (); it != m_Sessions.end ();) { diff --git a/Garlic.h b/Garlic.h index 73231d10..b42f92cf 100644 --- a/Garlic.h +++ b/Garlic.h @@ -126,12 +126,12 @@ namespace garlic { public: - GarlicDestination (): m_NumTags (32), m_LastTagsCleanupTime (0) {}; // 32 tags by default + GarlicDestination (): m_NumTags (32) {}; // 32 tags by default ~GarlicDestination (); void SetNumTags (int numTags) { m_NumTags = numTags; }; std::shared_ptr GetRoutingSession (std::shared_ptr destination, bool attachLeaseSet); - void CleanupRoutingSessions (); + void CleanupExpiredTags (); void RemoveDeliveryStatusSession (uint32_t msgID); std::shared_ptr WrapMessage (std::shared_ptr destination, std::shared_ptr msg, bool attachLeaseSet = false); @@ -167,7 +167,6 @@ namespace garlic std::map m_Sessions; // incoming std::map> m_Tags; - uint32_t m_LastTagsCleanupTime; // DeliveryStatus std::map m_DeliveryStatusSessions; // msgID -> session From f3b277aeef67c3fb6c31915968acaf6284334aad Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 7 Feb 2016 19:45:06 -0500 Subject: [PATCH 17/18] doesn't store leases in netdb --- Destination.cpp | 8 +++++--- Destination.h | 2 +- HTTPServer.cpp | 4 ++-- LeaseSet.cpp | 49 ++++++++++++++++++++++++++++++------------------- LeaseSet.h | 9 ++++++--- NetDb.cpp | 5 +++-- 6 files changed, 47 insertions(+), 30 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index f2dac631..c07718cb 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -187,16 +187,17 @@ namespace client auto it = m_RemoteLeaseSets.find (ident); if (it != m_RemoteLeaseSets.end ()) { - if (it->second->HasNonExpiredLeases ()) + if (!it->second->IsExpired ()) return it->second; else - LogPrint (eLogWarning, "Destination: All leases of remote LeaseSet expired"); + LogPrint (eLogWarning, "Destination: remote LeaseSet expired"); } else { auto ls = i2p::data::netdb.FindLeaseSet (ident); if (ls) { + ls->PopulateLeases (); // since we don't store them in netdb m_RemoteLeaseSets[ident] = ls; return ls; } @@ -674,9 +675,10 @@ namespace client void ClientDestination::CleanupRemoteLeaseSets () { + auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();) { - if (!it->second->HasNonExpiredLeases ()) // all leases expired + if (ts > it->second->GetExpirationTime ()) // leaseset expired { LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_RemoteLeaseSets.erase (it); diff --git a/Destination.h b/Destination.h index ece125e3..c45a20ec 100644 --- a/Destination.h +++ b/Destination.h @@ -72,7 +72,7 @@ namespace client bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service& GetService () { return m_Service; }; std::shared_ptr GetTunnelPool () { return m_Pool; }; - bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases () && m_Pool->GetOutboundTunnels ().size () > 0; }; + bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; }; std::shared_ptr FindLeaseSet (const i2p::data::IdentHash& ident); bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); void CancelDestinationRequest (const i2p::data::IdentHash& dest); diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 2fef6e66..f04b0b1c 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -793,7 +793,7 @@ namespace util } auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); - if (leaseSet && leaseSet->HasNonExpiredLeases ()) + if (leaseSet && !leaseSet->IsExpired ()) SendToDestination (leaseSet, port, buf, len); else { @@ -812,7 +812,7 @@ namespace util if (ecode != boost::asio::error::operation_aborted) { auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); - if (leaseSet && leaseSet->HasNonExpiredLeases ()) + if (leaseSet && !leaseSet->IsExpired ()) SendToDestination (leaseSet, port, buf, len); else // still no LeaseSet diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 716ee6d2..adcbc388 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -12,8 +12,8 @@ namespace i2p namespace data { - LeaseSet::LeaseSet (const uint8_t * buf, size_t len): - m_IsValid (true) + LeaseSet::LeaseSet (const uint8_t * buf, size_t len, bool storeLeases): + m_IsValid (true), m_StoreLeases (storeLeases), m_ExpirationTime (0) { m_Buffer = new uint8_t[len]; memcpy (m_Buffer, buf, len); @@ -22,7 +22,7 @@ namespace data } LeaseSet::LeaseSet (std::shared_ptr pool): - m_IsValid (true) + m_IsValid (true), m_StoreLeases (true), m_ExpirationTime (0) { if (!pool) return; // header @@ -55,6 +55,7 @@ namespace data uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration ts *= 1000; // in milliseconds ts += rand () % 6; // + random milliseconds 0-5 + if (ts > m_ExpirationTime) m_ExpirationTime = ts; htobe64buf (m_Buffer + m_BufferLen, ts); m_BufferLen += 8; // end date } @@ -79,7 +80,14 @@ namespace data m_BufferLen = len; ReadFromBuffer (false); } - + + void LeaseSet::PopulateLeases () + { + m_StoreLeases = true; + m_Leases.clear (); + ReadFromBuffer (false); + } + void LeaseSet::ReadFromBuffer (bool readIdentity) { if (readIdentity || !m_Identity) @@ -105,6 +113,7 @@ namespace data } // process leases + m_ExpirationTime = 0; const uint8_t * leases = m_Buffer + size; for (int i = 0; i < num; i++) { @@ -113,16 +122,20 @@ namespace data leases += 32; // gateway lease.tunnelID = bufbe32toh (leases); leases += 4; // tunnel ID - lease.endDate = bufbe64toh (leases); + lease.endDate = bufbe64toh (leases); leases += 8; // end date - m_Leases.push_back (lease); - - // check if lease's gateway is in our netDb - if (!netdb.FindRouter (lease.tunnelGateway)) - { - // if not found request it - LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); - netdb.RequestDestination (lease.tunnelGateway); + if (lease.endDate > m_ExpirationTime) + m_ExpirationTime = lease.endDate; + if (m_StoreLeases) + { + m_Leases.push_back (lease); + // check if lease's gateway is in our netDb + if (!netdb.FindRouter (lease.tunnelGateway)) + { + // if not found request it + LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); + netdb.RequestDestination (lease.tunnelGateway); + } } } @@ -150,19 +163,17 @@ namespace data } bool LeaseSet::HasExpiredLeases () const - { + { auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto& it: m_Leases) if (ts >= it.endDate) return true; return false; - } + } - bool LeaseSet::HasNonExpiredLeases () const + bool LeaseSet::IsExpired () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - for (auto& it: m_Leases) - if (ts < it.endDate) return true; - return false; + return ts > m_ExpirationTime; } } } diff --git a/LeaseSet.h b/LeaseSet.h index aa9b73ad..0f437170 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -37,10 +37,11 @@ namespace data { public: - LeaseSet (const uint8_t * buf, size_t len); + LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true); LeaseSet (std::shared_ptr pool); ~LeaseSet () { delete[] m_Buffer; }; void Update (const uint8_t * buf, size_t len); + void PopulateLeases (); /// from buffer std::shared_ptr GetIdentity () const { return m_Identity; }; const uint8_t * GetBuffer () const { return m_Buffer; }; @@ -52,7 +53,8 @@ namespace data const std::vector& GetLeases () const { return m_Leases; }; const std::vector GetNonExpiredLeases (bool withThreshold = true) const; bool HasExpiredLeases () const; - bool HasNonExpiredLeases () const; + bool IsExpired () const; + uint64_t GetExpirationTime () const { return m_ExpirationTime; }; const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; }; bool IsDestination () const { return true; }; @@ -62,8 +64,9 @@ namespace data private: - bool m_IsValid; + bool m_IsValid, m_StoreLeases; // we don't need to store leases for floodfill std::vector m_Leases; + uint64_t m_ExpirationTime; // in milliseconds std::shared_ptr m_Identity; uint8_t m_EncryptionKey[256]; uint8_t * m_Buffer; diff --git a/NetDb.cpp b/NetDb.cpp index 70b33f7f..fe1d6a45 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -206,7 +206,7 @@ namespace data } else { - auto leaseSet = std::make_shared (buf, len); + auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64()); @@ -981,9 +981,10 @@ namespace data void NetDb::ManageLeaseSets () { + auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();) { - if (!it->second->HasNonExpiredLeases ()) // all leases expired + if (ts > it->second->GetExpirationTime ()) { LogPrint (eLogWarning, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_LeaseSets.erase (it); From e90baf3ca6ee30d21861c1541ffb0b57b97b3894 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 7 Feb 2016 21:35:06 -0500 Subject: [PATCH 18/18] correct required base64 buffer size --- Base.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Base.cpp b/Base.cpp index f5144eda..1479d62f 100644 --- a/Base.cpp +++ b/Base.cpp @@ -190,6 +190,13 @@ namespace data return outCount; } + size_t Base64EncodingBufferSize (const size_t input_size) + { + auto d = div (input_size, 3); + if (d.rem) d.quot++; + return 4*d.quot; + } + /* * * iT64 @@ -328,13 +335,6 @@ namespace data return 0; } } - - // from https://stackoverflow.com/questions/1533113/calculate-the-size-to-a-base-64-encoded-message - size_t Base64EncodingBufferSize(const size_t input_size) { - const size_t code_size = ((input_size * 4) / 3); - const size_t padding_size = (input_size % 3) ? (3 - (input_size % 3)) : 0; - return code_size + padding_size; - } } }