diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp
index 917acdb8..4743efc2 100644
--- a/daemon/HTTPServer.cpp
+++ b/daemon/HTTPServer.cpp
@@ -315,6 +315,7 @@ namespace http {
{
for (const auto& address : *addresses)
{
+ if (!address) continue;
s << "
\r\n";
switch (address->transportStyle)
{
diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp
index 8928fc7f..5259a4f7 100644
--- a/libi2pd/RouterContext.cpp
+++ b/libi2pd/RouterContext.cpp
@@ -272,7 +272,7 @@ namespace i2p
bool updated = false;
for (auto& address : *addresses)
{
- if (address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
+ if (address && address->port != port && address->transportStyle == i2p::data::RouterInfo::eTransportSSU2)
{
address->port = port;
updated = true;
@@ -290,7 +290,7 @@ namespace i2p
bool updated = false;
for (auto& address : *addresses)
{
- if (address->IsNTCP2 () && (address->port != port || address->published != publish))
+ if (address && address->IsNTCP2 () && (address->port != port || address->published != publish))
{
bool isAddr = v4 && address->IsV4 ();
if (!isAddr && (v6 || ygg))
@@ -319,23 +319,20 @@ namespace i2p
auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return;
bool found = false, updated = false;
- for (auto it = addresses->begin (); it != addresses->end ();)
+ for (auto& it: *addresses)
{
- if ((*it)->IsNTCP2 ())
+ if (it && it->IsNTCP2 ())
{
found = true;
if (enable)
{
- (*it)->s = m_NTCP2Keys->staticPublicKey;
- memcpy ((*it)->i, m_NTCP2Keys->iv, 16);
- it++;
+ it->s = m_NTCP2Keys->staticPublicKey;
+ memcpy (it->i, m_NTCP2Keys->iv, 16);
}
else
- it = addresses->erase (it);
+ it.reset ();
updated = true;
- }
- else
- it++;
+ }
}
if (enable && !found)
{
@@ -365,7 +362,7 @@ namespace i2p
bool updated = false;
for (auto& address : *addresses)
{
- if (address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
+ if (address && address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
{
if (port) address->port = port;
@@ -387,23 +384,20 @@ namespace i2p
auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return;
bool found = false, updated = false;
- for (auto it = addresses->begin (); it != addresses->end ();)
+ for (auto& it : *addresses)
{
- if ((*it)->IsSSU2 ())
+ if (it && it->IsSSU2 ())
{
found = true;
if (enable)
{
- (*it)->s = m_SSU2Keys->staticPublicKey;
- (*it)->i = m_SSU2Keys->intro;
- it++;
+ it->s = m_SSU2Keys->staticPublicKey;
+ it->i = m_SSU2Keys->intro;
}
else
- it = addresses->erase (it);
+ it.reset ();
updated = true;
}
- else
- it++;
}
if (enable && !found)
{
@@ -435,6 +429,7 @@ namespace i2p
bool updated = false;
for (auto& address : *addresses)
{
+ if (!address) continue;
if (address->host != host && address->IsCompatible (host) &&
!i2p::util::net::IsYggdrasilAddress (address->host))
{
@@ -486,7 +481,7 @@ namespace i2p
if (!addresses) return;
bool updated = false;
for (auto& addr : *addresses)
- if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) &&
+ if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) &&
addr->ssu && !addr->ssu->introducers.empty ())
{
addr->ssu->introducers.clear ();
@@ -612,7 +607,7 @@ namespace i2p
if (addresses)
{
for (auto& addr : *addresses)
- if (addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
+ if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{
addr->published = false;
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
@@ -648,7 +643,7 @@ namespace i2p
if (addresses)
{
for (auto& addr : *addresses)
- if (addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
+ if (addr && addr->ssu && isSSU2Published && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{
addr->published = true;
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
@@ -685,7 +680,7 @@ namespace i2p
{
for (auto& addr: *addresses)
{
- if (addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
+ if (addr && addr->IsV6 () && !i2p::util::net::IsYggdrasilAddress (addr->host))
{
switch (addr->transportStyle)
{
@@ -768,7 +763,7 @@ namespace i2p
{
for (auto& addr: *addresses)
{
- if (addr->IsV4 ())
+ if (addr && addr->IsV4 ())
{
switch (addr->transportStyle)
{
@@ -781,7 +776,7 @@ namespace i2p
default: ;
}
}
- if (addr->port) port = addr->port;
+ if (addr && addr->port) port = addr->port;
}
}
if (!port)
@@ -844,8 +839,8 @@ namespace i2p
{
for (auto& addr: *addresses)
{
- if (!port) port = addr->port;
- if (i2p::util::net::IsYggdrasilAddress (addr->host))
+ if (!port && addr) port = addr->port;
+ if (addr && i2p::util::net::IsYggdrasilAddress (addr->host))
{
foundMesh = true;
break;
@@ -867,7 +862,7 @@ namespace i2p
if (!addresses) return;
for (auto& addr: *addresses)
{
- if (addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
+ if (addr && addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{
addr->ssu->mtu = mtu;
LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu);
@@ -883,7 +878,7 @@ namespace i2p
if (!addresses) return;
for (auto& addr: *addresses)
{
- if (addr->IsPublishedNTCP2 ())
+ if (addr && addr->IsPublishedNTCP2 ())
{
bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host);
if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1)))
diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp
index 13a0731e..a83fd043 100644
--- a/libi2pd/RouterInfo.cpp
+++ b/libi2pd/RouterInfo.cpp
@@ -209,7 +209,6 @@ namespace data
auto addresses = netdb.NewRouterInfoAddresses ();
uint8_t numAddresses;
s.read ((char *)&numAddresses, sizeof (numAddresses));
- addresses->reserve (numAddresses);
for (int i = 0; i < numAddresses; i++)
{
uint8_t supportedTransports = 0;
@@ -418,7 +417,11 @@ namespace data
if (supportedTransports)
{
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates
- addresses->push_back(address);
+ {
+ for (uint8_t i = 0; i < eNumTransports; i++)
+ if ((1 << i) & supportedTransports)
+ (*addresses)[i] = address;
+ }
m_SupportedTransports |= supportedTransports;
}
}
@@ -633,13 +636,23 @@ namespace data
{
m_SupportedTransports |= eNTCP2V4;
if (addr->published) m_ReachableTransports |= eNTCP2V4;
+ (*m_Addresses)[eNTCP2V4Idx] = addr;
}
if (addr->IsV6 ())
{
- m_SupportedTransports |= eNTCP2V6;
- if (addr->published) m_ReachableTransports |= eNTCP2V6;
+ if (i2p::util::net::IsYggdrasilAddress (addr->host))
+ {
+ m_SupportedTransports |= eNTCP2V6Mesh;
+ m_ReachableTransports |= eNTCP2V6Mesh;
+ (*m_Addresses)[eNTCP2V6MeshIdx] = addr;
+ }
+ else
+ {
+ m_SupportedTransports |= eNTCP2V6;
+ if (addr->published) m_ReachableTransports |= eNTCP2V6;
+ (*m_Addresses)[eNTCP2V6Idx] = addr;
+ }
}
- m_Addresses->push_back(std::move(addr));
}
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps)
@@ -653,9 +666,16 @@ namespace data
addr->ssu->mtu = 0;
memcpy (addr->s, staticKey, 32);
memcpy (addr->i, introKey, 32);
- if (addr->IsV4 ()) m_SupportedTransports |= eSSU2V4;
- if (addr->IsV6 ()) m_SupportedTransports |= eSSU2V6;
- m_Addresses->push_back(std::move(addr));
+ if (addr->IsV4 ())
+ {
+ m_SupportedTransports |= eSSU2V4;
+ (*m_Addresses)[eSSU2V4Idx] = addr;
+ }
+ if (addr->IsV6 ())
+ {
+ m_SupportedTransports |= eSSU2V6;
+ (*m_Addresses)[eSSU2V6Idx] = addr;
+ }
}
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
@@ -676,13 +696,14 @@ namespace data
{
m_SupportedTransports |= eSSU2V4;
m_ReachableTransports |= eSSU2V4;
+ (*m_Addresses)[eSSU2V4Idx] = addr;
}
if (addr->IsV6 ())
{
m_SupportedTransports |= eSSU2V6;
m_ReachableTransports |= eSSU2V6;
+ (*m_Addresses)[eSSU2V6Idx] = addr;
}
- m_Addresses->push_back(std::move(addr));
}
bool RouterInfo::IsNTCP2 (bool v4only) const
@@ -721,21 +742,15 @@ namespace data
{
if (IsV6 ())
{
- for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
+ for (auto& it : *m_Addresses)
{
- auto addr = *it;
- if (addr->IsV6 ())
+ if (it && it->IsV6 ())
{
- if (addr->IsV4 ())
- {
- addr->caps &= ~AddressCaps::eV6;
- ++it;
- }
+ if (it->IsV4 ())
+ it->caps &= ~AddressCaps::eV6;
else
- it = m_Addresses->erase (it);
+ it.reset ();
}
- else
- ++it;
}
UpdateSupportedTransports ();
}
@@ -745,21 +760,15 @@ namespace data
{
if (IsV4 ())
{
- for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
+ for (auto& it : *m_Addresses)
{
- auto addr = *it;
- if (addr->IsV4 ())
+ if (it && it->IsV4 ())
{
- if (addr->IsV6 ())
- {
- addr->caps &= ~AddressCaps::eV4;
- ++it;
- }
+ if (it->IsV6 ())
+ it->caps &= ~AddressCaps::eV4;
else
- it = m_Addresses->erase (it);
+ it.reset ();
}
- else
- ++it;
}
UpdateSupportedTransports ();
}
@@ -780,33 +789,22 @@ namespace data
{
m_SupportedTransports &= ~eNTCP2V6Mesh;
m_ReachableTransports &= ~eNTCP2V6Mesh;
- for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
+ for (auto& it: *m_Addresses)
{
- auto addr = *it;
- if (i2p::util::net::IsYggdrasilAddress (addr->host))
- it = m_Addresses->erase (it);
- else
- ++it;
+ if (it && i2p::util::net::IsYggdrasilAddress (it->host))
+ it.reset ();
}
}
}
std::shared_ptr RouterInfo::GetSSU2V4Address () const
{
- return GetAddress (
- [](std::shared_ptr address)->bool
- {
- return (address->transportStyle == eTransportSSU2) && address->IsV4();
- });
+ return (*GetAddresses ())[eSSU2V4Idx];
}
std::shared_ptr RouterInfo::GetSSU2V6Address () const
{
- return GetAddress (
- [](std::shared_ptr address)->bool
- {
- return (address->transportStyle == eTransportSSU2) && address->IsV6();
- });
+ return (*GetAddresses ())[eSSU2V6Idx];
}
std::shared_ptr RouterInfo::GetSSU2Address (bool v4) const
@@ -843,7 +841,7 @@ namespace data
auto addresses = m_Addresses;
#endif
for (const auto& address : *addresses)
- if (filter (address)) return address;
+ if (address && filter (address)) return address;
return nullptr;
}
@@ -871,30 +869,21 @@ namespace data
std::shared_ptr RouterInfo::GetPublishedNTCP2V4Address () const
{
- return GetAddress (
- [](std::shared_ptr address)->bool
- {
- return address->IsPublishedNTCP2 () && address->host.is_v4 ();
- });
+ auto addr = (*GetAddresses ())[eNTCP2V4Idx];
+ if (addr && addr->IsPublishedNTCP2 ()) return addr;
+ return nullptr;
}
std::shared_ptr RouterInfo::GetPublishedNTCP2V6Address () const
{
- return GetAddress (
- [](std::shared_ptr address)->bool
- {
- return address->IsPublishedNTCP2 () && address->host.is_v6 () &&
- !i2p::util::net::IsYggdrasilAddress (address->host);
- });
+ auto addr = (*GetAddresses ())[eNTCP2V6Idx];
+ if (addr && addr->IsPublishedNTCP2 ()) return addr;
+ return nullptr;
}
std::shared_ptr RouterInfo::GetYggdrasilAddress () const
{
- return GetAddress (
- [](std::shared_ptr address)->bool
- {
- return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host);
- });
+ return (*GetAddresses ())[eNTCP2V6MeshIdx];
}
std::shared_ptr RouterInfo::GetProfile () const
@@ -944,7 +933,7 @@ namespace data
{
for (auto& addr: *m_Addresses)
{
- if (!addr->published && (addr->transportStyle == eTransportNTCP2 || addr->transportStyle == eTransportSSU2))
+ if (addr && !addr->published)
{
addr->caps &= ~(eV4 | eV6);
addr->caps |= transports;
@@ -958,6 +947,7 @@ namespace data
m_ReachableTransports = 0;
for (const auto& addr: *m_Addresses)
{
+ if (!addr) continue;
uint8_t transports = 0;
switch (addr->transportStyle)
{
@@ -1061,10 +1051,22 @@ namespace data
uint64_t ts = htobe64 (GetTimestamp ());
s.write ((const char *)&ts, sizeof (ts));
// addresses
- uint8_t numAddresses = addresses->size ();
+ uint8_t numAddresses = 0;
+ for (size_t idx = 0; idx < addresses->size(); idx++)
+ {
+ auto addr_ptr = (*addresses)[idx];
+ if (!addr_ptr) continue;
+ if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue;
+ if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue;
+ numAddresses++;
+ }
s.write ((char *)&numAddresses, sizeof (numAddresses));
- for (const auto& addr_ptr : *addresses)
+ for (size_t idx = 0; idx < addresses->size(); idx++)
{
+ auto addr_ptr = (*addresses)[idx];
+ if (!addr_ptr) continue;
+ if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue;
+ if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue;
const Address& address = *addr_ptr;
// calculate cost
uint8_t cost = 0x7f;
@@ -1269,7 +1271,7 @@ namespace data
if (!addresses) return false;
for (auto& addr : *addresses)
{
- if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
+ if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{
for (auto& intro: addr->ssu->introducers)
if (intro.iTag == introducer.iTag) return false; // already presented
@@ -1287,7 +1289,7 @@ namespace data
if (!addresses) return false;
for (auto& addr: *addresses)
{
- if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
+ if (addr && addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
if (h == it->iH)
diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h
index 9e98769f..bd293d40 100644
--- a/libi2pd/RouterInfo.h
+++ b/libi2pd/RouterInfo.h
@@ -60,13 +60,25 @@ namespace data
{
public:
+ enum SupportedTransportsIdx
+ {
+ eNTCP2V4Idx = 0,
+ eNTCP2V6Idx,
+ eSSU2V4Idx,
+ eSSU2V6Idx,
+ eNTCP2V6MeshIdx,
+ eNumTransports
+ };
+
+#define TransportBit(tr) e##tr = (1 << e##tr##Idx)
+
enum SupportedTransports
{
- eNTCP2V4 = 0x01,
- eNTCP2V6 = 0x02,
- eSSU2V4 = 0x04,
- eSSU2V6 = 0x08,
- eNTCP2V6Mesh = 0x10,
+ TransportBit(NTCP2V4), // 0x01
+ TransportBit(NTCP2V6), // 0x02
+ TransportBit(SSU2V4), // 0x04
+ TransportBit(SSU2V6), // 0x08
+ TransportBit(NTCP2V6Mesh), // 0x10
eAllTransports = 0xFF
};
typedef uint8_t CompatibleTransports;
@@ -160,7 +172,7 @@ namespace data
Buffer (const uint8_t * buf, size_t len);
};
- typedef std::vector > Addresses;
+ typedef std::array, eNumTransports> Addresses;
RouterInfo (const std::string& fullPath);
RouterInfo (const RouterInfo& ) = default;
|