i2pd/Tunnel.h

309 lines
10 KiB
C
Raw Normal View History

2013-12-07 00:02:49 +00:00
#ifndef TUNNEL_H__
#define TUNNEL_H__
#include <inttypes.h>
#include <map>
2016-03-02 01:48:56 +00:00
#include <unordered_map>
2013-12-07 00:02:49 +00:00
#include <list>
2014-01-20 23:37:51 +00:00
#include <vector>
2013-12-07 00:02:49 +00:00
#include <string>
#include <thread>
2014-04-03 16:19:12 +00:00
#include <mutex>
2015-01-20 03:28:13 +00:00
#include <memory>
2013-12-07 00:02:49 +00:00
#include "Queue.h"
2015-11-03 14:15:49 +00:00
#include "Crypto.h"
2013-12-07 00:02:49 +00:00
#include "TunnelConfig.h"
2014-03-14 16:35:02 +00:00
#include "TunnelPool.h"
2013-12-07 00:02:49 +00:00
#include "TransitTunnel.h"
#include "TunnelEndpoint.h"
#include "TunnelGateway.h"
#include "TunnelBase.h"
#include "I2NPProtocol.h"
2016-10-20 16:14:32 +00:00
#include "Event.h"
2013-12-07 00:02:49 +00:00
namespace i2p
{
namespace tunnel
2016-10-20 16:14:32 +00:00
{
template<typename TunnelT>
static void EmitTunnelEvent(const std::string & ev, const TunnelT & t)
{
#ifdef WITH_EVENTS
EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}});
2016-11-01 14:46:07 +00:00
#else
(void) ev;
(void) t;
#endif
2016-10-20 16:14:32 +00:00
}
template<typename TunnelT, typename T>
static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val)
{
#ifdef WITH_EVENTS
EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}, {"value", std::to_string(val)}, {"inbound", std::to_string(t->IsInbound())}});
2016-11-01 14:46:07 +00:00
#else
(void) ev;
(void) t;
(void) val;
2016-10-20 16:14:32 +00:00
#endif
}
template<typename TunnelT>
static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const std::string & val)
{
#ifdef WITH_EVENTS
EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}, {"value", val}, {"inbound", std::to_string(t->IsInbound())}});
2016-11-01 14:46:07 +00:00
#else
(void) ev;
(void) t;
(void) val;
2016-10-20 16:14:32 +00:00
#endif
}
const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes
2014-08-26 14:31:32 +00:00
const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
2015-04-17 15:36:42 +00:00
const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes
2014-09-26 14:15:34 +00:00
const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds
const int STANDARD_NUM_RECORDS = 5; // in VariableTunnelBuild message
2014-07-27 00:56:42 +00:00
enum TunnelState
{
eTunnelStatePending,
2014-09-26 14:15:34 +00:00
eTunnelStateBuildReplyReceived,
eTunnelStateBuildFailed,
2014-07-27 00:56:42 +00:00
eTunnelStateEstablished,
eTunnelStateTestFailed,
2014-08-26 14:31:32 +00:00
eTunnelStateFailed,
eTunnelStateExpiring
2014-07-27 00:56:42 +00:00
};
2016-11-15 15:20:09 +00:00
2013-12-07 00:02:49 +00:00
class OutboundTunnel;
class InboundTunnel;
class Tunnel: public TunnelBase
{
2015-11-03 14:15:49 +00:00
struct TunnelHop
{
std::shared_ptr<const i2p::data::IdentityEx> ident;
i2p::crypto::TunnelDecryption decryption;
};
2013-12-07 00:02:49 +00:00
public:
2015-05-06 20:17:48 +00:00
Tunnel (std::shared_ptr<const TunnelConfig> config);
2013-12-07 00:02:49 +00:00
~Tunnel ();
2015-01-27 19:55:46 +00:00
void Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
2013-12-07 00:02:49 +00:00
2015-05-06 20:17:48 +00:00
std::shared_ptr<const TunnelConfig> GetTunnelConfig () const { return m_Config; }
2015-11-03 14:15:49 +00:00
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const;
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const;
2014-07-27 00:56:42 +00:00
TunnelState GetState () const { return m_State; };
2016-11-01 14:26:40 +00:00
void SetState (TunnelState state);
2014-07-27 00:56:42 +00:00
bool IsEstablished () const { return m_State == eTunnelStateEstablished; };
bool IsFailed () const { return m_State == eTunnelStateFailed; };
2015-04-17 15:36:42 +00:00
bool IsRecreated () const { return m_IsRecreated; };
void SetIsRecreated () { m_IsRecreated = true; };
2016-11-01 14:46:07 +00:00
virtual bool IsInbound() const = 0;
2015-01-20 03:28:13 +00:00
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; };
2014-03-14 16:35:02 +00:00
2013-12-07 00:02:49 +00:00
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
2016-03-03 03:41:53 +00:00
2016-06-01 00:00:00 +00:00
virtual void Print (std::stringstream&) const {};
2013-12-07 00:02:49 +00:00
// implements TunnelBase
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
void EncryptTunnelMsg (std::shared_ptr<const I2NPMessage> in, std::shared_ptr<I2NPMessage> out);
2015-12-10 00:07:12 +00:00
/** @brief add latency sample */
void AddLatencySample(const uint64_t ms) { m_Latency = (m_Latency + ms) >> 1; }
/** @brief get this tunnel's estimated latency */
uint64_t GetMeanLatency() const { return m_Latency; }
/** @breif return true if this tunnel's latency fits in range [lowerbound, upperbound] */
bool LatencyFitsRange(uint64_t lowerbound, uint64_t upperbound) const;
2016-11-15 15:20:09 +00:00
bool LatencyIsKnown() const { return m_Latency > 0; }
2015-12-10 00:07:12 +00:00
protected:
void PrintHops (std::stringstream& s) const;
2013-12-07 00:02:49 +00:00
private:
2015-05-06 20:17:48 +00:00
std::shared_ptr<const TunnelConfig> m_Config;
2015-11-03 14:15:49 +00:00
std::vector<std::unique_ptr<TunnelHop> > m_Hops;
2015-01-20 03:28:13 +00:00
std::shared_ptr<TunnelPool> m_Pool; // pool, tunnel belongs to, or null
2014-07-27 00:56:42 +00:00
TunnelState m_State;
2015-04-17 15:36:42 +00:00
bool m_IsRecreated;
uint64_t m_Latency; // in milliseconds
2013-12-07 00:02:49 +00:00
};
class OutboundTunnel: public Tunnel
{
public:
2015-11-03 14:15:49 +00:00
OutboundTunnel (std::shared_ptr<const TunnelConfig> config):
Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {};
2013-12-07 00:02:49 +00:00
2015-06-22 02:29:50 +00:00
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
2016-03-03 21:24:13 +00:00
virtual void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
2015-11-03 14:15:49 +00:00
const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; };
2016-03-03 21:24:13 +00:00
virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); };
2015-12-09 23:01:42 +00:00
void Print (std::stringstream& s) const;
2015-11-03 14:15:49 +00:00
2014-01-04 03:56:28 +00:00
// implements TunnelBase
void HandleTunnelDataMsg (std::shared_ptr<const i2p::I2NPMessage> tunnelMsg);
2016-11-01 14:46:07 +00:00
bool IsInbound() const { return false; }
2013-12-07 00:02:49 +00:00
private:
2014-04-03 16:19:12 +00:00
std::mutex m_SendMutex;
2013-12-07 00:02:49 +00:00
TunnelGateway m_Gateway;
2015-11-03 14:15:49 +00:00
i2p::data::IdentHash m_EndpointIdentHash;
2013-12-07 00:02:49 +00:00
};
2016-03-03 03:41:53 +00:00
2015-02-05 23:53:43 +00:00
class InboundTunnel: public Tunnel, public std::enable_shared_from_this<InboundTunnel>
2013-12-07 00:02:49 +00:00
{
public:
2015-05-06 20:17:48 +00:00
InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
void HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg);
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
2015-12-09 23:01:42 +00:00
void Print (std::stringstream& s) const;
2016-11-01 14:46:07 +00:00
bool IsInbound() const { return true; }
// override TunnelBase
void Cleanup () { m_Endpoint.Cleanup (); };
private:
2013-12-07 00:02:49 +00:00
TunnelEndpoint m_Endpoint;
};
2016-03-03 03:41:53 +00:00
class ZeroHopsInboundTunnel: public InboundTunnel
{
public:
2013-12-07 00:02:49 +00:00
2016-03-03 03:41:53 +00:00
ZeroHopsInboundTunnel ();
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
void Print (std::stringstream& s) const;
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
private:
size_t m_NumReceivedBytes;
2016-03-03 03:41:53 +00:00
};
2013-12-07 00:02:49 +00:00
2016-03-03 21:24:13 +00:00
class ZeroHopsOutboundTunnel: public OutboundTunnel
{
public:
ZeroHopsOutboundTunnel ();
void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs);
void Print (std::stringstream& s) const;
size_t GetNumSentBytes () const { return m_NumSentBytes; };
private:
size_t m_NumSentBytes;
};
2013-12-07 00:02:49 +00:00
class Tunnels
{
public:
Tunnels ();
~Tunnels ();
void Start ();
2014-03-15 00:24:12 +00:00
void Stop ();
2013-12-07 00:02:49 +00:00
2015-01-27 19:55:46 +00:00
std::shared_ptr<InboundTunnel> GetPendingInboundTunnel (uint32_t replyMsgID);
std::shared_ptr<OutboundTunnel> GetPendingOutboundTunnel (uint32_t replyMsgID);
std::shared_ptr<InboundTunnel> GetNextInboundTunnel ();
std::shared_ptr<OutboundTunnel> GetNextOutboundTunnel ();
2015-01-20 03:28:13 +00:00
std::shared_ptr<TunnelPool> GetExploratoryPool () const { return m_ExploratoryPool; };
2016-03-02 01:48:56 +00:00
std::shared_ptr<TunnelBase> GetTunnel (uint32_t tunnelID);
int GetTransitTunnelsExpirationTimeout ();
2016-03-01 20:22:36 +00:00
void AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
2015-01-27 19:55:46 +00:00
void AddOutboundTunnel (std::shared_ptr<OutboundTunnel> newTunnel);
void AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel);
std::shared_ptr<InboundTunnel> CreateInboundTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel);
std::shared_ptr<OutboundTunnel> CreateOutboundTunnel (std::shared_ptr<TunnelConfig> config);
void PostTunnelData (std::shared_ptr<I2NPMessage> msg);
void PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
2015-01-27 19:55:46 +00:00
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel);
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> tunnel);
std::shared_ptr<TunnelPool> CreateTunnelPool (int numInboundHops,
int numOuboundHops, int numInboundTunnels, int numOutboundTunnels);
2015-01-20 03:28:13 +00:00
void DeleteTunnelPool (std::shared_ptr<TunnelPool> pool);
void StopTunnelPool (std::shared_ptr<TunnelPool> pool);
2013-12-07 00:02:49 +00:00
private:
template<class TTunnel>
std::shared_ptr<TTunnel> CreateTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
template<class TTunnel>
2015-01-27 19:55:46 +00:00
std::shared_ptr<TTunnel> GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels);
2016-03-01 20:22:36 +00:00
void HandleTunnelGatewayMsg (std::shared_ptr<TunnelBase> tunnel, std::shared_ptr<I2NPMessage> msg);
2013-12-07 00:02:49 +00:00
void Run ();
void ManageTunnels ();
void ManageOutboundTunnels ();
void ManageInboundTunnels ();
2014-01-04 03:56:28 +00:00
void ManageTransitTunnels ();
2014-10-06 16:50:36 +00:00
void ManagePendingTunnels ();
template<class PendingTunnels>
void ManagePendingTunnels (PendingTunnels& pendingTunnels);
2014-03-15 00:24:12 +00:00
void ManageTunnelPools ();
2013-12-07 00:02:49 +00:00
std::shared_ptr<ZeroHopsInboundTunnel> CreateZeroHopsInboundTunnel ();
std::shared_ptr<ZeroHopsOutboundTunnel> CreateZeroHopsOutboundTunnel ();
2016-03-03 21:24:13 +00:00
2013-12-07 00:02:49 +00:00
private:
bool m_IsRunning;
std::thread * m_Thread;
2015-01-27 19:55:46 +00:00
std::map<uint32_t, std::shared_ptr<InboundTunnel> > m_PendingInboundTunnels; // by replyMsgID
std::map<uint32_t, std::shared_ptr<OutboundTunnel> > m_PendingOutboundTunnels; // by replyMsgID
std::list<std::shared_ptr<InboundTunnel> > m_InboundTunnels;
2015-01-27 19:55:46 +00:00
std::list<std::shared_ptr<OutboundTunnel> > m_OutboundTunnels;
2016-03-02 01:48:56 +00:00
std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels;
std::unordered_map<uint32_t, std::shared_ptr<TunnelBase> > m_Tunnels; // tunnelID->tunnel known by this id
2014-10-05 15:01:12 +00:00
std::mutex m_PoolsMutex;
2015-01-20 03:28:13 +00:00
std::list<std::shared_ptr<TunnelPool>> m_Pools;
std::shared_ptr<TunnelPool> m_ExploratoryPool;
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue;
2016-08-05 18:23:54 +00:00
2015-02-28 12:59:34 +00:00
// some stats
int m_NumSuccesiveTunnelCreations, m_NumFailedTunnelCreations;
2013-12-07 00:02:49 +00:00
public:
// for HTTP only
const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; };
const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; };
2013-12-10 13:10:49 +00:00
const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; };
size_t CountTransitTunnels() const;
size_t CountInboundTunnels() const;
size_t CountOutboundTunnels() const;
2015-02-03 21:45:19 +00:00
int GetQueueSize () { return m_Queue.GetSize (); };
2015-02-28 12:59:34 +00:00
int GetTunnelCreationSuccessRate () const // in percents
{
int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations;
return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0;
}
2013-12-07 00:02:49 +00:00
};
extern Tunnels tunnels;
}
}
#endif