2020-05-22 13:18:41 +00:00
|
|
|
/*
|
2021-03-02 00:02:27 +00:00
|
|
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
2020-05-22 13:18:41 +00:00
|
|
|
*
|
|
|
|
* 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>
|
2016-07-14 18:10:38 +00:00
|
|
|
#include <list>
|
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"
|
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";
|
2020-05-20 18:59:18 +00:00
|
|
|
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';
|
2016-03-31 00:00:00 +00:00
|
|
|
/* bandwidth flags */
|
|
|
|
const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */
|
|
|
|
const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */
|
|
|
|
const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */
|
|
|
|
const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */
|
|
|
|
const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */
|
|
|
|
const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */
|
|
|
|
const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */
|
2018-01-06 03:48:51 +00:00
|
|
|
|
2021-02-23 03:53:25 +00:00
|
|
|
const char CAPS_FLAG_V4 = '4';
|
|
|
|
const char CAPS_FLAG_V6 = '6';
|
2014-09-02 20:11:31 +00:00
|
|
|
const char CAPS_FLAG_SSU_TESTING = 'B';
|
|
|
|
const char CAPS_FLAG_SSU_INTRODUCER = 'C';
|
|
|
|
|
2021-03-01 16:09:25 +00:00
|
|
|
const uint8_t COST_NTCP2_PUBLISHED = 3;
|
|
|
|
const uint8_t COST_NTCP2_NON_PUBLISHED = 14;
|
|
|
|
const uint8_t COST_SSU_DIRECT = 9;
|
|
|
|
const uint8_t COST_SSU_THROUGH_INTRODUCERS = 11;
|
|
|
|
|
2019-05-23 13:32:07 +00:00
|
|
|
const int MAX_RI_BUFFER_SIZE = 2048; // if RouterInfo exceeds 2048 we consider it as malformed, might be changed later
|
2013-11-24 23:10:27 +00:00
|
|
|
class RouterInfo: public RoutingDestination
|
2013-10-27 15:28:23 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2014-01-26 02:47:01 +00:00
|
|
|
enum SupportedTranports
|
2018-01-06 03:48:51 +00:00
|
|
|
{
|
2021-01-30 21:50:53 +00:00
|
|
|
eNTCP2V4 = 0x01,
|
|
|
|
eNTCP2V6 = 0x02,
|
2014-03-19 16:02:51 +00:00
|
|
|
eSSUV4 = 0x04,
|
2021-01-30 23:32:17 +00:00
|
|
|
eSSUV6 = 0x08,
|
|
|
|
eNTCP2V6Mesh = 0x10
|
2014-01-26 02:47:01 +00:00
|
|
|
};
|
2018-01-06 03:48:51 +00:00
|
|
|
|
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
|
|
|
};
|
|
|
|
|
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,
|
|
|
|
eTransportNTCP,
|
|
|
|
eTransportSSU
|
|
|
|
};
|
|
|
|
|
2015-11-03 14:15:49 +00:00
|
|
|
typedef Tag<32> IntroKey; // should be castable to MacKey and AESKey
|
2018-01-06 03:48:51 +00:00
|
|
|
struct Introducer
|
2014-02-20 21:15:12 +00:00
|
|
|
{
|
2017-05-24 16:49:36 +00:00
|
|
|
Introducer (): iExp (0) {};
|
2014-02-20 21:15:12 +00:00
|
|
|
boost::asio::ip::address iHost;
|
|
|
|
int iPort;
|
2015-11-03 14:15:49 +00:00
|
|
|
IntroKey iKey;
|
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
|
|
|
};
|
|
|
|
|
2017-01-02 21:36:59 +00:00
|
|
|
struct SSUExt
|
|
|
|
{
|
|
|
|
int mtu;
|
|
|
|
IntroKey key; // intro key for SSU
|
2018-01-06 03:48:51 +00:00
|
|
|
std::vector<Introducer> introducers;
|
2017-01-02 21:36:59 +00:00
|
|
|
};
|
2018-01-06 03:48:51 +00:00
|
|
|
|
2018-06-06 15:51:34 +00:00
|
|
|
struct NTCP2Ext
|
|
|
|
{
|
2018-06-15 16:52:43 +00:00
|
|
|
Tag<32> staticKey;
|
|
|
|
Tag<16> iv;
|
2018-07-18 18:19:12 +00:00
|
|
|
bool isPublished = false;
|
2018-06-06 15:51:34 +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;
|
2017-01-02 21:36:59 +00:00
|
|
|
int port;
|
2013-10-27 15:28:23 +00:00
|
|
|
uint64_t date;
|
2021-02-23 02:04:26 +00:00
|
|
|
uint8_t cost, caps;
|
2017-01-02 21:36:59 +00:00
|
|
|
std::unique_ptr<SSUExt> ssu; // not null for SSU
|
2018-06-06 15:51:34 +00:00
|
|
|
std::unique_ptr<NTCP2Ext> ntcp2; // not null for NTCP2
|
2014-10-27 01:32:06 +00:00
|
|
|
|
2018-01-06 03:48:51 +00:00
|
|
|
bool IsCompatible (const boost::asio::ip::address& other) const
|
2014-10-27 01:32:06 +00:00
|
|
|
{
|
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
|
|
|
|
{
|
2018-08-26 13:40:27 +00:00
|
|
|
return transportStyle == other.transportStyle && IsNTCP2 () == other.IsNTCP2 () &&
|
|
|
|
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
|
|
|
|
|
|
|
bool IsNTCP2 () const { return (bool)ntcp2; };
|
2018-07-18 18:19:12 +00:00
|
|
|
bool IsPublishedNTCP2 () const { return IsNTCP2 () && ntcp2->isPublished; };
|
2021-03-02 00:02:27 +00:00
|
|
|
bool IsReachableSSU () const { return (bool)ssu && (!host.is_unspecified () || !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
|
|
|
|
|
|
|
bool IsV4 () const { return (caps & AddressCaps::eV4) || host.is_v4 (); };
|
|
|
|
bool IsV6 () const { return (caps & AddressCaps::eV6) || host.is_v6 (); };
|
2013-10-27 15:28:23 +00:00
|
|
|
};
|
2018-01-06 03:48:51 +00:00
|
|
|
typedef std::list<std::shared_ptr<Address> > Addresses;
|
2016-07-13 16:56:23 +00:00
|
|
|
|
2016-07-14 02:33:39 +00:00
|
|
|
RouterInfo ();
|
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;
|
2013-10-27 15:28:23 +00:00
|
|
|
RouterInfo (const uint8_t * buf, int len);
|
2014-07-22 02:59:57 +00:00
|
|
|
~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; };
|
2020-05-20 18:59:18 +00:00
|
|
|
int GetVersion () const { return m_Version; };
|
2016-07-13 16:56:23 +00:00
|
|
|
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
|
2021-02-17 23:46:41 +00:00
|
|
|
std::shared_ptr<const Address> GetNTCP2AddressWithStaticKey (const uint8_t * key) const;
|
2021-01-18 23:58:16 +00:00
|
|
|
std::shared_ptr<const Address> GetPublishedNTCP2V4Address () const;
|
|
|
|
std::shared_ptr<const Address> GetPublishedNTCP2V6Address () const;
|
2016-03-21 17:02:51 +00:00
|
|
|
std::shared_ptr<const Address> GetSSUAddress (bool v4only = true) const;
|
|
|
|
std::shared_ptr<const Address> GetSSUV6Address () const;
|
2021-01-31 22:25:07 +00:00
|
|
|
std::shared_ptr<const Address> GetYggdrasilAddress () const;
|
2018-01-06 03:48:51 +00:00
|
|
|
|
2014-10-30 14:07:39 +00:00
|
|
|
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
|
2018-08-27 20:01:47 +00:00
|
|
|
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0);
|
2015-11-03 14:15:49 +00:00
|
|
|
bool AddIntroducer (const Introducer& introducer);
|
2014-09-07 00:43:20 +00:00
|
|
|
bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
|
2015-03-18 19:06:15 +00:00
|
|
|
void SetProperty (const std::string& key, const std::string& value); // called from RouterContext only
|
|
|
|
void DeleteProperty (const std::string& key); // called from RouterContext only
|
2016-04-28 22:16:11 +00:00
|
|
|
std::string GetProperty (const std::string& key) const; // called from RouterContext only
|
2015-03-12 20:26:08 +00:00
|
|
|
void ClearProperties () { m_Properties.clear (); };
|
2021-03-08 20:57:05 +00:00
|
|
|
void SetUnreachableAddressesTransportCaps (uint8_t transports); // bitmask of AddressCaps
|
2016-02-22 15:27:43 +00:00
|
|
|
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
|
|
|
|
bool IsReachable () const { return m_Caps & Caps::eReachable; };
|
2014-02-09 02:06:40 +00:00
|
|
|
bool IsSSU (bool v4only = true) const;
|
2019-05-23 19:59:44 +00:00
|
|
|
bool IsSSUV6 () const;
|
2018-06-06 15:51:34 +00:00
|
|
|
bool IsNTCP2 (bool v4only = true) const;
|
2021-02-04 01:09:43 +00:00
|
|
|
bool IsNTCP2V6 () const;
|
2014-10-27 01:32:06 +00:00
|
|
|
bool IsV6 () const;
|
2016-03-24 22:44:41 +00:00
|
|
|
bool IsV4 () const;
|
2021-01-31 22:25:07 +00:00
|
|
|
bool IsMesh () const;
|
2014-10-27 01:32:06 +00:00
|
|
|
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 ();
|
2021-03-02 00:02:27 +00:00
|
|
|
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
|
|
|
bool IsReachableFrom (const RouterInfo& other) const;
|
2019-02-24 23:26:58 +00:00
|
|
|
bool HasValidAddresses () const { return m_SupportedTransports; };
|
2014-02-21 21:13:36 +00:00
|
|
|
bool UsesIntroducer () const;
|
2014-06-18 14:41:59 +00:00
|
|
|
bool IsHidden () const { return m_Caps & eHidden; };
|
2015-03-18 17:07:11 +00:00
|
|
|
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;
|
2021-02-23 02:04:26 +00:00
|
|
|
bool IsPeerTesting (bool v4only) const;
|
|
|
|
bool IsIntroducer () const;
|
2020-11-21 19:27:08 +00:00
|
|
|
|
2018-01-06 03:48:51 +00:00
|
|
|
uint8_t GetCaps () const { return m_Caps; };
|
2014-09-02 20:11:31 +00:00
|
|
|
void SetCaps (uint8_t caps);
|
2014-09-01 21:34:20 +00:00
|
|
|
void SetCaps (const char * caps);
|
2014-03-19 19:58:57 +00:00
|
|
|
|
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; };
|
2014-07-10 19:33:42 +00:00
|
|
|
|
|
|
|
const uint8_t * GetBuffer () const { return m_Buffer; };
|
2014-07-24 19:59:00 +00:00
|
|
|
const uint8_t * LoadBuffer (); // load if necessary
|
2018-01-06 03:48:51 +00:00
|
|
|
int GetBufferLen () const { return m_BufferLen; };
|
2014-08-26 02:47:12 +00:00
|
|
|
void CreateBuffer (const PrivateKeys& privateKeys);
|
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; };
|
2016-04-05 00:00:00 +00:00
|
|
|
bool SaveToFile (const std::string& fullPath);
|
2013-11-24 23:10:27 +00:00
|
|
|
|
2015-03-24 22:48:16 +00:00
|
|
|
std::shared_ptr<RouterProfile> GetProfile () const;
|
2016-12-31 01:59:18 +00:00
|
|
|
void SaveProfile () { if (m_Profile) m_Profile->Save (GetIdentHash ()); };
|
2018-01-06 03:48:51 +00:00
|
|
|
|
2019-05-23 13:32:07 +00:00
|
|
|
void Update (const uint8_t * buf, size_t len);
|
2015-04-07 20:26:35 +00:00
|
|
|
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
|
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
|
|
|
|
2020-03-01 10:25:50 +00:00
|
|
|
/** return true if we are in a router family and the signature is valid */
|
|
|
|
bool IsFamily(const std::string & fam) 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; };
|
2018-01-06 03:48:51 +00:00
|
|
|
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const;
|
2017-11-07 20:05:22 +00:00
|
|
|
|
2013-11-27 01:59:25 +00:00
|
|
|
bool IsDestination () const { return false; };
|
2014-07-22 02:59:57 +00:00
|
|
|
|
2013-10-27 15:28:23 +00:00
|
|
|
private:
|
|
|
|
|
2014-07-23 14:56:41 +00:00
|
|
|
bool LoadFile ();
|
|
|
|
void ReadFromFile ();
|
2013-10-27 15:28:23 +00:00
|
|
|
void ReadFromStream (std::istream& s);
|
2014-10-29 20:03:07 +00:00
|
|
|
void ReadFromBuffer (bool verifySignature);
|
2016-08-07 21:52:18 +00:00
|
|
|
void WriteToStream (std::ostream& s) const;
|
2016-08-15 17:12:56 +00:00
|
|
|
size_t ReadString (char* str, size_t len, std::istream& s) const;
|
|
|
|
void WriteString (const std::string& str, std::ostream& s) const;
|
2021-02-23 03:53:25 +00:00
|
|
|
void ExtractCaps (const char * value);
|
|
|
|
uint8_t ExtractAddressCaps (const char * value) const;
|
2018-08-04 12:47:58 +00:00
|
|
|
template<typename Filter>
|
|
|
|
std::shared_ptr<const Address> GetAddress (Filter filter) const;
|
2018-01-06 03:48:51 +00:00
|
|
|
void UpdateCapsProperty ();
|
2014-09-02 20:11:31 +00:00
|
|
|
|
2013-10-27 15:28:23 +00:00
|
|
|
private:
|
|
|
|
|
2016-02-19 21:37:41 +00:00
|
|
|
std::string m_FullPath, m_Family;
|
2015-11-03 14:15:49 +00:00
|
|
|
std::shared_ptr<const IdentityEx> m_RouterIdentity;
|
2014-07-22 02:59:57 +00:00
|
|
|
uint8_t * m_Buffer;
|
2016-02-02 16:55:38 +00:00
|
|
|
size_t m_BufferLen;
|
2013-10-27 15:28:23 +00:00
|
|
|
uint64_t m_Timestamp;
|
2018-01-06 03:48:51 +00:00
|
|
|
boost::shared_ptr<Addresses> m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9
|
2013-10-27 15:28:23 +00:00
|
|
|
std::map<std::string, std::string> m_Properties;
|
2013-12-10 13:10:49 +00:00
|
|
|
bool m_IsUpdated, m_IsUnreachable;
|
2014-03-19 16:02:51 +00:00
|
|
|
uint8_t m_SupportedTransports, m_Caps;
|
2020-05-20 18:59:18 +00:00
|
|
|
int m_Version;
|
2015-03-24 22:48:16 +00:00
|
|
|
mutable std::shared_ptr<RouterProfile> m_Profile;
|
2018-01-06 03:48:51 +00:00
|
|
|
};
|
|
|
|
}
|
2013-10-27 15:28:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|