diff --git a/NetDb.cpp b/NetDb.cpp index 9f0e4312..8516cbfe 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -149,22 +149,30 @@ namespace data } } - void NetDb::AddRouterInfo (const uint8_t * buf, int len) + bool NetDb::AddRouterInfo (const uint8_t * buf, int len) { IdentityEx identity; if (identity.FromBuffer (buf, len)) - AddRouterInfo (identity.GetIdentHash (), buf, len); + return AddRouterInfo (identity.GetIdentHash (), buf, len); + return false; } - void NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) + bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) { + bool updated = true; auto r = FindRouter (ident); if (r) { - auto ts = r->GetTimestamp (); - r->Update (buf, len); - if (r->GetTimestamp () > ts) + if (r->IsNewer (buf, len)) + { + r->Update (buf, len); LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); + } + else + { + LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); + updated = false; + } } else { @@ -182,27 +190,39 @@ namespace data m_Floodfills.push_back (r); } } + else + updated = false; } // take care about requested destination m_Requests.RequestComplete (ident, r); + return updated; } - void NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, + bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from) { + bool updated = false; if (!from) // unsolicited LS must be received directly { auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - it->second->Update (buf, len); - if (it->second->IsValid ()) - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64()); - else + if (it->second->IsNewer (buf, len)) { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64()); - m_LeaseSets.erase (it); - } + it->second->Update (buf, len); + if (it->second->IsValid ()) + { + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64()); + updated = true; + } + else + { + LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64()); + m_LeaseSets.erase (it); + } + } + else + LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase64()); } else { @@ -211,11 +231,13 @@ namespace data { LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64()); m_LeaseSets[ident] = leaseSet; + updated = true; } else LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase64()); } } + return updated; } std::shared_ptr NetDb::FindRouter (const IdentHash& ident) const @@ -487,39 +509,14 @@ namespace data LogPrint (eLogError, "NetDb: no outbound tunnels for DatabaseStore reply found"); } offset += 32; - - if (context.IsFloodfill ()) - { - // flood it - auto floodMsg = NewI2NPShortMessage (); - uint8_t * payload = floodMsg->GetPayload (); - memcpy (payload, buf, 33); // key + type - htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token - auto msgLen = len - offset; - floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen; - if (floodMsg->len < floodMsg->maxLen) - { - memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + offset, msgLen); - floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); - std::set excluded; - for (int i = 0; i < 3; i++) - { - auto floodfill = GetClosestFloodfill (ident, excluded, true); // we need a floodfill close than us only - if (floodfill) - transports.SendMessage (floodfill->GetIdentHash (), floodMsg); - else - break; - } - } - else - LogPrint (eLogError, "Database store message is too long ", floodMsg->len); - } } - + size_t payloadOffset = offset; + + bool updated = false; if (buf[DATABASE_STORE_TYPE_OFFSET]) // type { LogPrint (eLogDebug, "NetDb: store request: LeaseSet"); - AddLeaseSet (ident, buf + offset, len - offset, m->from); + updated = AddLeaseSet (ident, buf + offset, len - offset, m->from); } else { @@ -534,7 +531,34 @@ namespace data uint8_t uncompressed[2048]; size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048); if (uncompressedSize) - AddRouterInfo (ident, uncompressed, uncompressedSize); + updated = AddRouterInfo (ident, uncompressed, uncompressedSize); + } + + if (replyToken && context.IsFloodfill () && updated) + { + // flood updated + auto floodMsg = NewI2NPShortMessage (); + uint8_t * payload = floodMsg->GetPayload (); + memcpy (payload, buf, 33); // key + type + htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token + auto msgLen = len - payloadOffset; + floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen; + if (floodMsg->len < floodMsg->maxLen) + { + memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen); + floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); + std::set excluded; + for (int i = 0; i < 3; i++) + { + auto floodfill = GetClosestFloodfill (ident, excluded, true); // we need a floodfill close than us only + if (floodfill) + transports.SendMessage (floodfill->GetIdentHash (), floodMsg); + else + break; + } + } + else + LogPrint (eLogError, "Database store message is too long ", floodMsg->len); } } diff --git a/NetDb.h b/NetDb.h index f1b97728..cad00aa7 100644 --- a/NetDb.h +++ b/NetDb.h @@ -34,9 +34,9 @@ namespace data void Start (); void Stop (); - void AddRouterInfo (const uint8_t * buf, int len); - void AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); - void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); + bool AddRouterInfo (const uint8_t * buf, int len); + bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); + bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); std::shared_ptr FindRouter (const IdentHash& ident) const; std::shared_ptr FindLeaseSet (const IdentHash& destination) const; std::shared_ptr FindRouterProfile (const IdentHash& ident) const; diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 56482234..3267392b 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -459,6 +459,14 @@ namespace data s.write (properties.str ().c_str (), properties.str ().size ()); } + bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const + { + if (!m_RouterIdentity) return false; + size_t size = m_RouterIdentity->GetFullLen (); + if (size + 8 > len) return false; + return bufbe64toh (buf + size) > m_Timestamp; + } + const uint8_t * RouterInfo::LoadBuffer () { if (!m_Buffer) diff --git a/RouterInfo.h b/RouterInfo.h index 2d32edef..4870eb50 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -157,7 +157,8 @@ namespace data void Update (const uint8_t * buf, int len); void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; - + bool IsNewer (const uint8_t * buf, size_t len) const; + // implements RoutingDestination const IdentHash& GetIdentHash () const { return m_RouterIdentity->GetIdentHash (); }; const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity->GetStandardIdentity ().publicKey; };