diff --git a/Base.cpp b/Base.cpp index c9ba407a..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 @@ -327,7 +334,7 @@ namespace data LogPrint (eLogError, "Compression error ", err); return 0; } - } + } } } 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/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/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/Destination.cpp b/Destination.cpp index 233946ad..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; } @@ -664,7 +665,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, @@ -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/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 67e9b027..b42f92cf 100644 --- a/Garlic.h +++ b/Garlic.h @@ -119,18 +119,19 @@ 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 { 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); @@ -166,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 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/Identity.cpp b/Identity.cpp index ac49b711..e32c3a59 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; } @@ -228,26 +232,35 @@ namespace data } size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const - { + { + 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]; + const size_t len = Base64ToByteStream (s.c_str(), slen, buf, bufLen); 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/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/Log.cpp b/Log.cpp index 837abac8..6391bcae 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,16 +46,25 @@ 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); + m_FullFilePath = fullFilePath; + 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::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; } @@ -65,11 +75,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..05bae7d9 100644 --- a/Log.h +++ b/Log.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "Queue.h" enum LogLevel @@ -34,13 +35,14 @@ 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 ReopenLogFile (); 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 +52,8 @@ class Log: public i2p::util::MsgQueue private: - std::ostream * m_LogStream; + std::string m_FullFilePath; // empty if stream + 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 +76,7 @@ inline void StartLog (const std::string& fullFilePath) } } -inline void StartLog (std::ostream * s) +inline void StartLog (std::shared_ptr s) { if (!g_Log) { @@ -101,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) { 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 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) { diff --git a/NetDb.cpp b/NetDb.cpp index 0cbdce30..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()); @@ -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 @@ -980,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); 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]; diff --git a/SAM.cpp b/SAM.cpp index a20de13d..7b493eb3 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); - size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE); + // get remote peer address + auto ident_ptr = stream->GetRemoteIdentity(); + const size_t ident_len = ident_ptr->GetFullLen(); + uint8_t* ident = new uint8_t[ident_len]; + + // send remote peer address as base64 + 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 } 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 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