access to RouterInfo's addresses by index

This commit is contained in:
orignal 2022-12-16 15:12:30 -05:00
parent df737a65b2
commit 84d9c8f1b8
4 changed files with 116 additions and 106 deletions

View File

@ -315,6 +315,7 @@ namespace http {
{ {
for (const auto& address : *addresses) for (const auto& address : *addresses)
{ {
if (!address) continue;
s << "<tr>\r\n<td>"; s << "<tr>\r\n<td>";
switch (address->transportStyle) switch (address->transportStyle)
{ {

View File

@ -272,7 +272,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : *addresses) 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; address->port = port;
updated = true; updated = true;
@ -290,7 +290,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : *addresses) 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 (); bool isAddr = v4 && address->IsV4 ();
if (!isAddr && (v6 || ygg)) if (!isAddr && (v6 || ygg))
@ -319,23 +319,20 @@ namespace i2p
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return; 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)
{ {
if ((*it)->IsNTCP2 ()) if (it && it->IsNTCP2 ())
{ {
found = true; found = true;
if (enable) if (enable)
{ {
(*it)->s = m_NTCP2Keys->staticPublicKey; it->s = m_NTCP2Keys->staticPublicKey;
memcpy ((*it)->i, m_NTCP2Keys->iv, 16); memcpy (it->i, m_NTCP2Keys->iv, 16);
it++;
} }
else else
it = addresses->erase (it); it.reset ();
updated = true; updated = true;
} }
else
it++;
} }
if (enable && !found) if (enable && !found)
{ {
@ -365,7 +362,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : *addresses) 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 ()))) ((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
{ {
if (port) address->port = port; if (port) address->port = port;
@ -387,23 +384,20 @@ namespace i2p
auto addresses = m_RouterInfo.GetAddresses (); auto addresses = m_RouterInfo.GetAddresses ();
if (!addresses) return; 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)
{ {
if ((*it)->IsSSU2 ()) if (it && it->IsSSU2 ())
{ {
found = true; found = true;
if (enable) if (enable)
{ {
(*it)->s = m_SSU2Keys->staticPublicKey; it->s = m_SSU2Keys->staticPublicKey;
(*it)->i = m_SSU2Keys->intro; it->i = m_SSU2Keys->intro;
it++;
} }
else else
it = addresses->erase (it); it.reset ();
updated = true; updated = true;
} }
else
it++;
} }
if (enable && !found) if (enable && !found)
{ {
@ -435,6 +429,7 @@ namespace i2p
bool updated = false; bool updated = false;
for (auto& address : *addresses) for (auto& address : *addresses)
{ {
if (!address) continue;
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))
{ {
@ -486,7 +481,7 @@ namespace i2p
if (!addresses) return; if (!addresses) return;
bool updated = false; bool updated = false;
for (auto& addr : *addresses) 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 && !addr->ssu->introducers.empty ())
{ {
addr->ssu->introducers.clear (); addr->ssu->introducers.clear ();
@ -612,7 +607,7 @@ namespace i2p
if (addresses) if (addresses)
{ {
for (auto& addr : *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->published = false;
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
@ -648,7 +643,7 @@ namespace i2p
if (addresses) if (addresses)
{ {
for (auto& addr : *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->published = true;
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer; addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
@ -685,7 +680,7 @@ namespace i2p
{ {
for (auto& addr: *addresses) 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) switch (addr->transportStyle)
{ {
@ -768,7 +763,7 @@ namespace i2p
{ {
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (addr->IsV4 ()) if (addr && addr->IsV4 ())
{ {
switch (addr->transportStyle) switch (addr->transportStyle)
{ {
@ -781,7 +776,7 @@ namespace i2p
default: ; default: ;
} }
} }
if (addr->port) port = addr->port; if (addr && addr->port) port = addr->port;
} }
} }
if (!port) if (!port)
@ -844,8 +839,8 @@ namespace i2p
{ {
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (!port) port = addr->port; if (!port && addr) port = addr->port;
if (i2p::util::net::IsYggdrasilAddress (addr->host)) if (addr && i2p::util::net::IsYggdrasilAddress (addr->host))
{ {
foundMesh = true; foundMesh = true;
break; break;
@ -867,7 +862,7 @@ namespace i2p
if (!addresses) return; if (!addresses) return;
for (auto& addr: *addresses) 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; addr->ssu->mtu = mtu;
LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", 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; if (!addresses) return;
for (auto& addr: *addresses) for (auto& addr: *addresses)
{ {
if (addr->IsPublishedNTCP2 ()) if (addr && addr->IsPublishedNTCP2 ())
{ {
bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host); bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host);
if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1))) if (addr->IsV6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1)))

View File

@ -209,7 +209,6 @@ namespace data
auto addresses = netdb.NewRouterInfoAddresses (); 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;
@ -418,7 +417,11 @@ namespace data
if (supportedTransports) if (supportedTransports)
{ {
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates 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; m_SupportedTransports |= supportedTransports;
} }
} }
@ -633,13 +636,23 @@ namespace data
{ {
m_SupportedTransports |= eNTCP2V4; m_SupportedTransports |= eNTCP2V4;
if (addr->published) m_ReachableTransports |= eNTCP2V4; if (addr->published) m_ReachableTransports |= eNTCP2V4;
(*m_Addresses)[eNTCP2V4Idx] = addr;
} }
if (addr->IsV6 ()) if (addr->IsV6 ())
{ {
m_SupportedTransports |= eNTCP2V6; if (i2p::util::net::IsYggdrasilAddress (addr->host))
if (addr->published) m_ReachableTransports |= eNTCP2V6; {
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) void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps)
@ -653,9 +666,16 @@ namespace data
addr->ssu->mtu = 0; addr->ssu->mtu = 0;
memcpy (addr->s, staticKey, 32); memcpy (addr->s, staticKey, 32);
memcpy (addr->i, introKey, 32); memcpy (addr->i, introKey, 32);
if (addr->IsV4 ()) m_SupportedTransports |= eSSU2V4; if (addr->IsV4 ())
if (addr->IsV6 ()) m_SupportedTransports |= eSSU2V6; {
m_Addresses->push_back(std::move(addr)); 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, void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
@ -676,13 +696,14 @@ namespace data
{ {
m_SupportedTransports |= eSSU2V4; m_SupportedTransports |= eSSU2V4;
m_ReachableTransports |= eSSU2V4; m_ReachableTransports |= eSSU2V4;
(*m_Addresses)[eSSU2V4Idx] = addr;
} }
if (addr->IsV6 ()) if (addr->IsV6 ())
{ {
m_SupportedTransports |= eSSU2V6; m_SupportedTransports |= eSSU2V6;
m_ReachableTransports |= eSSU2V6; m_ReachableTransports |= eSSU2V6;
(*m_Addresses)[eSSU2V6Idx] = addr;
} }
m_Addresses->push_back(std::move(addr));
} }
bool RouterInfo::IsNTCP2 (bool v4only) const bool RouterInfo::IsNTCP2 (bool v4only) const
@ -721,21 +742,15 @@ namespace data
{ {
if (IsV6 ()) if (IsV6 ())
{ {
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) for (auto& it : *m_Addresses)
{ {
auto addr = *it; if (it && it->IsV6 ())
if (addr->IsV6 ())
{ {
if (addr->IsV4 ()) if (it->IsV4 ())
{ it->caps &= ~AddressCaps::eV6;
addr->caps &= ~AddressCaps::eV6;
++it;
}
else else
it = m_Addresses->erase (it); it.reset ();
} }
else
++it;
} }
UpdateSupportedTransports (); UpdateSupportedTransports ();
} }
@ -745,21 +760,15 @@ namespace data
{ {
if (IsV4 ()) if (IsV4 ())
{ {
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) for (auto& it : *m_Addresses)
{ {
auto addr = *it; if (it && it->IsV4 ())
if (addr->IsV4 ())
{ {
if (addr->IsV6 ()) if (it->IsV6 ())
{ it->caps &= ~AddressCaps::eV4;
addr->caps &= ~AddressCaps::eV4;
++it;
}
else else
it = m_Addresses->erase (it); it.reset ();
} }
else
++it;
} }
UpdateSupportedTransports (); UpdateSupportedTransports ();
} }
@ -780,33 +789,22 @@ namespace data
{ {
m_SupportedTransports &= ~eNTCP2V6Mesh; m_SupportedTransports &= ~eNTCP2V6Mesh;
m_ReachableTransports &= ~eNTCP2V6Mesh; m_ReachableTransports &= ~eNTCP2V6Mesh;
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) for (auto& it: *m_Addresses)
{ {
auto addr = *it; if (it && i2p::util::net::IsYggdrasilAddress (it->host))
if (i2p::util::net::IsYggdrasilAddress (addr->host)) it.reset ();
it = m_Addresses->erase (it);
else
++it;
} }
} }
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const
{ {
return GetAddress ( return (*GetAddresses ())[eSSU2V4Idx];
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->transportStyle == eTransportSSU2) && address->IsV4();
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const
{ {
return GetAddress ( return (*GetAddresses ())[eSSU2V6Idx];
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->transportStyle == eTransportSSU2) && address->IsV6();
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const
@ -843,7 +841,7 @@ namespace data
auto addresses = m_Addresses; auto addresses = m_Addresses;
#endif #endif
for (const auto& address : *addresses) for (const auto& address : *addresses)
if (filter (address)) return address; if (address && filter (address)) return address;
return nullptr; return nullptr;
} }
@ -871,30 +869,21 @@ namespace data
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const
{ {
return GetAddress ( auto addr = (*GetAddresses ())[eNTCP2V4Idx];
[](std::shared_ptr<const RouterInfo::Address> address)->bool if (addr && addr->IsPublishedNTCP2 ()) return addr;
{ return nullptr;
return address->IsPublishedNTCP2 () && address->host.is_v4 ();
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const
{ {
return GetAddress ( auto addr = (*GetAddresses ())[eNTCP2V6Idx];
[](std::shared_ptr<const RouterInfo::Address> address)->bool if (addr && addr->IsPublishedNTCP2 ()) return addr;
{ return nullptr;
return address->IsPublishedNTCP2 () && address->host.is_v6 () &&
!i2p::util::net::IsYggdrasilAddress (address->host);
});
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const
{ {
return GetAddress ( return (*GetAddresses ())[eNTCP2V6MeshIdx];
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host);
});
} }
std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const
@ -944,7 +933,7 @@ namespace data
{ {
for (auto& addr: *m_Addresses) for (auto& addr: *m_Addresses)
{ {
if (!addr->published && (addr->transportStyle == eTransportNTCP2 || addr->transportStyle == eTransportSSU2)) if (addr && !addr->published)
{ {
addr->caps &= ~(eV4 | eV6); addr->caps &= ~(eV4 | eV6);
addr->caps |= transports; addr->caps |= transports;
@ -958,6 +947,7 @@ namespace data
m_ReachableTransports = 0; m_ReachableTransports = 0;
for (const auto& addr: *m_Addresses) for (const auto& addr: *m_Addresses)
{ {
if (!addr) continue;
uint8_t transports = 0; uint8_t transports = 0;
switch (addr->transportStyle) switch (addr->transportStyle)
{ {
@ -1061,10 +1051,22 @@ namespace data
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
uint8_t numAddresses = addresses->size (); uint8_t numAddresses = 0;
s.write ((char *)&numAddresses, sizeof (numAddresses)); for (size_t idx = 0; idx < addresses->size(); idx++)
for (const auto& addr_ptr : *addresses)
{ {
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 (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; const Address& address = *addr_ptr;
// calculate cost // calculate cost
uint8_t cost = 0x7f; uint8_t cost = 0x7f;
@ -1269,7 +1271,7 @@ namespace data
if (!addresses) return false; if (!addresses) return false;
for (auto& addr : *addresses) 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) for (auto& intro: addr->ssu->introducers)
if (intro.iTag == introducer.iTag) return false; // already presented if (intro.iTag == introducer.iTag) return false; // already presented
@ -1287,7 +1289,7 @@ namespace data
if (!addresses) return false; if (!addresses) return false;
for (auto& addr: *addresses) 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) for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
if (h == it->iH) if (h == it->iH)

View File

@ -60,13 +60,25 @@ namespace data
{ {
public: public:
enum SupportedTransportsIdx
{
eNTCP2V4Idx = 0,
eNTCP2V6Idx,
eSSU2V4Idx,
eSSU2V6Idx,
eNTCP2V6MeshIdx,
eNumTransports
};
#define TransportBit(tr) e##tr = (1 << e##tr##Idx)
enum SupportedTransports enum SupportedTransports
{ {
eNTCP2V4 = 0x01, TransportBit(NTCP2V4), // 0x01
eNTCP2V6 = 0x02, TransportBit(NTCP2V6), // 0x02
eSSU2V4 = 0x04, TransportBit(SSU2V4), // 0x04
eSSU2V6 = 0x08, TransportBit(SSU2V6), // 0x08
eNTCP2V6Mesh = 0x10, TransportBit(NTCP2V6Mesh), // 0x10
eAllTransports = 0xFF eAllTransports = 0xFF
}; };
typedef uint8_t CompatibleTransports; typedef uint8_t CompatibleTransports;
@ -160,7 +172,7 @@ namespace data
Buffer (const uint8_t * buf, size_t len); Buffer (const uint8_t * buf, size_t len);
}; };
typedef std::vector<std::shared_ptr<Address> > Addresses; typedef std::array<std::shared_ptr<Address>, eNumTransports> Addresses;
RouterInfo (const std::string& fullPath); RouterInfo (const std::string& fullPath);
RouterInfo (const RouterInfo& ) = default; RouterInfo (const RouterInfo& ) = default;