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 << " ⇒ "; 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 << " ⇒ " << 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 << " ⇒ " << 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 << " ⇒ "; 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 ⇒ "; 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