diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 5ad6df78..6897148b 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -244,7 +244,8 @@ namespace i2p return m; } - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router, uint32_t replyToken) + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router, + uint32_t replyToken, std::shared_ptr replyTunnel) { if (!router) // we send own RouterInfo router = context.GetSharedRouterInfo (); @@ -258,10 +259,20 @@ namespace i2p uint8_t * buf = payload + DATABASE_STORE_HEADER_SIZE; if (replyToken) { - memset (buf, 0, 4); // zero tunnelID means direct reply - buf += 4; - memcpy (buf, router->GetIdentHash (), 32); - buf += 32; + if (replyTunnel) + { + htobe32buf (buf, replyTunnel->GetNextTunnelID ()); + buf += 4; // reply tunnelID + memcpy (buf, replyTunnel->GetNextIdentHash (), 32); + buf += 32; // reply tunnel gateway + } + else + { + memset (buf, 0, 4); // zero tunnelID means direct reply + buf += 4; + memcpy (buf, context.GetIdentHash (), 32); + buf += 32; + } } uint8_t * sizePtr = buf; diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index b8fbb303..c9b0fc04 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -276,7 +276,7 @@ namespace tunnel const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false); std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers); - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0); + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); std::shared_ptr CreateDatabaseStoreMsg (const i2p::data::IdentHash& storeHash, std::shared_ptr leaseSet); // for floodfill only std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); bool IsRouterInfoMsg (std::shared_ptr msg); diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 20b54376..c3e33411 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -643,6 +643,7 @@ namespace data auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ()); if (floodfill) { + if (direct && !floodfill->IsCompatible (i2p::context.GetRouterInfo ())) direct = false; // check if fllodfill is reachable if (direct) transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); else @@ -1087,7 +1088,19 @@ namespace data LogPrint (eLogInfo, "NetDb: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken); m_PublishExcluded.insert (floodfill->GetIdentHash ()); m_PublishReplyToken = replyToken; - transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); + if (floodfill->IsCompatible (i2p::context.GetRouterInfo ())) // able to connect? + // send directly + transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); + else + { + // otherwise through exploratory + auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; + auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; + if (inbound && outbound) + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, + CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); + } } }