Browse Source

Inroduced IdentHash

pull/6/head
orignal 11 years ago
parent
commit
885e996a8a
  1. 36
      LeaseSet.h
  2. 58
      NTCPSession.cpp
  3. 28
      NTCPSession.h
  4. 17
      NetDb.cpp
  5. 6
      NetDb.h
  6. 5
      RouterInfo.h
  7. 89
      TransitTunnel.cpp
  8. 64
      TransitTunnel.h
  9. 27
      Transports.cpp
  10. 11
      Transports.h
  11. 11
      TunnelGateway.cpp
  12. 12
      TunnelGateway.h

36
LeaseSet.h

@ -2,12 +2,14 @@
#define LEASE_SET_H__ #define LEASE_SET_H__
#include <inttypes.h> #include <inttypes.h>
#include <string.h>
#include <list> #include <list>
namespace i2p namespace i2p
{ {
namespace data namespace data
{ {
#pragma pack(1) #pragma pack(1)
struct Lease struct Lease
{ {
@ -17,10 +19,36 @@ namespace data
}; };
#pragma pack() #pragma pack()
class IdentHash
{
public:
IdentHash (const uint8_t * hash) { memcpy (m_Hash, hash, 32); };
IdentHash (const IdentHash& ) = default;
IdentHash (IdentHash&& ) = default;
IdentHash () = default;
IdentHash& operator= (const IdentHash& ) = default;
IdentHash& operator= (IdentHash&& ) = default;
uint8_t * operator()() { return m_Hash; };
const uint8_t * operator()() const { return m_Hash; };
operator uint8_t * () { return m_Hash; };
operator const uint8_t * () const { return m_Hash; };
bool operator== (const IdentHash& other) const { return !memcmp (m_Hash, other.m_Hash, 32); };
bool operator< (const IdentHash& other) const { return memcmp (m_Hash, other.m_Hash, 32) < 0; };
private:
uint8_t m_Hash[32];
};
class RoutingDestination // TODO: move to separate file later class RoutingDestination // TODO: move to separate file later
{ {
public: public:
virtual const uint8_t * GetIdentHash () const = 0; virtual const IdentHash& GetIdentHash () const = 0;
virtual const uint8_t * GetEncryptionPublicKey () const = 0; virtual const uint8_t * GetEncryptionPublicKey () const = 0;
virtual bool IsDestination () const = 0; // for garlic virtual bool IsDestination () const = 0; // for garlic
}; };
@ -32,14 +60,14 @@ namespace data
LeaseSet (const uint8_t * buf, int len); LeaseSet (const uint8_t * buf, int len);
// implements RoutingDestination // implements RoutingDestination
const uint8_t * GetIdentHash () const { return m_IdentHash; }; const IdentHash& GetIdentHash () const { return m_IdentHash; };
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; }; const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; };
bool IsDestination () const { return true; }; bool IsDestination () const { return true; };
private: private:
std::list<Lease> m_Leases; std::list<Lease> m_Leases;
uint8_t m_IdentHash[32]; IdentHash m_IdentHash;
uint8_t m_EncryptionKey[256]; uint8_t m_EncryptionKey[256];
}; };
} }

58
NTCPSession.cpp

@ -20,9 +20,9 @@ namespace i2p
{ {
namespace ntcp namespace ntcp
{ {
NTCPSession::NTCPSession (boost::asio::ip::tcp::socket& s, const i2p::data::RouterInfo * in_RemoteRouterInfo): NTCPSession::NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouterInfo):
m_Socket (s), m_IsEstablished (false), m_ReceiveBufferOffset (0), m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false),
m_NextMessage (nullptr), m_DelayedMessage (nullptr) m_ReceiveBufferOffset (0), m_NextMessage (nullptr)
{ {
if (in_RemoteRouterInfo) if (in_RemoteRouterInfo)
m_RemoteRouterInfo = *in_RemoteRouterInfo; m_RemoteRouterInfo = *in_RemoteRouterInfo;
@ -52,8 +52,9 @@ namespace ntcp
{ {
m_IsEstablished = false; m_IsEstablished = false;
m_Socket.close (); m_Socket.close ();
if (m_DelayedMessage) for (auto it :m_DelayedMessages)
delete m_DelayedMessage; delete it;
m_DelayedMessages.clear ();
// TODO: notify tunnels // TODO: notify tunnels
i2p::transports.RemoveNTCPSession (this); i2p::transports.RemoveNTCPSession (this);
delete this; delete this;
@ -64,16 +65,15 @@ namespace ntcp
{ {
LogPrint ("NTCP session connected"); LogPrint ("NTCP session connected");
m_IsEstablished = true; m_IsEstablished = true;
i2p::transports.AddNTCPSession (this);
SendTimeSyncMessage (); SendTimeSyncMessage ();
SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are
if (m_DelayedMessage) if (!m_DelayedMessages.empty ())
{ {
i2p::I2NPMessage * delayedMessage = m_DelayedMessage; for (auto it :m_DelayedMessages)
m_DelayedMessage = 0; SendI2NPMessage (it);
SendI2NPMessage (delayedMessage); m_DelayedMessages.clear ();
} }
} }
@ -467,7 +467,8 @@ namespace ntcp
} }
boost::asio::async_write (m_Socket, boost::asio::buffer (sendBuffer, l), boost::asio::transfer_all (), boost::asio::async_write (m_Socket, boost::asio::buffer (sendBuffer, l), boost::asio::transfer_all (),
boost::bind(&NTCPSession::HandleSent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, msg)); boost::bind(&NTCPSession::HandleSent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, msg));
ScheduleTermination (); // reset termination timer
} }
void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, i2p::I2NPMessage * msg) void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, i2p::I2NPMessage * msg)
@ -497,13 +498,31 @@ namespace ntcp
if (m_IsEstablished) if (m_IsEstablished)
Send (msg); Send (msg);
else else
m_DelayedMessage = msg; m_DelayedMessages.push_back (msg);
}
}
void NTCPSession::ScheduleTermination ()
{
m_TerminationTimer.cancel ();
m_TerminationTimer.expires_from_now (boost::posix_time::seconds(TERMINATION_TIMEOUT));
m_TerminationTimer.async_wait (boost::bind (&NTCPSession::HandleTerminationTimer,
this, boost::asio::placeholders::error));
}
void NTCPSession::HandleTerminationTimer (const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
{
LogPrint ("No activity fo ", TERMINATION_TIMEOUT, " seconds");
m_Socket.close ();
} }
} }
NTCPClient::NTCPClient (boost::asio::io_service& service, const char * address, NTCPClient::NTCPClient (boost::asio::io_service& service, const char * address,
int port, const i2p::data::RouterInfo& in_RouterInfo): NTCPSession (m_Socket, &in_RouterInfo), int port, const i2p::data::RouterInfo& in_RouterInfo): NTCPSession (service, &in_RouterInfo),
m_Socket (service), m_Endpoint (boost::asio::ip::address::from_string (address), port) m_Endpoint (boost::asio::ip::address::from_string (address), port)
{ {
Connect (); Connect ();
} }
@ -511,7 +530,7 @@ namespace ntcp
void NTCPClient::Connect () void NTCPClient::Connect ()
{ {
LogPrint ("Connecting to ", m_Endpoint.address ().to_string (),":", m_Endpoint.port ()); LogPrint ("Connecting to ", m_Endpoint.address ().to_string (),":", m_Endpoint.port ());
m_Socket.async_connect (m_Endpoint, boost::bind (&NTCPClient::HandleConnect, GetSocket ().async_connect (m_Endpoint, boost::bind (&NTCPClient::HandleConnect,
this, boost::asio::placeholders::error)); this, boost::asio::placeholders::error));
} }
@ -529,9 +548,14 @@ namespace ntcp
} }
} }
NTCPServerConnection::NTCPServerConnection (boost::asio::io_service& service): void NTCPServerConnection::Connected ()
NTCPSession (m_Socket), m_Socket (service)
{ {
LogPrint ("NTCP server session connected");
SetIsEstablished (true);
i2p::transports.AddNTCPSession (this);
SendTimeSyncMessage ();
SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are
} }
} }
} }

28
NTCPSession.h

@ -3,6 +3,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <mutex> #include <mutex>
#include <list>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <cryptopp/modes.h> #include <cryptopp/modes.h>
#include <cryptopp/aes.h> #include <cryptopp/aes.h>
@ -60,13 +61,15 @@ namespace ntcp
#pragma pack() #pragma pack()
const int TERMINATION_TIMEOUT = 60; // 1 minute
class NTCPSession class NTCPSession
{ {
public: public:
NTCPSession (boost::asio::ip::tcp::socket& s, const i2p::data::RouterInfo * in_RemoteRouterInfo = 0); NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouterInfo = 0);
virtual ~NTCPSession () {}; virtual ~NTCPSession () {};
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
bool IsEstablished () const { return m_IsEstablished; }; bool IsEstablished () const { return m_IsEstablished; };
const i2p::data::RouterInfo& GetRemoteRouterInfo () const { return m_RemoteRouterInfo; }; const i2p::data::RouterInfo& GetRemoteRouterInfo () const { return m_RemoteRouterInfo; };
@ -77,7 +80,9 @@ namespace ntcp
protected: protected:
void Terminate (); void Terminate ();
void Connected (); virtual void Connected ();
void SendTimeSyncMessage ();
void SetIsEstablished (bool isEstablished) { m_IsEstablished = isEstablished; }
private: private:
@ -106,11 +111,15 @@ namespace ntcp
void Send (i2p::I2NPMessage * msg); void Send (i2p::I2NPMessage * msg);
void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, i2p::I2NPMessage * msg); void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, i2p::I2NPMessage * msg);
void SendTimeSyncMessage ();
// timer
void ScheduleTermination ();
void HandleTerminationTimer (const boost::system::error_code& ecode);
private: private:
boost::asio::ip::tcp::socket& m_Socket; boost::asio::ip::tcp::socket m_Socket;
boost::asio::deadline_timer m_TerminationTimer;
bool m_IsEstablished; bool m_IsEstablished;
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption; CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
@ -127,7 +136,8 @@ namespace ntcp
uint8_t m_ReceiveBuffer[i2p::NTCP_MAX_MESSAGE_SIZE*2], m_TimeSyncBuffer[16]; uint8_t m_ReceiveBuffer[i2p::NTCP_MAX_MESSAGE_SIZE*2], m_TimeSyncBuffer[16];
int m_ReceiveBufferOffset; int m_ReceiveBufferOffset;
i2p::I2NPMessage * m_NextMessage, * m_DelayedMessage; i2p::I2NPMessage * m_NextMessage;
std::list<i2p::I2NPMessage *> m_DelayedMessages;
size_t m_NextMessageOffset; size_t m_NextMessageOffset;
std::mutex m_EncryptionMutex; std::mutex m_EncryptionMutex;
@ -146,7 +156,6 @@ namespace ntcp
private: private:
boost::asio::ip::tcp::socket m_Socket;
boost::asio::ip::tcp::endpoint m_Endpoint; boost::asio::ip::tcp::endpoint m_Endpoint;
}; };
@ -154,12 +163,11 @@ namespace ntcp
{ {
public: public:
NTCPServerConnection (boost::asio::io_service& service); NTCPServerConnection (boost::asio::io_service& service): NTCPSession (service) {};
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
private: protected:
boost::asio::ip::tcp::socket m_Socket; virtual void Connected ();
}; };
} }
} }

17
NetDb.cpp

@ -95,14 +95,13 @@ namespace data
void NetDb::AddRouterInfo (uint8_t * buf, int len) void NetDb::AddRouterInfo (uint8_t * buf, int len)
{ {
RouterInfo * r = new RouterInfo (buf, len); RouterInfo * r = new RouterInfo (buf, len);
std::string hash((const char *)r->GetIdentHash (), 32); auto it = m_RouterInfos.find(r->GetIdentHash ());
auto it = m_RouterInfos.find(hash);
if (it != m_RouterInfos.end ()) if (it != m_RouterInfos.end ())
{ {
if (r->GetTimestamp () > it->second->GetTimestamp ()) if (r->GetTimestamp () > it->second->GetTimestamp ())
{ {
LogPrint ("RouterInfo updated"); LogPrint ("RouterInfo updated");
*m_RouterInfos[hash] = *r; // we can't replace point because it's used by tunnels *m_RouterInfos[r->GetIdentHash ()] = *r; // we can't replace point because it's used by tunnels
} }
else else
delete r; delete r;
@ -110,19 +109,19 @@ namespace data
else else
{ {
LogPrint ("New RouterInfo added"); LogPrint ("New RouterInfo added");
m_RouterInfos[hash] = r; m_RouterInfos[r->GetIdentHash ()] = r;
} }
} }
void NetDb::AddLeaseSet (uint8_t * buf, int len) void NetDb::AddLeaseSet (uint8_t * buf, int len)
{ {
LeaseSet * l = new LeaseSet (buf, len); LeaseSet * l = new LeaseSet (buf, len);
m_LeaseSets[std::string ((const char *)l->GetIdentHash (), 32)] = l; m_LeaseSets[l->GetIdentHash ()] = l;
} }
RouterInfo * NetDb::FindRouter (const uint8_t * ident) const RouterInfo * NetDb::FindRouter (const IdentHash& ident) const
{ {
auto it = m_RouterInfos.find (std::string ((const char *)ident, 32)); auto it = m_RouterInfos.find (ident);
if (it != m_RouterInfos.end ()) if (it != m_RouterInfos.end ())
return it->second; return it->second;
else else
@ -143,7 +142,7 @@ namespace data
for (boost::filesystem::directory_iterator it1 (it->path ()); it1 != end; ++it1) for (boost::filesystem::directory_iterator it1 (it->path ()); it1 != end; ++it1)
{ {
RouterInfo * r = new RouterInfo (it1->path ().c_str ()); RouterInfo * r = new RouterInfo (it1->path ().c_str ());
m_RouterInfos[std::string ((const char *)r->GetIdentHash (), 32)] = r; m_RouterInfos[r->GetIdentHash ()] = r;
numRouters++; numRouters++;
} }
} }
@ -252,7 +251,7 @@ namespace data
if (isExploratory) if (isExploratory)
{ {
if (m_RouterInfos.find (std::string ((const char *)router, 32)) == m_RouterInfos.end ()) if (m_RouterInfos.find (IdentHash(router)) == m_RouterInfos.end ())
{ {
LogPrint ("Found new router. Requesting RouterInfo ..."); LogPrint ("Found new router. Requesting RouterInfo ...");
if (outbound && inbound) if (outbound && inbound)

6
NetDb.h

@ -26,7 +26,7 @@ namespace data
void AddRouterInfo (uint8_t * buf, int len); void AddRouterInfo (uint8_t * buf, int len);
void AddLeaseSet (uint8_t * buf, int len); void AddLeaseSet (uint8_t * buf, int len);
RouterInfo * FindRouter (const uint8_t * ident) const; RouterInfo * FindRouter (const IdentHash& ident) const;
void RequestDestination (const char * b32, const uint8_t * router); // in base32 void RequestDestination (const char * b32, const uint8_t * router); // in base32
void RequestDestination (const uint8_t * destination, const uint8_t * router); void RequestDestination (const uint8_t * destination, const uint8_t * router);
@ -47,8 +47,8 @@ namespace data
private: private:
std::map<std::string, LeaseSet *> m_LeaseSets; std::map<IdentHash, LeaseSet *> m_LeaseSets;
std::map<std::string, RouterInfo *> m_RouterInfos; std::map<IdentHash, RouterInfo *> m_RouterInfos;
bool m_IsRunning; bool m_IsRunning;
std::thread * m_Thread; std::thread * m_Thread;

5
RouterInfo.h

@ -53,6 +53,7 @@ namespace data
void SetRouterIdentity (const RouterIdentity& identity); void SetRouterIdentity (const RouterIdentity& identity);
const char * GetIdentHashBase64 () const { return m_IdentHashBase64; }; const char * GetIdentHashBase64 () const { return m_IdentHashBase64; };
const char * GetIdentHashAbbreviation () const { return m_IdentHashAbbreviation; }; const char * GetIdentHashAbbreviation () const { return m_IdentHashAbbreviation; };
uint64_t GetTimestamp () const { return m_Timestamp; };
const std::vector<Address>& GetAddresses () const { return m_Addresses; }; const std::vector<Address>& GetAddresses () const { return m_Addresses; };
Address * GetNTCPAddress (); Address * GetNTCPAddress ();
@ -70,7 +71,7 @@ namespace data
void SetUpdated (bool updated) { m_IsUpdated = updated; }; void SetUpdated (bool updated) { m_IsUpdated = updated; };
// implements RoutingDestination // implements RoutingDestination
const uint8_t * GetIdentHash () const { return m_IdentHash; }; const IdentHash& GetIdentHash () const { return m_IdentHash; };
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity.publicKey; }; const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity.publicKey; };
bool IsDestination () const { return false; }; bool IsDestination () const { return false; };
@ -86,7 +87,7 @@ namespace data
private: private:
RouterIdentity m_RouterIdentity; RouterIdentity m_RouterIdentity;
uint8_t m_IdentHash[32]; IdentHash m_IdentHash;
char m_IdentHashBase64[48], m_IdentHashAbbreviation[5]; char m_IdentHashBase64[48], m_IdentHashAbbreviation[5];
char m_Buffer[2048]; char m_Buffer[2048];
int m_BufferLen; int m_BufferLen;

89
TransitTunnel.cpp

@ -12,31 +12,21 @@ namespace tunnel
{ {
TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey, const uint8_t * layerKey,const uint8_t * ivKey):
bool isGateway, bool isEndpoint) m_TunnelID (receiveTunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent)
{ {
memcpy (m_LayerKey, layerKey, 32); memcpy (m_LayerKey, layerKey, 32);
memcpy (m_IVKey, ivKey, 32); memcpy (m_IVKey, ivKey, 32);
memcpy (m_NextIdent, nextIdent, 32);
m_IsGateway = isGateway;
m_IsEndpoint = isEndpoint;
m_TunnelID = receiveTunnelID;
m_NextTunnelID = nextTunnelID;
if (m_IsEndpoint)
LogPrint ("TransitTunnel endpoint: ", m_TunnelID, " created");
else if (m_IsGateway)
LogPrint ("TransitTunnel gateway: ", m_TunnelID, " created");
else
LogPrint ("TransitTunnel: ",m_TunnelID,"->", m_NextTunnelID, " created");
} }
void TransitTunnel::Encrypt (uint8_t * payload) void TransitTunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg)
{ {
uint8_t * payload = tunnelMsg->GetPayload () + 4;
m_ECBEncryption.SetKey (m_IVKey, 32); m_ECBEncryption.SetKey (m_IVKey, 32);
m_ECBEncryption.ProcessData(payload, payload, 16); // iv m_ECBEncryption.ProcessData(payload, payload, 16); // iv
m_CBCEncryption.SetKeyWithIV (m_LayerKey, 32, payload); m_CBCEncryption.SetKeyWithIV (m_LayerKey, 32, payload);
m_CBCEncryption.ProcessData(payload + 16, payload + 16, 1008); // payload m_CBCEncryption.ProcessData(payload + 16, payload + 16, TUNNEL_DATA_ENCRYPTED_SIZE); // payload
m_ECBEncryption.SetKey (m_IVKey, 32); m_ECBEncryption.SetKey (m_IVKey, 32);
m_ECBEncryption.ProcessData(payload, payload, 16); // double iv encryption m_ECBEncryption.ProcessData(payload, payload, 16); // double iv encryption
@ -45,40 +35,53 @@ namespace tunnel
void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg) void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
{ {
Encrypt (tunnelMsg->GetPayload () + 4); EncryptTunnelMsg (tunnelMsg);
if (m_IsEndpoint)
{
LogPrint ("TransitTunnel endpoint for ", m_TunnelID);
m_Endpoint.HandleDecryptedTunnelDataMsg (tunnelMsg);
}
else
{
LogPrint ("TransitTunnel: ",m_TunnelID,"->", m_NextTunnelID);
*(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID);
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
i2p::transports.SendMessage (m_NextIdent, tunnelMsg); LogPrint ("TransitTunnel: ",m_TunnelID,"->", m_NextTunnelID);
} *(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID);
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
i2p::transports.SendMessage (m_NextIdent, tunnelMsg);
} }
void TransitTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg) void TransitTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg)
{
LogPrint ("We are not a gateway for transit tunnel ", m_TunnelID);
i2p::DeleteI2NPMessage (msg);
}
void TransitTunnelGateway::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg)
{
m_Gateway.SendTunnelDataMsg (gwHash, gwTunnel, msg);
}
void TransitTunnelEndpoint::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg)
{
EncryptTunnelMsg (tunnelMsg);
LogPrint ("TransitTunnel endpoint for ", GetTunnelID ());
m_Endpoint.HandleDecryptedTunnelDataMsg (tunnelMsg);
}
TransitTunnel * CreateTransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey,
bool isGateway, bool isEndpoint)
{ {
if (m_IsGateway) if (isEndpoint)
{ {
m_Gateway.PutI2NPMsg (gwHash, gwTunnel, msg); LogPrint ("TransitTunnel endpoint: ", receiveTunnelID, " created");
auto tunnelMsgs = m_Gateway.GetTunnelDataMsgs (m_NextTunnelID); return new TransitTunnelEndpoint (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
for (auto tunnelMsg : tunnelMsgs) }
{ else if (isGateway)
Encrypt (tunnelMsg->GetPayload () + 4); {
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); LogPrint ("TransitTunnel gateway: ", receiveTunnelID, " created");
i2p::transports.SendMessage (m_NextIdent, tunnelMsg); return new TransitTunnelGateway (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
} }
} else
else
{ {
LogPrint ("We are not a gateway for transit tunnel ", m_TunnelID); LogPrint ("TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created");
i2p::DeleteI2NPMessage (msg); return new TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
} }
} }
} }

64
TransitTunnel.h

@ -7,46 +7,78 @@
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
#include "TunnelEndpoint.h" #include "TunnelEndpoint.h"
#include "TunnelGateway.h" #include "TunnelGateway.h"
#include "TunnelBase.h"
namespace i2p namespace i2p
{ {
namespace tunnel namespace tunnel
{ {
class TransitTunnel class TransitTunnel: public TunnelBase // tunnel patricipant
{ {
public: public:
TransitTunnel (uint32_t receiveTunnelID, TransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID, const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey, const uint8_t * layerKey,const uint8_t * ivKey);
bool isGateway, bool isEndpoint);
void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg); virtual void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg);
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg); virtual void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg);
uint32_t GetTunnelID () const { return m_TunnelID; }; uint32_t GetTunnelID () const { return m_TunnelID; };
bool IsGateway () const { return m_IsGateway; };
bool IsEndpoint () const { return m_IsEndpoint; };
bool IsParticipant () const { return !IsGateway () && !IsEndpoint (); };
private:
void Encrypt (uint8_t * payload); // implements TunnelBase
void EncryptTunnelMsg (I2NPMessage * tunnelMsg);
uint32_t GetNextTunnelID () const { return m_NextTunnelID; };
const i2p::data::IdentHash& GetNextIdentHash () const { return m_NextIdent; };
private: private:
uint32_t m_TunnelID, m_NextTunnelID; uint32_t m_TunnelID, m_NextTunnelID;
uint8_t m_NextIdent[32]; i2p::data::IdentHash m_NextIdent;
uint8_t m_LayerKey[32]; uint8_t m_LayerKey[32];
uint8_t m_IVKey[32]; uint8_t m_IVKey[32];
bool m_IsGateway, m_IsEndpoint;
TunnelEndpoint m_Endpoint;
TunnelGatewayBuffer m_Gateway;
CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_ECBEncryption; CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_ECBEncryption;
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_CBCEncryption; CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_CBCEncryption;
}; };
class TransitTunnelGateway: public TransitTunnel
{
public:
TransitTunnelGateway (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey):
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID,
layerKey, ivKey), m_Gateway(this) {};
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg);
private:
TunnelGateway m_Gateway;
};
class TransitTunnelEndpoint: public TransitTunnel
{
public:
TransitTunnelEndpoint (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey):
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey) {};
void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg);
private:
TunnelEndpoint m_Endpoint;
};
TransitTunnel * CreateTransitTunnel (uint32_t receiveTunnelID,
const uint8_t * nextIdent, uint32_t nextTunnelID,
const uint8_t * layerKey,const uint8_t * ivKey,
bool isGateway, bool isEndpoint);
} }
} }

27
Transports.cpp

@ -57,16 +57,28 @@ namespace i2p
} }
} }
void Transports::Run ()
{
try
{
m_Service.run ();
}
catch (std::exception& ex)
{
LogPrint ("Transports: ", ex.what ());
}
}
void Transports::AddNTCPSession (i2p::ntcp::NTCPSession * session) void Transports::AddNTCPSession (i2p::ntcp::NTCPSession * session)
{ {
if (session) if (session)
m_NTCPSessions[std::string ((const char *)session->GetRemoteRouterInfo ().GetIdentHash (), 32)] = session; m_NTCPSessions[session->GetRemoteRouterInfo ().GetIdentHash ()] = session;
} }
void Transports::RemoveNTCPSession (i2p::ntcp::NTCPSession * session) void Transports::RemoveNTCPSession (i2p::ntcp::NTCPSession * session)
{ {
if (session) if (session)
m_NTCPSessions.erase (std::string ((const char *)session->GetRemoteRouterInfo ().GetIdentHash (), 32)); m_NTCPSessions.erase (session->GetRemoteRouterInfo ().GetIdentHash ());
} }
void Transports::HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error) void Transports::HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error)
@ -94,17 +106,17 @@ namespace i2p
return 0; return 0;
} }
i2p::ntcp::NTCPSession * Transports::FindNTCPSession (const uint8_t * ident) i2p::ntcp::NTCPSession * Transports::FindNTCPSession (const i2p::data::IdentHash& ident)
{ {
auto it = m_NTCPSessions.find (std::string ((const char *)ident,32)); auto it = m_NTCPSessions.find (ident);
if (it != m_NTCPSessions.end ()) if (it != m_NTCPSessions.end ())
return it->second; return it->second;
return 0; return 0;
} }
void Transports::SendMessage (const uint8_t * ident, i2p::I2NPMessage * msg) void Transports::SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg)
{ {
if (!memcmp (ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32)) if (ident == i2p::context.GetRouterInfo ().GetIdentHash ())
// we send it to ourself // we send it to ourself
i2p::HandleI2NPMessage (msg); i2p::HandleI2NPMessage (msg);
else else
@ -117,7 +129,10 @@ namespace i2p
{ {
auto address = r->GetNTCPAddress (); auto address = r->GetNTCPAddress ();
if (address) if (address)
{
session = new i2p::ntcp::NTCPClient (m_Service, address->host.c_str (), address->port, *r); session = new i2p::ntcp::NTCPClient (m_Service, address->host.c_str (), address->port, *r);
AddNTCPSession (session);
}
} }
} }
if (session) if (session)

11
Transports.h

@ -28,15 +28,14 @@ namespace i2p
void RemoveNTCPSession (i2p::ntcp::NTCPSession * session); void RemoveNTCPSession (i2p::ntcp::NTCPSession * session);
i2p::ntcp::NTCPSession * GetNextNTCPSession (); i2p::ntcp::NTCPSession * GetNextNTCPSession ();
i2p::ntcp::NTCPSession * FindNTCPSession (const uint8_t * ident); i2p::ntcp::NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident);
void SendMessage (const uint8_t * ident, i2p::I2NPMessage * msg); void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
private: private:
void Run () { m_Service.run (); }; void Run ();
void HandleAccept (i2p::ntcp::NTCPServerConnection * conn, void HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error);
const boost::system::error_code& error);
private: private:
@ -45,7 +44,7 @@ namespace i2p
boost::asio::io_service::work m_Work; boost::asio::io_service::work m_Work;
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor; boost::asio::ip::tcp::acceptor * m_NTCPAcceptor;
std::map<std::string, i2p::ntcp::NTCPSession *> m_NTCPSessions; std::map<i2p::data::IdentHash, i2p::ntcp::NTCPSession *> m_NTCPSessions;
}; };
extern Transports transports; extern Transports transports;

11
TunnelGateway.cpp

@ -60,7 +60,7 @@ namespace tunnel
} }
} }
std::vector<I2NPMessage *> TunnelGatewayBuffer::GetTunnelDataMsgs (uint32_t tunnelID) std::vector<I2NPMessage *> TunnelGatewayBuffer::GetTunnelDataMsgs ()
{ {
m_Remaining = 0; m_Remaining = 0;
m_NextOffset = 0; m_NextOffset = 0;
@ -71,7 +71,7 @@ namespace tunnel
int ind = 0; int ind = 0;
while (ind < cnt) while (ind < cnt)
{ {
auto tunnelMsg = CreateNextTunnelMessage (tunnelID, ind); auto tunnelMsg = CreateNextTunnelMessage (ind);
if (!tunnelMsg) break; if (!tunnelMsg) break;
res.push_back (tunnelMsg); res.push_back (tunnelMsg);
} }
@ -139,7 +139,7 @@ namespace tunnel
return ret; return ret;
} }
I2NPMessage * TunnelGatewayBuffer::CreateNextTunnelMessage (uint32_t tunnelID, int& ind) I2NPMessage * TunnelGatewayBuffer::CreateNextTunnelMessage (int& ind)
{ {
int cnt = m_I2NPMsgs.size (); int cnt = m_I2NPMsgs.size ();
if (ind > cnt - 1) return nullptr; // no more messages if (ind > cnt - 1) return nullptr; // no more messages
@ -166,7 +166,7 @@ namespace tunnel
I2NPMessage * tunnelMsg = NewI2NPMessage (); I2NPMessage * tunnelMsg = NewI2NPMessage ();
uint8_t * buf = tunnelMsg->GetPayload (); uint8_t * buf = tunnelMsg->GetPayload ();
*(uint32_t *)(buf) = htobe32 (tunnelID); *(uint32_t *)(buf) = htobe32 (m_TunnelID);
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
rnd.GenerateBlock (buf + 4, 16); // original IV rnd.GenerateBlock (buf + 4, 16); // original IV
memcpy (buf + TUNNEL_DATA_MSG_SIZE, buf + 4, 16); // copy IV for checksum memcpy (buf + TUNNEL_DATA_MSG_SIZE, buf + 4, 16); // copy IV for checksum
@ -219,12 +219,13 @@ namespace tunnel
void TunnelGateway::SendBuffer () void TunnelGateway::SendBuffer ()
{ {
auto tunnelMsgs = m_Buffer.GetTunnelDataMsgs (m_Tunnel->GetNextTunnelID ()); auto tunnelMsgs = m_Buffer.GetTunnelDataMsgs ();
for (auto tunnelMsg : tunnelMsgs) for (auto tunnelMsg : tunnelMsgs)
{ {
m_Tunnel->EncryptTunnelMsg (tunnelMsg); m_Tunnel->EncryptTunnelMsg (tunnelMsg);
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
i2p::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg); i2p::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg);
m_NumSentBytes += TUNNEL_DATA_MSG_SIZE;
} }
} }
} }

12
TunnelGateway.h

@ -20,19 +20,20 @@ namespace tunnel
public: public:
TunnelGatewayBuffer (): m_Remaining (0) {}; TunnelGatewayBuffer (uint32_t tunnelID): m_TunnelID (tunnelID), m_Remaining (0) {};
void PutI2NPMsg (const uint8_t * gwHash, uint32_t gwTunnel, I2NPMessage * msg); void PutI2NPMsg (const uint8_t * gwHash, uint32_t gwTunnel, I2NPMessage * msg);
std::vector<I2NPMessage *> GetTunnelDataMsgs (uint32_t tunnelID); std::vector<I2NPMessage *> GetTunnelDataMsgs ();
private: private:
size_t CreateFirstFragment (TunnelMessageBlockExt * block, uint8_t * buf, size_t len); size_t CreateFirstFragment (TunnelMessageBlockExt * block, uint8_t * buf, size_t len);
size_t CreateFollowOnFragment (TunnelMessageBlockExt * block, uint8_t * buf, size_t len); size_t CreateFollowOnFragment (TunnelMessageBlockExt * block, uint8_t * buf, size_t len);
I2NPMessage * CreateNextTunnelMessage (uint32_t tunnelID, int& ind); I2NPMessage * CreateNextTunnelMessage (int& ind);
private: private:
uint32_t m_TunnelID;
std::vector<TunnelMessageBlockExt *> m_I2NPMsgs; std::vector<TunnelMessageBlockExt *> m_I2NPMsgs;
// for fragmented messages // for fragmented messages
size_t m_NextOffset, m_NextSeqn, m_Remaining; size_t m_NextOffset, m_NextSeqn, m_Remaining;
@ -43,15 +44,18 @@ namespace tunnel
{ {
public: public:
TunnelGateway (TunnelBase * tunnel): m_Tunnel (tunnel) {}; TunnelGateway (TunnelBase * tunnel):
m_Tunnel (tunnel), m_Buffer (tunnel->GetNextTunnelID ()), m_NumSentBytes (0) {};
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg); void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg);
void PutTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg); void PutTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg);
void SendBuffer (); void SendBuffer ();
size_t GetNumSentBytes () const { return m_NumSentBytes; };
private: private:
TunnelBase * m_Tunnel; TunnelBase * m_Tunnel;
TunnelGatewayBuffer m_Buffer; TunnelGatewayBuffer m_Buffer;
size_t m_NumSentBytes;
}; };
} }
} }

Loading…
Cancel
Save