2020-05-22 16:18:41 +03:00
|
|
|
/*
|
2023-01-05 19:59:47 +03:00
|
|
|
* Copyright (c) 2013-2023, The PurpleI2P Project
|
2020-05-22 16:18:41 +03:00
|
|
|
*
|
|
|
|
* This file is part of Purple i2pd project and licensed under BSD3
|
|
|
|
*
|
|
|
|
* See full license text in LICENSE file at top of project tree
|
|
|
|
*/
|
|
|
|
|
2014-12-31 17:14:53 +03:00
|
|
|
#include <string.h>
|
2014-01-09 23:56:07 +04:00
|
|
|
#include "I2PEndian.h"
|
2020-01-17 09:10:15 +03:00
|
|
|
#include <random>
|
2014-01-10 02:55:53 +04:00
|
|
|
#include <thread>
|
2014-08-16 22:35:35 +04:00
|
|
|
#include <algorithm>
|
2018-01-06 06:48:51 +03:00
|
|
|
#include <vector>
|
2016-05-11 22:12:38 +03:00
|
|
|
#include "Crypto.h"
|
2013-12-07 04:02:49 +04:00
|
|
|
#include "RouterContext.h"
|
|
|
|
#include "Log.h"
|
|
|
|
#include "Timestamp.h"
|
|
|
|
#include "I2NPProtocol.h"
|
|
|
|
#include "Transports.h"
|
2017-04-22 03:04:16 +03:00
|
|
|
#include "NetDb.hpp"
|
2017-02-28 23:58:53 +03:00
|
|
|
#include "Config.h"
|
2013-12-07 04:02:49 +04:00
|
|
|
#include "Tunnel.h"
|
2016-11-01 17:26:40 +03:00
|
|
|
#include "TunnelPool.h"
|
2020-12-07 06:22:16 +03:00
|
|
|
#include "util.h"
|
2021-07-10 21:33:23 +03:00
|
|
|
#include "ECIESX25519AEADRatchetSession.h"
|
2013-12-07 04:02:49 +04:00
|
|
|
|
|
|
|
namespace i2p
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2013-12-07 04:02:49 +04:00
|
|
|
namespace tunnel
|
2018-01-06 06:48:51 +03:00
|
|
|
{
|
|
|
|
Tunnel::Tunnel (std::shared_ptr<const TunnelConfig> config):
|
2015-11-03 17:15:49 +03:00
|
|
|
TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()),
|
2021-11-27 23:30:35 +03:00
|
|
|
m_Config (config), m_IsShortBuildMessage (false), m_Pool (nullptr),
|
2021-11-05 21:51:24 +03:00
|
|
|
m_State (eTunnelStatePending), m_FarEndTransports (i2p::data::RouterInfo::eAllTransports),
|
2021-10-06 02:38:33 +03:00
|
|
|
m_IsRecreated (false), m_Latency (0)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
|
|
|
Tunnel::~Tunnel ()
|
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2014-08-16 22:35:35 +04:00
|
|
|
auto numHops = m_Config->GetNumHops ();
|
2021-07-10 02:26:14 +03:00
|
|
|
const int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS;
|
2021-01-14 19:24:03 +03:00
|
|
|
auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage ();
|
2013-12-07 04:02:49 +04:00
|
|
|
*msg->GetPayload () = numRecords;
|
2021-11-27 23:30:35 +03:00
|
|
|
const size_t recordSize = m_Config->IsShort () ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
|
2021-07-10 02:26:14 +03:00
|
|
|
msg->len += numRecords*recordSize + 1;
|
2014-08-16 22:35:35 +04:00
|
|
|
// shuffle records
|
|
|
|
std::vector<int> recordIndicies;
|
|
|
|
for (int i = 0; i < numRecords; i++) recordIndicies.push_back(i);
|
2020-01-17 09:10:15 +03:00
|
|
|
std::shuffle (recordIndicies.begin(), recordIndicies.end(), std::mt19937(std::random_device()()));
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2014-08-16 22:35:35 +04:00
|
|
|
// create real records
|
2018-01-06 06:48:51 +03:00
|
|
|
uint8_t * records = msg->GetPayload () + 1;
|
2013-12-07 04:02:49 +04:00
|
|
|
TunnelHopConfig * hop = m_Config->GetFirstHop ();
|
|
|
|
int i = 0;
|
|
|
|
while (hop)
|
|
|
|
{
|
2015-11-03 17:15:49 +03:00
|
|
|
uint32_t msgID;
|
2018-01-06 06:48:51 +03:00
|
|
|
if (hop->next) // we set replyMsgID for last hop only
|
2015-11-03 17:15:49 +03:00
|
|
|
RAND_bytes ((uint8_t *)&msgID, 4);
|
|
|
|
else
|
|
|
|
msgID = replyMsgID;
|
2021-07-09 02:00:25 +03:00
|
|
|
hop->recordIndex = recordIndicies[i]; i++;
|
|
|
|
hop->CreateBuildRequestRecord (records, msgID);
|
2013-12-07 04:02:49 +04:00
|
|
|
hop = hop->next;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
// fill up fake records with random data
|
2014-08-16 22:35:35 +04:00
|
|
|
for (int i = numHops; i < numRecords; i++)
|
2014-06-19 05:24:24 +04:00
|
|
|
{
|
2014-08-16 22:35:35 +04:00
|
|
|
int idx = recordIndicies[i];
|
2021-07-10 02:26:14 +03:00
|
|
|
RAND_bytes (records + idx*recordSize, recordSize);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-08-16 22:35:35 +04:00
|
|
|
|
|
|
|
// decrypt real records
|
2013-12-07 04:02:49 +04:00
|
|
|
hop = m_Config->GetLastHop ()->prev;
|
|
|
|
while (hop)
|
|
|
|
{
|
2014-06-19 03:38:21 +04:00
|
|
|
// decrypt records after current hop
|
|
|
|
TunnelHopConfig * hop1 = hop->next;
|
|
|
|
while (hop1)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2021-07-08 04:16:30 +03:00
|
|
|
hop->DecryptRecord (records, hop1->recordIndex);
|
2014-06-19 03:38:21 +04:00
|
|
|
hop1 = hop1->next;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
hop = hop->prev;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2021-07-20 21:35:02 +03:00
|
|
|
msg->FillI2NPMessageHeader (m_Config->IsShort () ? eI2NPShortTunnelBuild : eI2NPVariableTunnelBuild);
|
2014-08-16 22:35:35 +04:00
|
|
|
|
|
|
|
// send message
|
2013-12-07 04:02:49 +04:00
|
|
|
if (outboundTunnel)
|
2021-07-10 21:33:23 +03:00
|
|
|
{
|
2021-07-11 00:28:18 +03:00
|
|
|
if (m_Config->IsShort ())
|
|
|
|
{
|
|
|
|
auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr;
|
2021-07-28 22:06:24 +03:00
|
|
|
if (ident && ident->GetIdentHash () != outboundTunnel->GetNextIdentHash ()) // don't encrypt if IBGW = OBEP
|
2021-11-27 23:30:35 +03:00
|
|
|
{
|
2021-07-11 00:28:18 +03:00
|
|
|
auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ());
|
2021-07-20 21:35:02 +03:00
|
|
|
if (msg1) msg = msg1;
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg);
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
else
|
2021-07-13 02:40:40 +03:00
|
|
|
{
|
2021-07-29 04:14:03 +03:00
|
|
|
if (m_Config->IsShort () && m_Config->GetLastHop () &&
|
2022-05-20 19:56:05 +03:00
|
|
|
m_Config->GetLastHop ()->ident->GetIdentHash () != m_Config->GetLastHop ()->nextIdent)
|
2021-07-13 02:40:40 +03:00
|
|
|
{
|
|
|
|
// add garlic key/tag for reply
|
|
|
|
uint8_t key[32];
|
|
|
|
uint64_t tag = m_Config->GetLastHop ()->GetGarlicKey (key);
|
2021-07-21 20:08:12 +03:00
|
|
|
if (m_Pool && m_Pool->GetLocalDestination ())
|
2022-03-28 19:15:40 +03:00
|
|
|
m_Pool->GetLocalDestination ()->SubmitECIESx25519Key (key, tag);
|
2021-11-27 23:30:35 +03:00
|
|
|
else
|
2021-07-21 20:08:12 +03:00
|
|
|
i2p::context.AddECIESx25519Key (key, tag);
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
2015-11-24 21:09:12 +03:00
|
|
|
i2p::transport::transports.SendMessage (GetNextIdentHash (), msg);
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2013-12-07 04:02:49 +04:00
|
|
|
bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len)
|
|
|
|
{
|
2015-12-18 09:20:06 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: TunnelBuildResponse ", (int)msg[0], " records.");
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2018-01-06 06:48:51 +03:00
|
|
|
TunnelHopConfig * hop = m_Config->GetLastHop ();
|
2013-12-07 04:02:49 +04:00
|
|
|
while (hop)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2021-07-02 20:20:24 +03:00
|
|
|
// decrypt current hop
|
2021-07-08 23:39:38 +03:00
|
|
|
if (hop->recordIndex >= 0 && hop->recordIndex < msg[0])
|
2021-07-02 20:20:24 +03:00
|
|
|
{
|
2021-07-08 23:39:38 +03:00
|
|
|
if (!hop->DecryptBuildResponseRecord (msg + 1))
|
2021-07-02 20:20:24 +03:00
|
|
|
return false;
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
2021-07-02 20:20:24 +03:00
|
|
|
else
|
|
|
|
{
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogWarning, "Tunnel: Hop index ", hop->recordIndex, " is out of range");
|
2021-07-02 20:20:24 +03:00
|
|
|
return false;
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// decrypt records before current hop
|
2021-07-02 20:20:24 +03:00
|
|
|
TunnelHopConfig * hop1 = hop->prev;
|
2014-06-19 03:38:21 +04:00
|
|
|
while (hop1)
|
|
|
|
{
|
2014-06-19 05:24:24 +04:00
|
|
|
auto idx = hop1->recordIndex;
|
|
|
|
if (idx >= 0 && idx < msg[0])
|
2021-07-08 04:16:30 +03:00
|
|
|
hop->DecryptRecord (msg + 1, idx);
|
2014-06-19 05:24:24 +04:00
|
|
|
else
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogWarning, "Tunnel: Hop index ", idx, " is out of range");
|
2014-06-19 03:38:21 +04:00
|
|
|
hop1 = hop1->prev;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
hop = hop->prev;
|
|
|
|
}
|
|
|
|
|
2014-07-27 04:56:42 +04:00
|
|
|
bool established = true;
|
2021-11-13 23:11:59 +03:00
|
|
|
size_t numHops = 0;
|
2014-06-19 05:24:24 +04:00
|
|
|
hop = m_Config->GetFirstHop ();
|
|
|
|
while (hop)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2021-07-08 23:39:38 +03:00
|
|
|
uint8_t ret = hop->GetRetCode (msg + 1);
|
2015-12-18 09:20:06 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
|
2015-11-03 17:15:49 +03:00
|
|
|
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
|
|
|
if (profile)
|
|
|
|
profile->TunnelBuildResponse (ret);
|
2018-01-06 06:48:51 +03:00
|
|
|
if (ret)
|
2013-12-07 04:02:49 +04:00
|
|
|
// if any of participants declined the tunnel is not established
|
2018-01-06 06:48:51 +03:00
|
|
|
established = false;
|
2014-06-19 05:24:24 +04:00
|
|
|
hop = hop->next;
|
2021-11-13 23:11:59 +03:00
|
|
|
numHops++;
|
2013-12-07 04:02:49 +04:00
|
|
|
}
|
2018-01-06 06:48:51 +03:00
|
|
|
if (established)
|
2014-05-10 03:34:12 +04:00
|
|
|
{
|
2015-11-03 17:15:49 +03:00
|
|
|
// create tunnel decryptions from layer and iv keys in reverse order
|
2021-11-13 23:11:59 +03:00
|
|
|
m_Hops.resize (numHops);
|
2015-11-03 17:15:49 +03:00
|
|
|
hop = m_Config->GetLastHop ();
|
2021-11-27 23:30:35 +03:00
|
|
|
int i = 0;
|
2014-05-10 03:34:12 +04:00
|
|
|
while (hop)
|
|
|
|
{
|
2021-11-13 23:11:59 +03:00
|
|
|
m_Hops[i].ident = hop->ident;
|
|
|
|
m_Hops[i].decryption.SetKeys (hop->layerKey, hop->ivKey);
|
2015-11-03 17:15:49 +03:00
|
|
|
hop = hop->prev;
|
2021-11-13 23:11:59 +03:00
|
|
|
i++;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2021-10-06 02:38:33 +03:00
|
|
|
m_IsShortBuildMessage = m_Config->IsShort ();
|
|
|
|
m_FarEndTransports = m_Config->GetFarEndTransports ();
|
2015-11-03 17:15:49 +03:00
|
|
|
m_Config = nullptr;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-07-27 04:56:42 +04:00
|
|
|
if (established) m_State = eTunnelStateEstablished;
|
|
|
|
return established;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2016-11-15 18:20:09 +03:00
|
|
|
bool Tunnel::LatencyFitsRange(uint64_t lower, uint64_t upper) const
|
|
|
|
{
|
|
|
|
auto latency = GetMeanLatency();
|
|
|
|
return latency >= lower && latency <= upper;
|
|
|
|
}
|
2018-01-06 06:48:51 +03:00
|
|
|
|
2015-06-25 05:19:56 +03:00
|
|
|
void Tunnel::EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2015-06-25 05:19:56 +03:00
|
|
|
const uint8_t * inPayload = in->GetPayload () + 4;
|
|
|
|
uint8_t * outPayload = out->GetPayload () + 4;
|
2015-11-03 17:15:49 +03:00
|
|
|
for (auto& it: m_Hops)
|
|
|
|
{
|
2021-11-13 23:11:59 +03:00
|
|
|
it.decryption.Decrypt (inPayload, outPayload);
|
2018-01-06 06:48:51 +03:00
|
|
|
inPayload = outPayload;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
2015-01-24 00:26:39 +03:00
|
|
|
|
2015-06-19 21:38:31 +03:00
|
|
|
void Tunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
|
2015-01-24 00:26:39 +03:00
|
|
|
{
|
2016-01-18 03:00:00 +03:00
|
|
|
LogPrint (eLogWarning, "Tunnel: Can't send I2NP messages without delivery instructions");
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2015-01-24 00:26:39 +03:00
|
|
|
|
2015-11-03 17:15:49 +03:00
|
|
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetPeers () const
|
|
|
|
{
|
|
|
|
auto peers = GetInvertedPeers ();
|
2016-08-11 12:25:26 +03:00
|
|
|
std::reverse (peers.begin (), peers.end ());
|
2015-11-03 17:15:49 +03:00
|
|
|
return peers;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2015-11-03 17:15:49 +03:00
|
|
|
|
|
|
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > Tunnel::GetInvertedPeers () const
|
|
|
|
{
|
|
|
|
// hops are in inverted order
|
|
|
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > ret;
|
2021-11-13 23:11:59 +03:00
|
|
|
for (const auto& it: m_Hops)
|
|
|
|
ret.push_back (it.ident);
|
2016-08-11 12:25:26 +03:00
|
|
|
return ret;
|
|
|
|
}
|
2015-12-10 03:07:12 +03:00
|
|
|
|
2016-11-01 17:26:40 +03:00
|
|
|
void Tunnel::SetState(TunnelState state)
|
|
|
|
{
|
|
|
|
m_State = state;
|
|
|
|
}
|
2018-01-06 06:48:51 +03:00
|
|
|
|
2022-05-01 23:25:08 +03:00
|
|
|
void Tunnel::VisitTunnelHops(TunnelHopVisitor v)
|
2015-12-10 03:07:12 +03:00
|
|
|
{
|
2022-05-01 23:25:08 +03:00
|
|
|
// hops are in inverted order, we must return in direct order
|
2016-10-31 22:13:43 +03:00
|
|
|
for (auto it = m_Hops.rbegin (); it != m_Hops.rend (); it++)
|
2022-05-01 23:25:08 +03:00
|
|
|
v((*it).ident);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2021-10-15 21:01:41 +03:00
|
|
|
void InboundTunnel::HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
if (IsFailed ()) SetState (eTunnelStateEstablished); // incoming messages means a tunnel is alive
|
2021-10-15 21:01:41 +03:00
|
|
|
EncryptTunnelMsg (msg, msg);
|
|
|
|
msg->from = shared_from_this ();
|
|
|
|
m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2015-12-10 02:01:42 +03:00
|
|
|
|
2016-03-03 06:41:53 +03:00
|
|
|
ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
|
2016-03-03 15:30:38 +03:00
|
|
|
InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
|
|
|
m_NumReceivedBytes (0)
|
2016-03-03 06:41:53 +03:00
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2016-03-03 06:41:53 +03:00
|
|
|
void ZeroHopsInboundTunnel::SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg)
|
2016-03-03 00:12:02 +03:00
|
|
|
{
|
2016-03-03 15:30:38 +03:00
|
|
|
if (msg)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2016-03-03 15:30:38 +03:00
|
|
|
m_NumReceivedBytes += msg->GetLength ();
|
2016-06-30 04:37:17 +03:00
|
|
|
msg->from = shared_from_this ();
|
2016-03-03 15:30:38 +03:00
|
|
|
HandleI2NPMessage (msg);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
2016-03-03 00:12:02 +03:00
|
|
|
|
2015-06-22 05:29:50 +03:00
|
|
|
void OutboundTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2014-02-20 07:08:57 +04:00
|
|
|
TunnelMessageBlock block;
|
|
|
|
if (gwHash)
|
|
|
|
{
|
|
|
|
block.hash = gwHash;
|
|
|
|
if (gwTunnel)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2014-02-20 07:08:57 +04:00
|
|
|
block.deliveryType = eDeliveryTypeTunnel;
|
|
|
|
block.tunnelID = gwTunnel;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-02-20 07:08:57 +04:00
|
|
|
else
|
|
|
|
block.deliveryType = eDeliveryTypeRouter;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
else
|
2014-02-20 07:08:57 +04:00
|
|
|
block.deliveryType = eDeliveryTypeLocal;
|
2015-06-22 05:29:50 +03:00
|
|
|
block.data = msg;
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2023-04-04 20:19:08 +03:00
|
|
|
SendTunnelDataMsgs ({block});
|
2013-12-07 04:02:49 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2023-04-04 20:19:08 +03:00
|
|
|
void OutboundTunnel::SendTunnelDataMsgs (const std::vector<TunnelMessageBlock>& msgs)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2014-04-03 20:19:12 +04:00
|
|
|
std::unique_lock<std::mutex> l(m_SendMutex);
|
2014-01-21 03:37:51 +04:00
|
|
|
for (auto& it : msgs)
|
2014-02-20 06:24:55 +04:00
|
|
|
m_Gateway.PutTunnelDataMsg (it);
|
2014-01-21 03:37:51 +04:00
|
|
|
m_Gateway.SendBuffer ();
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2021-10-15 21:01:41 +03:00
|
|
|
void OutboundTunnel::HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg)
|
2015-01-21 22:40:48 +03:00
|
|
|
{
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogError, "Tunnel: Incoming message for outbound tunnel ", GetTunnelID ());
|
2015-01-21 22:40:48 +03:00
|
|
|
}
|
2015-12-10 02:01:42 +03:00
|
|
|
|
2016-03-04 00:24:13 +03:00
|
|
|
ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
|
|
|
|
OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
|
|
|
m_NumSentBytes (0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-04-04 20:19:08 +03:00
|
|
|
void ZeroHopsOutboundTunnel::SendTunnelDataMsgs (const std::vector<TunnelMessageBlock>& msgs)
|
2016-03-04 00:24:13 +03:00
|
|
|
{
|
|
|
|
for (auto& msg : msgs)
|
|
|
|
{
|
2020-10-11 21:02:12 +03:00
|
|
|
if (!msg.data) continue;
|
2021-08-01 09:25:02 +03:00
|
|
|
m_NumSentBytes += msg.data->GetLength ();
|
2016-03-04 00:24:13 +03:00
|
|
|
switch (msg.deliveryType)
|
|
|
|
{
|
|
|
|
case eDeliveryTypeLocal:
|
2021-08-01 09:25:02 +03:00
|
|
|
HandleI2NPMessage (msg.data);
|
2016-03-04 00:24:13 +03:00
|
|
|
break;
|
|
|
|
case eDeliveryTypeTunnel:
|
|
|
|
i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data));
|
|
|
|
break;
|
2016-08-11 12:25:26 +03:00
|
|
|
case eDeliveryTypeRouter:
|
2016-03-04 00:24:13 +03:00
|
|
|
i2p::transport::transports.SendMessage (msg.hash, msg.data);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LogPrint (eLogError, "Tunnel: Unknown delivery type ", (int)msg.deliveryType);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2016-03-04 00:24:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-07 04:02:49 +04:00
|
|
|
Tunnels tunnels;
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2023-03-06 04:08:15 +03:00
|
|
|
Tunnels::Tunnels (): m_IsRunning (false), m_Thread (nullptr), m_MaxNumTransitTunnels (DEFAULT_MAX_NUM_TRANSIT_TUNNELS),
|
2023-03-24 23:15:47 +03:00
|
|
|
m_TotalNumSuccesiveTunnelCreations (0), m_TotalNumFailedTunnelCreations (0), // for normal average
|
2023-02-02 05:28:05 +03:00
|
|
|
m_TunnelCreationSuccessRate (TCSR_START_VALUE), m_TunnelCreationAttemptsNum(0)
|
2023-02-11 09:41:51 +03:00
|
|
|
{
|
2013-12-07 04:02:49 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
|
|
|
|
Tunnels::~Tunnels ()
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-03-07 13:06:50 +03:00
|
|
|
DeleteTunnelPool(m_ExploratoryPool);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2016-03-02 04:48:56 +03:00
|
|
|
|
|
|
|
std::shared_ptr<TunnelBase> Tunnels::GetTunnel (uint32_t tunnelID)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-03-02 04:48:56 +03:00
|
|
|
auto it = m_Tunnels.find(tunnelID);
|
|
|
|
if (it != m_Tunnels.end ())
|
2013-12-07 04:02:49 +04:00
|
|
|
return it->second;
|
|
|
|
return nullptr;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
std::shared_ptr<InboundTunnel> Tunnels::GetPendingInboundTunnel (uint32_t replyMsgID)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels);
|
2015-01-26 19:56:10 +03:00
|
|
|
}
|
2018-01-06 06:48:51 +03:00
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
std::shared_ptr<OutboundTunnel> Tunnels::GetPendingOutboundTunnel (uint32_t replyMsgID)
|
2015-01-26 19:56:10 +03:00
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels);
|
|
|
|
}
|
2015-01-26 19:56:10 +03:00
|
|
|
|
2016-08-11 12:25:26 +03:00
|
|
|
template<class TTunnel>
|
2015-01-27 22:55:46 +03:00
|
|
|
std::shared_ptr<TTunnel> Tunnels::GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels)
|
2015-01-26 19:56:10 +03:00
|
|
|
{
|
|
|
|
auto it = pendingTunnels.find(replyMsgID);
|
|
|
|
if (it != pendingTunnels.end () && it->second->GetState () == eTunnelStatePending)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
|
|
|
it->second->SetState (eTunnelStateBuildReplyReceived);
|
2014-08-18 22:37:19 +04:00
|
|
|
return it->second;
|
2014-09-26 18:15:34 +04:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
return nullptr;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
std::shared_ptr<InboundTunnel> Tunnels::GetNextInboundTunnel ()
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2018-01-06 06:48:51 +03:00
|
|
|
std::shared_ptr<InboundTunnel> tunnel;
|
2013-12-07 04:02:49 +04:00
|
|
|
size_t minReceived = 0;
|
2016-08-10 01:16:24 +03:00
|
|
|
for (const auto& it : m_InboundTunnels)
|
2014-03-21 23:54:55 +04:00
|
|
|
{
|
2016-03-02 19:58:52 +03:00
|
|
|
if (!it->IsEstablished ()) continue;
|
|
|
|
if (!tunnel || it->GetNumReceivedBytes () < minReceived)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-03-02 19:58:52 +03:00
|
|
|
tunnel = it;
|
|
|
|
minReceived = it->GetNumReceivedBytes ();
|
2014-03-21 23:54:55 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
return tunnel;
|
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-06-01 03:00:00 +03:00
|
|
|
if (m_OutboundTunnels.empty ()) return nullptr;
|
2015-11-03 17:15:49 +03:00
|
|
|
uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0;
|
2015-01-27 22:55:46 +03:00
|
|
|
std::shared_ptr<OutboundTunnel> tunnel;
|
2016-08-10 01:16:24 +03:00
|
|
|
for (const auto& it: m_OutboundTunnels)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2014-08-26 18:31:32 +04:00
|
|
|
if (it->IsEstablished ())
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
|
|
|
tunnel = it;
|
2014-03-21 23:54:55 +04:00
|
|
|
i++;
|
|
|
|
}
|
2014-08-29 15:44:12 +04:00
|
|
|
if (i > ind && tunnel) break;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-03-21 23:54:55 +04:00
|
|
|
return tunnel;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-03-15 04:24:12 +04:00
|
|
|
|
2022-05-20 19:56:05 +03:00
|
|
|
std::shared_ptr<TunnelPool> Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops,
|
2022-03-08 06:20:11 +03:00
|
|
|
int numInboundTunnels, int numOutboundTunnels, int inboundVariance, int outboundVariance)
|
2014-03-15 04:24:12 +04:00
|
|
|
{
|
2022-03-08 06:20:11 +03:00
|
|
|
auto pool = std::make_shared<TunnelPool> (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels, inboundVariance, outboundVariance);
|
2014-10-05 19:01:12 +04:00
|
|
|
std::unique_lock<std::mutex> l(m_PoolsMutex);
|
2014-12-10 05:07:54 +03:00
|
|
|
m_Pools.push_back (pool);
|
2014-03-15 04:51:51 +04:00
|
|
|
return pool;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-03-15 04:51:51 +04:00
|
|
|
|
2015-01-20 06:28:13 +03:00
|
|
|
void Tunnels::DeleteTunnelPool (std::shared_ptr<TunnelPool> pool)
|
2014-03-15 04:51:51 +04:00
|
|
|
{
|
2014-10-11 17:47:24 +04:00
|
|
|
if (pool)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2014-10-13 19:21:57 +04:00
|
|
|
StopTunnelPool (pool);
|
2014-12-10 05:07:54 +03:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> l(m_PoolsMutex);
|
|
|
|
m_Pools.remove (pool);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-10-13 19:21:57 +04:00
|
|
|
|
2015-01-20 06:28:13 +03:00
|
|
|
void Tunnels::StopTunnelPool (std::shared_ptr<TunnelPool> pool)
|
2014-10-13 19:21:57 +04:00
|
|
|
{
|
|
|
|
if (pool)
|
|
|
|
{
|
|
|
|
pool->SetActive (false);
|
2014-10-11 17:47:24 +04:00
|
|
|
pool->DetachTunnels ();
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
2018-01-06 06:48:51 +03:00
|
|
|
|
2023-01-05 19:59:47 +03:00
|
|
|
bool Tunnels::AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2021-11-01 05:03:34 +03:00
|
|
|
if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second)
|
2016-03-02 04:48:56 +03:00
|
|
|
m_TransitTunnels.push_back (tunnel);
|
2021-11-01 05:03:34 +03:00
|
|
|
else
|
2023-02-11 09:41:51 +03:00
|
|
|
{
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogError, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " already exists");
|
2023-02-11 09:41:51 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
|
|
|
void Tunnels::Start ()
|
|
|
|
{
|
|
|
|
m_IsRunning = true;
|
|
|
|
m_Thread = new std::thread (std::bind (&Tunnels::Run, this));
|
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2013-12-07 04:02:49 +04:00
|
|
|
void Tunnels::Stop ()
|
|
|
|
{
|
|
|
|
m_IsRunning = false;
|
|
|
|
m_Queue.WakeUp ();
|
|
|
|
if (m_Thread)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2018-01-06 06:48:51 +03:00
|
|
|
m_Thread->join ();
|
2013-12-07 04:02:49 +04:00
|
|
|
delete m_Thread;
|
|
|
|
m_Thread = 0;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
|
|
|
void Tunnels::Run ()
|
|
|
|
{
|
2020-12-07 06:22:16 +03:00
|
|
|
i2p::util::SetThreadName("Tunnels");
|
2014-01-10 02:55:53 +04:00
|
|
|
std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2021-10-21 04:05:22 +03:00
|
|
|
uint64_t lastTs = 0, lastPoolsTs = 0, lastMemoryPoolTs = 0;
|
2013-12-07 04:02:49 +04:00
|
|
|
while (m_IsRunning)
|
|
|
|
{
|
|
|
|
try
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2015-06-19 21:38:31 +03:00
|
|
|
auto msg = m_Queue.GetNextWithTimeout (1000); // 1 sec
|
2015-01-22 05:50:46 +03:00
|
|
|
if (msg)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2022-12-30 01:26:57 +03:00
|
|
|
int numMsgs = 0;
|
2015-01-27 04:49:16 +03:00
|
|
|
uint32_t prevTunnelID = 0, tunnelID = 0;
|
2016-06-29 17:11:14 +03:00
|
|
|
std::shared_ptr<TunnelBase> prevTunnel;
|
2015-01-22 05:50:46 +03:00
|
|
|
do
|
2015-01-21 23:13:46 +03:00
|
|
|
{
|
2016-03-01 23:22:36 +03:00
|
|
|
std::shared_ptr<TunnelBase> tunnel;
|
2015-01-27 04:49:16 +03:00
|
|
|
uint8_t typeID = msg->GetTypeID ();
|
|
|
|
switch (typeID)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2015-01-27 04:49:16 +03:00
|
|
|
case eI2NPTunnelData:
|
|
|
|
case eI2NPTunnelGateway:
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2018-01-06 06:48:51 +03:00
|
|
|
tunnelID = bufbe32toh (msg->GetPayload ());
|
2015-01-27 04:49:16 +03:00
|
|
|
if (tunnelID == prevTunnelID)
|
|
|
|
tunnel = prevTunnel;
|
|
|
|
else if (prevTunnel)
|
2018-01-06 06:48:51 +03:00
|
|
|
prevTunnel->FlushTunnelDataMsgs ();
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2015-01-27 04:49:16 +03:00
|
|
|
if (!tunnel)
|
2016-03-02 04:48:56 +03:00
|
|
|
tunnel = GetTunnel (tunnelID);
|
2015-01-27 04:49:16 +03:00
|
|
|
if (tunnel)
|
|
|
|
{
|
|
|
|
if (typeID == eI2NPTunnelData)
|
2021-10-15 21:01:41 +03:00
|
|
|
tunnel->HandleTunnelDataMsg (std::move (msg));
|
2015-01-27 04:49:16 +03:00
|
|
|
else // tunnel gateway assumed
|
|
|
|
HandleTunnelGatewayMsg (tunnel, msg);
|
|
|
|
}
|
2016-06-29 16:37:21 +03:00
|
|
|
else
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogWarning, "Tunnel: Tunnel not found, tunnelID=", tunnelID, " previousTunnelID=", prevTunnelID, " type=", (int)typeID);
|
2016-06-29 17:11:14 +03:00
|
|
|
|
2015-01-27 04:49:16 +03:00
|
|
|
break;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
case eI2NPVariableTunnelBuild:
|
2015-01-27 04:49:16 +03:00
|
|
|
case eI2NPVariableTunnelBuildReply:
|
2021-07-13 02:40:40 +03:00
|
|
|
case eI2NPShortTunnelBuild:
|
|
|
|
case eI2NPShortTunnelBuildReply:
|
2015-01-27 04:49:16 +03:00
|
|
|
case eI2NPTunnelBuild:
|
2021-11-27 23:30:35 +03:00
|
|
|
case eI2NPTunnelBuildReply:
|
2015-01-27 04:49:16 +03:00
|
|
|
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
|
2016-08-11 12:25:26 +03:00
|
|
|
break;
|
2015-01-27 04:49:16 +03:00
|
|
|
default:
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID);
|
2015-01-24 00:26:39 +03:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2022-12-31 02:06:47 +03:00
|
|
|
msg = (numMsgs <= MAX_TUNNEL_MSGS_BATCH_SIZE) ? m_Queue.Get () : nullptr;
|
2015-01-22 05:50:46 +03:00
|
|
|
if (msg)
|
|
|
|
{
|
|
|
|
prevTunnelID = tunnelID;
|
|
|
|
prevTunnel = tunnel;
|
2022-12-30 01:26:57 +03:00
|
|
|
numMsgs++;
|
2015-01-22 05:50:46 +03:00
|
|
|
}
|
|
|
|
else if (tunnel)
|
|
|
|
tunnel->FlushTunnelDataMsgs ();
|
2015-01-21 23:13:46 +03:00
|
|
|
}
|
2015-01-22 05:50:46 +03:00
|
|
|
while (msg);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2020-11-16 03:38:34 +03:00
|
|
|
if (i2p::transport::transports.IsOnline())
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2020-11-16 03:38:34 +03:00
|
|
|
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
2023-02-10 02:32:18 +03:00
|
|
|
if (ts - lastTs >= TUNNEL_MANAGE_INTERVAL || // manage tunnels every 15 seconds
|
2023-02-11 09:41:51 +03:00
|
|
|
ts + TUNNEL_MANAGE_INTERVAL < lastTs)
|
2020-11-16 03:38:34 +03:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
ManageTunnels (ts);
|
2020-11-16 03:38:34 +03:00
|
|
|
lastTs = ts;
|
|
|
|
}
|
2023-03-24 23:15:47 +03:00
|
|
|
if (ts - lastPoolsTs >= TUNNEL_POOLS_MANAGE_INTERVAL || // manage pools every 5 seconds
|
2023-02-11 09:41:51 +03:00
|
|
|
ts + TUNNEL_POOLS_MANAGE_INTERVAL < lastPoolsTs)
|
2020-11-16 03:38:34 +03:00
|
|
|
{
|
|
|
|
ManageTunnelPools (ts);
|
|
|
|
lastPoolsTs = ts;
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
2023-02-10 02:32:18 +03:00
|
|
|
if (ts - lastMemoryPoolTs >= TUNNEL_MEMORY_POOL_MANAGE_INTERVAL ||
|
|
|
|
ts + TUNNEL_MEMORY_POOL_MANAGE_INTERVAL < lastMemoryPoolTs) // manage memory pool every 2 minutes
|
2021-10-21 04:05:22 +03:00
|
|
|
{
|
2021-10-23 02:18:45 +03:00
|
|
|
m_I2NPTunnelEndpointMessagesMemoryPool.CleanUpMt ();
|
2021-10-21 04:05:22 +03:00
|
|
|
m_I2NPTunnelMessagesMemoryPool.CleanUpMt ();
|
|
|
|
lastMemoryPoolTs = ts;
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
}
|
|
|
|
catch (std::exception& ex)
|
|
|
|
{
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogError, "Tunnel: Runtime exception: ", ex.what ());
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2016-03-01 23:22:36 +03:00
|
|
|
void Tunnels::HandleTunnelGatewayMsg (std::shared_ptr<TunnelBase> tunnel, std::shared_ptr<I2NPMessage> msg)
|
2015-01-24 00:26:39 +03:00
|
|
|
{
|
|
|
|
if (!tunnel)
|
|
|
|
{
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogError, "Tunnel: Missing tunnel for gateway");
|
2015-01-24 00:26:39 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
const uint8_t * payload = msg->GetPayload ();
|
|
|
|
uint16_t len = bufbe16toh(payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET);
|
|
|
|
// we make payload as new I2NP message to send
|
|
|
|
msg->offset += I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE;
|
2016-01-25 22:31:51 +03:00
|
|
|
if (msg->offset + len > msg->len)
|
|
|
|
{
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogError, "Tunnel: Gateway payload ", (int)len, " exceeds message length ", (int)msg->len);
|
2016-01-25 22:31:51 +03:00
|
|
|
return;
|
|
|
|
}
|
2015-01-24 00:26:39 +03:00
|
|
|
msg->len = msg->offset + len;
|
|
|
|
auto typeID = msg->GetTypeID ();
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID);
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2016-01-05 03:56:46 +03:00
|
|
|
if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply)
|
2018-01-06 06:48:51 +03:00
|
|
|
// transit DatabaseStore my contain new/updated RI
|
2015-01-24 00:26:39 +03:00
|
|
|
// or DatabaseSearchReply with new routers
|
2018-01-06 06:48:51 +03:00
|
|
|
i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg));
|
2015-01-24 00:26:39 +03:00
|
|
|
tunnel->SendTunnelDataMsg (msg);
|
|
|
|
}
|
|
|
|
|
2023-02-10 02:32:18 +03:00
|
|
|
void Tunnels::ManageTunnels (uint64_t ts)
|
2014-10-06 20:50:36 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
ManagePendingTunnels (ts);
|
|
|
|
ManageInboundTunnels (ts);
|
|
|
|
ManageOutboundTunnels (ts);
|
|
|
|
ManageTransitTunnels (ts);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-10-06 20:50:36 +04:00
|
|
|
|
2023-02-10 02:32:18 +03:00
|
|
|
void Tunnels::ManagePendingTunnels (uint64_t ts)
|
2015-01-26 19:56:10 +03:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
ManagePendingTunnels (m_PendingInboundTunnels, ts);
|
|
|
|
ManagePendingTunnels (m_PendingOutboundTunnels, ts);
|
2015-01-26 19:56:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class PendingTunnels>
|
2023-02-10 02:32:18 +03:00
|
|
|
void Tunnels::ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2014-09-26 18:15:34 +04:00
|
|
|
// check pending tunnel. delete failed or timeout
|
2015-01-26 19:56:10 +03:00
|
|
|
for (auto it = pendingTunnels.begin (); it != pendingTunnels.end ();)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2014-09-26 18:15:34 +04:00
|
|
|
auto tunnel = it->second;
|
|
|
|
switch (tunnel->GetState ())
|
2014-08-18 22:37:19 +04:00
|
|
|
{
|
2018-01-06 06:48:51 +03:00
|
|
|
case eTunnelStatePending:
|
2023-02-10 02:32:18 +03:00
|
|
|
if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT ||
|
|
|
|
ts + TUNNEL_CREATION_TIMEOUT < tunnel->GetCreationTime ())
|
2014-09-26 18:15:34 +04:00
|
|
|
{
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " timeout, deleted");
|
2015-03-28 23:09:34 +03:00
|
|
|
// update stats
|
|
|
|
auto config = tunnel->GetTunnelConfig ();
|
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
auto hop = config->GetFirstHop ();
|
|
|
|
while (hop)
|
|
|
|
{
|
2015-11-03 17:15:49 +03:00
|
|
|
if (hop->ident)
|
|
|
|
{
|
|
|
|
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
|
|
|
if (profile)
|
|
|
|
profile->TunnelNonReplied ();
|
|
|
|
}
|
2015-03-28 23:09:34 +03:00
|
|
|
hop = hop->next;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
2015-03-28 23:09:34 +03:00
|
|
|
// delete
|
2015-01-26 19:56:10 +03:00
|
|
|
it = pendingTunnels.erase (it);
|
2023-01-03 03:07:07 +03:00
|
|
|
FailedTunnelCreation();
|
2014-09-26 18:15:34 +04:00
|
|
|
}
|
|
|
|
else
|
2016-08-10 01:16:24 +03:00
|
|
|
++it;
|
2014-09-26 18:15:34 +04:00
|
|
|
break;
|
|
|
|
case eTunnelStateBuildFailed:
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Pending build request ", it->first, " failed, deleted");
|
2015-01-26 19:56:10 +03:00
|
|
|
it = pendingTunnels.erase (it);
|
2023-01-03 03:07:07 +03:00
|
|
|
FailedTunnelCreation();
|
2014-09-26 18:15:34 +04:00
|
|
|
break;
|
|
|
|
case eTunnelStateBuildReplyReceived:
|
2015-01-27 22:55:46 +03:00
|
|
|
// intermediate state, will be either established of build failed
|
2016-08-10 01:16:24 +03:00
|
|
|
++it;
|
2016-08-11 12:25:26 +03:00
|
|
|
break;
|
2014-09-26 18:15:34 +04:00
|
|
|
default:
|
2015-02-28 15:59:34 +03:00
|
|
|
// success
|
2015-01-26 19:56:10 +03:00
|
|
|
it = pendingTunnels.erase (it);
|
2023-01-03 03:07:07 +03:00
|
|
|
SuccesiveTunnelCreation();
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
}
|
2014-10-06 20:50:36 +04:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2023-02-10 02:32:18 +03:00
|
|
|
void Tunnels::ManageOutboundTunnels (uint64_t ts)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
auto tunnel = *it;
|
|
|
|
if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired");
|
|
|
|
auto pool = tunnel->GetTunnelPool ();
|
|
|
|
if (pool)
|
|
|
|
pool->TunnelExpired (tunnel);
|
|
|
|
// we don't have outbound tunnels in m_Tunnels
|
|
|
|
it = m_OutboundTunnels.erase (it);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (tunnel->IsEstablished ())
|
2014-08-31 16:56:03 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
auto pool = tunnel->GetTunnelPool ();
|
|
|
|
// let it die if the tunnel pool has been reconfigured and this is old
|
|
|
|
if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops())
|
2015-04-17 18:36:42 +03:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
tunnel->SetRecreated (true);
|
|
|
|
pool->RecreateOutboundTunnel (tunnel);
|
2015-04-17 18:36:42 +03:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2023-02-10 02:32:18 +03:00
|
|
|
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
|
|
|
tunnel->SetState (eTunnelStateExpiring);
|
2014-08-31 16:56:03 +04:00
|
|
|
}
|
2023-02-10 02:32:18 +03:00
|
|
|
++it;
|
2014-08-26 18:31:32 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2018-01-06 06:48:51 +03:00
|
|
|
if (m_OutboundTunnels.size () < 3)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-03-24 23:15:47 +03:00
|
|
|
// trying to create one more outbound tunnel
|
2015-01-27 22:55:46 +03:00
|
|
|
auto inboundTunnel = GetNextInboundTunnel ();
|
2016-10-28 19:50:26 +03:00
|
|
|
auto router = i2p::transport::transports.RoutesRestricted() ?
|
|
|
|
i2p::transport::transports.GetRestrictedPeer() :
|
2021-03-02 16:46:13 +03:00
|
|
|
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us
|
2015-04-03 17:02:45 +03:00
|
|
|
if (!inboundTunnel || !router) return;
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel");
|
2014-04-03 04:42:02 +04:00
|
|
|
CreateTunnel<OutboundTunnel> (
|
2016-08-11 12:25:26 +03:00
|
|
|
std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () },
|
2021-10-06 02:38:33 +03:00
|
|
|
inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash (), false), nullptr
|
2016-08-11 12:25:26 +03:00
|
|
|
);
|
2013-12-07 04:02:49 +04:00
|
|
|
}
|
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2023-02-10 02:32:18 +03:00
|
|
|
void Tunnels::ManageInboundTunnels (uint64_t ts)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
auto tunnel = *it;
|
|
|
|
if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT ||
|
|
|
|
ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ())
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Tunnel with id ", tunnel->GetTunnelID (), " expired");
|
|
|
|
auto pool = tunnel->GetTunnelPool ();
|
|
|
|
if (pool)
|
|
|
|
pool->TunnelExpired (tunnel);
|
|
|
|
m_Tunnels.erase (tunnel->GetTunnelID ());
|
|
|
|
it = m_InboundTunnels.erase (it);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (tunnel->IsEstablished ())
|
2014-08-31 16:56:03 +04:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
auto pool = tunnel->GetTunnelPool ();
|
|
|
|
// let it die if the tunnel pool was reconfigured and has different number of hops
|
|
|
|
if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
|
2015-04-17 18:36:42 +03:00
|
|
|
{
|
2023-02-10 02:32:18 +03:00
|
|
|
tunnel->SetRecreated (true);
|
|
|
|
pool->RecreateInboundTunnel (tunnel);
|
2015-04-17 18:36:42 +03:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2023-02-10 02:32:18 +03:00
|
|
|
|
|
|
|
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
|
|
|
tunnel->SetState (eTunnelStateExpiring);
|
|
|
|
else // we don't need to cleanup expiring tunnels
|
|
|
|
tunnel->Cleanup ();
|
2014-08-31 16:56:03 +04:00
|
|
|
}
|
2023-02-10 02:32:18 +03:00
|
|
|
it++;
|
2014-08-26 18:31:32 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-10 17:10:49 +04:00
|
|
|
|
|
|
|
if (m_InboundTunnels.empty ())
|
|
|
|
{
|
2016-01-18 03:00:00 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Creating zero hops inbound tunnel");
|
2021-07-30 21:12:50 +03:00
|
|
|
CreateZeroHopsInboundTunnel (nullptr);
|
|
|
|
CreateZeroHopsOutboundTunnel (nullptr);
|
2014-04-03 04:42:02 +04:00
|
|
|
if (!m_ExploratoryPool)
|
2015-12-16 22:52:48 +03:00
|
|
|
{
|
2017-02-28 23:58:53 +03:00
|
|
|
int ibLen; i2p::config::GetOption("exploratory.inbound.length", ibLen);
|
|
|
|
int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen);
|
|
|
|
int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum);
|
|
|
|
int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum);
|
2022-03-08 06:20:11 +03:00
|
|
|
m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum, 0, 0);
|
2015-12-16 22:52:48 +03:00
|
|
|
m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ());
|
|
|
|
}
|
2013-12-10 17:10:49 +04:00
|
|
|
return;
|
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
|
2018-01-06 06:48:51 +03:00
|
|
|
if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
// trying to create one more inbound tunnel
|
2016-10-28 19:50:26 +03:00
|
|
|
auto router = i2p::transport::transports.RoutesRestricted() ?
|
|
|
|
i2p::transport::transports.GetRestrictedPeer() :
|
2021-03-02 16:46:13 +03:00
|
|
|
// should be reachable by us because we send build request directly
|
|
|
|
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false);
|
2016-06-28 21:24:18 +03:00
|
|
|
if (!router) {
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel");
|
2016-02-10 03:00:00 +03:00
|
|
|
return;
|
|
|
|
}
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Creating one hop inbound tunnel");
|
2014-04-03 04:42:02 +04:00
|
|
|
CreateTunnel<InboundTunnel> (
|
2021-10-06 02:38:33 +03:00
|
|
|
std::make_shared<TunnelConfig> (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > { router->GetRouterIdentity () }, false), nullptr
|
2016-08-11 12:25:26 +03:00
|
|
|
);
|
2013-12-07 04:02:49 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-01-04 07:56:28 +04:00
|
|
|
|
2023-02-10 02:32:18 +03:00
|
|
|
void Tunnels::ManageTransitTunnels (uint64_t ts)
|
2014-01-04 07:56:28 +04:00
|
|
|
{
|
|
|
|
for (auto it = m_TransitTunnels.begin (); it != m_TransitTunnels.end ();)
|
|
|
|
{
|
2016-03-02 04:48:56 +03:00
|
|
|
auto tunnel = *it;
|
2023-02-10 02:32:18 +03:00
|
|
|
if (ts > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT ||
|
|
|
|
ts + TUNNEL_EXPIRATION_TIMEOUT < tunnel->GetCreationTime ())
|
2014-01-04 07:56:28 +04:00
|
|
|
{
|
2016-03-02 04:48:56 +03:00
|
|
|
LogPrint (eLogDebug, "Tunnel: Transit tunnel with id ", tunnel->GetTunnelID (), " expired");
|
|
|
|
m_Tunnels.erase (tunnel->GetTunnelID ());
|
|
|
|
it = m_TransitTunnels.erase (it);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2018-01-06 06:48:51 +03:00
|
|
|
else
|
2016-11-09 22:51:55 +03:00
|
|
|
{
|
|
|
|
tunnel->Cleanup ();
|
2014-01-04 07:56:28 +04:00
|
|
|
it++;
|
2016-11-09 22:51:55 +03:00
|
|
|
}
|
2014-01-04 07:56:28 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2014-03-15 04:24:12 +04:00
|
|
|
|
2020-11-16 03:38:34 +03:00
|
|
|
void Tunnels::ManageTunnelPools (uint64_t ts)
|
2014-03-15 04:24:12 +04:00
|
|
|
{
|
2014-10-05 19:01:12 +04:00
|
|
|
std::unique_lock<std::mutex> l(m_PoolsMutex);
|
2016-08-10 01:16:24 +03:00
|
|
|
for (auto& pool : m_Pools)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2015-01-20 06:28:13 +03:00
|
|
|
if (pool && pool->IsActive ())
|
2020-11-16 03:38:34 +03:00
|
|
|
pool->ManageTunnels (ts);
|
2014-03-18 00:50:03 +04:00
|
|
|
}
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2015-06-19 21:38:31 +03:00
|
|
|
void Tunnels::PostTunnelData (std::shared_ptr<I2NPMessage> msg)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-08-11 12:25:26 +03:00
|
|
|
if (msg) m_Queue.Put (msg);
|
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2015-06-19 21:38:31 +03:00
|
|
|
void Tunnels::PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
2015-01-23 06:00:41 +03:00
|
|
|
{
|
|
|
|
m_Queue.Put (msgs);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2013-12-07 04:02:49 +04:00
|
|
|
template<class TTunnel>
|
2021-11-27 23:30:35 +03:00
|
|
|
std::shared_ptr<TTunnel> Tunnels::CreateTunnel (std::shared_ptr<TunnelConfig> config,
|
2022-05-20 19:56:05 +03:00
|
|
|
std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2015-01-27 22:55:46 +03:00
|
|
|
auto newTunnel = std::make_shared<TTunnel> (config);
|
2021-07-21 20:08:12 +03:00
|
|
|
newTunnel->SetTunnelPool (pool);
|
2015-11-03 17:15:49 +03:00
|
|
|
uint32_t replyMsgID;
|
|
|
|
RAND_bytes ((uint8_t *)&replyMsgID, 4);
|
2018-01-06 06:48:51 +03:00
|
|
|
AddPendingTunnel (replyMsgID, newTunnel);
|
2014-09-28 01:51:55 +04:00
|
|
|
newTunnel->Build (replyMsgID, outboundTunnel);
|
2013-12-07 04:02:49 +04:00
|
|
|
return newTunnel;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2021-11-27 23:30:35 +03:00
|
|
|
std::shared_ptr<InboundTunnel> Tunnels::CreateInboundTunnel (std::shared_ptr<TunnelConfig> config,
|
2021-07-21 20:08:12 +03:00
|
|
|
std::shared_ptr<TunnelPool> pool, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
2016-06-29 18:26:46 +03:00
|
|
|
{
|
2018-01-06 06:48:51 +03:00
|
|
|
if (config)
|
2021-07-21 20:08:12 +03:00
|
|
|
return CreateTunnel<InboundTunnel>(config, pool, outboundTunnel);
|
2016-11-01 17:26:40 +03:00
|
|
|
else
|
2021-07-30 21:12:50 +03:00
|
|
|
return CreateZeroHopsInboundTunnel (pool);
|
2016-06-29 18:26:46 +03:00
|
|
|
}
|
|
|
|
|
2021-07-21 20:08:12 +03:00
|
|
|
std::shared_ptr<OutboundTunnel> Tunnels::CreateOutboundTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<TunnelPool> pool)
|
2016-06-29 18:26:46 +03:00
|
|
|
{
|
2016-06-30 19:24:26 +03:00
|
|
|
if (config)
|
2021-07-21 20:08:12 +03:00
|
|
|
return CreateTunnel<OutboundTunnel>(config, pool);
|
2016-06-30 19:24:26 +03:00
|
|
|
else
|
2021-07-30 21:12:50 +03:00
|
|
|
return CreateZeroHopsOutboundTunnel (pool);
|
2016-06-29 18:26:46 +03:00
|
|
|
}
|
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel)
|
2015-01-26 19:56:10 +03:00
|
|
|
{
|
2018-01-06 06:48:51 +03:00
|
|
|
m_PendingInboundTunnels[replyMsgID] = tunnel;
|
2015-01-26 19:56:10 +03:00
|
|
|
}
|
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> tunnel)
|
2015-01-26 19:56:10 +03:00
|
|
|
{
|
2018-01-06 06:48:51 +03:00
|
|
|
m_PendingOutboundTunnels[replyMsgID] = tunnel;
|
2015-01-26 19:56:10 +03:00
|
|
|
}
|
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
void Tunnels::AddOutboundTunnel (std::shared_ptr<OutboundTunnel> newTunnel)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-03-02 04:48:56 +03:00
|
|
|
// we don't need to insert it to m_Tunnels
|
2013-12-10 17:10:49 +04:00
|
|
|
m_OutboundTunnels.push_back (newTunnel);
|
2014-03-17 00:03:20 +04:00
|
|
|
auto pool = newTunnel->GetTunnelPool ();
|
2014-10-13 19:21:57 +04:00
|
|
|
if (pool && pool->IsActive ())
|
2014-03-17 00:03:20 +04:00
|
|
|
pool->TunnelCreated (newTunnel);
|
2014-10-13 19:21:57 +04:00
|
|
|
else
|
|
|
|
newTunnel->SetTunnelPool (nullptr);
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2015-01-27 22:55:46 +03:00
|
|
|
void Tunnels::AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-03-02 04:48:56 +03:00
|
|
|
if (m_Tunnels.emplace (newTunnel->GetTunnelID (), newTunnel).second)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2016-03-02 19:58:52 +03:00
|
|
|
m_InboundTunnels.push_back (newTunnel);
|
2016-03-02 04:48:56 +03:00
|
|
|
auto pool = newTunnel->GetTunnelPool ();
|
|
|
|
if (!pool)
|
2016-08-11 12:25:26 +03:00
|
|
|
{
|
2016-03-02 04:48:56 +03:00
|
|
|
// build symmetric outbound tunnel
|
|
|
|
CreateTunnel<OutboundTunnel> (std::make_shared<TunnelConfig>(newTunnel->GetInvertedPeers (),
|
2021-10-06 02:38:33 +03:00
|
|
|
newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash (), false), nullptr,
|
2016-08-11 12:25:26 +03:00
|
|
|
GetNextOutboundTunnel ());
|
2016-03-02 04:48:56 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pool->IsActive ())
|
|
|
|
pool->TunnelCreated (newTunnel);
|
|
|
|
else
|
|
|
|
newTunnel->SetTunnelPool (nullptr);
|
|
|
|
}
|
2014-03-14 23:13:34 +04:00
|
|
|
}
|
2014-03-15 04:24:12 +04:00
|
|
|
else
|
2021-11-27 22:53:53 +03:00
|
|
|
LogPrint (eLogError, "Tunnel: Tunnel with id ", newTunnel->GetTunnelID (), " already exists");
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
|
|
|
|
2013-12-07 04:02:49 +04:00
|
|
|
|
2021-11-27 23:30:35 +03:00
|
|
|
std::shared_ptr<ZeroHopsInboundTunnel> Tunnels::CreateZeroHopsInboundTunnel (std::shared_ptr<TunnelPool> pool)
|
2013-12-07 04:02:49 +04:00
|
|
|
{
|
2016-03-03 06:41:53 +03:00
|
|
|
auto inboundTunnel = std::make_shared<ZeroHopsInboundTunnel> ();
|
2021-07-30 21:12:50 +03:00
|
|
|
inboundTunnel->SetTunnelPool (pool);
|
2016-03-04 01:57:15 +03:00
|
|
|
inboundTunnel->SetState (eTunnelStateEstablished);
|
2016-03-03 06:41:53 +03:00
|
|
|
m_InboundTunnels.push_back (inboundTunnel);
|
|
|
|
m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel;
|
2016-06-29 18:26:46 +03:00
|
|
|
return inboundTunnel;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2015-01-10 06:27:52 +03:00
|
|
|
|
2021-07-30 21:12:50 +03:00
|
|
|
std::shared_ptr<ZeroHopsOutboundTunnel> Tunnels::CreateZeroHopsOutboundTunnel (std::shared_ptr<TunnelPool> pool)
|
2016-03-04 00:24:13 +03:00
|
|
|
{
|
2016-03-04 01:57:15 +03:00
|
|
|
auto outboundTunnel = std::make_shared<ZeroHopsOutboundTunnel> ();
|
2021-07-30 21:12:50 +03:00
|
|
|
outboundTunnel->SetTunnelPool (pool);
|
2016-03-04 01:57:15 +03:00
|
|
|
outboundTunnel->SetState (eTunnelStateEstablished);
|
|
|
|
m_OutboundTunnels.push_back (outboundTunnel);
|
2016-03-04 00:24:13 +03:00
|
|
|
// we don't insert into m_Tunnels
|
2016-06-29 18:26:46 +03:00
|
|
|
return outboundTunnel;
|
2016-03-04 00:24:13 +03:00
|
|
|
}
|
|
|
|
|
2021-10-23 02:18:45 +03:00
|
|
|
std::shared_ptr<I2NPMessage> Tunnels::NewI2NPTunnelMessage (bool endpoint)
|
2021-10-21 04:05:22 +03:00
|
|
|
{
|
2021-10-23 02:18:45 +03:00
|
|
|
if (endpoint)
|
2021-11-27 23:30:35 +03:00
|
|
|
{
|
2021-10-23 02:18:45 +03:00
|
|
|
// should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet
|
2021-11-27 23:30:35 +03:00
|
|
|
auto msg = m_I2NPTunnelEndpointMessagesMemoryPool.AcquireSharedMt ();
|
2021-10-23 02:18:45 +03:00
|
|
|
msg->Align (6);
|
|
|
|
msg->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header
|
|
|
|
return msg;
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
2021-10-23 02:18:45 +03:00
|
|
|
else
|
|
|
|
{
|
2021-11-27 23:30:35 +03:00
|
|
|
auto msg = m_I2NPTunnelMessagesMemoryPool.AcquireSharedMt ();
|
2021-10-23 02:18:45 +03:00
|
|
|
msg->Align (12);
|
|
|
|
return msg;
|
2021-11-27 23:30:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-10 06:27:52 +03:00
|
|
|
int Tunnels::GetTransitTunnelsExpirationTimeout ()
|
|
|
|
{
|
|
|
|
int timeout = 0;
|
|
|
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
2016-03-02 04:48:56 +03:00
|
|
|
// TODO: possible race condition with I2PControl
|
2016-08-10 01:16:24 +03:00
|
|
|
for (const auto& it : m_TransitTunnels)
|
2015-01-10 06:27:52 +03:00
|
|
|
{
|
2016-03-02 04:48:56 +03:00
|
|
|
int t = it->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT - ts;
|
2015-01-10 06:27:52 +03:00
|
|
|
if (t > timeout) timeout = t;
|
2016-08-11 12:25:26 +03:00
|
|
|
}
|
2015-01-10 06:27:52 +03:00
|
|
|
return timeout;
|
2016-03-02 17:41:37 +03:00
|
|
|
}
|
|
|
|
|
2016-03-02 19:58:52 +03:00
|
|
|
size_t Tunnels::CountTransitTunnels() const
|
|
|
|
{
|
2021-11-01 05:03:34 +03:00
|
|
|
// TODO: locking
|
2016-03-02 18:05:26 +03:00
|
|
|
return m_TransitTunnels.size();
|
|
|
|
}
|
|
|
|
|
2016-03-02 19:58:52 +03:00
|
|
|
size_t Tunnels::CountInboundTunnels() const
|
|
|
|
{
|
2021-11-01 05:03:34 +03:00
|
|
|
// TODO: locking
|
2016-03-02 18:05:26 +03:00
|
|
|
return m_InboundTunnels.size();
|
|
|
|
}
|
|
|
|
|
2016-03-02 19:58:52 +03:00
|
|
|
size_t Tunnels::CountOutboundTunnels() const
|
|
|
|
{
|
2021-11-01 05:03:34 +03:00
|
|
|
// TODO: locking
|
2016-03-02 18:05:26 +03:00
|
|
|
return m_OutboundTunnels.size();
|
|
|
|
}
|
2023-03-06 04:08:15 +03:00
|
|
|
|
|
|
|
void Tunnels::SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels)
|
|
|
|
{
|
|
|
|
if (maxNumTransitTunnels > 0 && m_MaxNumTransitTunnels != maxNumTransitTunnels)
|
|
|
|
{
|
|
|
|
LogPrint (eLogDebug, "Tunnel: Max number of transit tunnels set to ", maxNumTransitTunnels);
|
|
|
|
m_MaxNumTransitTunnels = maxNumTransitTunnels;
|
|
|
|
}
|
|
|
|
}
|
2013-12-07 04:02:49 +04:00
|
|
|
}
|
|
|
|
}
|