Browse Source

SSU2 only introducers

pull/1811/head
orignal 2 years ago
parent
commit
a298588943
  1. 9
      libi2pd/NetDb.cpp
  2. 1
      libi2pd/NetDb.hpp
  3. 199
      libi2pd/RouterInfo.cpp
  4. 14
      libi2pd/RouterInfo.h
  5. 9
      libi2pd/SSU2.cpp

9
libi2pd/NetDb.cpp

@ -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 std::shared_ptr<const RouterInfo> NetDb::GetRandomIntroducer (bool v4, const std::set<IdentHash>& excluded) const
{ {
return GetRandomRouter ( return GetRandomRouter (

1
libi2pd/NetDb.hpp

@ -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> 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> 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> 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> 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> 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; std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;

199
libi2pd/RouterInfo.cpp

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

14
libi2pd/RouterInfo.h

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

9
libi2pd/SSU2.cpp

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

Loading…
Cancel
Save