1 /*
2 * Copyright (c) 2013-2021, 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 #include <string.h>
10 #include "I2PEndian.h"
11 #include <random>
12 #include <thread>
13 #include <algorithm>
14 #include <vector>
15 #include "Crypto.h"
16 #include "RouterContext.h"
17 #include "Log.h"
18 #include "Timestamp.h"
19 #include "I2NPProtocol.h"
20 #include "Transports.h"
21 #include "NetDb.hpp"
22 #include "Config.h"
23 #include "Tunnel.h"
24 #include "TunnelPool.h"
25 #include "util.h"
26 #include "ECIESX25519AEADRatchetSession.h"
27 
28 namespace i2p
29 {
30 namespace tunnel
31 {
Tunnel(std::shared_ptr<const TunnelConfig> config)32 	Tunnel::Tunnel (std::shared_ptr<const TunnelConfig> config):
33 		TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()),
34 		m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr),
35 		m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports),
36 		m_IsRecreated (false), m_Latency (0)
37 	{
38 	}
39 
~Tunnel()40 	Tunnel::~Tunnel ()
41 	{
42 	}
43 
Build(uint32_t replyMsgID,std::shared_ptr<OutboundTunnel> outboundTunnel)44 	void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel)
45 	{
46 		auto numHops = m_Config->GetNumHops ();
47 		const int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS;
48 		auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage ();
49 		*msg->GetPayload () = numRecords;
50 		const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
51 		msg->len += numRecords*recordSize + 1;
52 		// shuffle records
53 		std::vector<int> recordIndicies;
54 		for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i);
55 		std::shuffle (recordIndicies.begin(), recordIndicies.end(), std::mt19937(std::random_device()()));
56 
57 		// create real records
58 		uint8_t * records = msg->GetPayload () + 1;
59 		TunnelHopConfig * hop = m_Config->GetFirstHop ();
60 		int i = 0;
61 		while (hop)
62 		{
63 			uint32_t msgID;
64 			if (hop->next) // we set replyMsgID for last hop only
65 				RAND_bytes ((uint8_t *)&msgID, 4);
66 			else
67 				msgID = replyMsgID;
68 			hop->recordIndex = recordIndicies[i]; i++;
69 			hop->CreateBuildRequestRecord (records, msgID);
70 			hop = hop->next;
71 		}
72 		// fill up fake records with random data
73 		for (int i = numHops; i < numRecords; i++)
74 		{
75 			int idx = recordIndicies[i];
76 			RAND_bytes (records + idx*recordSize, recordSize);
77 		}
78 
79 		// decrypt real records
80 		hop = m_Config->GetLastHop ()->prev;
81 		while (hop)
82 		{
83 			// decrypt records after current hop
84 			TunnelHopConfig * hop1 = hop->next;
85 			while (hop1)
86 			{
87 				hop->DecryptRecord (records, hop1->recordIndex);
88 				hop1 = hop1->next;
89 			}
90 			hop = hop->prev;
91 		}
92 		msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild);
93 
94 		// send message
95 		if (outboundTunnel)
96 		{
97 			if (m_Config->IsShort ())
98 			{
99 				auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr;
100 				if (ident && ident->GetIdentHash () != outboundTunnel->GetNextIdentHash ()) // don't encrypt if IBGW = OBEP
101 				{
102 					auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ());
103 					if (msg1) msg = msg1;
104 				}
105 			}
106 			outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg);
107 		}
108 		else
109 		{
110 			if (m_Config->IsShort () && m_Config->GetLastHop () &&
111 			    m_Config->GetLastHop ()->ident->GetIdentHash () != m_Config->GetLastHop ()->nextIdent)
112 			{
113 				// add garlic key/tag for reply
114 				uint8_t key[32];
115 				uint64_t tag = m_Config->GetLastHop ()->GetGarlicKey (key);
116 				if (m_Pool && m_Pool->GetLocalDestination ())
117 					m_Pool->GetLocalDestination ()->AddECIESx25519Key (key, tag);
118 				else
119 					i2p::context.AddECIESx25519Key (key, tag);
120 			}
121 			i2p::transport::transports.SendMessage (GetNextIdentHash (), msg);
122 		}
123 	}
124 
HandleTunnelBuildResponse(uint8_t * msg,size_t len)125 	bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len)
126 	{
127 		LogPrint (eLogDebug, "Tunnel: TunnelBuildResponse ", (int)msg[0], " records.");
128 
129 		TunnelHopConfig * hop = m_Config->GetLastHop ();
130 		while (hop)
131 		{
132 			// decrypt current hop
133 			if (hop->recordIndex >= 0 && hop->recordIndex < msg[0])
134 			{
135 				if (!hop->DecryptBuildResponseRecord (msg + 1))
136 					return false;
137 			}
138 			else
139 			{
140 				LogPrint (eLogWarning, "Tunnel: Hop index ", hop->recordIndex, " is out of range");
141 				return false;
142 			}
143 
144 			// decrypt records before current hop
145 			TunnelHopConfig * hop1 = hop->prev;
146 			while (hop1)
147 			{
148 				auto idx = hop1->recordIndex;
149 				if (idx >= 0 && idx < msg[0])
150 					hop->DecryptRecord (msg + 1, idx);
151 				else
152 					LogPrint (eLogWarning, "Tunnel: Hop index ", idx, " is out of range");
153 				hop1 = hop1->prev;
154 			}
155 			hop = hop->prev;
156 		}
157 
158 		bool established = true;
159 		size_t numHops = 0;
160 		hop = m_Config->GetFirstHop ();
161 		while (hop)
162 		{
163 			uint8_t ret = hop->GetRetCode (msg + 1);
164 			LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
165 			auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
166 			if (profile)
167 				profile->TunnelBuildResponse (ret);
168 			if (ret)
169 				// if any of participants declined the tunnel is not established
170 				established = false;
171 			hop = hop->next;
172 			numHops++;
173 		}
174 		if (established)
175 		{
176 			// create tunnel decryptions from layer and iv keys in reverse order
177 			m_Hops.resize (numHops);
178 			hop = m_Config->GetLastHop ();
179 			int i = 0;
180 			while (hop)
181 			{
182 				m_Hops[i].ident = hop->ident;
183 				m_Hops[i].decryption.SetKeys (hop->layerKey, hop->ivKey);
184 				hop = hop->prev;
185 				i++;
186 			}
187 			m_IsShortBuildMessage = m_Config->IsShort ();
188 			m_FarEndTransports = m_Config->GetFarEndTransports ();
189 			m_Config = nullptr;
190 		}
191 		if (established) m_State = eTunnelStateEstablished;
192 		return established;
193 	}
194 
LatencyFitsRange(uint64_t lower,uint64_t upper) const195 	bool Tunnel::LatencyFitsRange(uint64_t lower, uint64_t upper) const
196 	{
197 		auto latency = GetMeanLatency();
198 		return latency >= lower && latency <= upper;
199 	}
200 
EncryptTunnelMsg(std::shared_ptr<const I2NPMessage> in,std::shared_ptr<I2NPMessage> out)201 	void Tunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out)
202 	{
203 		const uint8_t * inPayload = in->GetPayload () + 4;
204 		uint8_t * outPayload = out->GetPayload () + 4;
205 		for (auto& it: m_Hops)
206 		{
207 			it.decryption.Decrypt (inPayload, outPayload);
208 			inPayload = outPayload;
209 		}
210 	}
211 
SendTunnelDataMsg(std::shared_ptr<i2p::I2NPMessage> msg)212 	void Tunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
213 	{
214 		LogPrint (eLogWarning, "Tunnel: Can't send I2NP messages without delivery instructions");
215 	}
216 
GetPeers() const217 	std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetPeers () const
218 	{
219 		auto peers = GetInvertedPeers ();
220 		std::reverse (peers.begin (), peers.end ());
221 		return peers;
222 	}
223 
GetInvertedPeers() const224 	std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetInvertedPeers () const
225 	{
226 		// hops are in inverted order
227 		std::vector<std::shared_ptr<const i2p::data::IdentityEx> > ret;
228 		for (const auto& it: m_Hops)
229 			ret.push_back (it.ident);
230 		return ret;
231 	}
232 
SetState(TunnelState state)233 	void Tunnel::SetState(TunnelState state)
234 	{
235 		m_State = state;
236 	}
237 
238 
PrintHops(std::stringstream & s) const239 	void Tunnel::PrintHops (std::stringstream& s) const
240 	{
241 		// hops are in inverted order, we must print in direct order
242 		for (auto it = m_Hops.rbegin (); it != m_Hops.rend (); it++)
243 		{
244 			s << " &#8658; ";
245 			s << i2p::data::GetIdentHashAbbreviation ((*it).ident->GetIdentHash ());
246 		}
247 	}
248 
HandleTunnelDataMsg(std::shared_ptr<I2NPMessage> && msg)249 	void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg)
250 	{
251 		if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive
252 		EncryptTunnelMsg (msg, msg);
253 		msg->from = shared_from_this ();
254 		m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
255 	}
256 
Print(std::stringstream & s) const257 	void InboundTunnel::Print (std::stringstream& s) const
258 	{
259 		PrintHops (s);
260 		s << " &#8658; " << GetTunnelID () << ":me";
261 	}
262 
ZeroHopsInboundTunnel()263 	ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
264 		InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
265 		m_NumReceivedBytes (0)
266 	{
267 	}
268 
SendTunnelDataMsg(std::shared_ptr<i2p::I2NPMessage> msg)269 	void ZeroHopsInboundTunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
270 	{
271 		if (msg)
272 		{
273 			m_NumReceivedBytes += msg->GetLength ();
274 			msg->from = shared_from_this ();
275 			HandleI2NPMessage (msg);
276 		}
277 	}
278 
Print(std::stringstream & s) const279 	void ZeroHopsInboundTunnel::Print (std::stringstream& s) const
280 	{
281 		s << " &#8658; " << GetTunnelID () << ":me";
282 	}
283 
SendTunnelDataMsg(const uint8_t * gwHash,uint32_t gwTunnel,std::shared_ptr<i2p::I2NPMessage> msg)284 	void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg)
285 	{
286 		TunnelMessageBlock block;
287 		if (gwHash)
288 		{
289 			block.hash = gwHash;
290 			if (gwTunnel)
291 			{
292 				block.deliveryType = eDeliveryTypeTunnel;
293 				block.tunnelID = gwTunnel;
294 			}
295 			else
296 				block.deliveryType = eDeliveryTypeRouter;
297 		}
298 		else
299 			block.deliveryType = eDeliveryTypeLocal;
300 		block.data = msg;
301 
302 		SendTunnelDataMsg ({block});
303 	}
304 
SendTunnelDataMsg(const std::vector<TunnelMessageBlock> & msgs)305 	void OutboundTunnel::SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs)
306 	{
307 		std::unique_lock<std::mutex> l(m_SendMutex);
308 		for (auto& it : msgs)
309 			m_Gateway.PutTunnelDataMsg (it);
310 		m_Gateway.SendBuffer ();
311 	}
312 
HandleTunnelDataMsg(std::shared_ptr<i2p::I2NPMessage> && tunnelMsg)313 	void OutboundTunnel::HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg)
314 	{
315 		LogPrint (eLogError, "Tunnel: Incoming message for outbound tunnel ", GetTunnelID ());
316 	}
317 
Print(std::stringstream & s) const318 	void OutboundTunnel::Print (std::stringstream& s) const
319 	{
320 		s << GetTunnelID () << ":me";
321 		PrintHops (s);
322 		s << " &#8658; ";
323 	}
324 
ZeroHopsOutboundTunnel()325 	ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
326 		OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
327 		m_NumSentBytes (0)
328 	{
329 	}
330 
SendTunnelDataMsg(const std::vector<TunnelMessageBlock> & msgs)331 	void ZeroHopsOutboundTunnel::SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs)
332 	{
333 		for (auto& msg : msgs)
334 		{
335 			if (!msg.data) continue;
336 			m_NumSentBytes += msg.data->GetLength ();
337 			switch (msg.deliveryType)
338 			{
339 				case eDeliveryTypeLocal:
340 					HandleI2NPMessage (msg.data);
341 				break;
342 				case eDeliveryTypeTunnel:
343 					i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data));
344 				break;
345 				case eDeliveryTypeRouter:
346 					i2p::transport::transports.SendMessage (msg.hash, msg.data);
347 				break;
348 				default:
349 					LogPrint (eLogError, "Tunnel: Unknown delivery type ", (int)msg.deliveryType);
350 			}
351 		}
352 	}
353 
Print(std::stringstream & s) const354 	void ZeroHopsOutboundTunnel::Print (std::stringstream& s) const
355 	{
356 		s << GetTunnelID () << ":me &#8658; ";
357 	}
358 
359 	Tunnels tunnels;
360 
Tunnels()361 	Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr),
362 		m_NumSuccesiveTunnelCreations (0), m_NumFailedTunnelCreations (0)
363 	{
364 	}
365 
~Tunnels()366 	Tunnels::~Tunnels ()
367 	{
368 	}
369 
GetTunnel(uint32_t tunnelID)370 	std::shared_ptr<TunnelBase> Tunnels::GetTunnel (uint32_t tunnelID)
371 	{
372 		auto it = m_Tunnels.find(tunnelID);
373 		if (it != m_Tunnels.end ())
374 			return it->second;
375 		return nullptr;
376 	}
377 
GetPendingInboundTunnel(uint32_t replyMsgID)378 	std::shared_ptr<InboundTunnel> Tunnels::GetPendingInboundTunnel (uint32_t replyMsgID)
379 	{
380 		return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels);
381 	}
382 
GetPendingOutboundTunnel(uint32_t replyMsgID)383 	std::shared_ptr<OutboundTunnel> Tunnels::GetPendingOutboundTunnel (uint32_t replyMsgID)
384 	{
385 		return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels);
386 	}
387 
388 	template<class TTunnel>
GetPendingTunnel(uint32_t replyMsgID,const std::map<uint32_t,std::shared_ptr<TTunnel>> & pendingTunnels)389 	std::shared_ptr<TTunnel> Tunnels::GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels)
390 	{
391 		auto it = pendingTunnels.find(replyMsgID);
392 		if (it != pendingTunnels.end () && it->second->GetState () == eTunnelStatePending)
393 		{
394 			it->second->SetState (eTunnelStateBuildReplyReceived);
395 			return it->second;
396 		}
397 		return nullptr;
398 	}
399 
GetNextInboundTunnel()400 	std::shared_ptr<InboundTunnel> Tunnels::GetNextInboundTunnel ()
401 	{
402 		std::shared_ptr<InboundTunnel> tunnel;
403 		size_t minReceived = 0;
404 		for (const auto& it : m_InboundTunnels)
405 		{
406 			if (!it->IsEstablished ()) continue;
407 			if (!tunnel || it->GetNumReceivedBytes () < minReceived)
408 			{
409 				tunnel = it;
410 				minReceived = it->GetNumReceivedBytes ();
411 			}
412 		}
413 		return tunnel;
414 	}
415 
GetNextOutboundTunnel()416 	std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
417 	{
418 		if (m_OutboundTunnels.empty ()) return nullptr;
419 		uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0;
420 		std::shared_ptr<OutboundTunnel> tunnel;
421 		for (const auto& it: m_OutboundTunnels)
422 		{
423 			if (it->IsEstablished ())
424 			{
425 				tunnel = it;
426 				i++;
427 			}
428 			if (i > ind && tunnel) break;
429 		}
430 		return tunnel;
431 	}
432 
CreateTunnelPool(int numInboundHops,int numOutboundHops,int numInboundTunnels,int numOutboundTunnels)433 	std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops,
434 		int numOutboundHops, int numInboundTunnels, int numOutboundTunnels)
435 	{
436 		auto pool = std::make_shared<TunnelPool> (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels);
437 		std::unique_lock<std::mutex> l(m_PoolsMutex);
438 		m_Pools.push_back (pool);
439 		return pool;
440 	}
441 
DeleteTunnelPool(std::shared_ptr<TunnelPool> pool)442 	void Tunnels::DeleteTunnelPool (std::shared_ptr<TunnelPool> pool)
443 	{
444 		if (pool)
445 		{
446 			StopTunnelPool (pool);
447 			{
448 				std::unique_lock<std::mutex> l(m_PoolsMutex);
449 				m_Pools.remove (pool);
450 			}
451 		}
452 	}
453 
StopTunnelPool(std::shared_ptr<TunnelPool> pool)454 	void Tunnels::StopTunnelPool (std::shared_ptr<TunnelPool> pool)
455 	{
456 		if (pool)
457 		{
458 			pool->SetActive (false);
459 			pool->DetachTunnels ();
460 		}
461 	}
462 
AddTransitTunnel(std::shared_ptr<TransitTunnel> tunnel)463 	void Tunnels::AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel)
464 	{
465 		if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second)
466 			m_TransitTunnels.push_back (tunnel);
467 		else
468 			LogPrint (eLogError, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " already exists");
469 	}
470 
Start()471 	void Tunnels::Start ()
472 	{
473 		m_IsRunning = true;
474 		m_Thread = new std::thread (std::bind (&Tunnels::Run, this));
475 	}
476 
Stop()477 	void Tunnels::Stop ()
478 	{
479 		m_IsRunning = false;
480 		m_Queue.WakeUp ();
481 		if (m_Thread)
482 		{
483 			m_Thread->join ();
484 			delete m_Thread;
485 			m_Thread = 0;
486 		}
487 	}
488 
Run()489 	void Tunnels::Run ()
490 	{
491 		i2p::util::SetThreadName("Tunnels");
492 		std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready
493 
494 		uint64_t lastTs = 0, lastPoolsTs = 0, lastMemoryPoolTs = 0;
495 		while (m_IsRunning)
496 		{
497 			try
498 			{
499 				auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec
500 				if (msg)
501 				{
502 					uint32_t prevTunnelID = 0, tunnelID = 0;
503 					std::shared_ptr<TunnelBase> prevTunnel;
504 					do
505 					{
506 						std::shared_ptr<TunnelBase> tunnel;
507 						uint8_t typeID = msg->GetTypeID ();
508 						switch (typeID)
509 						{
510 							case eI2NPTunnelData:
511 							case eI2NPTunnelGateway:
512 							{
513 								tunnelID = bufbe32toh (msg->GetPayload ());
514 								if (tunnelID == prevTunnelID)
515 									tunnel = prevTunnel;
516 								else if (prevTunnel)
517 									prevTunnel->FlushTunnelDataMsgs ();
518 
519 								if (!tunnel)
520 									tunnel = GetTunnel (tunnelID);
521 								if (tunnel)
522 								{
523 									if (typeID == eI2NPTunnelData)
524 										tunnel->HandleTunnelDataMsg (std::move (msg));
525 									else // tunnel gateway assumed
526 										HandleTunnelGatewayMsg (tunnel, msg);
527 								}
528 								else
529 									LogPrint (eLogWarning, "Tunnel: Tunnel not found, tunnelID=", tunnelID, " previousTunnelID=", prevTunnelID, " type=", (int)typeID);
530 
531 								break;
532 							}
533 							case eI2NPVariableTunnelBuild:
534 							case eI2NPVariableTunnelBuildReply:
535 							case eI2NPShortTunnelBuild:
536 							case eI2NPShortTunnelBuildReply:
537 							case eI2NPTunnelBuild:
538 							case eI2NPTunnelBuildReply:
539 								HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
540 							break;
541 							default:
542 								LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID);
543 						}
544 
545 						msg = m_Queue.Get ();
546 						if (msg)
547 						{
548 							prevTunnelID = tunnelID;
549 							prevTunnel = tunnel;
550 						}
551 						else if (tunnel)
552 							tunnel->FlushTunnelDataMsgs ();
553 					}
554 					while (msg);
555 				}
556 
557 				if (i2p::transport::transports.IsOnline())
558 				{
559 					uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
560 					if (ts - lastTs >= 15) // manage tunnels every 15 seconds
561 					{
562 						ManageTunnels ();
563 						lastTs = ts;
564 					}
565 					if (ts - lastPoolsTs >= 5) // manage pools every 5 seconds
566 					{
567 						ManageTunnelPools (ts);
568 						lastPoolsTs = ts;
569 					}
570 					if (ts - lastMemoryPoolTs >= 120) // manage memory pool every 2 minutes
571 					{
572 						m_I2NPTunnelEndpointMessagesMemoryPool.CleanUpMt ();
573 						m_I2NPTunnelMessagesMemoryPool.CleanUpMt ();
574 						lastMemoryPoolTs = ts;
575 					}
576 				}
577 			}
578 			catch (std::exception& ex)
579 			{
580 				LogPrint (eLogError, "Tunnel: Runtime exception: ", ex.what ());
581 			}
582 		}
583 	}
584 
HandleTunnelGatewayMsg(std::shared_ptr<TunnelBase> tunnel,std::shared_ptr<I2NPMessage> msg)585 	void Tunnels::HandleTunnelGatewayMsg (std::shared_ptr<TunnelBase> tunnel, std::shared_ptr<I2NPMessage> msg)
586 	{
587 		if (!tunnel)
588 		{
589 			LogPrint (eLogError, "Tunnel: Missing tunnel for gateway");
590 			return;
591 		}
592 		const uint8_t * payload = msg->GetPayload ();
593 		uint16_t len = bufbe16toh(payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET);
594 		// we make payload as new I2NP message to send
595 		msg->offset += I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE;
596 		if (msg->offset + len > msg->len)
597 		{
598 			LogPrint (eLogError, "Tunnel: Gateway payload ", (int)len, " exceeds message length ", (int)msg->len);
599 			return;
600 		}
601 		msg->len = msg->offset + len;
602 		auto typeID = msg->GetTypeID ();
603 		LogPrint (eLogDebug, "Tunnel: Gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID);
604 
605 		if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply)
606 			// transit DatabaseStore my contain new/updated RI
607 			// or DatabaseSearchReply with new routers
608 			i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg));
609 		tunnel->SendTunnelDataMsg (msg);
610 	}
611 
ManageTunnels()612 	void Tunnels::ManageTunnels ()
613 	{
614 		ManagePendingTunnels ();
615 		ManageInboundTunnels ();
616 		ManageOutboundTunnels ();
617 		ManageTransitTunnels ();
618 	}
619 
ManagePendingTunnels()620 	void Tunnels::ManagePendingTunnels ()
621 	{
622 		ManagePendingTunnels (m_PendingInboundTunnels);
623 		ManagePendingTunnels (m_PendingOutboundTunnels);
624 	}
625 
626 	template<class PendingTunnels>
ManagePendingTunnels(PendingTunnels & pendingTunnels)627 	void Tunnels::ManagePendingTunnels (PendingTunnels& pendingTunnels)
628 	{
629 		// check pending tunnel. delete failed or timeout
630 		uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
631 		for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();)
632 		{
633 			auto tunnel = it->second;
634 			switch (tunnel->GetState ())
635 			{
636 				case eTunnelStatePending:
637 					if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT)
638 					{
639 						LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " timeout, deleted");
640 						// update stats
641 						auto config = tunnel->GetTunnelConfig ();
642 						if (config)
643 						{
644 							auto hop = config->GetFirstHop ();
645 							while (hop)
646 							{
647 								if (hop->ident)
648 								{
649 									auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
650 									if (profile)
651 										profile->TunnelNonReplied ();
652 								}
653 								hop = hop->next;
654 							}
655 						}
656 						// delete
657 						it = pendingTunnels.erase (it);
658 						m_NumFailedTunnelCreations++;
659 					}
660 					else
661 						++it;
662 				break;
663 				case eTunnelStateBuildFailed:
664 					LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " failed, deleted");
665 					it = pendingTunnels.erase (it);
666 					m_NumFailedTunnelCreations++;
667 				break;
668 				case eTunnelStateBuildReplyReceived:
669 					// intermediate state, will be either established of build failed
670 					++it;
671 				break;
672 				default:
673 					// success
674 					it = pendingTunnels.erase (it);
675 					m_NumSuccesiveTunnelCreations++;
676 			}
677 		}
678 	}
679 
ManageOutboundTunnels()680 	void Tunnels::ManageOutboundTunnels ()
681 	{
682 		uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
683 		{
684 			for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();)
685 			{
686 				auto tunnel = *it;
687 				if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
688 				{
689 					LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired");
690 					auto pool = tunnel->GetTunnelPool ();
691 					if (pool)
692 						pool->TunnelExpired (tunnel);
693 					// we don't have outbound tunnels in m_Tunnels
694 					it = m_OutboundTunnels.erase (it);
695 				}
696 				else
697 				{
698 					if (tunnel->IsEstablished ())
699 					{
700 						if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
701 						{
702 							auto pool = tunnel->GetTunnelPool ();
703 							// let it die if the tunnel pool has been reconfigured and this is old
704 							if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops())
705 							{
706 								tunnel->SetRecreated (true);
707 								pool->RecreateOutboundTunnel (tunnel);
708 							}
709 						}
710 						if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
711 							tunnel->SetState (eTunnelStateExpiring);
712 					}
713 					++it;
714 				}
715 			}
716 		}
717 
718 		if (m_OutboundTunnels.size () < 3)
719 		{
720 			// trying to create one more oubound tunnel
721 			auto inboundTunnel = GetNextInboundTunnel ();
722 			auto router = i2p::transport::transports.RoutesRestricted() ?
723 				i2p::transport::transports.GetRestrictedPeer() :
724 				i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us
725 			if (!inboundTunnel || !router) return;
726 			LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel");
727 			CreateTunnel<OutboundTunnel> (
728 				std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () },
729 					inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash (), false), nullptr
730 			);
731 		}
732 	}
733 
ManageInboundTunnels()734 	void Tunnels::ManageInboundTunnels ()
735 	{
736 		uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
737 		{
738 			for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
739 			{
740 				auto tunnel = *it;
741 				if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
742 				{
743 					LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired");
744 					auto pool = tunnel->GetTunnelPool ();
745 					if (pool)
746 						pool->TunnelExpired (tunnel);
747 					m_Tunnels.erase (tunnel->GetTunnelID ());
748 					it = m_InboundTunnels.erase (it);
749 				}
750 				else
751 				{
752 					if (tunnel->IsEstablished ())
753 					{
754 						if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
755 						{
756 							auto pool = tunnel->GetTunnelPool ();
757 							// let it die if the tunnel pool was reconfigured and has different number of hops
758 							if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
759 							{
760 								tunnel->SetRecreated (true);
761 								pool->RecreateInboundTunnel (tunnel);
762 							}
763 						}
764 
765 						if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
766 							tunnel->SetState (eTunnelStateExpiring);
767 						else // we don't need to cleanup expiring tunnels
768 							tunnel->Cleanup ();
769 					}
770 					it++;
771 				}
772 			}
773 		}
774 
775 		if (m_InboundTunnels.empty ())
776 		{
777 			LogPrint (eLogDebug, "Tunnel: Creating zero hops inbound tunnel");
778 			CreateZeroHopsInboundTunnel (nullptr);
779 			CreateZeroHopsOutboundTunnel (nullptr);
780 			if (!m_ExploratoryPool)
781 			{
782 				int ibLen; i2p::config::GetOption("exploratory.inbound.length", ibLen);
783 				int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen);
784 				int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum);
785 				int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum);
786 				m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum);
787 				m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ());
788 			}
789 			return;
790 		}
791 
792 		if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3)
793 		{
794 			// trying to create one more inbound tunnel
795 			auto router = i2p::transport::transports.RoutesRestricted() ?
796 				i2p::transport::transports.GetRestrictedPeer() :
797 				// should be reachable by us because we send build request directly
798 				i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false);
799 			if (!router) {
800 				LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel");
801 				return;
802 			}
803 			LogPrint (eLogDebug, "Tunnel: Creating one hop inbound tunnel");
804 			CreateTunnel<InboundTunnel> (
805 				std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () }, false), nullptr
806 			);
807 		}
808 	}
809 
ManageTransitTunnels()810 	void Tunnels::ManageTransitTunnels ()
811 	{
812 		uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
813 		for (auto it = m_TransitTunnels.begin (); it != m_TransitTunnels.end ();)
814 		{
815 			auto tunnel = *it;
816 			if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
817 			{
818 				LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tunnel->GetTunnelID (), " expired");
819 				m_Tunnels.erase (tunnel->GetTunnelID ());
820 				it = m_TransitTunnels.erase (it);
821 			}
822 			else
823 			{
824 				tunnel->Cleanup ();
825 				it++;
826 			}
827 		}
828 	}
829 
ManageTunnelPools(uint64_t ts)830 	void Tunnels::ManageTunnelPools (uint64_t ts)
831 	{
832 		std::unique_lock<std::mutex> l(m_PoolsMutex);
833 		for (auto& pool : m_Pools)
834 		{
835 			if (pool && pool->IsActive ())
836 				pool->ManageTunnels (ts);
837 		}
838 	}
839 
PostTunnelData(std::shared_ptr<I2NPMessage> msg)840 	void Tunnels::PostTunnelData (std::shared_ptr<I2NPMessage> msg)
841 	{
842 		if (msg) m_Queue.Put (msg);
843 	}
844 
PostTunnelData(const std::vector<std::shared_ptr<I2NPMessage>> & msgs)845 	void Tunnels::PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
846 	{
847 		m_Queue.Put (msgs);
848 	}
849 
850 	template<class TTunnel>
CreateTunnel(std::shared_ptr<TunnelConfig> config,std::shared_ptr<TunnelPool> pool,std::shared_ptr<OutboundTunnel> outboundTunnel)851 	std::shared_ptr<TTunnel> Tunnels::CreateTunnel (std::shared_ptr<TunnelConfig> config,
852 	    std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel)
853 	{
854 		auto newTunnel = std::make_shared<TTunnel> (config);
855 		newTunnel->SetTunnelPool (pool);
856 		uint32_t replyMsgID;
857 		RAND_bytes ((uint8_t *)&replyMsgID, 4);
858 		AddPendingTunnel (replyMsgID, newTunnel);
859 		newTunnel->Build (replyMsgID, outboundTunnel);
860 		return newTunnel;
861 	}
862 
CreateInboundTunnel(std::shared_ptr<TunnelConfig> config,std::shared_ptr<TunnelPool> pool,std::shared_ptr<OutboundTunnel> outboundTunnel)863 	std::shared_ptr<InboundTunnel> Tunnels::CreateInboundTunnel (std::shared_ptr<TunnelConfig> config,
864 		std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel)
865 	{
866 		if (config)
867 			return CreateTunnel<InboundTunnel>(config, pool, outboundTunnel);
868 		else
869 			return CreateZeroHopsInboundTunnel (pool);
870 	}
871 
CreateOutboundTunnel(std::shared_ptr<TunnelConfig> config,std::shared_ptr<TunnelPool> pool)872 	std::shared_ptr<OutboundTunnel> Tunnels::CreateOutboundTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<TunnelPool> pool)
873 	{
874 		if (config)
875 			return CreateTunnel<OutboundTunnel>(config, pool);
876 		else
877 			return CreateZeroHopsOutboundTunnel (pool);
878 	}
879 
AddPendingTunnel(uint32_t replyMsgID,std::shared_ptr<InboundTunnel> tunnel)880 	void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel)
881 	{
882 		m_PendingInboundTunnels[replyMsgID] = tunnel;
883 	}
884 
AddPendingTunnel(uint32_t replyMsgID,std::shared_ptr<OutboundTunnel> tunnel)885 	void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> tunnel)
886 	{
887 		m_PendingOutboundTunnels[replyMsgID] = tunnel;
888 	}
889 
AddOutboundTunnel(std::shared_ptr<OutboundTunnel> newTunnel)890 	void Tunnels::AddOutboundTunnel (std::shared_ptr<OutboundTunnel> newTunnel)
891 	{
892 		// we don't need to insert it to m_Tunnels
893 		m_OutboundTunnels.push_back (newTunnel);
894 		auto pool = newTunnel->GetTunnelPool ();
895 		if (pool && pool->IsActive ())
896 			pool->TunnelCreated (newTunnel);
897 		else
898 			newTunnel->SetTunnelPool (nullptr);
899 	}
900 
AddInboundTunnel(std::shared_ptr<InboundTunnel> newTunnel)901 	void Tunnels::AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel)
902 	{
903 		if (m_Tunnels.emplace (newTunnel->GetTunnelID (), newTunnel).second)
904 		{
905 			m_InboundTunnels.push_back (newTunnel);
906 			auto pool = newTunnel->GetTunnelPool ();
907 			if (!pool)
908 			{
909 				// build symmetric outbound tunnel
910 				CreateTunnel<OutboundTunnel> (std::make_shared<TunnelConfig>(newTunnel->GetInvertedPeers (),
911 						newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash (), false), nullptr,
912 					GetNextOutboundTunnel ());
913 			}
914 			else
915 			{
916 				if (pool->IsActive ())
917 					pool->TunnelCreated (newTunnel);
918 				else
919 					newTunnel->SetTunnelPool (nullptr);
920 			}
921 		}
922 		else
923 			LogPrint (eLogError, "Tunnel: Tunnel with id ", newTunnel->GetTunnelID (), " already exists");
924 	}
925 
926 
CreateZeroHopsInboundTunnel(std::shared_ptr<TunnelPool> pool)927 	std::shared_ptr<ZeroHopsInboundTunnel> Tunnels::CreateZeroHopsInboundTunnel (std::shared_ptr<TunnelPool> pool)
928 	{
929 		auto inboundTunnel = std::make_shared<ZeroHopsInboundTunnel> ();
930 		inboundTunnel->SetTunnelPool (pool);
931 		inboundTunnel->SetState (eTunnelStateEstablished);
932 		m_InboundTunnels.push_back (inboundTunnel);
933 		m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel;
934 		return inboundTunnel;
935 	}
936 
CreateZeroHopsOutboundTunnel(std::shared_ptr<TunnelPool> pool)937 	std::shared_ptr<ZeroHopsOutboundTunnel> Tunnels::CreateZeroHopsOutboundTunnel (std::shared_ptr<TunnelPool> pool)
938 	{
939 		auto outboundTunnel = std::make_shared<ZeroHopsOutboundTunnel> ();
940 		outboundTunnel->SetTunnelPool (pool);
941 		outboundTunnel->SetState (eTunnelStateEstablished);
942 		m_OutboundTunnels.push_back (outboundTunnel);
943 		// we don't insert into m_Tunnels
944 		return outboundTunnel;
945 	}
946 
NewI2NPTunnelMessage(bool endpoint)947 	std::shared_ptr<I2NPMessage> Tunnels::NewI2NPTunnelMessage (bool endpoint)
948 	{
949 		if (endpoint)
950 		{
951 			// should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet
952 			auto msg = m_I2NPTunnelEndpointMessagesMemoryPool.AcquireSharedMt ();
953 			msg->Align (6);
954 			msg->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header
955 			return msg;
956 		}
957 		else
958 		{
959 			auto msg = m_I2NPTunnelMessagesMemoryPool.AcquireSharedMt ();
960 			msg->Align (12);
961 			return msg;
962 		}
963 	}
964 
GetTransitTunnelsExpirationTimeout()965 	int Tunnels::GetTransitTunnelsExpirationTimeout ()
966 	{
967 		int timeout = 0;
968 		uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
969 		// TODO: possible race condition with I2PControl
970 		for (const auto& it : m_TransitTunnels)
971 		{
972 			int t = it->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT - ts;
973 			if (t > timeout) timeout = t;
974 		}
975 		return timeout;
976 	}
977 
CountTransitTunnels() const978 	size_t Tunnels::CountTransitTunnels() const
979 	{
980 		// TODO: locking
981 		return m_TransitTunnels.size();
982 	}
983 
CountInboundTunnels() const984 	size_t Tunnels::CountInboundTunnels() const
985 	{
986 		// TODO: locking
987 		return m_InboundTunnels.size();
988 	}
989 
CountOutboundTunnels() const990 	size_t Tunnels::CountOutboundTunnels() const
991 	{
992 		// TODO: locking
993 		return m_OutboundTunnels.size();
994 	}
995 }
996 }
997