From 06088ff7a2255b9dbf3da1f5cd2afca43a691123 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 13 Mar 2014 07:43:54 -0400 Subject: [PATCH 01/10] fixed crash and few other small issues --- Garlic.cpp | 2 +- HTTPServer.cpp | 13 ++++++++----- SSU.cpp | 3 ++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index 32639142..3e336092 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -218,7 +218,7 @@ namespace garlic } GarlicRouting routing; - GarlicRouting::GarlicRouting () + GarlicRouting::GarlicRouting (): m_IsRunning (false), m_Thread (nullptr) { } diff --git a/HTTPServer.cpp b/HTTPServer.cpp index ec655709..e8620f09 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -121,13 +121,16 @@ namespace util s << "Our external address:" << "
" << "
"; for (auto& address : i2p::context.GetRouterInfo().GetAddresses()) { - switch (address.transportStyle) { - case i2p::data::RouterInfo::eTransportNTCP: - s << "NTCP  "; + switch (address.transportStyle) + { + case i2p::data::RouterInfo::eTransportNTCP: + s << "NTCP  "; break; - case i2p::data::RouterInfo::eTransportSSU: - s << "SSU     "; + case i2p::data::RouterInfo::eTransportSSU: + s << "SSU     "; break; + default: + s << "Unknown  "; } s << address.host.to_string() << ":" << address.port << "
"; } diff --git a/SSU.cpp b/SSU.cpp index 7efd14e4..196c0a72 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -853,8 +853,9 @@ namespace ssu auto it = m_Sessions.find (oldEndpoint); if (it != m_Sessions.end ()) { + auto session = it->second; m_Sessions.erase (it); - m_Sessions[newEndpoint] = it->second; + m_Sessions[newEndpoint] = session; LogPrint ("SSU session ressigned from ", oldEndpoint.address ().to_string (), ":", oldEndpoint.port (), " to ", newEndpoint.address ().to_string (), ":", newEndpoint.port ()); } From 94a23be9d93da29ed5937d05eed624eb9b28603e Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 13 Mar 2014 14:22:32 -0400 Subject: [PATCH 02/10] adress book added --- AddressBook.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ NetDb.h | 2 ++ util.cpp | 12 +++++++++ util.h | 1 + 4 files changed, 88 insertions(+) create mode 100644 AddressBook.h diff --git a/AddressBook.h b/AddressBook.h new file mode 100644 index 00000000..6d134247 --- /dev/null +++ b/AddressBook.h @@ -0,0 +1,73 @@ +#ifndef ADDRESS_BOOK_H__ +#define ADDRESS_BOOK_H__ + +#include +#include +#include +#include "base64.h" +#include "util.h" +#include "Identity.h" +#include "Log.h" + +namespace i2p +{ +namespace data +{ + class AddressBook + { + 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; + } + + 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: + + std::map m_Addresses; + bool m_IsLoaded; + }; +} +} + +#endif + + diff --git a/NetDb.h b/NetDb.h index 39f87df0..96188513 100644 --- a/NetDb.h +++ b/NetDb.h @@ -12,6 +12,7 @@ #include "RouterInfo.h" #include "LeaseSet.h" #include "Tunnel.h" +#include "AddressBook.h" namespace i2p { @@ -104,6 +105,7 @@ namespace data int m_ReseedRetries; std::thread * m_Thread; i2p::util::Queue m_Queue; // of I2NPDatabaseStoreMsg + AddressBook m_AddressBook; static const char m_NetDbPath[]; }; diff --git a/util.cpp b/util.cpp index 262b6e25..ef4c2e86 100644 --- a/util.cpp +++ b/util.cpp @@ -121,6 +121,18 @@ namespace filesystem return path; } + std::string GetFullPath (const std::string& filename) + { + std::string fullPath = GetDataDir ().string (); +#ifndef _WIN32 + fullPath.append ("/"); +#else + fullPath.append ("\\"); +#endif + fullPath.append (filename); + return fullPath; + } + boost::filesystem::path GetConfigFile() { boost::filesystem::path pathConfigFile(i2p::util::config::GetArg("-conf", "i2p.conf")); diff --git a/util.h b/util.h index 519e51b3..6bd367e2 100644 --- a/util.h +++ b/util.h @@ -25,6 +25,7 @@ namespace util namespace filesystem { const boost::filesystem::path &GetDataDir(); + std::string GetFullPath (const std::string& filename); boost::filesystem::path GetDefaultDataDir(); boost::filesystem::path GetConfigFile(); void ReadConfigFile(std::map& mapSettingsRet, From 66ff021938fef39ec0c162ed2f70a96e4ea204cf Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 13 Mar 2014 16:26:04 -0400 Subject: [PATCH 03/10] find address --- NetDb.cpp | 7 ------- NetDb.h | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index 1b115c63..951f9623 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -318,13 +318,6 @@ namespace data LogPrint (deletedCount," routers deleted"); } - void NetDb::RequestDestination (const char * b32) - { - uint8_t destination[32]; - Base32ToByteStream (b32, strlen(b32), destination, 32); - RequestDestination (destination, true); - } - void NetDb::RequestDestination (const IdentHash& destination, bool isLeaseSet) { if (isLeaseSet) // we request LeaseSet through tunnels diff --git a/NetDb.h b/NetDb.h index 96188513..f9cf3900 100644 --- a/NetDb.h +++ b/NetDb.h @@ -64,10 +64,10 @@ namespace data void AddLeaseSet (uint8_t * buf, int len); RouterInfo * FindRouter (const IdentHash& ident) const; LeaseSet * FindLeaseSet (const IdentHash& destination) const; + const IdentHash * FindAddress (const std::string& address) { return m_AddressBook.FindAddress (address); }; // TODO: move AddressBook away from NetDb + void Subscribe (const IdentHash& ident); // keep LeaseSets upto date void Unsubscribe (const IdentHash& ident); - - void RequestDestination (const char * b32); // in base32 void RequestDestination (const IdentHash& destination, bool isLeaseSet = false); void HandleDatabaseStoreMsg (uint8_t * buf, size_t len); From 70df239d14d1e8418d0bf4cf2158085ddbe1ba90 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Mar 2014 07:32:11 -0400 Subject: [PATCH 04/10] use GetFullPath --- RouterContext.cpp | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/RouterContext.cpp b/RouterContext.cpp index af88c84a..cb8eb355 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -76,49 +76,27 @@ namespace i2p bool RouterContext::Load () { - std::string dataDir = i2p::util::filesystem::GetDataDir ().string (); -#ifndef _WIN32 - dataDir.append ("/"); -#else - dataDir.append ("\\"); -#endif - std::string router_keys = dataDir; - router_keys.append (ROUTER_KEYS); - std::string router_info = dataDir; - router_info.append (ROUTER_INFO); - - std::ifstream fk (router_keys.c_str (), std::ifstream::binary | std::ofstream::in); + std::ifstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ifstream::binary | std::ofstream::in); if (!fk.is_open ()) return false; fk.read ((char *)&m_Keys, sizeof (m_Keys)); m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_Keys.signingPrivateKey, 20)); - m_RouterInfo = i2p::data::RouterInfo (router_info.c_str ()); // TODO + m_RouterInfo = i2p::data::RouterInfo (i2p::util::filesystem::GetFullPath (ROUTER_INFO).c_str ()); // TODO return true; } void RouterContext::Save (bool infoOnly) { - std::string dataDir = i2p::util::filesystem::GetDataDir ().string (); -#ifndef _WIN32 - dataDir.append ("/"); -#else - dataDir.append ("\\"); -#endif - std::string router_keys = dataDir; - router_keys.append (ROUTER_KEYS); - std::string router_info = dataDir; - router_info.append (ROUTER_INFO); - if (!infoOnly) { - std::ofstream fk (router_keys.c_str (), std::ofstream::binary | std::ofstream::out); + std::ofstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ofstream::binary | std::ofstream::out); fk.write ((char *)&m_Keys, sizeof (m_Keys)); } - std::ofstream fi (router_info.c_str (), std::ofstream::binary | std::ofstream::out); + std::ofstream fi (i2p::util::filesystem::GetFullPath (ROUTER_INFO).c_str (), std::ofstream::binary | std::ofstream::out); fi.write ((char *)m_RouterInfo.GetBuffer (), m_RouterInfo.GetBufferLen ()); } } From 7caa46b3819a0cf53b9d27263eaf10406510937f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Mar 2014 12:35:02 -0400 Subject: [PATCH 05/10] TunnelPool added --- Makefile | 2 +- Tunnel.cpp | 8 +++++++- Tunnel.h | 6 +++++- TunnelPool.cpp | 26 ++++++++++++++++++++++++++ TunnelPool.h | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 TunnelPool.cpp create mode 100644 TunnelPool.h diff --git a/Makefile b/Makefile index d9d9b4c9..84a1acc0 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/UPnP.o obj/TunnelPool.o INCFLAGS = LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LIBS = diff --git a/Tunnel.cpp b/Tunnel.cpp index ed9708cb..df1229a5 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -14,7 +14,7 @@ namespace i2p namespace tunnel { - Tunnel::Tunnel (TunnelConfig * config): m_Config (config), m_IsEstablished (false) + Tunnel::Tunnel (TunnelConfig * config): m_Config (config), m_Pool (nullptr), m_IsEstablished (false) { } @@ -343,6 +343,9 @@ namespace tunnel for (auto& it : m_PendingTunnels) { LogPrint ("Pending tunnel build request ", it.first, " has not been responded. Deleted"); + auto pool = it.second->GetTunnelPool (); + if (pool) + pool->TunnelCreationFailed (it.second); delete it.second; } m_PendingTunnels.clear (); @@ -418,6 +421,9 @@ namespace tunnel if (ts > it->second->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { LogPrint ("Tunnel ", it->second->GetTunnelID (), " expired"); + auto pool = it->second->GetTunnelPool (); + if (pool) + pool->TunnelExpired (it->second); it = m_InboundTunnels.erase (it); } else diff --git a/Tunnel.h b/Tunnel.h index 7e7f94d5..2200dc2e 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -11,6 +11,7 @@ #include #include "Queue.h" #include "TunnelConfig.h" +#include "TunnelPool.h" #include "TransitTunnel.h" #include "TunnelEndpoint.h" #include "TunnelGateway.h" @@ -36,7 +37,9 @@ namespace tunnel TunnelConfig * GetTunnelConfig () const { return m_Config; } bool IsEstablished () const { return m_IsEstablished; }; - + TunnelPool * GetTunnelPool () const { return m_Pool; }; + void SetTunnelPool (TunnelPool * pool) { m_Pool = pool; }; + bool HandleTunnelBuildResponse (uint8_t * msg, size_t len); // implements TunnelBase @@ -53,6 +56,7 @@ namespace tunnel private: TunnelConfig * m_Config; + TunnelPool * m_Pool; // pool, tunnel belongs to, or null bool m_IsEstablished; CryptoPP::ECB_Mode::Decryption m_ECBDecryption; diff --git a/TunnelPool.cpp b/TunnelPool.cpp new file mode 100644 index 00000000..2acdef6c --- /dev/null +++ b/TunnelPool.cpp @@ -0,0 +1,26 @@ +#include "Tunnel.h" +#include "TunnelPool.h" + +namespace i2p +{ +namespace tunnel +{ + TunnelPool::TunnelPool () + { + } + + TunnelPool::~TunnelPool () + { + for (auto it: m_InboundTunnels) + it->SetTunnelPool (nullptr); + } + + void TunnelPool::TunnelCreationFailed (Tunnel * failedTunnel) + { + } + + void TunnelPool::TunnelExpired (InboundTunnel * expiredTunnel) + { + } +} +} diff --git a/TunnelPool.h b/TunnelPool.h new file mode 100644 index 00000000..c4b7e347 --- /dev/null +++ b/TunnelPool.h @@ -0,0 +1,33 @@ +#ifndef TUNNEL_POOL__ +#define TUNNEL_POOL__ + +#include +#include "LeaseSet.h" + +namespace i2p +{ +namespace tunnel +{ + class Tunnel; + class InboundTunnel; + class OutboundTunnel; + + class TunnelPool // per local destination + { + public: + + TunnelPool (); + ~TunnelPool (); + + void TunnelCreationFailed (Tunnel * failedTunnel); + void TunnelExpired (InboundTunnel * expiredTunnel); + + private: + + std::list m_InboundTunnels; + }; +} +} + +#endif + From cba18faa87abb57fa06c5be0bc7e9d90a8015d3c Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Mar 2014 15:13:34 -0400 Subject: [PATCH 06/10] create inbound tunnels per local destination --- Identity.h | 7 +++++++ Streaming.cpp | 14 ++++++++++++-- Streaming.h | 15 +++++++++++---- Tunnel.cpp | 10 ++++++++-- TunnelBase.h | 11 +++++++++++ TunnelPool.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++++- TunnelPool.h | 20 +++++++++++++++++--- 7 files changed, 112 insertions(+), 12 deletions(-) diff --git a/Identity.h b/Identity.h index 10af227c..6552fa38 100644 --- a/Identity.h +++ b/Identity.h @@ -104,6 +104,13 @@ namespace data mutable i2p::crypto::ElGamalEncryption * m_ElGamalEncryption; // use lazy initialization }; + + class LocalDestination + { + public: + + virtual void UpdateLeaseSet () = 0; // LeaseSet must be update + }; } } diff --git a/Streaming.cpp b/Streaming.cpp index 6caa2a0f..cbe6575b 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -300,7 +300,7 @@ namespace stream StreamingDestination * sharedLocalDestination = nullptr; - StreamingDestination::StreamingDestination (): m_LeaseSet (nullptr) + StreamingDestination::StreamingDestination (): m_TunnelPool (this), m_LeaseSet (nullptr) { // TODO: read from file later m_Keys = i2p::data::CreateRandomKeys (); @@ -315,7 +315,17 @@ namespace stream if (m_LeaseSet) DeleteI2NPMessage (m_LeaseSet); } - + + void StreamingDestination::Start () + { + m_TunnelPool.CreateTunnels (); + } + + void StreamingDestination::Stop () + { + // TODO: + } + void StreamingDestination::HandleNextPacket (Packet * packet) { uint32_t sendStreamID = packet->GetSendStreamID (); diff --git a/Streaming.h b/Streaming.h index 4e33d111..60044a6b 100644 --- a/Streaming.h +++ b/Streaming.h @@ -11,6 +11,7 @@ #include "LeaseSet.h" #include "I2NPProtocol.h" #include "Tunnel.h" +#include "TunnelPool.h" namespace i2p { @@ -97,22 +98,27 @@ namespace stream i2p::tunnel::OutboundTunnel * m_OutboundTunnel; }; - class StreamingDestination + class StreamingDestination: public i2p::data::LocalDestination { public: StreamingDestination (); ~StreamingDestination (); - + void Start (); + void Stop (); + const i2p::data::Keys& GetKeys () const { return m_Keys; }; const i2p::data::Identity& GetIdentity () const { return m_Identity; }; I2NPMessage * GetLeaseSet (); - void Sign (uint8_t * buf, int len, uint8_t * signature) const; - + void Sign (uint8_t * buf, int len, uint8_t * signature) const; + Stream * CreateNewStream (const i2p::data::LeaseSet& remote); void DeleteStream (Stream * stream); void HandleNextPacket (Packet * packet); + // implements LocalDestination + void UpdateLeaseSet () {}; // TODO: + private: I2NPMessage * CreateLeaseSet () const; @@ -124,6 +130,7 @@ namespace stream i2p::data::Identity m_Identity; i2p::data::IdentHash m_IdentHash; + i2p::tunnel::TunnelPool m_TunnelPool; I2NPMessage * m_LeaseSet; CryptoPP::DSA::PrivateKey m_SigningPrivateKey; diff --git a/Tunnel.cpp b/Tunnel.cpp index df1229a5..1c03405e 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -504,8 +504,14 @@ namespace tunnel void Tunnels::AddInboundTunnel (InboundTunnel * newTunnel) { m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel; - // build symmetric outbound tunnel - CreateTunnel (newTunnel->GetTunnelConfig ()->Invert (), GetNextOutboundTunnel ()); + auto pool = newTunnel->GetTunnelPool (); + if (pool) + pool->TunnelCreated (newTunnel); + else + { + // build symmetric outbound tunnel + CreateTunnel (newTunnel->GetTunnelConfig ()->Invert (), GetNextOutboundTunnel ()); + } } diff --git a/TunnelBase.h b/TunnelBase.h index 6be902ca..24704d46 100644 --- a/TunnelBase.h +++ b/TunnelBase.h @@ -48,6 +48,17 @@ namespace tunnel uint32_t m_CreationTime; // seconds since epoch }; + + struct TunnelCreationTimeCmp + { + bool operator() (const TunnelBase * t1, const TunnelBase * t2) const + { + if (t1->GetCreationTime () != t2->GetCreationTime ()) + return t1->GetCreationTime () > t2->GetCreationTime (); + else + return t1 < t2; + }; + }; } } diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 2acdef6c..c6e36ca3 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -1,11 +1,13 @@ #include "Tunnel.h" +#include "NetDb.h" #include "TunnelPool.h" namespace i2p { namespace tunnel { - TunnelPool::TunnelPool () + TunnelPool::TunnelPool (i2p::data::LocalDestination * owner, int numTunnels): + m_Owner (owner), m_NumTunnels (numTunnels) { } @@ -17,10 +19,53 @@ namespace tunnel void TunnelPool::TunnelCreationFailed (Tunnel * failedTunnel) { + CreateInboundTunnel (); } void TunnelPool::TunnelExpired (InboundTunnel * expiredTunnel) { + CreateInboundTunnel (); + if (m_Owner) + m_Owner->UpdateLeaseSet (); + } + + void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel) + { + m_InboundTunnels.insert (createdTunnel); + } + + std::vector TunnelPool::GetInboundTunnels (int num) const + { + std::vector v; + int i = 0; + for (auto it : m_InboundTunnels) + { + if (i >= num) break; + v.push_back (it); + i++; + } + return v; + } + + void TunnelPool::CreateTunnels () + { + for (int i = 0; i < m_NumTunnels; i++) + CreateInboundTunnel (); + } + + void TunnelPool::CreateInboundTunnel () + { + OutboundTunnel * outboundTunnel = tunnels.GetNextOutboundTunnel (); + LogPrint ("Creating destination inbound tunnel..."); + auto firstHop = i2p::data::netdb.GetRandomRouter (outboundTunnel ? outboundTunnel->GetEndpointRouter () : nullptr); + auto * tunnel = tunnels.CreateTunnel ( + new TunnelConfig (std::vector + { + firstHop, + i2p::data::netdb.GetRandomRouter (firstHop) + }), + outboundTunnel); + tunnel->SetTunnelPool (this); } } } diff --git a/TunnelPool.h b/TunnelPool.h index c4b7e347..6feb2afc 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -1,8 +1,12 @@ #ifndef TUNNEL_POOL__ #define TUNNEL_POOL__ -#include +#include +#include +#include "Identity.h" #include "LeaseSet.h" +#include "I2NPProtocol.h" +#include "TunnelBase.h" namespace i2p { @@ -16,15 +20,25 @@ namespace tunnel { public: - TunnelPool (); + TunnelPool (i2p::data::LocalDestination * owner, int numTunnels = 5); ~TunnelPool (); + void CreateTunnels (); + std::vector GetInboundTunnels (int num) const; + void TunnelCreationFailed (Tunnel * failedTunnel); void TunnelExpired (InboundTunnel * expiredTunnel); + void TunnelCreated (InboundTunnel * createdTunnel); + + private: + + void CreateInboundTunnel (); private: - std::list m_InboundTunnels; + i2p::data::LocalDestination * m_Owner; + int m_NumTunnels; + std::set m_InboundTunnels; // recent tunnel appears first }; } } From ab23327da6b7f25d42cf8398b632b64e4c182676 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Mar 2014 20:24:12 -0400 Subject: [PATCH 07/10] manage tunnel pools --- HTTPServer.cpp | 11 +++++++++++ Streaming.cpp | 13 ++----------- Streaming.h | 6 +----- Tunnel.cpp | 30 ++++++++++++++++++++---------- Tunnel.h | 7 +++++-- TunnelPool.cpp | 38 ++++++++++++++++++++++++-------------- TunnelPool.h | 11 +++++++---- 7 files changed, 70 insertions(+), 46 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index e8620f09..b1f03e86 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -148,6 +148,17 @@ namespace util s << " " << (int)it.second->GetNumReceivedBytes () << "
"; } + s << "

Tunnel pools

"; + for (auto it: i2p::tunnel::tunnels.GetTunnelPools ()) + { + for (auto it1: it->GetInboundTunnels ()) + { + it1->GetTunnelConfig ()->Print (s); + s << " " << (int)it1->GetNumReceivedBytes () << "
"; + } + s << "
"; + } + s << "

Transit tunnels

"; for (auto it: i2p::tunnel::tunnels.GetTransitTunnels ()) { diff --git a/Streaming.cpp b/Streaming.cpp index cbe6575b..0bd88f66 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -300,7 +300,7 @@ namespace stream StreamingDestination * sharedLocalDestination = nullptr; - StreamingDestination::StreamingDestination (): m_TunnelPool (this), m_LeaseSet (nullptr) + StreamingDestination::StreamingDestination (): m_LeaseSet (nullptr) { // TODO: read from file later m_Keys = i2p::data::CreateRandomKeys (); @@ -308,6 +308,7 @@ namespace stream m_IdentHash = i2p::data::CalculateIdentHash (m_Identity); m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_Keys.signingPrivateKey, 20)); + i2p::tunnel::tunnels.CreateTunnelPool (this); } StreamingDestination::~StreamingDestination () @@ -316,16 +317,6 @@ namespace stream DeleteI2NPMessage (m_LeaseSet); } - void StreamingDestination::Start () - { - m_TunnelPool.CreateTunnels (); - } - - void StreamingDestination::Stop () - { - // TODO: - } - void StreamingDestination::HandleNextPacket (Packet * packet) { uint32_t sendStreamID = packet->GetSendStreamID (); diff --git a/Streaming.h b/Streaming.h index 60044a6b..e4438e0c 100644 --- a/Streaming.h +++ b/Streaming.h @@ -11,7 +11,6 @@ #include "LeaseSet.h" #include "I2NPProtocol.h" #include "Tunnel.h" -#include "TunnelPool.h" namespace i2p { @@ -103,9 +102,7 @@ namespace stream public: StreamingDestination (); - ~StreamingDestination (); - void Start (); - void Stop (); + ~StreamingDestination (); const i2p::data::Keys& GetKeys () const { return m_Keys; }; const i2p::data::Identity& GetIdentity () const { return m_Identity; }; @@ -130,7 +127,6 @@ namespace stream i2p::data::Identity m_Identity; i2p::data::IdentHash m_IdentHash; - i2p::tunnel::TunnelPool m_TunnelPool; I2NPMessage * m_LeaseSet; CryptoPP::DSA::PrivateKey m_SigningPrivateKey; diff --git a/Tunnel.cpp b/Tunnel.cpp index 1c03405e..8c58f8ae 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -186,6 +186,10 @@ namespace tunnel for (auto& it : m_PendingTunnels) delete it.second; m_PendingTunnels.clear (); + + for (auto& it: m_Pools) + delete it; + m_Pools.clear (); } InboundTunnel * Tunnels::GetInboundTunnel (uint32_t tunnelID) @@ -268,6 +272,11 @@ namespace tunnel } return tunnel;*/ } + + void Tunnels::CreateTunnelPool (i2p::data::LocalDestination * localDestination) + { + m_Pools.push_back (new TunnelPool (localDestination)); + } void Tunnels::AddTransitTunnel (TransitTunnel * tunnel) { @@ -343,9 +352,6 @@ namespace tunnel for (auto& it : m_PendingTunnels) { LogPrint ("Pending tunnel build request ", it.first, " has not been responded. Deleted"); - auto pool = it.second->GetTunnelPool (); - if (pool) - pool->TunnelCreationFailed (it.second); delete it.second; } m_PendingTunnels.clear (); @@ -353,6 +359,7 @@ namespace tunnel ManageInboundTunnels (); ManageOutboundTunnels (); ManageTransitTunnels (); + ManageTunnelPools (); /* if (!m_IsTunnelCreated) { @@ -421,9 +428,6 @@ namespace tunnel if (ts > it->second->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { LogPrint ("Tunnel ", it->second->GetTunnelID (), " expired"); - auto pool = it->second->GetTunnelPool (); - if (pool) - pool->TunnelExpired (it->second); it = m_InboundTunnels.erase (it); } else @@ -480,6 +484,12 @@ namespace tunnel it++; } } + + void Tunnels::ManageTunnelPools () + { + for (auto& it: m_Pools) + it->ManageTunnels (); + } void Tunnels::PostTunnelData (I2NPMessage * msg) { @@ -503,15 +513,15 @@ namespace tunnel void Tunnels::AddInboundTunnel (InboundTunnel * newTunnel) { - m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel; auto pool = newTunnel->GetTunnelPool (); - if (pool) - pool->TunnelCreated (newTunnel); - else + if (!pool) { + m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel; // build symmetric outbound tunnel CreateTunnel (newTunnel->GetTunnelConfig ()->Invert (), GetNextOutboundTunnel ()); } + else + pool->TunnelCreated (newTunnel); } diff --git a/Tunnel.h b/Tunnel.h index 2200dc2e..6a00aa0e 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -105,9 +105,8 @@ namespace tunnel Tunnels (); ~Tunnels (); - void Start (); - void Stop (); + void Stop (); InboundTunnel * GetInboundTunnel (uint32_t tunnelID); Tunnel * GetPendingTunnel (uint32_t replyMsgID); @@ -121,6 +120,7 @@ namespace tunnel void PostTunnelData (I2NPMessage * msg); template TTunnel * CreateTunnel (TunnelConfig * config, OutboundTunnel * outboundTunnel = 0); + void CreateTunnelPool (i2p::data::LocalDestination * localDestination); OutboundTunnel * CreateOneHopOutboundTestTunnel (InboundTunnel * replyTunnel); InboundTunnel * CreateOneHopInboundTestTunnel (OutboundTunnel * outboundTunnel = 0); @@ -134,6 +134,7 @@ namespace tunnel void ManageOutboundTunnels (); void ManageInboundTunnels (); void ManageTransitTunnels (); + void ManageTunnelPools (); void CreateZeroHopsInboundTunnel (); @@ -147,6 +148,7 @@ namespace tunnel std::map m_InboundTunnels; std::list m_OutboundTunnels; std::map m_TransitTunnels; + std::list m_Pools; i2p::util::Queue m_Queue; public: @@ -155,6 +157,7 @@ namespace tunnel const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; }; const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }; const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; }; + const decltype(m_Pools)& GetTunnelPools () const { return m_Pools; }; }; extern Tunnels tunnels; diff --git a/TunnelPool.cpp b/TunnelPool.cpp index c6e36ca3..8860c4b8 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -1,5 +1,6 @@ #include "Tunnel.h" #include "NetDb.h" +#include "Timestamp.h" #include "TunnelPool.h" namespace i2p @@ -14,19 +15,7 @@ namespace tunnel TunnelPool::~TunnelPool () { for (auto it: m_InboundTunnels) - it->SetTunnelPool (nullptr); - } - - void TunnelPool::TunnelCreationFailed (Tunnel * failedTunnel) - { - CreateInboundTunnel (); - } - - void TunnelPool::TunnelExpired (InboundTunnel * expiredTunnel) - { - CreateInboundTunnel (); - if (m_Owner) - m_Owner->UpdateLeaseSet (); + delete it; } void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel) @@ -49,7 +38,8 @@ namespace tunnel void TunnelPool::CreateTunnels () { - for (int i = 0; i < m_NumTunnels; i++) + int num = m_InboundTunnels.size (); + for (int i = num; i < m_NumTunnels; i++) CreateInboundTunnel (); } @@ -67,5 +57,25 @@ namespace tunnel outboundTunnel); tunnel->SetTunnelPool (this); } + + void TunnelPool::ManageTunnels () + { + uint64_t ts = i2p::util::GetSecondsSinceEpoch (); + bool isLeaseSetUpdated = false; + for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();) + { + if (ts > (*it)->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) + { + LogPrint ("Destination tunnel ", (*it)->GetTunnelID (), " expired"); + m_InboundTunnels.erase (it++); + isLeaseSetUpdated = true; + } + else + ++it; + } + CreateTunnels (); + if (isLeaseSetUpdated && m_Owner) + m_Owner->UpdateLeaseSet (); + } } } diff --git a/TunnelPool.h b/TunnelPool.h index 6feb2afc..e6017e64 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -24,11 +24,9 @@ namespace tunnel ~TunnelPool (); void CreateTunnels (); - std::vector GetInboundTunnels (int num) const; - - void TunnelCreationFailed (Tunnel * failedTunnel); - void TunnelExpired (InboundTunnel * expiredTunnel); void TunnelCreated (InboundTunnel * createdTunnel); + std::vector GetInboundTunnels (int num) const; + void ManageTunnels (); private: @@ -39,6 +37,11 @@ namespace tunnel i2p::data::LocalDestination * m_Owner; int m_NumTunnels; std::set m_InboundTunnels; // recent tunnel appears first + + public: + + // for HTTP only + const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }; }; } } From b47d7aceaad418c64e8ef5935804da8bfa9e1a98 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Mar 2014 20:51:51 -0400 Subject: [PATCH 08/10] manage tunnel pools --- HTTPServer.cpp | 13 ++----------- Tunnel.cpp | 18 +++++++++++++----- Tunnel.h | 3 ++- TunnelPool.cpp | 4 ++-- TunnelPool.h | 4 ---- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index b1f03e86..c7d1fcaf 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -145,19 +145,10 @@ namespace util for (auto it: i2p::tunnel::tunnels.GetInboundTunnels ()) { it.second->GetTunnelConfig ()->Print (s); + if (it.second->GetTunnelPool ()) + s << " " << "Pool"; s << " " << (int)it.second->GetNumReceivedBytes () << "
"; } - - s << "

Tunnel pools

"; - for (auto it: i2p::tunnel::tunnels.GetTunnelPools ()) - { - for (auto it1: it->GetInboundTunnels ()) - { - it1->GetTunnelConfig ()->Print (s); - s << " " << (int)it1->GetNumReceivedBytes () << "
"; - } - s << "
"; - } s << "

Transit tunnels

"; for (auto it: i2p::tunnel::tunnels.GetTransitTunnels ()) diff --git a/Tunnel.cpp b/Tunnel.cpp index 8c58f8ae..d0a2734f 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -273,9 +273,17 @@ namespace tunnel return tunnel;*/ } - void Tunnels::CreateTunnelPool (i2p::data::LocalDestination * localDestination) + TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination * localDestination) { - m_Pools.push_back (new TunnelPool (localDestination)); + auto pool = new TunnelPool (localDestination); + m_Pools.push_back (pool); + return pool; + } + + void Tunnels::DeleteTunnelPool (TunnelPool * pool) + { + m_Pools.remove (pool); + delete pool; } void Tunnels::AddTransitTunnel (TransitTunnel * tunnel) @@ -441,7 +449,7 @@ namespace tunnel return; } - if (m_InboundTunnels.size () < 10) + if (m_InboundTunnels.size () < 15) // TODO: store exploratory tunnels explicitly { // trying to create one more inbound tunnel if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3) @@ -513,10 +521,10 @@ namespace tunnel void Tunnels::AddInboundTunnel (InboundTunnel * newTunnel) { + m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel; auto pool = newTunnel->GetTunnelPool (); if (!pool) - { - m_InboundTunnels[newTunnel->GetTunnelID ()] = newTunnel; + { // build symmetric outbound tunnel CreateTunnel (newTunnel->GetTunnelConfig ()->Invert (), GetNextOutboundTunnel ()); } diff --git a/Tunnel.h b/Tunnel.h index 6a00aa0e..7d761453 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -120,7 +120,8 @@ namespace tunnel void PostTunnelData (I2NPMessage * msg); template TTunnel * CreateTunnel (TunnelConfig * config, OutboundTunnel * outboundTunnel = 0); - void CreateTunnelPool (i2p::data::LocalDestination * localDestination); + TunnelPool * CreateTunnelPool (i2p::data::LocalDestination * localDestination); + void DeleteTunnelPool (TunnelPool * pool); OutboundTunnel * CreateOneHopOutboundTestTunnel (InboundTunnel * replyTunnel); InboundTunnel * CreateOneHopInboundTestTunnel (OutboundTunnel * outboundTunnel = 0); diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 8860c4b8..3bdb55ab 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -15,7 +15,7 @@ namespace tunnel TunnelPool::~TunnelPool () { for (auto it: m_InboundTunnels) - delete it; + it->SetTunnelPool (nullptr); } void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel) @@ -55,7 +55,7 @@ namespace tunnel i2p::data::netdb.GetRandomRouter (firstHop) }), outboundTunnel); - tunnel->SetTunnelPool (this); + tunnel->SetTunnelPool (this); } void TunnelPool::ManageTunnels () diff --git a/TunnelPool.h b/TunnelPool.h index e6017e64..a6af0661 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -38,10 +38,6 @@ namespace tunnel int m_NumTunnels; std::set m_InboundTunnels; // recent tunnel appears first - public: - - // for HTTP only - const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }; }; } } From 26c5f6cd776e9fd8ae4a71c57611be823db3e0c2 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Mar 2014 21:22:59 -0400 Subject: [PATCH 09/10] 3-hops tunnels for tunnel pool --- Tunnel.cpp | 5 ++++- Tunnel.h | 1 - TunnelPool.cpp | 31 ++++++++++--------------------- TunnelPool.h | 2 +- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/Tunnel.cpp b/Tunnel.cpp index d0a2734f..e9e59b86 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -436,6 +436,9 @@ namespace tunnel if (ts > it->second->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { LogPrint ("Tunnel ", it->second->GetTunnelID (), " expired"); + auto pool = it->second->GetTunnelPool (); + if (pool) + pool->TunnelExpired (it->second); it = m_InboundTunnels.erase (it); } else @@ -496,7 +499,7 @@ namespace tunnel void Tunnels::ManageTunnelPools () { for (auto& it: m_Pools) - it->ManageTunnels (); + it->CreateTunnels (); } void Tunnels::PostTunnelData (I2NPMessage * msg) diff --git a/Tunnel.h b/Tunnel.h index 7d761453..4374c631 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -158,7 +158,6 @@ namespace tunnel const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; }; const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }; const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; }; - const decltype(m_Pools)& GetTunnelPools () const { return m_Pools; }; }; extern Tunnels tunnels; diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 3bdb55ab..7f14dbec 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -23,6 +23,13 @@ namespace tunnel m_InboundTunnels.insert (createdTunnel); } + void TunnelPool::TunnelExpired (InboundTunnel * expiredTunnel) + { + m_InboundTunnels.erase (expiredTunnel); + if (m_Owner) + m_Owner->UpdateLeaseSet (); + } + std::vector TunnelPool::GetInboundTunnels (int num) const { std::vector v; @@ -48,34 +55,16 @@ namespace tunnel OutboundTunnel * outboundTunnel = tunnels.GetNextOutboundTunnel (); LogPrint ("Creating destination inbound tunnel..."); auto firstHop = i2p::data::netdb.GetRandomRouter (outboundTunnel ? outboundTunnel->GetEndpointRouter () : nullptr); + auto secondHop = i2p::data::netdb.GetRandomRouter (firstHop); auto * tunnel = tunnels.CreateTunnel ( new TunnelConfig (std::vector { firstHop, - i2p::data::netdb.GetRandomRouter (firstHop) + secondHop, + i2p::data::netdb.GetRandomRouter (secondHop) }), outboundTunnel); tunnel->SetTunnelPool (this); } - - void TunnelPool::ManageTunnels () - { - uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - bool isLeaseSetUpdated = false; - for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();) - { - if (ts > (*it)->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) - { - LogPrint ("Destination tunnel ", (*it)->GetTunnelID (), " expired"); - m_InboundTunnels.erase (it++); - isLeaseSetUpdated = true; - } - else - ++it; - } - CreateTunnels (); - if (isLeaseSetUpdated && m_Owner) - m_Owner->UpdateLeaseSet (); - } } } diff --git a/TunnelPool.h b/TunnelPool.h index a6af0661..988e83c0 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -25,8 +25,8 @@ namespace tunnel void CreateTunnels (); void TunnelCreated (InboundTunnel * createdTunnel); + void TunnelExpired (InboundTunnel * expiredTunnel); std::vector GetInboundTunnels (int num) const; - void ManageTunnels (); private: From 3313a5af5c956258616357b01f384ac0aa2c7043 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 15 Mar 2014 09:16:55 -0400 Subject: [PATCH 10/10] generate LeaseSet from tunnel pool --- Streaming.cpp | 33 +++++++++++++++++++++++++++------ Streaming.h | 6 +++++- TunnelPool.cpp | 7 +++++-- i2p.cpp | 3 +++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 0bd88f66..b7282145 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -308,13 +308,15 @@ namespace stream m_IdentHash = i2p::data::CalculateIdentHash (m_Identity); m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_Keys.signingPrivateKey, 20)); - i2p::tunnel::tunnels.CreateTunnelPool (this); + m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (this); } StreamingDestination::~StreamingDestination () { if (m_LeaseSet) DeleteI2NPMessage (m_LeaseSet); + if (m_Pool) + i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); } void StreamingDestination::HandleNextPacket (Packet * packet) @@ -346,12 +348,20 @@ namespace stream } } - I2NPMessage * StreamingDestination::GetLeaseSet () + void StreamingDestination::UpdateLeaseSet () { - if (m_LeaseSet) // temporary always create new LeaseSet - DeleteI2NPMessage (m_LeaseSet); - m_LeaseSet = CreateLeaseSet (); + auto newLeaseSet = CreateLeaseSet (); + // TODO: make it atomic + auto oldLeaseSet = m_LeaseSet; + m_LeaseSet = newLeaseSet; + if (oldLeaseSet) + DeleteI2NPMessage (oldLeaseSet); + } + I2NPMessage * StreamingDestination::GetLeaseSet () + { + if (!m_LeaseSet) + m_LeaseSet = CreateLeaseSet (); return m_LeaseSet; } @@ -371,7 +381,7 @@ namespace stream size += 256; // encryption key memset (buf + size, 0, 128); size += 128; // signing key - auto tunnels = i2p::tunnel::tunnels.GetInboundTunnels (5); // 5 tunnels maximum + auto tunnels = m_Pool->GetInboundTunnels (5); // 5 tunnels maximum buf[size] = tunnels.size (); // num leases size++; // num for (auto it: tunnels) @@ -412,6 +422,17 @@ namespace stream if (sharedLocalDestination) sharedLocalDestination->DeleteStream (stream); } + + void StartStreaming () + { + if (!sharedLocalDestination) + sharedLocalDestination = new StreamingDestination (); + } + + void StopStreaming () + { + delete sharedLocalDestination; + } void HandleDataMessage (i2p::data::IdentHash * destination, const uint8_t * buf, size_t len) { diff --git a/Streaming.h b/Streaming.h index e4438e0c..8f0f289a 100644 --- a/Streaming.h +++ b/Streaming.h @@ -11,6 +11,7 @@ #include "LeaseSet.h" #include "I2NPProtocol.h" #include "Tunnel.h" +#include "TunnelPool.h" namespace i2p { @@ -114,7 +115,7 @@ namespace stream void HandleNextPacket (Packet * packet); // implements LocalDestination - void UpdateLeaseSet () {}; // TODO: + void UpdateLeaseSet (); private: @@ -127,6 +128,7 @@ namespace stream i2p::data::Identity m_Identity; i2p::data::IdentHash m_IdentHash; + i2p::tunnel::TunnelPool * m_Pool; I2NPMessage * m_LeaseSet; CryptoPP::DSA::PrivateKey m_SigningPrivateKey; @@ -134,6 +136,8 @@ namespace stream Stream * CreateStream (const i2p::data::LeaseSet& remote); void DeleteStream (Stream * stream); + void StartStreaming (); + void StopStreaming (); // assuming data is I2CP message void HandleDataMessage (i2p::data::IdentHash * destination, const uint8_t * buf, size_t len); diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 7f14dbec..d9d38354 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -21,6 +21,8 @@ namespace tunnel void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel) { m_InboundTunnels.insert (createdTunnel); + if (m_Owner) + m_Owner->UpdateLeaseSet (); } void TunnelPool::TunnelExpired (InboundTunnel * expiredTunnel) @@ -60,8 +62,9 @@ namespace tunnel new TunnelConfig (std::vector { firstHop, - secondHop, - i2p::data::netdb.GetRandomRouter (secondHop) + secondHop + // TODO: swithc to 3-hops later + /*i2p::data::netdb.GetRandomRouter (secondHop) */ }), outboundTunnel); tunnel->SetTunnelPool (this); diff --git a/i2p.cpp b/i2p.cpp index 839e7c01..b13b1791 100644 --- a/i2p.cpp +++ b/i2p.cpp @@ -24,6 +24,7 @@ #include "HTTPServer.h" #include "Garlic.h" #include "util.h" +#include "Streaming.h" // Global @@ -154,6 +155,7 @@ int main( int argc, char* argv[] ) i2p::transports.Start (); i2p::tunnel::tunnels.Start (); i2p::garlic::routing.Start (); + i2p::stream::StartStreaming (); while (running) { @@ -162,6 +164,7 @@ int main( int argc, char* argv[] ) } LogPrint("Shutdown started."); + i2p::stream::StopStreaming (); i2p::garlic::routing.Stop (); i2p::tunnel::tunnels.Stop (); i2p::transports.Stop ();