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)
{
if (!address) continue;
s << "<tr>\r\n<td>";
switch (address->transportStyle)
{

View File

@ -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)))

View File

@ -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<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const
{
return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->transportStyle == eTransportSSU2) && address->IsV4();
});
return (*GetAddresses ())[eSSU2V4Idx];
}
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const
{
return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->transportStyle == eTransportSSU2) && address->IsV6();
});
return (*GetAddresses ())[eSSU2V6Idx];
}
std::shared_ptr<const RouterInfo::Address> 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<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const
{
return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return address->IsPublishedNTCP2 () && address->host.is_v4 ();
});
auto addr = (*GetAddresses ())[eNTCP2V4Idx];
if (addr && addr->IsPublishedNTCP2 ()) return addr;
return nullptr;
}
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const
{
return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> 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<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const
{
return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host);
});
return (*GetAddresses ())[eNTCP2V6MeshIdx];
}
std::shared_ptr<RouterProfile> 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 ();
s.write ((char *)&numAddresses, sizeof (numAddresses));
for (const auto& addr_ptr : *addresses)
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 (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)

View File

@ -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<std::shared_ptr<Address> > Addresses;
typedef std::array<std::shared_ptr<Address>, eNumTransports> Addresses;
RouterInfo (const std::string& fullPath);
RouterInfo (const RouterInfo& ) = default;