/ libi2pd / NetDbRequests.h
NetDbRequests.h
  1  /*
  2  * Copyright (c) 2013-2025, The PurpleI2P Project
  3  *
  4  * This file is part of Purple i2pd project and licensed under BSD3
  5  *
  6  * See full license text in LICENSE file at top of project tree
  7  */
  8  
  9  #ifndef NETDB_REQUESTS_H__
 10  #define NETDB_REQUESTS_H__
 11  
 12  #include <inttypes.h>
 13  #include <memory>
 14  #include <random>
 15  #include <unordered_set>
 16  #include <unordered_map>
 17  #include <list>
 18  #include "Identity.h"
 19  #include "RouterInfo.h"
 20  #include "util.h"
 21  
 22  namespace i2p
 23  {
 24  namespace data
 25  {
 26  	const int MAX_NUM_REQUEST_ATTEMPTS = 5;
 27  	const uint64_t MANAGE_REQUESTS_INTERVAL = 400; // in milliseconds
 28  	const uint64_t MANAGE_REQUESTS_INTERVAL_VARIANCE = 300; // in milliseconds
 29  	const uint64_t MIN_REQUEST_TIME = 1200; // in milliseconds
 30  	const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS * (MIN_REQUEST_TIME + MANAGE_REQUESTS_INTERVAL + MANAGE_REQUESTS_INTERVAL_VARIANCE);
 31  	const uint64_t MIN_DIRECT_REQUEST_TIME = 600; // in milliseconds
 32  	const uint64_t EXPLORATORY_REQUEST_INTERVAL = 55; // in seconds
 33  	const uint64_t EXPLORATORY_REQUEST_INTERVAL_VARIANCE = 170; // in seconds 
 34  	const uint64_t DISCOVERED_REQUEST_INTERVAL = 360; // in milliseconds
 35  	const uint64_t DISCOVERED_REQUEST_INTERVAL_VARIANCE = 540; // in milliseconds
 36  	const uint64_t MAX_EXPLORATORY_REQUEST_TIME = 30000; // in milliseconds
 37  	const uint64_t REQUEST_CACHE_TIME = MAX_REQUEST_TIME + 40000; // in milliseconds
 38  	const uint64_t REQUESTED_DESTINATIONS_POOL_CLEANUP_INTERVAL = 191; // in seconds
 39  	
 40  	class RequestedDestination
 41  	{
 42  		public:
 43  
 44  			typedef std::function<void (std::shared_ptr<RouterInfo>)> RequestComplete;
 45  
 46  			RequestedDestination (const IdentHash& destination, bool isExploratory = false, bool direct = true);
 47  			~RequestedDestination ();
 48  
 49  			const IdentHash& GetDestination () const { return m_Destination; };
 50  			const std::unordered_set<IdentHash>& GetExcludedPeers () const { return m_ExcludedPeers; };
 51  			int GetNumAttempts () const { return m_NumAttempts; };
 52  			void ClearExcludedPeers ();
 53  			bool IsExploratory () const { return m_IsExploratory; };
 54  			bool IsDirect () const { return m_IsDirect; };
 55  			bool IsActive () const { return m_IsActive; };
 56  			bool IsSentDirectly () const { return m_IsSentDirectly; };
 57  			bool IsExcluded (const IdentHash& ident) const;
 58  			uint64_t GetCreationTime () const { return m_CreationTime; };
 59  			uint64_t GetLastRequestTime () const { return m_LastRequestTime; };
 60  			std::shared_ptr<I2NPMessage> CreateRequestMessage (std::shared_ptr<const RouterInfo>, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel);
 61  			std::shared_ptr<I2NPMessage> CreateRequestMessage (const IdentHash& floodfill);
 62  
 63  			void AddRequestComplete (const RequestComplete& requestComplete) { m_RequestComplete.push_back (requestComplete); };
 64  			void ResetRequestComplete () { m_RequestComplete.clear (); };
 65  			void Success (std::shared_ptr<RouterInfo> r);
 66  			void Fail ();
 67  
 68  		private:
 69  
 70  			void InvokeRequestComplete (std::shared_ptr<RouterInfo> r);
 71  			
 72  		private:
 73  
 74  			IdentHash m_Destination;
 75  			bool m_IsExploratory, m_IsDirect, m_IsActive, m_IsSentDirectly;
 76  			std::unordered_set<IdentHash> m_ExcludedPeers;
 77  			uint64_t m_CreationTime, m_LastRequestTime; // in milliseconds
 78  			std::list<RequestComplete> m_RequestComplete;
 79  			int m_NumAttempts;
 80  	};
 81  
 82  	class NetDbRequests: public std::enable_shared_from_this<NetDbRequests>,
 83  		 private i2p::util::RunnableServiceWithWork
 84  	{
 85  		public:
 86  
 87  			NetDbRequests ();
 88  			~NetDbRequests ();
 89  			
 90  			void Start ();
 91  			void Stop ();
 92  
 93  			void RequestComplete (const IdentHash& ident, std::shared_ptr<RouterInfo> r);
 94  			void PostDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
 95  			void PostRequestDestination (const IdentHash& destination, const RequestedDestination::RequestComplete& requestComplete, bool direct);
 96  			
 97  		private:	
 98  
 99  			std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, 
100  				bool direct = false, RequestedDestination::RequestComplete requestComplete = nullptr);
101  			std::shared_ptr<RequestedDestination> FindRequest (const IdentHash& ident) const;
102  			bool SendNextRequest (std::shared_ptr<RequestedDestination> dest);
103  			
104  			void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
105  			void RequestRouter (const IdentHash& router);
106  			void RequestDestination (const IdentHash& destination, const RequestedDestination::RequestComplete& requestComplete, bool direct);
107  			void Explore (int numDestinations);
108  			void ManageRequests ();
109  			// timer
110  			void ScheduleManageRequests ();
111  			void HandleManageRequestsTimer (const boost::system::error_code& ecode);
112  			void ScheduleExploratory (uint64_t interval);
113  			void HandleExploratoryTimer (const boost::system::error_code& ecode);
114  			void ScheduleCleanup ();
115  			void HandleCleanupTimer (const boost::system::error_code& ecode);
116  			void ScheduleDiscoveredRoutersRequest ();
117  			void HandleDiscoveredRoutersTimer (const boost::system::error_code& ecode);
118  			
119  		private:
120  
121  			i2p::util::MemoryPoolMt<RequestedDestination> m_RequestedDestinationsPool;
122  			std::unordered_map<IdentHash, std::shared_ptr<RequestedDestination> > m_RequestedDestinations;
123  			std::list<IdentHash> m_DiscoveredRouterHashes;
124  			boost::asio::deadline_timer m_ManageRequestsTimer, m_ExploratoryTimer,
125  				m_CleanupTimer, m_DiscoveredRoutersTimer;
126  			std::mt19937 m_Rng;
127  	};
128  }
129  }
130  
131  #endif