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;