mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-07 07:44:13 +00:00
Merge pull request #26 from orignal/master
Merge pull request from orignal/master
This commit is contained in:
commit
85884a5b84
2
.gitignore
vendored
2
.gitignore
vendored
@ -53,7 +53,6 @@ local.properties
|
|||||||
[Dd]ebug/
|
[Dd]ebug/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
x64/
|
x64/
|
||||||
build/
|
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
|
||||||
@ -200,7 +199,6 @@ $RECYCLE.BIN/
|
|||||||
*.egg
|
*.egg
|
||||||
*.egg-info
|
*.egg-info
|
||||||
dist/
|
dist/
|
||||||
build/
|
|
||||||
eggs/
|
eggs/
|
||||||
parts/
|
parts/
|
||||||
var/
|
var/
|
||||||
|
28
.travis.yml
Normal file
28
.travis.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
language: cpp
|
||||||
|
compiler: gcc
|
||||||
|
cache: apt
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
before_install:
|
||||||
|
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test # GCC 4.7
|
||||||
|
- sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ quantal main universe" # Boost 1.50
|
||||||
|
- sudo apt-get update -qq
|
||||||
|
- sudo apt-get install -qq libboost1.50-all-dev libcrypto++9 libcrypto++-dev
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
recipients:
|
||||||
|
- meeh@sigterm.no
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
- "irc.freenode.net#i2p-dev"
|
||||||
|
template:
|
||||||
|
- "%{repository}/%{branch} (%{commit} - %{author}): %{message}"
|
||||||
|
on_failure: always
|
||||||
|
on_success: change
|
||||||
|
|
||||||
|
|
70
AddressBook.cpp
Normal file
70
AddressBook.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include "base64.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "Identity.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "AddressBook.h"
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace data
|
||||||
|
{
|
||||||
|
|
||||||
|
AddressBook::AddressBook (): m_IsLoaded (false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const IdentHash * AddressBook::FindAddress (const std::string& address)
|
||||||
|
{
|
||||||
|
if (!m_IsLoaded)
|
||||||
|
LoadHosts ();
|
||||||
|
auto it = m_Addresses.find (address);
|
||||||
|
if (it != m_Addresses.end ())
|
||||||
|
return &it->second;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AddressBook::LoadHosts ()
|
||||||
|
{
|
||||||
|
m_IsLoaded = true;
|
||||||
|
std::ifstream f (i2p::util::filesystem::GetFullPath ("hosts.txt").c_str (), std::ofstream::in); // in text mode
|
||||||
|
if (!f.is_open ())
|
||||||
|
{
|
||||||
|
LogPrint ("hosts.txt not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int numAddresses = 0;
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
while (!f.eof ())
|
||||||
|
{
|
||||||
|
getline(f, s);
|
||||||
|
|
||||||
|
if (!s.length())
|
||||||
|
break;
|
||||||
|
|
||||||
|
size_t pos = s.find('=');
|
||||||
|
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string name = s.substr(0, pos++);
|
||||||
|
std::string addr = s.substr(pos);
|
||||||
|
|
||||||
|
Identity ident;
|
||||||
|
Base64ToByteStream (addr.c_str(), addr.length(), (uint8_t *)&ident, sizeof (ident));
|
||||||
|
m_Addresses[name] = CalculateIdentHash (ident);
|
||||||
|
numAddresses++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogPrint (numAddresses, " addresses loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,50 +17,12 @@ namespace data
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AddressBook (): m_IsLoaded (false) {};
|
AddressBook ();
|
||||||
|
const IdentHash * FindAddress (const std::string& address);
|
||||||
const IdentHash * FindAddress (const std::string& address)
|
|
||||||
{
|
|
||||||
if (!m_IsLoaded)
|
|
||||||
LoadHosts ();
|
|
||||||
auto it = m_Addresses.find (address);
|
|
||||||
if (it != m_Addresses.end ())
|
|
||||||
return &it->second;
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void LoadHosts ()
|
void LoadHosts ();
|
||||||
{
|
|
||||||
m_IsLoaded = true;
|
|
||||||
std::ifstream f (i2p::util::filesystem::GetFullPath ("hosts.txt").c_str (), std::ofstream::in); // in text mode
|
|
||||||
if (!f.is_open ())
|
|
||||||
{
|
|
||||||
LogPrint ("hosts.txt not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int numAddresses = 0;
|
|
||||||
char str[1024];
|
|
||||||
while (!f.eof ())
|
|
||||||
{
|
|
||||||
f.getline (str, 1024);
|
|
||||||
char * key = strchr (str, '=');
|
|
||||||
if (key)
|
|
||||||
{
|
|
||||||
*key = 0;
|
|
||||||
key++;
|
|
||||||
Identity ident;
|
|
||||||
Base64ToByteStream (key, strlen(key), (uint8_t *)&ident, sizeof (ident));
|
|
||||||
m_Addresses[str] = CalculateIdentHash (ident);
|
|
||||||
numAddresses++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogPrint (numAddresses, " addresses loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::map<std::string, IdentHash> m_Addresses;
|
std::map<std::string, IdentHash> m_Addresses;
|
||||||
bool m_IsLoaded;
|
bool m_IsLoaded;
|
||||||
|
@ -245,7 +245,7 @@ namespace util
|
|||||||
for (auto it: i2p::tunnel::tunnels.GetOutboundTunnels ())
|
for (auto it: i2p::tunnel::tunnels.GetOutboundTunnels ())
|
||||||
{
|
{
|
||||||
it->GetTunnelConfig ()->Print (s);
|
it->GetTunnelConfig ()->Print (s);
|
||||||
if (it->GetTunnelPool ())
|
if (it->GetTunnelPool () && !it->GetTunnelPool ()->IsExploratory ())
|
||||||
s << " " << "Pool";
|
s << " " << "Pool";
|
||||||
if (it->IsFailed ())
|
if (it->IsFailed ())
|
||||||
s << " " << "Failed";
|
s << " " << "Failed";
|
||||||
@ -255,7 +255,7 @@ namespace util
|
|||||||
for (auto it: i2p::tunnel::tunnels.GetInboundTunnels ())
|
for (auto it: i2p::tunnel::tunnels.GetInboundTunnels ())
|
||||||
{
|
{
|
||||||
it.second->GetTunnelConfig ()->Print (s);
|
it.second->GetTunnelConfig ()->Print (s);
|
||||||
if (it.second->GetTunnelPool ())
|
if (it.second->GetTunnelPool () && !it.second->GetTunnelPool ()->IsExploratory ())
|
||||||
s << " " << "Pool";
|
s << " " << "Pool";
|
||||||
if (it.second->IsFailed ())
|
if (it.second->IsFailed ())
|
||||||
s << " " << "Failed";
|
s << " " << "Failed";
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
#ifndef I2PENDIAN_H__
|
#ifndef I2PENDIAN_H__
|
||||||
#define I2PENDIAN_H__
|
#define I2PENDIAN_H__
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifdef __linux__
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
#elif __FreeBSD__
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#elif __MACH__ // Mac OS X
|
||||||
|
#include <machine/endian.h>
|
||||||
#else
|
#else
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
@ -53,6 +53,14 @@ namespace data
|
|||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreateRandomDHKeysPair (DHKeysPair * keys)
|
||||||
|
{
|
||||||
|
if (!keys) return;
|
||||||
|
CryptoPP::AutoSeededRandomPool rnd;
|
||||||
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
|
dh.GenerateKeyPair(rnd, keys->privateKey, keys->publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
RoutingKey CreateRoutingKey (const IdentHash& ident)
|
RoutingKey CreateRoutingKey (const IdentHash& ident)
|
||||||
{
|
{
|
||||||
uint8_t buf[41]; // ident + yyyymmdd
|
uint8_t buf[41]; // ident + yyyymmdd
|
||||||
|
12
Identity.h
12
Identity.h
@ -11,6 +11,12 @@ namespace data
|
|||||||
{
|
{
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
|
struct DHKeysPair // transient keys for transport sessions
|
||||||
|
{
|
||||||
|
uint8_t publicKey[256];
|
||||||
|
uint8_t privateKey[256];
|
||||||
|
};
|
||||||
|
|
||||||
struct Keys
|
struct Keys
|
||||||
{
|
{
|
||||||
uint8_t privateKey[256];
|
uint8_t privateKey[256];
|
||||||
@ -71,6 +77,7 @@ namespace data
|
|||||||
|
|
||||||
IdentHash CalculateIdentHash (const Identity& identity);
|
IdentHash CalculateIdentHash (const Identity& identity);
|
||||||
Keys CreateRandomKeys ();
|
Keys CreateRandomKeys ();
|
||||||
|
void CreateRandomDHKeysPair (DHKeysPair * keys); // for transport sessions
|
||||||
|
|
||||||
// kademlia
|
// kademlia
|
||||||
struct RoutingKey
|
struct RoutingKey
|
||||||
@ -118,7 +125,10 @@ namespace data
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void UpdateLeaseSet () = 0; // LeaseSet must be update
|
virtual const IdentHash& GetIdentHash () const = 0;
|
||||||
|
virtual const uint8_t * GetEncryptionPrivateKey () const = 0;
|
||||||
|
virtual const uint8_t * GetEncryptionPublicKey () const = 0;
|
||||||
|
virtual void UpdateLeaseSet () = 0; // LeaseSet must be updated
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
Makefile
2
Makefile
@ -5,7 +5,7 @@ OBJECTS = obj/i2p.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transpor
|
|||||||
obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.o \
|
obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.o \
|
||||||
obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \
|
obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \
|
||||||
obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \
|
obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \
|
||||||
obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o
|
obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o
|
||||||
INCFLAGS =
|
INCFLAGS =
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
||||||
LIBS =
|
LIBS =
|
||||||
|
@ -24,13 +24,19 @@ namespace ntcp
|
|||||||
m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false),
|
m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false),
|
||||||
m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), m_NextMessage (nullptr)
|
m_RemoteRouterInfo (in_RemoteRouterInfo), m_ReceiveBufferOffset (0), m_NextMessage (nullptr)
|
||||||
{
|
{
|
||||||
|
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTCPSession::~NTCPSession ()
|
||||||
|
{
|
||||||
|
delete m_DHKeysPair;
|
||||||
|
}
|
||||||
|
|
||||||
void NTCPSession::CreateAESKey (uint8_t * pubKey, uint8_t * aesKey)
|
void NTCPSession::CreateAESKey (uint8_t * pubKey, uint8_t * aesKey)
|
||||||
{
|
{
|
||||||
CryptoPP::DH dh (elgp, elgg);
|
CryptoPP::DH dh (elgp, elgg);
|
||||||
CryptoPP::SecByteBlock secretKey(dh.AgreedValueLength());
|
CryptoPP::SecByteBlock secretKey(dh.AgreedValueLength());
|
||||||
if (!dh.Agree (secretKey, i2p::context.GetPrivateKey (), pubKey))
|
if (!dh.Agree (secretKey, m_DHKeysPair->privateKey, pubKey))
|
||||||
{
|
{
|
||||||
LogPrint ("Couldn't create shared key");
|
LogPrint ("Couldn't create shared key");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
@ -50,11 +56,19 @@ namespace ntcp
|
|||||||
{
|
{
|
||||||
m_IsEstablished = false;
|
m_IsEstablished = false;
|
||||||
m_Socket.close ();
|
m_Socket.close ();
|
||||||
for (auto it :m_DelayedMessages)
|
|
||||||
delete it;
|
|
||||||
m_DelayedMessages.clear ();
|
|
||||||
// TODO: notify tunnels
|
|
||||||
i2p::transports.RemoveNTCPSession (this);
|
i2p::transports.RemoveNTCPSession (this);
|
||||||
|
int numDelayed = 0;
|
||||||
|
for (auto it :m_DelayedMessages)
|
||||||
|
{
|
||||||
|
// try to send them again
|
||||||
|
i2p::transports.SendMessage (m_RemoteRouterInfo.GetIdentHash (), it);
|
||||||
|
numDelayed++;
|
||||||
|
}
|
||||||
|
m_DelayedMessages.clear ();
|
||||||
|
if (numDelayed > 0)
|
||||||
|
LogPrint ("NTCP session ", numDelayed, " not sent");
|
||||||
|
// TODO: notify tunnels
|
||||||
|
|
||||||
delete this;
|
delete this;
|
||||||
LogPrint ("NTCP session terminated");
|
LogPrint ("NTCP session terminated");
|
||||||
}
|
}
|
||||||
@ -78,7 +92,7 @@ namespace ntcp
|
|||||||
void NTCPSession::ClientLogin ()
|
void NTCPSession::ClientLogin ()
|
||||||
{
|
{
|
||||||
// send Phase1
|
// send Phase1
|
||||||
const uint8_t * x = i2p::context.GetRouterIdentity ().publicKey;
|
const uint8_t * x = m_DHKeysPair->publicKey;
|
||||||
memcpy (m_Phase1.pubKey, x, 256);
|
memcpy (m_Phase1.pubKey, x, 256);
|
||||||
CryptoPP::SHA256().CalculateDigest(m_Phase1.HXxorHI, x, 256);
|
CryptoPP::SHA256().CalculateDigest(m_Phase1.HXxorHI, x, 256);
|
||||||
const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash ();
|
const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash ();
|
||||||
@ -143,7 +157,7 @@ namespace ntcp
|
|||||||
|
|
||||||
void NTCPSession::SendPhase2 ()
|
void NTCPSession::SendPhase2 ()
|
||||||
{
|
{
|
||||||
const uint8_t * y = i2p::context.GetRouterIdentity ().publicKey;
|
const uint8_t * y = m_DHKeysPair->publicKey;
|
||||||
memcpy (m_Phase2.pubKey, y, 256);
|
memcpy (m_Phase2.pubKey, y, 256);
|
||||||
uint8_t xy[512];
|
uint8_t xy[512];
|
||||||
memcpy (xy, m_Phase1.pubKey, 256);
|
memcpy (xy, m_Phase1.pubKey, 256);
|
||||||
@ -200,7 +214,7 @@ namespace ntcp
|
|||||||
m_Decryption.ProcessData((uint8_t *)&m_Phase2.encrypted, (uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted));
|
m_Decryption.ProcessData((uint8_t *)&m_Phase2.encrypted, (uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted));
|
||||||
// verify
|
// verify
|
||||||
uint8_t xy[512], hxy[32];
|
uint8_t xy[512], hxy[32];
|
||||||
memcpy (xy, i2p::context.GetRouterIdentity ().publicKey, 256);
|
memcpy (xy, m_DHKeysPair->publicKey, 256);
|
||||||
memcpy (xy + 256, m_Phase2.pubKey, 256);
|
memcpy (xy + 256, m_Phase2.pubKey, 256);
|
||||||
CryptoPP::SHA256().CalculateDigest(hxy, xy, 512);
|
CryptoPP::SHA256().CalculateDigest(hxy, xy, 512);
|
||||||
if (memcmp (hxy, m_Phase2.encrypted.hxy, 32))
|
if (memcmp (hxy, m_Phase2.encrypted.hxy, 32))
|
||||||
@ -321,6 +335,7 @@ namespace ntcp
|
|||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint ("Phase 4 read error: ", ecode.message ());
|
LogPrint ("Phase 4 read error: ", ecode.message ());
|
||||||
|
GetRemoteRouterInfo ().SetUnreachable (true); // this router doesn't like us
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <cryptopp/modes.h>
|
#include <cryptopp/modes.h>
|
||||||
#include <cryptopp/aes.h>
|
#include <cryptopp/aes.h>
|
||||||
#include <cryptopp/adler32.h>
|
#include <cryptopp/adler32.h>
|
||||||
|
#include "Identity.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ namespace ntcp
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo);
|
NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo);
|
||||||
virtual ~NTCPSession () {};
|
virtual ~NTCPSession ();
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||||
bool IsEstablished () const { return m_IsEstablished; };
|
bool IsEstablished () const { return m_IsEstablished; };
|
||||||
@ -120,6 +121,7 @@ namespace ntcp
|
|||||||
boost::asio::ip::tcp::socket m_Socket;
|
boost::asio::ip::tcp::socket m_Socket;
|
||||||
boost::asio::deadline_timer m_TerminationTimer;
|
boost::asio::deadline_timer m_TerminationTimer;
|
||||||
bool m_IsEstablished;
|
bool m_IsEstablished;
|
||||||
|
i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
|
||||||
|
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
|
||||||
|
11
NetDb.cpp
11
NetDb.cpp
@ -442,9 +442,11 @@ namespace data
|
|||||||
|
|
||||||
if (dest->IsExploratory ())
|
if (dest->IsExploratory ())
|
||||||
{
|
{
|
||||||
if (!FindRouter (router)) // router with ident not found
|
auto r = FindRouter (router);
|
||||||
|
if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL)
|
||||||
{
|
{
|
||||||
LogPrint ("Found new router. Requesting RouterInfo ...");
|
// router with ident not found or too old (1 hour)
|
||||||
|
LogPrint ("Found new/outdated router. Requesting RouterInfo ...");
|
||||||
if (outbound && inbound)
|
if (outbound && inbound)
|
||||||
{
|
{
|
||||||
RequestedDestination * d1 = CreateRequestedDestination (router, false, false);
|
RequestedDestination * d1 = CreateRequestedDestination (router, false, false);
|
||||||
@ -532,8 +534,9 @@ namespace data
|
|||||||
|
|
||||||
void NetDb::Explore ()
|
void NetDb::Explore ()
|
||||||
{
|
{
|
||||||
auto outbound = i2p::tunnel::tunnels.GetNextOutboundTunnel ();
|
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||||
auto inbound = i2p::tunnel::tunnels.GetNextInboundTunnel ();
|
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
|
||||||
|
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr;
|
||||||
if (outbound && inbound)
|
if (outbound && inbound)
|
||||||
{
|
{
|
||||||
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
||||||
|
@ -9,6 +9,8 @@ on Windows
|
|||||||
|
|
||||||
Requires msvs2013, boost 1.46 and higher, crypto++
|
Requires msvs2013, boost 1.46 and higher, crypto++
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/orignal/i2pd.svg?branch=master)](https://travis-ci.org/orignal/i2pd)
|
||||||
|
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
-------
|
-------
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <cryptopp/dsa.h>
|
#include <cryptopp/dsa.h>
|
||||||
#include <cryptopp/osrng.h>
|
#include <cryptopp/osrng.h>
|
||||||
|
#include "Identity.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@ -11,7 +12,7 @@ namespace i2p
|
|||||||
const char ROUTER_INFO[] = "router.info";
|
const char ROUTER_INFO[] = "router.info";
|
||||||
const char ROUTER_KEYS[] = "router.keys";
|
const char ROUTER_KEYS[] = "router.keys";
|
||||||
|
|
||||||
class RouterContext
|
class RouterContext: public i2p::data::LocalDestination
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -28,6 +29,12 @@ namespace i2p
|
|||||||
void OverrideNTCPAddress (const char * host, int port); // temporary
|
void OverrideNTCPAddress (const char * host, int port); // temporary
|
||||||
void UpdateAddress (const char * host); // called from SSU
|
void UpdateAddress (const char * host); // called from SSU
|
||||||
|
|
||||||
|
// implements LocalDestination
|
||||||
|
void UpdateLeaseSet () {};
|
||||||
|
const i2p::data::IdentHash& GetIdentHash () const { return m_RouterInfo.GetIdentHash (); };
|
||||||
|
const uint8_t * GetEncryptionPrivateKey () const { return GetPrivateKey (); };
|
||||||
|
const uint8_t * GetEncryptionPublicKey () const { return m_Keys.publicKey; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void CreateNewRouter ();
|
void CreateNewRouter ();
|
||||||
|
71
SSU.cpp
71
SSU.cpp
@ -6,6 +6,7 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
|
#include "Transports.h"
|
||||||
#include "hmac.h"
|
#include "hmac.h"
|
||||||
#include "SSU.h"
|
#include "SSU.h"
|
||||||
|
|
||||||
@ -14,23 +15,23 @@ namespace i2p
|
|||||||
namespace ssu
|
namespace ssu
|
||||||
{
|
{
|
||||||
|
|
||||||
SSUSession::SSUSession (SSUServer * server, boost::asio::ip::udp::endpoint& remoteEndpoint,
|
SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint,
|
||||||
const i2p::data::RouterInfo * router): m_Server (server), m_RemoteEndpoint (remoteEndpoint),
|
const i2p::data::RouterInfo * router): m_Server (server), m_RemoteEndpoint (remoteEndpoint),
|
||||||
m_RemoteRouter (router), m_ConnectTimer (nullptr),m_State (eSessionStateUnknown)
|
m_RemoteRouter (router), m_Timer (m_Server.GetService ()), m_State (eSessionStateUnknown)
|
||||||
{
|
{
|
||||||
|
m_DHKeysPair = i2p::transports.GetNextDHKeysPair ();
|
||||||
}
|
}
|
||||||
|
|
||||||
SSUSession::~SSUSession ()
|
SSUSession::~SSUSession ()
|
||||||
{
|
{
|
||||||
if (m_ConnectTimer)
|
delete m_DHKeysPair;
|
||||||
delete m_ConnectTimer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::CreateAESandMacKey (uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey)
|
void SSUSession::CreateAESandMacKey (uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey)
|
||||||
{
|
{
|
||||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
CryptoPP::SecByteBlock secretKey(dh.AgreedValueLength());
|
CryptoPP::SecByteBlock secretKey(dh.AgreedValueLength());
|
||||||
if (!dh.Agree (secretKey, i2p::context.GetPrivateKey (), pubKey))
|
if (!dh.Agree (secretKey, m_DHKeysPair->privateKey, pubKey))
|
||||||
{
|
{
|
||||||
LogPrint ("Couldn't create shared key");
|
LogPrint ("Couldn't create shared key");
|
||||||
return;
|
return;
|
||||||
@ -110,8 +111,7 @@ namespace ssu
|
|||||||
case PAYLOAD_TYPE_SESSION_DESTROYED:
|
case PAYLOAD_TYPE_SESSION_DESTROYED:
|
||||||
{
|
{
|
||||||
LogPrint ("SSU session destroy received");
|
LogPrint ("SSU session destroy received");
|
||||||
if (m_Server)
|
m_Server.DeleteSession (this); // delete this
|
||||||
m_Server->DeleteSession (this); // delete this
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PAYLOAD_TYPE_RELAY_INTRO:
|
case PAYLOAD_TYPE_RELAY_INTRO:
|
||||||
@ -166,11 +166,11 @@ namespace ssu
|
|||||||
{
|
{
|
||||||
m_State = eSessionStateCreatedReceived;
|
m_State = eSessionStateCreatedReceived;
|
||||||
LogPrint ("Session created received");
|
LogPrint ("Session created received");
|
||||||
if (m_ConnectTimer) m_ConnectTimer->cancel ();
|
m_Timer.cancel (); // connect timer
|
||||||
uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time
|
uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
uint8_t * y = payload;
|
uint8_t * y = payload;
|
||||||
memcpy (signedData, i2p::context.GetRouterIdentity ().publicKey, 256); // x
|
memcpy (signedData, m_DHKeysPair->publicKey, 256); // x
|
||||||
memcpy (signedData + 256, y, 256); // y
|
memcpy (signedData + 256, y, 256); // y
|
||||||
payload += 256;
|
payload += 256;
|
||||||
payload += 1; // size, assume 4
|
payload += 1; // size, assume 4
|
||||||
@ -235,7 +235,7 @@ namespace ssu
|
|||||||
|
|
||||||
uint8_t buf[304 + 18]; // 304 bytes for ipv4 (320 for ipv6)
|
uint8_t buf[304 + 18]; // 304 bytes for ipv4 (320 for ipv6)
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
memcpy (payload, i2p::context.GetRouterIdentity ().publicKey, 256);
|
memcpy (payload, m_DHKeysPair->publicKey, 256); // x
|
||||||
payload[256] = 4; // we assume ipv4
|
payload[256] = 4; // we assume ipv4
|
||||||
*(uint32_t *)(payload + 257) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ());
|
*(uint32_t *)(payload + 257) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ());
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ namespace ssu
|
|||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_REQUEST, buf, 304, introKey, iv, introKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_REQUEST, buf, 304, introKey, iv, introKey);
|
||||||
|
|
||||||
m_State = eSessionStateRequestSent;
|
m_State = eSessionStateRequestSent;
|
||||||
m_Server->Send (buf, 304, m_RemoteEndpoint);
|
m_Server.Send (buf, 304, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::SendRelayRequest (const i2p::data::RouterInfo::Introducer& introducer)
|
void SSUSession::SendRelayRequest (const i2p::data::RouterInfo::Introducer& introducer)
|
||||||
@ -276,7 +276,7 @@ namespace ssu
|
|||||||
rnd.GenerateBlock (iv, 16); // random iv
|
rnd.GenerateBlock (iv, 16); // random iv
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey);
|
||||||
m_State = eSessionRelayRequestSent;
|
m_State = eSessionRelayRequestSent;
|
||||||
m_Server->Send (buf, 96, m_RemoteEndpoint);
|
m_Server.Send (buf, 96, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::SendSessionCreated (const uint8_t * x)
|
void SSUSession::SendSessionCreated (const uint8_t * x)
|
||||||
@ -293,7 +293,7 @@ namespace ssu
|
|||||||
|
|
||||||
uint8_t buf[368 + 18];
|
uint8_t buf[368 + 18];
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
memcpy (payload, i2p::context.GetRouterIdentity ().publicKey, 256);
|
memcpy (payload, m_DHKeysPair->publicKey, 256);
|
||||||
memcpy (signedData + 256, payload, 256); // y
|
memcpy (signedData + 256, payload, 256); // y
|
||||||
payload += 256;
|
payload += 256;
|
||||||
*payload = 4; // we assume ipv4
|
*payload = 4; // we assume ipv4
|
||||||
@ -323,7 +323,7 @@ namespace ssu
|
|||||||
// encrypt message with intro key
|
// encrypt message with intro key
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey);
|
||||||
m_State = eSessionStateCreatedSent;
|
m_State = eSessionStateCreatedSent;
|
||||||
m_Server->Send (buf, 368, m_RemoteEndpoint);
|
m_Server.Send (buf, 368, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, uint32_t relayTag)
|
void SSUSession::SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, uint32_t relayTag)
|
||||||
@ -347,7 +347,7 @@ namespace ssu
|
|||||||
|
|
||||||
// signature
|
// signature
|
||||||
uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time
|
uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time
|
||||||
memcpy (signedData, i2p::context.GetRouterIdentity ().publicKey, 256); // x
|
memcpy (signedData, m_DHKeysPair->publicKey, 256); // x
|
||||||
memcpy (signedData + 256, y, 256); // y
|
memcpy (signedData + 256, y, 256); // y
|
||||||
memcpy (signedData + 512, ourAddress, 6); // our address/port as seem by party
|
memcpy (signedData + 512, ourAddress, 6); // our address/port as seem by party
|
||||||
*(uint32_t *)(signedData + 518) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ()); // remote IP
|
*(uint32_t *)(signedData + 518) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ()); // remote IP
|
||||||
@ -362,7 +362,7 @@ namespace ssu
|
|||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CONFIRMED, buf, 480, m_SessionKey, iv, m_MacKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CONFIRMED, buf, 480, m_SessionKey, iv, m_MacKey);
|
||||||
m_State = eSessionStateConfirmedSent;
|
m_State = eSessionStateConfirmedSent;
|
||||||
m_Server->Send (buf, 480, m_RemoteEndpoint);
|
m_Server.Send (buf, 480, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::ProcessRelayResponse (uint8_t * buf, size_t len)
|
void SSUSession::ProcessRelayResponse (uint8_t * buf, size_t len)
|
||||||
@ -390,7 +390,7 @@ namespace ssu
|
|||||||
uint16_t remotePort = be16toh (*(uint16_t *)(payload));
|
uint16_t remotePort = be16toh (*(uint16_t *)(payload));
|
||||||
payload += 2;
|
payload += 2;
|
||||||
boost::asio::ip::udp::endpoint newRemoteEndpoint(remoteIP, remotePort);
|
boost::asio::ip::udp::endpoint newRemoteEndpoint(remoteIP, remotePort);
|
||||||
m_Server->ReassignSession (m_RemoteEndpoint, newRemoteEndpoint);
|
m_Server.ReassignSession (m_RemoteEndpoint, newRemoteEndpoint);
|
||||||
m_RemoteEndpoint = newRemoteEndpoint;
|
m_RemoteEndpoint = newRemoteEndpoint;
|
||||||
payload++;
|
payload++;
|
||||||
boost::asio::ip::address_v4 ourIP (be32toh (*(uint32_t* )(payload)));
|
boost::asio::ip::address_v4 ourIP (be32toh (*(uint32_t* )(payload)));
|
||||||
@ -494,13 +494,10 @@ namespace ssu
|
|||||||
{
|
{
|
||||||
if (m_State == eSessionStateUnknown)
|
if (m_State == eSessionStateUnknown)
|
||||||
{
|
{
|
||||||
if (m_Server)
|
// set connect timer
|
||||||
{
|
m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
|
||||||
m_ConnectTimer = new boost::asio::deadline_timer (m_Server->GetService ());
|
m_Timer.async_wait (boost::bind (&SSUSession::HandleConnectTimer,
|
||||||
m_ConnectTimer->expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
|
this, boost::asio::placeholders::error));
|
||||||
m_ConnectTimer->async_wait (boost::bind (&SSUSession::HandleConnectTimer,
|
|
||||||
this, boost::asio::placeholders::error));
|
|
||||||
}
|
|
||||||
SendSessionRequest ();
|
SendSessionRequest ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,8 +513,15 @@ namespace ssu
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::ConnectThroughIntroducer (const i2p::data::RouterInfo::Introducer& introducer)
|
void SSUSession::ConnectThroughIntroducer (const i2p::data::RouterInfo::Introducer& introducer)
|
||||||
{
|
{
|
||||||
SendRelayRequest (introducer);
|
if (m_State == eSessionStateUnknown)
|
||||||
|
{
|
||||||
|
// set connect timer
|
||||||
|
m_Timer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
|
||||||
|
m_Timer.async_wait (boost::bind (&SSUSession::HandleConnectTimer,
|
||||||
|
this, boost::asio::placeholders::error));
|
||||||
|
SendRelayRequest (introducer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::Close ()
|
void SSUSession::Close ()
|
||||||
@ -548,8 +552,7 @@ namespace ssu
|
|||||||
{
|
{
|
||||||
m_State = eSessionStateFailed;
|
m_State = eSessionStateFailed;
|
||||||
Close ();
|
Close ();
|
||||||
if (m_Server)
|
m_Server.DeleteSession (this); // delete this
|
||||||
m_Server->DeleteSession (this); // delete this
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,7 +695,7 @@ namespace ssu
|
|||||||
rnd.GenerateBlock (iv, 16); // random iv
|
rnd.GenerateBlock (iv, 16); // random iv
|
||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48, m_SessionKey, iv, m_MacKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48, m_SessionKey, iv, m_MacKey);
|
||||||
m_Server->Send (buf, 48, m_RemoteEndpoint);
|
m_Server.Send (buf, 48, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::SendSesionDestroyed ()
|
void SSUSession::SendSesionDestroyed ()
|
||||||
@ -715,7 +718,7 @@ namespace ssu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_Server->Send (buf, 48, m_RemoteEndpoint);
|
m_Server.Send (buf, 48, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::Send (i2p::I2NPMessage * msg)
|
void SSUSession::Send (i2p::I2NPMessage * msg)
|
||||||
@ -755,7 +758,7 @@ namespace ssu
|
|||||||
rnd.GenerateBlock (iv, 16); // random iv
|
rnd.GenerateBlock (iv, 16); // random iv
|
||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size, m_SessionKey, iv, m_MacKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size, m_SessionKey, iv, m_MacKey);
|
||||||
m_Server->Send (buf, size, m_RemoteEndpoint);
|
m_Server.Send (buf, size, m_RemoteEndpoint);
|
||||||
|
|
||||||
if (!isLast)
|
if (!isLast)
|
||||||
{
|
{
|
||||||
@ -815,7 +818,7 @@ namespace ssu
|
|||||||
session = it->second;
|
session = it->second;
|
||||||
if (!session)
|
if (!session)
|
||||||
{
|
{
|
||||||
session = new SSUSession (this, m_SenderEndpoint);
|
session = new SSUSession (*this, m_SenderEndpoint);
|
||||||
m_Sessions[m_SenderEndpoint] = session;
|
m_Sessions[m_SenderEndpoint] = session;
|
||||||
LogPrint ("New SSU session from ", m_SenderEndpoint.address ().to_string (), ":", m_SenderEndpoint.port (), " created");
|
LogPrint ("New SSU session from ", m_SenderEndpoint.address ().to_string (), ":", m_SenderEndpoint.port (), " created");
|
||||||
}
|
}
|
||||||
@ -856,7 +859,7 @@ namespace ssu
|
|||||||
if (!router->UsesIntroducer ())
|
if (!router->UsesIntroducer ())
|
||||||
{
|
{
|
||||||
// connect directly
|
// connect directly
|
||||||
session = new SSUSession (this, remoteEndpoint, router);
|
session = new SSUSession (*this, remoteEndpoint, router);
|
||||||
m_Sessions[remoteEndpoint] = session;
|
m_Sessions[remoteEndpoint] = session;
|
||||||
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (), "] ",
|
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (), "] ",
|
||||||
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port (), " created");
|
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port (), " created");
|
||||||
@ -869,7 +872,7 @@ namespace ssu
|
|||||||
{
|
{
|
||||||
auto& introducer = address->introducers[0]; // TODO:
|
auto& introducer = address->introducers[0]; // TODO:
|
||||||
boost::asio::ip::udp::endpoint introducerEndpoint (introducer.iHost, introducer.iPort);
|
boost::asio::ip::udp::endpoint introducerEndpoint (introducer.iHost, introducer.iPort);
|
||||||
session = new SSUSession (this, introducerEndpoint, router);
|
session = new SSUSession (*this, introducerEndpoint, router);
|
||||||
m_Sessions[introducerEndpoint] = session;
|
m_Sessions[introducerEndpoint] = session;
|
||||||
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (),
|
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (),
|
||||||
"] through introducer ", introducerEndpoint.address ().to_string (), ":", introducerEndpoint.port ());
|
"] through introducer ", introducerEndpoint.address ().to_string (), ":", introducerEndpoint.port ());
|
||||||
|
8
SSU.h
8
SSU.h
@ -8,6 +8,7 @@
|
|||||||
#include <cryptopp/modes.h>
|
#include <cryptopp/modes.h>
|
||||||
#include <cryptopp/aes.h>
|
#include <cryptopp/aes.h>
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
|
#include "Identity.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ namespace ssu
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SSUSession (SSUServer * server, boost::asio::ip::udp::endpoint& remoteEndpoint,
|
SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint,
|
||||||
const i2p::data::RouterInfo * router = nullptr);
|
const i2p::data::RouterInfo * router = nullptr);
|
||||||
void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
|
void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
|
||||||
~SSUSession ();
|
~SSUSession ();
|
||||||
@ -109,10 +110,11 @@ namespace ssu
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SSUServer * m_Server;
|
SSUServer& m_Server;
|
||||||
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
||||||
const i2p::data::RouterInfo * m_RemoteRouter;
|
const i2p::data::RouterInfo * m_RemoteRouter;
|
||||||
boost::asio::deadline_timer * m_ConnectTimer;
|
boost::asio::deadline_timer m_Timer;
|
||||||
|
i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
|
||||||
SessionState m_State;
|
SessionState m_State;
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cryptopp/dh.h>
|
||||||
#include <cryptopp/gzip.h>
|
#include <cryptopp/gzip.h>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
@ -347,7 +348,9 @@ namespace stream
|
|||||||
m_IdentHash = i2p::data::CalculateIdentHash (m_Keys.pub);
|
m_IdentHash = i2p::data::CalculateIdentHash (m_Keys.pub);
|
||||||
m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag,
|
m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag,
|
||||||
CryptoPP::Integer (m_Keys.signingPrivateKey, 20));
|
CryptoPP::Integer (m_Keys.signingPrivateKey, 20));
|
||||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (this);
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
|
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||||
|
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamingDestination::StreamingDestination (const std::string& fullPath): m_LeaseSet (nullptr)
|
StreamingDestination::StreamingDestination (const std::string& fullPath): m_LeaseSet (nullptr)
|
||||||
@ -357,7 +360,9 @@ namespace stream
|
|||||||
s.read ((char *)&m_Keys, sizeof (m_Keys));
|
s.read ((char *)&m_Keys, sizeof (m_Keys));
|
||||||
else
|
else
|
||||||
LogPrint ("Can't open file ", fullPath);
|
LogPrint ("Can't open file ", fullPath);
|
||||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (this);
|
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||||
|
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||||
|
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamingDestination::~StreamingDestination ()
|
StreamingDestination::~StreamingDestination ()
|
||||||
|
@ -138,6 +138,9 @@ namespace stream
|
|||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
void UpdateLeaseSet ();
|
void UpdateLeaseSet ();
|
||||||
|
const i2p::data::IdentHash& GetIdentHash () const { return m_IdentHash; };
|
||||||
|
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
||||||
|
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -148,7 +151,8 @@ namespace stream
|
|||||||
std::map<uint32_t, Stream *> m_Streams;
|
std::map<uint32_t, Stream *> m_Streams;
|
||||||
i2p::data::PrivateKeys m_Keys;
|
i2p::data::PrivateKeys m_Keys;
|
||||||
i2p::data::IdentHash m_IdentHash;
|
i2p::data::IdentHash m_IdentHash;
|
||||||
|
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
||||||
|
|
||||||
i2p::tunnel::TunnelPool * m_Pool;
|
i2p::tunnel::TunnelPool * m_Pool;
|
||||||
I2NPMessage * m_LeaseSet;
|
I2NPMessage * m_LeaseSet;
|
||||||
|
|
||||||
|
@ -9,10 +9,76 @@ using namespace i2p::data;
|
|||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
DHKeysPairSupplier::~DHKeysPairSupplier ()
|
||||||
|
{
|
||||||
|
Stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DHKeysPairSupplier::Start ()
|
||||||
|
{
|
||||||
|
m_IsRunning = true;
|
||||||
|
m_Thread = new std::thread (std::bind (&DHKeysPairSupplier::Run, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DHKeysPairSupplier::Stop ()
|
||||||
|
{
|
||||||
|
m_IsRunning = false;
|
||||||
|
m_Acquired.notify_one ();
|
||||||
|
if (m_Thread)
|
||||||
|
{
|
||||||
|
m_Thread->join ();
|
||||||
|
delete m_Thread;
|
||||||
|
m_Thread = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DHKeysPairSupplier::Run ()
|
||||||
|
{
|
||||||
|
while (m_IsRunning)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
while ((num = m_QueueSize - m_Queue.size ()) > 0)
|
||||||
|
CreateDHKeysPairs (num);
|
||||||
|
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||||
|
m_Acquired.wait (l); // wait for element gets aquired
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DHKeysPairSupplier::CreateDHKeysPairs (int num)
|
||||||
|
{
|
||||||
|
if (num > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair ();
|
||||||
|
i2p::data::CreateRandomDHKeysPair (pair);
|
||||||
|
m_Queue.push (pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i2p::data::DHKeysPair * DHKeysPairSupplier::Acquire ()
|
||||||
|
{
|
||||||
|
if (!m_Queue.empty ())
|
||||||
|
{
|
||||||
|
auto pair = m_Queue.front ();
|
||||||
|
m_Queue.pop ();
|
||||||
|
m_Acquired.notify_one ();
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
else // queue is empty, create new
|
||||||
|
{
|
||||||
|
i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair ();
|
||||||
|
i2p::data::CreateRandomDHKeysPair (pair);
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Transports transports;
|
Transports transports;
|
||||||
|
|
||||||
Transports::Transports ():
|
Transports::Transports ():
|
||||||
m_Thread (nullptr), m_Work (m_Service),m_NTCPAcceptor (nullptr), m_SSUServer (nullptr)
|
m_Thread (nullptr), m_Work (m_Service), m_NTCPAcceptor (nullptr),
|
||||||
|
m_SSUServer (nullptr), m_DHKeysPairSupplier (5) // 5 pre-generated keys
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,6 +89,7 @@ namespace i2p
|
|||||||
|
|
||||||
void Transports::Start ()
|
void Transports::Start ()
|
||||||
{
|
{
|
||||||
|
m_DHKeysPairSupplier.Start ();
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
||||||
m_Timer = new boost::asio::deadline_timer (m_Service);
|
m_Timer = new boost::asio::deadline_timer (m_Service);
|
||||||
@ -74,6 +141,7 @@ namespace i2p
|
|||||||
delete m_SSUServer;
|
delete m_SSUServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_DHKeysPairSupplier.Stop ();
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
m_Service.stop ();
|
m_Service.stop ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
@ -171,7 +239,7 @@ namespace i2p
|
|||||||
// existing session not found. create new
|
// existing session not found. create new
|
||||||
// try NTCP first
|
// try NTCP first
|
||||||
auto address = r->GetNTCPAddress ();
|
auto address = r->GetNTCPAddress ();
|
||||||
if (address)
|
if (address && !r->UsesIntroducer () && !r->IsUnreachable ())
|
||||||
{
|
{
|
||||||
auto s = new i2p::ntcp::NTCPClient (m_Service, address->host, address->port, *r);
|
auto s = new i2p::ntcp::NTCPClient (m_Service, address->host, address->port, *r);
|
||||||
AddNTCPSession (s);
|
AddNTCPSession (s);
|
||||||
@ -221,4 +289,8 @@ namespace i2p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i2p::data::DHKeysPair * Transports::GetNextDHKeysPair ()
|
||||||
|
{
|
||||||
|
return m_DHKeysPairSupplier.Acquire ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
33
Transports.h
33
Transports.h
@ -2,17 +2,47 @@
|
|||||||
#define TRANSPORTS_H__
|
#define TRANSPORTS_H__
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "NTCPSession.h"
|
#include "NTCPSession.h"
|
||||||
#include "SSU.h"
|
#include "SSU.h"
|
||||||
#include "RouterInfo.h"
|
#include "RouterInfo.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
#include "Identity.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
class DHKeysPairSupplier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DHKeysPairSupplier (int size): m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) {};
|
||||||
|
~DHKeysPairSupplier ();
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
i2p::data::DHKeysPair * Acquire ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Run ();
|
||||||
|
void CreateDHKeysPairs (int num);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int m_QueueSize;
|
||||||
|
std::queue<i2p::data::DHKeysPair *> m_Queue;
|
||||||
|
|
||||||
|
bool m_IsRunning;
|
||||||
|
std::thread * m_Thread;
|
||||||
|
std::condition_variable m_Acquired;
|
||||||
|
std::mutex m_AcquiredMutex;
|
||||||
|
};
|
||||||
|
|
||||||
class Transports
|
class Transports
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -24,6 +54,7 @@ namespace i2p
|
|||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
|
i2p::data::DHKeysPair * GetNextDHKeysPair ();
|
||||||
|
|
||||||
void AddNTCPSession (i2p::ntcp::NTCPSession * session);
|
void AddNTCPSession (i2p::ntcp::NTCPSession * session);
|
||||||
void RemoveNTCPSession (i2p::ntcp::NTCPSession * session);
|
void RemoveNTCPSession (i2p::ntcp::NTCPSession * session);
|
||||||
@ -54,6 +85,8 @@ namespace i2p
|
|||||||
i2p::ssu::SSUServer * m_SSUServer;
|
i2p::ssu::SSUServer * m_SSUServer;
|
||||||
boost::asio::deadline_timer * m_Timer;
|
boost::asio::deadline_timer * m_Timer;
|
||||||
|
|
||||||
|
DHKeysPairSupplier m_DHKeysPairSupplier;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
|
153
Tunnel.cpp
153
Tunnel.cpp
@ -154,11 +154,14 @@ namespace tunnel
|
|||||||
else
|
else
|
||||||
block.deliveryType = eDeliveryTypeLocal;
|
block.deliveryType = eDeliveryTypeLocal;
|
||||||
block.data = msg;
|
block.data = msg;
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||||
m_Gateway.SendTunnelDataMsg (block);
|
m_Gateway.SendTunnelDataMsg (block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutboundTunnel::SendTunnelDataMsg (std::vector<TunnelMessageBlock> msgs)
|
void OutboundTunnel::SendTunnelDataMsg (std::vector<TunnelMessageBlock> msgs)
|
||||||
{
|
{
|
||||||
|
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||||
for (auto& it : msgs)
|
for (auto& it : msgs)
|
||||||
m_Gateway.PutTunnelDataMsg (it);
|
m_Gateway.PutTunnelDataMsg (it);
|
||||||
m_Gateway.SendBuffer ();
|
m_Gateway.SendBuffer ();
|
||||||
@ -167,7 +170,7 @@ namespace tunnel
|
|||||||
Tunnels tunnels;
|
Tunnels tunnels;
|
||||||
|
|
||||||
Tunnels::Tunnels (): m_IsRunning (false), m_IsTunnelCreated (false),
|
Tunnels::Tunnels (): m_IsRunning (false), m_IsTunnelCreated (false),
|
||||||
m_NextReplyMsgID (555),m_Thread (0)
|
m_NextReplyMsgID (555), m_Thread (nullptr), m_ExploratoryPool (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +193,7 @@ namespace tunnel
|
|||||||
m_PendingTunnels.clear ();
|
m_PendingTunnels.clear ();
|
||||||
|
|
||||||
for (auto& it: m_Pools)
|
for (auto& it: m_Pools)
|
||||||
delete it;
|
delete it.second;
|
||||||
m_Pools.clear ();
|
m_Pools.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,23 +240,6 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
return tunnel;
|
return tunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<InboundTunnel *> Tunnels::GetInboundTunnels (int num) const
|
|
||||||
{
|
|
||||||
std::vector<InboundTunnel *> v;
|
|
||||||
int i = 0;
|
|
||||||
for (auto it : m_InboundTunnels)
|
|
||||||
{
|
|
||||||
if (i >= num) break;
|
|
||||||
if (!it.second->IsFailed () && it.second->GetNextIdentHash () != i2p::context.GetRouterInfo ().GetIdentHash ())
|
|
||||||
{
|
|
||||||
// exclude one hop tunnels
|
|
||||||
v.push_back (it.second);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutboundTunnel * Tunnels::GetNextOutboundTunnel ()
|
OutboundTunnel * Tunnels::GetNextOutboundTunnel ()
|
||||||
{
|
{
|
||||||
@ -272,17 +258,20 @@ namespace tunnel
|
|||||||
return tunnel;
|
return tunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination * localDestination)
|
TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination& localDestination)
|
||||||
{
|
{
|
||||||
auto pool = new TunnelPool (localDestination);
|
auto pool = new TunnelPool (localDestination);
|
||||||
m_Pools.push_back (pool);
|
m_Pools[pool->GetIdentHash ()] = pool;
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tunnels::DeleteTunnelPool (TunnelPool * pool)
|
void Tunnels::DeleteTunnelPool (TunnelPool * pool)
|
||||||
{
|
{
|
||||||
m_Pools.remove (pool);
|
if (pool)
|
||||||
delete pool;
|
{
|
||||||
|
m_Pools.erase (pool->GetIdentHash ());
|
||||||
|
delete pool;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tunnels::AddTransitTunnel (TransitTunnel * tunnel)
|
void Tunnels::AddTransitTunnel (TransitTunnel * tunnel)
|
||||||
@ -398,35 +387,18 @@ namespace tunnel
|
|||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_OutboundTunnels.size () < 15) // TODO: store exploratory tunnels explicitly
|
if (m_OutboundTunnels.size () < 5)
|
||||||
{
|
{
|
||||||
// trying to create one more oubound tunnel
|
// trying to create one more oubound tunnel
|
||||||
if (m_InboundTunnels.empty ()) return;
|
|
||||||
|
|
||||||
InboundTunnel * inboundTunnel = GetNextInboundTunnel ();
|
InboundTunnel * inboundTunnel = GetNextInboundTunnel ();
|
||||||
if (m_OutboundTunnels.empty () || m_OutboundTunnels.size () < 3)
|
if (!inboundTunnel) return;
|
||||||
{
|
LogPrint ("Creating one hop outbound tunnel...");
|
||||||
LogPrint ("Creating one hop outbound tunnel...");
|
CreateTunnel<OutboundTunnel> (
|
||||||
CreateTunnel<OutboundTunnel> (
|
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
||||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
{
|
||||||
{
|
i2p::data::netdb.GetRandomRouter ()
|
||||||
i2p::data::netdb.GetRandomRouter ()
|
},
|
||||||
},
|
inboundTunnel->GetTunnelConfig ()));
|
||||||
inboundTunnel->GetTunnelConfig ()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
LogPrint ("Creating two hops outbound tunnel...");
|
|
||||||
auto firstHop = i2p::data::netdb.GetRandomRouter ();
|
|
||||||
CreateTunnel<OutboundTunnel> (
|
|
||||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
|
||||||
{
|
|
||||||
firstHop,
|
|
||||||
i2p::data::netdb.GetRandomRouter (firstHop)
|
|
||||||
},
|
|
||||||
inboundTunnel->GetTunnelConfig ()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,35 +423,20 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
LogPrint ("Creating zero hops inbound tunnel...");
|
LogPrint ("Creating zero hops inbound tunnel...");
|
||||||
CreateZeroHopsInboundTunnel ();
|
CreateZeroHopsInboundTunnel ();
|
||||||
|
if (!m_ExploratoryPool)
|
||||||
|
m_ExploratoryPool = CreateTunnelPool (i2p::context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_InboundTunnels.size () < 15) // TODO: store exploratory tunnels explicitly
|
if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 5)
|
||||||
{
|
{
|
||||||
// trying to create one more inbound tunnel
|
// trying to create one more inbound tunnel
|
||||||
if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3)
|
LogPrint ("Creating one hop inbound tunnel...");
|
||||||
{
|
CreateTunnel<InboundTunnel> (
|
||||||
LogPrint ("Creating one hop inbound tunnel...");
|
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
||||||
CreateTunnel<InboundTunnel> (
|
{
|
||||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
i2p::data::netdb.GetRandomRouter ()
|
||||||
{
|
}));
|
||||||
i2p::data::netdb.GetRandomRouter ()
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OutboundTunnel * outboundTunnel = GetNextOutboundTunnel ();
|
|
||||||
LogPrint ("Creating two hops inbound tunnel...");
|
|
||||||
auto router = outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router;
|
|
||||||
auto firstHop = i2p::data::netdb.GetRandomRouter (outboundTunnel->GetEndpointRouter ());
|
|
||||||
CreateTunnel<InboundTunnel> (
|
|
||||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
|
||||||
{
|
|
||||||
firstHop,
|
|
||||||
router != &i2p::context.GetRouterInfo () ? router : i2p::data::netdb.GetRandomRouter (firstHop)
|
|
||||||
}),
|
|
||||||
outboundTunnel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,8 +459,8 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
for (auto& it: m_Pools)
|
for (auto& it: m_Pools)
|
||||||
{
|
{
|
||||||
it->CreateTunnels ();
|
it.second->CreateTunnels ();
|
||||||
it->TestTunnels ();
|
it.second->TestTunnels ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,49 +509,5 @@ namespace tunnel
|
|||||||
&i2p::context.GetRouterInfo ()
|
&i2p::context.GetRouterInfo ()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
OutboundTunnel * Tunnels::CreateOneHopOutboundTestTunnel (InboundTunnel * replyTunnel)
|
|
||||||
{
|
|
||||||
return CreateTunnel<OutboundTunnel> (replyTunnel->GetTunnelConfig ()->Invert ());
|
|
||||||
}
|
|
||||||
|
|
||||||
InboundTunnel * Tunnels::CreateOneHopInboundTestTunnel (OutboundTunnel * outboundTunnel)
|
|
||||||
{
|
|
||||||
i2p::ntcp::NTCPSession * peer = i2p::transports.GetNextNTCPSession ();
|
|
||||||
if (peer)
|
|
||||||
{
|
|
||||||
const i2p::data::RouterInfo& router = peer->GetRemoteRouterInfo ();
|
|
||||||
return CreateTunnel<InboundTunnel> (
|
|
||||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>{&router}),
|
|
||||||
outboundTunnel);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint ("No established peers");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutboundTunnel * Tunnels::CreateTwoHopsOutboundTestTunnel (InboundTunnel * replyTunnel)
|
|
||||||
{
|
|
||||||
return CreateTunnel<OutboundTunnel> (replyTunnel->GetTunnelConfig ()->Invert ());
|
|
||||||
}
|
|
||||||
|
|
||||||
InboundTunnel * Tunnels::CreateTwoHopsInboundTestTunnel (OutboundTunnel * outboundTunnel)
|
|
||||||
{
|
|
||||||
i2p::ntcp::NTCPSession * peer = i2p::transports.GetNextNTCPSession ();
|
|
||||||
if (peer)
|
|
||||||
{
|
|
||||||
const i2p::data::RouterInfo& router = peer->GetRemoteRouterInfo ();
|
|
||||||
return CreateTunnel<InboundTunnel> (
|
|
||||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
|
||||||
{
|
|
||||||
&router,
|
|
||||||
&i2p::context.GetRouterInfo ()
|
|
||||||
}),
|
|
||||||
outboundTunnel);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint ("No established peers");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
Tunnel.h
14
Tunnel.h
@ -7,6 +7,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
#include <cryptopp/modes.h>
|
#include <cryptopp/modes.h>
|
||||||
#include <cryptopp/aes.h>
|
#include <cryptopp/aes.h>
|
||||||
#include "Queue.h"
|
#include "Queue.h"
|
||||||
@ -83,6 +84,7 @@ namespace tunnel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
std::mutex m_SendMutex;
|
||||||
TunnelGateway m_Gateway;
|
TunnelGateway m_Gateway;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,8 +116,8 @@ namespace tunnel
|
|||||||
InboundTunnel * GetInboundTunnel (uint32_t tunnelID);
|
InboundTunnel * GetInboundTunnel (uint32_t tunnelID);
|
||||||
Tunnel * GetPendingTunnel (uint32_t replyMsgID);
|
Tunnel * GetPendingTunnel (uint32_t replyMsgID);
|
||||||
InboundTunnel * GetNextInboundTunnel ();
|
InboundTunnel * GetNextInboundTunnel ();
|
||||||
std::vector<InboundTunnel *> GetInboundTunnels (int num) const;
|
|
||||||
OutboundTunnel * GetNextOutboundTunnel ();
|
OutboundTunnel * GetNextOutboundTunnel ();
|
||||||
|
TunnelPool * GetExploratoryPool () const { return m_ExploratoryPool; };
|
||||||
TransitTunnel * GetTransitTunnel (uint32_t tunnelID);
|
TransitTunnel * GetTransitTunnel (uint32_t tunnelID);
|
||||||
void AddTransitTunnel (TransitTunnel * tunnel);
|
void AddTransitTunnel (TransitTunnel * tunnel);
|
||||||
void AddOutboundTunnel (OutboundTunnel * newTunnel);
|
void AddOutboundTunnel (OutboundTunnel * newTunnel);
|
||||||
@ -123,14 +125,9 @@ namespace tunnel
|
|||||||
void PostTunnelData (I2NPMessage * msg);
|
void PostTunnelData (I2NPMessage * msg);
|
||||||
template<class TTunnel>
|
template<class TTunnel>
|
||||||
TTunnel * CreateTunnel (TunnelConfig * config, OutboundTunnel * outboundTunnel = 0);
|
TTunnel * CreateTunnel (TunnelConfig * config, OutboundTunnel * outboundTunnel = 0);
|
||||||
TunnelPool * CreateTunnelPool (i2p::data::LocalDestination * localDestination);
|
TunnelPool * CreateTunnelPool (i2p::data::LocalDestination& localDestination);
|
||||||
void DeleteTunnelPool (TunnelPool * pool);
|
void DeleteTunnelPool (TunnelPool * pool);
|
||||||
|
|
||||||
OutboundTunnel * CreateOneHopOutboundTestTunnel (InboundTunnel * replyTunnel);
|
|
||||||
InboundTunnel * CreateOneHopInboundTestTunnel (OutboundTunnel * outboundTunnel = 0);
|
|
||||||
OutboundTunnel * CreateTwoHopsOutboundTestTunnel (InboundTunnel * replyTunnel);
|
|
||||||
InboundTunnel * CreateTwoHopsInboundTestTunnel (OutboundTunnel * outboundTunnel = 0);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
@ -152,7 +149,8 @@ namespace tunnel
|
|||||||
std::map<uint32_t, InboundTunnel *> m_InboundTunnels;
|
std::map<uint32_t, InboundTunnel *> m_InboundTunnels;
|
||||||
std::list<OutboundTunnel *> m_OutboundTunnels;
|
std::list<OutboundTunnel *> m_OutboundTunnels;
|
||||||
std::map<uint32_t, TransitTunnel *> m_TransitTunnels;
|
std::map<uint32_t, TransitTunnel *> m_TransitTunnels;
|
||||||
std::list<TunnelPool *> m_Pools;
|
std::map<i2p::data::IdentHash, TunnelPool *> m_Pools;
|
||||||
|
TunnelPool * m_ExploratoryPool;
|
||||||
i2p::util::Queue<I2NPMessage> m_Queue;
|
i2p::util::Queue<I2NPMessage> m_Queue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
#include <cryptopp/dh.h>
|
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "CryptoConst.h"
|
#include "CryptoConst.h"
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "RouterContext.h"
|
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
#include "TunnelPool.h"
|
#include "TunnelPool.h"
|
||||||
|
|
||||||
@ -12,12 +10,9 @@ namespace i2p
|
|||||||
{
|
{
|
||||||
namespace tunnel
|
namespace tunnel
|
||||||
{
|
{
|
||||||
TunnelPool::TunnelPool (i2p::data::LocalDestination * localDestination, int numTunnels):
|
TunnelPool::TunnelPool (i2p::data::LocalDestination& localDestination, int numTunnels):
|
||||||
m_LocalDestination (localDestination), m_NumTunnels (numTunnels), m_LastOutboundTunnel (nullptr)
|
m_LocalDestination (localDestination), m_NumTunnels (numTunnels), m_LastOutboundTunnel (nullptr)
|
||||||
{
|
{
|
||||||
CryptoPP::AutoSeededRandomPool rnd;
|
|
||||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
|
||||||
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnelPool::~TunnelPool ()
|
TunnelPool::~TunnelPool ()
|
||||||
@ -40,8 +35,7 @@ namespace tunnel
|
|||||||
expiredTunnel->SetTunnelPool (nullptr);
|
expiredTunnel->SetTunnelPool (nullptr);
|
||||||
m_InboundTunnels.erase (expiredTunnel);
|
m_InboundTunnels.erase (expiredTunnel);
|
||||||
}
|
}
|
||||||
if (m_LocalDestination)
|
m_LocalDestination.UpdateLeaseSet ();
|
||||||
m_LocalDestination->UpdateLeaseSet ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel)
|
void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel)
|
||||||
@ -92,7 +86,22 @@ namespace tunnel
|
|||||||
m_LastOutboundTunnel = tunnel;
|
m_LastOutboundTunnel = tunnel;
|
||||||
return tunnel;
|
return tunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InboundTunnel * TunnelPool::GetNextInboundTunnel ()
|
||||||
|
{
|
||||||
|
return GetNextTunnel (m_InboundTunnels);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TTunnels>
|
||||||
|
typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels)
|
||||||
|
{
|
||||||
|
if (tunnels.empty ()) return nullptr;
|
||||||
|
for (auto it: tunnels)
|
||||||
|
if (!it->IsFailed ())
|
||||||
|
return it;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void TunnelPool::CreateTunnels ()
|
void TunnelPool::CreateTunnels ()
|
||||||
{
|
{
|
||||||
int num = m_InboundTunnels.size ();
|
int num = m_InboundTunnels.size ();
|
||||||
|
19
TunnelPool.h
19
TunnelPool.h
@ -9,6 +9,7 @@
|
|||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
#include "TunnelBase.h"
|
#include "TunnelBase.h"
|
||||||
|
#include "RouterContext.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -22,12 +23,13 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TunnelPool (i2p::data::LocalDestination * localDestination, int numTunnels = 5);
|
TunnelPool (i2p::data::LocalDestination& localDestination, int numTunnels = 5);
|
||||||
~TunnelPool ();
|
~TunnelPool ();
|
||||||
|
|
||||||
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
const uint8_t * GetEncryptionPrivateKey () const { return m_LocalDestination.GetEncryptionPrivateKey (); };
|
||||||
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; };
|
const uint8_t * GetEncryptionPublicKey () const { return m_LocalDestination.GetEncryptionPublicKey (); };
|
||||||
|
bool IsExploratory () const { return m_LocalDestination.GetIdentHash () == i2p::context.GetIdentHash (); };
|
||||||
|
|
||||||
void CreateTunnels ();
|
void CreateTunnels ();
|
||||||
void TunnelCreated (InboundTunnel * createdTunnel);
|
void TunnelCreated (InboundTunnel * createdTunnel);
|
||||||
void TunnelExpired (InboundTunnel * expiredTunnel);
|
void TunnelExpired (InboundTunnel * expiredTunnel);
|
||||||
@ -35,7 +37,9 @@ namespace tunnel
|
|||||||
void TunnelExpired (OutboundTunnel * expiredTunnel);
|
void TunnelExpired (OutboundTunnel * expiredTunnel);
|
||||||
std::vector<InboundTunnel *> GetInboundTunnels (int num) const;
|
std::vector<InboundTunnel *> GetInboundTunnels (int num) const;
|
||||||
OutboundTunnel * GetNextOutboundTunnel ();
|
OutboundTunnel * GetNextOutboundTunnel ();
|
||||||
|
InboundTunnel * GetNextInboundTunnel ();
|
||||||
|
const i2p::data::IdentHash& GetIdentHash () { return m_LocalDestination.GetIdentHash (); };
|
||||||
|
|
||||||
void TestTunnels ();
|
void TestTunnels ();
|
||||||
void ProcessDeliveryStatus (I2NPMessage * msg);
|
void ProcessDeliveryStatus (I2NPMessage * msg);
|
||||||
|
|
||||||
@ -43,11 +47,12 @@ namespace tunnel
|
|||||||
|
|
||||||
void CreateInboundTunnel ();
|
void CreateInboundTunnel ();
|
||||||
void CreateOutboundTunnel ();
|
void CreateOutboundTunnel ();
|
||||||
|
template<class TTunnels>
|
||||||
|
typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
i2p::data::LocalDestination& m_LocalDestination;
|
||||||
i2p::data::LocalDestination * m_LocalDestination;
|
|
||||||
int m_NumTunnels;
|
int m_NumTunnels;
|
||||||
std::set<InboundTunnel *, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
|
std::set<InboundTunnel *, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
|
||||||
std::set<OutboundTunnel *, TunnelCreationTimeCmp> m_OutboundTunnels;
|
std::set<OutboundTunnel *, TunnelCreationTimeCmp> m_OutboundTunnels;
|
||||||
|
113
build/CMakeLists.txt
Normal file
113
build/CMakeLists.txt
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
cmake_minimum_required ( VERSION 2.8 )
|
||||||
|
project ( i2pd )
|
||||||
|
|
||||||
|
# Default build is Debug
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
|
||||||
|
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall")
|
||||||
|
|
||||||
|
set ( SRC_DIR ".." )
|
||||||
|
set ( INC_DIR ".." )
|
||||||
|
|
||||||
|
|
||||||
|
add_definitions ( "-std=c++0x -Wall" )
|
||||||
|
|
||||||
|
set ( SOURCES
|
||||||
|
AddressBook.cpp
|
||||||
|
Garlic.cpp
|
||||||
|
HTTPServer.cpp
|
||||||
|
i2p.cpp
|
||||||
|
Identity.cpp
|
||||||
|
Log.cpp
|
||||||
|
NTCPSession.cpp
|
||||||
|
RouterContext.cpp
|
||||||
|
SSU.cpp
|
||||||
|
TransitTunnel.cpp
|
||||||
|
Tunnel.cpp
|
||||||
|
TunnelGateway.cpp
|
||||||
|
UPnP.cpp
|
||||||
|
base64.cpp
|
||||||
|
HTTPProxy.cpp
|
||||||
|
I2NPProtocol.cpp
|
||||||
|
LeaseSet.cpp
|
||||||
|
NetDb.cpp
|
||||||
|
Reseed.cpp
|
||||||
|
RouterInfo.cpp
|
||||||
|
Streaming.cpp
|
||||||
|
Transports.cpp
|
||||||
|
TunnelEndpoint.cpp
|
||||||
|
TunnelPool.cpp
|
||||||
|
util.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set ( HEADERS
|
||||||
|
AddressBook.h
|
||||||
|
Garlic.h
|
||||||
|
HTTPServer.h
|
||||||
|
Identity.h
|
||||||
|
Log.h
|
||||||
|
NTCPSession.h
|
||||||
|
RouterContext.h
|
||||||
|
SSU.h
|
||||||
|
TransitTunnel.h
|
||||||
|
Tunnel.h
|
||||||
|
TunnelGateway.h
|
||||||
|
UPnP.h
|
||||||
|
base64.h
|
||||||
|
HTTPProxy.h
|
||||||
|
I2NPProtocol.h
|
||||||
|
LeaseSet.h
|
||||||
|
NetDb.h
|
||||||
|
Reseed.h
|
||||||
|
RouterInfo.h
|
||||||
|
Streaming.h
|
||||||
|
Transports.h
|
||||||
|
TunnelEndpoint.h
|
||||||
|
TunnelPool.h
|
||||||
|
util.h
|
||||||
|
)
|
||||||
|
|
||||||
|
source_group ("Header Files" FILES ${HEADERS})
|
||||||
|
source_group ("Source Files" FILES ${SOURCES})
|
||||||
|
|
||||||
|
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
||||||
|
|
||||||
|
find_package ( Threads REQUIRED )
|
||||||
|
|
||||||
|
find_package ( Boost COMPONENTS system filesystem regex program_options REQUIRED )
|
||||||
|
|
||||||
|
find_package ( CryptoPP REQUIRED )
|
||||||
|
|
||||||
|
# Check for libraries
|
||||||
|
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||||
|
message(FATAL_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CRYPTO++_INCLUDE_DIR)
|
||||||
|
message(FATAL_ERROR "Could not find Crypto++. Please download and install it first!")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# End checks
|
||||||
|
|
||||||
|
|
||||||
|
include_directories ( ${Boost_INCLUDE_DIRS} ${CRYPTO++_INCLUDE_DIR})
|
||||||
|
|
||||||
|
|
||||||
|
unset ( TMP )
|
||||||
|
foreach ( src ${SOURCES} )
|
||||||
|
list ( APPEND TMP "${SRC_DIR}/${src}" )
|
||||||
|
endforeach ()
|
||||||
|
set ( SOURCES ${TMP} )
|
||||||
|
|
||||||
|
unset ( TMP )
|
||||||
|
foreach ( hdr ${HEADERS} )
|
||||||
|
list ( APPEND TMP "${INC_DIR}/${hdr}" )
|
||||||
|
endforeach ()
|
||||||
|
set ( HEADERS ${TMP} )
|
||||||
|
|
||||||
|
|
||||||
|
add_executable ( ${PROJECT_NAME} WIN32 ${HEADERS} ${SOURCES} )
|
||||||
|
|
||||||
|
target_link_libraries( ${PROJECT_NAME} ${Boost_LIBRARIES} ${CRYPTO++_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} )
|
35
build/cmake_modules/FindCryptoPP.cmake
Normal file
35
build/cmake_modules/FindCryptoPP.cmake
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# - Find Crypto++
|
||||||
|
|
||||||
|
if(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||||
|
set(CRYPTO++_FOUND TRUE)
|
||||||
|
|
||||||
|
else(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||||
|
find_path(CRYPTO++_INCLUDE_DIR cryptlib.h
|
||||||
|
/usr/include/crypto++
|
||||||
|
/usr/include/cryptopp
|
||||||
|
/usr/local/include/crypto++
|
||||||
|
/usr/local/include/cryptopp
|
||||||
|
/opt/local/include/crypto++
|
||||||
|
/opt/local/include/cryptopp
|
||||||
|
$ENV{SystemDrive}/Crypto++/include
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(CRYPTO++_LIBRARIES NAMES cryptopp
|
||||||
|
PATHS
|
||||||
|
/usr/lib
|
||||||
|
/usr/local/lib
|
||||||
|
/opt/local/lib
|
||||||
|
$ENV{SystemDrive}/Crypto++/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||||
|
set(CRYPTO++_FOUND TRUE)
|
||||||
|
message(STATUS "Found Crypto++: ${CRYPTO++_INCLUDE_DIR}, ${CRYPTO++_LIBRARIES}")
|
||||||
|
else(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||||
|
set(CRYPTO++_FOUND FALSE)
|
||||||
|
message(STATUS "Crypto++ not found.")
|
||||||
|
endif(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
||||||
|
|
||||||
|
mark_as_advanced(CRYPTO++_INCLUDE_DIR CRYPTO++_LIBRARIES)
|
||||||
|
|
||||||
|
endif(CRYPTO++_INCLUDE_DIR AND CRYPTO++_LIBRARIES)
|
Loading…
x
Reference in New Issue
Block a user