NetDbRequests.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "Log.h"
  2. #include "I2NPProtocol.h"
  3. #include "Transports.h"
  4. #include "NetDb.hpp"
  5. #include "NetDbRequests.h"
  6. namespace i2p
  7. {
  8. namespace data
  9. {
  10. std::shared_ptr<I2NPMessage> RequestedDestination::CreateRequestMessage (std::shared_ptr<const RouterInfo> router,
  11. std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
  12. {
  13. std::shared_ptr<I2NPMessage> msg;
  14. if(replyTunnel)
  15. msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
  16. replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory,
  17. &m_ExcludedPeers);
  18. else
  19. msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers);
  20. if(router)
  21. m_ExcludedPeers.insert (router->GetIdentHash ());
  22. m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
  23. return msg;
  24. }
  25. std::shared_ptr<I2NPMessage> RequestedDestination::CreateRequestMessage (const IdentHash& floodfill)
  26. {
  27. auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
  28. i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers);
  29. m_ExcludedPeers.insert (floodfill);
  30. m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
  31. return msg;
  32. }
  33. void RequestedDestination::ClearExcludedPeers ()
  34. {
  35. m_ExcludedPeers.clear ();
  36. }
  37. void RequestedDestination::Success (std::shared_ptr<RouterInfo> r)
  38. {
  39. if (m_RequestComplete)
  40. {
  41. m_RequestComplete (r);
  42. m_RequestComplete = nullptr;
  43. }
  44. }
  45. void RequestedDestination::Fail ()
  46. {
  47. if (m_RequestComplete)
  48. {
  49. m_RequestComplete (nullptr);
  50. m_RequestComplete = nullptr;
  51. }
  52. }
  53. void NetDbRequests::Start ()
  54. {
  55. }
  56. void NetDbRequests::Stop ()
  57. {
  58. m_RequestedDestinations.clear ();
  59. }
  60. std::shared_ptr<RequestedDestination> NetDbRequests::CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete)
  61. {
  62. // request RouterInfo directly
  63. auto dest = std::make_shared<RequestedDestination> (destination, isExploratory);
  64. dest->SetRequestComplete (requestComplete);
  65. {
  66. std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex);
  67. if (!m_RequestedDestinations.insert (std::make_pair (destination, dest)).second) // not inserted
  68. return nullptr;
  69. }
  70. return dest;
  71. }
  72. void NetDbRequests::RequestComplete (const IdentHash& ident, std::shared_ptr<RouterInfo> r)
  73. {
  74. std::shared_ptr<RequestedDestination> request;
  75. {
  76. std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex);
  77. auto it = m_RequestedDestinations.find (ident);
  78. if (it != m_RequestedDestinations.end ())
  79. {
  80. request = it->second;
  81. m_RequestedDestinations.erase (it);
  82. }
  83. }
  84. if (request)
  85. {
  86. if (r)
  87. request->Success (r);
  88. else
  89. request->Fail ();
  90. }
  91. }
  92. std::shared_ptr<RequestedDestination> NetDbRequests::FindRequest (const IdentHash& ident) const
  93. {
  94. std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex);
  95. auto it = m_RequestedDestinations.find (ident);
  96. if (it != m_RequestedDestinations.end ())
  97. return it->second;
  98. return nullptr;
  99. }
  100. void NetDbRequests::ManageRequests ()
  101. {
  102. uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
  103. std::unique_lock<std::mutex> l(m_RequestedDestinationsMutex);
  104. for (auto it = m_RequestedDestinations.begin (); it != m_RequestedDestinations.end ();)
  105. {
  106. auto& dest = it->second;
  107. bool done = false;
  108. if (ts < dest->GetCreationTime () + 60) // request is worthless after 1 minute
  109. {
  110. if (ts > dest->GetCreationTime () + 5) // no response for 5 seconds
  111. {
  112. auto count = dest->GetExcludedPeers ().size ();
  113. if (!dest->IsExploratory () && count < 7)
  114. {
  115. auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
  116. auto outbound = pool->GetNextOutboundTunnel ();
  117. auto inbound = pool->GetNextInboundTunnel ();
  118. auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ());
  119. if (nextFloodfill && outbound && inbound)
  120. outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0,
  121. dest->CreateRequestMessage (nextFloodfill, inbound));
  122. else
  123. {
  124. done = true;
  125. if (!inbound) LogPrint (eLogWarning, "NetDbReq: No inbound tunnels");
  126. if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels");
  127. if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills");
  128. }
  129. }
  130. else
  131. {
  132. if (!dest->IsExploratory ())
  133. LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts");
  134. done = true;
  135. }
  136. }
  137. }
  138. else // delete obsolete request
  139. done = true;
  140. if (done)
  141. it = m_RequestedDestinations.erase (it);
  142. else
  143. ++it;
  144. }
  145. }
  146. }
  147. }