File: AddressBook.h

package info (click to toggle)
i2pd 2.58.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,612 kB
  • sloc: cpp: 59,663; makefile: 224; sh: 138
file content (184 lines) | stat: -rw-r--r-- 6,207 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
* Copyright (c) 2013-2025, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/

#ifndef ADDRESS_BOOK_H__
#define ADDRESS_BOOK_H__

#include <string.h>
#include <string>
#include <string_view>
#include <map>
#include <vector>
#include <iostream>
#include <mutex>
#include <future>
#include <memory>
#include <boost/asio.hpp>
#include "Base.h"
#include "Identity.h"
#include "Log.h"
#include "Destination.h"
#include "LeaseSet.h"

namespace i2p
{
namespace client
{
	const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes
	const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes
	const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours)
	const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes
	const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout
	const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in seconds
	const int ADDRESS_CACHE_EXPIRATION_TIMEOUT = 710; // in seconds
	const int ADDRESS_CACHE_UPDATE_INTERVAL = 76; // in seconds

	const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53;
	const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54;

	const size_t B33_ADDRESS_THRESHOLD = 52; // characters

	struct Address
	{
		enum { eAddressIndentHash, eAddressBlindedPublicKey, eAddressInvalid } addressType;
		i2p::data::IdentHash identHash;
		std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey;

		Address (std::string_view b32);
		Address (const i2p::data::IdentHash& hash);
		bool IsIdentHash () const { return addressType == eAddressIndentHash; };
		bool IsValid () const { return addressType != eAddressInvalid; };
	};

	inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); }

	class AddressBookStorage // interface for storage
	{
		public:

			typedef std::map<std::string, std::shared_ptr<Address>, std::less<> > Addresses;
			
			virtual ~AddressBookStorage () {};
			virtual std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) = 0;
			virtual void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) = 0;
			virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0;
			virtual void CleanUpCache () = 0;

			virtual bool Init () = 0;
			virtual int Load (Addresses& addresses) = 0;
			virtual int LoadLocal (Addresses& addresses) = 0;
			virtual int Save (const Addresses& addresses) = 0;

			virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0;
			virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0;
			virtual void ResetEtags () = 0;
	};

	class AddressBookSubscription;
	class AddressResolver;
	class AddressBook
	{
		public:
			
			AddressBook ();
			~AddressBook ();
			void Start ();
			void StartResolvers ();
			void Stop ();
			std::shared_ptr<const Address> GetAddress (std::string_view address);
			std::shared_ptr<const i2p::data::IdentityEx> GetFullAddress (const std::string& address);
			std::shared_ptr<const Address> FindAddress (std::string_view address);
			void LookupAddress (std::string_view address);
			void InsertAddress (const std::string& address, const std::string& jump); // for jump links
			void InsertFullAddress (std::shared_ptr<const i2p::data::IdentityEx> address);

			bool RecordExists (const std::string& address, const std::string& jump);

			bool LoadHostsFromStream (std::istream& f, bool is_update);
			void DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified);
			//This method returns the ".b32.i2p" address
			std::string ToAddress(const i2p::data::IdentHash& ident) { return GetB32Address(ident); }
			std::string ToAddress(std::shared_ptr<const i2p::data::IdentityEx> ident) { return ToAddress(ident->GetIdentHash ()); }

			bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified);
			bool IsEnabled () const { return m_IsEnabled; }
			
		private:

			void StartSubscriptions ();
			void StopSubscriptions ();

			void LoadHosts ();
			void LoadSubscriptions ();
			void LoadLocal ();

			void HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode);

			void StartLookups ();
			void StopLookups ();
			void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);

			void ScheduleCacheUpdate ();
			
		private:

			std::mutex m_AddressBookMutex;
			AddressBookStorage::Addresses m_Addresses;
			std::map<i2p::data::IdentHash, std::shared_ptr<AddressResolver> > m_Resolvers; // local destination->resolver
			std::mutex m_LookupsMutex;
			std::map<uint32_t, std::string> m_Lookups; // nonce -> address
			AddressBookStorage * m_Storage;
			volatile bool m_IsLoaded;
			std::future<void> m_Downloading;
			int m_NumRetries;
			std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions;
			std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
			std::unique_ptr<boost::asio::deadline_timer> m_SubscriptionsUpdateTimer, m_AddressCacheUpdateTimer;
			bool m_IsEnabled;
	};

	class AddressBookSubscription
	{
		public:

			AddressBookSubscription (AddressBook& book, std::string_view link);
			void CheckUpdates ();

		private:

			bool MakeRequest ();

		private:

			AddressBook& m_Book;
			std::string m_Link, m_Etag, m_LastModified;
			i2p::data::IdentHash m_Ident;
			// m_Etag must be surrounded by ""
	};

	class AddressResolver
	{
		public:

			AddressResolver (std::shared_ptr<ClientDestination> destination);
			~AddressResolver ();
			void AddAddress (const std::string& name, const i2p::data::IdentHash& ident);

		private:

			void HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);

		private:

			std::shared_ptr<ClientDestination> m_LocalDestination;
			std::map<std::string, i2p::data::IdentHash> m_LocalAddresses;
	};
}
}

#endif