mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
2 Commits
2.56.0
...
8b28f3fd8e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b28f3fd8e | ||
|
|
32a70562c4 |
27
ChangeLog
27
ChangeLog
@@ -1,29 +1,6 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.56.0] - 2025-02-11
|
||||
### Added
|
||||
- Config params for shared local destination
|
||||
- AddressBook full addresses cache
|
||||
- Decline transit tunnel to duplicated router
|
||||
- Recreate tunnels in random order
|
||||
### Changed
|
||||
- Exclude disk operations from SSU2 and NTCP2 threads
|
||||
- Set minimal version for peer test to 0.9.62
|
||||
- Send ack requested flag after second SSU2 resend attempt
|
||||
- Shorter ECIESx25519 ack request interval for datagram and I2CP sessions
|
||||
- Don't change datagram routing path too often if unidirectional data stream
|
||||
- Reduce LeaseSet and local RouterInfo publishing confirmation intervals
|
||||
- Don't delete buffer of connected routers or if an update received
|
||||
- Smaller RouterInfo request timeout if sent directly
|
||||
- Persist local RouterInfo in separate thread
|
||||
- Don't recalculate and process ranges for every SSU2 Ack block
|
||||
- Reseeds list
|
||||
### Fixed
|
||||
- Termination deadlock if SAM session is active
|
||||
- Race condition at tunnel endpoint
|
||||
- Inbound tunnel build encryption
|
||||
|
||||
## [2.55.0] - 2024-12-30
|
||||
### Added
|
||||
- Support boost 1.87
|
||||
@@ -85,12 +62,12 @@
|
||||
- Handle i2cp.inboundlimit and i2cp.outboundlimit params in I2CP
|
||||
- Publish LeaseSet with new timestamp update if tunnel was replaced in the same second
|
||||
- Increase max number of generated tags to 800 per tagset
|
||||
- Routing path expiration by time instead num attempts
|
||||
- Routing path expiration by time instead num attempts
|
||||
- Save timestamp from epoch instead local time to profiles
|
||||
- Update introducer's iTag if session to introducer was replaced to new one
|
||||
- RTT, window size and number of NACKs calculation for streaming
|
||||
- Don't select same peer for tunnel too often
|
||||
- Use WinApi for data path UTF-8 conversion for Windows
|
||||
- Use WinApi for data path UTF-8 conversion for Windows
|
||||
### Fixed
|
||||
- Jump link crash if address book is disabled
|
||||
- Race condition if connect through an introducer
|
||||
|
||||
@@ -3,7 +3,7 @@ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misl
|
||||
DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1
|
||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
||||
LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||
LDLIBS = -lssl -lcrypto -lz -lpthread -lboost_system -lboost_program_options
|
||||
LDLIBS = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options
|
||||
|
||||
## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time
|
||||
## **without** overwriting the CXXFLAGS which we need in order to build.
|
||||
|
||||
@@ -2,7 +2,7 @@ CXX = g++
|
||||
CXXFLAGS := -Wall -std=c++17
|
||||
INCFLAGS = -I/system/develop/headers
|
||||
DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
||||
LDLIBS = -lbe -lbsd -lnetwork -lz -lssl -lcrypto -lboost_system -lboost_program_options -lpthread
|
||||
LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_program_options -lpthread
|
||||
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
DEFINES += -DUSE_UPNP
|
||||
|
||||
@@ -18,7 +18,7 @@ endif
|
||||
LDLIBS += -lpthread -ldl
|
||||
else
|
||||
LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
||||
LDLIBS = -lz -lssl -lcrypto -lboost_system -lboost_filesystem -lboost_program_options -lpthread
|
||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_filesystem -lboost_program_options -lpthread
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
LDFLAGS += -L${UPNPROOT}/lib
|
||||
LDLIBS += -lminiupnpc
|
||||
|
||||
@@ -40,7 +40,7 @@ ifeq ($(USE_UPNP),yes)
|
||||
endif
|
||||
LDLIBS += -lpthread -ldl
|
||||
else
|
||||
LDLIBS += -lssl -lcrypto -lz -lboost_program_options -lpthread -latomic
|
||||
LDLIBS += -lcrypto -lssl -lz -lboost_program_options -lpthread -latomic
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
LDLIBS += -lminiupnpc
|
||||
endif
|
||||
|
||||
@@ -7,9 +7,9 @@ LDFLAGS += -Wl,-dead_strip
|
||||
LDFLAGS += -Wl,-dead_strip_dylibs
|
||||
|
||||
ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS = -lz /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
||||
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
|
||||
else
|
||||
LDLIBS = -lz -lssl -lcrypto -lboost_system -lboost_filesystem -lboost_program_options -lpthread
|
||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_filesystem -lboost_program_options -lpthread
|
||||
endif
|
||||
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
|
||||
@@ -59,7 +59,7 @@ get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
# function returns an empty string via _git_dir_var.
|
||||
#
|
||||
# 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 will return
|
||||
# neither foo nor bar contain a file/directory .git. This wil return
|
||||
# C:/bla/.git
|
||||
#
|
||||
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||
|
||||
@@ -243,7 +243,7 @@ verify = true
|
||||
## Default: reg.i2p at "mainline" I2P Network
|
||||
# defaulturl = http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt
|
||||
## Optional subscriptions URLs, separated by comma
|
||||
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt
|
||||
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
|
||||
|
||||
[limits]
|
||||
## Maximum active transit sessions (default: 5000)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.56.0
|
||||
Version: 2.55.0
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
@@ -148,9 +148,6 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Feb 11 2025 orignal <orignal@i2pmail.org> - 2.56.0
|
||||
- update to 2.56.0
|
||||
|
||||
* Mon Dec 30 2024 orignal <orignal@i2pmail.org> - 2.55.0
|
||||
- update to 2.55.0
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: i2pd
|
||||
Version: 2.56.0
|
||||
Version: 2.55.0
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
@@ -146,9 +146,6 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Feb 11 2025 orignal <orignal@i2pmail.org> - 2.56.0
|
||||
- update to 2.56.0
|
||||
|
||||
* Mon Dec 30 2024 orignal <orignal@i2pmail.org> - 2.55.0
|
||||
- update to 2.55.0
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ port = 6668
|
||||
destination = irc.ilita.i2p
|
||||
destinationport = 6667
|
||||
keys = irc-keys.dat
|
||||
i2p.streaming.profile=2
|
||||
|
||||
#[IRC-IRC2P]
|
||||
#type = client
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace transport
|
||||
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||
#endif
|
||||
m_upnpUrlsInitialized=err!=0;
|
||||
if (err == UPNP_IGD_VALID_CONNECTED)
|
||||
if (err == UPNP_IGD_VALID_CONNECTED || err == UPNP_IGD_VALID_NOT_CONNECTED)
|
||||
{
|
||||
#if (MINIUPNPC_API_VERSION < 18)
|
||||
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,9 +1,3 @@
|
||||
i2pd (2.56.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.56.0/0.9.65
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Tue, 11 Feb 2025 16:00:00 +0000
|
||||
|
||||
i2pd (2.55.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.55.0
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace config {
|
||||
"https://reseed.onion.im/,"
|
||||
"https://i2pseed.creativecowpat.net:8443/,"
|
||||
"https://reseed.i2pgit.org/,"
|
||||
"https://coconut.incognet.io/,"
|
||||
"https://banana.incognet.io/,"
|
||||
"https://reseed-pl.i2pd.xyz/,"
|
||||
"https://www2.mk16.de/,"
|
||||
"https://i2p.ghativega.in/,"
|
||||
|
||||
@@ -32,10 +32,10 @@ namespace data
|
||||
|
||||
RouterProfile::RouterProfile ():
|
||||
m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0),
|
||||
m_LastUpdateTime (i2p::util::GetSecondsSinceEpoch ()), m_LastAccessTime (0),
|
||||
m_LastPersistTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0),
|
||||
m_NumTunnelsNonReplied (0),m_NumTimesTaken (0), m_NumTimesRejected (0),
|
||||
m_HasConnected (false), m_IsDuplicated (false)
|
||||
m_LastUpdateTime (i2p::util::GetSecondsSinceEpoch ()),
|
||||
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0),
|
||||
m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false),
|
||||
m_IsDuplicated (false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ namespace data
|
||||
|
||||
void RouterProfile::Load (const IdentHash& identHash)
|
||||
{
|
||||
m_IsUpdated = false;
|
||||
std::string ident = identHash.ToBase64 ();
|
||||
std::string path = g_ProfilesStorage.Path(ident);
|
||||
boost::property_tree::ptree pt;
|
||||
@@ -258,10 +257,7 @@ namespace data
|
||||
std::unique_lock<std::mutex> l(g_ProfilesMutex);
|
||||
auto it = g_Profiles.find (identHash);
|
||||
if (it != g_Profiles.end ())
|
||||
{
|
||||
it->second->SetLastAccessTime (i2p::util::GetSecondsSinceEpoch ());
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
auto profile = netdb.NewRouterProfile ();
|
||||
profile->Load (identHash); // if possible
|
||||
@@ -278,15 +274,6 @@ namespace data
|
||||
return it->second->IsUnreachable ();
|
||||
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 ()
|
||||
{
|
||||
@@ -308,14 +295,12 @@ namespace data
|
||||
std::lock_guard<std::mutex> l(g_ProfilesMutex);
|
||||
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
|
||||
{
|
||||
if (it->second->IsUpdated () && ts > it->second->GetLastPersistTime () + PEER_PROFILE_PERSIST_INTERVAL)
|
||||
if (ts - it->second->GetLastUpdateTime () > PEER_PROFILE_PERSIST_INTERVAL)
|
||||
{
|
||||
tmp.push_back (std::make_pair (it->first, it->second));
|
||||
it->second->SetLastPersistTime (ts);
|
||||
it->second->SetUpdated (false);
|
||||
}
|
||||
if (!it->second->IsUpdated () && ts > std::max (it->second->GetLastUpdateTime (), it->second->GetLastAccessTime ()) + PEER_PROFILE_PERSIST_INTERVAL)
|
||||
if (it->second->IsUpdated ())
|
||||
tmp.push_back (std::make_pair (it->first, it->second));
|
||||
it = g_Profiles.erase (it);
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
|
||||
@@ -70,11 +70,6 @@ namespace data
|
||||
|
||||
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
|
||||
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 IsDuplicated () const { return m_IsDuplicated; };
|
||||
@@ -96,8 +91,7 @@ namespace data
|
||||
private:
|
||||
|
||||
bool m_IsUpdated;
|
||||
uint64_t m_LastDeclineTime, m_LastUnreachableTime, m_LastUpdateTime,
|
||||
m_LastAccessTime, m_LastPersistTime; // in seconds
|
||||
uint64_t m_LastDeclineTime, m_LastUnreachableTime, m_LastUpdateTime; // in seconds
|
||||
// participation
|
||||
uint32_t m_NumTunnelsAgreed;
|
||||
uint32_t m_NumTunnelsDeclined;
|
||||
@@ -113,7 +107,6 @@ namespace data
|
||||
|
||||
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);
|
||||
bool IsRouterBanned (const IdentHash& identHash); // check only existing profiles
|
||||
bool IsRouterDuplicated (const IdentHash& identHash); // check only existing profiles
|
||||
void InitProfilesStorage ();
|
||||
std::future<void> DeleteObsoleteProfiles ();
|
||||
void SaveProfiles ();
|
||||
|
||||
@@ -33,14 +33,13 @@ namespace i2p
|
||||
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
|
||||
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone),
|
||||
m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID),
|
||||
m_PublishReplyToken (0), m_IsHiddenMode (false),
|
||||
m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL), m_IsSaving (false)
|
||||
m_PublishReplyToken (0), m_IsHiddenMode (false)
|
||||
{
|
||||
}
|
||||
|
||||
void RouterContext::Init ()
|
||||
{
|
||||
srand (m_Rng () % 1000);
|
||||
srand (i2p::util::GetMillisecondsSinceEpoch () % 1000);
|
||||
m_StartupTime = i2p::util::GetMonotonicSeconds ();
|
||||
|
||||
if (!Load ())
|
||||
@@ -77,7 +76,7 @@ namespace i2p
|
||||
m_CongestionUpdateTimer->cancel ();
|
||||
m_Service->Stop ();
|
||||
CleanUp (); // GarlicDestination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<i2p::data::RouterInfo::Buffer> RouterContext::CopyRouterInfoBuffer () const
|
||||
@@ -254,36 +253,11 @@ namespace i2p
|
||||
|
||||
void RouterContext::UpdateRouterInfo ()
|
||||
{
|
||||
std::shared_ptr<i2p::data::RouterInfo::Buffer> buffer;
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_RouterInfoMutex);
|
||||
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 ();
|
||||
}
|
||||
|
||||
@@ -1385,7 +1359,7 @@ namespace i2p
|
||||
{
|
||||
m_PublishTimer->cancel ();
|
||||
m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL +
|
||||
m_Rng () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE));
|
||||
rand () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE));
|
||||
m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishTimer,
|
||||
this, std::placeholders::_1));
|
||||
}
|
||||
@@ -1497,8 +1471,7 @@ namespace i2p
|
||||
if (m_CongestionUpdateTimer)
|
||||
{
|
||||
m_CongestionUpdateTimer->cancel ();
|
||||
m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(
|
||||
ROUTER_INFO_CONGESTION_UPDATE_INTERVAL + m_Rng () % ROUTER_INFO_CONGESTION_UPDATE_INTERVAL_VARIANCE));
|
||||
m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONGESTION_UPDATE_INTERVAL));
|
||||
m_CongestionUpdateTimer->async_wait (std::bind (&RouterContext::HandleCongestionUpdateTimer,
|
||||
this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <unordered_set>
|
||||
#include <boost/asio.hpp>
|
||||
#include "Identity.h"
|
||||
@@ -37,8 +36,7 @@ namespace garlic
|
||||
const int ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE = 105;// in seconds
|
||||
const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 1600; // in milliseconds
|
||||
const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
|
||||
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_CONGESTION_UPDATE_INTERVAL = 12*60; // in seconds
|
||||
const int ROUTER_INFO_CLEANUP_INTERVAL = 102; // in seconds
|
||||
|
||||
enum RouterStatus
|
||||
@@ -265,10 +263,6 @@ namespace garlic
|
||||
uint32_t m_PublishReplyToken;
|
||||
bool m_IsHiddenMode; // not publish
|
||||
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;
|
||||
|
||||
@@ -623,8 +623,7 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t packetNum = SendData (it->second->payload, it->second->payloadSize,
|
||||
it->second->numResends > 1 ? SSU2_FLAG_IMMEDIATE_ACK_REQUESTED : 0);
|
||||
uint32_t packetNum = SendData (it->second->payload, it->second->payloadSize);
|
||||
it->second->numResends++;
|
||||
it->second->sendTime = ts;
|
||||
resentPackets.emplace (packetNum, it->second);
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace tunnel
|
||||
}
|
||||
|
||||
TransitTunnels::TransitTunnels ():
|
||||
m_IsRunning (false), m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL)
|
||||
m_IsRunning (false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -328,44 +328,19 @@ namespace tunnel
|
||||
// check if we accept this tunnel
|
||||
std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
|
||||
uint8_t retCode = 0;
|
||||
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
|
||||
if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= CONGESTION_LEVEL_FULL)
|
||||
retCode = 30;
|
||||
|
||||
if (!retCode)
|
||||
{
|
||||
i2p::data::IdentHash nextIdent(clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET);
|
||||
bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
|
||||
if (isEndpoint || !i2p::data::IsRouterDuplicated (nextIdent))
|
||||
{
|
||||
// create new transit tunnel
|
||||
transitTunnel = CreateTransitTunnel (
|
||||
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||
nextIdent,
|
||||
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
|
||||
// create new transit tunnel
|
||||
transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
||||
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||
bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
layerKey, ivKey,
|
||||
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
|
||||
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
|
||||
if (!AddTransitTunnel (transitTunnel))
|
||||
retCode = 30;
|
||||
}
|
||||
|
||||
@@ -477,7 +452,7 @@ namespace tunnel
|
||||
if (congestionLevel < CONGESTION_LEVEL_FULL)
|
||||
{
|
||||
// random reject depending on congestion level
|
||||
int level = m_Rng () % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM;
|
||||
int level = i2p::tunnel::tunnels.GetRng ()() % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM;
|
||||
if (congestionLevel > level)
|
||||
accept = false;
|
||||
}
|
||||
@@ -485,32 +460,23 @@ namespace tunnel
|
||||
accept = false;
|
||||
}
|
||||
}
|
||||
|
||||
// replace record to reply
|
||||
if (accept)
|
||||
{
|
||||
i2p::data::IdentHash nextIdent(clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET);
|
||||
bool isEndpoint = clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
|
||||
if (isEndpoint || !i2p::data::IsRouterDuplicated (nextIdent))
|
||||
{
|
||||
auto transitTunnel = CreateTransitTunnel (
|
||||
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||
nextIdent,
|
||||
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
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
|
||||
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
||||
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||
clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||
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,
|
||||
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
|
||||
if (!AddTransitTunnel (transitTunnel))
|
||||
retCode = 30;
|
||||
}
|
||||
else
|
||||
retCode = 30; // always reject with bandwidth reason (30)
|
||||
|
||||
// replace record to reply
|
||||
memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
|
||||
record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
|
||||
// encrypt reply
|
||||
|
||||
@@ -152,7 +152,6 @@ namespace tunnel
|
||||
std::unique_ptr<std::thread> m_Thread;
|
||||
std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels;
|
||||
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_TunnelBuildMsgQueue;
|
||||
std::mt19937 m_Rng;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -1042,7 +1042,7 @@ namespace transport
|
||||
// if still testing or unknown, repeat peer test
|
||||
if (ipv4Testing || ipv6Testing)
|
||||
PeerTest (ipv4Testing, ipv6Testing);
|
||||
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(2 * SESSION_CREATION_TIMEOUT + m_Rng() % SESSION_CREATION_TIMEOUT));
|
||||
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(3 * SESSION_CREATION_TIMEOUT));
|
||||
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace tunnel
|
||||
if (m_Config->IsShort ())
|
||||
{
|
||||
auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr;
|
||||
if (ident && ident->GetIdentHash () != outboundTunnel->GetEndpointIdentHash ()) // don't encrypt if IBGW = OBEP
|
||||
if (ident && ident->GetIdentHash () != outboundTunnel->GetNextIdentHash ()) // don't encrypt if IBGW = OBEP
|
||||
{
|
||||
auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ());
|
||||
if (msg1) msg = msg1;
|
||||
@@ -281,21 +281,6 @@ namespace tunnel
|
||||
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 ():
|
||||
InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
||||
m_NumReceivedBytes (0)
|
||||
@@ -315,28 +300,22 @@ namespace tunnel
|
||||
void OutboundTunnel::SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg)
|
||||
{
|
||||
TunnelMessageBlock block;
|
||||
block.tunnelID = 0; // Initialize tunnelID to a default value
|
||||
|
||||
if (gwHash)
|
||||
{
|
||||
block.hash = gwHash;
|
||||
if (gwTunnel)
|
||||
{
|
||||
block.deliveryType = eDeliveryTypeTunnel;
|
||||
block.tunnelID = gwTunnel; // Set tunnelID only if gwTunnel is non-zero
|
||||
block.tunnelID = gwTunnel;
|
||||
}
|
||||
else
|
||||
{
|
||||
block.deliveryType = eDeliveryTypeRouter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
block.deliveryType = eDeliveryTypeLocal;
|
||||
}
|
||||
|
||||
block.data = msg;
|
||||
SendTunnelDataMsgs({block});
|
||||
|
||||
SendTunnelDataMsgs ({block});
|
||||
}
|
||||
|
||||
void OutboundTunnel::SendTunnelDataMsgs (const std::vector<TunnelMessageBlock>& msgs)
|
||||
@@ -352,21 +331,6 @@ namespace tunnel
|
||||
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 ():
|
||||
OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
|
||||
m_NumSentBytes (0)
|
||||
@@ -473,7 +437,7 @@ namespace tunnel
|
||||
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
|
||||
{
|
||||
if (m_OutboundTunnels.empty ()) return nullptr;
|
||||
uint32_t ind = m_Rng () % m_OutboundTunnels.size (), i = 0;
|
||||
uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0;
|
||||
std::shared_ptr<OutboundTunnel> tunnel;
|
||||
for (const auto& it: m_OutboundTunnels)
|
||||
{
|
||||
@@ -750,17 +714,8 @@ namespace tunnel
|
||||
void Tunnels::ManageTunnels (uint64_t ts)
|
||||
{
|
||||
ManagePendingTunnels (ts);
|
||||
std::vector<std::shared_ptr<Tunnel> > tunnelsToRecreate;
|
||||
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 ();
|
||||
}
|
||||
ManageInboundTunnels (ts);
|
||||
ManageOutboundTunnels (ts);
|
||||
}
|
||||
|
||||
void Tunnels::ManagePendingTunnels (uint64_t ts)
|
||||
@@ -823,7 +778,7 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void Tunnels::ManageOutboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate)
|
||||
void Tunnels::ManageOutboundTunnels (uint64_t ts)
|
||||
{
|
||||
for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();)
|
||||
{
|
||||
@@ -847,7 +802,10 @@ namespace tunnel
|
||||
auto pool = tunnel->GetTunnelPool ();
|
||||
// let it die if the tunnel pool has been reconfigured and this is old
|
||||
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)
|
||||
tunnel->SetState (eTunnelStateExpiring);
|
||||
@@ -872,7 +830,7 @@ namespace tunnel
|
||||
}
|
||||
}
|
||||
|
||||
void Tunnels::ManageInboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate)
|
||||
void Tunnels::ManageInboundTunnels (uint64_t ts)
|
||||
{
|
||||
for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
|
||||
{
|
||||
@@ -896,7 +854,10 @@ namespace tunnel
|
||||
auto pool = tunnel->GetTunnelPool ();
|
||||
// let it die if the tunnel pool was reconfigured and has different number of hops
|
||||
if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
|
||||
toRecreate.push_back (tunnel);
|
||||
{
|
||||
tunnel->SetRecreated (true);
|
||||
pool->RecreateInboundTunnel (tunnel);
|
||||
}
|
||||
}
|
||||
|
||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -99,7 +99,6 @@ namespace tunnel
|
||||
void SetRecreated (bool recreated) { m_IsRecreated = recreated; };
|
||||
int GetNumHops () const { return m_Hops.size (); };
|
||||
virtual bool IsInbound() const = 0;
|
||||
virtual bool Recreate () = 0;
|
||||
|
||||
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
|
||||
void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; };
|
||||
@@ -151,7 +150,6 @@ namespace tunnel
|
||||
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
|
||||
|
||||
bool IsInbound() const override { return false; }
|
||||
bool Recreate () override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -168,7 +166,6 @@ namespace tunnel
|
||||
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override;
|
||||
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
||||
bool IsInbound() const override { return true; }
|
||||
bool Recreate () override;
|
||||
|
||||
// override TunnelBase
|
||||
void Cleanup () override { m_Endpoint.Cleanup (); };
|
||||
@@ -248,6 +245,8 @@ namespace tunnel
|
||||
void SetMaxNumTransitTunnels (uint32_t 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; }
|
||||
|
||||
std::mt19937& GetRng () { return m_Rng; };
|
||||
|
||||
private:
|
||||
|
||||
@@ -265,8 +264,8 @@ namespace tunnel
|
||||
|
||||
void Run ();
|
||||
void ManageTunnels (uint64_t ts);
|
||||
void ManageOutboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate);
|
||||
void ManageInboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate);
|
||||
void ManageOutboundTunnels (uint64_t ts);
|
||||
void ManageInboundTunnels (uint64_t ts);
|
||||
void ManagePendingTunnels (uint64_t ts);
|
||||
template<class PendingTunnels>
|
||||
void ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts);
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace tunnel
|
||||
void HandleDecryptedTunnelDataMsg (std::shared_ptr<I2NPMessage> msg);
|
||||
void FlushI2NPMsgs ();
|
||||
|
||||
const i2p::data::IdentHash * GetCurrentHash () const; // return null if not available
|
||||
const i2p::data::IdentHash * GetCurrentHash () const; // return null if not avaiable
|
||||
const std::unique_ptr<TunnelTransportSender>& GetSender () const { return m_Sender; };
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
|
||||
|
||||
#define I2PD_VERSION_MAJOR 2
|
||||
#define I2PD_VERSION_MINOR 56
|
||||
#define I2PD_VERSION_MINOR 55
|
||||
#define I2PD_VERSION_MICRO 0
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#ifdef GITVER
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
#define I2P_VERSION_MICRO 65
|
||||
#define I2P_VERSION_MICRO 64
|
||||
#define I2P_VERSION_PATCH 0
|
||||
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
#define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "Base.h"
|
||||
#include "util.h"
|
||||
#include "Timestamp.h"
|
||||
#include "Identity.h"
|
||||
#include "FS.h"
|
||||
#include "Log.h"
|
||||
@@ -50,10 +49,9 @@ namespace client
|
||||
if (m_IsPersist)
|
||||
i2p::config::GetOption("addressbook.hostsfile", m_HostsFile);
|
||||
}
|
||||
std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) override;
|
||||
std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const override;
|
||||
void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) override;
|
||||
void RemoveAddress (const i2p::data::IdentHash& ident) override;
|
||||
void CleanUpCache () override;
|
||||
|
||||
bool Init () override;
|
||||
int Load (Addresses& addresses) override;
|
||||
@@ -63,7 +61,7 @@ namespace client
|
||||
void SaveEtag (const i2p::data::IdentHash& subsciption, const std::string& etag, const std::string& lastModified) override;
|
||||
bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) override;
|
||||
void ResetEtags () override;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int LoadFromFile (const std::string& filename, Addresses& addresses); // returns -1 if can't open file, otherwise number of records
|
||||
@@ -74,8 +72,6 @@ namespace client
|
||||
std::string etagsPath, indexPath, localPath;
|
||||
bool m_IsPersist;
|
||||
std::string m_HostsFile; // file to dump hosts.txt, empty if not used
|
||||
std::unordered_map<i2p::data::IdentHash, std::pair<std::vector<uint8_t>, uint64_t> > m_FullAddressCache; // ident hash -> (full ident buffer, last access timestamp)
|
||||
std::mutex m_FullAddressCacheMutex;
|
||||
};
|
||||
|
||||
bool AddressBookFilesystemStorage::Init()
|
||||
@@ -96,19 +92,8 @@ namespace client
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident)
|
||||
std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const
|
||||
{
|
||||
auto ts = i2p::util::GetMonotonicSeconds ();
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_FullAddressCacheMutex);
|
||||
auto it = m_FullAddressCache.find (ident);
|
||||
if (it != m_FullAddressCache.end ())
|
||||
{
|
||||
it->second.second = ts;
|
||||
return std::make_shared<i2p::data::IdentityEx>(it->second.first.data (), it->second.first.size ());
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_IsPersist)
|
||||
{
|
||||
LogPrint(eLogDebug, "Addressbook: Persistence is disabled");
|
||||
@@ -116,67 +101,43 @@ namespace client
|
||||
}
|
||||
std::string filename = storage.Path(ident.ToBase32());
|
||||
std::ifstream f(filename, std::ifstream::binary);
|
||||
if (!f.is_open ())
|
||||
{
|
||||
if (!f.is_open ()) {
|
||||
LogPrint(eLogDebug, "Addressbook: Requested, but not found: ", filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
f.seekg (0,std::ios::end);
|
||||
size_t len = f.tellg ();
|
||||
if (len < i2p::data::DEFAULT_IDENTITY_SIZE)
|
||||
{
|
||||
if (len < i2p::data::DEFAULT_IDENTITY_SIZE) {
|
||||
LogPrint (eLogError, "Addressbook: File ", filename, " is too short: ", len);
|
||||
return nullptr;
|
||||
}
|
||||
f.seekg(0, std::ios::beg);
|
||||
std::vector<uint8_t> buf(len);
|
||||
f.read((char *)buf.data (), len);
|
||||
if (!f)
|
||||
{
|
||||
LogPrint (eLogError, "Addressbook: Couldn't read ", filename);
|
||||
return nullptr;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_FullAddressCacheMutex);
|
||||
m_FullAddressCache.try_emplace (ident, buf, ts);
|
||||
}
|
||||
return std::make_shared<i2p::data::IdentityEx>(buf.data (), len);
|
||||
uint8_t * buf = new uint8_t[len];
|
||||
f.read((char *)buf, len);
|
||||
auto address = std::make_shared<i2p::data::IdentityEx>(buf, len);
|
||||
delete[] buf;
|
||||
return address;
|
||||
}
|
||||
|
||||
void AddressBookFilesystemStorage::AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address)
|
||||
{
|
||||
if (!address) return;
|
||||
size_t len = address->GetFullLen ();
|
||||
std::vector<uint8_t> buf;
|
||||
if (!len) return; // invalid address
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_FullAddressCacheMutex);
|
||||
auto [it, inserted] = m_FullAddressCache.try_emplace (address->GetIdentHash(), len, i2p::util::GetMonotonicSeconds ());
|
||||
if (inserted)
|
||||
address->ToBuffer (it->second.first.data (), len);
|
||||
if (m_IsPersist)
|
||||
buf = it->second.first;
|
||||
if (!m_IsPersist) return;
|
||||
std::string path = storage.Path( address->GetIdentHash().ToBase32() );
|
||||
std::ofstream f (path, std::ofstream::binary | std::ofstream::out);
|
||||
if (!f.is_open ()) {
|
||||
LogPrint (eLogError, "Addressbook: Can't open file ", path);
|
||||
return;
|
||||
}
|
||||
if (m_IsPersist && !buf.empty ())
|
||||
{
|
||||
std::string path = storage.Path(address->GetIdentHash().ToBase32());
|
||||
std::ofstream f (path, std::ofstream::binary | std::ofstream::out);
|
||||
if (!f.is_open ())
|
||||
{
|
||||
LogPrint (eLogError, "Addressbook: Can't open file ", path);
|
||||
return;
|
||||
}
|
||||
f.write ((const char *)buf.data (), len);
|
||||
}
|
||||
size_t len = address->GetFullLen ();
|
||||
uint8_t * buf = new uint8_t[len];
|
||||
address->ToBuffer (buf, len);
|
||||
f.write ((char *)buf, len);
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_FullAddressCacheMutex);
|
||||
m_FullAddressCache.erase (ident);
|
||||
}
|
||||
if (!m_IsPersist) return;
|
||||
storage.Remove( ident.ToBase32() );
|
||||
}
|
||||
@@ -320,19 +281,6 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void AddressBookFilesystemStorage::CleanUpCache ()
|
||||
{
|
||||
auto ts = i2p::util::GetMonotonicSeconds ();
|
||||
std::lock_guard<std::mutex> l(m_FullAddressCacheMutex);
|
||||
for (auto it = m_FullAddressCache.begin (); it != m_FullAddressCache.end ();)
|
||||
{
|
||||
if (ts > it->second.second + ADDRESS_CACHE_EXPIRATION_TIMEOUT)
|
||||
it = m_FullAddressCache.erase (it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
Address::Address (std::string_view b32):
|
||||
@@ -379,7 +327,6 @@ namespace client
|
||||
LoadHosts (); /* try storage, then hosts.txt, then download */
|
||||
StartSubscriptions ();
|
||||
StartLookups ();
|
||||
ScheduleCacheUpdate ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,14 +341,9 @@ namespace client
|
||||
StopSubscriptions ();
|
||||
if (m_SubscriptionsUpdateTimer)
|
||||
{
|
||||
m_SubscriptionsUpdateTimer->cancel ();
|
||||
delete m_SubscriptionsUpdateTimer;
|
||||
m_SubscriptionsUpdateTimer = nullptr;
|
||||
}
|
||||
if (m_AddressCacheUpdateTimer)
|
||||
{
|
||||
m_AddressCacheUpdateTimer->cancel ();
|
||||
m_AddressCacheUpdateTimer = nullptr;
|
||||
}
|
||||
bool isDownloading = m_Downloading.valid ();
|
||||
if (isDownloading)
|
||||
{
|
||||
@@ -740,7 +682,7 @@ namespace client
|
||||
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
||||
if (dest)
|
||||
{
|
||||
m_SubscriptionsUpdateTimer = std::make_unique<boost::asio::deadline_timer>(dest->GetService ());
|
||||
m_SubscriptionsUpdateTimer = new boost::asio::deadline_timer (dest->GetService ());
|
||||
m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT));
|
||||
m_SubscriptionsUpdateTimer->async_wait (std::bind (&AddressBook::HandleSubscriptionsUpdateTimer,
|
||||
this, std::placeholders::_1));
|
||||
@@ -891,29 +833,6 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void AddressBook::ScheduleCacheUpdate ()
|
||||
{
|
||||
if (!m_AddressCacheUpdateTimer)
|
||||
{
|
||||
auto dest = i2p::client::context.GetSharedLocalDestination ();
|
||||
if(dest)
|
||||
m_AddressCacheUpdateTimer = std::make_unique<boost::asio::deadline_timer>(dest->GetService ());
|
||||
}
|
||||
if (m_AddressCacheUpdateTimer)
|
||||
{
|
||||
m_AddressCacheUpdateTimer->expires_from_now (boost::posix_time::seconds(ADDRESS_CACHE_UPDATE_INTERVAL ));
|
||||
m_AddressCacheUpdateTimer->async_wait (
|
||||
[this](const boost::system::error_code& ecode)
|
||||
{
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
{
|
||||
if (m_Storage) m_Storage->CleanUpCache ();
|
||||
ScheduleCacheUpdate ();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
AddressBookSubscription::AddressBookSubscription (AddressBook& book, std::string_view link):
|
||||
m_Book (book), m_Link (link)
|
||||
{
|
||||
|
||||
@@ -34,9 +34,7 @@ namespace client
|
||||
const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours)
|
||||
const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes
|
||||
const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout
|
||||
const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in seconds
|
||||
const int ADDRESS_CACHE_EXPIRATION_TIMEOUT = 710; // in seconds
|
||||
const int ADDRESS_CACHE_UPDATE_INTERVAL = 76; // in seconds
|
||||
const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in second
|
||||
|
||||
const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53;
|
||||
const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54;
|
||||
@@ -64,10 +62,9 @@ namespace client
|
||||
typedef std::map<std::string, std::shared_ptr<Address>, std::less<> > Addresses;
|
||||
|
||||
virtual ~AddressBookStorage () {};
|
||||
virtual std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) = 0;
|
||||
virtual std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const = 0;
|
||||
virtual void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) = 0;
|
||||
virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0;
|
||||
virtual void CleanUpCache () = 0;
|
||||
|
||||
virtual bool Init () = 0;
|
||||
virtual int Load (Addresses& addresses) = 0;
|
||||
@@ -123,8 +120,6 @@ namespace client
|
||||
void StopLookups ();
|
||||
void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||
|
||||
void ScheduleCacheUpdate ();
|
||||
|
||||
private:
|
||||
|
||||
std::mutex m_AddressBookMutex;
|
||||
@@ -138,7 +133,7 @@ namespace client
|
||||
int m_NumRetries;
|
||||
std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions;
|
||||
std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
|
||||
std::unique_ptr<boost::asio::deadline_timer> m_SubscriptionsUpdateTimer, m_AddressCacheUpdateTimer;
|
||||
boost::asio::deadline_timer * m_SubscriptionsUpdateTimer;
|
||||
bool m_IsEnabled;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user