diff --git a/Destination.cpp b/Destination.cpp index 307e803a..5e1dd2c8 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include "Log.h" @@ -6,6 +7,7 @@ #include "Timestamp.h" #include "NetDb.h" #include "Destination.h" +#include "ClientContext.h" namespace i2p { @@ -383,12 +385,48 @@ namespace client } } + std::shared_ptr ClientDestination::CreateStream (const std::string& dest, int port) { + i2p::data::IdentHash identHash; + if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash)) + return CreateStream (identHash, port); + else + { + LogPrint (eLogWarning, "Remote destination ", dest, " not found"); + return nullptr; + } + } + + std::shared_ptr ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port) { + const i2p::data::LeaseSet * leaseSet = FindLeaseSet (dest); + if (!leaseSet) + { + bool found = false; + std::condition_variable newDataReceived; + std::mutex newDataReceivedMutex; + std::unique_lock l(newDataReceivedMutex); + RequestDestination (dest, + [&newDataReceived, &found](bool success) + { + found = success; + newDataReceived.notify_all (); + }); + if (newDataReceived.wait_for (l, std::chrono::seconds (STREAM_REQUEST_TIMEOUT)) == std::cv_status::timeout) + LogPrint (eLogError, "Subscription LeseseSet request timeout expired"); + if (found) + leaseSet = FindLeaseSet (dest); + } + if (leaseSet) + return CreateStream (*leaseSet, port); + else + return nullptr; + } + std::shared_ptr ClientDestination::CreateStream (const i2p::data::LeaseSet& remote, int port) { if (m_StreamingDestination) return m_StreamingDestination->CreateNewOutgoingStream (remote, port); return nullptr; - } + } void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor) { diff --git a/Destination.h b/Destination.h index 66836725..1f42dba3 100644 --- a/Destination.h +++ b/Destination.h @@ -35,6 +35,7 @@ namespace client const int DEFAULT_INBOUND_TUNNEL_LENGTH = 3; const char I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH[] = "outbound.length"; const int DEFAULT_OUTBOUND_TUNNEL_LENGTH = 3; + const int STREAM_REQUEST_TIMEOUT = 60; //in seconds class ClientDestination: public i2p::garlic::GarlicDestination { @@ -64,6 +65,8 @@ namespace client // streaming i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; }; + std::shared_ptr CreateStream (const std::string& dest, int port = 0); + std::shared_ptr CreateStream (const i2p::data::IdentHash& dest, int port = 0); std::shared_ptr CreateStream (const i2p::data::LeaseSet& remote, int port = 0); void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor); void StopAcceptingStreams (); diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index ac372112..d083ba6a 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -139,6 +139,11 @@ namespace client } } + I2PTunnel::I2PTunnel (ClientDestination * localDestination) : + m_LocalDestination (localDestination ? localDestination : + i2p::client::context.CreateNewLocalDestination (false, I2P_TUNNEL_DEFAULT_KEY_TYPE)) + { + } void I2PTunnel::AddConnection (std::shared_ptr conn) { m_Connections.insert (conn); @@ -155,8 +160,7 @@ namespace client } I2PClientTunnel::I2PClientTunnel (const std::string& destination, int port, ClientDestination * localDestination): - I2PTunnel (localDestination ? localDestination : - i2p::client::context.CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256)), + I2PTunnel (localDestination), m_Acceptor (GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)), m_Timer (GetService ()), m_Destination (destination), m_DestinationIdentHash (nullptr), m_RemoteLeaseSet (nullptr) diff --git a/I2PTunnel.h b/I2PTunnel.h index 5df769b6..5b00cec7 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -17,6 +17,7 @@ namespace client const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 8192; const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds + const uint16_t I2P_TUNNEL_DEFAULT_KEY_TYPE = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256; class I2PTunnel; class I2PTunnelConnection: public std::enable_shared_from_this @@ -58,8 +59,7 @@ namespace client { public: - I2PTunnel (ClientDestination * localDestination): - m_LocalDestination (localDestination) {}; + I2PTunnel (ClientDestination * localDestination = nullptr); virtual ~I2PTunnel () { ClearConnections (); }; void AddConnection (std::shared_ptr conn);