mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
15 Commits
build-test
...
aedf59d11a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aedf59d11a | ||
|
|
d09367d686 | ||
|
|
70f99ccc21 | ||
|
|
ef72ba3f34 | ||
|
|
251605e2b8 | ||
|
|
fa2178ca3e | ||
|
|
3d19fa12f6 | ||
|
|
48aaecacce | ||
|
|
4bb86b6a86 | ||
|
|
0588116489 | ||
|
|
78a37cc00f | ||
|
|
fb90b01f6c | ||
|
|
ea55215668 | ||
|
|
58a86fa2dc | ||
|
|
ff0b6a6a6a |
10
ChangeLog
10
ChangeLog
@@ -1,7 +1,7 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.56.0] - 2025-02-10
|
||||
## [2.56.0] - 2025-02-11
|
||||
### Added
|
||||
- Config params for shared local destination
|
||||
- AddressBook full addresses cache
|
||||
@@ -12,8 +12,8 @@
|
||||
- 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 confimation intervals
|
||||
- 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
|
||||
@@ -85,12 +85,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 = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options
|
||||
LDLIBS = -lssl -lcrypto -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 -lcrypto -lssl -lboost_system -lboost_program_options -lpthread
|
||||
LDLIBS = -lbe -lbsd -lnetwork -lz -lssl -lcrypto -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 -lcrypto -lssl -lboost_system -lboost_filesystem -lboost_program_options -lpthread
|
||||
LDLIBS = -lz -lssl -lcrypto -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 += -lcrypto -lssl -lz -lboost_program_options -lpthread -latomic
|
||||
LDLIBS += -lssl -lcrypto -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/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
|
||||
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
|
||||
else
|
||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_filesystem -lboost_program_options -lpthread
|
||||
LDLIBS = -lz -lssl -lcrypto -lboost_system -lboost_filesystem -lboost_program_options -lpthread
|
||||
endif
|
||||
|
||||
ifeq ($(USE_UPNP),yes)
|
||||
|
||||
@@ -148,7 +148,7 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Sun Feb 09 2025 orignal <orignal@i2pmail.org> - 2.56.0
|
||||
* 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
|
||||
|
||||
@@ -146,7 +146,7 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Sun Feb 09 2025 orignal <orignal@i2pmail.org> - 2.56.0
|
||||
* 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
|
||||
|
||||
2
debian/changelog
vendored
2
debian/changelog
vendored
@@ -2,7 +2,7 @@ i2pd (2.56.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.56.0/0.9.65
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Sun, 09 Feb 2025 16:00:00 +0000
|
||||
-- orignal <orignal@i2pmail.org> Tue, 11 Feb 2025 16:00:00 +0000
|
||||
|
||||
i2pd (2.55.0-1) unstable; urgency=medium
|
||||
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -90,10 +90,10 @@ namespace data
|
||||
}
|
||||
|
||||
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||
const char * signature, const char * key) const
|
||||
std::string_view signature, const char * key) const
|
||||
{
|
||||
uint8_t buf[100], signatureBuf[64];
|
||||
size_t len = family.length (), signatureLen = strlen (signature);
|
||||
size_t len = family.length ();
|
||||
if (len + 32 > 100)
|
||||
{
|
||||
LogPrint (eLogError, "Family: ", family, " is too long");
|
||||
@@ -105,7 +105,7 @@ namespace data
|
||||
memcpy (buf, family.c_str (), len);
|
||||
memcpy (buf + len, (const uint8_t *)ident, 32);
|
||||
len += 32;
|
||||
auto signatureBufLen = Base64ToByteStream (signature, signatureLen, signatureBuf, 64);
|
||||
auto signatureBufLen = Base64ToByteStream (signature.data (), signature.length (), signatureBuf, 64);
|
||||
if (signatureBufLen)
|
||||
{
|
||||
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||
* Copyright (c) 2013-2025, The PurpleI2P Project
|
||||
*
|
||||
* This file is part of Purple i2pd project and licensed under BSD3
|
||||
*
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <memory>
|
||||
#include <openssl/evp.h>
|
||||
#include "Identity.h"
|
||||
@@ -28,7 +29,7 @@ namespace data
|
||||
~Families ();
|
||||
void LoadCertificates ();
|
||||
bool VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||
const char * signature, const char * key = nullptr) const;
|
||||
std::string_view signature, const char * key = nullptr) const;
|
||||
FamilyID GetFamilyID (const std::string& family) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "I2PEndian.h"
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <charconv>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string.hpp> // for boost::to_lower
|
||||
#ifndef __cpp_lib_atomic_shared_ptr
|
||||
@@ -106,8 +107,7 @@ namespace data
|
||||
// skip identity
|
||||
size_t identityLen = m_RouterIdentity->GetFullLen ();
|
||||
// read new RI
|
||||
std::stringstream str (std::string ((char *)buf + identityLen, len - identityLen));
|
||||
ReadFromStream (str);
|
||||
ReadFromBuffer (buf + identityLen, len - identityLen);
|
||||
if (!m_IsUnreachable)
|
||||
UpdateBuffer (buf, len); // save buffer
|
||||
// don't delete buffer until saved to the file
|
||||
@@ -195,39 +195,34 @@ namespace data
|
||||
}
|
||||
}
|
||||
// parse RI
|
||||
std::stringstream str;
|
||||
str.write ((const char *)m_Buffer->data () + identityLen, bufferLen - identityLen);
|
||||
ReadFromStream (str);
|
||||
if (!str)
|
||||
if (!ReadFromBuffer (m_Buffer->data () + identityLen, bufferLen - identityLen))
|
||||
{
|
||||
LogPrint (eLogError, "RouterInfo: Malformed message");
|
||||
m_IsUnreachable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RouterInfo::ReadFromStream (std::istream& s)
|
||||
bool RouterInfo::ReadFromBuffer (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (!s) return;
|
||||
if (len < 9) return false;
|
||||
m_Caps = 0; m_Congestion = eLowCongestion;
|
||||
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp));
|
||||
m_Timestamp = be64toh (m_Timestamp);
|
||||
m_Timestamp = bufbe64toh (buf);
|
||||
size_t offset = 8; // timestamp
|
||||
// read addresses
|
||||
auto addresses = NewAddresses ();
|
||||
uint8_t numAddresses;
|
||||
s.read ((char *)&numAddresses, sizeof (numAddresses));
|
||||
uint8_t numAddresses = buf[offset]; offset++;
|
||||
for (int i = 0; i < numAddresses; i++)
|
||||
{
|
||||
if (offset + 9 > len) return false; // 1 byte cost + 8 bytes date
|
||||
uint8_t supportedTransports = 0;
|
||||
auto address = NewAddress ();
|
||||
uint8_t cost; // ignore
|
||||
s.read ((char *)&cost, sizeof (cost));
|
||||
s.read ((char *)&address->date, sizeof (address->date));
|
||||
offset++; // cost, ignore
|
||||
address->date = bufbe64toh (buf + offset); offset += 8; // date
|
||||
bool isHost = false, isStaticKey = false, isV2 = false, isIntroKey = false;
|
||||
char transportStyle[6];
|
||||
ReadString (transportStyle, 6, s);
|
||||
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
|
||||
auto transportStyle = ExtractString (buf + offset, len - offset); offset += transportStyle.length () + 1;
|
||||
if (!transportStyle.compare (0, 4, "NTCP")) // NTCP or NTCP2
|
||||
address->transportStyle = eTransportNTCP2;
|
||||
else if (!strncmp (transportStyle, "SSU", 3)) // SSU or SSU2
|
||||
else if (!transportStyle.compare (0, 3, "SSU")) // SSU or SSU2
|
||||
{
|
||||
address->transportStyle = eTransportSSU2;
|
||||
address->ssu.reset (new SSUExt ());
|
||||
@@ -237,24 +232,22 @@ namespace data
|
||||
address->transportStyle = eTransportUnknown;
|
||||
address->caps = 0;
|
||||
address->port = 0;
|
||||
uint16_t size, r = 0;
|
||||
s.read ((char *)&size, sizeof (size)); if (!s) return;
|
||||
size = be16toh (size);
|
||||
if (offset + 2 > len) return false;
|
||||
uint16_t size = bufbe16toh (buf + offset); offset += 2; // size
|
||||
if (offset + size >= len) return false;
|
||||
if (address->transportStyle == eTransportUnknown)
|
||||
{
|
||||
// skip unknown address
|
||||
s.seekg (size, std::ios_base::cur);
|
||||
if (s) continue; else return;
|
||||
offset += size;
|
||||
continue;
|
||||
}
|
||||
size_t r = 0;
|
||||
while (r < size)
|
||||
{
|
||||
char key[255], value[255];
|
||||
r += ReadString (key, 255, s);
|
||||
s.seekg (1, std::ios_base::cur); r++; // =
|
||||
r += ReadString (value, 255, s);
|
||||
s.seekg (1, std::ios_base::cur); r++; // ;
|
||||
if (!s) return;
|
||||
if (!strcmp (key, "host"))
|
||||
auto [key, value, sz] = ExtractParam (buf + offset, len - offset);
|
||||
r += sz; offset += sz;
|
||||
if (key.empty ()) continue;
|
||||
if (key == "host")
|
||||
{
|
||||
boost::system::error_code ecode;
|
||||
address->host = boost::asio::ip::make_address (value, ecode);
|
||||
@@ -268,7 +261,7 @@ namespace data
|
||||
address->transportStyle = eTransportUnknown;
|
||||
}
|
||||
}
|
||||
else if (!strcmp (key, "port"))
|
||||
else if (key == "port")
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -279,7 +272,7 @@ namespace data
|
||||
LogPrint (eLogWarning, "RouterInfo: 'port' exception ", ex.what ());
|
||||
}
|
||||
}
|
||||
else if (!strcmp (key, "mtu"))
|
||||
else if (key == "mtu")
|
||||
{
|
||||
if (address->ssu)
|
||||
{
|
||||
@@ -295,36 +288,36 @@ namespace data
|
||||
else
|
||||
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2");
|
||||
}
|
||||
else if (!strcmp (key, "caps"))
|
||||
else if (key == "caps")
|
||||
address->caps = ExtractAddressCaps (value);
|
||||
else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key
|
||||
else if (key == "s") // ntcp2 or ssu2 static key
|
||||
{
|
||||
if (Base64ToByteStream (value, strlen (value), address->s, 32) == 32 &&
|
||||
if (Base64ToByteStream (value.data (), value.length (), address->s, 32) == 32 &&
|
||||
!(address->s[31] & 0x80)) // check if x25519 public key
|
||||
isStaticKey = true;
|
||||
else
|
||||
address->transportStyle = eTransportUnknown; // invalid address
|
||||
}
|
||||
else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro
|
||||
else if (key == "i") // ntcp2 iv or ssu2 intro
|
||||
{
|
||||
if (address->IsNTCP2 ())
|
||||
{
|
||||
if (Base64ToByteStream (value, strlen (value), address->i, 16) == 16)
|
||||
if (Base64ToByteStream (value.data (), value.length (), address->i, 16) == 16)
|
||||
address->published = true; // presence of "i" means "published" NTCP2
|
||||
else
|
||||
address->transportStyle = eTransportUnknown; // invalid address
|
||||
}
|
||||
else if (address->IsSSU2 ())
|
||||
{
|
||||
if (Base64ToByteStream (value, strlen (value), address->i, 32) == 32)
|
||||
if (Base64ToByteStream (value.data (), value.length (), address->i, 32) == 32)
|
||||
isIntroKey = true;
|
||||
else
|
||||
address->transportStyle = eTransportUnknown; // invalid address
|
||||
}
|
||||
}
|
||||
else if (!strcmp (key, "v"))
|
||||
else if (key == "v")
|
||||
{
|
||||
if (!strcmp (value, "2"))
|
||||
if (value == "2")
|
||||
isV2 = true;
|
||||
else
|
||||
{
|
||||
@@ -340,13 +333,11 @@ namespace data
|
||||
LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped");
|
||||
continue;
|
||||
}
|
||||
size_t l = strlen(key);
|
||||
unsigned char index = key[l-1] - '0'; // TODO:
|
||||
key[l-1] = 0;
|
||||
unsigned char index = key[key.length () - 1] - '0'; // TODO:
|
||||
if (index > 9)
|
||||
{
|
||||
LogPrint (eLogError, "RouterInfo: Unexpected introducer's index ", index, " skipped");
|
||||
if (s) continue; else return;
|
||||
continue;
|
||||
}
|
||||
if (index >= address->ssu->introducers.size ())
|
||||
{
|
||||
@@ -355,7 +346,8 @@ namespace data
|
||||
address->ssu->introducers.resize (index + 1);
|
||||
}
|
||||
Introducer& introducer = address->ssu->introducers.at (index);
|
||||
if (!strcmp (key, "itag"))
|
||||
auto key1 = key.substr(0, key.length () - 1);
|
||||
if (key1 == "itag")
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -366,9 +358,9 @@ namespace data
|
||||
LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ());
|
||||
}
|
||||
}
|
||||
else if (!strcmp (key, "ih"))
|
||||
Base64ToByteStream (value, strlen (value), introducer.iH, 32);
|
||||
else if (!strcmp (key, "iexp"))
|
||||
else if (key1 == "ih")
|
||||
Base64ToByteStream (value.data (), value.length (), introducer.iH, 32);
|
||||
else if (key1 == "iexp")
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -380,9 +372,7 @@ namespace data
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!s) return;
|
||||
}
|
||||
|
||||
}
|
||||
if (address->transportStyle == eTransportNTCP2)
|
||||
{
|
||||
if (isStaticKey)
|
||||
@@ -446,45 +436,41 @@ namespace data
|
||||
boost::atomic_store (&m_Addresses, addresses);
|
||||
#endif
|
||||
// read peers
|
||||
uint8_t numPeers;
|
||||
s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return;
|
||||
s.seekg (numPeers*32, std::ios_base::cur); // TODO: read peers
|
||||
if (offset + 1 > len) return false;
|
||||
uint8_t numPeers = buf[offset]; offset++; // num peers
|
||||
offset += numPeers*32; // TODO: read peers
|
||||
// read properties
|
||||
if (offset + 2 > len) return false;
|
||||
m_Version = 0;
|
||||
bool isNetId = false;
|
||||
std::string family;
|
||||
uint16_t size, r = 0;
|
||||
s.read ((char *)&size, sizeof (size)); if (!s) return;
|
||||
size = be16toh (size);
|
||||
uint16_t size = bufbe16toh (buf + offset); offset += 2; // size
|
||||
if (offset + size > len) return false;
|
||||
size_t r = 0;
|
||||
while (r < size)
|
||||
{
|
||||
char key[255], value[255];
|
||||
r += ReadString (key, 255, s);
|
||||
s.seekg (1, std::ios_base::cur); r++; // =
|
||||
r += ReadString (value, 255, s);
|
||||
s.seekg (1, std::ios_base::cur); r++; // ;
|
||||
if (!s) return;
|
||||
auto [key, value, sz] = ExtractParam (buf + offset, len - offset);
|
||||
r += sz; offset += sz;
|
||||
if (key.empty ()) continue;
|
||||
SetProperty (key, value);
|
||||
|
||||
// extract caps
|
||||
if (!strcmp (key, "caps"))
|
||||
if (key == "caps")
|
||||
{
|
||||
ExtractCaps (value);
|
||||
m_IsFloodfill = IsDeclaredFloodfill ();
|
||||
}
|
||||
// extract version
|
||||
else if (!strcmp (key, ROUTER_INFO_PROPERTY_VERSION))
|
||||
else if (key == ROUTER_INFO_PROPERTY_VERSION)
|
||||
{
|
||||
m_Version = 0;
|
||||
char * ch = value;
|
||||
while (*ch)
|
||||
for (auto ch: value)
|
||||
{
|
||||
if (*ch >= '0' && *ch <= '9')
|
||||
if (ch >= '0' && ch <= '9')
|
||||
{
|
||||
m_Version *= 10;
|
||||
m_Version += (*ch - '0');
|
||||
m_Version += (ch - '0');
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
if (m_Version < NETDB_MIN_PEER_TEST_VERSION && (m_SupportedTransports & (eSSU2V4 | eSSU2V6)))
|
||||
{
|
||||
@@ -497,24 +483,26 @@ namespace data
|
||||
}
|
||||
}
|
||||
// check netId
|
||||
else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID))
|
||||
else if (key == ROUTER_INFO_PROPERTY_NETID)
|
||||
{
|
||||
isNetId = true;
|
||||
if (atoi (value) != i2p::context.GetNetID ())
|
||||
int netID;
|
||||
auto res = std::from_chars(value.data(), value.data() + value.size(), netID);
|
||||
if (res.ec != std::errc() || netID != i2p::context.GetNetID ())
|
||||
{
|
||||
LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value);
|
||||
m_IsUnreachable = true;
|
||||
}
|
||||
}
|
||||
// family
|
||||
else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY))
|
||||
else if (key == ROUTER_INFO_PROPERTY_FAMILY)
|
||||
{
|
||||
family = value;
|
||||
boost::to_lower (family);
|
||||
}
|
||||
else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY_SIG))
|
||||
else if (key == ROUTER_INFO_PROPERTY_FAMILY_SIG)
|
||||
{
|
||||
if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value))
|
||||
if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value)) // TODO
|
||||
m_FamilyID = netdb.GetFamilies ().GetFamilyID (family);
|
||||
else
|
||||
{
|
||||
@@ -522,25 +510,24 @@ namespace data
|
||||
SetUnreachable (true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!s) return;
|
||||
}
|
||||
|
||||
if (!m_SupportedTransports || !isNetId || !m_Version)
|
||||
SetUnreachable (true);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RouterInfo::IsFamily (FamilyID famid) const
|
||||
{
|
||||
return m_FamilyID == famid;
|
||||
}
|
||||
|
||||
void RouterInfo::ExtractCaps (const char * value)
|
||||
void RouterInfo::ExtractCaps (std::string_view value)
|
||||
{
|
||||
const char * cap = value;
|
||||
while (*cap)
|
||||
for (auto cap: value)
|
||||
{
|
||||
switch (*cap)
|
||||
switch (cap)
|
||||
{
|
||||
case CAPS_FLAG_FLOODFILL:
|
||||
m_Caps |= Caps::eFloodfill;
|
||||
@@ -549,16 +536,16 @@ namespace data
|
||||
case CAPS_FLAG_LOW_BANDWIDTH2:
|
||||
case CAPS_FLAG_LOW_BANDWIDTH3:
|
||||
case CAPS_FLAG_LOW_BANDWIDTH4:
|
||||
m_BandwidthCap = *cap;
|
||||
m_BandwidthCap = cap;
|
||||
break;
|
||||
case CAPS_FLAG_HIGH_BANDWIDTH:
|
||||
m_Caps |= Caps::eHighBandwidth;
|
||||
m_BandwidthCap = *cap;
|
||||
m_BandwidthCap = cap;
|
||||
break;
|
||||
case CAPS_FLAG_EXTRA_BANDWIDTH1:
|
||||
case CAPS_FLAG_EXTRA_BANDWIDTH2:
|
||||
m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth;
|
||||
m_BandwidthCap = *cap;
|
||||
m_BandwidthCap = cap;
|
||||
break;
|
||||
case CAPS_FLAG_HIDDEN:
|
||||
m_Caps |= Caps::eHidden;
|
||||
@@ -580,17 +567,15 @@ namespace data
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
cap++;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t RouterInfo::ExtractAddressCaps (const char * value) const
|
||||
}
|
||||
|
||||
uint8_t RouterInfo::ExtractAddressCaps (std::string_view value) const
|
||||
{
|
||||
uint8_t caps = 0;
|
||||
const char * cap = value;
|
||||
while (*cap)
|
||||
for (auto cap: value)
|
||||
{
|
||||
switch (*cap)
|
||||
switch (cap)
|
||||
{
|
||||
case CAPS_FLAG_V4:
|
||||
caps |= AddressCaps::eV4;
|
||||
@@ -606,11 +591,10 @@ namespace data
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
cap++;
|
||||
}
|
||||
return caps;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RouterInfo::UpdateIntroducers (std::shared_ptr<Address> address, uint64_t ts)
|
||||
{
|
||||
if (!address || !address->ssu) return;
|
||||
@@ -670,25 +654,41 @@ namespace data
|
||||
return SaveToFile (fullPath, m_Buffer);
|
||||
}
|
||||
|
||||
size_t RouterInfo::ReadString (char * str, size_t len, std::istream& s) const
|
||||
std::string_view RouterInfo::ExtractString (const uint8_t * buf, size_t len) const
|
||||
{
|
||||
uint8_t l;
|
||||
s.read ((char *)&l, 1);
|
||||
if (l < len)
|
||||
{
|
||||
s.read (str, l);
|
||||
if (!s) l = 0; // failed, return empty string
|
||||
str[l] = 0;
|
||||
}
|
||||
else
|
||||
uint8_t l = buf[0];
|
||||
if (l > len)
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: String length ", (int)l, " exceeds buffer size ", len);
|
||||
s.seekg (l, std::ios::cur); // skip
|
||||
str[0] = 0;
|
||||
}
|
||||
return l+1;
|
||||
l = len;
|
||||
}
|
||||
return { (const char *)(buf + 1), l };
|
||||
}
|
||||
|
||||
std::tuple<std::string_view, std::string_view, size_t> RouterInfo::ExtractParam (const uint8_t * buf, size_t len) const
|
||||
{
|
||||
auto key = ExtractString (buf, len);
|
||||
size_t offset = key.length () + 1;
|
||||
if (offset >= len) return { std::string_view(), std::string_view(), len };
|
||||
if (buf[offset] != '=')
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: Unexpected character ", buf[offset], " instead '=' after ", key);
|
||||
key = std::string_view();
|
||||
}
|
||||
offset++;
|
||||
if (offset >= len) return { key, std::string_view(), len };
|
||||
auto value = ExtractString (buf + offset, len - offset);
|
||||
offset += value.length () + 1;
|
||||
if (offset >= len) return { key, std::string_view(), len };
|
||||
if (buf[offset] != ';')
|
||||
{
|
||||
LogPrint (eLogWarning, "RouterInfo: Unexpected character ", buf[offset], " instead ';' after ", value);
|
||||
value = std::string_view();
|
||||
}
|
||||
offset++;
|
||||
return { key, value, offset };
|
||||
}
|
||||
|
||||
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,int port, uint8_t caps)
|
||||
{
|
||||
auto addr = std::make_shared<Address>();
|
||||
@@ -1485,9 +1485,11 @@ namespace data
|
||||
s.write (properties.str ().c_str (), properties.str ().size ());
|
||||
}
|
||||
|
||||
void LocalRouterInfo::SetProperty (const std::string& key, const std::string& value)
|
||||
void LocalRouterInfo::SetProperty (std::string_view key, std::string_view value)
|
||||
{
|
||||
m_Properties[key] = value;
|
||||
auto [it, inserted] = m_Properties.emplace (key, value);
|
||||
if (!inserted)
|
||||
it->second = value;
|
||||
}
|
||||
|
||||
void LocalRouterInfo::DeleteProperty (const std::string& key)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
@@ -219,7 +221,7 @@ namespace data
|
||||
std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); };
|
||||
uint64_t GetTimestamp () const { return m_Timestamp; };
|
||||
int GetVersion () const { return m_Version; };
|
||||
virtual void SetProperty (const std::string& key, const std::string& value) {};
|
||||
virtual void SetProperty (std::string_view key, std::string_view value) {};
|
||||
virtual void ClearProperties () {};
|
||||
AddressesPtr GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr
|
||||
std::shared_ptr<const Address> GetNTCP2V4Address () const;
|
||||
@@ -333,11 +335,12 @@ namespace data
|
||||
|
||||
bool LoadFile (const std::string& fullPath);
|
||||
void ReadFromFile (const std::string& fullPath);
|
||||
void ReadFromStream (std::istream& s);
|
||||
bool ReadFromBuffer (const uint8_t * buf, size_t len); // return false if malformed
|
||||
void ReadFromBuffer (bool verifySignature);
|
||||
size_t ReadString (char* str, size_t len, std::istream& s) const;
|
||||
void ExtractCaps (const char * value);
|
||||
uint8_t ExtractAddressCaps (const char * value) const;
|
||||
std::string_view ExtractString (const uint8_t * buf, size_t len) const;
|
||||
std::tuple<std::string_view, std::string_view, size_t> ExtractParam (const uint8_t * buf, size_t len) const;
|
||||
void ExtractCaps (std::string_view value);
|
||||
uint8_t ExtractAddressCaps (std::string_view value) const;
|
||||
void UpdateIntroducers (std::shared_ptr<Address> address, uint64_t ts);
|
||||
template<typename Filter>
|
||||
std::shared_ptr<const Address> GetAddress (Filter filter) const;
|
||||
@@ -379,7 +382,7 @@ namespace data
|
||||
void UpdateCaps (uint8_t caps);
|
||||
bool UpdateCongestion (Congestion c); // returns true if updated
|
||||
|
||||
void SetProperty (const std::string& key, const std::string& value) override;
|
||||
void SetProperty (std::string_view key, std::string_view value) override;
|
||||
void DeleteProperty (const std::string& key);
|
||||
std::string GetProperty (const std::string& key) const;
|
||||
void ClearProperties () override { m_Properties.clear (); };
|
||||
|
||||
@@ -1251,18 +1251,21 @@ namespace transport
|
||||
}
|
||||
uint64_t token;
|
||||
RAND_bytes ((uint8_t *)&token, 8);
|
||||
m_IncomingTokens.emplace (ep, std::make_pair (token, uint32_t(ts + SSU2_TOKEN_EXPIRATION_TIMEOUT)));
|
||||
if (!token) token = 1; // token can't be zero
|
||||
m_IncomingTokens.try_emplace (ep, token, uint32_t(ts + SSU2_TOKEN_EXPIRATION_TIMEOUT));
|
||||
return token;
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint32_t> SSU2Server::NewIncomingToken (const boost::asio::ip::udp::endpoint& ep)
|
||||
{
|
||||
m_IncomingTokens.erase (ep); // drop previous
|
||||
uint64_t token;
|
||||
RAND_bytes ((uint8_t *)&token, 8);
|
||||
auto ret = std::make_pair (token, uint32_t(i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT));
|
||||
m_IncomingTokens.emplace (ep, ret);
|
||||
return ret;
|
||||
if (!token) token = 1; // token can't be zero
|
||||
uint32_t expires = i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT;
|
||||
auto [it, inserted] = m_IncomingTokens.try_emplace (ep, token, expires);
|
||||
if (!inserted)
|
||||
it->second = { token, expires }; // override
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<SSU2Session> > SSU2Server::FindIntroducers (int maxNumIntroducers,
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace transport
|
||||
{
|
||||
// we are Charlie
|
||||
uint64_t destConnID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id
|
||||
uint32_t sourceConnID = ~destConnID;
|
||||
uint64_t sourceConnID = ~destConnID;
|
||||
SetSourceConnID (sourceConnID);
|
||||
SetDestConnID (destConnID);
|
||||
SetState (eSSU2SessionStateHolePunch);
|
||||
|
||||
@@ -2762,7 +2762,7 @@ namespace transport
|
||||
size_t SSU2Session::CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize)
|
||||
{
|
||||
if (len < 3 || len < minSize) return 0;
|
||||
size_t paddingSize = m_Server.GetRng ()() & 0x0F; // 0 - 15
|
||||
size_t paddingSize = m_Server.GetRng ()() & 0x1F; // 0 - 31
|
||||
if (paddingSize + 3 > len) paddingSize = len - 3;
|
||||
else if (paddingSize + 3 < minSize) paddingSize = minSize - 3;
|
||||
buf[0] = eSSU2BlkPadding;
|
||||
|
||||
@@ -1297,7 +1297,7 @@ namespace stream
|
||||
m_NumPacketsToSend = 1; m_PacingTimeRem = 0;
|
||||
}
|
||||
m_IsSendTime = true;
|
||||
if (m_WindowIncCounter && (m_WindowSize < MAX_WINDOW_SIZE || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime)
|
||||
if (m_WindowIncCounter && (m_WindowSize < MAX_WINDOW_SIZE || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime && m_RTT <= m_SlowRTT)
|
||||
{
|
||||
for (int i = 0; i < m_NumPacketsToSend; i++)
|
||||
{
|
||||
@@ -1307,7 +1307,7 @@ namespace stream
|
||||
{
|
||||
if (m_LastWindowDropSize && (m_LastWindowDropSize >= m_WindowDropTargetSize))
|
||||
m_WindowDropTargetSize += 1 - (1 / ((m_LastWindowDropSize + PREV_SPEED_KEEP_TIME_COEFF) / m_WindowDropTargetSize)); // some magic here
|
||||
else if (m_LastWindowDropSize && (m_LastWindowDropSize < m_WindowSize))
|
||||
else if (m_LastWindowDropSize && (m_LastWindowDropSize < m_WindowDropTargetSize))
|
||||
m_WindowDropTargetSize += (m_WindowDropTargetSize - (m_LastWindowDropSize - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize; // some magic here
|
||||
else
|
||||
m_WindowDropTargetSize += (m_WindowDropTargetSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize;
|
||||
@@ -1646,14 +1646,22 @@ namespace stream
|
||||
|
||||
void Stream::ProcessWindowDrop ()
|
||||
{
|
||||
if (m_WindowSize > m_LastWindowDropSize)
|
||||
{
|
||||
m_LastWindowDropSize = (m_LastWindowDropSize + m_WindowSize + m_WindowSizeTail) / 2;
|
||||
if (m_LastWindowDropSize > MAX_WINDOW_SIZE) m_LastWindowDropSize = MAX_WINDOW_SIZE;
|
||||
}
|
||||
if (m_WindowDropTargetSize)
|
||||
m_WindowDropTargetSize = (m_WindowDropTargetSize / 2) * 0.75; // congestion window size and -25% to drain queue
|
||||
else
|
||||
m_LastWindowDropSize = m_WindowSize;
|
||||
m_WindowDropTargetSize = m_LastWindowDropSize - (m_LastWindowDropSize / 4); // -25%;
|
||||
{
|
||||
if (m_WindowSize < m_LastWindowDropSize)
|
||||
{
|
||||
m_LastWindowDropSize = m_WindowSize - (m_LastWindowDropSize - m_WindowSize);
|
||||
if (m_LastWindowDropSize < MIN_WINDOW_SIZE) m_LastWindowDropSize = MIN_WINDOW_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LastWindowDropSize = (m_LastWindowDropSize + m_WindowSize + m_WindowSizeTail) / 2;
|
||||
if (m_LastWindowDropSize > MAX_WINDOW_SIZE) m_LastWindowDropSize = MAX_WINDOW_SIZE;
|
||||
}
|
||||
m_WindowDropTargetSize = m_LastWindowDropSize * 0.75; // -25% to drain queue
|
||||
}
|
||||
if (m_WindowDropTargetSize < MIN_WINDOW_SIZE)
|
||||
m_WindowDropTargetSize = MIN_WINDOW_SIZE;
|
||||
m_WindowIncCounter = 0; // disable window growth
|
||||
|
||||
@@ -315,22 +315,28 @@ 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;
|
||||
block.tunnelID = gwTunnel; // Set tunnelID only if gwTunnel is non-zero
|
||||
}
|
||||
else
|
||||
{
|
||||
block.deliveryType = eDeliveryTypeRouter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
block.deliveryType = eDeliveryTypeLocal;
|
||||
}
|
||||
|
||||
block.data = msg;
|
||||
|
||||
SendTunnelDataMsgs ({block});
|
||||
SendTunnelDataMsgs({block});
|
||||
}
|
||||
|
||||
void OutboundTunnel::SendTunnelDataMsgs (const std::vector<TunnelMessageBlock>& msgs)
|
||||
|
||||
@@ -351,10 +351,13 @@ namespace tunnel
|
||||
{
|
||||
it.second.first->SetState (eTunnelStateFailed);
|
||||
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
|
||||
if (m_OutboundTunnels.size () > 1 || m_NumOutboundTunnels <= 1) // don't fail last tunnel
|
||||
if (m_OutboundTunnels.size () > 1) // don't fail last tunnel
|
||||
m_OutboundTunnels.erase (it.second.first);
|
||||
else
|
||||
{
|
||||
it.second.first->SetState (eTunnelStateTestFailed);
|
||||
CreateOutboundTunnel (); // create new tunnel immediately because last one failed
|
||||
}
|
||||
}
|
||||
else if (it.second.first->GetState () != eTunnelStateExpiring)
|
||||
it.second.first->SetState (eTunnelStateTestFailed);
|
||||
@@ -368,13 +371,16 @@ namespace tunnel
|
||||
bool failed = false;
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
|
||||
if (m_InboundTunnels.size () > 1 || m_NumInboundTunnels <= 1) // don't fail last tunnel
|
||||
if (m_InboundTunnels.size () > 1) // don't fail last tunnel
|
||||
{
|
||||
m_InboundTunnels.erase (it.second.second);
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
it.second.second->SetState (eTunnelStateTestFailed);
|
||||
CreateInboundTunnel (); // create new tunnel immediately because last one failed
|
||||
}
|
||||
}
|
||||
if (failed && m_LocalDestination)
|
||||
m_LocalDestination->SetLeaseSetUpdated (true);
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace client
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogCritical, "Clients: Can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType);
|
||||
LogPrint (eLogInfo, "Clients: Can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType);
|
||||
keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true);
|
||||
std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out);
|
||||
size_t len = keys.GetFullLen ();
|
||||
@@ -871,7 +871,7 @@ namespace client
|
||||
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "Clients: Unknown section type = ", type, " of ", name, " in ", tunConf);
|
||||
LogPrint (eLogError, "Clients: Unknown section type = ", type, " of ", name, " in ", tunConf);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
|
||||
@@ -29,13 +29,15 @@ namespace client
|
||||
const std::map<std::string, std::string>& params):
|
||||
LeaseSetDestination (service, isPublic, ¶ms),
|
||||
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()),
|
||||
m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread), m_LeaseSetCreationTimer (service)
|
||||
m_IsCreatingLeaseSet (false), m_IsSameThread (isSameThread),
|
||||
m_LeaseSetCreationTimer (service), m_ReadinessCheckTimer (service)
|
||||
{
|
||||
}
|
||||
|
||||
void I2CPDestination::Stop ()
|
||||
{
|
||||
m_LeaseSetCreationTimer.cancel ();
|
||||
m_ReadinessCheckTimer.cancel ();
|
||||
LeaseSetDestination::Stop ();
|
||||
m_Owner = nullptr;
|
||||
}
|
||||
@@ -88,7 +90,7 @@ namespace client
|
||||
|
||||
void I2CPDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels)
|
||||
{
|
||||
boost::asio::post (GetService (), std::bind (&I2CPDestination::PostCreateNewLeaseSet, this, tunnels));
|
||||
boost::asio::post (GetService (), std::bind (&I2CPDestination::PostCreateNewLeaseSet, GetSharedFromThis (), tunnels));
|
||||
}
|
||||
|
||||
void I2CPDestination::PostCreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
||||
@@ -98,6 +100,20 @@ namespace client
|
||||
LogPrint (eLogInfo, "I2CP: LeaseSet is being created");
|
||||
return;
|
||||
}
|
||||
m_ReadinessCheckTimer.cancel ();
|
||||
auto pool = GetTunnelPool ();
|
||||
if (!pool || pool->GetOutboundTunnels ().empty ())
|
||||
{
|
||||
// try again later
|
||||
m_ReadinessCheckTimer.expires_from_now (boost::posix_time::seconds(I2CP_DESTINATION_READINESS_CHECK_INTERVAL));
|
||||
m_ReadinessCheckTimer.async_wait(
|
||||
[s=GetSharedFromThis (), tunnels=std::move(tunnels)](const boost::system::error_code& ecode)
|
||||
{
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
s->PostCreateNewLeaseSet (tunnels);
|
||||
});
|
||||
return;
|
||||
}
|
||||
uint8_t priv[256] = {0};
|
||||
i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only
|
||||
m_LeaseSetExpirationTime = ls.GetExpirationTime ();
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace client
|
||||
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
|
||||
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M
|
||||
const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds
|
||||
const int I2CP_DESTINATION_READINESS_CHECK_INTERVAL = 5; // in seconds
|
||||
const int I2CP_SESSION_ACK_REQUEST_INTERVAL = 12100; // in milliseconds
|
||||
|
||||
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
|
||||
@@ -131,7 +132,7 @@ namespace client
|
||||
uint8_t m_ECIESx25519PrivateKey[32];
|
||||
uint64_t m_LeaseSetExpirationTime;
|
||||
bool m_IsCreatingLeaseSet, m_IsSameThread;
|
||||
boost::asio::deadline_timer m_LeaseSetCreationTimer;
|
||||
boost::asio::deadline_timer m_LeaseSetCreationTimer, m_ReadinessCheckTimer;
|
||||
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> > m_I2NPMsgsPool;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user