forked from PurpleI2P/i2pd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTransports.h
258 lines (209 loc) · 8.96 KB
/
Transports.h
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*
* Copyright (c) 2013-2024, 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 TRANSPORTS_H__
#define TRANSPORTS_H__
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <unordered_map>
#include <vector>
#include <queue>
#include <string>
#include <memory>
#include <atomic>
#include <boost/asio.hpp>
#include "TransportSession.h"
#include "SSU2.h"
#include "NTCP2.h"
#include "RouterInfo.h"
#include "I2NPProtocol.h"
#include "Identity.h"
#include "util.h"
namespace i2p
{
namespace transport
{
template<typename Keys>
class EphemeralKeysSupplier
{
// called from this file only, so implementation is in Transports.cpp
public:
EphemeralKeysSupplier (int size);
~EphemeralKeysSupplier ();
void Start ();
void Stop ();
std::shared_ptr<Keys> Acquire ();
void Return (std::shared_ptr<Keys> pair);
private:
void Run ();
void CreateEphemeralKeys (int num);
private:
const int m_QueueSize;
std::queue<std::shared_ptr<Keys> > m_Queue;
i2p::util::MemoryPoolMt<Keys> m_KeysPool;
bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread;
std::condition_variable m_Acquired;
std::mutex m_AcquiredMutex;
};
typedef EphemeralKeysSupplier<i2p::crypto::X25519Keys> X25519KeysPairSupplier;
const int PEER_ROUTER_INFO_UPDATE_INTERVAL = 31*60; // in seconds
const int PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE = 7*60; // in seconds
const size_t PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE = 25;
const int PEER_SELECTION_MIN_INTERVAL = 20; // in seconds
struct Peer
{
int numAttempts;
std::shared_ptr<const i2p::data::RouterInfo> router;
std::list<std::shared_ptr<TransportSession> > sessions;
uint64_t creationTime, nextRouterInfoUpdateTime, lastSelectionTime;
std::list<std::shared_ptr<i2p::I2NPMessage> > delayedMessages;
std::vector<i2p::data::RouterInfo::SupportedTransports> priority;
bool isHighBandwidth, isEligible;
Peer (std::shared_ptr<const i2p::data::RouterInfo> r, uint64_t ts):
numAttempts (0), router (r), creationTime (ts),
nextRouterInfoUpdateTime (ts + PEER_ROUTER_INFO_UPDATE_INTERVAL),
lastSelectionTime (0), isHighBandwidth (false), isEligible (false)
{
UpdateParams (router);
}
void Done ()
{
for (auto& it: sessions)
it->Done ();
// drop not sent delayed messages
for (auto& it: delayedMessages)
it->Drop ();
}
void SetRouter (std::shared_ptr<const i2p::data::RouterInfo> r)
{
router = r;
UpdateParams (router);
}
bool IsConnected () const { return !sessions.empty (); }
void UpdateParams (std::shared_ptr<const i2p::data::RouterInfo> router);
};
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
const int PEER_TEST_INTERVAL = 71; // in minutes
const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
const int MAX_NUM_DELAYED_MESSAGES = 150;
const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after
const int NUM_X25519_PRE_GENERATED_KEYS = 25; // pre-generated x25519 keys pairs
const int TRAFFIC_SAMPLE_COUNT = 301; // seconds
struct TrafficSample
{
uint64_t Timestamp;
uint64_t TotalReceivedBytes;
uint64_t TotalSentBytes;
uint64_t TotalTransitTransmittedBytes;
};
class Transports
{
public:
Transports ();
~Transports ();
void Start (bool enableNTCP2=true, bool enableSSU2=true);
void Stop ();
bool IsRunning () const { return m_IsRunning; }
bool IsBoundSSU2() const { return m_SSU2Server != nullptr; }
bool IsBoundNTCP2() const { return m_NTCP2Server != nullptr; }
bool IsOnline() const { return m_IsOnline; };
void SetOnline (bool online);
auto& GetService () { return *m_Service; };
std::shared_ptr<i2p::crypto::X25519Keys> GetNextX25519KeysPair ();
void ReuseX25519KeysPair (std::shared_ptr<i2p::crypto::X25519Keys> pair);
void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg);
void SendMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
void SendMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >&& msgs);
void PeerConnected (std::shared_ptr<TransportSession> session);
void PeerDisconnected (std::shared_ptr<TransportSession> session);
bool IsConnected (const i2p::data::IdentHash& ident) const;
void UpdateSentBytes (uint64_t numBytes) { m_TotalSentBytes += numBytes; };
void UpdateReceivedBytes (uint64_t numBytes) { m_TotalReceivedBytes += numBytes; };
uint64_t GetTotalSentBytes () const { return m_TotalSentBytes; };
uint64_t GetTotalReceivedBytes () const { return m_TotalReceivedBytes; };
uint64_t GetTotalTransitTransmittedBytes () const { return m_TotalTransitTransmittedBytes; }
void UpdateTotalTransitTransmittedBytes (uint32_t add) { m_TotalTransitTransmittedBytes += add; };
uint32_t GetInBandwidth () const { return m_InBandwidth; };
uint32_t GetOutBandwidth () const { return m_OutBandwidth; };
uint32_t GetTransitBandwidth () const { return m_TransitBandwidth; };
uint32_t GetInBandwidth15s () const { return m_InBandwidth15s; };
uint32_t GetOutBandwidth15s () const { return m_OutBandwidth15s; };
uint32_t GetTransitBandwidth15s () const { return m_TransitBandwidth15s; };
int GetCongestionLevel (bool longTerm) const;
size_t GetNumPeers () const { return m_Peers.size (); };
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
/** get a trusted first hop for restricted routes */
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
/** do we want to use restricted routes? */
bool RoutesRestricted() const;
/** restrict routes to use only these router families for first hops */
void RestrictRoutesToFamilies(const std::set<std::string>& families);
/** restrict routes to use only these routers for first hops */
void RestrictRoutesToRouters(const std::set<i2p::data::IdentHash>& routers);
bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const;
void PeerTest (bool ipv4 = true, bool ipv6 = true);
void SetCheckReserved (bool check) { m_CheckReserved = check; };
bool IsCheckReserved () const { return m_CheckReserved; };
bool IsInReservedRange (const boost::asio::ip::address& host) const;
private:
void Run ();
void RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident);
void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident);
void PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer);
void SetPriority (std::shared_ptr<Peer> peer) const;
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
void HandlePeerTestTimer (const boost::system::error_code& ecode);
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
void UpdateBandwidthValues (int interval, uint32_t& in, uint32_t& out, uint32_t& transit);
void DetectExternalIP ();
template<typename Filter>
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (Filter filter) const;
private:
volatile bool m_IsOnline;
bool m_IsRunning, m_IsNAT, m_CheckReserved;
std::thread * m_Thread;
boost::asio::io_context * m_Service;
boost::asio::io_context::work * m_Work;
boost::asio::deadline_timer * m_PeerCleanupTimer, * m_PeerTestTimer, * m_UpdateBandwidthTimer;
SSU2Server * m_SSU2Server;
NTCP2Server * m_NTCP2Server;
mutable std::mutex m_PeersMutex;
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<Peer> > m_Peers;
X25519KeysPairSupplier m_X25519KeysPairSupplier;
std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes;
TrafficSample m_TrafficSamples[TRAFFIC_SAMPLE_COUNT];
int m_TrafficSamplePtr;
// Bandwidth per second
uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth;
// Bandwidth during last 15 seconds
uint32_t m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s;
// Bandwidth during last 5 minutes
uint32_t m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m;
/** which router families to trust for first hops */
std::vector<i2p::data::FamilyID> m_TrustedFamilies;
mutable std::mutex m_FamilyMutex;
/** which routers for first hop to trust */
std::vector<i2p::data::IdentHash> m_TrustedRouters;
mutable std::mutex m_TrustedRoutersMutex;
i2p::I2NPMessagesHandler m_LoopbackHandler;
public:
// for HTTP only
const NTCP2Server * GetNTCP2Server () const { return m_NTCP2Server; };
const SSU2Server * GetSSU2Server () const { return m_SSU2Server; };
const decltype(m_Peers)& GetPeers () const { return m_Peers; };
};
extern Transports transports;
void InitAddressFromIface ();
void InitTransports ();
}
}
#endif