mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
1 Commits
ed7f3f6c71
...
faa10eb88e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faa10eb88e |
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -711,40 +711,18 @@ namespace crypto
|
|||||||
return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, false);
|
return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ChaCha20 (EVP_CIPHER_CTX *ctx, const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
||||||
{
|
{
|
||||||
|
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
||||||
uint32_t iv[4];
|
uint32_t iv[4];
|
||||||
iv[0] = htole32 (1); memcpy (iv + 1, nonce, 12); // counter | nonce
|
iv[0] = htole32 (1); memcpy (iv + 1, nonce, 12); // counter | nonce
|
||||||
EVP_EncryptInit_ex(ctx, EVP_chacha20 (), NULL, key, (const uint8_t *)iv);
|
EVP_EncryptInit_ex(ctx, EVP_chacha20 (), NULL, key, (const uint8_t *)iv);
|
||||||
int outlen = 0;
|
int outlen = 0;
|
||||||
EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen);
|
EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen);
|
||||||
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
||||||
}
|
|
||||||
|
|
||||||
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
|
||||||
{
|
|
||||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
|
||||||
ChaCha20 (ctx, msg, msgLen, key, nonce, out);
|
|
||||||
EVP_CIPHER_CTX_free (ctx);
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ChaCha20Context::ChaCha20Context ()
|
|
||||||
{
|
|
||||||
m_Ctx = EVP_CIPHER_CTX_new ();
|
|
||||||
}
|
|
||||||
|
|
||||||
ChaCha20Context::~ChaCha20Context ()
|
|
||||||
{
|
|
||||||
if (m_Ctx)
|
|
||||||
EVP_CIPHER_CTX_free (m_Ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChaCha20Context::operator ()(const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
|
||||||
{
|
|
||||||
ChaCha20 (m_Ctx, msg, msgLen, key, nonce, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info,
|
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info,
|
||||||
uint8_t * out, size_t outLen)
|
uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -226,19 +226,6 @@ namespace crypto
|
|||||||
// ChaCha20
|
// ChaCha20
|
||||||
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
|
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
|
||||||
|
|
||||||
class ChaCha20Context
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
ChaCha20Context ();
|
|
||||||
~ChaCha20Context ();
|
|
||||||
void operator ()(const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
EVP_CIPHER_CTX * m_Ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
// HKDF
|
// HKDF
|
||||||
|
|
||||||
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32
|
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ namespace client
|
|||||||
m_IsPublic = itr->second != "true";
|
m_IsPublic = itr->second != "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
int inLen = 0, outLen = 0, inQuant = 0, outQuant = 0, numTags = 0, minLatency = 0, maxLatency = 0;
|
int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency;
|
||||||
std::map<std::string, int&> intOpts = {
|
std::map<std::string, int&> intOpts = {
|
||||||
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
|
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
|
||||||
{I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen},
|
{I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen},
|
||||||
|
|||||||
@@ -27,15 +27,18 @@ namespace data
|
|||||||
|
|
||||||
size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
|
size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
if (len < DEFAULT_IDENTITY_SIZE) return 0; // buffer too small, don't overflow
|
if ( len < DEFAULT_IDENTITY_SIZE ) {
|
||||||
memcpy (this, buf, DEFAULT_IDENTITY_SIZE);
|
// buffer too small, don't overflow
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy (publicKey, buf, DEFAULT_IDENTITY_SIZE);
|
||||||
return DEFAULT_IDENTITY_SIZE;
|
return DEFAULT_IDENTITY_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentHash Identity::Hash () const
|
IdentHash Identity::Hash () const
|
||||||
{
|
{
|
||||||
IdentHash hash;
|
IdentHash hash;
|
||||||
SHA256((const uint8_t *)this, DEFAULT_IDENTITY_SIZE, hash);
|
SHA256(publicKey, DEFAULT_IDENTITY_SIZE, hash);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -819,22 +819,17 @@ namespace transport
|
|||||||
Terminate ();
|
Terminate ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::shared_ptr<i2p::data::RouterProfile> profile; // not null if older
|
||||||
bool isOlder = false;
|
|
||||||
if (ri.GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
|
if (ri.GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
|
||||||
{
|
{
|
||||||
// received RouterInfo is older than one in netdb
|
// received RouterInfo is older than one in netdb
|
||||||
isOlder = true;
|
profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
|
||||||
if (ri1->HasProfile ())
|
|
||||||
{
|
|
||||||
auto profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
|
|
||||||
if (profile && profile->IsDuplicated ())
|
if (profile && profile->IsDuplicated ())
|
||||||
{
|
{
|
||||||
SendTerminationAndTerminate (eNTCP2Banned);
|
SendTerminationAndTerminate (eNTCP2Banned);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri1->GetNTCP2V4Address () :
|
auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri1->GetNTCP2V4Address () :
|
||||||
(i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri1->GetYggdrasilAddress () : ri1->GetNTCP2V6Address ());
|
(i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri1->GetYggdrasilAddress () : ri1->GetNTCP2V6Address ());
|
||||||
@@ -849,12 +844,8 @@ namespace transport
|
|||||||
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data () + 1, addr->host.to_v6 ().to_bytes ().data () + 1, 7) : // from the same yggdrasil subnet
|
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data () + 1, addr->host.to_v6 ().to_bytes ().data () + 1, 7) : // from the same yggdrasil subnet
|
||||||
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), addr->host.to_v6 ().to_bytes ().data (), 8)))) // temporary address
|
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), addr->host.to_v6 ().to_bytes ().data (), 8)))) // temporary address
|
||||||
{
|
{
|
||||||
if (isOlder) // older router?
|
if (profile) // older router?
|
||||||
i2p::data::UpdateRouterProfile (ri1->GetIdentHash (),
|
profile->Duplicated (); // mark router as duplicated in profile
|
||||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
|
||||||
{
|
|
||||||
if (profile) profile->Duplicated (); // mark router as duplicated in profile
|
|
||||||
});
|
|
||||||
else
|
else
|
||||||
LogPrint (eLogInfo, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ());
|
LogPrint (eLogInfo, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ());
|
||||||
SendTerminationAndTerminate (eNTCP2Banned);
|
SendTerminationAndTerminate (eNTCP2Banned);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <random>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ namespace data
|
|||||||
|
|
||||||
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr),
|
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr),
|
||||||
m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true),
|
m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true),
|
||||||
m_LastExploratorySelectionUpdateTime (0), m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL)
|
m_LastExploratorySelectionUpdateTime (0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,9 +119,8 @@ namespace data
|
|||||||
i2p::util::SetThreadName("NetDB");
|
i2p::util::SetThreadName("NetDB");
|
||||||
|
|
||||||
uint64_t lastManage = 0;
|
uint64_t lastManage = 0;
|
||||||
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (),
|
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (), lastObsoleteProfilesCleanup = lastProfilesCleanup;
|
||||||
lastObsoleteProfilesCleanup = lastProfilesCleanup, lastApplyingProfileUpdates = lastProfilesCleanup;
|
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0;
|
||||||
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0, applyingProfileUpdatesVariance = 0;
|
|
||||||
|
|
||||||
std::list<std::shared_ptr<const I2NPMessage> > msgs;
|
std::list<std::shared_ptr<const I2NPMessage> > msgs;
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
@@ -181,7 +181,7 @@ namespace data
|
|||||||
LogPrint (eLogWarning, "NetDb: Can't persist profiles. Profiles are being saved to disk");
|
LogPrint (eLogWarning, "NetDb: Can't persist profiles. Profiles are being saved to disk");
|
||||||
}
|
}
|
||||||
lastProfilesCleanup = mts;
|
lastProfilesCleanup = mts;
|
||||||
profilesCleanupVariance = m_Rng () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE;
|
profilesCleanupVariance = rand () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mts >= lastObsoleteProfilesCleanup + (uint64_t)(i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_TIMEOUT + obsoleteProfilesCleanVariance)*1000)
|
if (mts >= lastObsoleteProfilesCleanup + (uint64_t)(i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_TIMEOUT + obsoleteProfilesCleanVariance)*1000)
|
||||||
@@ -197,20 +197,7 @@ namespace data
|
|||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "NetDb: Can't delete profiles. Profiles are being deleted from disk");
|
LogPrint (eLogWarning, "NetDb: Can't delete profiles. Profiles are being deleted from disk");
|
||||||
lastObsoleteProfilesCleanup = mts;
|
lastObsoleteProfilesCleanup = mts;
|
||||||
obsoleteProfilesCleanVariance = m_Rng () % i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE;
|
obsoleteProfilesCleanVariance = rand () % i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE;
|
||||||
}
|
|
||||||
if (mts >= lastApplyingProfileUpdates + i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT + applyingProfileUpdatesVariance)
|
|
||||||
{
|
|
||||||
bool isApplying = m_ApplyingProfileUpdates.valid ();
|
|
||||||
if (isApplying && m_ApplyingProfileUpdates.wait_for(std::chrono::seconds(0)) == std::future_status::ready) // still active?
|
|
||||||
{
|
|
||||||
m_ApplyingProfileUpdates.get ();
|
|
||||||
isApplying = false;
|
|
||||||
}
|
|
||||||
if (!isApplying)
|
|
||||||
m_ApplyingProfileUpdates = i2p::data::FlushPostponedRouterProfileUpdates ();
|
|
||||||
lastApplyingProfileUpdates = mts;
|
|
||||||
applyingProfileUpdatesVariance = m_Rng () % i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
@@ -294,7 +281,6 @@ namespace data
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r->CancelBufferToDelete (); // since an update received
|
|
||||||
if (CheckLogLevel (eLogDebug))
|
if (CheckLogLevel (eLogDebug))
|
||||||
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
|
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
|
||||||
updated = false;
|
updated = false;
|
||||||
@@ -571,7 +557,7 @@ namespace data
|
|||||||
while(n > 0)
|
while(n > 0)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_RouterInfosMutex);
|
std::lock_guard<std::mutex> lock(m_RouterInfosMutex);
|
||||||
uint32_t idx = m_Rng () % m_RouterInfos.size ();
|
uint32_t idx = rand () % m_RouterInfos.size ();
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (const auto & it : m_RouterInfos) {
|
for (const auto & it : m_RouterInfos) {
|
||||||
if(i >= idx) // are we at the random start point?
|
if(i >= idx) // are we at the random start point?
|
||||||
@@ -674,20 +660,15 @@ namespace data
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update
|
std::lock_guard<std::mutex> l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update
|
||||||
buffer = r->CopyBuffer ();
|
buffer = r->CopyBuffer ();
|
||||||
}
|
|
||||||
if (!i2p::transport::transports.IsConnected (ident))
|
|
||||||
r->ScheduleBufferToDelete ();
|
r->ScheduleBufferToDelete ();
|
||||||
|
}
|
||||||
if (buffer)
|
if (buffer)
|
||||||
saveToDisk.emplace_back(ident.ToBase64 (), buffer);
|
saveToDisk.push_back(std::make_pair(ident.ToBase64 (), buffer));
|
||||||
}
|
}
|
||||||
r->SetUpdated (false);
|
r->SetUpdated (false);
|
||||||
updatedCount++;
|
updatedCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (r->GetBuffer () && ts > r->GetTimestamp () + NETDB_MIN_EXPIRATION_TIMEOUT*1000LL)
|
|
||||||
// since update was long time ago we assume that router is not connected anymore
|
|
||||||
r->ScheduleBufferToDelete ();
|
|
||||||
|
|
||||||
if (r->GetProfile ()->IsUnreachable ())
|
if (r->GetProfile ()->IsUnreachable ())
|
||||||
r->SetUnreachable (true);
|
r->SetUnreachable (true);
|
||||||
// make router reachable back if too few routers or floodfills
|
// make router reachable back if too few routers or floodfills
|
||||||
@@ -723,7 +704,7 @@ namespace data
|
|||||||
{
|
{
|
||||||
if (r->IsFloodfill ()) deletedFloodfillsCount++;
|
if (r->IsFloodfill ()) deletedFloodfillsCount++;
|
||||||
// delete RI file
|
// delete RI file
|
||||||
removeFromDisk.emplace_back (ident.ToBase64());
|
removeFromDisk.push_back (ident.ToBase64());
|
||||||
deletedCount++;
|
deletedCount++;
|
||||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||||
}
|
}
|
||||||
@@ -1350,7 +1331,7 @@ namespace data
|
|||||||
if (eligible.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE)
|
if (eligible.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE)
|
||||||
{
|
{
|
||||||
std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection),
|
std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection),
|
||||||
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, m_Rng);
|
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, std::mt19937(ts));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::swap (m_ExploratorySelection, eligible);
|
std::swap (m_ExploratorySelection, eligible);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <random>
|
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Gzip.h"
|
#include "Gzip.h"
|
||||||
@@ -186,11 +185,10 @@ namespace data
|
|||||||
std::shared_ptr<NetDbRequests> m_Requests;
|
std::shared_ptr<NetDbRequests> m_Requests;
|
||||||
|
|
||||||
bool m_PersistProfiles;
|
bool m_PersistProfiles;
|
||||||
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_ApplyingProfileUpdates, m_PersistingRouters;
|
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_PersistingRouters;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<const RouterInfo> > m_ExploratorySelection;
|
std::vector<std::shared_ptr<const RouterInfo> > m_ExploratorySelection;
|
||||||
uint64_t m_LastExploratorySelectionUpdateTime; // in monotonic seconds
|
uint64_t m_LastExploratorySelectionUpdateTime; // in monotonic seconds
|
||||||
std::mt19937 m_Rng;
|
|
||||||
|
|
||||||
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
|
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
|
||||||
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;
|
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -27,8 +27,6 @@ namespace data
|
|||||||
static i2p::fs::HashedStorage g_ProfilesStorage("peerProfiles", "p", "profile-", "txt");
|
static i2p::fs::HashedStorage g_ProfilesStorage("peerProfiles", "p", "profile-", "txt");
|
||||||
static std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > g_Profiles;
|
static std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > g_Profiles;
|
||||||
static std::mutex g_ProfilesMutex;
|
static std::mutex g_ProfilesMutex;
|
||||||
static std::list<std::pair<i2p::data::IdentHash, std::function<void (std::shared_ptr<RouterProfile>)> > > g_PostponedUpdates;
|
|
||||||
static std::mutex g_PostponedUpdatesMutex;
|
|
||||||
|
|
||||||
RouterProfile::RouterProfile ():
|
RouterProfile::RouterProfile ():
|
||||||
m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0),
|
m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0),
|
||||||
@@ -261,14 +259,14 @@ namespace data
|
|||||||
}
|
}
|
||||||
auto profile = netdb.NewRouterProfile ();
|
auto profile = netdb.NewRouterProfile ();
|
||||||
profile->Load (identHash); // if possible
|
profile->Load (identHash); // if possible
|
||||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||||
g_Profiles.emplace (identHash, profile);
|
g_Profiles.emplace (identHash, profile);
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRouterBanned (const IdentHash& identHash)
|
bool IsRouterBanned (const IdentHash& identHash)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||||
auto it = g_Profiles.find (identHash);
|
auto it = g_Profiles.find (identHash);
|
||||||
if (it != g_Profiles.end ())
|
if (it != g_Profiles.end ())
|
||||||
return it->second->IsUnreachable ();
|
return it->second->IsUnreachable ();
|
||||||
@@ -292,7 +290,7 @@ namespace data
|
|||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > > tmp;
|
std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > > tmp;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||||
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
||||||
{
|
{
|
||||||
if (ts - it->second->GetLastUpdateTime () > PEER_PROFILE_PERSIST_INTERVAL)
|
if (ts - it->second->GetLastUpdateTime () > PEER_PROFILE_PERSIST_INTERVAL)
|
||||||
@@ -314,7 +312,7 @@ namespace data
|
|||||||
{
|
{
|
||||||
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > tmp;
|
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > tmp;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||||
std::swap (tmp, g_Profiles);
|
std::swap (tmp, g_Profiles);
|
||||||
}
|
}
|
||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
@@ -349,7 +347,7 @@ namespace data
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||||
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
||||||
{
|
{
|
||||||
if (ts - it->second->GetLastUpdateTime () >= PEER_PROFILE_EXPIRATION_TIMEOUT)
|
if (ts - it->second->GetLastUpdateTime () >= PEER_PROFILE_EXPIRATION_TIMEOUT)
|
||||||
@@ -361,47 +359,5 @@ namespace data
|
|||||||
|
|
||||||
return std::async (std::launch::async, DeleteFilesFromDisk);
|
return std::async (std::launch::async, DeleteFilesFromDisk);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateRouterProfile (const IdentHash& identHash, std::function<void (std::shared_ptr<RouterProfile>)> update)
|
|
||||||
{
|
|
||||||
if (!update) return true;
|
|
||||||
std::shared_ptr<RouterProfile> profile;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
|
||||||
auto it = g_Profiles.find (identHash);
|
|
||||||
if (it != g_Profiles.end ())
|
|
||||||
profile = it->second;
|
|
||||||
}
|
|
||||||
if (profile)
|
|
||||||
{
|
|
||||||
update (profile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// postpone
|
|
||||||
std::lock_guard<std::mutex> l(g_PostponedUpdatesMutex);
|
|
||||||
g_PostponedUpdates.emplace_back (identHash, update);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ApplyPostponedUpdates (std::list<std::pair<i2p::data::IdentHash, std::function<void (std::shared_ptr<RouterProfile>)> > >&& updates)
|
|
||||||
{
|
|
||||||
for (const auto& [ident, update] : updates)
|
|
||||||
{
|
|
||||||
auto profile = GetRouterProfile (ident);
|
|
||||||
update (profile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<void> FlushPostponedRouterProfileUpdates ()
|
|
||||||
{
|
|
||||||
if (g_PostponedUpdates.empty ()) return std::future<void>();
|
|
||||||
|
|
||||||
std::list<std::pair<i2p::data::IdentHash, std::function<void (std::shared_ptr<RouterProfile>)> > > updates;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> l(g_PostponedUpdatesMutex);
|
|
||||||
g_PostponedUpdates.swap (updates);
|
|
||||||
}
|
|
||||||
return std::async (std::launch::async, ApplyPostponedUpdates, std::move (updates));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <functional>
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
|
||||||
@@ -45,8 +44,6 @@ namespace data
|
|||||||
const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes)
|
const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes)
|
||||||
const int PEER_PROFILE_USEFUL_THRESHOLD = 3;
|
const int PEER_PROFILE_USEFUL_THRESHOLD = 3;
|
||||||
const int PEER_PROFILE_ALWAYS_DECLINING_NUM = 5; // num declines in row to consider always declined
|
const int PEER_PROFILE_ALWAYS_DECLINING_NUM = 5; // num declines in row to consider always declined
|
||||||
const int PEER_PROFILE_APPLY_POSTPONED_TIMEOUT = 2100; // in milliseconds
|
|
||||||
const int PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE = 500; // in milliseconds
|
|
||||||
|
|
||||||
class RouterProfile
|
class RouterProfile
|
||||||
{
|
{
|
||||||
@@ -111,8 +108,6 @@ namespace data
|
|||||||
std::future<void> DeleteObsoleteProfiles ();
|
std::future<void> DeleteObsoleteProfiles ();
|
||||||
void SaveProfiles ();
|
void SaveProfiles ();
|
||||||
std::future<void> PersistProfiles ();
|
std::future<void> PersistProfiles ();
|
||||||
bool UpdateRouterProfile (const IdentHash& identHash, std::function<void (std::shared_ptr<RouterProfile>)> update); // return true if updated immediately, and false if postponed
|
|
||||||
std::future<void> FlushPostponedRouterProfileUpdates ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -1136,12 +1136,12 @@ namespace data
|
|||||||
|
|
||||||
void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len)
|
void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
m_IsBufferScheduledToDelete = false;
|
|
||||||
if (!m_Buffer)
|
if (!m_Buffer)
|
||||||
m_Buffer = NewBuffer ();
|
m_Buffer = NewBuffer ();
|
||||||
if (len > m_Buffer->size ()) len = m_Buffer->size ();
|
if (len > m_Buffer->size ()) len = m_Buffer->size ();
|
||||||
memcpy (m_Buffer->data (), buf, len);
|
memcpy (m_Buffer->data (), buf, len);
|
||||||
m_Buffer->SetBufferLen (len);
|
m_Buffer->SetBufferLen (len);
|
||||||
|
m_IsBufferScheduledToDelete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RouterInfo::Buffer> RouterInfo::CopyBuffer () const
|
std::shared_ptr<RouterInfo::Buffer> RouterInfo::CopyBuffer () const
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -294,7 +294,6 @@ namespace data
|
|||||||
std::shared_ptr<Buffer> GetSharedBuffer () const { return m_Buffer; };
|
std::shared_ptr<Buffer> GetSharedBuffer () const { return m_Buffer; };
|
||||||
std::shared_ptr<Buffer> CopyBuffer () const;
|
std::shared_ptr<Buffer> CopyBuffer () const;
|
||||||
void ScheduleBufferToDelete () { m_IsBufferScheduledToDelete = true; };
|
void ScheduleBufferToDelete () { m_IsBufferScheduledToDelete = true; };
|
||||||
void CancelBufferToDelete () { m_IsBufferScheduledToDelete = false; };
|
|
||||||
bool IsBufferScheduledToDelete () const { return m_IsBufferScheduledToDelete; };
|
bool IsBufferScheduledToDelete () const { return m_IsBufferScheduledToDelete; };
|
||||||
|
|
||||||
bool IsUpdated () const { return m_IsUpdated; };
|
bool IsUpdated () const { return m_IsUpdated; };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022-2025, The PurpleI2P Project
|
* Copyright (c) 2022-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -890,7 +890,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto session = std::make_shared<SSU2Session> (*this, router, address);
|
auto session = std::make_shared<SSU2Session> (*this, router, address);
|
||||||
if (!isValidEndpoint && router->HasProfile () && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
|
if (!isValidEndpoint && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
|
||||||
{
|
{
|
||||||
// router doesn't publish endpoint, but we connected before and hole punch might be alive
|
// router doesn't publish endpoint, but we connected before and hole punch might be alive
|
||||||
auto ep = router->GetProfile ()->GetLastEndpoint ();
|
auto ep = router->GetProfile ()->GetLastEndpoint ();
|
||||||
@@ -1528,11 +1528,6 @@ namespace transport
|
|||||||
return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
|
return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSU2Server::ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
|
||||||
{
|
|
||||||
m_ChaCha20 (msg, msgLen, key, nonce, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SSU2Server::SendThroughProxy (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
|
void SSU2Server::SendThroughProxy (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
|
||||||
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to)
|
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022-2025, The PurpleI2P Project
|
* Copyright (c) 2022-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -86,7 +86,6 @@ namespace transport
|
|||||||
const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len);
|
const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len);
|
||||||
bool AEADChaCha20Poly1305Decrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen,
|
bool AEADChaCha20Poly1305Decrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen,
|
||||||
const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len);
|
const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len);
|
||||||
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
|
|
||||||
bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; }
|
bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; }
|
||||||
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
|
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
|
||||||
void AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from);
|
void AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from);
|
||||||
@@ -207,7 +206,6 @@ namespace transport
|
|||||||
mutable std::mutex m_ReceivedPacketsQueueMutex;
|
mutable std::mutex m_ReceivedPacketsQueueMutex;
|
||||||
i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor;
|
i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor;
|
||||||
i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor;
|
i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor;
|
||||||
i2p::crypto::ChaCha20Context m_ChaCha20;
|
|
||||||
|
|
||||||
// proxy
|
// proxy
|
||||||
bool m_IsThroughProxy;
|
bool m_IsThroughProxy;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2024-2025, The PurpleI2P Project
|
* Copyright (c) 2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -46,7 +46,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
uint8_t nonce[12] = {0};
|
uint8_t nonce[12] = {0};
|
||||||
uint64_t headerX[2]; // sourceConnID, token
|
uint64_t headerX[2]; // sourceConnID, token
|
||||||
GetServer ().ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
||||||
SetDestConnID (headerX[0]);
|
SetDestConnID (headerX[0]);
|
||||||
// decrypt and handle payload
|
// decrypt and handle payload
|
||||||
uint8_t * payload = buf + 32;
|
uint8_t * payload = buf + 32;
|
||||||
@@ -183,7 +183,7 @@ namespace transport
|
|||||||
header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24));
|
header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24));
|
||||||
header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12));
|
header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12));
|
||||||
memset (n, 0, 12);
|
memset (n, 0, 12);
|
||||||
GetServer ().ChaCha20 (h + 16, 16, addr->i, n, h + 16);
|
i2p::crypto::ChaCha20 (h + 16, 16, addr->i, n, h + 16);
|
||||||
// send
|
// send
|
||||||
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ());
|
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ());
|
||||||
UpdateNumSentBytes (payloadSize + 32);
|
UpdateNumSentBytes (payloadSize + 32);
|
||||||
@@ -305,7 +305,7 @@ namespace transport
|
|||||||
header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24));
|
header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24));
|
||||||
header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12));
|
header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12));
|
||||||
memset (n, 0, 12);
|
memset (n, 0, 12);
|
||||||
GetServer ().ChaCha20 (h + 16, 16, addr->i, n, h + 16);
|
i2p::crypto::ChaCha20 (h + 16, 16, addr->i, n, h + 16);
|
||||||
// send
|
// send
|
||||||
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep);
|
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep);
|
||||||
UpdateNumSentBytes (payloadSize + 32);
|
UpdateNumSentBytes (payloadSize + 32);
|
||||||
|
|||||||
@@ -682,7 +682,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
const uint8_t nonce[12] = {0};
|
const uint8_t nonce[12] = {0};
|
||||||
uint64_t headerX[2];
|
uint64_t headerX[2];
|
||||||
m_Server.ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
||||||
LogPrint (eLogWarning, "SSU2: Unexpected PeerTest message SourceConnID=", connID, " DestConnID=", headerX[0]);
|
LogPrint (eLogWarning, "SSU2: Unexpected PeerTest message SourceConnID=", connID, " DestConnID=", headerX[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -748,7 +748,7 @@ namespace transport
|
|||||||
payloadSize += 16;
|
payloadSize += 16;
|
||||||
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24));
|
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24));
|
||||||
header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12));
|
header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12));
|
||||||
m_Server.ChaCha20 (headerX, 48, m_Address->i, nonce, headerX);
|
i2p::crypto::ChaCha20 (headerX, 48, m_Address->i, nonce, headerX);
|
||||||
m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted payload from Session Request) for SessionCreated
|
m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted payload from Session Request) for SessionCreated
|
||||||
m_SentHandshakePacket->payloadSize = payloadSize;
|
m_SentHandshakePacket->payloadSize = payloadSize;
|
||||||
// send
|
// send
|
||||||
@@ -775,7 +775,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
const uint8_t nonce[12] = {0};
|
const uint8_t nonce[12] = {0};
|
||||||
uint8_t headerX[48];
|
uint8_t headerX[48];
|
||||||
m_Server.ChaCha20 (buf + 16, 48, i2p::context.GetSSU2IntroKey (), nonce, headerX);
|
i2p::crypto::ChaCha20 (buf + 16, 48, i2p::context.GetSSU2IntroKey (), nonce, headerX);
|
||||||
memcpy (&m_DestConnID, headerX, 8);
|
memcpy (&m_DestConnID, headerX, 8);
|
||||||
uint64_t token;
|
uint64_t token;
|
||||||
memcpy (&token, headerX + 8, 8);
|
memcpy (&token, headerX + 8, 8);
|
||||||
@@ -874,7 +874,7 @@ namespace transport
|
|||||||
m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted Noise payload from Session Created)
|
m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted Noise payload from Session Created)
|
||||||
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24));
|
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24));
|
||||||
header.ll[1] ^= CreateHeaderMask (kh2, payload + (payloadSize - 12));
|
header.ll[1] ^= CreateHeaderMask (kh2, payload + (payloadSize - 12));
|
||||||
m_Server.ChaCha20 (headerX, 48, kh2, nonce, headerX);
|
i2p::crypto::ChaCha20 (headerX, 48, kh2, nonce, headerX);
|
||||||
m_State = eSSU2SessionStateSessionCreatedSent;
|
m_State = eSSU2SessionStateSessionCreatedSent;
|
||||||
m_SentHandshakePacket->payloadSize = payloadSize;
|
m_SentHandshakePacket->payloadSize = payloadSize;
|
||||||
// send
|
// send
|
||||||
@@ -902,7 +902,7 @@ namespace transport
|
|||||||
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval;
|
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval;
|
||||||
const uint8_t nonce[12] = {0};
|
const uint8_t nonce[12] = {0};
|
||||||
uint8_t headerX[48];
|
uint8_t headerX[48];
|
||||||
m_Server.ChaCha20 (buf + 16, 48, kh2, nonce, headerX);
|
i2p::crypto::ChaCha20 (buf + 16, 48, kh2, nonce, headerX);
|
||||||
// KDF for SessionCreated
|
// KDF for SessionCreated
|
||||||
m_NoiseState->MixHash ( { {header.buf, 16}, {headerX, 16} } ); // h = SHA256(h || header)
|
m_NoiseState->MixHash ( { {header.buf, 16}, {headerX, 16} } ); // h = SHA256(h || header)
|
||||||
m_NoiseState->MixHash (headerX + 16, 32); // h = SHA256(h || bepk);
|
m_NoiseState->MixHash (headerX + 16, 32); // h = SHA256(h || bepk);
|
||||||
@@ -1178,19 +1178,14 @@ namespace transport
|
|||||||
LogPrint (eLogError, "SSU2: Couldn't update RouterInfo from SessionConfirmed in netdb");
|
LogPrint (eLogError, "SSU2: Couldn't update RouterInfo from SessionConfirmed in netdb");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
std::shared_ptr<i2p::data::RouterProfile> profile; // not null if older
|
||||||
bool isOlder = false;
|
|
||||||
if (ri->GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
|
if (ri->GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
|
||||||
{
|
{
|
||||||
// received RouterInfo is older than one in netdb
|
// received RouterInfo is older than one in netdb
|
||||||
isOlder = true;
|
profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
|
||||||
if (ri->HasProfile ())
|
|
||||||
{
|
|
||||||
auto profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
|
|
||||||
if (profile && profile->IsDuplicated ())
|
if (profile && profile->IsDuplicated ())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ri = ri1;
|
ri = ri1;
|
||||||
|
|
||||||
m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address ();
|
m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address ();
|
||||||
@@ -1203,28 +1198,15 @@ namespace transport
|
|||||||
(!m_RemoteEndpoint.address ().is_v6 () ||
|
(!m_RemoteEndpoint.address ().is_v6 () ||
|
||||||
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), m_Address->host.to_v6 ().to_bytes ().data (), 8))) // temporary address
|
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), m_Address->host.to_v6 ().to_bytes ().data (), 8))) // temporary address
|
||||||
{
|
{
|
||||||
if (isOlder) // older router?
|
if (profile) // older router?
|
||||||
i2p::data::UpdateRouterProfile (ri->GetIdentHash (),
|
profile->Duplicated (); // mark router as duplicated in profile
|
||||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
|
||||||
{
|
|
||||||
if (profile) profile->Duplicated (); // mark router as duplicated in profile
|
|
||||||
});
|
|
||||||
else
|
else
|
||||||
LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host,
|
LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host,
|
||||||
" and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));
|
" and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_Address->published)
|
if (!m_Address->published)
|
||||||
{
|
|
||||||
if (ri->HasProfile ())
|
|
||||||
ri->GetProfile ()->SetLastEndpoint (m_RemoteEndpoint);
|
ri->GetProfile ()->SetLastEndpoint (m_RemoteEndpoint);
|
||||||
else
|
|
||||||
i2p::data::UpdateRouterProfile (ri->GetIdentHash (),
|
|
||||||
[ep = m_RemoteEndpoint](std::shared_ptr<i2p::data::RouterProfile> profile)
|
|
||||||
{
|
|
||||||
if (profile) profile->SetLastEndpoint (ep);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
SetRemoteIdentity (ri->GetRouterIdentity ());
|
SetRemoteIdentity (ri->GetRouterIdentity ());
|
||||||
AdjustMaxPayloadSize ();
|
AdjustMaxPayloadSize ();
|
||||||
m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now
|
m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now
|
||||||
@@ -1282,7 +1264,7 @@ namespace transport
|
|||||||
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24));
|
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24));
|
||||||
header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12));
|
header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12));
|
||||||
memset (nonce, 0, 12);
|
memset (nonce, 0, 12);
|
||||||
m_Server.ChaCha20 (h + 16, 16, m_Address->i, nonce, h + 16);
|
i2p::crypto::ChaCha20 (h + 16, 16, m_Address->i, nonce, h + 16);
|
||||||
// send
|
// send
|
||||||
if (m_Server.AddPendingOutgoingSession (shared_from_this ()))
|
if (m_Server.AddPendingOutgoingSession (shared_from_this ()))
|
||||||
m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint);
|
m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint);
|
||||||
@@ -1304,7 +1286,7 @@ namespace transport
|
|||||||
uint8_t nonce[12] = {0};
|
uint8_t nonce[12] = {0};
|
||||||
uint8_t h[32];
|
uint8_t h[32];
|
||||||
memcpy (h, header.buf, 16);
|
memcpy (h, header.buf, 16);
|
||||||
m_Server.ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16);
|
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16);
|
||||||
memcpy (&m_DestConnID, h + 16, 8);
|
memcpy (&m_DestConnID, h + 16, 8);
|
||||||
// decrypt
|
// decrypt
|
||||||
CreateNonce (be32toh (header.h.packetNum), nonce);
|
CreateNonce (be32toh (header.h.packetNum), nonce);
|
||||||
@@ -1356,7 +1338,7 @@ namespace transport
|
|||||||
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24));
|
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24));
|
||||||
header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 12));
|
header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 12));
|
||||||
memset (nonce, 0, 12);
|
memset (nonce, 0, 12);
|
||||||
m_Server.ChaCha20 (h + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16);
|
i2p::crypto::ChaCha20 (h + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16);
|
||||||
// send
|
// send
|
||||||
m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint);
|
m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
@@ -1380,7 +1362,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
uint8_t nonce[12] = {0};
|
uint8_t nonce[12] = {0};
|
||||||
uint64_t headerX[2]; // sourceConnID, token
|
uint64_t headerX[2]; // sourceConnID, token
|
||||||
m_Server.ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX);
|
i2p::crypto::ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX);
|
||||||
uint64_t token = headerX[1];
|
uint64_t token = headerX[1];
|
||||||
if (token)
|
if (token)
|
||||||
m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT);
|
m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT);
|
||||||
@@ -1429,7 +1411,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
uint8_t nonce[12] = {0};
|
uint8_t nonce[12] = {0};
|
||||||
uint64_t headerX[2]; // sourceConnID, token
|
uint64_t headerX[2]; // sourceConnID, token
|
||||||
m_Server.ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
|
||||||
m_DestConnID = headerX[0];
|
m_DestConnID = headerX[0];
|
||||||
// decrypt and handle payload
|
// decrypt and handle payload
|
||||||
uint8_t * payload = buf + 32;
|
uint8_t * payload = buf + 32;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -101,13 +101,13 @@ namespace tunnel
|
|||||||
TunnelMessageBlock block;
|
TunnelMessageBlock block;
|
||||||
block.deliveryType = eDeliveryTypeLocal;
|
block.deliveryType = eDeliveryTypeLocal;
|
||||||
block.data = msg;
|
block.data = msg;
|
||||||
std::lock_guard<std::mutex> l(m_SendMutex);
|
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||||
m_Gateway.PutTunnelDataMsg (block);
|
m_Gateway.PutTunnelDataMsg (block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitTunnelGateway::FlushTunnelDataMsgs ()
|
void TransitTunnelGateway::FlushTunnelDataMsgs ()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_SendMutex);
|
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||||
m_Gateway.SendBuffer ();
|
m_Gateway.SendBuffer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,22 +130,14 @@ namespace tunnel
|
|||||||
EncryptTunnelMsg (tunnelMsg, newMsg);
|
EncryptTunnelMsg (tunnelMsg, newMsg);
|
||||||
|
|
||||||
LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ());
|
LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ());
|
||||||
std::lock_guard<std::mutex> l(m_HandleMutex);
|
|
||||||
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
|
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitTunnelEndpoint::FlushTunnelDataMsgs ()
|
void TransitTunnelEndpoint::FlushTunnelDataMsgs ()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_HandleMutex);
|
|
||||||
m_Endpoint.FlushI2NPMsgs ();
|
m_Endpoint.FlushI2NPMsgs ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitTunnelEndpoint::Cleanup ()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> l(m_HandleMutex);
|
|
||||||
m_Endpoint.Cleanup ();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TransitTunnelEndpoint::GetNextPeerName () const
|
std::string TransitTunnelEndpoint::GetNextPeerName () const
|
||||||
{
|
{
|
||||||
auto hash = m_Endpoint.GetCurrentHash ();
|
auto hash = m_Endpoint.GetCurrentHash ();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -100,7 +100,7 @@ namespace tunnel
|
|||||||
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
|
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
|
||||||
m_Endpoint (false) {}; // transit endpoint is always outbound
|
m_Endpoint (false) {}; // transit endpoint is always outbound
|
||||||
|
|
||||||
void Cleanup () override;
|
void Cleanup () override { m_Endpoint.Cleanup (); }
|
||||||
|
|
||||||
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
|
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
|
||||||
void FlushTunnelDataMsgs () override;
|
void FlushTunnelDataMsgs () override;
|
||||||
@@ -109,7 +109,6 @@ namespace tunnel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::mutex m_HandleMutex;
|
|
||||||
TunnelEndpoint m_Endpoint;
|
TunnelEndpoint m_Endpoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -160,8 +160,7 @@ namespace transport
|
|||||||
m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
|
m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
|
||||||
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0),
|
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0),
|
||||||
m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
|
m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
|
||||||
m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0),
|
m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0)
|
||||||
m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +338,7 @@ namespace transport
|
|||||||
|
|
||||||
if (m_IsNAT)
|
if (m_IsNAT)
|
||||||
{
|
{
|
||||||
m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
|
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
|
||||||
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
|
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -561,14 +560,7 @@ namespace transport
|
|||||||
bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer)
|
bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer)
|
||||||
{
|
{
|
||||||
if (!peer->router) // reconnect
|
if (!peer->router) // reconnect
|
||||||
{
|
peer->SetRouter (netdb.FindRouter (ident)); // try to get new one from netdb
|
||||||
auto r = netdb.FindRouter (ident); // try to get new one from netdb
|
|
||||||
if (r)
|
|
||||||
{
|
|
||||||
peer->SetRouter (r);
|
|
||||||
r->CancelBufferToDelete ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (peer->router) // we have RI already
|
if (peer->router) // we have RI already
|
||||||
{
|
{
|
||||||
if (peer->priority.empty ())
|
if (peer->priority.empty ())
|
||||||
@@ -655,7 +647,7 @@ namespace transport
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::SetPriority (std::shared_ptr<Peer> peer)
|
void Transports::SetPriority (std::shared_ptr<Peer> peer) const
|
||||||
{
|
{
|
||||||
static const std::vector<i2p::data::RouterInfo::SupportedTransports>
|
static const std::vector<i2p::data::RouterInfo::SupportedTransports>
|
||||||
ntcp2Priority =
|
ntcp2Priority =
|
||||||
@@ -681,7 +673,7 @@ namespace transport
|
|||||||
peer->numAttempts = 0;
|
peer->numAttempts = 0;
|
||||||
peer->priority.clear ();
|
peer->priority.clear ();
|
||||||
bool isReal = peer->router->GetProfile ()->IsReal ();
|
bool isReal = peer->router->GetProfile ()->IsReal ();
|
||||||
bool ssu2 = isReal ? (m_Rng () & 1) : false; // try NTCP2 if router is not confirmed real
|
bool ssu2 = isReal ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real
|
||||||
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
|
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
|
||||||
if (directTransports)
|
if (directTransports)
|
||||||
{
|
{
|
||||||
@@ -709,8 +701,7 @@ namespace transport
|
|||||||
// try recently connected SSU2 if any
|
// try recently connected SSU2 if any
|
||||||
auto supportedTransports = context.GetRouterInfo ().GetCompatibleTransports (false) &
|
auto supportedTransports = context.GetRouterInfo ().GetCompatibleTransports (false) &
|
||||||
peer->router->GetCompatibleTransports (false);
|
peer->router->GetCompatibleTransports (false);
|
||||||
if ((supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6)) &&
|
if (supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6))
|
||||||
peer->router->HasProfile ())
|
|
||||||
{
|
{
|
||||||
auto ep = peer->router->GetProfile ()->GetLastEndpoint ();
|
auto ep = peer->router->GetProfile ()->GetLastEndpoint ();
|
||||||
if (!ep.address ().is_unspecified () && ep.port ())
|
if (!ep.address ().is_unspecified () && ep.port ())
|
||||||
@@ -800,7 +791,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||||
if (m_Service)
|
if (m_Service)
|
||||||
{
|
{
|
||||||
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
||||||
@@ -838,7 +829,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||||
if (m_Service)
|
if (m_Service)
|
||||||
{
|
{
|
||||||
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
||||||
@@ -895,11 +886,7 @@ namespace transport
|
|||||||
auto transport = peer->priority[peer->numAttempts-1];
|
auto transport = peer->priority[peer->numAttempts-1];
|
||||||
if (transport == i2p::data::RouterInfo::eNTCP2V4 ||
|
if (transport == i2p::data::RouterInfo::eNTCP2V4 ||
|
||||||
transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh)
|
transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh)
|
||||||
i2p::data::UpdateRouterProfile (ident,
|
peer->router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real
|
||||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
|
||||||
{
|
|
||||||
if (profile) profile->Connected (); // outgoing NTCP2 connection if always real
|
|
||||||
});
|
|
||||||
i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable
|
i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable
|
||||||
}
|
}
|
||||||
peer->numAttempts = 0;
|
peer->numAttempts = 0;
|
||||||
@@ -934,11 +921,7 @@ namespace transport
|
|||||||
session->SendI2NPMessages (msgs); // send DatabaseStore
|
session->SendI2NPMessages (msgs); // send DatabaseStore
|
||||||
}
|
}
|
||||||
auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
|
auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
|
||||||
i2p::data::UpdateRouterProfile (ident,
|
if (r) r->GetProfile ()->Connected ();
|
||||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
|
||||||
{
|
|
||||||
if (profile) profile->Connected ();
|
|
||||||
});
|
|
||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
auto peer = std::make_shared<Peer>(r, ts);
|
auto peer = std::make_shared<Peer>(r, ts);
|
||||||
peer->sessions.push_back (session);
|
peer->sessions.push_back (session);
|
||||||
@@ -971,15 +954,10 @@ namespace transport
|
|||||||
ConnectToPeer (ident, peer);
|
ConnectToPeer (ident, peer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_PeersMutex);
|
std::lock_guard<std::mutex> l(m_PeersMutex);
|
||||||
m_Peers.erase (it);
|
m_Peers.erase (it);
|
||||||
}
|
}
|
||||||
// delete buffer of just disconnected router
|
|
||||||
auto r = i2p::data::netdb.FindRouter (ident);
|
|
||||||
if (r && !r->IsUpdated ()) r->ScheduleBufferToDelete ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1028,7 +1006,7 @@ namespace transport
|
|||||||
if (session)
|
if (session)
|
||||||
session->SendLocalRouterInfo (true);
|
session->SendLocalRouterInfo (true);
|
||||||
it->second->nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL +
|
it->second->nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL +
|
||||||
m_Rng() % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
|
rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
@@ -1052,7 +1030,7 @@ namespace transport
|
|||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
PeerTest ();
|
PeerTest ();
|
||||||
m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
|
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
|
||||||
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
|
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1199,7 +1177,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** XXX: if routes are not restricted this dies */
|
/** XXX: if routes are not restricted this dies */
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer()
|
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer() const
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_FamilyMutex);
|
std::lock_guard<std::mutex> l(m_FamilyMutex);
|
||||||
@@ -1208,7 +1186,7 @@ namespace transport
|
|||||||
if(sz > 1)
|
if(sz > 1)
|
||||||
{
|
{
|
||||||
auto it = m_TrustedFamilies.begin ();
|
auto it = m_TrustedFamilies.begin ();
|
||||||
std::advance(it, m_Rng() % sz);
|
std::advance(it, rand() % sz);
|
||||||
fam = *it;
|
fam = *it;
|
||||||
}
|
}
|
||||||
else if (sz == 1)
|
else if (sz == 1)
|
||||||
@@ -1226,7 +1204,7 @@ namespace transport
|
|||||||
if(sz == 1)
|
if(sz == 1)
|
||||||
return i2p::data::netdb.FindRouter(m_TrustedRouters[0]);
|
return i2p::data::netdb.FindRouter(m_TrustedRouters[0]);
|
||||||
auto it = m_TrustedRouters.begin();
|
auto it = m_TrustedRouters.begin();
|
||||||
std::advance(it, m_Rng() % sz);
|
std::advance(it, rand() % sz);
|
||||||
return i2p::data::netdb.FindRouter(*it);
|
return i2p::data::netdb.FindRouter(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <random>
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "TransportSession.h"
|
#include "TransportSession.h"
|
||||||
#include "SSU2.h"
|
#include "SSU2.h"
|
||||||
@@ -107,8 +106,7 @@ namespace transport
|
|||||||
};
|
};
|
||||||
|
|
||||||
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
|
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
|
||||||
const int PEER_TEST_INTERVAL = 68*60; // in seconds
|
const int PEER_TEST_INTERVAL = 71; // in minutes
|
||||||
const int PEER_TEST_INTERVAL_VARIANCE = 3*60; // in seconds
|
|
||||||
const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds
|
const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds
|
||||||
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
|
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
|
||||||
const int MAX_NUM_DELAYED_MESSAGES = 150;
|
const int MAX_NUM_DELAYED_MESSAGES = 150;
|
||||||
@@ -170,7 +168,7 @@ namespace transport
|
|||||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
|
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
|
||||||
|
|
||||||
/** get a trusted first hop for restricted routes */
|
/** get a trusted first hop for restricted routes */
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer();
|
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
|
||||||
/** do we want to use restricted routes? */
|
/** do we want to use restricted routes? */
|
||||||
bool RoutesRestricted() const;
|
bool RoutesRestricted() const;
|
||||||
/** restrict routes to use only these router families for first hops */
|
/** restrict routes to use only these router families for first hops */
|
||||||
@@ -193,7 +191,7 @@ namespace transport
|
|||||||
void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident);
|
void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident);
|
||||||
std::shared_ptr<TransportSession> PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
|
std::shared_ptr<TransportSession> PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
|
||||||
bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer);
|
bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer);
|
||||||
void SetPriority (std::shared_ptr<Peer> peer);
|
void SetPriority (std::shared_ptr<Peer> peer) const;
|
||||||
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
|
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
|
||||||
void HandlePeerTestTimer (const boost::system::error_code& ecode);
|
void HandlePeerTestTimer (const boost::system::error_code& ecode);
|
||||||
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
|
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
|
||||||
@@ -241,7 +239,6 @@ namespace transport
|
|||||||
mutable std::mutex m_TrustedRoutersMutex;
|
mutable std::mutex m_TrustedRoutersMutex;
|
||||||
|
|
||||||
i2p::I2NPMessagesHandler m_LoopbackHandler;
|
i2p::I2NPMessagesHandler m_LoopbackHandler;
|
||||||
std::mt19937 m_Rng;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -179,12 +179,9 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
uint8_t ret = hop->GetRetCode (msg + 1);
|
uint8_t ret = hop->GetRetCode (msg + 1);
|
||||||
LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
|
LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
|
||||||
if (hop->ident)
|
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
||||||
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
|
if (profile)
|
||||||
[ret](std::shared_ptr<i2p::data::RouterProfile> profile)
|
profile->TunnelBuildResponse (ret);
|
||||||
{
|
|
||||||
if (profile) profile->TunnelBuildResponse (ret);
|
|
||||||
});
|
|
||||||
if (ret)
|
if (ret)
|
||||||
// if any of participants declined the tunnel is not established
|
// if any of participants declined the tunnel is not established
|
||||||
established = false;
|
established = false;
|
||||||
@@ -746,11 +743,11 @@ namespace tunnel
|
|||||||
while (hop)
|
while (hop)
|
||||||
{
|
{
|
||||||
if (hop->ident)
|
if (hop->ident)
|
||||||
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
|
|
||||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
|
||||||
{
|
{
|
||||||
if (profile) profile->TunnelNonReplied ();
|
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
||||||
});
|
if (profile)
|
||||||
|
profile->TunnelNonReplied ();
|
||||||
|
}
|
||||||
hop = hop->next;
|
hop = hop->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace tunnel
|
|||||||
struct Fragment
|
struct Fragment
|
||||||
{
|
{
|
||||||
Fragment (bool last, uint64_t t, const uint8_t * buf, size_t size):
|
Fragment (bool last, uint64_t t, const uint8_t * buf, size_t size):
|
||||||
isLastFragment (last), receiveTime (t), data (size) { memcpy (data.data(), buf, size); };
|
isLastFragment (last), receiveTime (t), data (buf, buf + size) {};
|
||||||
bool isLastFragment;
|
bool isLastFragment;
|
||||||
uint64_t receiveTime; // milliseconds since epoch
|
uint64_t receiveTime; // milliseconds since epoch
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -560,7 +560,7 @@ namespace tunnel
|
|||||||
i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false);
|
i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false);
|
||||||
if (hop)
|
if (hop)
|
||||||
{
|
{
|
||||||
if (!hop->HasProfile () || !hop->GetProfile ()->IsBad ())
|
if (!hop->GetProfile ()->IsBad ())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (tryClient)
|
else if (tryClient)
|
||||||
@@ -588,7 +588,7 @@ namespace tunnel
|
|||||||
(inbound && i2p::transport::transports.GetNumPeers () > 25))
|
(inbound && i2p::transport::transports.GetNumPeers () > 25))
|
||||||
{
|
{
|
||||||
auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ());
|
auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ());
|
||||||
if (r && r->IsECIES () && (!r->HasProfile () || !r->GetProfile ()->IsBad ()) &&
|
if (r && r->IsECIES () && !r->GetProfile ()->IsBad () &&
|
||||||
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4
|
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4
|
||||||
{
|
{
|
||||||
prevHop = r;
|
prevHop = r;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -1350,14 +1350,12 @@ namespace client
|
|||||||
LogPrint (eLogError, "SAM: Runtime exception: ", ex.what ());
|
LogPrint (eLogError, "SAM: Runtime exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
|
|
||||||
decltype(m_Sessions) sessions;
|
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
||||||
m_Sessions.swap (sessions);
|
for (auto& it: m_Sessions)
|
||||||
}
|
|
||||||
for (auto& it: sessions)
|
|
||||||
it.second->Close ();
|
it.second->Close ();
|
||||||
|
m_Sessions.clear ();
|
||||||
|
}
|
||||||
StopIOService ();
|
StopIOService ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user