mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 08:14:15 +00:00
request and handle LeaseSets through local destination only
This commit is contained in:
parent
46ea2291fe
commit
3547a4042c
@ -433,7 +433,7 @@ namespace client
|
|||||||
const i2p::data::LeaseSet * leaseSet = i2p::data::netdb.FindLeaseSet (ident);
|
const i2p::data::LeaseSet * leaseSet = i2p::data::netdb.FindLeaseSet (ident);
|
||||||
if (!leaseSet)
|
if (!leaseSet)
|
||||||
{
|
{
|
||||||
i2p::data::netdb.RequestDestination (ident, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ());
|
i2p::client::context.GetSharedLocalDestination ()->RequestDestination (ident);
|
||||||
std::this_thread::sleep_for (std::chrono::seconds (5)); // wait for 5 seconds
|
std::this_thread::sleep_for (std::chrono::seconds (5)); // wait for 5 seconds
|
||||||
leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (ident);
|
leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (ident);
|
||||||
}
|
}
|
||||||
|
3
BOB.cpp
3
BOB.cpp
@ -1,7 +1,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "NetDb.h"
|
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "BOB.h"
|
#include "BOB.h"
|
||||||
|
|
||||||
@ -97,7 +96,7 @@ namespace client
|
|||||||
CreateConnection (receiver, leaseSet);
|
CreateConnection (receiver, leaseSet);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i2p::data::netdb.RequestDestination (ident, true, GetLocalDestination ()->GetTunnelPool ());
|
GetLocalDestination ()->RequestDestination (ident);
|
||||||
m_Timer.expires_from_now (boost::posix_time::seconds (I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT));
|
m_Timer.expires_from_now (boost::posix_time::seconds (I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT));
|
||||||
m_Timer.async_wait (std::bind (&BOBI2PInboundTunnel::HandleDestinationRequestTimer,
|
m_Timer.async_wait (std::bind (&BOBI2PInboundTunnel::HandleDestinationRequestTimer,
|
||||||
this, std::placeholders::_1, receiver, ident));
|
this, std::placeholders::_1, receiver, ident));
|
||||||
|
146
Destination.cpp
146
Destination.cpp
@ -3,6 +3,7 @@
|
|||||||
#include <cryptopp/dh.h>
|
#include <cryptopp/dh.h>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "Timestamp.h"
|
||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
#include "Destination.h"
|
#include "Destination.h"
|
||||||
|
|
||||||
@ -53,6 +54,8 @@ namespace client
|
|||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
Stop ();
|
Stop ();
|
||||||
|
for (auto it: m_LeaseSetRequests)
|
||||||
|
delete it.second;
|
||||||
for (auto it: m_RemoteLeaseSets)
|
for (auto it: m_RemoteLeaseSets)
|
||||||
delete it.second;
|
delete it.second;
|
||||||
if (m_Pool)
|
if (m_Pool)
|
||||||
@ -193,7 +196,9 @@ namespace client
|
|||||||
break;
|
break;
|
||||||
case eI2NPDatabaseStore:
|
case eI2NPDatabaseStore:
|
||||||
HandleDatabaseStoreMessage (buf + sizeof (I2NPHeader), be16toh (header->size));
|
HandleDatabaseStoreMessage (buf + sizeof (I2NPHeader), be16toh (header->size));
|
||||||
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); // TODO: remove
|
break;
|
||||||
|
case eI2NPDatabaseSearchReply:
|
||||||
|
HandleDatabaseSearchReplyMessage (buf + sizeof (I2NPHeader), be16toh (header->size));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
|
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
|
||||||
@ -203,6 +208,12 @@ namespace client
|
|||||||
void ClientDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
|
void ClientDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)buf;
|
I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)buf;
|
||||||
|
auto it1 = m_LeaseSetRequests.find (msg->key);
|
||||||
|
if (it1 != m_LeaseSetRequests.end ())
|
||||||
|
{
|
||||||
|
delete it1->second;
|
||||||
|
m_LeaseSetRequests.erase (it1);
|
||||||
|
}
|
||||||
size_t offset = sizeof (I2NPDatabaseStoreMsg);
|
size_t offset = sizeof (I2NPDatabaseStoreMsg);
|
||||||
if (msg->replyToken) // TODO:
|
if (msg->replyToken) // TODO:
|
||||||
offset += 36;
|
offset += 36;
|
||||||
@ -225,6 +236,46 @@ namespace client
|
|||||||
LogPrint (eLogError, "Unexpected client's DatabaseStore type ", msg->type, ". Dropped");
|
LogPrint (eLogError, "Unexpected client's DatabaseStore type ", msg->type, ". Dropped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
i2p::data::IdentHash key (buf);
|
||||||
|
int num = buf[32]; // num
|
||||||
|
LogPrint ("DatabaseSearchReply for ", key.ToBase64 (), " num=", num);
|
||||||
|
auto it = m_LeaseSetRequests.find (key);
|
||||||
|
if (it != m_LeaseSetRequests.end ())
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
if (it->second->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
i2p::data::IdentHash peerHash (buf + 33 + i*32);
|
||||||
|
auto floodfill = i2p::data::netdb.FindRouter (peerHash);
|
||||||
|
if (floodfill)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
SendLeaseSetRequest (key, floodfill, it->second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "Found new floodfill. Request it");
|
||||||
|
i2p::data::netdb.RequestDestination (peerHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogInfo, key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST," floodfills");
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Suggested floodfills are not presented in netDb");
|
||||||
|
delete it->second;
|
||||||
|
m_LeaseSetRequests.erase (it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint ("Request for ", key.ToBase64 (), " not found");
|
||||||
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleDeliveryStatusMessage (I2NPMessage * msg)
|
void ClientDestination::HandleDeliveryStatusMessage (I2NPMessage * msg)
|
||||||
{
|
{
|
||||||
I2NPDeliveryStatusMsg * deliveryStatus = (I2NPDeliveryStatusMsg *)msg->GetPayload ();
|
I2NPDeliveryStatusMsg * deliveryStatus = (I2NPDeliveryStatusMsg *)msg->GetPayload ();
|
||||||
@ -247,7 +298,7 @@ namespace client
|
|||||||
if (m_IsPublic)
|
if (m_IsPublic)
|
||||||
Publish ();
|
Publish ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Publish ()
|
void ClientDestination::Publish ()
|
||||||
{
|
{
|
||||||
if (!m_LeaseSet || !m_Pool)
|
if (!m_LeaseSet || !m_Pool)
|
||||||
@ -355,5 +406,96 @@ namespace client
|
|||||||
m_DatagramDestination = new i2p::datagram::DatagramDestination (*this);
|
m_DatagramDestination = new i2p::datagram::DatagramDestination (*this);
|
||||||
return m_DatagramDestination;
|
return m_DatagramDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClientDestination::RequestDestination (const i2p::data::IdentHash& dest)
|
||||||
|
{
|
||||||
|
if (!m_Pool || !IsReady ()) return false;
|
||||||
|
m_Service.post (std::bind (&ClientDestination::RequestLeaseSet, this, dest));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientDestination::RequestLeaseSet (const i2p::data::IdentHash& dest)
|
||||||
|
{
|
||||||
|
std::set<i2p::data::IdentHash> excluded;
|
||||||
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
|
||||||
|
if (floodfill)
|
||||||
|
{
|
||||||
|
LeaseSetRequest * request = new LeaseSetRequest (m_Service);
|
||||||
|
m_LeaseSetRequests[dest] = request;
|
||||||
|
SendLeaseSetRequest (dest, floodfill, request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "No floodfills found");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
|
||||||
|
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, LeaseSetRequest * request)
|
||||||
|
{
|
||||||
|
auto replyTunnel = m_Pool->GetNextInboundTunnel ();
|
||||||
|
if (!replyTunnel) LogPrint (eLogError, "No inbound tunnels found");
|
||||||
|
|
||||||
|
auto outboundTunnel = m_Pool->GetNextOutboundTunnel ();
|
||||||
|
if (!outboundTunnel) LogPrint (eLogError, "No outbound tunnels found");
|
||||||
|
|
||||||
|
if (replyTunnel && outboundTunnel)
|
||||||
|
{
|
||||||
|
request->excluded.insert (nextFloodfill->GetIdentHash ());
|
||||||
|
request->requestTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
request->requestTimeoutTimer.cancel ();
|
||||||
|
|
||||||
|
I2NPMessage * msg = WrapMessage (*nextFloodfill,
|
||||||
|
CreateDatabaseLookupMsg (dest, replyTunnel->GetNextIdentHash (),
|
||||||
|
replyTunnel->GetNextTunnelID (), false, &request->excluded, true, m_Pool));
|
||||||
|
outboundTunnel->SendTunnelDataMsg (
|
||||||
|
{
|
||||||
|
i2p::tunnel::TunnelMessageBlock
|
||||||
|
{
|
||||||
|
i2p::tunnel::eDeliveryTypeRouter,
|
||||||
|
nextFloodfill->GetIdentHash (), 0, msg
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT));
|
||||||
|
request->requestTimeoutTimer.async_wait (std::bind (&ClientDestination::HandleRequestTimoutTimer,
|
||||||
|
this, std::placeholders::_1, dest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// request failed
|
||||||
|
delete request;
|
||||||
|
m_LeaseSetRequests.erase (dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
auto it = m_LeaseSetRequests.find (dest);
|
||||||
|
if (it != m_LeaseSetRequests.end ())
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
if (ts < it->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT)
|
||||||
|
{
|
||||||
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, it->second->excluded);
|
||||||
|
if (floodfill)
|
||||||
|
SendLeaseSetRequest (dest, floodfill, it->second);
|
||||||
|
else
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
m_LeaseSetRequests.erase (it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,15 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "TunnelPool.h"
|
#include "TunnelPool.h"
|
||||||
#include "CryptoConst.h"
|
#include "CryptoConst.h"
|
||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
|
#include "NetDb.h"
|
||||||
#include "Streaming.h"
|
#include "Streaming.h"
|
||||||
#include "Datagram.h"
|
#include "Datagram.h"
|
||||||
|
|
||||||
@ -22,7 +25,10 @@ namespace client
|
|||||||
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
|
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
|
||||||
const uint8_t PROTOCOL_TYPE_RAW = 18;
|
const uint8_t PROTOCOL_TYPE_RAW = 18;
|
||||||
const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
||||||
|
const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds
|
||||||
|
const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds
|
||||||
|
const int MAX_NUM_FLOODFILLS_PER_REQUEST = 7;
|
||||||
|
|
||||||
// I2CP
|
// I2CP
|
||||||
const char I2CP_PARAM_INBOUND_TUNNEL_LENGTH[] = "inbound.length";
|
const char I2CP_PARAM_INBOUND_TUNNEL_LENGTH[] = "inbound.length";
|
||||||
const int DEFAULT_INBOUND_TUNNEL_LENGTH = 3;
|
const int DEFAULT_INBOUND_TUNNEL_LENGTH = 3;
|
||||||
@ -31,6 +37,14 @@ namespace client
|
|||||||
|
|
||||||
class ClientDestination: public i2p::garlic::GarlicDestination
|
class ClientDestination: public i2p::garlic::GarlicDestination
|
||||||
{
|
{
|
||||||
|
struct LeaseSetRequest
|
||||||
|
{
|
||||||
|
LeaseSetRequest (boost::asio::io_service& service): requestTime (0), requestTimeoutTimer (service) {};
|
||||||
|
std::set<i2p::data::IdentHash> excluded;
|
||||||
|
uint64_t requestTime;
|
||||||
|
boost::asio::deadline_timer requestTimeoutTimer;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
@ -43,7 +57,8 @@ namespace client
|
|||||||
i2p::tunnel::TunnelPool * GetTunnelPool () { return m_Pool; };
|
i2p::tunnel::TunnelPool * GetTunnelPool () { return m_Pool; };
|
||||||
bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases (); };
|
bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases (); };
|
||||||
const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident);
|
const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident);
|
||||||
|
bool RequestDestination (const i2p::data::IdentHash& dest);
|
||||||
|
|
||||||
// streaming
|
// streaming
|
||||||
i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; };
|
i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; };
|
||||||
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::LeaseSet& remote, int port = 0);
|
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::LeaseSet& remote, int port = 0);
|
||||||
@ -79,9 +94,14 @@ namespace client
|
|||||||
void UpdateLeaseSet ();
|
void UpdateLeaseSet ();
|
||||||
void Publish ();
|
void Publish ();
|
||||||
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
||||||
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
|
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
|
||||||
|
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
||||||
void HandleDeliveryStatusMessage (I2NPMessage * msg);
|
void HandleDeliveryStatusMessage (I2NPMessage * msg);
|
||||||
|
|
||||||
|
void RequestLeaseSet (const i2p::data::IdentHash& dest);
|
||||||
|
void SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, LeaseSetRequest * request);
|
||||||
|
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
@ -91,6 +111,7 @@ namespace client
|
|||||||
i2p::data::PrivateKeys m_Keys;
|
i2p::data::PrivateKeys m_Keys;
|
||||||
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
||||||
std::map<i2p::data::IdentHash, i2p::data::LeaseSet *> m_RemoteLeaseSets;
|
std::map<i2p::data::IdentHash, i2p::data::LeaseSet *> m_RemoteLeaseSets;
|
||||||
|
std::map<i2p::data::IdentHash, LeaseSetRequest *> m_LeaseSetRequests;
|
||||||
|
|
||||||
i2p::tunnel::TunnelPool * m_Pool;
|
i2p::tunnel::TunnelPool * m_Pool;
|
||||||
i2p::data::LeaseSet * m_LeaseSet;
|
i2p::data::LeaseSet * m_LeaseSet;
|
||||||
|
@ -874,7 +874,7 @@ namespace util
|
|||||||
SendToDestination (leaseSet, port, buf, len);
|
SendToDestination (leaseSet, port, buf, len);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i2p::data::netdb.RequestDestination (destination, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ());
|
i2p::client::context.GetSharedLocalDestination ()->RequestDestination (destination);
|
||||||
m_Timer.expires_from_now (boost::posix_time::seconds(HTTP_DESTINATION_REQUEST_TIMEOUT));
|
m_Timer.expires_from_now (boost::posix_time::seconds(HTTP_DESTINATION_REQUEST_TIMEOUT));
|
||||||
m_Timer.async_wait (boost::bind (&HTTPConnection::HandleDestinationRequestTimeout,
|
m_Timer.async_wait (boost::bind (&HTTPConnection::HandleDestinationRequestTimeout,
|
||||||
this, boost::asio::placeholders::error, destination, port, buf, len));
|
this, boost::asio::placeholders::error, destination, port, buf, len));
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "NetDb.h"
|
|
||||||
#include "Destination.h"
|
#include "Destination.h"
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "I2PTunnel.h"
|
#include "I2PTunnel.h"
|
||||||
@ -214,7 +213,7 @@ namespace client
|
|||||||
CreateConnection (socket);
|
CreateConnection (socket);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i2p::data::netdb.RequestDestination (*m_DestinationIdentHash, true, GetLocalDestination ()->GetTunnelPool ());
|
GetLocalDestination ()->RequestDestination (*m_DestinationIdentHash);
|
||||||
m_Timer.expires_from_now (boost::posix_time::seconds (I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT));
|
m_Timer.expires_from_now (boost::posix_time::seconds (I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT));
|
||||||
m_Timer.async_wait (std::bind (&I2PClientTunnel::HandleDestinationRequestTimer,
|
m_Timer.async_wait (std::bind (&I2PClientTunnel::HandleDestinationRequestTimer,
|
||||||
this, std::placeholders::_1, socket));
|
this, std::placeholders::_1, socket));
|
||||||
|
4
SAM.cpp
4
SAM.cpp
@ -7,7 +7,6 @@
|
|||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "NetDb.h"
|
|
||||||
#include "Destination.h"
|
#include "Destination.h"
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "SAM.h"
|
#include "SAM.h"
|
||||||
@ -757,8 +756,7 @@ namespace client
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint ("SAM datagram destination not found");
|
LogPrint ("SAM datagram destination not found");
|
||||||
i2p::data::netdb.RequestDestination (dest.GetIdentHash (), true,
|
session->localDestination->RequestDestination (dest.GetIdentHash ());
|
||||||
session->localDestination->GetTunnelPool ());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user