mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-24 06:17:16 +01:00
commit
4540d22de8
|
@ -248,6 +248,9 @@ namespace http {
|
||||||
case eRouterErrorSymmetricNAT:
|
case eRouterErrorSymmetricNAT:
|
||||||
s << " - " << tr("Symmetric NAT");
|
s << " - " << tr("Symmetric NAT");
|
||||||
break;
|
break;
|
||||||
|
case eRouterErrorNoDescriptors:
|
||||||
|
s << " - " << tr("No Descriptors");
|
||||||
|
break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,43 +302,48 @@ namespace http {
|
||||||
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
|
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
|
||||||
s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n";
|
s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n";
|
||||||
}
|
}
|
||||||
if (includeHiddenContent) {
|
if (includeHiddenContent)
|
||||||
|
{
|
||||||
s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
||||||
if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
|
if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
|
||||||
s << "<b>" << tr("Router Family") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
s << "<b>" << tr("Router Family") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
||||||
s << "<b>" << tr("Router Caps") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
|
s << "<b>" << tr("Router Caps") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
|
||||||
s << "<b>" << tr("Version") << ":</b> " VERSION "<br>\r\n";
|
s << "<b>" << tr("Version") << ":</b> " VERSION "<br>\r\n";
|
||||||
s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
|
s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
|
||||||
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
auto addresses = i2p::context.GetRouterInfo().GetAddresses ();
|
||||||
|
if (addresses)
|
||||||
{
|
{
|
||||||
s << "<tr>\r\n<td>";
|
for (const auto& address : *addresses)
|
||||||
switch (address->transportStyle)
|
|
||||||
{
|
{
|
||||||
case i2p::data::RouterInfo::eTransportNTCP2:
|
s << "<tr>\r\n<td>";
|
||||||
s << "NTCP2";
|
switch (address->transportStyle)
|
||||||
break;
|
{
|
||||||
case i2p::data::RouterInfo::eTransportSSU2:
|
case i2p::data::RouterInfo::eTransportNTCP2:
|
||||||
s << "SSU2";
|
s << "NTCP2";
|
||||||
break;
|
break;
|
||||||
default:
|
case i2p::data::RouterInfo::eTransportSSU2:
|
||||||
s << tr("Unknown");
|
s << "SSU2";
|
||||||
}
|
break;
|
||||||
if (address->IsV6 ())
|
default:
|
||||||
{
|
s << tr("Unknown");
|
||||||
if (address->IsV4 ()) s << "v4";
|
}
|
||||||
s << "v6";
|
if (address->IsV6 ())
|
||||||
}
|
{
|
||||||
s << "</td>\r\n";
|
if (address->IsV4 ()) s << "v4";
|
||||||
if (address->published)
|
s << "v6";
|
||||||
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
s << "<td>" << tr("supported");
|
|
||||||
if (address->port)
|
|
||||||
s << " :" << address->port;
|
|
||||||
s << "</td>\r\n";
|
s << "</td>\r\n";
|
||||||
|
if (address->published)
|
||||||
|
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s << "<td>" << tr("supported");
|
||||||
|
if (address->port)
|
||||||
|
s << " :" << address->port;
|
||||||
|
s << "</td>\r\n";
|
||||||
|
}
|
||||||
|
s << "</tr>\r\n";
|
||||||
}
|
}
|
||||||
s << "</tr>\r\n";
|
|
||||||
}
|
}
|
||||||
s << "</tbody></table>\r\n";
|
s << "</tbody></table>\r\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,8 +159,9 @@ namespace transport
|
||||||
|
|
||||||
void UPnP::PortMapping ()
|
void UPnP::PortMapping ()
|
||||||
{
|
{
|
||||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
auto a = context.GetRouterInfo().GetAddresses();
|
||||||
for (const auto& address : a)
|
if (!a) return;
|
||||||
|
for (const auto& address : *a)
|
||||||
{
|
{
|
||||||
if (!address->host.is_v6 () && address->port)
|
if (!address->host.is_v6 () && address->port)
|
||||||
TryPortMapping (address);
|
TryPortMapping (address);
|
||||||
|
@ -210,8 +211,9 @@ namespace transport
|
||||||
|
|
||||||
void UPnP::CloseMapping ()
|
void UPnP::CloseMapping ()
|
||||||
{
|
{
|
||||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
auto a = context.GetRouterInfo().GetAddresses();
|
||||||
for (const auto& address : a)
|
if (!a) return;
|
||||||
|
for (const auto& address : *a)
|
||||||
{
|
{
|
||||||
if (!address->host.is_v6 () && address->port)
|
if (!address->host.is_v6 () && address->port)
|
||||||
CloseMapping (address);
|
CloseMapping (address);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -57,7 +57,8 @@ namespace data
|
||||||
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END)
|
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END)
|
||||||
return outLen - m_Inflator.avail_out;
|
return outLen - m_Inflator.avail_out;
|
||||||
// else
|
// else
|
||||||
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
if (err)
|
||||||
|
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,8 @@ namespace data
|
||||||
return outLen - m_Deflator.avail_out;
|
return outLen - m_Deflator.avail_out;
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
if (err)
|
||||||
|
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +160,8 @@ namespace data
|
||||||
offset = outLen - m_Deflator.avail_out;
|
offset = outLen - m_Deflator.avail_out;
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
if (err)
|
||||||
|
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1210,8 +1210,9 @@ namespace transport
|
||||||
else
|
else
|
||||||
LogPrint(eLogInfo, "NTCP2: Proxy is not used");
|
LogPrint(eLogInfo, "NTCP2: Proxy is not used");
|
||||||
// start acceptors
|
// start acceptors
|
||||||
auto& addresses = context.GetRouterInfo ().GetAddresses ();
|
auto addresses = context.GetRouterInfo ().GetAddresses ();
|
||||||
for (const auto& address: addresses)
|
if (!addresses) return;
|
||||||
|
for (const auto& address: *addresses)
|
||||||
{
|
{
|
||||||
if (!address) continue;
|
if (!address) continue;
|
||||||
if (address->IsPublishedNTCP2 () && address->port)
|
if (address->IsPublishedNTCP2 () && address->port)
|
||||||
|
@ -1424,7 +1425,14 @@ namespace transport
|
||||||
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
|
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
LogPrint (eLogError, "NTCP2: Accept error ", error.message ());
|
LogPrint (eLogError, "NTCP2: Accept error ", error.message ());
|
||||||
|
if (error == boost::asio::error::no_descriptors)
|
||||||
|
{
|
||||||
|
i2p::context.SetError (eRouterErrorNoDescriptors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (error != boost::asio::error::operation_aborted)
|
if (error != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
|
@ -1456,6 +1464,15 @@ namespace transport
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
|
LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "NTCP2: Accept ipv6 error ", error.message ());
|
||||||
|
if (error == boost::asio::error::no_descriptors)
|
||||||
|
{
|
||||||
|
i2p::context.SetErrorV6 (eRouterErrorNoDescriptors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (error != boost::asio::error::operation_aborted)
|
if (error != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
|
@ -1500,8 +1517,24 @@ namespace transport
|
||||||
else
|
else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduleTermination ();
|
ScheduleTermination ();
|
||||||
|
|
||||||
|
// try to restart acceptors if no description
|
||||||
|
// we do it after timer to let timer take descriptor first
|
||||||
|
if (i2p::context.GetError () == eRouterErrorNoDescriptors)
|
||||||
|
{
|
||||||
|
i2p::context.SetError (eRouterErrorNone);
|
||||||
|
auto conn = std::make_shared<NTCP2Session> (*this);
|
||||||
|
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this,
|
||||||
|
conn, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
if (i2p::context.GetErrorV6 () == eRouterErrorNoDescriptors)
|
||||||
|
{
|
||||||
|
i2p::context.SetErrorV6 (eRouterErrorNone);
|
||||||
|
auto conn = std::make_shared<NTCP2Session> (*this);
|
||||||
|
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this,
|
||||||
|
conn, std::placeholders::_1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -603,6 +603,7 @@ namespace data
|
||||||
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
|
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
|
||||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||||
auto uptime = i2p::context.GetUptime ();
|
auto uptime = i2p::context.GetUptime ();
|
||||||
|
bool isLowRate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE;
|
||||||
// routers don't expire if less than 90 or uptime is less than 1 hour
|
// routers don't expire if less than 90 or uptime is less than 1 hour
|
||||||
bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
|
bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
|
||||||
if (checkForExpiration && uptime > 3600) // 1 hour
|
if (checkForExpiration && uptime > 3600) // 1 hour
|
||||||
|
@ -624,7 +625,7 @@ namespace data
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// make router reachable back if too few routers or floodfills
|
// make router reachable back if too few routers or floodfills
|
||||||
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS ||
|
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || isLowRate ||
|
||||||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
|
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
|
||||||
it.second->SetUnreachable (false);
|
it.second->SetUnreachable (false);
|
||||||
// find & mark expired routers
|
// find & mark expired routers
|
||||||
|
@ -650,6 +651,7 @@ namespace data
|
||||||
|
|
||||||
m_RouterInfoBuffersPool.CleanUpMt ();
|
m_RouterInfoBuffersPool.CleanUpMt ();
|
||||||
m_RouterInfoAddressesPool.CleanUpMt ();
|
m_RouterInfoAddressesPool.CleanUpMt ();
|
||||||
|
m_RouterInfoAddressVectorsPool.CleanUpMt ();
|
||||||
|
|
||||||
if (updatedCount > 0)
|
if (updatedCount > 0)
|
||||||
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
|
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace data
|
||||||
{
|
{
|
||||||
const int NETDB_MIN_ROUTERS = 90;
|
const int NETDB_MIN_ROUTERS = 90;
|
||||||
const int NETDB_MIN_FLOODFILLS = 5;
|
const int NETDB_MIN_FLOODFILLS = 5;
|
||||||
|
const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents
|
||||||
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
|
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
|
||||||
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
|
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
|
||||||
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
|
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
|
||||||
|
@ -124,6 +125,13 @@ namespace data
|
||||||
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
|
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
|
||||||
void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r);
|
void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r);
|
||||||
std::shared_ptr<RouterInfo::Address> NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); };
|
std::shared_ptr<RouterInfo::Address> NewRouterInfoAddress () { return m_RouterInfoAddressesPool.AcquireSharedMt (); };
|
||||||
|
boost::shared_ptr<RouterInfo::Addresses> NewRouterInfoAddresses ()
|
||||||
|
{
|
||||||
|
return boost::shared_ptr<RouterInfo::Addresses>(m_RouterInfoAddressVectorsPool.AcquireMt (),
|
||||||
|
std::bind <void (i2p::util::MemoryPoolMt<RouterInfo::Addresses>::*)(RouterInfo::Addresses *)>
|
||||||
|
(&i2p::util::MemoryPoolMt<RouterInfo::Addresses>::ReleaseMt,
|
||||||
|
&m_RouterInfoAddressVectorsPool, std::placeholders::_1));
|
||||||
|
};
|
||||||
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };
|
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };
|
||||||
|
|
||||||
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
|
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
|
||||||
|
@ -182,6 +190,7 @@ namespace data
|
||||||
|
|
||||||
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
|
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
|
||||||
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;
|
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;
|
||||||
|
i2p::util::MemoryPoolMt<RouterInfo::Addresses> m_RouterInfoAddressVectorsPool;
|
||||||
i2p::util::MemoryPoolMt<Lease> m_LeasesPool;
|
i2p::util::MemoryPoolMt<Lease> m_LeasesPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -267,8 +267,10 @@ namespace i2p
|
||||||
|
|
||||||
void RouterContext::UpdatePort (int port)
|
void RouterContext::UpdatePort (int port)
|
||||||
{
|
{
|
||||||
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
for (auto& address : *addresses)
|
||||||
{
|
{
|
||||||
if (address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
|
if (address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
|
||||||
{
|
{
|
||||||
|
@ -283,8 +285,10 @@ namespace i2p
|
||||||
void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg)
|
void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4, bool v6, bool ygg)
|
||||||
{
|
{
|
||||||
if (!m_NTCP2Keys) return;
|
if (!m_NTCP2Keys) return;
|
||||||
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
for (auto& address : *addresses)
|
||||||
{
|
{
|
||||||
if (address->IsNTCP2 () && (address->port != port || address->published != publish))
|
if (address->IsNTCP2 () && (address->port != port || address->published != publish))
|
||||||
{
|
{
|
||||||
|
@ -312,9 +316,10 @@ namespace i2p
|
||||||
|
|
||||||
void RouterContext::UpdateNTCP2Address (bool enable)
|
void RouterContext::UpdateNTCP2Address (bool enable)
|
||||||
{
|
{
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
bool found = false, updated = false;
|
bool found = false, updated = false;
|
||||||
for (auto it = addresses.begin (); it != addresses.end ();)
|
for (auto it = addresses->begin (); it != addresses->end ();)
|
||||||
{
|
{
|
||||||
if ((*it)->IsNTCP2 ())
|
if ((*it)->IsNTCP2 ())
|
||||||
{
|
{
|
||||||
|
@ -326,7 +331,7 @@ namespace i2p
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
it = addresses.erase (it);
|
it = addresses->erase (it);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -344,10 +349,12 @@ namespace i2p
|
||||||
void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6)
|
void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6)
|
||||||
{
|
{
|
||||||
if (!m_SSU2Keys) return;
|
if (!m_SSU2Keys) return;
|
||||||
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
int newPort = 0;
|
int newPort = 0;
|
||||||
if (!port)
|
if (!port)
|
||||||
{
|
{
|
||||||
for (const auto& address : m_RouterInfo.GetAddresses ())
|
for (const auto& address : *addresses)
|
||||||
if (address->port)
|
if (address->port)
|
||||||
{
|
{
|
||||||
newPort = address->port;
|
newPort = address->port;
|
||||||
|
@ -356,7 +363,7 @@ namespace i2p
|
||||||
if (!newPort) newPort = SelectRandomPort ();
|
if (!newPort) newPort = SelectRandomPort ();
|
||||||
}
|
}
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
for (auto& address : *addresses)
|
||||||
{
|
{
|
||||||
if (address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
|
if (address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
|
||||||
((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
|
((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
|
||||||
|
@ -377,9 +384,10 @@ namespace i2p
|
||||||
|
|
||||||
void RouterContext::UpdateSSU2Address (bool enable)
|
void RouterContext::UpdateSSU2Address (bool enable)
|
||||||
{
|
{
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
bool found = false, updated = false;
|
bool found = false, updated = false;
|
||||||
for (auto it = addresses.begin (); it != addresses.end ();)
|
for (auto it = addresses->begin (); it != addresses->end ();)
|
||||||
{
|
{
|
||||||
if ((*it)->IsSSU2 ())
|
if ((*it)->IsSSU2 ())
|
||||||
{
|
{
|
||||||
|
@ -391,7 +399,7 @@ namespace i2p
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
it = addresses.erase (it);
|
it = addresses->erase (it);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -422,8 +430,10 @@ namespace i2p
|
||||||
|
|
||||||
void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
|
void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
|
||||||
{
|
{
|
||||||
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
for (auto& address : m_RouterInfo.GetAddresses ())
|
for (auto& address : *addresses)
|
||||||
{
|
{
|
||||||
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))
|
||||||
|
@ -472,9 +482,10 @@ namespace i2p
|
||||||
|
|
||||||
void RouterContext::ClearSSU2Introducers (bool v4)
|
void RouterContext::ClearSSU2Introducers (bool v4)
|
||||||
{
|
{
|
||||||
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
for (auto& addr : *addresses)
|
||||||
for (auto& addr : addresses)
|
|
||||||
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) &&
|
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) &&
|
||||||
addr->ssu && !addr->ssu->introducers.empty ())
|
addr->ssu && !addr->ssu->introducers.empty ())
|
||||||
{
|
{
|
||||||
|
@ -597,15 +608,18 @@ namespace i2p
|
||||||
}
|
}
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
// delete previous introducers
|
// delete previous introducers
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr : addresses)
|
if (addresses)
|
||||||
if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
{
|
||||||
{
|
for (auto& addr : *addresses)
|
||||||
addr->published = false;
|
if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||||
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
|
{
|
||||||
addr->ssu->introducers.clear ();
|
addr->published = false;
|
||||||
port = addr->port;
|
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
|
||||||
}
|
addr->ssu->introducers.clear ();
|
||||||
|
port = addr->port;
|
||||||
|
}
|
||||||
|
}
|
||||||
// unpublish NTCP2 addreeses
|
// unpublish NTCP2 addreeses
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
|
@ -630,15 +644,18 @@ namespace i2p
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
// delete previous introducers
|
// delete previous introducers
|
||||||
bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published);
|
bool isSSU2Published; i2p::config::GetOption ("ssu2.published", isSSU2Published);
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr : addresses)
|
if (addresses)
|
||||||
if (addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
{
|
||||||
{
|
for (auto& addr : *addresses)
|
||||||
addr->published = true;
|
if (addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
|
||||||
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
|
{
|
||||||
addr->ssu->introducers.clear ();
|
addr->published = true;
|
||||||
if (addr->port) port = addr->port;
|
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
|
||||||
}
|
addr->ssu->introducers.clear ();
|
||||||
|
if (addr->port) port = addr->port;
|
||||||
|
}
|
||||||
|
}
|
||||||
// publish NTCP2
|
// publish NTCP2
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
|
@ -663,23 +680,26 @@ namespace i2p
|
||||||
// insert v6 addresses if necessary
|
// insert v6 addresses if necessary
|
||||||
bool foundNTCP2 = false, foundSSU2 = false;
|
bool foundNTCP2 = false, foundSSU2 = false;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr: addresses)
|
if (addresses)
|
||||||
{
|
{
|
||||||
if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
|
for (auto& addr: *addresses)
|
||||||
{
|
{
|
||||||
switch (addr->transportStyle)
|
if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||||
{
|
{
|
||||||
case i2p::data::RouterInfo::eTransportNTCP2:
|
switch (addr->transportStyle)
|
||||||
foundNTCP2 = true;
|
{
|
||||||
break;
|
case i2p::data::RouterInfo::eTransportNTCP2:
|
||||||
case i2p::data::RouterInfo::eTransportSSU2:
|
foundNTCP2 = true;
|
||||||
foundSSU2 = true;
|
break;
|
||||||
break;
|
case i2p::data::RouterInfo::eTransportSSU2:
|
||||||
default: ;
|
foundSSU2 = true;
|
||||||
|
break;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
port = addr->port;
|
||||||
}
|
}
|
||||||
port = addr->port;
|
|
||||||
}
|
}
|
||||||
if (!port)
|
if (!port)
|
||||||
{
|
{
|
||||||
|
@ -743,23 +763,26 @@ namespace i2p
|
||||||
bool foundNTCP2 = false, foundSSU2 = false;
|
bool foundNTCP2 = false, foundSSU2 = 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)
|
if (addresses)
|
||||||
{
|
{
|
||||||
if (addr->IsV4 ())
|
for (auto& addr: *addresses)
|
||||||
{
|
{
|
||||||
switch (addr->transportStyle)
|
if (addr->IsV4 ())
|
||||||
{
|
{
|
||||||
case i2p::data::RouterInfo::eTransportNTCP2:
|
switch (addr->transportStyle)
|
||||||
foundNTCP2 = true;
|
{
|
||||||
break;
|
case i2p::data::RouterInfo::eTransportNTCP2:
|
||||||
case i2p::data::RouterInfo::eTransportSSU2:
|
foundNTCP2 = true;
|
||||||
foundSSU2 = true;
|
break;
|
||||||
break;
|
case i2p::data::RouterInfo::eTransportSSU2:
|
||||||
default: ;
|
foundSSU2 = true;
|
||||||
|
break;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (addr->port) port = addr->port;
|
||||||
}
|
}
|
||||||
if (addr->port) port = addr->port;
|
|
||||||
}
|
}
|
||||||
if (!port)
|
if (!port)
|
||||||
{
|
{
|
||||||
|
@ -816,14 +839,17 @@ namespace i2p
|
||||||
i2p::config::GetOption ("ntcp2.port", port);
|
i2p::config::GetOption ("ntcp2.port", port);
|
||||||
if (!port) i2p::config::GetOption("port", port);
|
if (!port) i2p::config::GetOption("port", port);
|
||||||
bool foundMesh = false;
|
bool foundMesh = false;
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr: addresses)
|
if (addresses)
|
||||||
{
|
{
|
||||||
if (!port) port = addr->port;
|
for (auto& addr: *addresses)
|
||||||
if (i2p::util::net::IsYggdrasilAddress (addr->host))
|
|
||||||
{
|
{
|
||||||
foundMesh = true;
|
if (!port) port = addr->port;
|
||||||
break;
|
if (i2p::util::net::IsYggdrasilAddress (addr->host))
|
||||||
|
{
|
||||||
|
foundMesh = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!foundMesh)
|
if (!foundMesh)
|
||||||
|
@ -837,8 +863,9 @@ namespace i2p
|
||||||
void RouterContext::SetMTU (int mtu, bool v4)
|
void RouterContext::SetMTU (int mtu, bool v4)
|
||||||
{
|
{
|
||||||
if (mtu < 1280 || mtu > 1500) return;
|
if (mtu < 1280 || mtu > 1500) return;
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr: addresses)
|
if (!addresses) return;
|
||||||
|
for (auto& addr: *addresses)
|
||||||
{
|
{
|
||||||
if (addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
|
if (addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
|
||||||
{
|
{
|
||||||
|
@ -852,8 +879,9 @@ namespace i2p
|
||||||
{
|
{
|
||||||
bool isYgg = i2p::util::net::IsYggdrasilAddress (host);
|
bool isYgg = i2p::util::net::IsYggdrasilAddress (host);
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
auto& addresses = m_RouterInfo.GetAddresses ();
|
auto addresses = m_RouterInfo.GetAddresses ();
|
||||||
for (auto& addr: addresses)
|
if (!addresses) return;
|
||||||
|
for (auto& addr: *addresses)
|
||||||
{
|
{
|
||||||
if (addr->IsPublishedNTCP2 ())
|
if (addr->IsPublishedNTCP2 ())
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,8 @@ namespace garlic
|
||||||
eRouterErrorNone = 0,
|
eRouterErrorNone = 0,
|
||||||
eRouterErrorClockSkew = 1,
|
eRouterErrorClockSkew = 1,
|
||||||
eRouterErrorOffline = 2,
|
eRouterErrorOffline = 2,
|
||||||
eRouterErrorSymmetricNAT = 3
|
eRouterErrorSymmetricNAT = 3,
|
||||||
|
eRouterErrorNoDescriptors = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
class RouterContext: public i2p::garlic::GarlicDestination
|
class RouterContext: public i2p::garlic::GarlicDestination
|
||||||
|
|
|
@ -206,9 +206,10 @@ namespace data
|
||||||
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp));
|
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp));
|
||||||
m_Timestamp = be64toh (m_Timestamp);
|
m_Timestamp = be64toh (m_Timestamp);
|
||||||
// read addresses
|
// read addresses
|
||||||
if (!m_NewAddresses) m_NewAddresses = boost::make_shared<Addresses>();
|
auto addresses = netdb.NewRouterInfoAddresses ();
|
||||||
uint8_t numAddresses;
|
uint8_t numAddresses;
|
||||||
s.read ((char *)&numAddresses, sizeof (numAddresses));
|
s.read ((char *)&numAddresses, sizeof (numAddresses));
|
||||||
|
addresses->reserve (numAddresses);
|
||||||
for (int i = 0; i < numAddresses; i++)
|
for (int i = 0; i < numAddresses; i++)
|
||||||
{
|
{
|
||||||
uint8_t supportedTransports = 0;
|
uint8_t supportedTransports = 0;
|
||||||
|
@ -417,19 +418,16 @@ namespace data
|
||||||
if (supportedTransports)
|
if (supportedTransports)
|
||||||
{
|
{
|
||||||
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates
|
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates
|
||||||
m_NewAddresses->push_back(address);
|
addresses->push_back(address);
|
||||||
m_SupportedTransports |= supportedTransports;
|
m_SupportedTransports |= supportedTransports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update addresses
|
// update addresses
|
||||||
auto prev = m_Addresses;
|
|
||||||
#if (BOOST_VERSION >= 105300)
|
#if (BOOST_VERSION >= 105300)
|
||||||
boost::atomic_store (&m_Addresses, m_NewAddresses);
|
boost::atomic_store (&m_Addresses, addresses);
|
||||||
#else
|
#else
|
||||||
m_Addresses = m_NewAddresses; // race condition
|
m_Addresses = addresses; // race condition
|
||||||
#endif
|
#endif
|
||||||
if (prev) prev->clear ();
|
|
||||||
m_NewAddresses = prev;
|
|
||||||
// read peers
|
// read peers
|
||||||
uint8_t numPeers;
|
uint8_t numPeers;
|
||||||
s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return;
|
s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return;
|
||||||
|
@ -826,6 +824,15 @@ namespace data
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<RouterInfo::Addresses> RouterInfo::GetAddresses () const
|
||||||
|
{
|
||||||
|
#if (BOOST_VERSION >= 105300)
|
||||||
|
return boost::atomic_load (&m_Addresses);
|
||||||
|
#else
|
||||||
|
return m_Addresses;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Filter>
|
template<typename Filter>
|
||||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
|
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
|
||||||
{
|
{
|
||||||
|
@ -1048,14 +1055,15 @@ namespace data
|
||||||
|
|
||||||
void LocalRouterInfo::WriteToStream (std::ostream& s) const
|
void LocalRouterInfo::WriteToStream (std::ostream& s) const
|
||||||
{
|
{
|
||||||
|
auto addresses = GetAddresses ();
|
||||||
|
if (!addresses) return;
|
||||||
|
|
||||||
uint64_t ts = htobe64 (GetTimestamp ());
|
uint64_t ts = htobe64 (GetTimestamp ());
|
||||||
s.write ((const char *)&ts, sizeof (ts));
|
s.write ((const char *)&ts, sizeof (ts));
|
||||||
|
|
||||||
// addresses
|
// addresses
|
||||||
const Addresses& addresses = GetAddresses ();
|
uint8_t numAddresses = addresses->size ();
|
||||||
uint8_t numAddresses = addresses.size ();
|
|
||||||
s.write ((char *)&numAddresses, sizeof (numAddresses));
|
s.write ((char *)&numAddresses, sizeof (numAddresses));
|
||||||
for (const auto& addr_ptr : addresses)
|
for (const auto& addr_ptr : *addresses)
|
||||||
{
|
{
|
||||||
const Address& address = *addr_ptr;
|
const Address& address = *addr_ptr;
|
||||||
// calculate cost
|
// calculate cost
|
||||||
|
@ -1257,7 +1265,9 @@ namespace data
|
||||||
|
|
||||||
bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4)
|
bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4)
|
||||||
{
|
{
|
||||||
for (auto& addr : GetAddresses ())
|
auto addresses = GetAddresses ();
|
||||||
|
if (!addresses) return false;
|
||||||
|
for (auto& addr : *addresses)
|
||||||
{
|
{
|
||||||
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
|
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
|
||||||
{
|
{
|
||||||
|
@ -1273,7 +1283,9 @@ namespace data
|
||||||
|
|
||||||
bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4)
|
bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4)
|
||||||
{
|
{
|
||||||
for (auto& addr: GetAddresses ())
|
auto addresses = GetAddresses ();
|
||||||
|
if (!addresses) return false;
|
||||||
|
for (auto& addr: *addresses)
|
||||||
{
|
{
|
||||||
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
|
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
|
||||||
{
|
{
|
||||||
|
|
|
@ -176,7 +176,7 @@ namespace data
|
||||||
int GetVersion () const { return m_Version; };
|
int GetVersion () const { return m_Version; };
|
||||||
virtual void SetProperty (const std::string& key, const std::string& value) {};
|
virtual void SetProperty (const std::string& key, const std::string& value) {};
|
||||||
virtual void ClearProperties () {};
|
virtual void ClearProperties () {};
|
||||||
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
boost::shared_ptr<Addresses> GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr
|
||||||
std::shared_ptr<const Address> GetNTCP2AddressWithStaticKey (const uint8_t * key) const;
|
std::shared_ptr<const Address> GetNTCP2AddressWithStaticKey (const uint8_t * key) const;
|
||||||
std::shared_ptr<const Address> GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const;
|
std::shared_ptr<const Address> GetSSU2AddressWithStaticKey (const uint8_t * key, bool isV6) const;
|
||||||
std::shared_ptr<const Address> GetPublishedNTCP2V4Address () const;
|
std::shared_ptr<const Address> GetPublishedNTCP2V4Address () const;
|
||||||
|
@ -258,7 +258,6 @@ namespace data
|
||||||
void UpdateBuffer (const uint8_t * buf, size_t len);
|
void UpdateBuffer (const uint8_t * buf, size_t len);
|
||||||
void SetBufferLen (size_t len) { m_BufferLen = len; };
|
void SetBufferLen (size_t len) { m_BufferLen = len; };
|
||||||
void RefreshTimestamp ();
|
void RefreshTimestamp ();
|
||||||
const Addresses& GetAddresses () const { return *m_Addresses; };
|
|
||||||
CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; };
|
CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; };
|
||||||
void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; };
|
void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; };
|
||||||
|
|
||||||
|
@ -282,7 +281,7 @@ namespace data
|
||||||
std::shared_ptr<Buffer> m_Buffer;
|
std::shared_ptr<Buffer> m_Buffer;
|
||||||
size_t m_BufferLen;
|
size_t m_BufferLen;
|
||||||
uint64_t m_Timestamp;
|
uint64_t m_Timestamp;
|
||||||
boost::shared_ptr<Addresses> m_Addresses, m_NewAddresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9
|
boost::shared_ptr<Addresses> m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9
|
||||||
bool m_IsUpdated, m_IsUnreachable;
|
bool m_IsUpdated, m_IsUnreachable;
|
||||||
CompatibleTransports m_SupportedTransports, m_ReachableTransports;
|
CompatibleTransports m_SupportedTransports, m_ReachableTransports;
|
||||||
uint8_t m_Caps;
|
uint8_t m_Caps;
|
||||||
|
|
|
@ -36,8 +36,9 @@ namespace transport
|
||||||
i2p::config::GetOption ("ssu2.published", m_IsPublished);
|
i2p::config::GetOption ("ssu2.published", m_IsPublished);
|
||||||
i2p::config::GetOption("nettime.frompeers", m_IsSyncClockFromPeers);
|
i2p::config::GetOption("nettime.frompeers", m_IsSyncClockFromPeers);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
auto& addresses = i2p::context.GetRouterInfo ().GetAddresses ();
|
auto addresses = i2p::context.GetRouterInfo ().GetAddresses ();
|
||||||
for (const auto& address: addresses)
|
if (!addresses) return;
|
||||||
|
for (const auto& address: *addresses)
|
||||||
{
|
{
|
||||||
if (!address) continue;
|
if (!address) continue;
|
||||||
if (address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
|
if (address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
|
||||||
|
@ -368,6 +369,7 @@ namespace transport
|
||||||
bool SSU2Server::AddPendingOutgoingSession (std::shared_ptr<SSU2Session> session)
|
bool SSU2Server::AddPendingOutgoingSession (std::shared_ptr<SSU2Session> session)
|
||||||
{
|
{
|
||||||
if (!session) return false;
|
if (!session) return false;
|
||||||
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex);
|
||||||
return m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session).second;
|
return m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,6 +383,7 @@ namespace transport
|
||||||
|
|
||||||
std::shared_ptr<SSU2Session> SSU2Server::FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const
|
std::shared_ptr<SSU2Session> SSU2Server::FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const
|
||||||
{
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex);
|
||||||
auto it = m_PendingOutgoingSessions.find (ep);
|
auto it = m_PendingOutgoingSessions.find (ep);
|
||||||
if (it != m_PendingOutgoingSessions.end ())
|
if (it != m_PendingOutgoingSessions.end ())
|
||||||
return it->second;
|
return it->second;
|
||||||
|
@ -389,6 +392,7 @@ namespace transport
|
||||||
|
|
||||||
void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep)
|
void SSU2Server::RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep)
|
||||||
{
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex);
|
||||||
m_PendingOutgoingSessions.erase (ep);
|
m_PendingOutgoingSessions.erase (ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,9 +496,10 @@ namespace transport
|
||||||
break;
|
break;
|
||||||
case eSSU2SessionStateClosing:
|
case eSSU2SessionStateClosing:
|
||||||
m_LastSession->ProcessData (buf, len, senderEndpoint); // we might receive termintaion block
|
m_LastSession->ProcessData (buf, len, senderEndpoint); // we might receive termintaion block
|
||||||
if (m_LastSession && m_LastSession->GetState () != eSSU2SessionStateTerminated)
|
if (m_LastSession && m_LastSession->GetState () == eSSU2SessionStateClosing)
|
||||||
m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again
|
m_LastSession->RequestTermination (eSSU2TerminationReasonIdleTimeout); // send termination again
|
||||||
break;
|
break;
|
||||||
|
case eSSU2SessionStateClosingConfirmed:
|
||||||
case eSSU2SessionStateTerminated:
|
case eSSU2SessionStateTerminated:
|
||||||
m_LastSession = nullptr;
|
m_LastSession = nullptr;
|
||||||
break;
|
break;
|
||||||
|
@ -510,7 +515,10 @@ namespace transport
|
||||||
{
|
{
|
||||||
if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent &&
|
if (it1->second->GetState () == eSSU2SessionStateSessionRequestSent &&
|
||||||
it1->second->ProcessSessionCreated (buf, len))
|
it1->second->ProcessSessionCreated (buf, len))
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex);
|
||||||
m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint
|
m_PendingOutgoingSessions.erase (it1); // we are done with that endpoint
|
||||||
|
}
|
||||||
else
|
else
|
||||||
it1->second->ProcessRetry (buf, len);
|
it1->second->ProcessRetry (buf, len);
|
||||||
}
|
}
|
||||||
|
@ -754,6 +762,7 @@ namespace transport
|
||||||
if (it->second->IsTerminationTimeoutExpired (ts))
|
if (it->second->IsTerminationTimeoutExpired (ts))
|
||||||
{
|
{
|
||||||
//it->second->Terminate ();
|
//it->second->Terminate ();
|
||||||
|
std::unique_lock<std::mutex> l(m_PendingOutgoingSessionsMutex);
|
||||||
it = m_PendingOutgoingSessions.erase (it);
|
it = m_PendingOutgoingSessions.erase (it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -844,13 +853,17 @@ namespace transport
|
||||||
m_OutgoingTokens[ep] = {token, exp};
|
m_OutgoingTokens[ep] = {token, exp};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t SSU2Server::FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const
|
uint64_t SSU2Server::FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep)
|
||||||
{
|
{
|
||||||
auto it = m_OutgoingTokens.find (ep);
|
auto it = m_OutgoingTokens.find (ep);
|
||||||
if (it != m_OutgoingTokens.end ())
|
if (it != m_OutgoingTokens.end ())
|
||||||
{
|
{
|
||||||
if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second)
|
if (i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_THRESHOLD > it->second.second)
|
||||||
return 0; // token expired
|
{
|
||||||
|
// token expired
|
||||||
|
m_OutgoingTokens.erase (it);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return it->second.first;
|
return it->second.first;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -858,12 +871,18 @@ namespace transport
|
||||||
|
|
||||||
uint64_t SSU2Server::GetIncomingToken (const boost::asio::ip::udp::endpoint& ep)
|
uint64_t SSU2Server::GetIncomingToken (const boost::asio::ip::udp::endpoint& ep)
|
||||||
{
|
{
|
||||||
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
auto it = m_IncomingTokens.find (ep);
|
auto it = m_IncomingTokens.find (ep);
|
||||||
if (it != m_IncomingTokens.end ())
|
if (it != m_IncomingTokens.end ())
|
||||||
return it->second.first;
|
{
|
||||||
|
if (ts + SSU2_TOKEN_EXPIRATION_THRESHOLD <= it->second.second)
|
||||||
|
return it->second.first;
|
||||||
|
else // token expired
|
||||||
|
m_IncomingTokens.erase (it);
|
||||||
|
}
|
||||||
uint64_t token;
|
uint64_t token;
|
||||||
RAND_bytes ((uint8_t *)&token, 8);
|
RAND_bytes ((uint8_t *)&token, 8);
|
||||||
m_IncomingTokens.emplace (ep, std::make_pair (token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT));
|
m_IncomingTokens.emplace (ep, std::make_pair (token, ts + SSU2_TOKEN_EXPIRATION_TIMEOUT));
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#define SSU2_H__
|
#define SSU2_H__
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <mutex>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "SSU2Session.h"
|
#include "SSU2Session.h"
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ namespace transport
|
||||||
bool StartPeerTest (std::shared_ptr<const i2p::data::RouterInfo> router, bool v4);
|
bool StartPeerTest (std::shared_ptr<const i2p::data::RouterInfo> router, bool v4);
|
||||||
|
|
||||||
void UpdateOutgoingToken (const boost::asio::ip::udp::endpoint& ep, uint64_t token, uint32_t exp);
|
void UpdateOutgoingToken (const boost::asio::ip::udp::endpoint& ep, uint64_t token, uint32_t exp);
|
||||||
uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const;
|
uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep);
|
||||||
uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep);
|
uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep);
|
||||||
std::pair<uint64_t, uint32_t> NewIncomingToken (const boost::asio::ip::udp::endpoint& ep);
|
std::pair<uint64_t, uint32_t> NewIncomingToken (const boost::asio::ip::udp::endpoint& ep);
|
||||||
|
|
||||||
|
@ -140,6 +141,7 @@ namespace transport
|
||||||
std::unordered_map<uint64_t, std::shared_ptr<SSU2Session> > m_Sessions;
|
std::unordered_map<uint64_t, std::shared_ptr<SSU2Session> > m_Sessions;
|
||||||
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<SSU2Session> > m_SessionsByRouterHash;
|
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<SSU2Session> > m_SessionsByRouterHash;
|
||||||
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSU2Session> > m_PendingOutgoingSessions;
|
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSU2Session> > m_PendingOutgoingSessions;
|
||||||
|
mutable std::mutex m_PendingOutgoingSessionsMutex;
|
||||||
std::map<boost::asio::ip::udp::endpoint, std::pair<uint64_t, uint32_t> > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds)
|
std::map<boost::asio::ip::udp::endpoint, std::pair<uint64_t, uint32_t> > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds)
|
||||||
std::map<uint32_t, std::shared_ptr<SSU2Session> > m_Relays; // we are introducer, relay tag -> session
|
std::map<uint32_t, std::shared_ptr<SSU2Session> > m_Relays; // we are introducer, relay tag -> session
|
||||||
std::list<i2p::data::IdentHash> m_Introducers, m_IntroducersV6; // introducers we are connected to
|
std::list<i2p::data::IdentHash> m_Introducers, m_IntroducersV6; // introducers we are connected to
|
||||||
|
|
|
@ -878,7 +878,7 @@ namespace transport
|
||||||
// fragmented
|
// fragmented
|
||||||
if (numFragments > 2)
|
if (numFragments > 2)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SSU2: Too many fragments ", numFragments, " in SessionConfirmed");
|
LogPrint (eLogError, "SSU2: Too many fragments ", (int)numFragments, " in SessionConfirmed from ", m_RemoteEndpoint);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (len < 32)
|
if (len < 32)
|
||||||
|
@ -1462,12 +1462,19 @@ namespace transport
|
||||||
m_IsDataReceived = true;
|
m_IsDataReceived = true;
|
||||||
break;
|
break;
|
||||||
case eSSU2BlkTermination:
|
case eSSU2BlkTermination:
|
||||||
LogPrint (eLogDebug, "SSU2: Termination reason=", (int)buf[11]);
|
{
|
||||||
if (IsEstablished () && buf[11] != eSSU2TerminationReasonTerminationReceived)
|
uint8_t rsn = buf[11]; // reason
|
||||||
|
LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn);
|
||||||
|
if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived)
|
||||||
RequestTermination (eSSU2TerminationReasonTerminationReceived);
|
RequestTermination (eSSU2TerminationReasonTerminationReceived);
|
||||||
else
|
else if (m_State != eSSU2SessionStateTerminated)
|
||||||
|
{
|
||||||
|
if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived)
|
||||||
|
m_State = eSSU2SessionStateClosingConfirmed;
|
||||||
Done ();
|
Done ();
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case eSSU2BlkRelayRequest:
|
case eSSU2BlkRelayRequest:
|
||||||
LogPrint (eLogDebug, "SSU2: RelayRequest");
|
LogPrint (eLogDebug, "SSU2: RelayRequest");
|
||||||
HandleRelayRequest (buf + offset, size);
|
HandleRelayRequest (buf + offset, size);
|
||||||
|
@ -1623,7 +1630,7 @@ namespace transport
|
||||||
if (ts > it1->second->sendTime)
|
if (ts > it1->second->sendTime)
|
||||||
{
|
{
|
||||||
auto rtt = ts - it1->second->sendTime;
|
auto rtt = ts - it1->second->sendTime;
|
||||||
m_RTT = (m_RTT*m_SendPacketNum + rtt)/(m_SendPacketNum + 1);
|
m_RTT = std::round ((m_RTT*m_SendPacketNum + rtt)/(m_SendPacketNum + 1.0));
|
||||||
m_RTO = m_RTT*SSU2_kAPPA;
|
m_RTO = m_RTT*SSU2_kAPPA;
|
||||||
if (m_RTO < SSU2_MIN_RTO) m_RTO = SSU2_MIN_RTO;
|
if (m_RTO < SSU2_MIN_RTO) m_RTO = SSU2_MIN_RTO;
|
||||||
if (m_RTO > SSU2_MAX_RTO) m_RTO = SSU2_MAX_RTO;
|
if (m_RTO > SSU2_MAX_RTO) m_RTO = SSU2_MAX_RTO;
|
||||||
|
@ -1656,13 +1663,23 @@ namespace transport
|
||||||
{
|
{
|
||||||
if (isV4)
|
if (isV4)
|
||||||
{
|
{
|
||||||
if (i2p::context.GetStatus () == eRouterStatusTesting)
|
if (i2p::context.GetStatus () == eRouterStatusTesting ||
|
||||||
|
m_State == eSSU2SessionStatePeerTest)
|
||||||
|
{
|
||||||
i2p::context.SetError (eRouterErrorSymmetricNAT);
|
i2p::context.SetError (eRouterErrorSymmetricNAT);
|
||||||
|
i2p::context.SetStatus (eRouterStatusFirewalled);
|
||||||
|
m_Server.RescheduleIntroducersUpdateTimer ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (i2p::context.GetStatusV6 () == eRouterStatusTesting)
|
if (i2p::context.GetStatusV6 () == eRouterStatusTesting ||
|
||||||
|
m_State == eSSU2SessionStatePeerTest)
|
||||||
|
{
|
||||||
i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT);
|
i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT);
|
||||||
|
i2p::context.SetStatusV6 (eRouterStatusFirewalled);
|
||||||
|
m_Server.RescheduleIntroducersUpdateTimerV6 ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -100,6 +100,7 @@ namespace transport
|
||||||
eSSU2SessionStateSessionConfirmedSent,
|
eSSU2SessionStateSessionConfirmedSent,
|
||||||
eSSU2SessionStateEstablished,
|
eSSU2SessionStateEstablished,
|
||||||
eSSU2SessionStateClosing,
|
eSSU2SessionStateClosing,
|
||||||
|
eSSU2SessionStateClosingConfirmed,
|
||||||
eSSU2SessionStateTerminated,
|
eSSU2SessionStateTerminated,
|
||||||
eSSU2SessionStateFailed,
|
eSSU2SessionStateFailed,
|
||||||
eSSU2SessionStateIntroduced,
|
eSSU2SessionStateIntroduced,
|
||||||
|
|
|
@ -435,7 +435,7 @@ namespace stream
|
||||||
LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime);
|
LogPrint(eLogError, "Streaming: Packet ", seqn, "sent from the future, sendTime=", sentPacket->sendTime);
|
||||||
rtt = 1;
|
rtt = 1;
|
||||||
}
|
}
|
||||||
m_RTT = (m_RTT*seqn + rtt)/(seqn + 1);
|
m_RTT = std::round ((m_RTT*seqn + rtt)/(seqn + 1.0));
|
||||||
m_RTO = m_RTT*1.5; // TODO: implement it better
|
m_RTO = m_RTT*1.5; // TODO: implement it better
|
||||||
LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt, " sentTime=", sentPacket->sendTime);
|
LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt, " sentTime=", sentPacket->sendTime);
|
||||||
m_SentPackets.erase (it++);
|
m_SentPackets.erase (it++);
|
||||||
|
|
|
@ -113,6 +113,7 @@ namespace transport
|
||||||
virtual uint32_t GetRelayTag () const { return 0; };
|
virtual uint32_t GetRelayTag () const { return 0; };
|
||||||
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
|
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
|
||||||
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
|
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
|
||||||
|
virtual bool IsEstablished () const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -743,7 +743,12 @@ namespace transport
|
||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
for (auto it = m_Peers.begin (); it != m_Peers.end (); )
|
for (auto it = m_Peers.begin (); it != m_Peers.end (); )
|
||||||
{
|
{
|
||||||
if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT)
|
it->second.sessions.remove_if (
|
||||||
|
[](std::shared_ptr<TransportSession> session)->bool
|
||||||
|
{
|
||||||
|
return !session || !session->IsEstablished ();
|
||||||
|
});
|
||||||
|
if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds");
|
LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds");
|
||||||
auto profile = i2p::data::GetRouterProfile(it->first);
|
auto profile = i2p::data::GetRouterProfile(it->first);
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace util
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class MemoryPoolMt: public MemoryPool<T>
|
class MemoryPoolMt: private MemoryPool<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,7 @@ namespace proxy {
|
||||||
req.RemoveHeader("From");
|
req.RemoveHeader("From");
|
||||||
req.RemoveHeader("Forwarded");
|
req.RemoveHeader("Forwarded");
|
||||||
req.RemoveHeader("DNT"); // Useless DoNotTrack flag
|
req.RemoveHeader("DNT"); // Useless DoNotTrack flag
|
||||||
|
req.RemoveHeader("X-Requested-With"); // Android Webview send this with the value set to the application ID
|
||||||
req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding
|
req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding
|
||||||
/* drop proxy-disclosing headers */
|
/* drop proxy-disclosing headers */
|
||||||
req.RemoveHeader("X-Forwarded");
|
req.RemoveHeader("X-Forwarded");
|
||||||
|
|
Loading…
Reference in a new issue