diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index a4d3a853..b8240fd3 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -215,16 +215,32 @@ namespace i2p return m; } - I2NPMessage * CreateDatabaseStoreMsg (const i2p::data::LeaseSet * leaseSet) + I2NPMessage * CreateDatabaseStoreMsg (const i2p::data::LeaseSet * leaseSet, uint32_t replyToken) { if (!leaseSet) return nullptr; I2NPMessage * m = NewI2NPShortMessage (); - I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)m->GetPayload (); + uint8_t * payload = m->GetPayload (); + I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)payload; memcpy (msg->key, leaseSet->GetIdentHash (), 32); msg->type = 1; // LeaseSet - msg->replyToken = 0; - memcpy (m->GetPayload () + sizeof (I2NPDatabaseStoreMsg), leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); - m->len += leaseSet->GetBufferLen () + sizeof (I2NPDatabaseStoreMsg); + msg->replyToken = htobe32 (replyToken); + size_t size = sizeof (I2NPDatabaseStoreMsg); + if (replyToken) + { + auto leases = leaseSet->GetNonExpiredLeases (); + if (leases.size () > 0) + { + *(uint32_t *)(payload + size) = htobe32 (leases[0].tunnelID); + size += 4; // reply tunnelID + memcpy (payload + size, leases[0].tunnelGateway, 32); + size += 32; // reply tunnel gateway + } + else + msg->replyToken = 0; + } + memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ()); + size += leaseSet->GetBufferLen (); + m->len += size; FillI2NPMessageHeader (m, eI2NPDatabaseStore); return m; } diff --git a/I2NPProtocol.h b/I2NPProtocol.h index 815cd7cf..faddd92f 100644 --- a/I2NPProtocol.h +++ b/I2NPProtocol.h @@ -172,7 +172,7 @@ namespace tunnel I2NPMessage * CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, const i2p::data::RouterInfo * floodfill); I2NPMessage * CreateDatabaseStoreMsg (const i2p::data::RouterInfo * router = nullptr); - I2NPMessage * CreateDatabaseStoreMsg (const i2p::data::LeaseSet * leaseSet); + I2NPMessage * CreateDatabaseStoreMsg (const i2p::data::LeaseSet * leaseSet, uint32_t replyToken = 0); I2NPBuildRequestRecordClearText CreateBuildRequestRecord ( const uint8_t * ourIdent, uint32_t receiveTunnelID, diff --git a/NetDb.cpp b/NetDb.cpp index e5586a3a..8e44b7d7 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -873,5 +873,26 @@ namespace data it++; } } + + void NetDb::PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool) + { + if (!leaseSet || !pool) return; + auto outbound = pool->GetNextOutboundTunnel (); + if (!outbound) + { + LogPrint ("Can't publish LeaseSet. No outbound tunnels"); + return; + } + std::set excluded; + auto floodfill = GetClosestFloodfill (leaseSet->GetIdentHash (), excluded); + if (!floodfill) + { + LogPrint ("Can't publish LeaseSet. No floodfills found"); + return; + } + uint32_t replyToken = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); + auto msg = i2p::garlic::routing.WrapSingleMessage (*floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, replyToken)); + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); + } } } diff --git a/NetDb.h b/NetDb.h index 95c692ca..b7050fa5 100644 --- a/NetDb.h +++ b/NetDb.h @@ -13,6 +13,7 @@ #include "RouterInfo.h" #include "LeaseSet.h" #include "Tunnel.h" +#include "TunnelPool.h" #include "AddressBook.h" namespace i2p @@ -66,8 +67,9 @@ namespace data void Subscribe (const IdentHash& ident); // keep LeaseSets upto date void Unsubscribe (const IdentHash& ident); - void RequestDestination (const IdentHash& destination, bool isLeaseSet = false); - + void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool); + void RequestDestination (const IdentHash& destination, bool isLeaseSet = false); + void HandleDatabaseStoreMsg (uint8_t * buf, size_t len); void HandleDatabaseSearchReplyMsg (I2NPMessage * msg); void HandleDatabaseLookupMsg (I2NPMessage * msg); diff --git a/Streaming.cpp b/Streaming.cpp index f2985c3b..28774010 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -494,7 +494,7 @@ namespace stream StreamingDestination::StreamingDestination (boost::asio::io_service& service): - m_Service (service), m_LeaseSet (nullptr) + m_Service (service), m_LeaseSet (nullptr), m_IsPublic (false) { m_Keys = i2p::data::CreateRandomKeys (); @@ -507,7 +507,7 @@ namespace stream } StreamingDestination::StreamingDestination (boost::asio::io_service& service, const std::string& fullPath): - m_Service (service), m_LeaseSet (nullptr) + m_Service (service), m_LeaseSet (nullptr), m_IsPublic (true) { std::ifstream s(fullPath.c_str (), std::ifstream::binary); if (s.is_open ()) @@ -602,6 +602,8 @@ namespace stream UpdateLeaseSet (); for (auto it: m_Streams) it.second->SetLeaseSetUpdated (); + if (m_IsPublic) + i2p::data::netdb.PublishLeaseSet (m_LeaseSet, m_Pool); } void StreamingDestination::Sign (const uint8_t * buf, int len, uint8_t * signature) const diff --git a/Streaming.h b/Streaming.h index e3425e57..7d1f47fb 100644 --- a/Streaming.h +++ b/Streaming.h @@ -175,7 +175,8 @@ namespace stream i2p::tunnel::TunnelPool * m_Pool; i2p::data::LeaseSet * m_LeaseSet; - + bool m_IsPublic; + CryptoPP::DSA::PrivateKey m_SigningPrivateKey; std::function m_Acceptor; };