SSU2 only introducers

This commit is contained in:
orignal 2022-11-23 13:44:03 -05:00
parent ccfeca728e
commit a298588943
5 changed files with 23 additions and 209 deletions

View File

@ -1229,15 +1229,6 @@ namespace data
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSUV6Router () const
{
return GetRandomRouter (
[](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router->IsECIES () && router->IsSSUV6 ();
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomIntroducer (bool v4, const std::set<IdentHash>& excluded) const
{
return GetRandomRouter (

View File

@ -91,7 +91,6 @@ namespace data
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSUV6Router () const; // TODO: change to v6 peer test later
std::shared_ptr<const RouterInfo> GetRandomIntroducer (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;

View File

@ -330,21 +330,9 @@ namespace data
}
Introducer& introducer = address->ssu->introducers.at (index);
if (!strcmp (key, "ihost"))
{
boost::system::error_code ecode;
introducer.iHost = boost::asio::ip::address::from_string (value, ecode);
}
introducer.isH = false; // SSU1
else if (!strcmp (key, "iport"))
{
try
{
introducer.iPort = boost::lexical_cast<int>(value);
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'iport' exception ", ex.what ());
}
}
introducer.isH = false; // SSU1
else if (!strcmp (key, "itag"))
{
try
@ -356,8 +344,11 @@ namespace data
LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ());
}
}
else if (!strcmp (key, "ikey") || !strcmp (key, "ih"))
Base64ToByteStream (value, strlen (value), introducer.iKey, 32);
else if (!strcmp (key, "ih"))
{
Base64ToByteStream (value, strlen (value), introducer.iH, 32);
introducer.isH = true;
}
else if (!strcmp (key, "iexp"))
{
try
@ -413,7 +404,7 @@ namespace data
int numValid = 0;
for (auto& it: address->ssu->introducers)
{
if (it.iTag && ts < it.iExp && !it.iPort && it.iHost.is_unspecified ()) // SSU2 only
if (it.iTag && ts < it.iExp && it.isH)
numValid++;
else
it.iTag = 0;
@ -625,29 +616,6 @@ namespace data
return l+1;
}
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
{
auto addr = std::make_shared<Address>();
addr->host = boost::asio::ip::address::from_string (host);
addr->port = port;
addr->transportStyle = eTransportSSU;
addr->published = true;
addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC;
addr->date = 0;
addr->ssu.reset (new SSUExt ());
addr->ssu->mtu = mtu;
if (key)
memcpy (addr->i, key, 32);
else
RAND_bytes (addr->i, 32);
for (const auto& it: *m_Addresses) // don't insert same address twice
if (*it == *addr) return;
m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
m_ReachableTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4;
m_Addresses->push_back(std::move(addr));
}
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
const boost::asio::ip::address& host, int port, uint8_t caps)
{
@ -716,51 +684,6 @@ namespace data
m_Addresses->push_back(std::move(addr));
}
bool RouterInfo::AddIntroducer (const Introducer& introducer)
{
for (auto& addr : *m_Addresses)
{
if (addr->transportStyle == eTransportSSU &&
((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ())))
{
for (auto& intro: addr->ssu->introducers)
if (intro.iTag == introducer.iTag) return false; // already presented
addr->ssu->introducers.push_back (introducer);
m_ReachableTransports |= (addr->IsV4 () ? eSSUV4 : eSSUV6);
return true;
}
}
return false;
}
bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e)
{
for (auto& addr: *m_Addresses)
{
if (addr->transportStyle == eTransportSSU &&
((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ())))
{
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
if (boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e)
{
addr->ssu->introducers.erase (it);
if (addr->ssu->introducers.empty ())
m_ReachableTransports &= ~(addr->IsV4 () ? eSSUV4 : eSSUV6);
return true;
}
}
}
return false;
}
bool RouterInfo::IsSSU (bool v4only) const
{
if (v4only)
return m_SupportedTransports & eSSUV4;
else
return m_SupportedTransports & (eSSUV4 | eSSUV6);
}
bool RouterInfo::IsNTCP2 (bool v4only) const
{
if (v4only)
@ -867,15 +790,6 @@ namespace data
}
}
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
{
return GetAddress (
[v4only](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->transportStyle == eTransportSSU) && (!v4only || address->IsV4 ());
});
}
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUV6Address () const
{
return GetAddress (
@ -1051,7 +965,6 @@ namespace data
{
for (auto& addr: *m_Addresses)
{
// TODO: implement SSU
if (!addr->published && (addr->transportStyle == eTransportNTCP || addr->transportStyle == eTransportSSU2))
{
addr->caps &= ~(eV4 | eV6);
@ -1076,12 +989,6 @@ namespace data
if (addr->IsPublishedNTCP2 ())
m_ReachableTransports |= transports;
break;
case eTransportSSU:
if (addr->IsV4 ()) transports |= eSSUV4;
if (addr->IsV6 ()) transports |= eSSUV6;
if (addr->IsReachableSSU ())
m_ReachableTransports |= transports;
break;
case eTransportSSU2:
if (addr->IsV4 ()) transports |= eSSU2V4;
if (addr->IsV6 ()) transports |= eSSU2V6;
@ -1183,8 +1090,6 @@ namespace data
uint8_t cost = 0x7f;
if (address.transportStyle == eTransportNTCP)
cost = address.published ? COST_NTCP2_PUBLISHED : COST_NTCP2_NON_PUBLISHED;
else if (address.transportStyle == eTransportSSU)
cost = address.published ? COST_SSU_DIRECT : COST_SSU_THROUGH_INTRODUCERS;
else if (address.transportStyle == eTransportSSU2)
cost = address.published ? COST_SSU2_DIRECT : COST_SSU2_NON_PUBLISHED;
s.write ((const char *)&cost, sizeof (cost));
@ -1213,43 +1118,6 @@ namespace data
else
continue; // don't write NTCP address
}
else if (address.transportStyle == eTransportSSU)
{
WriteString ("SSU", s);
// caps
WriteString ("caps", properties);
properties << '=';
std::string caps;
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING;
if (address.host.is_v4 ())
{
if (address.published)
{
isPublished = true;
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
}
else
caps += CAPS_FLAG_V4;
}
else if (address.host.is_v6 ())
{
if (address.published)
{
isPublished = true;
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
}
else
caps += CAPS_FLAG_V6;
}
else
{
if (address.IsV4 ()) caps += CAPS_FLAG_V4;
if (address.IsV6 ()) caps += CAPS_FLAG_V6;
if (caps.empty ()) caps += CAPS_FLAG_V4;
}
WriteString (caps, properties);
properties << ';';
}
else if (address.transportStyle == eTransportSSU2)
{
WriteString ("SSU2", s);
@ -1292,7 +1160,7 @@ namespace data
size_t len = address.IsSSU2 () ? 32 : 16;
WriteString (address.i.ToBase64 (len), properties); properties << ';';
}
if (address.transportStyle == eTransportSSU || address.IsSSU2 ())
if (address.transportStyle == eTransportSSU2)
{
// write introducers if any
if (address.ssu && !address.ssu->introducers.empty())
@ -1309,45 +1177,18 @@ namespace data
}
i++;
}
if (address.transportStyle == eTransportSSU)
{
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
WriteString ("ihost" + boost::lexical_cast<std::string>(i), properties);
properties << '=';
WriteString (introducer.iHost.to_string (), properties);
properties << ';';
i++;
}
}
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
if (address.IsSSU2 ())
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
else
WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties);
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
properties << '=';
char value[64];
size_t l = ByteStreamToBase64 (introducer.iKey, 32, value, 64);
size_t l = ByteStreamToBase64 (introducer.iH, 32, value, 64);
value[l] = 0;
WriteString (value, properties);
properties << ';';
i++;
}
if (address.transportStyle == eTransportSSU)
{
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
WriteString ("iport" + boost::lexical_cast<std::string>(i), properties);
properties << '=';
WriteString (boost::lexical_cast<std::string>(introducer.iPort), properties);
properties << ';';
i++;
}
}
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
@ -1359,18 +1200,8 @@ namespace data
}
}
}
if (address.transportStyle == eTransportSSU)
{
// write intro key
WriteString ("key", properties);
properties << '=';
char value[64];
size_t l = ByteStreamToBase64 (address.i, 32, value, 64);
value[l] = 0;
WriteString (value, properties);
properties << ';';
}
if (address.transportStyle == eTransportSSU || address.IsSSU2 ())
if (address.transportStyle == eTransportSSU2)
{
// write mtu
if (address.ssu && address.ssu->mtu)
@ -1381,7 +1212,7 @@ namespace data
properties << ';';
}
}
if ((isPublished || (address.ssu && !address.IsSSU2 ())) && address.port)
if (isPublished && address.port)
{
WriteString ("port", properties);
properties << '=';
@ -1473,7 +1304,7 @@ namespace data
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
if (h == it->iKey)
if (h == it->iH)
{
addr->ssu->introducers.erase (it);
if (addr->ssu->introducers.empty ())

View File

@ -101,15 +101,13 @@ namespace data
eTransportSSU2
};
typedef Tag<32> IntroKey; // should be castable to MacKey and AESKey
struct Introducer
{
Introducer (): iPort (0), iExp (0) {};
boost::asio::ip::address iHost;
int iPort;
IntroKey iKey; // or ih for SSU2
Introducer (): iTag (0), iExp (0), isH (false) {};
uint32_t iTag;
uint32_t iExp;
IdentHash iH;
bool isH; // TODO: remove later
};
struct SSUExt
@ -188,28 +186,22 @@ namespace data
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> GetPublishedNTCP2V6Address () const;
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
std::shared_ptr<const Address> GetSSUV6Address () const;
std::shared_ptr<const Address> GetYggdrasilAddress () const;
std::shared_ptr<const Address> GetSSU2V4Address () const;
std::shared_ptr<const Address> GetSSU2V6Address () const;
std::shared_ptr<const Address> GetSSU2Address (bool v4) const;
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0, uint8_t caps = 0);
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, uint8_t caps = 0); // non published
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
const boost::asio::ip::address& host, int port); // published
bool AddIntroducer (const Introducer& introducer);
bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps
void UpdateSupportedTransports ();
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
bool IsReachable () const { return m_Caps & Caps::eReachable; };
bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
bool IsSSU (bool v4only = true) const;
bool IsSSUV6 () const { return m_SupportedTransports & eSSUV6; };
bool IsNTCP2 (bool v4only = true) const;
bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; };
bool IsSSU2V4 () const { return m_SupportedTransports & eSSU2V4; };

View File

@ -641,7 +641,7 @@ namespace transport
// try to find existing session first
for (auto& it: address->ssu->introducers)
{
auto it1 = m_SessionsByRouterHash.find (it.iKey);
auto it1 = m_SessionsByRouterHash.find (it.iH);
if (it1 != m_SessionsByRouterHash.end ())
{
it1->second->Introduce (session, it.iTag);
@ -664,7 +664,7 @@ namespace transport
const auto& introducer = address->ssu->introducers[indicies[i]];
if (introducer.iTag && ts < introducer.iExp)
{
r = i2p::data::netdb.FindRouter (introducer.iKey);
r = i2p::data::netdb.FindRouter (introducer.iH);
if (r && r->IsReachableFrom (i2p::context.GetRouterInfo ()))
{
relayTag = introducer.iTag;
@ -713,7 +713,7 @@ namespace transport
// introducers not found, try to request them
for (auto& it: address->ssu->introducers)
if (it.iTag && ts < it.iExp)
i2p::data::netdb.RequestDestination (it.iKey);
i2p::data::netdb.RequestDestination (it.iH);
}
}
@ -961,7 +961,8 @@ namespace transport
{
i2p::data::RouterInfo::Introducer introducer;
introducer.iTag = it->GetRelayTag ();
introducer.iKey = it->GetRemoteIdentity ()->GetIdentHash ();
introducer.iH = it->GetRemoteIdentity ()->GetIdentHash ();
introducer.isH = true;
introducer.iExp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION;
excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ());
if (i2p::context.AddSSU2Introducer (introducer, v4))