mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
21 Commits
69015adbe5
...
3e356200fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e356200fe | ||
|
|
ef19a85fc0 | ||
|
|
2ce3145195 | ||
|
|
b8d74dab47 | ||
|
|
e8f5efd156 | ||
|
|
57aa8b3de8 | ||
|
|
972b66f9a5 | ||
|
|
eadeea76e7 | ||
|
|
da7d3c55b0 | ||
|
|
60d3e4d963 | ||
|
|
adc230acde | ||
|
|
e4ba07a540 | ||
|
|
93ec5ac5c4 | ||
|
|
774c606b09 | ||
|
|
1bff42042d | ||
|
|
daeb177579 | ||
|
|
5d7a062f1b | ||
|
|
35f7bd5127 | ||
|
|
d411da451a | ||
|
|
588855c6a7 | ||
|
|
17399da399 |
@@ -59,7 +59,7 @@ get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
|||||||
# function returns an empty string via _git_dir_var.
|
# function returns an empty string via _git_dir_var.
|
||||||
#
|
#
|
||||||
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||||
# neither foo nor bar contain a file/directory .git. This wil return
|
# neither foo nor bar contain a file/directory .git. This will return
|
||||||
# C:/bla/.git
|
# C:/bla/.git
|
||||||
#
|
#
|
||||||
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||||
|
|||||||
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
|
||||||
@@ -5,6 +5,7 @@ port = 6668
|
|||||||
destination = irc.ilita.i2p
|
destination = irc.ilita.i2p
|
||||||
destinationport = 6667
|
destinationport = 6667
|
||||||
keys = irc-keys.dat
|
keys = irc-keys.dat
|
||||||
|
i2p.streaming.profile=2
|
||||||
|
|
||||||
#[IRC-IRC2P]
|
#[IRC-IRC2P]
|
||||||
#type = client
|
#type = client
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ namespace config {
|
|||||||
"https://reseed.onion.im/,"
|
"https://reseed.onion.im/,"
|
||||||
"https://i2pseed.creativecowpat.net:8443/,"
|
"https://i2pseed.creativecowpat.net:8443/,"
|
||||||
"https://reseed.i2pgit.org/,"
|
"https://reseed.i2pgit.org/,"
|
||||||
"https://banana.incognet.io/,"
|
"https://coconut.incognet.io/,"
|
||||||
"https://reseed-pl.i2pd.xyz/,"
|
"https://reseed-pl.i2pd.xyz/,"
|
||||||
"https://www2.mk16.de/,"
|
"https://www2.mk16.de/,"
|
||||||
"https://i2p.ghativega.in/,"
|
"https://i2p.ghativega.in/,"
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ namespace data
|
|||||||
|
|
||||||
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 ()), m_LastAccessTime (0),
|
||||||
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0),
|
m_LastPersistTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0),
|
||||||
m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false),
|
m_NumTunnelsNonReplied (0),m_NumTimesTaken (0), m_NumTimesRejected (0),
|
||||||
m_IsDuplicated (false)
|
m_HasConnected (false), m_IsDuplicated (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +80,7 @@ namespace data
|
|||||||
|
|
||||||
void RouterProfile::Load (const IdentHash& identHash)
|
void RouterProfile::Load (const IdentHash& identHash)
|
||||||
{
|
{
|
||||||
|
m_IsUpdated = false;
|
||||||
std::string ident = identHash.ToBase64 ();
|
std::string ident = identHash.ToBase64 ();
|
||||||
std::string path = g_ProfilesStorage.Path(ident);
|
std::string path = g_ProfilesStorage.Path(ident);
|
||||||
boost::property_tree::ptree pt;
|
boost::property_tree::ptree pt;
|
||||||
@@ -257,7 +258,10 @@ namespace data
|
|||||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||||
auto it = g_Profiles.find (identHash);
|
auto it = g_Profiles.find (identHash);
|
||||||
if (it != g_Profiles.end ())
|
if (it != g_Profiles.end ())
|
||||||
|
{
|
||||||
|
it->second->SetLastAccessTime (i2p::util::GetSecondsSinceEpoch ());
|
||||||
return it->second;
|
return it->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto profile = netdb.NewRouterProfile ();
|
auto profile = netdb.NewRouterProfile ();
|
||||||
profile->Load (identHash); // if possible
|
profile->Load (identHash); // if possible
|
||||||
@@ -275,6 +279,15 @@ namespace data
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsRouterDuplicated (const IdentHash& identHash)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
||||||
|
auto it = g_Profiles.find (identHash);
|
||||||
|
if (it != g_Profiles.end ())
|
||||||
|
return it->second->IsDuplicated ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void InitProfilesStorage ()
|
void InitProfilesStorage ()
|
||||||
{
|
{
|
||||||
g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir());
|
g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir());
|
||||||
@@ -295,12 +308,14 @@ namespace data
|
|||||||
std::lock_guard<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 (it->second->IsUpdated () && ts > it->second->GetLastPersistTime () + PEER_PROFILE_PERSIST_INTERVAL)
|
||||||
{
|
{
|
||||||
if (it->second->IsUpdated ())
|
tmp.push_back (std::make_pair (it->first, it->second));
|
||||||
tmp.push_back (std::make_pair (it->first, it->second));
|
it->second->SetLastPersistTime (ts);
|
||||||
it = g_Profiles.erase (it);
|
it->second->SetUpdated (false);
|
||||||
}
|
}
|
||||||
|
if (!it->second->IsUpdated () && ts > std::max (it->second->GetLastUpdateTime (), it->second->GetLastAccessTime ()) + PEER_PROFILE_PERSIST_INTERVAL)
|
||||||
|
it = g_Profiles.erase (it);
|
||||||
else
|
else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ namespace data
|
|||||||
|
|
||||||
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
|
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
|
||||||
bool IsUpdated () const { return m_IsUpdated; };
|
bool IsUpdated () const { return m_IsUpdated; };
|
||||||
|
void SetUpdated (bool updated) { m_IsUpdated = updated; }
|
||||||
|
uint64_t GetLastAccessTime () const { return m_LastAccessTime; };
|
||||||
|
void SetLastAccessTime (uint64_t ts) { m_LastAccessTime = ts; };
|
||||||
|
uint64_t GetLastPersistTime () const { return m_LastPersistTime; };
|
||||||
|
void SetLastPersistTime (uint64_t ts) { m_LastPersistTime = ts; };
|
||||||
|
|
||||||
bool IsUseful() const;
|
bool IsUseful() const;
|
||||||
bool IsDuplicated () const { return m_IsDuplicated; };
|
bool IsDuplicated () const { return m_IsDuplicated; };
|
||||||
@@ -91,7 +96,8 @@ namespace data
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsUpdated;
|
bool m_IsUpdated;
|
||||||
uint64_t m_LastDeclineTime, m_LastUnreachableTime, m_LastUpdateTime; // in seconds
|
uint64_t m_LastDeclineTime, m_LastUnreachableTime, m_LastUpdateTime,
|
||||||
|
m_LastAccessTime, m_LastPersistTime; // in seconds
|
||||||
// participation
|
// participation
|
||||||
uint32_t m_NumTunnelsAgreed;
|
uint32_t m_NumTunnelsAgreed;
|
||||||
uint32_t m_NumTunnelsDeclined;
|
uint32_t m_NumTunnelsDeclined;
|
||||||
@@ -107,6 +113,7 @@ namespace data
|
|||||||
|
|
||||||
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);
|
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);
|
||||||
bool IsRouterBanned (const IdentHash& identHash); // check only existing profiles
|
bool IsRouterBanned (const IdentHash& identHash); // check only existing profiles
|
||||||
|
bool IsRouterDuplicated (const IdentHash& identHash); // check only existing profiles
|
||||||
void InitProfilesStorage ();
|
void InitProfilesStorage ();
|
||||||
std::future<void> DeleteObsoleteProfiles ();
|
std::future<void> DeleteObsoleteProfiles ();
|
||||||
void SaveProfiles ();
|
void SaveProfiles ();
|
||||||
|
|||||||
@@ -33,13 +33,14 @@ namespace i2p
|
|||||||
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
|
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
|
||||||
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone),
|
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone),
|
||||||
m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID),
|
m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID),
|
||||||
m_PublishReplyToken (0), m_IsHiddenMode (false)
|
m_PublishReplyToken (0), m_IsHiddenMode (false),
|
||||||
|
m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL), m_IsSaving (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterContext::Init ()
|
void RouterContext::Init ()
|
||||||
{
|
{
|
||||||
srand (i2p::util::GetMillisecondsSinceEpoch () % 1000);
|
srand (m_Rng () % 1000);
|
||||||
m_StartupTime = i2p::util::GetMonotonicSeconds ();
|
m_StartupTime = i2p::util::GetMonotonicSeconds ();
|
||||||
|
|
||||||
if (!Load ())
|
if (!Load ())
|
||||||
@@ -253,11 +254,36 @@ namespace i2p
|
|||||||
|
|
||||||
void RouterContext::UpdateRouterInfo ()
|
void RouterContext::UpdateRouterInfo ()
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<i2p::data::RouterInfo::Buffer> buffer;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_RouterInfoMutex);
|
std::lock_guard<std::mutex> l(m_RouterInfoMutex);
|
||||||
m_RouterInfo.CreateBuffer (m_Keys);
|
m_RouterInfo.CreateBuffer (m_Keys);
|
||||||
|
buffer = m_RouterInfo.CopyBuffer ();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// update save buffer to latest
|
||||||
|
std::lock_guard<std::mutex> l(m_SaveBufferMutex);
|
||||||
|
m_SaveBuffer = buffer;
|
||||||
|
}
|
||||||
|
bool isSaving = false;
|
||||||
|
if (m_IsSaving.compare_exchange_strong (isSaving, true)) // try to save only if not being saved
|
||||||
|
{
|
||||||
|
auto savingRouterInfo = std::async (std::launch::async, [this]()
|
||||||
|
{
|
||||||
|
std::shared_ptr<i2p::data::RouterInfo::Buffer> buffer;
|
||||||
|
while (m_SaveBuffer)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> l(m_SaveBufferMutex);
|
||||||
|
buffer = m_SaveBuffer;
|
||||||
|
m_SaveBuffer = nullptr;
|
||||||
|
}
|
||||||
|
if (buffer)
|
||||||
|
i2p::data::RouterInfo::SaveToFile (i2p::fs::DataDirPath (ROUTER_INFO), buffer);
|
||||||
|
}
|
||||||
|
m_IsSaving = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
m_RouterInfo.SaveToFile (i2p::fs::DataDirPath (ROUTER_INFO));
|
|
||||||
m_LastUpdateTime = i2p::util::GetSecondsSinceEpoch ();
|
m_LastUpdateTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1359,7 +1385,7 @@ namespace i2p
|
|||||||
{
|
{
|
||||||
m_PublishTimer->cancel ();
|
m_PublishTimer->cancel ();
|
||||||
m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL +
|
m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL +
|
||||||
rand () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE));
|
m_Rng () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE));
|
||||||
m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishTimer,
|
m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishTimer,
|
||||||
this, std::placeholders::_1));
|
this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
@@ -1471,7 +1497,8 @@ namespace i2p
|
|||||||
if (m_CongestionUpdateTimer)
|
if (m_CongestionUpdateTimer)
|
||||||
{
|
{
|
||||||
m_CongestionUpdateTimer->cancel ();
|
m_CongestionUpdateTimer->cancel ();
|
||||||
m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONGESTION_UPDATE_INTERVAL));
|
m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(
|
||||||
|
ROUTER_INFO_CONGESTION_UPDATE_INTERVAL + m_Rng () % ROUTER_INFO_CONGESTION_UPDATE_INTERVAL_VARIANCE));
|
||||||
m_CongestionUpdateTimer->async_wait (std::bind (&RouterContext::HandleCongestionUpdateTimer,
|
m_CongestionUpdateTimer->async_wait (std::bind (&RouterContext::HandleCongestionUpdateTimer,
|
||||||
this, std::placeholders::_1));
|
this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <random>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
@@ -36,7 +37,8 @@ namespace garlic
|
|||||||
const int ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE = 105;// in seconds
|
const int ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE = 105;// in seconds
|
||||||
const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 1600; // in milliseconds
|
const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 1600; // in milliseconds
|
||||||
const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
|
const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
|
||||||
const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 12*60; // in seconds
|
const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 11*60; // in seconds
|
||||||
|
const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL_VARIANCE = 130; // in seconds
|
||||||
const int ROUTER_INFO_CLEANUP_INTERVAL = 102; // in seconds
|
const int ROUTER_INFO_CLEANUP_INTERVAL = 102; // in seconds
|
||||||
|
|
||||||
enum RouterStatus
|
enum RouterStatus
|
||||||
@@ -263,6 +265,10 @@ namespace garlic
|
|||||||
uint32_t m_PublishReplyToken;
|
uint32_t m_PublishReplyToken;
|
||||||
bool m_IsHiddenMode; // not publish
|
bool m_IsHiddenMode; // not publish
|
||||||
mutable std::mutex m_RouterInfoMutex;
|
mutable std::mutex m_RouterInfoMutex;
|
||||||
|
std::mt19937 m_Rng;
|
||||||
|
std::shared_ptr<i2p::data::RouterInfo::Buffer> m_SaveBuffer;
|
||||||
|
std::mutex m_SaveBufferMutex; // TODO: make m_SaveBuffer atomic
|
||||||
|
std::atomic<bool> m_IsSaving;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern RouterContext context;
|
extern RouterContext context;
|
||||||
|
|||||||
@@ -623,7 +623,8 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t packetNum = SendData (it->second->payload, it->second->payloadSize);
|
uint32_t packetNum = SendData (it->second->payload, it->second->payloadSize,
|
||||||
|
it->second->numResends > 1 ? SSU2_FLAG_IMMEDIATE_ACK_REQUESTED : 0);
|
||||||
it->second->numResends++;
|
it->second->numResends++;
|
||||||
it->second->sendTime = ts;
|
it->second->sendTime = ts;
|
||||||
resentPackets.emplace (packetNum, it->second);
|
resentPackets.emplace (packetNum, it->second);
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
|
|
||||||
TransitTunnels::TransitTunnels ():
|
TransitTunnels::TransitTunnels ():
|
||||||
m_IsRunning (false)
|
m_IsRunning (false), m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,19 +328,44 @@ namespace tunnel
|
|||||||
// check if we accept this tunnel
|
// check if we accept this tunnel
|
||||||
std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
|
std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
|
||||||
uint8_t retCode = 0;
|
uint8_t retCode = 0;
|
||||||
if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= CONGESTION_LEVEL_FULL)
|
if (i2p::context.AcceptsTunnels ())
|
||||||
|
{
|
||||||
|
auto congestionLevel = i2p::context.GetCongestionLevel (false);
|
||||||
|
if (congestionLevel < CONGESTION_LEVEL_FULL)
|
||||||
|
{
|
||||||
|
if (congestionLevel >= CONGESTION_LEVEL_MEDIUM)
|
||||||
|
{
|
||||||
|
// random reject depending on congestion level
|
||||||
|
int level = m_Rng () % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM;
|
||||||
|
if (congestionLevel > level)
|
||||||
|
retCode = 30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
retCode = 30;
|
||||||
|
}
|
||||||
|
else
|
||||||
retCode = 30;
|
retCode = 30;
|
||||||
|
|
||||||
if (!retCode)
|
if (!retCode)
|
||||||
{
|
{
|
||||||
// create new transit tunnel
|
i2p::data::IdentHash nextIdent(clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET);
|
||||||
transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
|
||||||
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
if (isEndpoint || !i2p::data::IsRouterDuplicated (nextIdent))
|
||||||
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
{
|
||||||
bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
// create new transit tunnel
|
||||||
layerKey, ivKey,
|
transitTunnel = CreateTransitTunnel (
|
||||||
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
|
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||||
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
|
nextIdent,
|
||||||
if (!AddTransitTunnel (transitTunnel))
|
bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||||
|
layerKey, ivKey,
|
||||||
|
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
|
||||||
|
isEndpoint);
|
||||||
|
if (!AddTransitTunnel (transitTunnel))
|
||||||
|
retCode = 30;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// decline tunnel going to duplicated router
|
||||||
retCode = 30;
|
retCode = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +477,7 @@ namespace tunnel
|
|||||||
if (congestionLevel < CONGESTION_LEVEL_FULL)
|
if (congestionLevel < CONGESTION_LEVEL_FULL)
|
||||||
{
|
{
|
||||||
// random reject depending on congestion level
|
// random reject depending on congestion level
|
||||||
int level = i2p::tunnel::tunnels.GetRng ()() % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM;
|
int level = m_Rng () % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM;
|
||||||
if (congestionLevel > level)
|
if (congestionLevel > level)
|
||||||
accept = false;
|
accept = false;
|
||||||
}
|
}
|
||||||
@@ -460,23 +485,32 @@ namespace tunnel
|
|||||||
accept = false;
|
accept = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// replace record to reply
|
|
||||||
if (accept)
|
if (accept)
|
||||||
{
|
{
|
||||||
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
i2p::data::IdentHash nextIdent(clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET);
|
||||||
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
bool isEndpoint = clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
|
||||||
clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
if (isEndpoint || !i2p::data::IsRouterDuplicated (nextIdent))
|
||||||
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
{
|
||||||
clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
|
auto transitTunnel = CreateTransitTunnel (
|
||||||
clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
|
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||||
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
|
nextIdent,
|
||||||
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
|
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||||
if (!AddTransitTunnel (transitTunnel))
|
clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
|
||||||
|
clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
|
||||||
|
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
|
||||||
|
isEndpoint);
|
||||||
|
if (!AddTransitTunnel (transitTunnel))
|
||||||
|
retCode = 30;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// decline tunnel going to duplicated router
|
||||||
retCode = 30;
|
retCode = 30;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
retCode = 30; // always reject with bandwidth reason (30)
|
retCode = 30; // always reject with bandwidth reason (30)
|
||||||
|
|
||||||
|
// replace record to reply
|
||||||
memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
|
memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
|
||||||
record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
|
record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
|
||||||
// encrypt reply
|
// encrypt reply
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ namespace tunnel
|
|||||||
std::unique_ptr<std::thread> m_Thread;
|
std::unique_ptr<std::thread> m_Thread;
|
||||||
std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels;
|
std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels;
|
||||||
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_TunnelBuildMsgQueue;
|
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_TunnelBuildMsgQueue;
|
||||||
|
std::mt19937 m_Rng;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -1042,7 +1042,7 @@ namespace transport
|
|||||||
// if still testing or unknown, repeat peer test
|
// if still testing or unknown, repeat peer test
|
||||||
if (ipv4Testing || ipv6Testing)
|
if (ipv4Testing || ipv6Testing)
|
||||||
PeerTest (ipv4Testing, ipv6Testing);
|
PeerTest (ipv4Testing, ipv6Testing);
|
||||||
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(3 * SESSION_CREATION_TIMEOUT));
|
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(2 * SESSION_CREATION_TIMEOUT + m_Rng() % SESSION_CREATION_TIMEOUT));
|
||||||
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
|
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ namespace tunnel
|
|||||||
if (m_Config->IsShort ())
|
if (m_Config->IsShort ())
|
||||||
{
|
{
|
||||||
auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr;
|
auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr;
|
||||||
if (ident && ident->GetIdentHash () != outboundTunnel->GetNextIdentHash ()) // don't encrypt if IBGW = OBEP
|
if (ident && ident->GetIdentHash () != outboundTunnel->GetEndpointIdentHash ()) // don't encrypt if IBGW = OBEP
|
||||||
{
|
{
|
||||||
auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ());
|
auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ());
|
||||||
if (msg1) msg = msg1;
|
if (msg1) msg = msg1;
|
||||||
@@ -281,6 +281,21 @@ namespace tunnel
|
|||||||
m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
|
m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InboundTunnel::Recreate ()
|
||||||
|
{
|
||||||
|
if (!IsRecreated ())
|
||||||
|
{
|
||||||
|
auto pool = GetTunnelPool ();
|
||||||
|
if (pool)
|
||||||
|
{
|
||||||
|
SetRecreated (true);
|
||||||
|
pool->RecreateInboundTunnel (std::static_pointer_cast<InboundTunnel>(shared_from_this ()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
|
ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
|
||||||
InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
||||||
m_NumReceivedBytes (0)
|
m_NumReceivedBytes (0)
|
||||||
@@ -331,6 +346,21 @@ namespace tunnel
|
|||||||
LogPrint (eLogError, "Tunnel: Incoming message for outbound tunnel ", GetTunnelID ());
|
LogPrint (eLogError, "Tunnel: Incoming message for outbound tunnel ", GetTunnelID ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OutboundTunnel::Recreate ()
|
||||||
|
{
|
||||||
|
if (!IsRecreated ())
|
||||||
|
{
|
||||||
|
auto pool = GetTunnelPool ();
|
||||||
|
if (pool)
|
||||||
|
{
|
||||||
|
SetRecreated (true);
|
||||||
|
pool->RecreateOutboundTunnel (std::static_pointer_cast<OutboundTunnel>(shared_from_this ()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
|
ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
|
||||||
OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
||||||
m_NumSentBytes (0)
|
m_NumSentBytes (0)
|
||||||
@@ -437,7 +467,7 @@ namespace tunnel
|
|||||||
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
|
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
|
||||||
{
|
{
|
||||||
if (m_OutboundTunnels.empty ()) return nullptr;
|
if (m_OutboundTunnels.empty ()) return nullptr;
|
||||||
uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0;
|
uint32_t ind = m_Rng () % m_OutboundTunnels.size (), i = 0;
|
||||||
std::shared_ptr<OutboundTunnel> tunnel;
|
std::shared_ptr<OutboundTunnel> tunnel;
|
||||||
for (const auto& it: m_OutboundTunnels)
|
for (const auto& it: m_OutboundTunnels)
|
||||||
{
|
{
|
||||||
@@ -714,8 +744,17 @@ namespace tunnel
|
|||||||
void Tunnels::ManageTunnels (uint64_t ts)
|
void Tunnels::ManageTunnels (uint64_t ts)
|
||||||
{
|
{
|
||||||
ManagePendingTunnels (ts);
|
ManagePendingTunnels (ts);
|
||||||
ManageInboundTunnels (ts);
|
std::vector<std::shared_ptr<Tunnel> > tunnelsToRecreate;
|
||||||
ManageOutboundTunnels (ts);
|
ManageInboundTunnels (ts, tunnelsToRecreate);
|
||||||
|
ManageOutboundTunnels (ts, tunnelsToRecreate);
|
||||||
|
// rec-create in random order
|
||||||
|
if (!tunnelsToRecreate.empty ())
|
||||||
|
{
|
||||||
|
if (tunnelsToRecreate.size () > 1)
|
||||||
|
std::shuffle (tunnelsToRecreate.begin(), tunnelsToRecreate.end(), m_Rng);
|
||||||
|
for (auto& it: tunnelsToRecreate)
|
||||||
|
it->Recreate ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tunnels::ManagePendingTunnels (uint64_t ts)
|
void Tunnels::ManagePendingTunnels (uint64_t ts)
|
||||||
@@ -778,7 +817,7 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tunnels::ManageOutboundTunnels (uint64_t ts)
|
void Tunnels::ManageOutboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate)
|
||||||
{
|
{
|
||||||
for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();)
|
for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();)
|
||||||
{
|
{
|
||||||
@@ -802,10 +841,7 @@ namespace tunnel
|
|||||||
auto pool = tunnel->GetTunnelPool ();
|
auto pool = tunnel->GetTunnelPool ();
|
||||||
// let it die if the tunnel pool has been reconfigured and this is old
|
// let it die if the tunnel pool has been reconfigured and this is old
|
||||||
if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops())
|
if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops())
|
||||||
{
|
toRecreate.push_back (tunnel);
|
||||||
tunnel->SetRecreated (true);
|
|
||||||
pool->RecreateOutboundTunnel (tunnel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||||
tunnel->SetState (eTunnelStateExpiring);
|
tunnel->SetState (eTunnelStateExpiring);
|
||||||
@@ -830,7 +866,7 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tunnels::ManageInboundTunnels (uint64_t ts)
|
void Tunnels::ManageInboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate)
|
||||||
{
|
{
|
||||||
for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
|
for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
|
||||||
{
|
{
|
||||||
@@ -854,10 +890,7 @@ namespace tunnel
|
|||||||
auto pool = tunnel->GetTunnelPool ();
|
auto pool = tunnel->GetTunnelPool ();
|
||||||
// let it die if the tunnel pool was reconfigured and has different number of hops
|
// let it die if the tunnel pool was reconfigured and has different number of hops
|
||||||
if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
|
if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
|
||||||
{
|
toRecreate.push_back (tunnel);
|
||||||
tunnel->SetRecreated (true);
|
|
||||||
pool->RecreateInboundTunnel (tunnel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||||
|
|||||||
@@ -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
|
||||||
*
|
*
|
||||||
@@ -99,6 +99,7 @@ namespace tunnel
|
|||||||
void SetRecreated (bool recreated) { m_IsRecreated = recreated; };
|
void SetRecreated (bool recreated) { m_IsRecreated = recreated; };
|
||||||
int GetNumHops () const { return m_Hops.size (); };
|
int GetNumHops () const { return m_Hops.size (); };
|
||||||
virtual bool IsInbound() const = 0;
|
virtual bool IsInbound() const = 0;
|
||||||
|
virtual bool Recreate () = 0;
|
||||||
|
|
||||||
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
|
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
|
||||||
void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; };
|
void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; };
|
||||||
@@ -150,6 +151,7 @@ namespace tunnel
|
|||||||
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
|
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
|
||||||
|
|
||||||
bool IsInbound() const override { return false; }
|
bool IsInbound() const override { return false; }
|
||||||
|
bool Recreate () override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -166,6 +168,7 @@ namespace tunnel
|
|||||||
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override;
|
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override;
|
||||||
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
||||||
bool IsInbound() const override { return true; }
|
bool IsInbound() const override { return true; }
|
||||||
|
bool Recreate () override;
|
||||||
|
|
||||||
// override TunnelBase
|
// override TunnelBase
|
||||||
void Cleanup () override { m_Endpoint.Cleanup (); };
|
void Cleanup () override { m_Endpoint.Cleanup (); };
|
||||||
@@ -246,8 +249,6 @@ namespace tunnel
|
|||||||
uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
|
uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
|
||||||
int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.GetNumTransitTunnels () / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; }
|
int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.GetNumTransitTunnels () / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; }
|
||||||
|
|
||||||
std::mt19937& GetRng () { return m_Rng; };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<class TTunnel>
|
template<class TTunnel>
|
||||||
@@ -264,8 +265,8 @@ namespace tunnel
|
|||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
void ManageTunnels (uint64_t ts);
|
void ManageTunnels (uint64_t ts);
|
||||||
void ManageOutboundTunnels (uint64_t ts);
|
void ManageOutboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate);
|
||||||
void ManageInboundTunnels (uint64_t ts);
|
void ManageInboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate);
|
||||||
void ManagePendingTunnels (uint64_t ts);
|
void ManagePendingTunnels (uint64_t ts);
|
||||||
template<class PendingTunnels>
|
template<class PendingTunnels>
|
||||||
void ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts);
|
void ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts);
|
||||||
|
|||||||
@@ -902,7 +902,7 @@ namespace client
|
|||||||
if (m_AddressCacheUpdateTimer)
|
if (m_AddressCacheUpdateTimer)
|
||||||
{
|
{
|
||||||
m_AddressCacheUpdateTimer->expires_from_now (boost::posix_time::seconds(ADDRESS_CACHE_UPDATE_INTERVAL ));
|
m_AddressCacheUpdateTimer->expires_from_now (boost::posix_time::seconds(ADDRESS_CACHE_UPDATE_INTERVAL ));
|
||||||
m_SubscriptionsUpdateTimer->async_wait (
|
m_AddressCacheUpdateTimer->async_wait (
|
||||||
[this](const boost::system::error_code& ecode)
|
[this](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
|||||||
Reference in New Issue
Block a user