i2pd/libi2pd/RouterInfo.h

388 lines
14 KiB
C
Raw Normal View History

/*
2024-02-21 17:37:33 +00:00
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
2013-10-27 15:28:23 +00:00
#ifndef ROUTER_INFO_H__
#define ROUTER_INFO_H__
#include <inttypes.h>
#include <string>
#include <map>
#include <vector>
2021-12-30 20:16:13 +00:00
#include <array>
2013-10-27 15:28:23 +00:00
#include <iostream>
#include <boost/asio.hpp>
2018-01-06 03:48:51 +00:00
#include <boost/shared_ptr.hpp>
2014-01-10 03:26:30 +00:00
#include "Identity.h"
2015-03-24 16:47:57 +00:00
#include "Profiling.h"
2022-03-24 19:50:20 +00:00
#include "Family.h"
2013-10-27 15:28:23 +00:00
namespace i2p
{
namespace data
2014-09-02 20:11:31 +00:00
{
2016-02-21 01:20:19 +00:00
const char ROUTER_INFO_PROPERTY_LEASESETS[] = "netdb.knownLeaseSets";
2018-01-06 03:48:51 +00:00
const char ROUTER_INFO_PROPERTY_ROUTERS[] = "netdb.knownRouters";
2016-02-21 01:20:19 +00:00
const char ROUTER_INFO_PROPERTY_NETID[] = "netId";
const char ROUTER_INFO_PROPERTY_VERSION[] = "router.version";
2018-01-06 03:48:51 +00:00
const char ROUTER_INFO_PROPERTY_FAMILY[] = "family";
2016-02-21 01:20:19 +00:00
const char ROUTER_INFO_PROPERTY_FAMILY_SIG[] = "family.sig";
2018-01-06 03:48:51 +00:00
2014-09-02 20:11:31 +00:00
const char CAPS_FLAG_FLOODFILL = 'f';
const char CAPS_FLAG_HIDDEN = 'H';
const char CAPS_FLAG_REACHABLE = 'R';
2018-01-06 03:48:51 +00:00
const char CAPS_FLAG_UNREACHABLE = 'U';
/* bandwidth flags */
const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */
const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */
2024-02-21 17:37:33 +00:00
const char CAPS_FLAG_LOW_BANDWIDTH3 = 'M'; /* 48-64 KBps */
const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'N'; /* 64-128 KBps */
const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'O'; /* 128-256 KBps */
2023-10-15 12:31:55 +00:00
const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */
const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */
// bandwidth limits in kBps
const uint32_t LOW_BANDWIDTH_LIMIT = 48;
const uint32_t HIGH_BANDWIDTH_LIMIT = 256;
const uint32_t EXTRA_BANDWIDTH_LIMIT = 2048;
2023-03-04 01:21:56 +00:00
// congesion flags
2023-03-04 20:46:44 +00:00
const char CAPS_FLAG_MEDIUM_CONGESTION = 'D';
const char CAPS_FLAG_HIGH_CONGESTION = 'E';
const char CAPS_FLAG_REJECT_ALL_CONGESTION = 'G';
2023-03-04 01:21:56 +00:00
2021-02-23 03:53:25 +00:00
const char CAPS_FLAG_V4 = '4';
const char CAPS_FLAG_V6 = '6';
2022-11-23 20:45:00 +00:00
const char CAPS_FLAG_SSU2_TESTING = 'B';
const char CAPS_FLAG_SSU2_INTRODUCER = 'C';
2014-09-02 20:11:31 +00:00
2021-03-01 16:09:25 +00:00
const uint8_t COST_NTCP2_PUBLISHED = 3;
const uint8_t COST_NTCP2_NON_PUBLISHED = 14;
2022-04-02 18:32:26 +00:00
const uint8_t COST_SSU2_DIRECT = 8;
2022-03-13 02:40:12 +00:00
const uint8_t COST_SSU2_NON_PUBLISHED = 15;
2022-04-09 18:40:38 +00:00
const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later
2023-03-07 00:48:04 +00:00
const int HIGH_CONGESTION_INTERVAL = 15*60; // in seconds, 15 minutes
const int INTRODUCER_UPDATE_INTERVAL = 20*60*1000; // in milliseconds, 20 minutes
2023-03-04 01:21:56 +00:00
2013-11-24 23:10:27 +00:00
class RouterInfo: public RoutingDestination
2013-10-27 15:28:23 +00:00
{
public:
enum SupportedTransportsIdx
{
eNTCP2V4Idx = 0,
eNTCP2V6Idx,
eSSU2V4Idx,
eSSU2V6Idx,
eNTCP2V6MeshIdx,
eNumTransports
};
#define TransportBit(tr) e##tr = (1 << e##tr##Idx)
2021-06-02 16:55:08 +00:00
enum SupportedTransports
2018-01-06 03:48:51 +00:00
{
TransportBit(NTCP2V4), // 0x01
TransportBit(NTCP2V6), // 0x02
TransportBit(SSU2V4), // 0x04
TransportBit(SSU2V6), // 0x08
TransportBit(NTCP2V6Mesh), // 0x10
eAllTransports = 0xFF
};
typedef uint8_t CompatibleTransports;
2014-03-19 16:02:51 +00:00
enum Caps
{
eFloodfill = 0x01,
2014-03-19 19:58:57 +00:00
eHighBandwidth = 0x02,
2016-01-03 03:17:04 +00:00
eExtraBandwidth = 0x04,
eReachable = 0x08,
2021-02-23 03:53:25 +00:00
eHidden = 0x10,
eUnreachable = 0x20
2014-03-19 16:02:51 +00:00
};
2023-03-04 01:21:56 +00:00
enum Congestion
{
eLowCongestion = 0,
eMediumCongestion,
eHighCongestion,
eRejectAll
};
2021-02-23 03:53:25 +00:00
enum AddressCaps
{
eV4 = 0x01,
eV6 = 0x02,
eSSUTesting = 0x04,
eSSUIntroducer = 0x08
};
2013-10-27 15:28:23 +00:00
enum TransportStyle
{
eTransportUnknown = 0,
2022-11-23 20:45:00 +00:00
eTransportNTCP2,
2022-03-11 21:17:44 +00:00
eTransportSSU2
2013-10-27 15:28:23 +00:00
};
2018-01-06 03:48:51 +00:00
struct Introducer
2014-02-20 21:15:12 +00:00
{
2023-08-08 01:28:13 +00:00
Introducer (): iTag (0), iExp (0) { iH.Fill(0); };
2022-11-23 20:45:00 +00:00
IdentHash iH;
2014-02-20 21:15:12 +00:00
uint32_t iTag;
2017-05-24 16:49:36 +00:00
uint32_t iExp;
2014-02-20 21:15:12 +00:00
};
struct SSUExt
{
int mtu;
2018-01-06 03:48:51 +00:00
std::vector<Introducer> introducers;
};
2018-01-06 03:48:51 +00:00
2013-10-27 15:28:23 +00:00
struct Address
{
TransportStyle transportStyle;
2014-01-21 21:07:16 +00:00
boost::asio::ip::address host;
2022-02-06 15:17:35 +00:00
Tag<32> s, i; // keys, i is first 16 bytes for NTCP2 and 32 bytes intro key for SSU
int port;
2013-10-27 15:28:23 +00:00
uint64_t date;
2021-04-07 17:05:38 +00:00
uint8_t caps;
2021-04-06 01:45:48 +00:00
bool published = false;
std::unique_ptr<SSUExt> ssu; // not null for SSU
2018-01-06 03:48:51 +00:00
bool IsCompatible (const boost::asio::ip::address& other) const
{
2021-03-13 01:51:12 +00:00
return (IsV4 () && other.is_v4 ()) ||
(IsV6 () && other.is_v6 ());
2018-01-06 03:48:51 +00:00
}
2015-11-03 14:15:49 +00:00
bool operator==(const Address& other) const
{
return transportStyle == other.transportStyle &&
2018-08-26 13:40:27 +00:00
host == other.host && port == other.port;
2018-01-06 03:48:51 +00:00
}
2015-11-03 14:15:49 +00:00
bool operator!=(const Address& other) const
{
return !(*this == other);
2018-01-06 03:48:51 +00:00
}
2018-06-15 16:52:43 +00:00
2022-11-23 20:45:00 +00:00
bool IsNTCP2 () const { return transportStyle == eTransportNTCP2; };
bool IsSSU2 () const { return transportStyle == eTransportSSU2; };
2021-04-06 01:45:48 +00:00
bool IsPublishedNTCP2 () const { return IsNTCP2 () && published; };
bool IsReachableSSU () const { return (bool)ssu && (published || UsesIntroducer ()); };
bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); };
2021-02-23 02:04:26 +00:00
bool IsIntroducer () const { return caps & eSSUIntroducer; };
bool IsPeerTesting () const { return caps & eSSUTesting; };
2021-03-12 21:13:01 +00:00
2021-04-04 02:18:09 +00:00
bool IsV4 () const { return (caps & AddressCaps::eV4) || (host.is_v4 () && !host.is_unspecified ()); };
bool IsV6 () const { return (caps & AddressCaps::eV6) || (host.is_v6 () && !host.is_unspecified ()); };
2013-10-27 15:28:23 +00:00
};
class Buffer: public std::array<uint8_t, MAX_RI_BUFFER_SIZE>
{
public:
Buffer () = default;
Buffer (const uint8_t * buf, size_t len);
Buffer (const Buffer& other): Buffer (other.data (), other.m_BufferLen) {};
size_t GetBufferLen () const { return m_BufferLen; };
void SetBufferLen (size_t len) { m_BufferLen = len; };
private:
size_t m_BufferLen = 0;
};
typedef std::array<std::shared_ptr<Address>, eNumTransports> Addresses;
2016-07-13 16:56:23 +00:00
2014-07-23 14:56:41 +00:00
RouterInfo (const std::string& fullPath);
2013-10-27 15:28:23 +00:00
RouterInfo (const RouterInfo& ) = default;
2013-12-29 15:48:57 +00:00
RouterInfo& operator=(const RouterInfo& ) = default;
RouterInfo (std::shared_ptr<Buffer>&& buf, size_t len);
RouterInfo (const uint8_t * buf, size_t len);
2022-01-15 17:48:49 +00:00
virtual ~RouterInfo ();
2018-01-06 03:48:51 +00:00
2015-11-03 14:15:49 +00:00
std::shared_ptr<const IdentityEx> GetRouterIdentity () const { return m_RouterIdentity; };
void SetRouterIdentity (std::shared_ptr<const IdentityEx> identity);
2014-11-20 17:21:27 +00:00
std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); };
2013-11-29 12:52:09 +00:00
uint64_t GetTimestamp () const { return m_Timestamp; };
int GetVersion () const { return m_Version; };
virtual void SetProperty (const std::string& key, const std::string& value) {};
2022-01-16 00:26:11 +00:00
virtual void ClearProperties () {};
boost::shared_ptr<Addresses> GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr
std::shared_ptr<const Address> GetNTCP2V4Address () const;
std::shared_ptr<const Address> GetNTCP2V6Address () const;
std::shared_ptr<const Address> GetPublishedNTCP2V4Address () const;
std::shared_ptr<const Address> GetPublishedNTCP2V6Address () const;
2021-01-31 22:25:07 +00:00
std::shared_ptr<const Address> GetYggdrasilAddress () const;
2022-03-17 01:11:48 +00:00
std::shared_ptr<const Address> GetSSU2V4Address () const;
std::shared_ptr<const Address> GetSSU2V6Address () const;
2022-06-07 20:09:20 +00:00
std::shared_ptr<const Address> GetSSU2Address (bool v4) const;
2018-01-06 03:48:51 +00:00
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,int port, uint8_t caps); // non published
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
const boost::asio::ip::address& host, int port); // published
void RemoveNTCP2Address (bool v4);
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, int port, uint8_t caps); // non published
2022-03-29 17:56:56 +00:00
void AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
const boost::asio::ip::address& host, int port); // published
void RemoveSSU2Address (bool v4);
void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps
2021-06-02 16:55:08 +00:00
void UpdateSupportedTransports ();
void UpdateIntroducers (uint64_t ts); // ts in seconds
bool IsFloodfill () const { return m_IsFloodfill; };
void SetFloodfill () { m_IsFloodfill = true; };
void ResetFloodfill () { m_IsFloodfill = false; };
bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
2018-06-06 15:51:34 +00:00
bool IsNTCP2 (bool v4only = true) const;
2022-03-17 01:11:48 +00:00
bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; };
bool IsSSU2V4 () const { return m_SupportedTransports & eSSU2V4; };
bool IsSSU2V6 () const { return m_SupportedTransports & eSSU2V6; };
2022-11-23 20:45:00 +00:00
bool IsV6 () const { return m_SupportedTransports & (eNTCP2V6 | eSSU2V6); };
bool IsV4 () const { return m_SupportedTransports & (eNTCP2V4 | eSSU2V4); };
2022-03-17 01:11:48 +00:00
bool IsMesh () const { return m_SupportedTransports & eNTCP2V6Mesh; };
void EnableV6 ();
void DisableV6 ();
2016-03-24 22:44:41 +00:00
void EnableV4 ();
void DisableV4 ();
2021-01-31 22:25:07 +00:00
void EnableMesh ();
void DisableMesh ();
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
bool IsReachableFrom (const RouterInfo& other) const { return m_ReachableTransports & other.m_SupportedTransports; };
bool IsReachableBy (CompatibleTransports transports) const { return m_ReachableTransports & transports; };
CompatibleTransports GetCompatibleTransports (bool incoming) const { return incoming ? m_ReachableTransports : m_SupportedTransports; };
2024-04-19 23:12:29 +00:00
CompatibleTransports GetPublishedTransports () const { return m_PublishedTransports; };
bool HasValidAddresses () const { return m_SupportedTransports; };
2014-06-18 14:41:59 +00:00
bool IsHidden () const { return m_Caps & eHidden; };
bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; };
2018-01-06 03:48:51 +00:00
bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; };
2020-11-23 17:49:18 +00:00
bool IsEligibleFloodfill () const;
bool IsDeclaredFloodfill () const { return m_Caps & RouterInfo::eFloodfill; };
bool IsPublished (bool v4) const;
bool IsNAT2NATOnly (const RouterInfo& other) const; // only NAT-to-NAT connection is possible
2022-06-02 01:51:02 +00:00
bool IsSSU2PeerTesting (bool v4) const;
2022-07-19 22:38:58 +00:00
bool IsSSU2Introducer (bool v4) const;
bool IsHighCongestion (bool highBandwidth) const;
2018-01-06 03:48:51 +00:00
uint8_t GetCaps () const { return m_Caps; };
2022-01-15 23:54:02 +00:00
void SetCaps (uint8_t caps) { m_Caps = caps; };
2014-03-19 19:58:57 +00:00
2023-03-04 01:21:56 +00:00
Congestion GetCongestion () const { return m_Congestion; };
2018-01-06 03:48:51 +00:00
void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; };
2013-12-10 13:10:49 +00:00
bool IsUnreachable () const { return m_IsUnreachable; };
void ExcludeReachableTransports (CompatibleTransports transports) { m_ReachableTransports &= ~transports; };
2014-07-10 19:33:42 +00:00
const uint8_t * GetBuffer () const { return m_Buffer ? m_Buffer->data () : nullptr; };
2021-10-07 19:08:33 +00:00
const uint8_t * LoadBuffer (const std::string& fullPath); // load if necessary
size_t GetBufferLen () const { return m_Buffer ? m_Buffer->GetBufferLen () : 0; };
void DeleteBuffer () { m_Buffer = nullptr; };
std::shared_ptr<Buffer> GetSharedBuffer () const { return m_Buffer; };
std::shared_ptr<Buffer> CopyBuffer () const;
2013-11-20 12:46:09 +00:00
bool IsUpdated () const { return m_IsUpdated; };
2018-01-06 03:48:51 +00:00
void SetUpdated (bool updated) { m_IsUpdated = updated; };
bool SaveToFile (const std::string& fullPath);
static bool SaveToFile (const std::string& fullPath, std::shared_ptr<Buffer> buf);
std::shared_ptr<RouterProfile> GetProfile () const;
2023-02-11 21:22:02 +00:00
void DropProfile () { m_Profile = nullptr; };
bool HasProfile () const { return (bool)m_Profile; };
2018-01-06 03:48:51 +00:00
2023-02-12 23:02:16 +00:00
bool Update (const uint8_t * buf, size_t len);
2018-01-06 03:48:51 +00:00
bool IsNewer (const uint8_t * buf, size_t len) const;
2016-02-17 20:36:55 +00:00
/** return true if we are in a router family and the signature is valid */
2022-03-24 19:50:20 +00:00
bool IsFamily (FamilyID famid) const;
2018-01-06 03:48:51 +00:00
2013-11-24 23:10:27 +00:00
// implements RoutingDestination
2017-11-02 18:50:57 +00:00
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; };
void Encrypt (const uint8_t * data, uint8_t * encrypted) const;
bool IsDestination () const { return false; };
2022-01-15 17:48:49 +00:00
protected:
RouterInfo ();
uint8_t * GetBufferPointer (size_t offset = 0 ) { return m_Buffer->data () + offset; };
void UpdateBuffer (const uint8_t * buf, size_t len);
void SetBufferLen (size_t len) { if (m_Buffer) m_Buffer->SetBufferLen (len); };
2022-01-15 17:48:49 +00:00
void RefreshTimestamp ();
CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; };
void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; };
2023-03-07 00:48:04 +00:00
void SetCongestion (Congestion c) { m_Congestion = c; };
2013-10-27 15:28:23 +00:00
private:
2021-10-07 19:08:33 +00:00
bool LoadFile (const std::string& fullPath);
void ReadFromFile (const std::string& fullPath);
2013-10-27 15:28:23 +00:00
void ReadFromStream (std::istream& s);
void ReadFromBuffer (bool verifySignature);
2016-08-15 17:12:56 +00:00
size_t ReadString (char* str, size_t len, std::istream& s) const;
2021-02-23 03:53:25 +00:00
void ExtractCaps (const char * value);
uint8_t ExtractAddressCaps (const char * value) const;
void UpdateIntroducers (std::shared_ptr<Address> address, uint64_t ts);
2018-08-04 12:47:58 +00:00
template<typename Filter>
std::shared_ptr<const Address> GetAddress (Filter filter) const;
virtual std::shared_ptr<Buffer> NewBuffer () const;
virtual std::shared_ptr<Address> NewAddress () const;
virtual boost::shared_ptr<Addresses> NewAddresses () const;
2023-03-17 01:32:53 +00:00
virtual std::shared_ptr<IdentityEx> NewIdentity (const uint8_t * buf, size_t len) const;
2013-10-27 15:28:23 +00:00
private:
2022-03-24 19:50:20 +00:00
FamilyID m_FamilyID;
2015-11-03 14:15:49 +00:00
std::shared_ptr<const IdentityEx> m_RouterIdentity;
2021-12-30 20:16:13 +00:00
std::shared_ptr<Buffer> m_Buffer;
uint64_t m_Timestamp; // in milliseconds
2022-12-07 19:08:27 +00:00
boost::shared_ptr<Addresses> m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9
bool m_IsUpdated, m_IsUnreachable, m_IsFloodfill;
CompatibleTransports m_SupportedTransports, m_ReachableTransports, m_PublishedTransports;
uint8_t m_Caps;
int m_Version;
2023-03-04 01:21:56 +00:00
Congestion m_Congestion;
mutable std::shared_ptr<RouterProfile> m_Profile;
2018-01-06 03:48:51 +00:00
};
2022-01-15 17:48:49 +00:00
class LocalRouterInfo: public RouterInfo
{
public:
LocalRouterInfo () = default;
void CreateBuffer (const PrivateKeys& privateKeys);
2022-01-15 23:54:02 +00:00
void UpdateCaps (uint8_t caps);
2023-04-02 15:27:51 +00:00
bool UpdateCongestion (Congestion c); // returns true if updated
2022-01-15 23:54:02 +00:00
void SetProperty (const std::string& key, const std::string& value) override;
void DeleteProperty (const std::string& key);
std::string GetProperty (const std::string& key) const;
2022-01-16 00:26:11 +00:00
void ClearProperties () override { m_Properties.clear (); };
void UpdateFloodfillProperty (bool floodfill);
bool AddSSU2Introducer (const Introducer& introducer, bool v4);
bool RemoveSSU2Introducer (const IdentHash& h, bool v4);
2022-01-15 23:54:02 +00:00
private:
void WriteToStream (std::ostream& s) const;
void UpdateCapsProperty ();
void WriteString (const std::string& str, std::ostream& s) const;
std::shared_ptr<Buffer> NewBuffer () const override;
std::shared_ptr<Address> NewAddress () const override;
boost::shared_ptr<Addresses> NewAddresses () const override;
2023-03-17 01:32:53 +00:00
std::shared_ptr<IdentityEx> NewIdentity (const uint8_t * buf, size_t len) const override;
2022-01-15 23:54:02 +00:00
private:
std::map<std::string, std::string> m_Properties;
};
2018-01-06 03:48:51 +00:00
}
2013-10-27 15:28:23 +00:00
}
#endif