Browse Source

update config file example, add v6 status to windows daemon window, code cleanup

Signed-off-by: R4SAS <r4sas@i2pmail.org>
pull/1656/head
R4SAS 4 years ago
parent
commit
c359c6e634
Signed by: r4sas
GPG Key ID: 66F6C87B98EBCFE2
  1. 42
      Win32/Win32App.cpp
  2. 54
      contrib/i2pd.conf
  3. 26
      daemon/Daemon.cpp
  4. 22
      daemon/HTTPServer.cpp
  5. 4
      daemon/I2PControl.cpp
  6. 14
      libi2pd/Config.cpp
  7. 5
      libi2pd/Destination.cpp
  8. 56
      libi2pd/NTCP2.cpp
  9. 154
      libi2pd/RouterContext.cpp
  10. 98
      libi2pd/SSU.cpp
  11. 2
      libi2pd/SSUSession.cpp

42
Win32/Win32App.cpp

@ -142,25 +142,47 @@ namespace win32
s << bytes << " Bytes\n"; s << bytes << " Bytes\n";
} }
static void PrintMainWindowText (std::stringstream& s) static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
{ {
s << "\n"; switch (status)
s << "Status: ";
switch (i2p::context.GetStatus())
{ {
case eRouterStatusOK: s << "OK"; break; case eRouterStatusOK: s << "OK"; break;
case eRouterStatusTesting: s << "Testing"; break; case eRouterStatusTesting: s << "Test"; break;
case eRouterStatusFirewalled: s << "Firewalled"; break; case eRouterStatusFirewalled: s << "FW"; break;
case eRouterStatusUnknown: s << "Unk"; break;
case eRouterStatusProxy: s << "Proxy"; break;
case eRouterStatusMesh: s << "Mesh"; break;
case eRouterStatusError: case eRouterStatusError:
{ {
switch (i2p::context.GetError()) s << "Err";
switch (i2p::context.GetError ())
{ {
case eRouterErrorClockSkew: s << "Clock skew"; break; case eRouterErrorClockSkew:
default: s << "Error"; s << " - Clock skew";
break;
case eRouterErrorOffline:
s << " - Offline";
break;
case eRouterErrorSymmetricNAT:
s << " - Symmetric NAT";
break;
default: ;
} }
break; break;
} }
default: s << "Unknown"; default: s << "Unk";
}
}
static void PrintMainWindowText (std::stringstream& s)
{
s << "\n";
s << "Status: ";
ShowNetworkStatus (s, i2p::context.GetStatus ());
if (i2p::context.SupportsV6 ())
{
s << " / ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
} }
s << "; "; s << "; ";
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n"; s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";

54
contrib/i2pd.conf

@ -35,14 +35,30 @@
## Write full CLF-formatted date and time to log (default: write only time) ## Write full CLF-formatted date and time to log (default: write only time)
# logclftime = true # logclftime = true
## Daemon mode. Router will go to background after start ## Daemon mode. Router will go to background after start. Ignored on Windows
# daemon = true # daemon = true
## Specify a family, router belongs to (default - none) ## Specify a family, router belongs to (default - none)
# family = # family =
## External IP address to listen for connections ## Network interface to bind to
## Updates address4/6 options if they are not set
# ifname =
## You can specify different interfaces for IPv4 and IPv6
# ifname4 =
# ifname6 =
## Local address to bind transport sockets to
## Overrides host option if:
## For ipv4: if ipv4 = true and nat = false
## For ipv6: if 'host' is not set or ipv4 = true
# address4 =
# address6 =
## External IPv4 or IPv6 address to listen for connections
## By default i2pd sets IP automatically ## By default i2pd sets IP automatically
## Sets published NTCP2v4/SSUv4 address to 'host' value if nat = true
## Sets published NTCP2v6/SSUv6 address to 'host' value if ipv4 = false
# host = 1.2.3.4 # host = 1.2.3.4
## Port to listen for connections ## Port to listen for connections
@ -55,17 +71,6 @@ ipv4 = true
## Enable communication through ipv6 ## Enable communication through ipv6
ipv6 = false ipv6 = false
## Network interface to bind to
# ifname =
## You can specify different interfaces for IPv4 and IPv6
# ifname4 =
# ifname6 =
## Enable NTCP transport (default = true)
# ntcp = true
## If you run i2pd behind a proxy server, you can only use NTCP transport with ntcpproxy option
## Should be http://address:port or socks://address:port
# ntcpproxy = http://127.0.0.1:8118
## Enable SSU transport (default = true) ## Enable SSU transport (default = true)
# ssu = true # ssu = true
@ -82,6 +87,7 @@ ipv6 = false
# notransit = true # notransit = true
## Router will be floodfill ## Router will be floodfill
## Note: that mode uses much more network connections and CPU!
# floodfill = true # floodfill = true
[http] [http]
@ -93,7 +99,7 @@ address = 127.0.0.1
port = 7070 port = 7070
## Path to web console, default "/" ## Path to web console, default "/"
# webroot = / # webroot = /
## Uncomment following lines to enable Web Console authentication ## Uncomment following lines to enable Web Console authentication
# auth = true # auth = true
# user = i2pd # user = i2pd
# pass = changeme # pass = changeme
@ -170,11 +176,11 @@ enabled = true
# name = I2Pd # name = I2Pd
[meshnets] [meshnets]
## Enable connectivity over the Yggdrasil network ## Enable connectivity over the Yggdrasil network
# yggdrasil = false # yggdrasil = false
## You can bind address from your Yggdrasil subnet 300::/64 ## You can bind address from your Yggdrasil subnet 300::/64
## The address must first be added to the network interface ## The address must first be added to the network interface
# yggaddress = # yggaddress =
[reseed] [reseed]
## Options for bootstrapping into I2P network, aka reseeding ## Options for bootstrapping into I2P network, aka reseeding
@ -207,13 +213,13 @@ verify = true
[limits] [limits]
## Maximum active transit sessions (default:2500) ## Maximum active transit sessions (default:2500)
# transittunnels = 2500 # transittunnels = 2500
## Limit number of open file descriptors (0 - use system limit) ## Limit number of open file descriptors (0 - use system limit)
# openfiles = 0 # openfiles = 0
## Maximum size of corefile in Kb (0 - use system limit) ## Maximum size of corefile in Kb (0 - use system limit)
# coresize = 0 # coresize = 0
## Threshold to start probabalistic backoff with ntcp sessions (0 - use system limit) ## Threshold to start probabalistic backoff with ntcp sessions (0 - use system limit)
# ntcpsoft = 0 # ntcpsoft = 0
## Maximum number of ntcp sessions (0 - use system limit) ## Maximum number of ntcp sessions (0 - use system limit)
# ntcphard = 0 # ntcphard = 0
[trust] [trust]
@ -222,13 +228,13 @@ verify = true
## Make direct I2P connections only to routers in specified Family. ## Make direct I2P connections only to routers in specified Family.
# family = MyFamily # family = MyFamily
## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities. ## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities.
# routers = # routers =
## Should we hide our router from other routers? false by default ## Should we hide our router from other routers? false by default
# hidden = true # hidden = true
[exploratory] [exploratory]
## Exploratory tunnels settings with default values ## Exploratory tunnels settings with default values
# inbound.length = 2 # inbound.length = 2
# inbound.quantity = 3 # inbound.quantity = 3
# outbound.length = 2 # outbound.length = 2
# outbound.quantity = 3 # outbound.quantity = 3
@ -237,7 +243,7 @@ verify = true
## Save peer profiles on disk (default: true) ## Save peer profiles on disk (default: true)
# profiles = true # profiles = true
## Save full addresses on disk (default: true) ## Save full addresses on disk (default: true)
# addressbook = true # addressbook = true
[cpuext] [cpuext]
## Use CPU AES-NI instructions set when work with cryptography when available (default: true) ## Use CPU AES-NI instructions set when work with cryptography when available (default: true)

26
daemon/Daemon.cpp

@ -142,23 +142,23 @@ namespace util
i2p::context.SetNetID (netID); i2p::context.SetNetID (netID);
i2p::context.Init (); i2p::context.Init ();
bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv4; i2p::config::GetOption("ipv4", ipv4);
#ifdef MESHNET #ifdef MESHNET
// manual override for meshnet // manual override for meshnet
ipv4 = false; ipv4 = false;
ipv6 = true; ipv6 = true;
#endif #endif
// ifname -> address // ifname -> address
std::string ifname; i2p::config::GetOption("ifname", ifname); std::string ifname; i2p::config::GetOption("ifname", ifname);
if (ipv4 && i2p::config::IsDefault ("address4")) if (ipv4 && i2p::config::IsDefault ("address4"))
{ {
std::string ifname4; i2p::config::GetOption("ifname4", ifname4); std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
if (!ifname4.empty ()) if (!ifname4.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4 i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4
else if (!ifname.empty ()) else if (!ifname.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4 i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4
} }
if (ipv6 && i2p::config::IsDefault ("address6")) if (ipv6 && i2p::config::IsDefault ("address6"))
{ {
std::string ifname6; i2p::config::GetOption("ifname6", ifname6); std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
@ -166,8 +166,8 @@ namespace util
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6 i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6
else if (!ifname.empty ()) else if (!ifname.empty ())
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6 i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6
} }
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
boost::asio::ip::address_v6 yggaddr; boost::asio::ip::address_v6 yggaddr;
if (ygg) if (ygg)
@ -210,10 +210,10 @@ namespace util
{ {
bool published; i2p::config::GetOption("ntcp2.published", published); bool published; i2p::config::GetOption("ntcp2.published", published);
if (published) if (published)
{ {
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
if (!ntcp2proxy.empty ()) published = false; if (!ntcp2proxy.empty ()) published = false;
} }
if (published) if (published)
{ {
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port); uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
@ -232,12 +232,12 @@ namespace util
} }
if (ygg) if (ygg)
{ {
i2p::context.PublishNTCP2Address (port, true, false, false, true); i2p::context.PublishNTCP2Address (port, true, false, false, true);
i2p::context.UpdateNTCP2V6Address (yggaddr); i2p::context.UpdateNTCP2V6Address (yggaddr);
if (!ipv4 && !ipv6) if (!ipv4 && !ipv6)
i2p::context.SetStatus (eRouterStatusMesh); i2p::context.SetStatus (eRouterStatusMesh);
} }
bool transit; i2p::config::GetOption("notransit", transit); bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit); i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);

22
daemon/HTTPServer.cpp

@ -265,15 +265,15 @@ namespace http {
break; break;
case eRouterErrorSymmetricNAT: case eRouterErrorSymmetricNAT:
s << " - Symmetric NAT"; s << " - Symmetric NAT";
break; break;
default: ; default: ;
} }
break; break;
} }
default: s << "Unknown"; default: s << "Unknown";
} }
} }
void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat) void ShowStatus (std::stringstream& s, bool includeHiddenContent, i2p::http::OutputFormatEnum outputFormat)
{ {
s << "<b>Uptime:</b> "; s << "<b>Uptime:</b> ";
@ -287,7 +287,7 @@ namespace http {
s << "<b>Network status 6:</b> "; s << "<b>Network status 6:</b> ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 ()); ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
s << "<br>\r\n"; s << "<br>\r\n";
} }
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY)) #if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
if (auto remains = Daemon.gracefulShutdownInterval) { if (auto remains = Daemon.gracefulShutdownInterval) {
s << "<b>Stopping in:</b> "; s << "<b>Stopping in:</b> ";
@ -1276,14 +1276,14 @@ namespace http {
ident.FromBase32 (b32); ident.FromBase32 (b32);
auto dest = i2p::client::context.FindLocalDestination (ident); auto dest = i2p::client::context.FindLocalDestination (ident);
if (dest) if (dest)
{ {
std::size_t pos; std::size_t pos;
pos = name.find (".i2p"); pos = name.find (".i2p");
if (pos == (name.length () - 4)) if (pos == (name.length () - 4))
{ {
pos = name.find (".b32.i2p"); pos = name.find (".b32.i2p");
if (pos == std::string::npos) if (pos == std::string::npos)
{ {
auto signatureLen = dest->GetIdentity ()->GetSignatureLen (); auto signatureLen = dest->GetIdentity ()->GetSignatureLen ();
uint8_t * signature = new uint8_t[signatureLen]; uint8_t * signature = new uint8_t[signatureLen];
@ -1303,13 +1303,13 @@ namespace http {
"</form>\r\n<br>\r\n"; "</form>\r\n<br>\r\n";
delete[] signature; delete[] signature;
delete[] sig; delete[] sig;
} }
else else
s << "<b>ERROR</b>:&nbsp;Domain can't end with .b32.i2p\r\n<br>\r\n<br>\r\n"; s << "<b>ERROR</b>:&nbsp;Domain can't end with .b32.i2p\r\n<br>\r\n<br>\r\n";
} }
else else
s << "<b>ERROR</b>:&nbsp;Domain must end with .i2p\r\n<br>\r\n<br>\r\n"; s << "<b>ERROR</b>:&nbsp;Domain must end with .i2p\r\n<br>\r\n<br>\r\n";
} }
else else
s << "<b>ERROR</b>:&nbsp;Such destination is not found\r\n<br>\r\n<br>\r\n"; s << "<b>ERROR</b>:&nbsp;Such destination is not found\r\n<br>\r\n<br>\r\n";

4
daemon/I2PControl.cpp

@ -2,6 +2,10 @@
#include <sstream> #include <sstream>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/pem.h> #include <openssl/pem.h>
// Use global placeholders from boost introduced when local_time.hpp is loaded
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/date_time/local_time/local_time.hpp> #include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>

14
libi2pd/Config.cpp

@ -62,11 +62,11 @@ namespace config {
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)") ("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)") ("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)") ("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
("ntcp", bool_switch()->default_value(false), "Ignored. Always false") ("ntcp", bool_switch()->default_value(false), "Deprecated option. Always false")
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)") ("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
("ntcpproxy", value<std::string>()->default_value(""), "Ignored") ("ntcpproxy", value<std::string>()->default_value(""), "Deprecated option")
#ifdef _WIN32 #ifdef _WIN32
("svcctl", value<std::string>()->default_value(""), "Ignored") ("svcctl", value<std::string>()->default_value(""), "Deprecated option")
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)") ("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask") ("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask")
#endif #endif
@ -77,9 +77,9 @@ namespace config {
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)") ("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)") ("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabilistic backoff with ntcp sessions (default: use system limit)") ("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Deprecated option")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)") ("limits.ntcphard", value<uint16_t>()->default_value(0), "Deprecated option")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Maximum number of threads used by NTCP DH worker (default: 1)") ("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Deprecated option")
; ;
options_description httpserver("HTTP Server options"); options_description httpserver("HTTP Server options");
@ -281,7 +281,7 @@ namespace config {
options_description meshnets("Meshnet transports options"); options_description meshnets("Meshnet transports options");
meshnets.add_options() meshnets.add_options()
("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (deafult: false)") ("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (default: false)")
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish") ("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
; ;

5
libi2pd/Destination.cpp

@ -509,7 +509,7 @@ namespace client
// schedule verification // schedule verification
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
} }
else else
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msgID); i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msgID);
@ -592,8 +592,7 @@ namespace client
// assume it successive and try to verify // assume it successive and try to verify
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
} }
} }
} }

56
libi2pd/NTCP2.cpp

@ -342,7 +342,7 @@ namespace transport
else else
LogPrint (eLogWarning, "NTCP2: Missing NTCP2 address"); LogPrint (eLogWarning, "NTCP2: Missing NTCP2 address");
} }
m_NextRouterInfoResendTime = i2p::util::GetSecondsSinceEpoch () + NTCP2_ROUTERINFO_RESEND_INTERVAL + m_NextRouterInfoResendTime = i2p::util::GetSecondsSinceEpoch () + NTCP2_ROUTERINFO_RESEND_INTERVAL +
rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD; rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD;
} }
@ -717,7 +717,7 @@ namespace transport
m_Establisher->m_SessionRequestBuffer = new uint8_t[287]; // 287 bytes max for now m_Establisher->m_SessionRequestBuffer = new uint8_t[287]; // 287 bytes max for now
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (), boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (), std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (),
std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
} }
void NTCP2Session::ReceiveLength () void NTCP2Session::ReceiveLength ()
@ -726,7 +726,7 @@ namespace transport
#ifdef __linux__ #ifdef __linux__
const int one = 1; const int one = 1;
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one)); setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif #endif
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_NextReceivedLen, 2), boost::asio::transfer_all (), boost::asio::async_read (m_Socket, boost::asio::buffer(&m_NextReceivedLen, 2), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
} }
@ -780,8 +780,8 @@ namespace transport
if (IsTerminated ()) return; if (IsTerminated ()) return;
#ifdef __linux__ #ifdef __linux__
const int one = 1; const int one = 1;
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one)); setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif #endif
boost::asio::async_read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), boost::asio::async_read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); std::bind(&NTCP2Session::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
} }
@ -1009,11 +1009,11 @@ namespace transport
LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred); LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred);
if (m_LastActivityTimestamp > m_NextRouterInfoResendTime) if (m_LastActivityTimestamp > m_NextRouterInfoResendTime)
{ {
m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL + m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL +
rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD; rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD;
SendRouterInfo (); SendRouterInfo ();
} }
else else
SendQueue (); SendQueue ();
} }
} }
@ -1113,7 +1113,7 @@ namespace transport
SendQueue (); SendQueue ();
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
{ {
LogPrint (eLogWarning, "NTCP2: outgoing messages queue size to ", LogPrint (eLogWarning, "NTCP2: outgoing messages queue size to ",
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
Terminate (); Terminate ();
} }
@ -1279,7 +1279,7 @@ namespace transport
{ {
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); LogPrint (eLogError, "NTCP2: Can't connect to unspecified address");
return; return;
} }
LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ()); LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ());
GetService ().post([this, conn]() GetService ().post([this, conn]()
{ {
@ -1300,25 +1300,25 @@ namespace transport
// bind to local address // bind to local address
std::shared_ptr<boost::asio::ip::tcp::endpoint> localAddress; std::shared_ptr<boost::asio::ip::tcp::endpoint> localAddress;
if (conn->GetRemoteEndpoint ().address ().is_v6 ()) if (conn->GetRemoteEndpoint ().address ().is_v6 ())
{ {
if (i2p::util::net::IsYggdrasilAddress (conn->GetRemoteEndpoint ().address ())) if (i2p::util::net::IsYggdrasilAddress (conn->GetRemoteEndpoint ().address ()))
localAddress = m_YggdrasilAddress; localAddress = m_YggdrasilAddress;
else else
localAddress = m_Address6; localAddress = m_Address6;
conn->GetSocket ().open (boost::asio::ip::tcp::v6 ()); conn->GetSocket ().open (boost::asio::ip::tcp::v6 ());
} }
else else
{ {
localAddress = m_Address4; localAddress = m_Address4;
conn->GetSocket ().open (boost::asio::ip::tcp::v4 ()); conn->GetSocket ().open (boost::asio::ip::tcp::v4 ());
} }
if (localAddress) if (localAddress)
{ {
boost::system::error_code ec; boost::system::error_code ec;
conn->GetSocket ().bind (*localAddress, ec); conn->GetSocket ().bind (*localAddress, ec);
if (ec) if (ec)
LogPrint (eLogError, "NTCP2: can't bind to ", localAddress->address ().to_string (), ": ", ec.message ()); LogPrint (eLogError, "NTCP2: can't bind to ", localAddress->address ().to_string (), ": ", ec.message ());
} }
conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer)); conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer));
} }
else else
@ -1448,8 +1448,8 @@ namespace transport
{ {
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); LogPrint (eLogError, "NTCP2: Can't connect to unspecified address");
return; return;
} }
GetService().post([this, conn]() GetService().post([this, conn]()
{ {
if (this->AddNTCP2Session (conn)) if (this->AddNTCP2Session (conn))
{ {
@ -1546,10 +1546,10 @@ namespace transport
if(ep.address ().is_v6 ()) if(ep.address ().is_v6 ())
req.uri = "[" + ep.address ().to_string() + "]:" + std::to_string(ep.port ()); req.uri = "[" + ep.address ().to_string() + "]:" + std::to_string(ep.port ());
else else
req.uri = ep.address ().to_string() + ":" + std::to_string(ep.port ()); req.uri = ep.address ().to_string() + ":" + std::to_string(ep.port ());
if (!m_ProxyAuthorization.empty ()) if (!m_ProxyAuthorization.empty ())
req.AddHeader("Proxy-Authorization", m_ProxyAuthorization); req.AddHeader("Proxy-Authorization", m_ProxyAuthorization);
boost::asio::streambuf writebuff; boost::asio::streambuf writebuff;
std::ostream out(&writebuff); std::ostream out(&writebuff);
out << req.to_string(); out << req.to_string();
@ -1627,7 +1627,7 @@ namespace transport
sz += 16; sz += 16;
memcpy(buff->data () + 4, addrbytes.data(), 16); memcpy(buff->data () + 4, addrbytes.data(), 16);
} }
else else
{ {
// We mustn't really fall here because all connections are made to IP addresses // We mustn't really fall here because all connections are made to IP addresses
LogPrint(eLogError, "NTCP2: Tried to connect to unexpected address via proxy"); LogPrint(eLogError, "NTCP2: Tried to connect to unexpected address via proxy");
@ -1666,17 +1666,17 @@ namespace transport
} }
void NTCP2Server::SetLocalAddress (const boost::asio::ip::address& localAddress) void NTCP2Server::SetLocalAddress (const boost::asio::ip::address& localAddress)
{ {
auto addr = std::make_shared<boost::asio::ip::tcp::endpoint>(boost::asio::ip::tcp::endpoint(localAddress, 0)); auto addr = std::make_shared<boost::asio::ip::tcp::endpoint>(boost::asio::ip::tcp::endpoint(localAddress, 0));
if (localAddress.is_v6 ()) if (localAddress.is_v6 ())
{ {
if (i2p::util::net::IsYggdrasilAddress (localAddress)) if (i2p::util::net::IsYggdrasilAddress (localAddress))
m_YggdrasilAddress = addr; m_YggdrasilAddress = addr;
else else
m_Address6 = addr; m_Address6 = addr;
} }
else else
m_Address4 = addr; m_Address4 = addr;
} }
} }
} }

154
libi2pd/RouterContext.cpp

@ -28,7 +28,7 @@ namespace i2p
RouterContext::RouterContext (): RouterContext::RouterContext ():
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID) m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID)
{ {
} }
@ -44,12 +44,12 @@ namespace i2p
m_TunnelDecryptor = m_Keys.CreateDecryptor (nullptr); m_TunnelDecryptor = m_Keys.CreateDecryptor (nullptr);
UpdateRouterInfo (); UpdateRouterInfo ();
if (IsECIES ()) if (IsECIES ())
{ {
auto initState = new i2p::crypto::NoiseSymmetricState (); auto initState = new i2p::crypto::NoiseSymmetricState ();
i2p::crypto::InitNoiseNState (*initState, GetIdentity ()->GetEncryptionPublicKey ()); i2p::crypto::InitNoiseNState (*initState, GetIdentity ()->GetEncryptionPublicKey ());
m_InitialNoiseState.reset (initState); m_InitialNoiseState.reset (initState);
m_ECIESSession = std::make_shared<i2p::garlic::RouterIncomingRatchetSession>(*initState); m_ECIESSession = std::make_shared<i2p::garlic::RouterIncomingRatchetSession>(*initState);
} }
} }
void RouterContext::CreateNewRouter () void RouterContext::CreateNewRouter ()
@ -74,21 +74,21 @@ namespace i2p
bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
bool nat; i2p::config::GetOption("nat", nat); bool nat; i2p::config::GetOption("nat", nat);
if ((ntcp2 || ygg) && !m_NTCP2Keys) if ((ntcp2 || ygg) && !m_NTCP2Keys)
NewNTCP2Keys (); NewNTCP2Keys ();
bool ntcp2Published = false; bool ntcp2Published = false;
if (ntcp2) if (ntcp2)
{ {
i2p::config::GetOption("ntcp2.published", ntcp2Published); i2p::config::GetOption("ntcp2.published", ntcp2Published);
if (ntcp2Published) if (ntcp2Published)
{ {
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy); std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
if (!ntcp2proxy.empty ()) ntcp2Published = false; if (!ntcp2proxy.empty ()) ntcp2Published = false;
} }
} }
uint8_t caps = 0, addressCaps = 0; uint8_t caps = 0, addressCaps = 0;
if (ipv4) if (ipv4)
{ {
@ -100,8 +100,8 @@ namespace i2p
// we have no NAT so set external address from local address // we have no NAT so set external address from local address
std::string address4; i2p::config::GetOption("address4", address4); std::string address4; i2p::config::GetOption("address4", address4);
if (!address4.empty ()) host = address4; if (!address4.empty ()) host = address4;
} }
if (ntcp2) if (ntcp2)
{ {
if (ntcp2Published) if (ntcp2Published)
@ -109,26 +109,26 @@ namespace i2p
else // add non-published NTCP2 address else // add non-published NTCP2 address
{ {
addressCaps = i2p::data::RouterInfo::AddressCaps::eV4; addressCaps = i2p::data::RouterInfo::AddressCaps::eV4;
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
} }
} }
if (ssu) if (ssu)
{ {
routerInfo.AddSSUAddress (host.c_str(), port, nullptr); routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
caps |= i2p::data::RouterInfo::eReachable; // R caps |= i2p::data::RouterInfo::eReachable; // R
} }
} }
if (ipv6) if (ipv6)
{ {
std::string host = "::1"; std::string host = "::1";
if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only
i2p::config::GetOption("host", host); i2p::config::GetOption("host", host);
else else
{ {
std::string address6; i2p::config::GetOption("address6", address6); std::string address6; i2p::config::GetOption("address6", address6);
if (!address6.empty ()) host = address6; if (!address6.empty ()) host = address6;
} }
if (ntcp2) if (ntcp2)
{ {
if (ntcp2Published) if (ntcp2Published)
@ -140,29 +140,29 @@ namespace i2p
ntcp2Host = host; ntcp2Host = host;
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port); routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (ntcp2Host), port);
} }
else else
{ {
if (!ipv4) // no other ntcp2 addresses yet if (!ipv4) // no other ntcp2 addresses yet
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6; addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
} }
} }
if (ssu) if (ssu)
{ {
routerInfo.AddSSUAddress (host.c_str(), port, nullptr); routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
caps |= i2p::data::RouterInfo::eReachable; // R caps |= i2p::data::RouterInfo::eReachable; // R
} }
} }
if (ygg) if (ygg)
{ {
auto yggaddr = i2p::util::net::GetYggdrasilAddress (); auto yggaddr = i2p::util::net::GetYggdrasilAddress ();
if (!yggaddr.is_unspecified ()) if (!yggaddr.is_unspecified ())
routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, yggaddr, port); routerInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, yggaddr, port);
} }
if (addressCaps) if (addressCaps)
routerInfo.SetUnreachableAddressesTransportCaps (addressCaps); routerInfo.SetUnreachableAddressesTransportCaps (addressCaps);
routerInfo.SetCaps (caps); // caps + L routerInfo.SetCaps (caps); // caps + L
routerInfo.SetProperty ("netId", std::to_string (m_NetID)); routerInfo.SetProperty ("netId", std::to_string (m_NetID));
routerInfo.SetProperty ("router.version", I2P_VERSION); routerInfo.SetProperty ("router.version", I2P_VERSION);
routerInfo.CreateBuffer (m_Keys); routerInfo.CreateBuffer (m_Keys);
@ -213,7 +213,7 @@ namespace i2p
void RouterContext::SetStatusV6 (RouterStatus status) void RouterContext::SetStatusV6 (RouterStatus status)
{ {
if (status != m_StatusV6) if (status != m_StatusV6)
{ {
m_StatusV6 = status; m_StatusV6 = status;
switch (m_StatusV6) switch (m_StatusV6)
{ {
@ -226,9 +226,9 @@ namespace i2p
default: default:
; ;
} }
} }
} }
void RouterContext::UpdatePort (int port) void RouterContext::UpdatePort (int port)
{ {
bool updated = false; bool updated = false;
@ -250,18 +250,18 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ()) for (auto& address : m_RouterInfo.GetAddresses ())
{ {
if (address->IsNTCP2 () && (address->port != port || address->published != publish)) if (address->IsNTCP2 () && (address->port != port || address->published != publish))
{ {
bool isAddr = v4 && address->IsV4 (); bool isAddr = v4 && address->IsV4 ();
if (!isAddr && (v6 || ygg)) if (!isAddr && (v6 || ygg))
{ {
if (i2p::util::net::IsYggdrasilAddress (address->host)) if (i2p::util::net::IsYggdrasilAddress (address->host))
isAddr = ygg; isAddr = ygg;
else else
isAddr = v6 && address->IsV6 (); isAddr = v6 && address->IsV6 ();
} }
if (isAddr) if (isAddr)
{ {
if (!port && !address->port) if (!port && !address->port)
{ {
// select random port only if address's port is not set // select random port only if address's port is not set
@ -272,7 +272,7 @@ namespace i2p
address->published = publish; address->published = publish;
address->ntcp2->iv = m_NTCP2Keys->iv; address->ntcp2->iv = m_NTCP2Keys->iv;
updated = true; updated = true;
} }
} }
} }
if (updated) if (updated)
@ -310,7 +310,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ()) for (auto& address : m_RouterInfo.GetAddresses ())
{ {
if (address->host != host && address->IsCompatible (host) && if (address->host != host && address->IsCompatible (host) &&
!i2p::util::net::IsYggdrasilAddress (address->host)) !i2p::util::net::IsYggdrasilAddress (address->host))
{ {
address->host = host; address->host = host;
@ -402,7 +402,7 @@ namespace i2p
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break; case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break;
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s
default: default:
limit = 48; type = low; limit = 48; type = low;
} }
/* update caps & flags in RI */ /* update caps & flags in RI */
auto caps = m_RouterInfo.GetCaps (); auto caps = m_RouterInfo.GetCaps ();
@ -416,8 +416,8 @@ namespace i2p
#if (__cplusplus >= 201703L) // C++ 17 or higher #if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]]; [[fallthrough]];
#endif #endif
// no break here, extra + high means 'X' // no break here, extra + high means 'X'
case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break; case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break;
} }
m_RouterInfo.SetCaps (caps); m_RouterInfo.SetCaps (caps);
UpdateRouterInfo (); UpdateRouterInfo ();
@ -467,14 +467,14 @@ namespace i2p
void RouterContext::SetUnreachable (bool v4, bool v6) void RouterContext::SetUnreachable (bool v4, bool v6)
{ {
if (v4 || (v6 && !SupportsV4 ())) if (v4 || (v6 && !SupportsV4 ()))
{ {
// set caps // set caps
uint8_t caps = m_RouterInfo.GetCaps (); uint8_t caps = m_RouterInfo.GetCaps ();
caps &= ~i2p::data::RouterInfo::eReachable; caps &= ~i2p::data::RouterInfo::eReachable;
caps |= i2p::data::RouterInfo::eUnreachable; caps |= i2p::data::RouterInfo::eUnreachable;
caps &= ~i2p::data::RouterInfo::eFloodfill; // can't be floodfill caps &= ~i2p::data::RouterInfo::eFloodfill; // can't be floodfill
m_RouterInfo.SetCaps (caps); m_RouterInfo.SetCaps (caps);
} }
uint16_t port = 0; uint16_t port = 0;
// delete previous introducers // delete previous introducers
auto& addresses = m_RouterInfo.GetAddresses (); auto& addresses = m_RouterInfo.GetAddresses ();
@ -497,7 +497,7 @@ namespace i2p
void RouterContext::SetReachable (bool v4, bool v6) void RouterContext::SetReachable (bool v4, bool v6)
{ {
if (v4 || (v6 && !SupportsV4 ())) if (v4 || (v6 && !SupportsV4 ()))
{ {
// update caps // update caps
uint8_t caps = m_RouterInfo.GetCaps (); uint8_t caps = m_RouterInfo.GetCaps ();
caps &= ~i2p::data::RouterInfo::eUnreachable; caps &= ~i2p::data::RouterInfo::eUnreachable;
@ -505,7 +505,7 @@ namespace i2p
if (m_IsFloodfill) if (m_IsFloodfill)
caps |= i2p::data::RouterInfo::eFloodfill; caps |= i2p::data::RouterInfo::eFloodfill;
m_RouterInfo.SetCaps (caps); m_RouterInfo.SetCaps (caps);
} }
uint16_t port = 0; uint16_t port = 0;
// delete previous introducers // delete previous introducers
auto& addresses = m_RouterInfo.GetAddresses (); auto& addresses = m_RouterInfo.GetAddresses ();
@ -526,7 +526,7 @@ namespace i2p
{ {
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
if (!ntcp2Port) ntcp2Port = port; if (!ntcp2Port) ntcp2Port = port;
PublishNTCP2Address (ntcp2Port, true, v4, v6, false); PublishNTCP2Address (ntcp2Port, true, v4, v6, false);
} }
} }
// update // update
@ -596,7 +596,7 @@ namespace i2p
if (supportsV4) if (supportsV4)
{ {
bool foundSSU = false, foundNTCP2 = false; bool foundSSU = false, foundNTCP2 = false;
std::string host = "127.0.0.1"; std::string host = "127.0.0.1";
uint16_t port = 0; uint16_t port = 0;
auto& addresses = m_RouterInfo.GetAddresses (); auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr: addresses) for (auto& addr: addresses)
@ -626,26 +626,26 @@ namespace i2p
{ {
bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published); bool ntcp2Published; i2p::config::GetOption("ntcp2.published", ntcp2Published);
if (ntcp2Published) if (ntcp2Published)
{ {
uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port); uint16_t ntcp2Port; i2p::config::GetOption ("ntcp2.port", ntcp2Port);
if (!ntcp2Port) ntcp2Port = port; if (!ntcp2Port) ntcp2Port = port;
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (host), ntcp2Port); m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address::from_string (host), ntcp2Port);
} }
else else
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv); m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv);
} }
} }
m_RouterInfo.EnableV4 (); m_RouterInfo.EnableV4 ();
} }
else else
m_RouterInfo.DisableV4 (); m_RouterInfo.DisableV4 ();
UpdateRouterInfo (); UpdateRouterInfo ();
} }
void RouterContext::SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host) void RouterContext::SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host)
{ {
if (supportsmesh) if (supportsmesh)
{ {
m_RouterInfo.EnableMesh (); m_RouterInfo.EnableMesh ();
uint16_t port = 0; uint16_t port = 0;
i2p::config::GetOption ("ntcp2.port", port); i2p::config::GetOption ("ntcp2.port", port);
@ -659,16 +659,16 @@ namespace i2p
{ {
foundMesh = true; foundMesh = true;
break; break;
} }
} }
if (!foundMesh) if (!foundMesh)
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port); m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port);
} }
else else
m_RouterInfo.DisableMesh (); m_RouterInfo.DisableMesh ();
UpdateRouterInfo (); UpdateRouterInfo ();
} }
void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host) void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host)
{ {
bool isYgg = i2p::util::net::IsYggdrasilAddress (host); bool isYgg = i2p::util::net::IsYggdrasilAddress (host);
@ -742,7 +742,7 @@ namespace i2p
// rekey routers with bandwidth = L (or default) this time // rekey routers with bandwidth = L (or default) this time
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (!isFloodfill) rekey = true; if (!isFloodfill) rekey = true;
} }
if (rekey) if (rekey)
{ {
// update keys // update keys
@ -751,7 +751,7 @@ namespace i2p
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519, m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
SaveKeys (); SaveKeys ();
} }
// read NTCP2 keys if available // read NTCP2 keys if available
std::ifstream n2k (i2p::fs::DataDirPath (NTCP2_KEYS), std::ifstream::in | std::ifstream::binary); std::ifstream n2k (i2p::fs::DataDirPath (NTCP2_KEYS), std::ifstream::in | std::ifstream::binary);
if (n2k) if (n2k)
@ -787,8 +787,8 @@ namespace i2p
SetReachable (true, true); // we assume reachable until we discover firewall through peer tests SetReachable (true, true); // we assume reachable until we discover firewall through peer tests
// read NTCP2 // read NTCP2
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
if (ntcp2 || ygg) if (ntcp2 || ygg)
{ {
if (!m_NTCP2Keys) NewNTCP2Keys (); if (!m_NTCP2Keys) NewNTCP2Keys ();
@ -821,15 +821,15 @@ namespace i2p
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len))); i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len)));
} }
bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len) bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len)
{ {
auto msg = CreateI2NPMessage (typeID, payload, len); auto msg = CreateI2NPMessage (typeID, payload, len);
if (!msg) return false; if (!msg) return false;
i2p::HandleI2NPMessage (msg); i2p::HandleI2NPMessage (msg);
return true; return true;
} }
void RouterContext::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg) void RouterContext::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{ {
std::unique_lock<std::mutex> l(m_GarlicMutex); std::unique_lock<std::mutex> l(m_GarlicMutex);
@ -847,8 +847,8 @@ namespace i2p
m_ECIESSession->HandleNextMessage (buf, len); m_ECIESSession->HandleNextMessage (buf, len);
else else
LogPrint (eLogError, "Router: Session is not set for ECIES router"); LogPrint (eLogError, "Router: Session is not set for ECIES router");
} }
else else
i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg); i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg);
} }
@ -857,10 +857,10 @@ namespace i2p
if (i2p::data::netdb.GetPublishReplyToken () == bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET)) if (i2p::data::netdb.GetPublishReplyToken () == bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET))
i2p::data::netdb.PostI2NPMsg (msg); i2p::data::netdb.PostI2NPMsg (msg);
else else
{ {
std::unique_lock<std::mutex> l(m_GarlicMutex); std::unique_lock<std::mutex> l(m_GarlicMutex);
i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg); i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg);
} }
} }
void RouterContext::CleanupDestination () void RouterContext::CleanupDestination ()
@ -886,34 +886,34 @@ namespace i2p
{ {
if (!m_InitialNoiseState) return false; if (!m_InitialNoiseState) return false;
// m_InitialNoiseState is h = SHA256(h || hepk) // m_InitialNoiseState is h = SHA256(h || hepk)
m_CurrentNoiseState.reset (new i2p::crypto::NoiseSymmetricState (*m_InitialNoiseState)); m_CurrentNoiseState.reset (new i2p::crypto::NoiseSymmetricState (*m_InitialNoiseState));
m_CurrentNoiseState->MixHash (encrypted, 32); // h = SHA256(h || sepk) m_CurrentNoiseState->MixHash (encrypted, 32); // h = SHA256(h || sepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
if (!m_TunnelDecryptor->Decrypt (encrypted, sharedSecret, nullptr, false)) if (!m_TunnelDecryptor->Decrypt (encrypted, sharedSecret, nullptr, false))
{ {
LogPrint (eLogWarning, "Router: Incorrect ephemeral public key"); LogPrint (eLogWarning, "Router: Incorrect ephemeral public key");
return false; return false;
} }
m_CurrentNoiseState->MixKey (sharedSecret); m_CurrentNoiseState->MixKey (sharedSecret);
encrypted += 32; encrypted += 32;
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); memset (nonce, 0, 12);
if (!i2p::crypto::AEADChaCha20Poly1305 (encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE, if (!i2p::crypto::AEADChaCha20Poly1305 (encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE,
m_CurrentNoiseState->m_H, 32, m_CurrentNoiseState->m_CK + 32, nonce, data, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE, false)) // decrypt m_CurrentNoiseState->m_H, 32, m_CurrentNoiseState->m_CK + 32, nonce, data, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE, false)) // decrypt
{ {
LogPrint (eLogWarning, "Router: Tunnel record AEAD decryption failed"); LogPrint (eLogWarning, "Router: Tunnel record AEAD decryption failed");
return false; return false;
} }
m_CurrentNoiseState->MixHash (encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 16); // h = SHA256(h || ciphertext) m_CurrentNoiseState->MixHash (encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 16); // h = SHA256(h || ciphertext)
return true; return true;
} }
else else
{ {
BN_CTX * ctx = BN_CTX_new (); BN_CTX * ctx = BN_CTX_new ();
bool success = m_TunnelDecryptor->Decrypt (encrypted, data, ctx, false); bool success = m_TunnelDecryptor->Decrypt (encrypted, data, ctx, false);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return success; return success;
} }
} }
i2p::crypto::X25519Keys& RouterContext::GetStaticKeys () i2p::crypto::X25519Keys& RouterContext::GetStaticKeys ()

98
libi2pd/SSU.cpp

@ -28,7 +28,7 @@ namespace transport
m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6), m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6),
m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port),
m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6), m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6),
m_IntroducersUpdateTimer (m_Service), m_IntroducersUpdateTimerV6 (m_Service), m_IntroducersUpdateTimer (m_Service), m_IntroducersUpdateTimerV6 (m_Service),
m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_Service) m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_Service)
{ {
} }
@ -79,7 +79,7 @@ namespace transport
if (context.SupportsV4 ()) if (context.SupportsV4 ())
{ {
OpenSocket (); OpenSocket ();
m_ReceiversThread = new std::thread (std::bind (&SSUServer::RunReceivers, this)); m_ReceiversThread = new std::thread (std::bind (&SSUServer::RunReceivers, this));
m_ReceiversService.post (std::bind (&SSUServer::Receive, this)); m_ReceiversService.post (std::bind (&SSUServer::Receive, this));
ScheduleTermination (); ScheduleTermination ();
ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers
@ -125,7 +125,7 @@ namespace transport
m_Thread->join (); m_Thread->join ();
delete m_Thread; delete m_Thread;
m_Thread = nullptr; m_Thread = nullptr;
} }
} }
void SSUServer::Run () void SSUServer::Run ()
@ -198,8 +198,8 @@ namespace transport
m_EndpointV6.address (localAddress); m_EndpointV6.address (localAddress);
else if (localAddress.is_v4 ()) else if (localAddress.is_v4 ())
m_Endpoint.address (localAddress); m_Endpoint.address (localAddress);
} }
void SSUServer::AddRelay (uint32_t tag, std::shared_ptr<SSUSession> relay) void SSUServer::AddRelay (uint32_t tag, std::shared_ptr<SSUSession> relay)
{ {
m_Relays[tag] = relay; m_Relays[tag] = relay;
@ -412,7 +412,7 @@ namespace transport
std::shared_ptr<SSUSession> SSUServer::FindSession (const boost::asio::ip::udp::endpoint& e) const std::shared_ptr<SSUSession> SSUServer::FindSession (const boost::asio::ip::udp::endpoint& e) const
{ {
auto& sessions = e.address ().is_v6 () ? m_SessionsV6 : m_Sessions; auto& sessions = e.address ().is_v6 () ? m_SessionsV6 : m_Sessions;
auto it = sessions.find (e); auto it = sessions.find (e);
if (it != sessions.end ()) if (it != sessions.end ())
return it->second; return it->second;
@ -439,7 +439,7 @@ namespace transport
m_Service.post (std::bind (&SSUServer::CreateSessionThroughIntroducer, this, router, address, peerTest)); // always V4 thread m_Service.post (std::bind (&SSUServer::CreateSessionThroughIntroducer, this, router, address, peerTest)); // always V4 thread
else else
{ {
if (address->host.is_unspecified () || !address->port) return false; if (address->host.is_unspecified () || !address->port) return false;
boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port);
m_Service.post (std::bind (&SSUServer::CreateDirectSession, this, router, remoteEndpoint, peerTest)); m_Service.post (std::bind (&SSUServer::CreateDirectSession, this, router, remoteEndpoint, peerTest));
} }
@ -472,15 +472,15 @@ namespace transport
} }
} }
void SSUServer::CreateSessionThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router, void SSUServer::CreateSessionThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest) std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest)
{ {
if (router && address && address->UsesIntroducer ()) if (router && address && address->UsesIntroducer ())
{ {
if (address->IsV4 () && !i2p::context.SupportsV4 ()) return; if (address->IsV4 () && !i2p::context.SupportsV4 ()) return;
if (address->IsV6 () && !i2p::context.SupportsV6 ()) return; if (address->IsV6 () && !i2p::context.SupportsV6 ()) return;
if (!address->host.is_unspecified () && address->port) if (!address->host.is_unspecified () && address->port)
{ {
// we rarely come here // we rarely come here
auto& sessions = address->host.is_v6 () ? m_SessionsV6 : m_Sessions; auto& sessions = address->host.is_v6 () ? m_SessionsV6 : m_Sessions;
boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port); boost::asio::ip::udp::endpoint remoteEndpoint (address->host, address->port);
@ -493,7 +493,7 @@ namespace transport
session->SendPeerTest (); session->SendPeerTest ();
return; return;
} }
} }
// create new session // create new session
int numIntroducers = address->ssu->introducers.size (); int numIntroducers = address->ssu->introducers.size ();
if (numIntroducers > 0) if (numIntroducers > 0)
@ -509,9 +509,9 @@ namespace transport
if (!intr->iPort) continue; // skip invalid introducer if (!intr->iPort) continue; // skip invalid introducer
if (intr->iExp > 0 && ts > intr->iExp) continue; // skip expired introducer if (intr->iExp > 0 && ts > intr->iExp) continue; // skip expired introducer
boost::asio::ip::udp::endpoint ep (intr->iHost, intr->iPort); boost::asio::ip::udp::endpoint ep (intr->iHost, intr->iPort);
if (ep.address ().is_v4 () && address->IsV4 ()) // ipv4 if (ep.address ().is_v4 () && address->IsV4 ()) // ipv4
{ {
if (!introducer) introducer = intr; if (!introducer) introducer = intr;
auto it = m_Sessions.find (ep); auto it = m_Sessions.find (ep);
if (it != m_Sessions.end ()) if (it != m_Sessions.end ())
{ {
@ -519,9 +519,9 @@ namespace transport
break; break;
} }
} }
if (ep.address ().is_v6 () && address->IsV6 ()) // ipv6 if (ep.address ().is_v6 () && address->IsV6 ()) // ipv6
{ {
if (!introducer) introducer = intr; if (!introducer) introducer = intr;
auto it = m_SessionsV6.find (ep); auto it = m_SessionsV6.find (ep);
if (it != m_SessionsV6.end ()) if (it != m_SessionsV6.end ())
{ {
@ -546,7 +546,7 @@ namespace transport
if (introducerEndpoint.address ().is_v4 ()) if (introducerEndpoint.address ().is_v4 ())
m_Sessions[introducerEndpoint] = introducerSession; m_Sessions[introducerEndpoint] = introducerSession;
else if (introducerEndpoint.address ().is_v6 ()) else if (introducerEndpoint.address ().is_v6 ())
m_SessionsV6[introducerEndpoint] = introducerSession; m_SessionsV6[introducerEndpoint] = introducerSession;
} }
if (!address->host.is_unspecified () && address->port) if (!address->host.is_unspecified () && address->port)
{ {
@ -563,7 +563,7 @@ namespace transport
"] through introducer ", introducer->iHost, ":", introducer->iPort); "] through introducer ", introducer->iHost, ":", introducer->iPort);
session->WaitForIntroduction (); session->WaitForIntroduction ();
if ((address->host.is_v4 () && i2p::context.GetStatus () == eRouterStatusFirewalled) || if ((address->host.is_v4 () && i2p::context.GetStatus () == eRouterStatusFirewalled) ||
(address->host.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled)) (address->host.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled))
{ {
uint8_t buf[1]; uint8_t buf[1];
Send (buf, 0, remoteEndpoint); // send HolePunch Send (buf, 0, remoteEndpoint); // send HolePunch
@ -648,23 +648,23 @@ namespace transport
); );
} }
std::list<std::shared_ptr<SSUSession> > SSUServer::FindIntroducers (int maxNumIntroducers, std::list<std::shared_ptr<SSUSession> > SSUServer::FindIntroducers (int maxNumIntroducers,
bool v4, std::set<i2p::data::IdentHash>& excluded) bool v4, std::set<i2p::data::IdentHash>& excluded)
{ {
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
std::list<std::shared_ptr<SSUSession> > ret; std::list<std::shared_ptr<SSUSession> > ret;
const auto& sessions = v4 ? m_Sessions : m_SessionsV6; const auto& sessions = v4 ? m_Sessions : m_SessionsV6;
for (const auto& s : sessions) for (const auto& s : sessions)
{ {
if (s.second->GetRelayTag () && s.second->GetState () == eSessionStateEstablished && if (s.second->GetRelayTag () && s.second->GetState () == eSessionStateEstablished &&
ts < s.second->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION) ts < s.second->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION)
ret.push_back (s.second); ret.push_back (s.second);
else if (s.second->GetRemoteIdentity ()) else if (s.second->GetRemoteIdentity ())
excluded.insert (s.second->GetRemoteIdentity ()->GetIdentHash ()); excluded.insert (s.second->GetRemoteIdentity ()->GetIdentHash ());
} }
if ((int)ret.size () > maxNumIntroducers) if ((int)ret.size () > maxNumIntroducers)
{ {
// shink ret randomly // shink ret randomly
int sz = ret.size () - maxNumIntroducers; int sz = ret.size () - maxNumIntroducers;
for (int i = 0; i < sz; i++) for (int i = 0; i < sz; i++)
{ {
@ -672,8 +672,8 @@ namespace transport
auto it = ret.begin (); auto it = ret.begin ();
std::advance (it, ind); std::advance (it, ind);
ret.erase (it); ret.erase (it);
} }
} }
return ret; return ret;
} }
@ -683,8 +683,8 @@ namespace transport
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL/2)); m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL/2));
m_IntroducersUpdateTimer.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer, m_IntroducersUpdateTimer.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, true)); this, std::placeholders::_1, true));
} }
void SSUServer::ScheduleIntroducersUpdateTimer () void SSUServer::ScheduleIntroducersUpdateTimer ()
{ {
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL));
@ -698,22 +698,22 @@ namespace transport
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL/2)); m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL/2));
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer, m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, false)); this, std::placeholders::_1, false));
} }
void SSUServer::ScheduleIntroducersUpdateTimerV6 () void SSUServer::ScheduleIntroducersUpdateTimerV6 ()
{ {
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL));
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer, m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, false)); this, std::placeholders::_1, false));
} }
void SSUServer::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4) void SSUServer::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
// timeout expired // timeout expired
if (v4) if (v4)
{ {
if (i2p::context.GetStatus () == eRouterStatusTesting) if (i2p::context.GetStatus () == eRouterStatusTesting)
{ {
// we still don't know if we need introducers // we still don't know if we need introducers
@ -721,14 +721,14 @@ namespace transport
return; return;
} }
if (i2p::context.GetStatus () != eRouterStatusFirewalled) if (i2p::context.GetStatus () != eRouterStatusFirewalled)
{ {
// we don't need introducers // we don't need introducers
m_Introducers.clear (); m_Introducers.clear ();
return; return;
} }
// we are firewalled // we are firewalled
if (!i2p::context.IsUnreachable ()) i2p::context.SetUnreachable (true, false); // v4 if (!i2p::context.IsUnreachable ()) i2p::context.SetUnreachable (true, false); // v4
} }
else else
{ {
if (i2p::context.GetStatusV6 () == eRouterStatusTesting) if (i2p::context.GetStatusV6 () == eRouterStatusTesting)
@ -738,17 +738,17 @@ namespace transport
return; return;
} }
if (i2p::context.GetStatusV6 () != eRouterStatusFirewalled) if (i2p::context.GetStatusV6 () != eRouterStatusFirewalled)
{ {
// we don't need introducers // we don't need introducers
m_IntroducersV6.clear (); m_IntroducersV6.clear ();
return; return;
} }
// we are firewalled // we are firewalled
auto addr = i2p::context.GetRouterInfo ().GetSSUV6Address (); auto addr = i2p::context.GetRouterInfo ().GetSSUV6Address ();
if (addr && addr->ssu && addr->ssu->introducers.empty ()) if (addr && addr->ssu && addr->ssu->introducers.empty ())
i2p::context.SetUnreachable (false, true); // v6 i2p::context.SetUnreachable (false, true); // v6
} }
std::list<boost::asio::ip::udp::endpoint> newList; std::list<boost::asio::ip::udp::endpoint> newList;
size_t numIntroducers = 0; size_t numIntroducers = 0;
uint32_t ts = i2p::util::GetSecondsSinceEpoch (); uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
@ -762,7 +762,7 @@ namespace transport
if (ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION) if (ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION)
session->SendKeepAlive (); session->SendKeepAlive ();
if (ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION) if (ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION)
{ {
newList.push_back (it); newList.push_back (it);
numIntroducers++; numIntroducers++;
if (session->GetRemoteIdentity ()) if (session->GetRemoteIdentity ())
@ -787,11 +787,11 @@ namespace transport
auto session = FindSession (it); auto session = FindSession (it);
if (session) if (session)
session->SetCreationTime (session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION); session->SetCreationTime (session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION);
} }
// try again // try again
excluded.clear (); excluded.clear ();
sessions = FindIntroducers (SSU_MAX_NUM_INTRODUCERS, v4, excluded); sessions = FindIntroducers (SSU_MAX_NUM_INTRODUCERS, v4, excluded);
} }
for (const auto& it1: sessions) for (const auto& it1: sessions)
{ {
const auto& ep = it1->GetRemoteEndpoint (); const auto& ep = it1->GetRemoteEndpoint ();
@ -814,27 +814,27 @@ namespace transport
if (introducers.size () < SSU_MAX_NUM_INTRODUCERS) if (introducers.size () < SSU_MAX_NUM_INTRODUCERS)
{ {
for (auto i = introducers.size (); i < SSU_MAX_NUM_INTRODUCERS; i++) for (auto i = introducers.size (); i < SSU_MAX_NUM_INTRODUCERS; i++)
{ {
auto introducer = i2p::data::netdb.GetRandomIntroducer (v4, excluded); auto introducer = i2p::data::netdb.GetRandomIntroducer (v4, excluded);
if (introducer) if (introducer)
{ {
auto address = v4 ? introducer->GetSSUAddress (true) : introducer->GetSSUV6Address (); auto address = v4 ? introducer->GetSSUAddress (true) : introducer->GetSSUV6Address ();
if (address && !address->host.is_unspecified () && address->port) if (address && !address->host.is_unspecified () && address->port)
{ {
boost::asio::ip::udp::endpoint ep (address->host, address->port); boost::asio::ip::udp::endpoint ep (address->host, address->port);
if (std::find (introducers.begin (), introducers.end (), ep) == introducers.end ()) // not connected yet if (std::find (introducers.begin (), introducers.end (), ep) == introducers.end ()) // not connected yet
{ {
CreateDirectSession (introducer, ep, false); CreateDirectSession (introducer, ep, false);
excluded.insert (introducer->GetIdentHash ()); excluded.insert (introducer->GetIdentHash ());
} }
} }
} }
else else
{ {
LogPrint (eLogDebug, "SSU: can't find more introducers"); LogPrint (eLogDebug, "SSU: can't find more introducers");
break; break;
} }
} }
} }
if (v4) if (v4)
ScheduleIntroducersUpdateTimer (); ScheduleIntroducersUpdateTimer ();

2
libi2pd/SSUSession.cpp

@ -383,7 +383,7 @@ namespace transport
{ {
// tell out peer to now assign relay tag // tell out peer to now assign relay tag
flag = SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; flag = SSU_HEADER_EXTENDED_OPTIONS_INCLUDED;
*payload = 2; payload++; // 1 byte length *payload = 2; payload++; // 1 byte length
uint16_t flags = 0; // clear EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG uint16_t flags = 0; // clear EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG
htobe16buf (payload, flags); htobe16buf (payload, flags);
payload += 2; payload += 2;

Loading…
Cancel
Save