/ libi2pd_client / AddressBook.h
AddressBook.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 ADDRESS_BOOK_H__ 10 #define ADDRESS_BOOK_H__ 11 12 #include <string.h> 13 #include <string> 14 #include <string_view> 15 #include <map> 16 #include <vector> 17 #include <iostream> 18 #include <mutex> 19 #include <future> 20 #include <memory> 21 #include <boost/asio.hpp> 22 #include "Base.h" 23 #include "Identity.h" 24 #include "Log.h" 25 #include "Destination.h" 26 #include "LeaseSet.h" 27 28 namespace i2p 29 { 30 namespace client 31 { 32 const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes 33 const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes 34 const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) 35 const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes 36 const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout 37 const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in seconds 38 const int ADDRESS_CACHE_EXPIRATION_TIMEOUT = 710; // in seconds 39 const int ADDRESS_CACHE_UPDATE_INTERVAL = 76; // in seconds 40 41 const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; 42 const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54; 43 44 const size_t B33_ADDRESS_THRESHOLD = 52; // characters 45 46 struct Address 47 { 48 enum { eAddressIndentHash, eAddressBlindedPublicKey, eAddressInvalid } addressType; 49 i2p::data::IdentHash identHash; 50 std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey; 51 52 Address (std::string_view b32); 53 Address (const i2p::data::IdentHash& hash); 54 bool IsIdentHash () const { return addressType == eAddressIndentHash; }; 55 bool IsValid () const { return addressType != eAddressInvalid; }; 56 }; 57 58 inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } 59 60 class AddressBookStorage // interface for storage 61 { 62 public: 63 64 typedef std::map<std::string, std::shared_ptr<Address>, std::less<> > Addresses; 65 66 virtual ~AddressBookStorage () {}; 67 virtual std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) = 0; 68 virtual void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) = 0; 69 virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0; 70 virtual void CleanUpCache () = 0; 71 72 virtual bool Init () = 0; 73 virtual int Load (Addresses& addresses) = 0; 74 virtual int LoadLocal (Addresses& addresses) = 0; 75 virtual int Save (const Addresses& addresses) = 0; 76 77 virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0; 78 virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0; 79 virtual void ResetEtags () = 0; 80 }; 81 82 class AddressBookSubscription; 83 class AddressResolver; 84 class AddressBook 85 { 86 public: 87 88 AddressBook (); 89 ~AddressBook (); 90 void Start (); 91 void StartResolvers (); 92 void Stop (); 93 std::shared_ptr<const Address> GetAddress (std::string_view address); 94 std::shared_ptr<const i2p::data::IdentityEx> GetFullAddress (const std::string& address); 95 std::shared_ptr<const Address> FindAddress (std::string_view address); 96 void LookupAddress (std::string_view address); 97 void InsertAddress (const std::string& address, const std::string& jump); // for jump links 98 void InsertFullAddress (std::shared_ptr<const i2p::data::IdentityEx> address); 99 100 bool RecordExists (const std::string& address, const std::string& jump); 101 102 bool LoadHostsFromStream (std::istream& f, bool is_update); 103 void DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified); 104 //This method returns the ".b32.i2p" address 105 std::string ToAddress(const i2p::data::IdentHash& ident) { return GetB32Address(ident); } 106 std::string ToAddress(std::shared_ptr<const i2p::data::IdentityEx> ident) { return ToAddress(ident->GetIdentHash ()); } 107 108 bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified); 109 bool IsEnabled () const { return m_IsEnabled; } 110 111 private: 112 113 void StartSubscriptions (); 114 void StopSubscriptions (); 115 116 void LoadHosts (); 117 void LoadSubscriptions (); 118 void LoadLocal (); 119 120 void HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode); 121 122 void StartLookups (); 123 void StopLookups (); 124 void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); 125 126 void ScheduleCacheUpdate (); 127 128 private: 129 130 std::mutex m_AddressBookMutex; 131 AddressBookStorage::Addresses m_Addresses; 132 std::map<i2p::data::IdentHash, std::shared_ptr<AddressResolver> > m_Resolvers; // local destination->resolver 133 std::mutex m_LookupsMutex; 134 std::map<uint32_t, std::string> m_Lookups; // nonce -> address 135 AddressBookStorage * m_Storage; 136 volatile bool m_IsLoaded; 137 std::future<void> m_Downloading; 138 int m_NumRetries; 139 std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions; 140 std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet 141 std::unique_ptr<boost::asio::deadline_timer> m_SubscriptionsUpdateTimer, m_AddressCacheUpdateTimer; 142 bool m_IsEnabled; 143 }; 144 145 class AddressBookSubscription 146 { 147 public: 148 149 AddressBookSubscription (AddressBook& book, std::string_view link); 150 void CheckUpdates (); 151 152 private: 153 154 bool MakeRequest (); 155 156 private: 157 158 AddressBook& m_Book; 159 std::string m_Link, m_Etag, m_LastModified; 160 i2p::data::IdentHash m_Ident; 161 // m_Etag must be surrounded by "" 162 }; 163 164 class AddressResolver 165 { 166 public: 167 168 AddressResolver (std::shared_ptr<ClientDestination> destination); 169 ~AddressResolver (); 170 void AddAddress (const std::string& name, const i2p::data::IdentHash& ident); 171 172 private: 173 174 void HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); 175 176 private: 177 178 std::shared_ptr<ClientDestination> m_LocalDestination; 179 std::map<std::string, i2p::data::IdentHash> m_LocalAddresses; 180 }; 181 } 182 } 183 184 #endif