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)
|
size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
if ( len < DEFAULT_IDENTITY_SIZE ) {
|
if (len < DEFAULT_IDENTITY_SIZE) return 0; // buffer too small, don't overflow
|
||||||
// buffer too small, don't overflow
|
memcpy (this, buf, DEFAULT_IDENTITY_SIZE);
|
||||||
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(publicKey, DEFAULT_IDENTITY_SIZE, hash);
|
SHA256((const uint8_t *)this, DEFAULT_IDENTITY_SIZE, hash);
|
||||||
return 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
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -819,15 +819,20 @@ 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
|
||||||
profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
|
isOlder = true;
|
||||||
if (profile && profile->IsDuplicated ())
|
if (ri1->HasProfile ())
|
||||||
{
|
{
|
||||||
SendTerminationAndTerminate (eNTCP2Banned);
|
auto profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
|
||||||
return;
|
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 () + 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 (profile) // older router?
|
if (isOlder) // older router?
|
||||||
profile->Duplicated (); // mark router as duplicated in profile
|
i2p::data::UpdateRouterProfile (ri1->GetIdentHash (),
|
||||||
|
[](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);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#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>
|
||||||
|
|
||||||
@@ -40,7 +39,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_LastExploratorySelectionUpdateTime (0), m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +118,9 @@ namespace data
|
|||||||
i2p::util::SetThreadName("NetDB");
|
i2p::util::SetThreadName("NetDB");
|
||||||
|
|
||||||
uint64_t lastManage = 0;
|
uint64_t lastManage = 0;
|
||||||
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (), lastObsoleteProfilesCleanup = lastProfilesCleanup;
|
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (),
|
||||||
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0;
|
lastObsoleteProfilesCleanup = lastProfilesCleanup, lastApplyingProfileUpdates = lastProfilesCleanup;
|
||||||
|
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 = 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)
|
if (mts >= lastObsoleteProfilesCleanup + (uint64_t)(i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_TIMEOUT + obsoleteProfilesCleanVariance)*1000)
|
||||||
@@ -197,7 +197,20 @@ 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 = 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)
|
catch (std::exception& ex)
|
||||||
@@ -281,6 +294,7 @@ 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;
|
||||||
@@ -557,7 +571,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 = rand () % m_RouterInfos.size ();
|
uint32_t idx = m_Rng () % 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?
|
||||||
@@ -660,15 +674,20 @@ 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 ();
|
||||||
r->ScheduleBufferToDelete ();
|
|
||||||
}
|
}
|
||||||
|
if (!i2p::transport::transports.IsConnected (ident))
|
||||||
|
r->ScheduleBufferToDelete ();
|
||||||
if (buffer)
|
if (buffer)
|
||||||
saveToDisk.push_back(std::make_pair(ident.ToBase64 (), buffer));
|
saveToDisk.emplace_back(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
|
||||||
@@ -696,18 +715,15 @@ namespace data
|
|||||||
r->SetUnreachable (true);
|
r->SetUnreachable (true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// make router reachable back and don't delete buffer if connected now
|
// make router reachable back if connected now
|
||||||
if ((r->IsUnreachable () || r->IsBufferScheduledToDelete ()) && i2p::transport::transports.IsConnected (ident))
|
if (r->IsUnreachable () && i2p::transport::transports.IsConnected (ident))
|
||||||
{
|
|
||||||
r->SetUnreachable (false);
|
r->SetUnreachable (false);
|
||||||
r->CancelBufferToDelete ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r->IsUnreachable ())
|
if (r->IsUnreachable ())
|
||||||
{
|
{
|
||||||
if (r->IsFloodfill ()) deletedFloodfillsCount++;
|
if (r->IsFloodfill ()) deletedFloodfillsCount++;
|
||||||
// delete RI file
|
// delete RI file
|
||||||
removeFromDisk.push_back (ident.ToBase64());
|
removeFromDisk.emplace_back (ident.ToBase64());
|
||||||
deletedCount++;
|
deletedCount++;
|
||||||
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
|
||||||
}
|
}
|
||||||
@@ -1334,7 +1350,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, std::mt19937(ts));
|
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, m_Rng);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::swap (m_ExploratorySelection, eligible);
|
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
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#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"
|
||||||
@@ -185,10 +186,11 @@ 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_PersistingRouters;
|
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_ApplyingProfileUpdates, 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-2024, The PurpleI2P Project
|
* Copyright (c) 2013-2025, 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,8 +20,10 @@ namespace i2p
|
|||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct):
|
RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct):
|
||||||
m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_IsActive (true),
|
m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct),
|
||||||
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()), m_LastRequestTime (0), m_NumAttempts (0)
|
m_IsActive (true), m_IsSentDirectly (false),
|
||||||
|
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()),
|
||||||
|
m_LastRequestTime (0), m_NumAttempts (0)
|
||||||
{
|
{
|
||||||
if (i2p::context.IsFloodfill ())
|
if (i2p::context.IsFloodfill ())
|
||||||
m_ExcludedPeers.insert (i2p::context.GetIdentHash ()); // exclude self if floodfill
|
m_ExcludedPeers.insert (i2p::context.GetIdentHash ()); // exclude self if floodfill
|
||||||
@@ -46,6 +48,7 @@ namespace data
|
|||||||
m_ExcludedPeers.insert (router->GetIdentHash ());
|
m_ExcludedPeers.insert (router->GetIdentHash ());
|
||||||
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
|
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
m_NumAttempts++;
|
m_NumAttempts++;
|
||||||
|
m_IsSentDirectly = false;
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +59,7 @@ namespace data
|
|||||||
m_ExcludedPeers.insert (floodfill);
|
m_ExcludedPeers.insert (floodfill);
|
||||||
m_NumAttempts++;
|
m_NumAttempts++;
|
||||||
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
|
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
m_IsSentDirectly = true;
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +226,8 @@ namespace data
|
|||||||
bool done = false;
|
bool done = false;
|
||||||
if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME)
|
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);
|
done = !SendNextRequest (dest);
|
||||||
}
|
}
|
||||||
else // request is expired
|
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
|
* 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 MANAGE_REQUESTS_INTERVAL_VARIANCE = 300; // in milliseconds
|
||||||
const uint64_t MIN_REQUEST_TIME = 1200; // 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 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 = 55; // in seconds
|
||||||
const uint64_t EXPLORATORY_REQUEST_INTERVAL_VARIANCE = 170; // in seconds
|
const uint64_t EXPLORATORY_REQUEST_INTERVAL_VARIANCE = 170; // in seconds
|
||||||
const uint64_t DISCOVERED_REQUEST_INTERVAL = 360; // in milliseconds
|
const uint64_t DISCOVERED_REQUEST_INTERVAL = 360; // in milliseconds
|
||||||
@@ -52,6 +53,7 @@ namespace data
|
|||||||
bool IsExploratory () const { return m_IsExploratory; };
|
bool IsExploratory () const { return m_IsExploratory; };
|
||||||
bool IsDirect () const { return m_IsDirect; };
|
bool IsDirect () const { return m_IsDirect; };
|
||||||
bool IsActive () const { return m_IsActive; };
|
bool IsActive () const { return m_IsActive; };
|
||||||
|
bool IsSentDirectly () const { return m_IsSentDirectly; };
|
||||||
bool IsExcluded (const IdentHash& ident) const;
|
bool IsExcluded (const IdentHash& ident) const;
|
||||||
uint64_t GetCreationTime () const { return m_CreationTime; };
|
uint64_t GetCreationTime () const { return m_CreationTime; };
|
||||||
uint64_t GetLastRequestTime () const { return m_LastRequestTime; };
|
uint64_t GetLastRequestTime () const { return m_LastRequestTime; };
|
||||||
@@ -70,7 +72,7 @@ namespace data
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
IdentHash m_Destination;
|
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;
|
std::unordered_set<IdentHash> m_ExcludedPeers;
|
||||||
uint64_t m_CreationTime, m_LastRequestTime; // in milliseconds
|
uint64_t m_CreationTime, m_LastRequestTime; // in milliseconds
|
||||||
std::list<RequestComplete> m_RequestComplete;
|
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
|
* 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 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),
|
||||||
m_LastUpdateTime (i2p::util::GetSecondsSinceEpoch ()),
|
m_LastUpdateTime (i2p::util::GetSecondsSinceEpoch ()),
|
||||||
@@ -259,14 +261,14 @@ namespace data
|
|||||||
}
|
}
|
||||||
auto profile = netdb.NewRouterProfile ();
|
auto profile = netdb.NewRouterProfile ();
|
||||||
profile->Load (identHash); // if possible
|
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);
|
g_Profiles.emplace (identHash, profile);
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRouterBanned (const IdentHash& identHash)
|
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);
|
auto it = g_Profiles.find (identHash);
|
||||||
if (it != g_Profiles.end ())
|
if (it != g_Profiles.end ())
|
||||||
return it->second->IsUnreachable ();
|
return it->second->IsUnreachable ();
|
||||||
@@ -278,7 +280,7 @@ namespace data
|
|||||||
g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir());
|
g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir());
|
||||||
g_ProfilesStorage.Init(i2p::data::GetBase64SubstitutionTable(), 64);
|
g_ProfilesStorage.Init(i2p::data::GetBase64SubstitutionTable(), 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SaveProfilesToDisk (std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > >&& profiles)
|
static void SaveProfilesToDisk (std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > >&& profiles)
|
||||||
{
|
{
|
||||||
for (auto& it: profiles)
|
for (auto& it: profiles)
|
||||||
@@ -290,7 +292,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::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 ();)
|
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)
|
||||||
@@ -312,7 +314,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::unique_lock<std::mutex> l(g_ProfilesMutex);
|
std::lock_guard<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 ();
|
||||||
@@ -347,7 +349,7 @@ namespace data
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
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 ();)
|
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)
|
||||||
@@ -359,5 +361,47 @@ 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-2024, The PurpleI2P Project
|
* Copyright (c) 2013-2025, 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,6 +11,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <functional>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
|
||||||
@@ -44,6 +45,8 @@ 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
|
||||||
{
|
{
|
||||||
@@ -108,6 +111,8 @@ 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-2024, The PurpleI2P Project
|
* Copyright (c) 2013-2025, 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
|
||||||
|
|||||||
@@ -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->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
|
// 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 ();
|
||||||
|
|||||||
@@ -1178,13 +1178,18 @@ 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
|
||||||
profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
|
isOlder = true;
|
||||||
if (profile && profile->IsDuplicated ())
|
if (ri->HasProfile ())
|
||||||
return false;
|
{
|
||||||
|
auto profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
|
||||||
|
if (profile && profile->IsDuplicated ())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ri = ri1;
|
ri = ri1;
|
||||||
|
|
||||||
@@ -1198,15 +1203,28 @@ 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 (profile) // older router?
|
if (isOlder) // older router?
|
||||||
profile->Duplicated (); // mark router as duplicated in profile
|
i2p::data::UpdateRouterProfile (ri->GetIdentHash (),
|
||||||
|
[](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)
|
||||||
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 ());
|
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
|
||||||
|
|||||||
@@ -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
|
* 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::unique_lock<std::mutex> l(m_SendMutex);
|
std::lock_guard<std::mutex> l(m_SendMutex);
|
||||||
m_Gateway.PutTunnelDataMsg (block);
|
m_Gateway.PutTunnelDataMsg (block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitTunnelGateway::FlushTunnelDataMsgs ()
|
void TransitTunnelGateway::FlushTunnelDataMsgs ()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_SendMutex);
|
std::lock_guard<std::mutex> l(m_SendMutex);
|
||||||
m_Gateway.SendBuffer ();
|
m_Gateway.SendBuffer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,14 +130,22 @@ 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-2024, The PurpleI2P Project
|
* Copyright (c) 2013-2025, 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 { m_Endpoint.Cleanup (); }
|
void Cleanup () override;
|
||||||
|
|
||||||
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,6 +109,7 @@ namespace tunnel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
std::mutex m_HandleMutex;
|
||||||
TunnelEndpoint m_Endpoint;
|
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
|
* 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_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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +339,7 @@ namespace transport
|
|||||||
|
|
||||||
if (m_IsNAT)
|
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));
|
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)
|
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 ())
|
||||||
@@ -647,7 +655,7 @@ namespace transport
|
|||||||
return true;
|
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>
|
static const std::vector<i2p::data::RouterInfo::SupportedTransports>
|
||||||
ntcp2Priority =
|
ntcp2Priority =
|
||||||
@@ -673,7 +681,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 ? (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;
|
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
|
||||||
if (directTransports)
|
if (directTransports)
|
||||||
{
|
{
|
||||||
@@ -701,7 +709,8 @@ 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 ())
|
||||||
@@ -791,7 +800,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
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)
|
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);
|
||||||
@@ -829,7 +838,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
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)
|
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);
|
||||||
@@ -886,7 +895,11 @@ 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)
|
||||||
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
|
i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable
|
||||||
}
|
}
|
||||||
peer->numAttempts = 0;
|
peer->numAttempts = 0;
|
||||||
@@ -921,7 +934,11 @@ 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
|
||||||
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 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);
|
||||||
@@ -955,8 +972,13 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
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)
|
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 +
|
||||||
rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
|
m_Rng() % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
@@ -1030,7 +1052,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::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));
|
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 */
|
/** 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);
|
std::lock_guard<std::mutex> l(m_FamilyMutex);
|
||||||
@@ -1186,7 +1208,7 @@ namespace transport
|
|||||||
if(sz > 1)
|
if(sz > 1)
|
||||||
{
|
{
|
||||||
auto it = m_TrustedFamilies.begin ();
|
auto it = m_TrustedFamilies.begin ();
|
||||||
std::advance(it, rand() % sz);
|
std::advance(it, m_Rng() % sz);
|
||||||
fam = *it;
|
fam = *it;
|
||||||
}
|
}
|
||||||
else if (sz == 1)
|
else if (sz == 1)
|
||||||
@@ -1204,7 +1226,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, rand() % sz);
|
std::advance(it, m_Rng() % sz);
|
||||||
return i2p::data::netdb.FindRouter(*it);
|
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
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#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"
|
||||||
@@ -106,7 +107,8 @@ 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 = 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 = 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;
|
||||||
@@ -168,7 +170,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() const;
|
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer();
|
||||||
/** 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 */
|
||||||
@@ -191,7 +193,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) const;
|
void SetPriority (std::shared_ptr<Peer> peer);
|
||||||
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);
|
||||||
@@ -239,6 +241,7 @@ 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-2024, The PurpleI2P Project
|
* Copyright (c) 2013-2025, 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,9 +179,12 @@ 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);
|
||||||
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
if (hop->ident)
|
||||||
if (profile)
|
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
|
||||||
profile->TunnelBuildResponse (ret);
|
[ret](std::shared_ptr<i2p::data::RouterProfile> profile)
|
||||||
|
{
|
||||||
|
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;
|
||||||
@@ -743,11 +746,11 @@ namespace tunnel
|
|||||||
while (hop)
|
while (hop)
|
||||||
{
|
{
|
||||||
if (hop->ident)
|
if (hop->ident)
|
||||||
{
|
i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
|
||||||
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ());
|
[](std::shared_ptr<i2p::data::RouterProfile> profile)
|
||||||
if (profile)
|
{
|
||||||
profile->TunnelNonReplied ();
|
if (profile) profile->TunnelNonReplied ();
|
||||||
}
|
});
|
||||||
hop = hop->next;
|
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
|
* 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->GetProfile ()->IsBad ())
|
if (!hop->HasProfile () || !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->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
|
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4
|
||||||
{
|
{
|
||||||
prevHop = r;
|
prevHop = r;
|
||||||
|
|||||||
@@ -764,6 +764,7 @@ namespace client
|
|||||||
void I2CPSession::AddRoutingSession (const i2p::data::IdentHash& signingKey, std::shared_ptr<i2p::garlic::GarlicRoutingSession> remoteSession)
|
void I2CPSession::AddRoutingSession (const i2p::data::IdentHash& signingKey, std::shared_ptr<i2p::garlic::GarlicRoutingSession> remoteSession)
|
||||||
{
|
{
|
||||||
if (!remoteSession) return;
|
if (!remoteSession) return;
|
||||||
|
remoteSession->SetAckRequestInterval (I2CP_SESSION_ACK_REQUEST_INTERVAL);
|
||||||
std::lock_guard<std::mutex> l(m_RoutingSessionsMutex);
|
std::lock_guard<std::mutex> l(m_RoutingSessionsMutex);
|
||||||
m_RoutingSessions[signingKey] = remoteSession;
|
m_RoutingSessions[signingKey] = remoteSession;
|
||||||
}
|
}
|
||||||
@@ -1110,12 +1111,12 @@ namespace client
|
|||||||
void I2CPServer::Stop ()
|
void I2CPServer::Stop ()
|
||||||
{
|
{
|
||||||
m_Acceptor.cancel ();
|
m_Acceptor.cancel ();
|
||||||
{
|
|
||||||
auto sessions = m_Sessions;
|
decltype(m_Sessions) sessions;
|
||||||
for (auto& it: sessions)
|
m_Sessions.swap (sessions);
|
||||||
it.second->Stop ();
|
for (auto& it: sessions)
|
||||||
}
|
it.second->Stop ();
|
||||||
m_Sessions.clear ();
|
|
||||||
StopIOService ();
|
StopIOService ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace client
|
|||||||
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
|
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
|
||||||
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M
|
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_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_LENGTH_OFFSET = 0;
|
||||||
const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4;
|
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
|
* 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 ());
|
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);
|
||||||
for (auto& it: m_Sessions)
|
m_Sessions.swap (sessions);
|
||||||
it.second->Close ();
|
}
|
||||||
m_Sessions.clear ();
|
for (auto& it: sessions)
|
||||||
}
|
it.second->Close ();
|
||||||
|
|
||||||
StopIOService ();
|
StopIOService ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user