mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
17 Commits
959ef208a3
...
6f11fcdf7e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f11fcdf7e | ||
|
|
72ff0b9fbb | ||
|
|
b9c9988ff4 | ||
|
|
1bb5ad22af | ||
|
|
4fa5cec0dc | ||
|
|
1e7254dfaa | ||
|
|
ca0818af7e | ||
|
|
b3d09513b8 | ||
|
|
2857a163e9 | ||
|
|
cba7e5350d | ||
|
|
29a5effabb | ||
|
|
39e07ac265 | ||
|
|
57986bd348 | ||
|
|
5e301937f2 | ||
|
|
4edde333ad | ||
|
|
c600b834e3 | ||
|
|
17399da399 |
13
contrib/docker/docker-compose.yml
Normal file
13
contrib/docker/docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
i2pd:
|
||||
container_name: i2pd2
|
||||
image: purplei2p/i2pd
|
||||
#optional
|
||||
entrypoint: ["./entrypoint.sh", "--loglevel error"]
|
||||
ports:
|
||||
- 127.0.0.1:7656:7656
|
||||
- 127.0.0.1:7070:7070
|
||||
- 127.0.0.1:4444:4444
|
||||
volumes:
|
||||
- /path/to/i2pd/data:/home/i2pd/data # make sure data directory and it's contents are owned by 100:65533
|
||||
- /path/to/i2pd/i2pd_certificates:/i2pd_certificates # make sure i2pd_certificates is owned by root:root and 755 permissions on the directory
|
||||
@@ -27,18 +27,15 @@ namespace data
|
||||
|
||||
size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if ( len < DEFAULT_IDENTITY_SIZE ) {
|
||||
// buffer too small, don't overflow
|
||||
return 0;
|
||||
}
|
||||
memcpy (publicKey, buf, DEFAULT_IDENTITY_SIZE);
|
||||
if (len < DEFAULT_IDENTITY_SIZE) return 0; // buffer too small, don't overflow
|
||||
memcpy (this, buf, DEFAULT_IDENTITY_SIZE);
|
||||
return DEFAULT_IDENTITY_SIZE;
|
||||
}
|
||||
|
||||
IdentHash Identity::Hash () const
|
||||
{
|
||||
IdentHash hash;
|
||||
SHA256(publicKey, DEFAULT_IDENTITY_SIZE, hash);
|
||||
SHA256((const uint8_t *)this, DEFAULT_IDENTITY_SIZE, hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -819,15 +819,20 @@ namespace transport
|
||||
Terminate ();
|
||||
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 ())
|
||||
{
|
||||
// received RouterInfo is older than one in netdb
|
||||
profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
|
||||
if (profile && profile->IsDuplicated ())
|
||||
isOlder = true;
|
||||
if (ri1->HasProfile ())
|
||||
{
|
||||
SendTerminationAndTerminate (eNTCP2Banned);
|
||||
return;
|
||||
auto profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
|
||||
if (profile && profile->IsDuplicated ())
|
||||
{
|
||||
SendTerminationAndTerminate (eNTCP2Banned);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -844,8 +849,12 @@ 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 (), addr->host.to_v6 ().to_bytes ().data (), 8)))) // temporary address
|
||||
{
|
||||
if (profile) // older router?
|
||||
profile->Duplicated (); // mark router as duplicated in profile
|
||||
if (isOlder) // older router?
|
||||
i2p::data::UpdateRouterProfile (ri1->GetIdentHash (),
|
||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
||||
{
|
||||
if (profile) profile->Duplicated (); // mark router as duplicated in profile
|
||||
});
|
||||
else
|
||||
LogPrint (eLogInfo, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ());
|
||||
SendTerminationAndTerminate (eNTCP2Banned);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <random>
|
||||
#include <boost/asio.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -40,7 +39,7 @@ namespace data
|
||||
|
||||
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr),
|
||||
m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true),
|
||||
m_LastExploratorySelectionUpdateTime (0)
|
||||
m_LastExploratorySelectionUpdateTime (0), m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -119,8 +118,9 @@ namespace data
|
||||
i2p::util::SetThreadName("NetDB");
|
||||
|
||||
uint64_t lastManage = 0;
|
||||
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (), lastObsoleteProfilesCleanup = lastProfilesCleanup;
|
||||
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0;
|
||||
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (),
|
||||
lastObsoleteProfilesCleanup = lastProfilesCleanup, lastApplyingProfileUpdates = lastProfilesCleanup;
|
||||
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0, applyingProfileUpdatesVariance = 0;
|
||||
|
||||
std::list<std::shared_ptr<const I2NPMessage> > msgs;
|
||||
while (m_IsRunning)
|
||||
@@ -181,7 +181,7 @@ namespace data
|
||||
LogPrint (eLogWarning, "NetDb: Can't persist profiles. Profiles are being saved to disk");
|
||||
}
|
||||
lastProfilesCleanup = mts;
|
||||
profilesCleanupVariance = rand () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE;
|
||||
profilesCleanupVariance = m_Rng () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE;
|
||||
}
|
||||
|
||||
if (mts >= lastObsoleteProfilesCleanup + (uint64_t)(i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_TIMEOUT + obsoleteProfilesCleanVariance)*1000)
|
||||
@@ -197,7 +197,20 @@ namespace data
|
||||
else
|
||||
LogPrint (eLogWarning, "NetDb: Can't delete profiles. Profiles are being deleted from disk");
|
||||
lastObsoleteProfilesCleanup = mts;
|
||||
obsoleteProfilesCleanVariance = rand () % i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE;
|
||||
obsoleteProfilesCleanVariance = m_Rng () % 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)
|
||||
@@ -281,6 +294,7 @@ namespace data
|
||||
}
|
||||
else
|
||||
{
|
||||
r->CancelBufferToDelete (); // since an update received
|
||||
if (CheckLogLevel (eLogDebug))
|
||||
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
|
||||
updated = false;
|
||||
@@ -557,7 +571,7 @@ namespace data
|
||||
while(n > 0)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_RouterInfosMutex);
|
||||
uint32_t idx = rand () % m_RouterInfos.size ();
|
||||
uint32_t idx = m_Rng () % m_RouterInfos.size ();
|
||||
uint32_t i = 0;
|
||||
for (const auto & it : m_RouterInfos) {
|
||||
if(i >= idx) // are we at the random start point?
|
||||
@@ -660,15 +674,20 @@ namespace data
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update
|
||||
buffer = r->CopyBuffer ();
|
||||
r->ScheduleBufferToDelete ();
|
||||
}
|
||||
if (!i2p::transport::transports.IsConnected (ident))
|
||||
r->ScheduleBufferToDelete ();
|
||||
if (buffer)
|
||||
saveToDisk.push_back(std::make_pair(ident.ToBase64 (), buffer));
|
||||
saveToDisk.emplace_back(ident.ToBase64 (), buffer);
|
||||
}
|
||||
r->SetUpdated (false);
|
||||
updatedCount++;
|
||||
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 ())
|
||||
r->SetUnreachable (true);
|
||||
// make router reachable back if too few routers or floodfills
|
||||
@@ -696,18 +715,15 @@ namespace data
|
||||
r->SetUnreachable (true);
|
||||
}
|
||||
}
|
||||
// make router reachable back and don't delete buffer if connected now
|
||||
if ((r->IsUnreachable () || r->IsBufferScheduledToDelete ()) && i2p::transport::transports.IsConnected (ident))
|
||||
{
|
||||
// make router reachable back if connected now
|
||||
if (r->IsUnreachable () && i2p::transport::transports.IsConnected (ident))
|
||||
r->SetUnreachable (false);
|
||||
r->CancelBufferToDelete ();
|
||||
}
|
||||
|
||||
if (r->IsUnreachable ())
|
||||
{
|
||||
if (r->IsFloodfill ()) deletedFloodfillsCount++;
|
||||
// delete RI file
|
||||
removeFromDisk.push_back (ident.ToBase64());
|
||||
removeFromDisk.emplace_back (ident.ToBase64());
|
||||
deletedCount++;
|
||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||
}
|
||||
@@ -1334,7 +1350,7 @@ namespace data
|
||||
if (eligible.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE)
|
||||
{
|
||||
std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection),
|
||||
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, std::mt19937(ts));
|
||||
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, m_Rng);
|
||||
}
|
||||
else
|
||||
std::swap (m_ExploratorySelection, eligible);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <future>
|
||||
#include <random>
|
||||
|
||||
#include "Base.h"
|
||||
#include "Gzip.h"
|
||||
@@ -185,10 +186,11 @@ namespace data
|
||||
std::shared_ptr<NetDbRequests> m_Requests;
|
||||
|
||||
bool m_PersistProfiles;
|
||||
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_PersistingRouters;
|
||||
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_ApplyingProfileUpdates, m_PersistingRouters;
|
||||
|
||||
std::vector<std::shared_ptr<const RouterInfo> > m_ExploratorySelection;
|
||||
uint64_t m_LastExploratorySelectionUpdateTime; // in monotonic seconds
|
||||
std::mt19937 m_Rng;
|
||||
|
||||
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
|
||||
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -20,8 +20,10 @@ namespace i2p
|
||||
namespace data
|
||||
{
|
||||
RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct):
|
||||
m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_IsActive (true),
|
||||
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()), m_LastRequestTime (0), m_NumAttempts (0)
|
||||
m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct),
|
||||
m_IsActive (true), m_IsSentDirectly (false),
|
||||
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()),
|
||||
m_LastRequestTime (0), m_NumAttempts (0)
|
||||
{
|
||||
if (i2p::context.IsFloodfill ())
|
||||
m_ExcludedPeers.insert (i2p::context.GetIdentHash ()); // exclude self if floodfill
|
||||
@@ -46,6 +48,7 @@ namespace data
|
||||
m_ExcludedPeers.insert (router->GetIdentHash ());
|
||||
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
m_NumAttempts++;
|
||||
m_IsSentDirectly = false;
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -56,6 +59,7 @@ namespace data
|
||||
m_ExcludedPeers.insert (floodfill);
|
||||
m_NumAttempts++;
|
||||
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
m_IsSentDirectly = true;
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -222,7 +226,8 @@ namespace data
|
||||
bool done = false;
|
||||
if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME)
|
||||
{
|
||||
if (ts > dest->GetLastRequestTime () + MIN_REQUEST_TIME) // try next floodfill if no response after min interval
|
||||
if (ts > dest->GetLastRequestTime () + (dest->IsSentDirectly () ? MIN_DIRECT_REQUEST_TIME : MIN_REQUEST_TIME))
|
||||
// try next floodfill if no response after min interval
|
||||
done = !SendNextRequest (dest);
|
||||
}
|
||||
else // request is expired
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -28,6 +28,7 @@ namespace data
|
||||
const uint64_t MANAGE_REQUESTS_INTERVAL_VARIANCE = 300; // in milliseconds
|
||||
const uint64_t MIN_REQUEST_TIME = 1200; // in milliseconds
|
||||
const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS * (MIN_REQUEST_TIME + MANAGE_REQUESTS_INTERVAL + MANAGE_REQUESTS_INTERVAL_VARIANCE);
|
||||
const uint64_t MIN_DIRECT_REQUEST_TIME = 600; // in milliseconds
|
||||
const uint64_t EXPLORATORY_REQUEST_INTERVAL = 55; // in seconds
|
||||
const uint64_t EXPLORATORY_REQUEST_INTERVAL_VARIANCE = 170; // in seconds
|
||||
const uint64_t DISCOVERED_REQUEST_INTERVAL = 360; // in milliseconds
|
||||
@@ -52,6 +53,7 @@ namespace data
|
||||
bool IsExploratory () const { return m_IsExploratory; };
|
||||
bool IsDirect () const { return m_IsDirect; };
|
||||
bool IsActive () const { return m_IsActive; };
|
||||
bool IsSentDirectly () const { return m_IsSentDirectly; };
|
||||
bool IsExcluded (const IdentHash& ident) const;
|
||||
uint64_t GetCreationTime () const { return m_CreationTime; };
|
||||
uint64_t GetLastRequestTime () const { return m_LastRequestTime; };
|
||||
@@ -70,7 +72,7 @@ namespace data
|
||||
private:
|
||||
|
||||
IdentHash m_Destination;
|
||||
bool m_IsExploratory, m_IsDirect, m_IsActive;
|
||||
bool m_IsExploratory, m_IsDirect, m_IsActive, m_IsSentDirectly;
|
||||
std::unordered_set<IdentHash> m_ExcludedPeers;
|
||||
uint64_t m_CreationTime, m_LastRequestTime; // in milliseconds
|
||||
std::list<RequestComplete> m_RequestComplete;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -27,7 +27,9 @@ namespace data
|
||||
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::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 ():
|
||||
m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0),
|
||||
m_LastUpdateTime (i2p::util::GetSecondsSinceEpoch ()),
|
||||
@@ -259,14 +261,14 @@ namespace data
|
||||
}
|
||||
auto profile = netdb.NewRouterProfile ();
|
||||
profile->Load (identHash); // if possible
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
||||
g_Profiles.emplace (identHash, profile);
|
||||
return profile;
|
||||
}
|
||||
|
||||
bool IsRouterBanned (const IdentHash& identHash)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
||||
auto it = g_Profiles.find (identHash);
|
||||
if (it != g_Profiles.end ())
|
||||
return it->second->IsUnreachable ();
|
||||
@@ -278,7 +280,7 @@ namespace data
|
||||
g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir());
|
||||
g_ProfilesStorage.Init(i2p::data::GetBase64SubstitutionTable(), 64);
|
||||
}
|
||||
|
||||
|
||||
static void SaveProfilesToDisk (std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > >&& profiles)
|
||||
{
|
||||
for (auto& it: profiles)
|
||||
@@ -290,7 +292,7 @@ namespace data
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > > tmp;
|
||||
{
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
||||
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
||||
{
|
||||
if (ts - it->second->GetLastUpdateTime () > PEER_PROFILE_PERSIST_INTERVAL)
|
||||
@@ -312,7 +314,7 @@ namespace data
|
||||
{
|
||||
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > tmp;
|
||||
{
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
||||
std::swap (tmp, g_Profiles);
|
||||
}
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
@@ -347,7 +349,7 @@ namespace data
|
||||
{
|
||||
{
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
||||
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
||||
{
|
||||
if (ts - it->second->GetLastUpdateTime () >= PEER_PROFILE_EXPIRATION_TIMEOUT)
|
||||
@@ -359,5 +361,47 @@ namespace data
|
||||
|
||||
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-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <functional>
|
||||
#include <boost/asio.hpp>
|
||||
#include "Identity.h"
|
||||
|
||||
@@ -44,6 +45,8 @@ namespace data
|
||||
const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes)
|
||||
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_APPLY_POSTPONED_TIMEOUT = 2100; // in milliseconds
|
||||
const int PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE = 500; // in milliseconds
|
||||
|
||||
class RouterProfile
|
||||
{
|
||||
@@ -108,6 +111,8 @@ namespace data
|
||||
std::future<void> DeleteObsoleteProfiles ();
|
||||
void SaveProfiles ();
|
||||
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-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
m_IsBufferScheduledToDelete = false;
|
||||
if (!m_Buffer)
|
||||
m_Buffer = NewBuffer ();
|
||||
if (len > m_Buffer->size ()) len = m_Buffer->size ();
|
||||
memcpy (m_Buffer->data (), buf, len);
|
||||
m_Buffer->SetBufferLen (len);
|
||||
m_IsBufferScheduledToDelete = false;
|
||||
}
|
||||
|
||||
std::shared_ptr<RouterInfo::Buffer> RouterInfo::CopyBuffer () const
|
||||
|
||||
@@ -890,7 +890,7 @@ namespace transport
|
||||
}
|
||||
|
||||
auto session = std::make_shared<SSU2Session> (*this, router, address);
|
||||
if (!isValidEndpoint && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
|
||||
if (!isValidEndpoint && router->HasProfile () && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
|
||||
{
|
||||
// router doesn't publish endpoint, but we connected before and hole punch might be alive
|
||||
auto ep = router->GetProfile ()->GetLastEndpoint ();
|
||||
|
||||
@@ -1178,13 +1178,18 @@ namespace transport
|
||||
LogPrint (eLogError, "SSU2: Couldn't update RouterInfo from SessionConfirmed in netdb");
|
||||
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 ())
|
||||
{
|
||||
// received RouterInfo is older than one in netdb
|
||||
profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
|
||||
if (profile && profile->IsDuplicated ())
|
||||
return false;
|
||||
isOlder = true;
|
||||
if (ri->HasProfile ())
|
||||
{
|
||||
auto profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
|
||||
if (profile && profile->IsDuplicated ())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ri = ri1;
|
||||
|
||||
@@ -1198,15 +1203,28 @@ namespace transport
|
||||
(!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
|
||||
{
|
||||
if (profile) // older router?
|
||||
profile->Duplicated (); // mark router as duplicated in profile
|
||||
if (isOlder) // older router?
|
||||
i2p::data::UpdateRouterProfile (ri->GetIdentHash (),
|
||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
||||
{
|
||||
if (profile) profile->Duplicated (); // mark router as duplicated in profile
|
||||
});
|
||||
else
|
||||
LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host,
|
||||
" and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));
|
||||
return false;
|
||||
}
|
||||
if (!m_Address->published)
|
||||
ri->GetProfile ()->SetLastEndpoint (m_RemoteEndpoint);
|
||||
{
|
||||
if (ri->HasProfile ())
|
||||
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 ());
|
||||
AdjustMaxPayloadSize ();
|
||||
m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -101,13 +101,13 @@ namespace tunnel
|
||||
TunnelMessageBlock block;
|
||||
block.deliveryType = eDeliveryTypeLocal;
|
||||
block.data = msg;
|
||||
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||
std::lock_guard<std::mutex> l(m_SendMutex);
|
||||
m_Gateway.PutTunnelDataMsg (block);
|
||||
}
|
||||
|
||||
void TransitTunnelGateway::FlushTunnelDataMsgs ()
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||
std::lock_guard<std::mutex> l(m_SendMutex);
|
||||
m_Gateway.SendBuffer ();
|
||||
}
|
||||
|
||||
@@ -130,14 +130,22 @@ namespace tunnel
|
||||
EncryptTunnelMsg (tunnelMsg, newMsg);
|
||||
|
||||
LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ());
|
||||
std::lock_guard<std::mutex> l(m_HandleMutex);
|
||||
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg);
|
||||
}
|
||||
|
||||
void TransitTunnelEndpoint::FlushTunnelDataMsgs ()
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_HandleMutex);
|
||||
m_Endpoint.FlushI2NPMsgs ();
|
||||
}
|
||||
|
||||
void TransitTunnelEndpoint::Cleanup ()
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_HandleMutex);
|
||||
m_Endpoint.Cleanup ();
|
||||
}
|
||||
|
||||
std::string TransitTunnelEndpoint::GetNextPeerName () const
|
||||
{
|
||||
auto hash = m_Endpoint.GetCurrentHash ();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -100,7 +100,7 @@ namespace tunnel
|
||||
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey),
|
||||
m_Endpoint (false) {}; // transit endpoint is always outbound
|
||||
|
||||
void Cleanup () override { m_Endpoint.Cleanup (); }
|
||||
void Cleanup () override;
|
||||
|
||||
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
|
||||
void FlushTunnelDataMsgs () override;
|
||||
@@ -109,6 +109,7 @@ namespace tunnel
|
||||
|
||||
private:
|
||||
|
||||
std::mutex m_HandleMutex;
|
||||
TunnelEndpoint m_Endpoint;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -160,7 +160,8 @@ namespace transport
|
||||
m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
|
||||
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -338,7 +339,7 @@ namespace transport
|
||||
|
||||
if (m_IsNAT)
|
||||
{
|
||||
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
|
||||
m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
|
||||
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
@@ -560,7 +561,14 @@ namespace transport
|
||||
bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer)
|
||||
{
|
||||
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->priority.empty ())
|
||||
@@ -647,7 +655,7 @@ namespace transport
|
||||
return true;
|
||||
}
|
||||
|
||||
void Transports::SetPriority (std::shared_ptr<Peer> peer) const
|
||||
void Transports::SetPriority (std::shared_ptr<Peer> peer)
|
||||
{
|
||||
static const std::vector<i2p::data::RouterInfo::SupportedTransports>
|
||||
ntcp2Priority =
|
||||
@@ -673,7 +681,7 @@ namespace transport
|
||||
peer->numAttempts = 0;
|
||||
peer->priority.clear ();
|
||||
bool isReal = peer->router->GetProfile ()->IsReal ();
|
||||
bool ssu2 = isReal ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real
|
||||
bool ssu2 = isReal ? (m_Rng () & 1) : false; // try NTCP2 if router is not confirmed real
|
||||
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
|
||||
if (directTransports)
|
||||
{
|
||||
@@ -701,7 +709,8 @@ namespace transport
|
||||
// try recently connected SSU2 if any
|
||||
auto supportedTransports = context.GetRouterInfo ().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 ();
|
||||
if (!ep.address ().is_unspecified () && ep.port ())
|
||||
@@ -791,7 +800,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||
testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||
if (m_Service)
|
||||
{
|
||||
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
||||
@@ -829,7 +838,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||
testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
|
||||
if (m_Service)
|
||||
{
|
||||
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
|
||||
@@ -886,7 +895,11 @@ namespace transport
|
||||
auto transport = peer->priority[peer->numAttempts-1];
|
||||
if (transport == i2p::data::RouterInfo::eNTCP2V4 ||
|
||||
transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh)
|
||||
peer->router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real
|
||||
i2p::data::UpdateRouterProfile (ident,
|
||||
[](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
|
||||
}
|
||||
peer->numAttempts = 0;
|
||||
@@ -921,7 +934,11 @@ namespace transport
|
||||
session->SendI2NPMessages (msgs); // send DatabaseStore
|
||||
}
|
||||
auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
|
||||
if (r) r->GetProfile ()->Connected ();
|
||||
i2p::data::UpdateRouterProfile (ident,
|
||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
||||
{
|
||||
if (profile) profile->Connected ();
|
||||
});
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
auto peer = std::make_shared<Peer>(r, ts);
|
||||
peer->sessions.push_back (session);
|
||||
@@ -955,8 +972,13 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it);
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_PeersMutex);
|
||||
m_Peers.erase (it);
|
||||
}
|
||||
// delete buffer of just disconnected router
|
||||
auto r = i2p::data::netdb.FindRouter (ident);
|
||||
if (r && !r->IsUpdated ()) r->ScheduleBufferToDelete ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1006,7 +1028,7 @@ namespace transport
|
||||
if (session)
|
||||
session->SendLocalRouterInfo (true);
|
||||
it->second->nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL +
|
||||
rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
|
||||
m_Rng() % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
@@ -1030,7 +1052,7 @@ namespace transport
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
{
|
||||
PeerTest ();
|
||||
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL));
|
||||
m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
|
||||
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
@@ -1177,7 +1199,7 @@ namespace transport
|
||||
}
|
||||
|
||||
/** XXX: if routes are not restricted this dies */
|
||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer() const
|
||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer()
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_FamilyMutex);
|
||||
@@ -1186,7 +1208,7 @@ namespace transport
|
||||
if(sz > 1)
|
||||
{
|
||||
auto it = m_TrustedFamilies.begin ();
|
||||
std::advance(it, rand() % sz);
|
||||
std::advance(it, m_Rng() % sz);
|
||||
fam = *it;
|
||||
}
|
||||
else if (sz == 1)
|
||||
@@ -1204,7 +1226,7 @@ namespace transport
|
||||
if(sz == 1)
|
||||
return i2p::data::netdb.FindRouter(m_TrustedRouters[0]);
|
||||
auto it = m_TrustedRouters.begin();
|
||||
std::advance(it, rand() % sz);
|
||||
std::advance(it, m_Rng() % sz);
|
||||
return i2p::data::netdb.FindRouter(*it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <random>
|
||||
#include <boost/asio.hpp>
|
||||
#include "TransportSession.h"
|
||||
#include "SSU2.h"
|
||||
@@ -106,7 +107,8 @@ namespace transport
|
||||
};
|
||||
|
||||
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
|
||||
const int PEER_TEST_INTERVAL = 71; // in minutes
|
||||
const int PEER_TEST_INTERVAL = 68*60; // in seconds
|
||||
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_VARIANCE = 30; // in milliseconds
|
||||
const int MAX_NUM_DELAYED_MESSAGES = 150;
|
||||
@@ -168,7 +170,7 @@ namespace transport
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
|
||||
|
||||
/** get a trusted first hop for restricted routes */
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
|
||||
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer();
|
||||
/** do we want to use restricted routes? */
|
||||
bool RoutesRestricted() const;
|
||||
/** restrict routes to use only these router families for first hops */
|
||||
@@ -191,7 +193,7 @@ namespace transport
|
||||
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);
|
||||
bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer);
|
||||
void SetPriority (std::shared_ptr<Peer> peer) const;
|
||||
void SetPriority (std::shared_ptr<Peer> peer);
|
||||
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
|
||||
void HandlePeerTestTimer (const boost::system::error_code& ecode);
|
||||
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
|
||||
@@ -239,6 +241,7 @@ namespace transport
|
||||
mutable std::mutex m_TrustedRoutersMutex;
|
||||
|
||||
i2p::I2NPMessagesHandler m_LoopbackHandler;
|
||||
std::mt19937 m_Rng;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -179,9 +179,12 @@ namespace tunnel
|
||||
{
|
||||
uint8_t ret = hop->GetRetCode (msg + 1);
|
||||
LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
|
||||
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
||||
if (profile)
|
||||
profile->TunnelBuildResponse (ret);
|
||||
if (hop->ident)
|
||||
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
|
||||
[ret](std::shared_ptr<i2p::data::RouterProfile> profile)
|
||||
{
|
||||
if (profile) profile->TunnelBuildResponse (ret);
|
||||
});
|
||||
if (ret)
|
||||
// if any of participants declined the tunnel is not established
|
||||
established = false;
|
||||
@@ -743,11 +746,11 @@ namespace tunnel
|
||||
while (hop)
|
||||
{
|
||||
if (hop->ident)
|
||||
{
|
||||
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
||||
if (profile)
|
||||
profile->TunnelNonReplied ();
|
||||
}
|
||||
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
|
||||
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
||||
{
|
||||
if (profile) profile->TunnelNonReplied ();
|
||||
});
|
||||
hop = hop->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* 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);
|
||||
if (hop)
|
||||
{
|
||||
if (!hop->GetProfile ()->IsBad ())
|
||||
if (!hop->HasProfile () || !hop->GetProfile ()->IsBad ())
|
||||
break;
|
||||
}
|
||||
else if (tryClient)
|
||||
@@ -588,7 +588,7 @@ namespace tunnel
|
||||
(inbound && i2p::transport::transports.GetNumPeers () > 25))
|
||||
{
|
||||
auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ());
|
||||
if (r && r->IsECIES () && !r->GetProfile ()->IsBad () &&
|
||||
if (r && r->IsECIES () && (!r->HasProfile () || !r->GetProfile ()->IsBad ()) &&
|
||||
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4
|
||||
{
|
||||
prevHop = r;
|
||||
|
||||
@@ -764,6 +764,7 @@ namespace client
|
||||
void I2CPSession::AddRoutingSession (const i2p::data::IdentHash& signingKey, std::shared_ptr<i2p::garlic::GarlicRoutingSession> remoteSession)
|
||||
{
|
||||
if (!remoteSession) return;
|
||||
remoteSession->SetAckRequestInterval (I2CP_SESSION_ACK_REQUEST_INTERVAL);
|
||||
std::lock_guard<std::mutex> l(m_RoutingSessionsMutex);
|
||||
m_RoutingSessions[signingKey] = remoteSession;
|
||||
}
|
||||
@@ -1110,12 +1111,12 @@ namespace client
|
||||
void I2CPServer::Stop ()
|
||||
{
|
||||
m_Acceptor.cancel ();
|
||||
{
|
||||
auto sessions = m_Sessions;
|
||||
for (auto& it: sessions)
|
||||
it.second->Stop ();
|
||||
}
|
||||
m_Sessions.clear ();
|
||||
|
||||
decltype(m_Sessions) sessions;
|
||||
m_Sessions.swap (sessions);
|
||||
for (auto& it: sessions)
|
||||
it.second->Stop ();
|
||||
|
||||
StopIOService ();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace client
|
||||
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
|
||||
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M
|
||||
const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds
|
||||
const int I2CP_SESSION_ACK_REQUEST_INTERVAL = 12100; // in milliseconds
|
||||
|
||||
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
|
||||
const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -1350,12 +1350,14 @@ namespace client
|
||||
LogPrint (eLogError, "SAM: Runtime exception: ", ex.what ());
|
||||
}
|
||||
|
||||
decltype(m_Sessions) sessions;
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
||||
for (auto& it: m_Sessions)
|
||||
it.second->Close ();
|
||||
m_Sessions.clear ();
|
||||
}
|
||||
m_Sessions.swap (sessions);
|
||||
}
|
||||
for (auto& it: sessions)
|
||||
it.second->Close ();
|
||||
|
||||
StopIOService ();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user