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

54
contrib/i2pd.conf

@ -35,14 +35,30 @@ @@ -35,14 +35,30 @@
## Write full CLF-formatted date and time to log (default: write only time)
# 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
## Specify a family, router belongs to (default - none)
# 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
## 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
## Port to listen for connections
@ -55,17 +71,6 @@ ipv4 = true @@ -55,17 +71,6 @@ ipv4 = true
## Enable communication through ipv6
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)
# ssu = true
@ -82,6 +87,7 @@ ipv6 = false @@ -82,6 +87,7 @@ ipv6 = false
# notransit = true
## Router will be floodfill
## Note: that mode uses much more network connections and CPU!
# floodfill = true
[http]
@ -93,7 +99,7 @@ address = 127.0.0.1 @@ -93,7 +99,7 @@ address = 127.0.0.1
port = 7070
## Path to web console, default "/"
# webroot = /
## Uncomment following lines to enable Web Console authentication
## Uncomment following lines to enable Web Console authentication
# auth = true
# user = i2pd
# pass = changeme
@ -170,11 +176,11 @@ enabled = true @@ -170,11 +176,11 @@ enabled = true
# name = I2Pd
[meshnets]
## Enable connectivity over the Yggdrasil network
## Enable connectivity over the Yggdrasil network
# yggdrasil = false
## You can bind address from your Yggdrasil subnet 300::/64
## The address must first be added to the network interface
# yggaddress =
## The address must first be added to the network interface
# yggaddress =
[reseed]
## Options for bootstrapping into I2P network, aka reseeding
@ -207,13 +213,13 @@ verify = true @@ -207,13 +213,13 @@ verify = true
[limits]
## Maximum active transit sessions (default: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
## Maximum size of corefile in Kb (0 - use system limit)
## Maximum size of corefile in Kb (0 - use system limit)
# 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
## Maximum number of ntcp sessions (0 - use system limit)
## Maximum number of ntcp sessions (0 - use system limit)
# ntcphard = 0
[trust]
@ -222,13 +228,13 @@ verify = true @@ -222,13 +228,13 @@ verify = true
## Make direct I2P connections only to routers in specified Family.
# family = MyFamily
## 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
# hidden = true
[exploratory]
## Exploratory tunnels settings with default values
# inbound.length = 2
# inbound.length = 2
# inbound.quantity = 3
# outbound.length = 2
# outbound.quantity = 3
@ -237,7 +243,7 @@ verify = true @@ -237,7 +243,7 @@ verify = true
## Save peer profiles on disk (default: true)
# profiles = true
## Save full addresses on disk (default: true)
# addressbook = true
# addressbook = true
[cpuext]
## Use CPU AES-NI instructions set when work with cryptography when available (default: true)

26
daemon/Daemon.cpp

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

22
daemon/HTTPServer.cpp

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

14
libi2pd/Config.cpp

@ -62,11 +62,11 @@ namespace config { @@ -62,11 +62,11 @@ namespace config {
("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)")
("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)")
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
("ntcpproxy", value<std::string>()->default_value(""), "Deprecated option")
#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)")
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask")
#endif
@ -77,9 +77,9 @@ namespace config { @@ -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.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.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabilistic backoff with ntcp sessions (default: use system limit)")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Maximum number of threads used by NTCP DH worker (default: 1)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Deprecated option")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Deprecated option")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Deprecated option")
;
options_description httpserver("HTTP Server options");
@ -281,7 +281,7 @@ namespace config { @@ -281,7 +281,7 @@ namespace config {
options_description meshnets("Meshnet transports 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")
;

5
libi2pd/Destination.cpp

@ -509,7 +509,7 @@ namespace client @@ -509,7 +509,7 @@ namespace client
// schedule verification
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
shared_from_this (), std::placeholders::_1));
shared_from_this (), std::placeholders::_1));
}
else
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msgID);
@ -592,8 +592,7 @@ namespace client @@ -592,8 +592,7 @@ namespace client
// assume it successive and try to verify
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
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 @@ -342,7 +342,7 @@ namespace transport
else
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;
}
@ -717,7 +717,7 @@ namespace transport @@ -717,7 +717,7 @@ namespace transport
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 (),
std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (),
std::placeholders::_1, std::placeholders::_2));
std::placeholders::_1, std::placeholders::_2));
}
void NTCP2Session::ReceiveLength ()
@ -726,7 +726,7 @@ namespace transport @@ -726,7 +726,7 @@ namespace transport
#ifdef __linux__
const int one = 1;
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 (),
std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
}
@ -780,8 +780,8 @@ namespace transport @@ -780,8 +780,8 @@ namespace transport
if (IsTerminated ()) return;
#ifdef __linux__
const int one = 1;
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif
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));
}
@ -1009,11 +1009,11 @@ namespace transport @@ -1009,11 +1009,11 @@ namespace transport
LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred);
if (m_LastActivityTimestamp > m_NextRouterInfoResendTime)
{
m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL +
m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL +
rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD;
SendRouterInfo ();
}
else
SendRouterInfo ();
}
else
SendQueue ();
}
}
@ -1113,7 +1113,7 @@ namespace transport @@ -1113,7 +1113,7 @@ namespace transport
SendQueue ();
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);
Terminate ();
}
@ -1279,7 +1279,7 @@ namespace transport @@ -1279,7 +1279,7 @@ namespace transport
{
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address");
return;
}
}
LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ());
GetService ().post([this, conn]()
{
@ -1300,25 +1300,25 @@ namespace transport @@ -1300,25 +1300,25 @@ namespace transport
// bind to local address
std::shared_ptr<boost::asio::ip::tcp::endpoint> localAddress;
if (conn->GetRemoteEndpoint ().address ().is_v6 ())
{
{
if (i2p::util::net::IsYggdrasilAddress (conn->GetRemoteEndpoint ().address ()))
localAddress = m_YggdrasilAddress;
else
else
localAddress = m_Address6;
conn->GetSocket ().open (boost::asio::ip::tcp::v6 ());
}
}
else
{
{
localAddress = m_Address4;
conn->GetSocket ().open (boost::asio::ip::tcp::v4 ());
}
}
if (localAddress)
{
boost::system::error_code ec;
conn->GetSocket ().bind (*localAddress, 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));
}
else
@ -1448,8 +1448,8 @@ namespace transport @@ -1448,8 +1448,8 @@ namespace transport
{
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address");
return;
}
GetService().post([this, conn]()
}
GetService().post([this, conn]()
{
if (this->AddNTCP2Session (conn))
{
@ -1546,10 +1546,10 @@ namespace transport @@ -1546,10 +1546,10 @@ namespace transport
if(ep.address ().is_v6 ())
req.uri = "[" + ep.address ().to_string() + "]:" + std::to_string(ep.port ());
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 ())
req.AddHeader("Proxy-Authorization", m_ProxyAuthorization);
boost::asio::streambuf writebuff;
std::ostream out(&writebuff);
out << req.to_string();
@ -1627,7 +1627,7 @@ namespace transport @@ -1627,7 +1627,7 @@ namespace transport
sz += 16;
memcpy(buff->data () + 4, addrbytes.data(), 16);
}
else
else
{
// 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");
@ -1666,17 +1666,17 @@ namespace transport @@ -1666,17 +1666,17 @@ namespace transport
}
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));
if (localAddress.is_v6 ())
{
{
if (i2p::util::net::IsYggdrasilAddress (localAddress))
m_YggdrasilAddress = addr;
else
else
m_Address6 = addr;
}
}
else
m_Address4 = addr;
}
}
}
}

154
libi2pd/RouterContext.cpp

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

98
libi2pd/SSU.cpp

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

2
libi2pd/SSUSession.cpp

@ -383,7 +383,7 @@ namespace transport @@ -383,7 +383,7 @@ namespace transport
{
// tell out peer to now assign relay tag
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
htobe16buf (payload, flags);
payload += 2;

Loading…
Cancel
Save