mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2024-11-04 06:00:37 +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/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
@ -200,7 +199,6 @@ $RECYCLE.BIN/
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist/
|
||||
build/
|
||||
eggs/
|
||||
parts/
|
||||
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:
|
||||
|
||||
AddressBook (): m_IsLoaded (false) {};
|
||||
|
||||
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;
|
||||
}
|
||||
AddressBook ();
|
||||
const IdentHash * FindAddress (const std::string& address);
|
||||
|
||||
private:
|
||||
|
||||
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:
|
||||
void LoadHosts ();
|
||||
|
||||
std::map<std::string, IdentHash> m_Addresses;
|
||||
bool m_IsLoaded;
|
||||
|
@ -245,7 +245,7 @@ namespace util
|
||||
for (auto it: i2p::tunnel::tunnels.GetOutboundTunnels ())
|
||||
{
|
||||
it->GetTunnelConfig ()->Print (s);
|
||||
if (it->GetTunnelPool ())
|
||||
if (it->GetTunnelPool () && !it->GetTunnelPool ()->IsExploratory ())
|
||||
s << " " << "Pool";
|
||||
if (it->IsFailed ())
|
||||
s << " " << "Failed";
|
||||
@ -255,7 +255,7 @@ namespace util
|
||||
for (auto it: i2p::tunnel::tunnels.GetInboundTunnels ())
|
||||
{
|
||||
it.second->GetTunnelConfig ()->Print (s);
|
||||
if (it.second->GetTunnelPool ())
|
||||
if (it.second->GetTunnelPool () && !it.second->GetTunnelPool ()->IsExploratory ())
|
||||
s << " " << "Pool";
|
||||
if (it.second->IsFailed ())
|
||||
s << " " << "Failed";
|
||||
|
@ -1,8 +1,12 @@
|
||||
#ifndef I2PENDIAN_H__
|
||||
#define I2PENDIAN_H__
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef __linux__
|
||||
#include <endian.h>
|
||||
#elif __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#elif __MACH__ // Mac OS X
|
||||
#include <machine/endian.h>
|
||||
#else
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -53,6 +53,14 @@ namespace data
|
||||
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)
|
||||
{
|
||||
uint8_t buf[41]; // ident + yyyymmdd
|
||||
|
12
Identity.h
12
Identity.h
@ -11,6 +11,12 @@ namespace data
|
||||
{
|
||||
#pragma pack(1)
|
||||
|
||||
struct DHKeysPair // transient keys for transport sessions
|
||||
{
|
||||
uint8_t publicKey[256];
|
||||
uint8_t privateKey[256];
|
||||
};
|
||||
|
||||
struct Keys
|
||||
{
|
||||
uint8_t privateKey[256];
|
||||
@ -71,6 +77,7 @@ namespace data
|
||||
|
||||
IdentHash CalculateIdentHash (const Identity& identity);
|
||||
Keys CreateRandomKeys ();
|
||||
void CreateRandomDHKeysPair (DHKeysPair * keys); // for transport sessions
|
||||
|
||||
// kademlia
|
||||
struct RoutingKey
|
||||
@ -118,7 +125,10 @@ namespace data
|
||||
{
|
||||
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/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/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o
|
||||
obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o
|
||||
INCFLAGS =
|
||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
||||
LIBS =
|
||||
|
@ -24,13 +24,19 @@ namespace ntcp
|
||||
m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false),
|
||||
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)
|
||||
{
|
||||
CryptoPP::DH dh (elgp, elgg);
|
||||
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");
|
||||
Terminate ();
|
||||
@ -50,11 +56,19 @@ namespace ntcp
|
||||
{
|
||||
m_IsEstablished = false;
|
||||
m_Socket.close ();
|
||||
for (auto it :m_DelayedMessages)
|
||||
delete it;
|
||||
m_DelayedMessages.clear ();
|
||||
// TODO: notify tunnels
|
||||
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;
|
||||
LogPrint ("NTCP session terminated");
|
||||
}
|
||||
@ -78,7 +92,7 @@ namespace ntcp
|
||||
void NTCPSession::ClientLogin ()
|
||||
{
|
||||
// send Phase1
|
||||
const uint8_t * x = i2p::context.GetRouterIdentity ().publicKey;
|
||||
const uint8_t * x = m_DHKeysPair->publicKey;
|
||||
memcpy (m_Phase1.pubKey, x, 256);
|
||||
CryptoPP::SHA256().CalculateDigest(m_Phase1.HXxorHI, x, 256);
|
||||
const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash ();
|
||||
@ -143,7 +157,7 @@ namespace ntcp
|
||||
|
||||
void NTCPSession::SendPhase2 ()
|
||||
{
|
||||
const uint8_t * y = i2p::context.GetRouterIdentity ().publicKey;
|
||||
const uint8_t * y = m_DHKeysPair->publicKey;
|
||||
memcpy (m_Phase2.pubKey, y, 256);
|
||||
uint8_t xy[512];
|
||||
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));
|
||||
// verify
|
||||
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);
|
||||
CryptoPP::SHA256().CalculateDigest(hxy, xy, 512);
|
||||
if (memcmp (hxy, m_Phase2.encrypted.hxy, 32))
|
||||
@ -321,6 +335,7 @@ namespace ntcp
|
||||
if (ecode)
|
||||
{
|
||||
LogPrint ("Phase 4 read error: ", ecode.message ());
|
||||
GetRemoteRouterInfo ().SetUnreachable (true); // this router doesn't like us
|
||||
Terminate ();
|
||||
}
|
||||
else
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <cryptopp/modes.h>
|
||||
#include <cryptopp/aes.h>
|
||||
#include <cryptopp/adler32.h>
|
||||
#include "Identity.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "I2NPProtocol.h"
|
||||
|
||||
@ -66,7 +67,7 @@ namespace ntcp
|
||||
public:
|
||||
|
||||
NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo);
|
||||
virtual ~NTCPSession () {};
|
||||
virtual ~NTCPSession ();
|
||||
|
||||
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
|
||||
bool IsEstablished () const { return m_IsEstablished; };
|
||||
@ -120,6 +121,7 @@ namespace ntcp
|
||||
boost::asio::ip::tcp::socket m_Socket;
|
||||
boost::asio::deadline_timer m_TerminationTimer;
|
||||
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>::Encryption m_Encryption;
|
||||
|
11
NetDb.cpp
11
NetDb.cpp
@ -442,9 +442,11 @@ namespace data
|
||||
|
||||
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)
|
||||
{
|
||||
RequestedDestination * d1 = CreateRequestedDestination (router, false, false);
|
||||
@ -532,8 +534,9 @@ namespace data
|
||||
|
||||
void NetDb::Explore ()
|
||||
{
|
||||
auto outbound = i2p::tunnel::tunnels.GetNextOutboundTunnel ();
|
||||
auto inbound = i2p::tunnel::tunnels.GetNextInboundTunnel ();
|
||||
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
|
||||
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr;
|
||||
if (outbound && inbound)
|
||||
{
|
||||
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
||||
|
@ -9,6 +9,8 @@ on Windows
|
||||
|
||||
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
|
||||
-------
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <cryptopp/dsa.h>
|
||||
#include <cryptopp/osrng.h>
|
||||
#include "Identity.h"
|
||||
#include "RouterInfo.h"
|
||||
|
||||
namespace i2p
|
||||
@ -11,7 +12,7 @@ namespace i2p
|
||||
const char ROUTER_INFO[] = "router.info";
|
||||
const char ROUTER_KEYS[] = "router.keys";
|
||||
|
||||
class RouterContext
|
||||
class RouterContext: public i2p::data::LocalDestination
|
||||
{
|
||||
public:
|
||||
|
||||
@ -28,6 +29,12 @@ namespace i2p
|
||||
void OverrideNTCPAddress (const char * host, int port); // temporary
|
||||
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:
|
||||
|
||||
void CreateNewRouter ();
|
||||
|
71
SSU.cpp
71
SSU.cpp
@ -6,6 +6,7 @@
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "RouterContext.h"
|
||||
#include "Transports.h"
|
||||
#include "hmac.h"
|
||||
#include "SSU.h"
|
||||
|
||||
@ -14,23 +15,23 @@ namespace i2p
|
||||
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),
|
||||
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 ()
|
||||
{
|
||||
if (m_ConnectTimer)
|
||||
delete m_ConnectTimer;
|
||||
delete m_DHKeysPair;
|
||||
}
|
||||
|
||||
void SSUSession::CreateAESandMacKey (uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey)
|
||||
{
|
||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||
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");
|
||||
return;
|
||||
@ -110,8 +111,7 @@ namespace ssu
|
||||
case PAYLOAD_TYPE_SESSION_DESTROYED:
|
||||
{
|
||||
LogPrint ("SSU session destroy received");
|
||||
if (m_Server)
|
||||
m_Server->DeleteSession (this); // delete this
|
||||
m_Server.DeleteSession (this); // delete this
|
||||
break;
|
||||
}
|
||||
case PAYLOAD_TYPE_RELAY_INTRO:
|
||||
@ -166,11 +166,11 @@ namespace ssu
|
||||
{
|
||||
m_State = eSessionStateCreatedReceived;
|
||||
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 * payload = buf + sizeof (SSUHeader);
|
||||
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
|
||||
payload += 256;
|
||||
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 * payload = buf + sizeof (SSUHeader);
|
||||
memcpy (payload, i2p::context.GetRouterIdentity ().publicKey, 256);
|
||||
memcpy (payload, m_DHKeysPair->publicKey, 256); // x
|
||||
payload[256] = 4; // we assume ipv4
|
||||
*(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);
|
||||
|
||||
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)
|
||||
@ -276,7 +276,7 @@ namespace ssu
|
||||
rnd.GenerateBlock (iv, 16); // random iv
|
||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey);
|
||||
m_State = eSessionRelayRequestSent;
|
||||
m_Server->Send (buf, 96, m_RemoteEndpoint);
|
||||
m_Server.Send (buf, 96, m_RemoteEndpoint);
|
||||
}
|
||||
|
||||
void SSUSession::SendSessionCreated (const uint8_t * x)
|
||||
@ -293,7 +293,7 @@ namespace ssu
|
||||
|
||||
uint8_t buf[368 + 18];
|
||||
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
|
||||
payload += 256;
|
||||
*payload = 4; // we assume ipv4
|
||||
@ -323,7 +323,7 @@ namespace ssu
|
||||
// encrypt message with intro key
|
||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey);
|
||||
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)
|
||||
@ -347,7 +347,7 @@ namespace ssu
|
||||
|
||||
// signature
|
||||
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 + 512, ourAddress, 6); // our address/port as seem by party
|
||||
*(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
|
||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CONFIRMED, buf, 480, m_SessionKey, iv, m_MacKey);
|
||||
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)
|
||||
@ -390,7 +390,7 @@ namespace ssu
|
||||
uint16_t remotePort = be16toh (*(uint16_t *)(payload));
|
||||
payload += 2;
|
||||
boost::asio::ip::udp::endpoint newRemoteEndpoint(remoteIP, remotePort);
|
||||
m_Server->ReassignSession (m_RemoteEndpoint, newRemoteEndpoint);
|
||||
m_Server.ReassignSession (m_RemoteEndpoint, newRemoteEndpoint);
|
||||
m_RemoteEndpoint = newRemoteEndpoint;
|
||||
payload++;
|
||||
boost::asio::ip::address_v4 ourIP (be32toh (*(uint32_t* )(payload)));
|
||||
@ -494,13 +494,10 @@ namespace ssu
|
||||
{
|
||||
if (m_State == eSessionStateUnknown)
|
||||
{
|
||||
if (m_Server)
|
||||
{
|
||||
m_ConnectTimer = new boost::asio::deadline_timer (m_Server->GetService ());
|
||||
m_ConnectTimer->expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT));
|
||||
m_ConnectTimer->async_wait (boost::bind (&SSUSession::HandleConnectTimer,
|
||||
this, boost::asio::placeholders::error));
|
||||
}
|
||||
// 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));
|
||||
SendSessionRequest ();
|
||||
}
|
||||
}
|
||||
@ -516,8 +513,15 @@ namespace ssu
|
||||
}
|
||||
|
||||
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 ()
|
||||
@ -548,8 +552,7 @@ namespace ssu
|
||||
{
|
||||
m_State = eSessionStateFailed;
|
||||
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
|
||||
// encrypt message with session key
|
||||
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 ()
|
||||
@ -715,7 +718,7 @@ namespace ssu
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_Server->Send (buf, 48, m_RemoteEndpoint);
|
||||
m_Server.Send (buf, 48, m_RemoteEndpoint);
|
||||
}
|
||||
|
||||
void SSUSession::Send (i2p::I2NPMessage * msg)
|
||||
@ -755,7 +758,7 @@ namespace ssu
|
||||
rnd.GenerateBlock (iv, 16); // random iv
|
||||
// encrypt message with session key
|
||||
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)
|
||||
{
|
||||
@ -815,7 +818,7 @@ namespace ssu
|
||||
session = it->second;
|
||||
if (!session)
|
||||
{
|
||||
session = new SSUSession (this, m_SenderEndpoint);
|
||||
session = new SSUSession (*this, m_SenderEndpoint);
|
||||
m_Sessions[m_SenderEndpoint] = session;
|
||||
LogPrint ("New SSU session from ", m_SenderEndpoint.address ().to_string (), ":", m_SenderEndpoint.port (), " created");
|
||||
}
|
||||
@ -856,7 +859,7 @@ namespace ssu
|
||||
if (!router->UsesIntroducer ())
|
||||
{
|
||||
// connect directly
|
||||
session = new SSUSession (this, remoteEndpoint, router);
|
||||
session = new SSUSession (*this, remoteEndpoint, router);
|
||||
m_Sessions[remoteEndpoint] = session;
|
||||
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (), "] ",
|
||||
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port (), " created");
|
||||
@ -869,7 +872,7 @@ namespace ssu
|
||||
{
|
||||
auto& introducer = address->introducers[0]; // TODO:
|
||||
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;
|
||||
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (),
|
||||
"] through introducer ", introducerEndpoint.address ().to_string (), ":", introducerEndpoint.port ());
|
||||
|
8
SSU.h
8
SSU.h
@ -8,6 +8,7 @@
|
||||
#include <cryptopp/modes.h>
|
||||
#include <cryptopp/aes.h>
|
||||
#include "I2PEndian.h"
|
||||
#include "Identity.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "I2NPProtocol.h"
|
||||
|
||||
@ -68,7 +69,7 @@ namespace ssu
|
||||
{
|
||||
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);
|
||||
void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
|
||||
~SSUSession ();
|
||||
@ -109,10 +110,11 @@ namespace ssu
|
||||
|
||||
private:
|
||||
|
||||
SSUServer * m_Server;
|
||||
SSUServer& m_Server;
|
||||
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
|
||||
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;
|
||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_Encryption;
|
||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption m_Decryption;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <cryptopp/dh.h>
|
||||
#include <cryptopp/gzip.h>
|
||||
#include "Log.h"
|
||||
#include "RouterInfo.h"
|
||||
@ -347,7 +348,9 @@ namespace stream
|
||||
m_IdentHash = i2p::data::CalculateIdentHash (m_Keys.pub);
|
||||
m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag,
|
||||
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)
|
||||
@ -357,7 +360,9 @@ namespace stream
|
||||
s.read ((char *)&m_Keys, sizeof (m_Keys));
|
||||
else
|
||||
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 ()
|
||||
|
@ -138,6 +138,9 @@ namespace stream
|
||||
|
||||
// implements LocalDestination
|
||||
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:
|
||||
|
||||
@ -148,7 +151,8 @@ namespace stream
|
||||
std::map<uint32_t, Stream *> m_Streams;
|
||||
i2p::data::PrivateKeys m_Keys;
|
||||
i2p::data::IdentHash m_IdentHash;
|
||||
|
||||
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
||||
|
||||
i2p::tunnel::TunnelPool * m_Pool;
|
||||
I2NPMessage * m_LeaseSet;
|
||||
|
||||
|
@ -9,10 +9,76 @@ using namespace i2p::data;
|
||||
|
||||
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 ():
|
||||
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 ()
|
||||
{
|
||||
m_DHKeysPairSupplier.Start ();
|
||||
m_IsRunning = true;
|
||||
m_Thread = new std::thread (std::bind (&Transports::Run, this));
|
||||
m_Timer = new boost::asio::deadline_timer (m_Service);
|
||||
@ -74,6 +141,7 @@ namespace i2p
|
||||
delete m_SSUServer;
|
||||
}
|
||||
|
||||
m_DHKeysPairSupplier.Stop ();
|
||||
m_IsRunning = false;
|
||||
m_Service.stop ();
|
||||
if (m_Thread)
|
||||
@ -171,7 +239,7 @@ namespace i2p
|
||||
// existing session not found. create new
|
||||
// try NTCP first
|
||||
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);
|
||||
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__
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <boost/asio.hpp>
|
||||
#include "NTCPSession.h"
|
||||
#include "SSU.h"
|
||||
#include "RouterInfo.h"
|
||||
#include "I2NPProtocol.h"
|
||||
#include "Identity.h"
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -24,6 +54,7 @@ namespace i2p
|
||||
void Stop ();
|
||||
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
i2p::data::DHKeysPair * GetNextDHKeysPair ();
|
||||
|
||||
void AddNTCPSession (i2p::ntcp::NTCPSession * session);
|
||||
void RemoveNTCPSession (i2p::ntcp::NTCPSession * session);
|
||||
@ -54,6 +85,8 @@ namespace i2p
|
||||
i2p::ssu::SSUServer * m_SSUServer;
|
||||
boost::asio::deadline_timer * m_Timer;
|
||||
|
||||
DHKeysPairSupplier m_DHKeysPairSupplier;
|
||||
|
||||
public:
|
||||
|
||||
// for HTTP only
|
||||
|
153
Tunnel.cpp
153
Tunnel.cpp
@ -154,11 +154,14 @@ namespace tunnel
|
||||
else
|
||||
block.deliveryType = eDeliveryTypeLocal;
|
||||
block.data = msg;
|
||||
|
||||
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||
m_Gateway.SendTunnelDataMsg (block);
|
||||
}
|
||||
|
||||
void OutboundTunnel::SendTunnelDataMsg (std::vector<TunnelMessageBlock> msgs)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_SendMutex);
|
||||
for (auto& it : msgs)
|
||||
m_Gateway.PutTunnelDataMsg (it);
|
||||
m_Gateway.SendBuffer ();
|
||||
@ -167,7 +170,7 @@ namespace tunnel
|
||||
Tunnels tunnels;
|
||||
|
||||
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 ();
|
||||
|
||||
for (auto& it: m_Pools)
|
||||
delete it;
|
||||
delete it.second;
|
||||
m_Pools.clear ();
|
||||
}
|
||||
|
||||
@ -237,23 +240,6 @@ namespace 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 ()
|
||||
{
|
||||
@ -272,17 +258,20 @@ namespace tunnel
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination * localDestination)
|
||||
TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination& localDestination)
|
||||
{
|
||||
auto pool = new TunnelPool (localDestination);
|
||||
m_Pools.push_back (pool);
|
||||
m_Pools[pool->GetIdentHash ()] = pool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
void Tunnels::DeleteTunnelPool (TunnelPool * pool)
|
||||
{
|
||||
m_Pools.remove (pool);
|
||||
delete pool;
|
||||
if (pool)
|
||||
{
|
||||
m_Pools.erase (pool->GetIdentHash ());
|
||||
delete pool;
|
||||
}
|
||||
}
|
||||
|
||||
void Tunnels::AddTransitTunnel (TransitTunnel * tunnel)
|
||||
@ -398,35 +387,18 @@ namespace tunnel
|
||||
it++;
|
||||
}
|
||||
|
||||
if (m_OutboundTunnels.size () < 15) // TODO: store exploratory tunnels explicitly
|
||||
if (m_OutboundTunnels.size () < 5)
|
||||
{
|
||||
// trying to create one more oubound tunnel
|
||||
if (m_InboundTunnels.empty ()) return;
|
||||
|
||||
InboundTunnel * inboundTunnel = GetNextInboundTunnel ();
|
||||
if (m_OutboundTunnels.empty () || m_OutboundTunnels.size () < 3)
|
||||
{
|
||||
LogPrint ("Creating one hop outbound tunnel...");
|
||||
CreateTunnel<OutboundTunnel> (
|
||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
||||
{
|
||||
i2p::data::netdb.GetRandomRouter ()
|
||||
},
|
||||
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 ()));
|
||||
}
|
||||
if (!inboundTunnel) return;
|
||||
LogPrint ("Creating one hop outbound tunnel...");
|
||||
CreateTunnel<OutboundTunnel> (
|
||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
||||
{
|
||||
i2p::data::netdb.GetRandomRouter ()
|
||||
},
|
||||
inboundTunnel->GetTunnelConfig ()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,35 +423,20 @@ namespace tunnel
|
||||
{
|
||||
LogPrint ("Creating zero hops inbound tunnel...");
|
||||
CreateZeroHopsInboundTunnel ();
|
||||
if (!m_ExploratoryPool)
|
||||
m_ExploratoryPool = CreateTunnelPool (i2p::context);
|
||||
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
|
||||
if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3)
|
||||
{
|
||||
LogPrint ("Creating one hop inbound tunnel...");
|
||||
CreateTunnel<InboundTunnel> (
|
||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
||||
{
|
||||
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);
|
||||
}
|
||||
// trying to create one more inbound tunnel
|
||||
LogPrint ("Creating one hop inbound tunnel...");
|
||||
CreateTunnel<InboundTunnel> (
|
||||
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
|
||||
{
|
||||
i2p::data::netdb.GetRandomRouter ()
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,8 +459,8 @@ namespace tunnel
|
||||
{
|
||||
for (auto& it: m_Pools)
|
||||
{
|
||||
it->CreateTunnels ();
|
||||
it->TestTunnels ();
|
||||
it.second->CreateTunnels ();
|
||||
it.second->TestTunnels ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,49 +509,5 @@ namespace tunnel
|
||||
&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 <string>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <cryptopp/modes.h>
|
||||
#include <cryptopp/aes.h>
|
||||
#include "Queue.h"
|
||||
@ -83,6 +84,7 @@ namespace tunnel
|
||||
|
||||
private:
|
||||
|
||||
std::mutex m_SendMutex;
|
||||
TunnelGateway m_Gateway;
|
||||
};
|
||||
|
||||
@ -114,8 +116,8 @@ namespace tunnel
|
||||
InboundTunnel * GetInboundTunnel (uint32_t tunnelID);
|
||||
Tunnel * GetPendingTunnel (uint32_t replyMsgID);
|
||||
InboundTunnel * GetNextInboundTunnel ();
|
||||
std::vector<InboundTunnel *> GetInboundTunnels (int num) const;
|
||||
OutboundTunnel * GetNextOutboundTunnel ();
|
||||
TunnelPool * GetExploratoryPool () const { return m_ExploratoryPool; };
|
||||
TransitTunnel * GetTransitTunnel (uint32_t tunnelID);
|
||||
void AddTransitTunnel (TransitTunnel * tunnel);
|
||||
void AddOutboundTunnel (OutboundTunnel * newTunnel);
|
||||
@ -123,14 +125,9 @@ namespace tunnel
|
||||
void PostTunnelData (I2NPMessage * msg);
|
||||
template<class TTunnel>
|
||||
TTunnel * CreateTunnel (TunnelConfig * config, OutboundTunnel * outboundTunnel = 0);
|
||||
TunnelPool * CreateTunnelPool (i2p::data::LocalDestination * localDestination);
|
||||
TunnelPool * CreateTunnelPool (i2p::data::LocalDestination& localDestination);
|
||||
void DeleteTunnelPool (TunnelPool * pool);
|
||||
|
||||
OutboundTunnel * CreateOneHopOutboundTestTunnel (InboundTunnel * replyTunnel);
|
||||
InboundTunnel * CreateOneHopInboundTestTunnel (OutboundTunnel * outboundTunnel = 0);
|
||||
OutboundTunnel * CreateTwoHopsOutboundTestTunnel (InboundTunnel * replyTunnel);
|
||||
InboundTunnel * CreateTwoHopsInboundTestTunnel (OutboundTunnel * outboundTunnel = 0);
|
||||
|
||||
private:
|
||||
|
||||
void Run ();
|
||||
@ -152,7 +149,8 @@ namespace tunnel
|
||||
std::map<uint32_t, InboundTunnel *> m_InboundTunnels;
|
||||
std::list<OutboundTunnel *> m_OutboundTunnels;
|
||||
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;
|
||||
|
||||
public:
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include <cryptopp/dh.h>
|
||||
#include "I2PEndian.h"
|
||||
#include "CryptoConst.h"
|
||||
#include "Tunnel.h"
|
||||
#include "NetDb.h"
|
||||
#include "Timestamp.h"
|
||||
#include "RouterContext.h"
|
||||
#include "Garlic.h"
|
||||
#include "TunnelPool.h"
|
||||
|
||||
@ -12,12 +10,9 @@ namespace i2p
|
||||
{
|
||||
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)
|
||||
{
|
||||
CryptoPP::AutoSeededRandomPool rnd;
|
||||
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
|
||||
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||
}
|
||||
|
||||
TunnelPool::~TunnelPool ()
|
||||
@ -40,8 +35,7 @@ namespace tunnel
|
||||
expiredTunnel->SetTunnelPool (nullptr);
|
||||
m_InboundTunnels.erase (expiredTunnel);
|
||||
}
|
||||
if (m_LocalDestination)
|
||||
m_LocalDestination->UpdateLeaseSet ();
|
||||
m_LocalDestination.UpdateLeaseSet ();
|
||||
}
|
||||
|
||||
void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel)
|
||||
@ -92,7 +86,22 @@ namespace tunnel
|
||||
m_LastOutboundTunnel = 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 ()
|
||||
{
|
||||
int num = m_InboundTunnels.size ();
|
||||
|
19
TunnelPool.h
19
TunnelPool.h
@ -9,6 +9,7 @@
|
||||
#include "LeaseSet.h"
|
||||
#include "I2NPProtocol.h"
|
||||
#include "TunnelBase.h"
|
||||
#include "RouterContext.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -22,12 +23,13 @@ namespace tunnel
|
||||
{
|
||||
public:
|
||||
|
||||
TunnelPool (i2p::data::LocalDestination * localDestination, int numTunnels = 5);
|
||||
TunnelPool (i2p::data::LocalDestination& localDestination, int numTunnels = 5);
|
||||
~TunnelPool ();
|
||||
|
||||
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
||||
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; };
|
||||
|
||||
const uint8_t * GetEncryptionPrivateKey () const { return m_LocalDestination.GetEncryptionPrivateKey (); };
|
||||
const uint8_t * GetEncryptionPublicKey () const { return m_LocalDestination.GetEncryptionPublicKey (); };
|
||||
bool IsExploratory () const { return m_LocalDestination.GetIdentHash () == i2p::context.GetIdentHash (); };
|
||||
|
||||
void CreateTunnels ();
|
||||
void TunnelCreated (InboundTunnel * createdTunnel);
|
||||
void TunnelExpired (InboundTunnel * expiredTunnel);
|
||||
@ -35,7 +37,9 @@ namespace tunnel
|
||||
void TunnelExpired (OutboundTunnel * expiredTunnel);
|
||||
std::vector<InboundTunnel *> GetInboundTunnels (int num) const;
|
||||
OutboundTunnel * GetNextOutboundTunnel ();
|
||||
|
||||
InboundTunnel * GetNextInboundTunnel ();
|
||||
const i2p::data::IdentHash& GetIdentHash () { return m_LocalDestination.GetIdentHash (); };
|
||||
|
||||
void TestTunnels ();
|
||||
void ProcessDeliveryStatus (I2NPMessage * msg);
|
||||
|
||||
@ -43,11 +47,12 @@ namespace tunnel
|
||||
|
||||
void CreateInboundTunnel ();
|
||||
void CreateOutboundTunnel ();
|
||||
template<class TTunnels>
|
||||
typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels);
|
||||
|
||||
private:
|
||||
|
||||
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
||||
i2p::data::LocalDestination * m_LocalDestination;
|
||||
i2p::data::LocalDestination& m_LocalDestination;
|
||||
int m_NumTunnels;
|
||||
std::set<InboundTunnel *, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first
|
||||
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…
Reference in New Issue
Block a user