diff --git a/.gitignore b/.gitignore index 0e609a70abb..5d0b360524f 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..a00511cd22e --- /dev/null +++ b/.travis.yml @@ -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 + + diff --git a/AddressBook.cpp b/AddressBook.cpp new file mode 100644 index 00000000000..023e75cf8e1 --- /dev/null +++ b/AddressBook.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#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"); +} + +} +} + diff --git a/AddressBook.h b/AddressBook.h index 6d134247ee1..8d255a7ac37 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -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 m_Addresses; bool m_IsLoaded; diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 27e6f0a1022..f7f15cc14f0 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -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"; diff --git a/I2PEndian.h b/I2PEndian.h index 01ba73e89d5..661179cb7fe 100644 --- a/I2PEndian.h +++ b/I2PEndian.h @@ -1,8 +1,12 @@ #ifndef I2PENDIAN_H__ #define I2PENDIAN_H__ -#ifndef _WIN32 +#ifdef __linux__ #include +#elif __FreeBSD__ +#include +#elif __MACH__ // Mac OS X +#include #else #include diff --git a/Identity.cpp b/Identity.cpp index eb107ca3784..387eef5075d 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -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 diff --git a/Identity.h b/Identity.h index 6b180999334..1dafdef40e7 100644 --- a/Identity.h +++ b/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 }; } } diff --git a/Makefile b/Makefile index d13d41b71a4..fec4f79d7d3 100644 --- a/Makefile +++ b/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 = diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 1a72fdbc823..e21e8d18eb3 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -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 (); + i2p::transports.RemoveNTCPSession (this); + int numDelayed = 0; for (auto it :m_DelayedMessages) - delete it; + { + // 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 - i2p::transports.RemoveNTCPSession (this); + 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 diff --git a/NTCPSession.h b/NTCPSession.h index eb31951dfe0..4202c5c9ba9 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -7,6 +7,7 @@ #include #include #include +#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::Decryption m_Decryption; CryptoPP::CBC_Mode::Encryption m_Encryption; diff --git a/NetDb.cpp b/NetDb.cpp index 57b5029a0e3..553ee52b374 100644 --- a/NetDb.cpp +++ b/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 (); diff --git a/README.md b/README.md index d19a666c5f9..2a393e85177 100644 --- a/README.md +++ b/README.md @@ -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 ------- diff --git a/RouterContext.h b/RouterContext.h index abbc3775b99..bd5acd4e981 100644 --- a/RouterContext.h +++ b/RouterContext.h @@ -4,6 +4,7 @@ #include #include #include +#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 (); diff --git a/SSU.cpp b/SSU.cpp index b0d351ff75a..a43e04f6154 100644 --- a/SSU.cpp +++ b/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 ()); diff --git a/SSU.h b/SSU.h index e43fa4adf59..e528d30b3e6 100644 --- a/SSU.h +++ b/SSU.h @@ -8,6 +8,7 @@ #include #include #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::Encryption m_Encryption; CryptoPP::CBC_Mode::Decryption m_Decryption; diff --git a/Streaming.cpp b/Streaming.cpp index facf68b4b93..9291235ad0f 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #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 () diff --git a/Streaming.h b/Streaming.h index b25c70a06c0..b1706e4a0af 100644 --- a/Streaming.h +++ b/Streaming.h @@ -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 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; diff --git a/Transports.cpp b/Transports.cpp index 60de2710ec1..9d86d60510a 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -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 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 (); + } } diff --git a/Transports.h b/Transports.h index aedd51b2ee4..bcec76901ad 100644 --- a/Transports.h +++ b/Transports.h @@ -2,17 +2,47 @@ #define TRANSPORTS_H__ #include +#include +#include #include #include +#include #include #include #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 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 diff --git a/Tunnel.cpp b/Tunnel.cpp index c32c5e0ef38..4b831fbc47b 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -154,11 +154,14 @@ namespace tunnel else block.deliveryType = eDeliveryTypeLocal; block.data = msg; + + std::unique_lock l(m_SendMutex); m_Gateway.SendTunnelDataMsg (block); } void OutboundTunnel::SendTunnelDataMsg (std::vector msgs) { + std::unique_lock 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 Tunnels::GetInboundTunnels (int num) const - { - std::vector 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 ( - new TunnelConfig (std::vector - { - i2p::data::netdb.GetRandomRouter () - }, - inboundTunnel->GetTunnelConfig ())); - } - else - { - - LogPrint ("Creating two hops outbound tunnel..."); - auto firstHop = i2p::data::netdb.GetRandomRouter (); - CreateTunnel ( - new TunnelConfig (std::vector - { - firstHop, - i2p::data::netdb.GetRandomRouter (firstHop) - }, - inboundTunnel->GetTunnelConfig ())); - } + if (!inboundTunnel) return; + LogPrint ("Creating one hop outbound tunnel..."); + CreateTunnel ( + new TunnelConfig (std::vector + { + 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 ( - new TunnelConfig (std::vector - { - 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 ( - new TunnelConfig (std::vector - { - 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 ( + new TunnelConfig (std::vector + { + 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 (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 ( - new TunnelConfig (std::vector{&router}), - outboundTunnel); - } - else - LogPrint ("No established peers"); - return 0; - } - - OutboundTunnel * Tunnels::CreateTwoHopsOutboundTestTunnel (InboundTunnel * replyTunnel) - { - return CreateTunnel (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 ( - new TunnelConfig (std::vector - { - &router, - &i2p::context.GetRouterInfo () - }), - outboundTunnel); - } - else - LogPrint ("No established peers"); - return 0; - } } } diff --git a/Tunnel.h b/Tunnel.h index 6711bd3d79b..16ffa9e42bd 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #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 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 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 m_InboundTunnels; std::list m_OutboundTunnels; std::map m_TransitTunnels; - std::list m_Pools; + std::map m_Pools; + TunnelPool * m_ExploratoryPool; i2p::util::Queue m_Queue; public: diff --git a/TunnelPool.cpp b/TunnelPool.cpp index f71a63c30dd..33f6cbda462 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -1,10 +1,8 @@ -#include #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 + 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 (); diff --git a/TunnelPool.h b/TunnelPool.h index 8cef8375d3e..1ff66cf393c 100644 --- a/TunnelPool.h +++ b/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 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 + 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 m_InboundTunnels; // recent tunnel appears first std::set m_OutboundTunnels; diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt new file mode 100644 index 00000000000..5541301fde0 --- /dev/null +++ b/build/CMakeLists.txt @@ -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} ) diff --git a/build/cmake_modules/FindCryptoPP.cmake b/build/cmake_modules/FindCryptoPP.cmake new file mode 100644 index 00000000000..7a8ac31770d --- /dev/null +++ b/build/cmake_modules/FindCryptoPP.cmake @@ -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)