mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-07-12 03:11:43 +00:00
acc0f94e49
A repeated SESSION CREATE (SAM/I2CP) presenting a fresh offline-signature transient of the same master resolves to the same identity hash, so CreateNewLocalDestination returns the existing destination and the new transient is dropped: the destination keeps signing LeaseSets with the old transient and goes offline at its expiry. Adopt the newer transient in place (swap keys and republish the LeaseSet, without touching tunnels or streams) when its expiry is later, so an offline transient can be rotated before it expires without rebuilding the destination.
365 lines
18 KiB
C++
365 lines
18 KiB
C++
/*
|
|
* Copyright (c) 2013-2026, The PurpleI2P Project
|
|
*
|
|
* This file is part of Purple i2pd project and licensed under BSD3
|
|
*
|
|
* See full license text in LICENSE file at top of project tree
|
|
*/
|
|
|
|
#ifndef DESTINATION_H__
|
|
#define DESTINATION_H__
|
|
|
|
#include <string.h>
|
|
#include <thread>
|
|
#include <mutex>
|
|
#include <memory>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <string>
|
|
#include <functional>
|
|
#include <boost/asio.hpp>
|
|
#include "Identity.h"
|
|
#include "TunnelPool.h"
|
|
#include "Crypto.h"
|
|
#include "CryptoKey.h"
|
|
#include "LeaseSet.h"
|
|
#include "Garlic.h"
|
|
#include "NetDb.hpp"
|
|
#include "Streaming.h"
|
|
#include "Datagram.h"
|
|
#include "util.h"
|
|
|
|
namespace i2p
|
|
{
|
|
namespace client
|
|
{
|
|
const uint8_t PROTOCOL_TYPE_STREAMING = 6;
|
|
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
|
|
const uint8_t PROTOCOL_TYPE_RAW = 18;
|
|
const uint8_t PROTOCOL_TYPE_DATAGRAM2 = 19;
|
|
const uint8_t PROTOCOL_TYPE_DATAGRAM3 = 20;
|
|
const int PUBLISH_CONFIRMATION_TIMEOUT = 1800; // in milliseconds
|
|
const int PUBLISH_VERIFICATION_TIMEOUT = 5; // in seconds after successful publish
|
|
const int PUBLISH_VERIFICATION_TIMEOUT_VARIANCE = 3; // in seconds
|
|
const int PUBLISH_MIN_INTERVAL = 20; // in seconds
|
|
const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically
|
|
const int LEASESET_REQUEST_TIMEOUT = 1600; // in milliseconds
|
|
const int MAX_LEASESET_REQUEST_TIMEOUT = 12000; // in milliseconds
|
|
const int DESTINATION_CLEANUP_TIMEOUT = 44; // in seconds
|
|
const int DESTINATION_CLEANUP_TIMEOUT_VARIANCE = 30; // in seconds
|
|
const unsigned int MAX_NUM_FLOODFILLS_PER_REQUEST = 7;
|
|
|
|
// I2CP
|
|
const char I2CP_PARAM_INBOUND_TUNNEL_LENGTH[] = "inbound.length";
|
|
const int DEFAULT_INBOUND_TUNNEL_LENGTH = 3;
|
|
const char I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH[] = "outbound.length";
|
|
const int DEFAULT_OUTBOUND_TUNNEL_LENGTH = 3;
|
|
const char I2CP_PARAM_INBOUND_TUNNELS_QUANTITY[] = "inbound.quantity";
|
|
const int DEFAULT_INBOUND_TUNNELS_QUANTITY = 5;
|
|
const char I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY[] = "outbound.quantity";
|
|
const int DEFAULT_OUTBOUND_TUNNELS_QUANTITY = 5;
|
|
const char I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE[] = "inbound.lengthVariance";
|
|
const int DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE = 0;
|
|
const char I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE[] = "outbound.lengthVariance";
|
|
const int DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE = 0;
|
|
const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers";
|
|
const char I2CP_PARAM_TRUSTED_ROUTERS[] = "trustedRouters";
|
|
const char I2CP_PARAM_INBOUND_RANDOM_KEY[] = "inbound.randomKey";
|
|
const char I2CP_PARAM_OUTBOUND_RANDOM_KEY[] = "outbound.randomKey";
|
|
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
|
|
const int DEFAULT_TAGS_TO_SEND = 40;
|
|
const char I2CP_PARAM_RATCHET_INBOUND_TAGS[] = "crypto.ratchet.inboundTags";
|
|
const char I2CP_PARAM_RATCHET_OUTBOUND_TAGS[] = "crypto.ratchet.outboundTags"; // not used yet
|
|
const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname";
|
|
const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname";
|
|
const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet";
|
|
const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType";
|
|
const int DEFAULT_LEASESET_TYPE = 3;
|
|
const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType";
|
|
const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64
|
|
const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType";
|
|
const char I2CP_PARAM_LEASESET_CLIENT_DH[] = "i2cp.leaseSetClient.dh"; // group of i2cp.leaseSetClient.dh.nnn
|
|
const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn
|
|
|
|
// latency
|
|
const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min";
|
|
const int DEFAULT_MIN_TUNNEL_LATENCY = 0;
|
|
const char I2CP_PARAM_MAX_TUNNEL_LATENCY[] = "latency.max";
|
|
const int DEFAULT_MAX_TUNNEL_LATENCY = 0;
|
|
|
|
// streaming
|
|
const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay";
|
|
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
|
|
const char I2CP_PARAM_STREAMING_MAX_OUTBOUND_SPEED[] = "i2p.streaming.maxOutboundSpeed"; // bytes/sec
|
|
const int DEFAULT_MAX_OUTBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s
|
|
const char I2CP_PARAM_STREAMING_MAX_INBOUND_SPEED[] = "i2p.streaming.maxInboundSpeed"; // bytes/sec
|
|
const int DEFAULT_MAX_INBOUND_SPEED = 1730000000; // no more than 1.73 Gbytes/s
|
|
const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings";
|
|
const int DEFAULT_ANSWER_PINGS = true;
|
|
const char I2CP_PARAM_STREAMING_PROFILE[] = "i2p.streaming.profile";
|
|
const int STREAMING_PROFILE_BULK = 1; // high bandwidth
|
|
const int STREAMING_PROFILE_INTERACTIVE = 2; // low bandwidth
|
|
const int DEFAULT_STREAMING_PROFILE = STREAMING_PROFILE_BULK;
|
|
const char I2CP_PARAM_STREAMING_MAX_CONCURRENT_STREAMS[] = "i2p.streaming.maxConcurrentStreams";
|
|
const int DEFAULT_MAX_CONCURRENT_STREAMS = 2048;
|
|
const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MINUTE[] ="i2p.streaming.maxConnsPerMinute"; // per dest
|
|
const int DEFAULT_MAX_CONNS_PER_MINUTE = 0; // unlimited
|
|
const char I2CP_PARAM_STREAMING_MAX_WINDOW_SIZE[] = "i2p.streaming.maxWindowSize";
|
|
const char I2CP_PARAM_STREAMING_MAX_RESENDS[] = "i2p.streaming.maxResends";
|
|
const char I2CP_PARAM_STREAMING_DONT_SIGN[] = "i2p.streaming.dontSign";
|
|
const int DEFAULT_DONT_SIGN = false;
|
|
|
|
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
|
|
|
|
class LeaseSetDestination: public i2p::garlic::GarlicDestination,
|
|
public std::enable_shared_from_this<LeaseSetDestination>
|
|
{
|
|
typedef std::function<void (std::shared_ptr<i2p::data::LeaseSet> leaseSet)> RequestComplete;
|
|
// leaseSet = nullptr means not found
|
|
struct LeaseSetRequest
|
|
{
|
|
LeaseSetRequest (boost::asio::io_context& service): requestTime (0), requestTimeoutTimer (service) {};
|
|
std::unordered_set<i2p::data::IdentHash> excluded;
|
|
uint64_t requestTime;
|
|
boost::asio::steady_timer requestTimeoutTimer;
|
|
std::list<RequestComplete> requestComplete;
|
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
|
|
std::shared_ptr<i2p::tunnel::InboundTunnel> replyTunnel;
|
|
std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey; // for encrypted LeaseSet2 only
|
|
|
|
void Complete (std::shared_ptr<i2p::data::LeaseSet> ls)
|
|
{
|
|
for (auto& it: requestComplete) it (ls);
|
|
requestComplete.clear ();
|
|
}
|
|
};
|
|
|
|
public:
|
|
|
|
LeaseSetDestination (boost::asio::io_context& service, bool isPublic, const i2p::util::Mapping * params = nullptr);
|
|
~LeaseSetDestination ();
|
|
const std::string& GetNickname () const { return m_Nickname; };
|
|
auto& GetService () { return m_Service; };
|
|
|
|
virtual void Start ();
|
|
virtual void Stop ();
|
|
|
|
/** i2cp reconfigure */
|
|
virtual bool Reconfigure(const i2p::util::Mapping& i2cpOpts);
|
|
|
|
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
|
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
|
|
std::shared_ptr<i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
|
|
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
|
|
bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr);
|
|
void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
|
|
void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify = true);
|
|
|
|
// implements GarlicDestination
|
|
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet () override;
|
|
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const override { return m_Pool; }
|
|
|
|
// override GarlicDestination
|
|
bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag) override;
|
|
void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag) override;
|
|
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg) override;
|
|
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg) override;
|
|
void SetLeaseSetUpdated (bool post) override;
|
|
|
|
bool IsPublic () const { return m_IsPublic; };
|
|
void SetPublic (bool pub) { m_IsPublic = pub; };
|
|
|
|
protected:
|
|
|
|
// implements GarlicDestination
|
|
void HandleI2NPMessage (const uint8_t * buf, size_t len) override;
|
|
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload,
|
|
size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from) override;
|
|
|
|
void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet);
|
|
int GetLeaseSetType () const { return m_LeaseSetType; };
|
|
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
|
|
int GetAuthType () const { return m_AuthType; };
|
|
virtual void CleanupDestination () {}; // additional clean up in derived classes
|
|
virtual i2p::data::CryptoKeyType GetPreferredCryptoType () const = 0;
|
|
// I2CP
|
|
virtual void HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) = 0;
|
|
virtual void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) = 0;
|
|
void UpdateLeaseSet ();
|
|
|
|
private:
|
|
|
|
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSetMt ();
|
|
void Publish ();
|
|
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
|
void HandlePublishVerificationTimer (const boost::system::error_code& ecode);
|
|
void HandlePublishDelayTimer (const boost::system::error_code& ecode);
|
|
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from);
|
|
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
|
void HandleDeliveryStatusMessage (uint32_t msgID);
|
|
|
|
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
|
|
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
|
|
void SendNextLeaseSetRequest (const i2p::data::IdentHash& key, std::shared_ptr<LeaseSetRequest> request);
|
|
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
|
|
void HandleCleanupTimer (const boost::system::error_code& ecode);
|
|
void CleanupRemoteLeaseSets ();
|
|
|
|
private:
|
|
|
|
boost::asio::io_context& m_Service;
|
|
mutable std::mutex m_RemoteLeaseSetsMutex;
|
|
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
|
|
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
|
|
|
|
std::list<std::shared_ptr<I2NPMessage> > m_IncomingMsgsQueue;
|
|
mutable std::mutex m_IncomingMsgsQueueMutex;
|
|
|
|
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
|
|
std::mutex m_LeaseSetMutex;
|
|
std::shared_ptr<const i2p::data::LocalLeaseSet> m_LeaseSet;
|
|
bool m_IsPublic;
|
|
uint32_t m_PublishReplyToken;
|
|
uint64_t m_LastSubmissionTime; // in seconds
|
|
std::unordered_set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
|
|
|
|
boost::asio::steady_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
|
|
m_PublishDelayTimer, m_CleanupTimer;
|
|
std::string m_Nickname;
|
|
int m_LeaseSetType, m_AuthType;
|
|
std::unique_ptr<i2p::data::Tag<32> > m_LeaseSetPrivKey; // non-null if presented
|
|
|
|
public:
|
|
|
|
// for HTTP only
|
|
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
|
|
const decltype(m_RemoteLeaseSets)& GetLeaseSets () const { return m_RemoteLeaseSets; };
|
|
bool IsEncryptedLeaseSet () const { return m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; };
|
|
bool IsPerClientAuth () const { return m_AuthType > 0; };
|
|
};
|
|
|
|
class ClientDestination: public LeaseSetDestination
|
|
{
|
|
public:
|
|
|
|
ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys,
|
|
bool isPublic, const i2p::util::Mapping * params = nullptr);
|
|
~ClientDestination ();
|
|
|
|
void Start () override;
|
|
void Stop () override;
|
|
|
|
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
|
void SetPrivateKeys (const i2p::data::PrivateKeys& keys);
|
|
void UpdateOfflineSignature (const i2p::data::PrivateKeys& keys);
|
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
|
|
|
|
// ref counter
|
|
int Acquire () { return ++m_RefCounter; };
|
|
int Release () { return --m_RefCounter; };
|
|
int GetRefCounter () const { return m_RefCounter; };
|
|
|
|
// streaming
|
|
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (uint16_t port, bool gzip = true); // additional
|
|
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (uint16_t port = 0) const;
|
|
std::shared_ptr<i2p::stream::StreamingDestination> RemoveStreamingDestination (uint16_t port);
|
|
// following methods operate with default streaming destination
|
|
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port = 0);
|
|
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0);
|
|
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, uint16_t port = 0); // sync
|
|
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0); // sync
|
|
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, uint16_t port = 0);
|
|
void SendPing (const i2p::data::IdentHash& to);
|
|
void SendPing (std::shared_ptr<const i2p::data::BlindedPublicKey> to);
|
|
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
|
void StopAcceptingStreams ();
|
|
bool IsAcceptingStreams () const;
|
|
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
|
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
|
int GetStreamingOutboundSpeed () const { return m_StreamingOutboundSpeed; }
|
|
int GetStreamingInboundSpeed () const { return m_StreamingInboundSpeed; }
|
|
int GetStreamingMaxConcurrentStreams () const { return m_StreamingMaxConcurrentStreams; }
|
|
int GetStreamingMaxConnsPerMinute () const { return m_StreamingMaxConnsPerMinute; }
|
|
bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; }
|
|
bool IsStreamingDontSign () const { return m_IsStreamingDontSign; }
|
|
int GetStreamingMaxWindowSize () const { return m_StreamingMaxWindowSize; }
|
|
int GetStreamingMaxResends () const { return m_StreamingMaxResends; }
|
|
|
|
// datagram
|
|
std::shared_ptr<i2p::datagram::DatagramDestination> GetDatagramDestination () const { return m_DatagramDestination; };
|
|
std::shared_ptr<i2p::datagram::DatagramDestination> CreateDatagramDestination (bool gzip = true,
|
|
i2p::datagram::DatagramVersion version = i2p::datagram::eDatagramV1);
|
|
|
|
// implements LocalDestination
|
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const override;
|
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const override { return m_Keys.GetPublic (); };
|
|
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const override;
|
|
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const override;
|
|
|
|
protected:
|
|
|
|
// GarlicDestionation
|
|
i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override;
|
|
// LeaseSetDestination
|
|
void CleanupDestination () override;
|
|
i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; }
|
|
// I2CP
|
|
void HandleDataMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from) override;
|
|
void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) override;
|
|
|
|
private:
|
|
|
|
std::shared_ptr<ClientDestination> GetSharedFromThis () {
|
|
return std::static_pointer_cast<ClientDestination>(shared_from_this ());
|
|
}
|
|
void PersistTemporaryKeys (std::shared_ptr<i2p::crypto::LocalEncryptionKey> keys);
|
|
void ReadAuthKey (const std::string& group, const i2p::util::Mapping * params);
|
|
|
|
template<typename Dest>
|
|
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, uint16_t port);
|
|
|
|
private:
|
|
|
|
i2p::data::PrivateKeys m_Keys;
|
|
std::map<i2p::data::CryptoKeyType, std::shared_ptr<i2p::crypto::LocalEncryptionKey> > m_EncryptionKeys; // last is most preferable
|
|
i2p::data::CryptoKeyType m_PreferredCryptoType;
|
|
|
|
int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed,
|
|
m_StreamingMaxConcurrentStreams, m_StreamingMaxConnsPerMinute, m_StreamingMaxWindowSize,
|
|
m_StreamingMaxResends;
|
|
bool m_IsStreamingAnswerPings, m_IsStreamingDontSign;
|
|
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
|
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
|
std::shared_ptr<i2p::stream::StreamingDestination> m_LastStreamingDestination; uint16_t m_LastPort; // for server tunnels
|
|
std::shared_ptr<i2p::datagram::DatagramDestination> m_DatagramDestination;
|
|
int m_RefCounter; // how many clients(tunnels) use this destination
|
|
uint64_t m_LastPublishedTimestamp;
|
|
|
|
boost::asio::steady_timer m_ReadyChecker;
|
|
|
|
std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys; // we don't need them for I2CP
|
|
|
|
public:
|
|
|
|
// for HTTP only
|
|
std::vector<std::shared_ptr<const i2p::stream::Stream> > GetAllStreams () const;
|
|
bool DeleteStream (uint32_t recvStreamID);
|
|
};
|
|
|
|
class RunnableClientDestination: private i2p::util::RunnableService, public ClientDestination
|
|
{
|
|
public:
|
|
|
|
RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const i2p::util::Mapping * params = nullptr);
|
|
~RunnableClientDestination ();
|
|
|
|
void Start ();
|
|
void Stop ();
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|