Reformat code

This commit is contained in:
Anatolii Cherednichenko 2022-08-30 02:11:28 +03:00
parent 3ddb370718
commit 55534ea002
140 changed files with 46068 additions and 48277 deletions

File diff suppressed because it is too large Load diff

View file

@ -23,149 +23,189 @@
#include "Destination.h"
#include "LeaseSet.h"
namespace i2p
{
namespace client
{
const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes
const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes
const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours)
const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes
const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout
const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in second
namespace i2p {
namespace client {
const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes
const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes
const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours)
const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes
const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout
const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in second
const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53;
const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54;
const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53;
const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54;
const size_t B33_ADDRESS_THRESHOLD = 52; // characters
const size_t B33_ADDRESS_THRESHOLD = 52; // characters
struct Address
{
enum { eAddressIndentHash, eAddressBlindedPublicKey, eAddressInvalid } addressType;
i2p::data::IdentHash identHash;
std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey;
struct Address {
enum {
eAddressIndentHash, eAddressBlindedPublicKey, eAddressInvalid
} addressType;
i2p::data::IdentHash identHash;
std::shared_ptr <i2p::data::BlindedPublicKey> blindedPublicKey;
Address (const std::string& b32);
Address (const i2p::data::IdentHash& hash);
bool IsIdentHash () const { return addressType == eAddressIndentHash; };
bool IsValid () const { return addressType != eAddressInvalid; };
};
Address(const std::string &b32);
inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); }
Address(const i2p::data::IdentHash &hash);
class AddressBookStorage // interface for storage
{
public:
bool IsIdentHash() const { return addressType == eAddressIndentHash; };
virtual ~AddressBookStorage () {};
virtual std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const = 0;
virtual void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) = 0;
virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0;
bool IsValid() const { return addressType != eAddressInvalid; };
};
virtual bool Init () = 0;
virtual int Load (std::map<std::string, std::shared_ptr<Address> >& addresses) = 0;
virtual int LoadLocal (std::map<std::string, std::shared_ptr<Address> >& addresses) = 0;
virtual int Save (const std::map<std::string, std::shared_ptr<Address> >& addresses) = 0;
inline std::string GetB32Address(const i2p::data::IdentHash &ident) {
return ident.ToBase32().append(".b32.i2p");
}
virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0;
virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0;
virtual void ResetEtags () = 0;
};
class AddressBookStorage // interface for storage
{
public:
class AddressBookSubscription;
class AddressResolver;
class AddressBook
{
public:
virtual ~AddressBookStorage() {};
AddressBook ();
~AddressBook ();
void Start ();
void StartResolvers ();
void Stop ();
std::shared_ptr<const Address> GetAddress (const std::string& address);
std::shared_ptr<const i2p::data::IdentityEx> GetFullAddress (const std::string& address);
std::shared_ptr<const Address> FindAddress (const std::string& address);
void LookupAddress (const std::string& address);
void InsertAddress (const std::string& address, const std::string& jump); // for jump links
void InsertFullAddress (std::shared_ptr<const i2p::data::IdentityEx> address);
virtual std::shared_ptr<const i2p::data::IdentityEx>
GetAddress(const i2p::data::IdentHash &ident) const = 0;
bool LoadHostsFromStream (std::istream& f, bool is_update);
void DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified);
//This method returns the ".b32.i2p" address
std::string ToAddress(const i2p::data::IdentHash& ident) { return GetB32Address(ident); }
std::string ToAddress(std::shared_ptr<const i2p::data::IdentityEx> ident) { return ToAddress(ident->GetIdentHash ()); }
virtual void AddAddress(std::shared_ptr<const i2p::data::IdentityEx> address) = 0;
bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified);
virtual void RemoveAddress(const i2p::data::IdentHash &ident) = 0;
private:
virtual bool Init() = 0;
void StartSubscriptions ();
void StopSubscriptions ();
virtual int Load(std::map <std::string, std::shared_ptr<Address>> &addresses) = 0;
void LoadHosts ();
void LoadSubscriptions ();
void LoadLocal ();
virtual int LoadLocal(std::map <std::string, std::shared_ptr<Address>> &addresses) = 0;
void HandleSubscriptionsUpdateTimer (const boost::system::error_code& ecode);
virtual int Save(const std::map <std::string, std::shared_ptr<Address>> &addresses) = 0;
void StartLookups ();
void StopLookups ();
void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
virtual void SaveEtag(const i2p::data::IdentHash &subscription, const std::string &etag,
const std::string &lastModified) = 0;
private:
virtual bool
GetEtag(const i2p::data::IdentHash &subscription, std::string &etag, std::string &lastModified) = 0;
std::mutex m_AddressBookMutex;
std::map<std::string, std::shared_ptr<Address> > m_Addresses;
std::map<i2p::data::IdentHash, std::shared_ptr<AddressResolver> > m_Resolvers; // local destination->resolver
std::mutex m_LookupsMutex;
std::map<uint32_t, std::string> m_Lookups; // nonce -> address
AddressBookStorage * m_Storage;
volatile bool m_IsLoaded, m_IsDownloading;
int m_NumRetries;
std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions;
std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
boost::asio::deadline_timer * m_SubscriptionsUpdateTimer;
bool m_IsEnabled;
};
virtual void ResetEtags() = 0;
};
class AddressBookSubscription
{
public:
class AddressBookSubscription;
AddressBookSubscription (AddressBook& book, const std::string& link);
void CheckUpdates ();
class AddressResolver;
private:
class AddressBook {
public:
bool MakeRequest ();
AddressBook();
private:
~AddressBook();
AddressBook& m_Book;
std::string m_Link, m_Etag, m_LastModified;
i2p::data::IdentHash m_Ident;
// m_Etag must be surrounded by ""
};
void Start();
class AddressResolver
{
public:
void StartResolvers();
AddressResolver (std::shared_ptr<ClientDestination> destination);
~AddressResolver ();
void AddAddress (const std::string& name, const i2p::data::IdentHash& ident);
void Stop();
private:
std::shared_ptr<const Address> GetAddress(const std::string &address);
void HandleRequest (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
std::shared_ptr<const i2p::data::IdentityEx> GetFullAddress(const std::string &address);
private:
std::shared_ptr<const Address> FindAddress(const std::string &address);
std::shared_ptr<ClientDestination> m_LocalDestination;
std::map<std::string, i2p::data::IdentHash> m_LocalAddresses;
};
}
void LookupAddress(const std::string &address);
void InsertAddress(const std::string &address, const std::string &jump); // for jump links
void InsertFullAddress(std::shared_ptr<const i2p::data::IdentityEx> address);
bool LoadHostsFromStream(std::istream &f, bool is_update);
void DownloadComplete(bool success, const i2p::data::IdentHash &subscription, const std::string &etag,
const std::string &lastModified);
//This method returns the ".b32.i2p" address
std::string ToAddress(const i2p::data::IdentHash &ident) { return GetB32Address(ident); }
std::string ToAddress(std::shared_ptr<const i2p::data::IdentityEx> ident) {
return ToAddress(ident->GetIdentHash());
}
bool GetEtag(const i2p::data::IdentHash &subscription, std::string &etag, std::string &lastModified);
private:
void StartSubscriptions();
void StopSubscriptions();
void LoadHosts();
void LoadSubscriptions();
void LoadLocal();
void HandleSubscriptionsUpdateTimer(const boost::system::error_code &ecode);
void StartLookups();
void StopLookups();
void HandleLookupResponse(const i2p::data::IdentityEx &from, uint16_t fromPort, uint16_t toPort,
const uint8_t *buf, size_t len);
private:
std::mutex m_AddressBookMutex;
std::map <std::string, std::shared_ptr<Address>> m_Addresses;
std::map <i2p::data::IdentHash, std::shared_ptr<AddressResolver>> m_Resolvers; // local destination->resolver
std::mutex m_LookupsMutex;
std::map <uint32_t, std::string> m_Lookups; // nonce -> address
AddressBookStorage *m_Storage;
volatile bool m_IsLoaded, m_IsDownloading;
int m_NumRetries;
std::vector <std::shared_ptr<AddressBookSubscription>> m_Subscriptions;
std::shared_ptr <AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
boost::asio::deadline_timer *m_SubscriptionsUpdateTimer;
bool m_IsEnabled;
};
class AddressBookSubscription {
public:
AddressBookSubscription(AddressBook &book, const std::string &link);
void CheckUpdates();
private:
bool MakeRequest();
private:
AddressBook &m_Book;
std::string m_Link, m_Etag, m_LastModified;
i2p::data::IdentHash m_Ident;
// m_Etag must be surrounded by ""
};
class AddressResolver {
public:
AddressResolver(std::shared_ptr <ClientDestination> destination);
~AddressResolver();
void AddAddress(const std::string &name, const i2p::data::IdentHash &ident);
private:
void
HandleRequest(const i2p::data::IdentityEx &from, uint16_t fromPort, uint16_t toPort, const uint8_t *buf,
size_t len);
private:
std::shared_ptr <ClientDestination> m_LocalDestination;
std::map <std::string, i2p::data::IdentHash> m_LocalAddresses;
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -21,263 +21,326 @@
#include "Identity.h"
#include "LeaseSet.h"
namespace i2p
{
namespace client
{
const size_t BOB_COMMAND_BUFFER_SIZE = 1024;
const char BOB_COMMAND_ZAP[] = "zap";
const char BOB_COMMAND_QUIT[] = "quit";
const char BOB_COMMAND_START[] = "start";
const char BOB_COMMAND_STOP[] = "stop";
const char BOB_COMMAND_SETNICK[] = "setnick";
const char BOB_COMMAND_GETNICK[] = "getnick";
const char BOB_COMMAND_NEWKEYS[] = "newkeys";
const char BOB_COMMAND_GETKEYS[] = "getkeys";
const char BOB_COMMAND_SETKEYS[] = "setkeys";
const char BOB_COMMAND_GETDEST[] = "getdest";
const char BOB_COMMAND_OUTHOST[] = "outhost";
const char BOB_COMMAND_OUTPORT[] = "outport";
const char BOB_COMMAND_INHOST[] = "inhost";
const char BOB_COMMAND_INPORT[] = "inport";
const char BOB_COMMAND_QUIET[] = "quiet";
const char BOB_COMMAND_LOOKUP[] = "lookup";
const char BOB_COMMAND_LOOKUP_LOCAL[] = "lookuplocal";
const char BOB_COMMAND_CLEAR[] = "clear";
const char BOB_COMMAND_LIST[] = "list";
const char BOB_COMMAND_OPTION[] = "option";
const char BOB_COMMAND_STATUS[] = "status";
const char BOB_COMMAND_HELP[] = "help";
namespace i2p {
namespace client {
const size_t BOB_COMMAND_BUFFER_SIZE = 1024;
const char BOB_COMMAND_ZAP[] = "zap";
const char BOB_COMMAND_QUIT[] = "quit";
const char BOB_COMMAND_START[] = "start";
const char BOB_COMMAND_STOP[] = "stop";
const char BOB_COMMAND_SETNICK[] = "setnick";
const char BOB_COMMAND_GETNICK[] = "getnick";
const char BOB_COMMAND_NEWKEYS[] = "newkeys";
const char BOB_COMMAND_GETKEYS[] = "getkeys";
const char BOB_COMMAND_SETKEYS[] = "setkeys";
const char BOB_COMMAND_GETDEST[] = "getdest";
const char BOB_COMMAND_OUTHOST[] = "outhost";
const char BOB_COMMAND_OUTPORT[] = "outport";
const char BOB_COMMAND_INHOST[] = "inhost";
const char BOB_COMMAND_INPORT[] = "inport";
const char BOB_COMMAND_QUIET[] = "quiet";
const char BOB_COMMAND_LOOKUP[] = "lookup";
const char BOB_COMMAND_LOOKUP_LOCAL[] = "lookuplocal";
const char BOB_COMMAND_CLEAR[] = "clear";
const char BOB_COMMAND_LIST[] = "list";
const char BOB_COMMAND_OPTION[] = "option";
const char BOB_COMMAND_STATUS[] = "status";
const char BOB_COMMAND_HELP[] = "help";
const char BOB_HELP_ZAP[] = "zap - Shuts down BOB.";
const char BOB_HELP_QUIT[] = "quit - Quits this session with BOB.";
const char BOB_HELP_START[] = "start - Starts the current nicknamed tunnel.";
const char BOB_HELP_STOP[] = "stop - Stops the current nicknamed tunnel.";
const char BOB_HELP_SETNICK[] = "setnick <NICKNAME> - Creates a new nickname.";
const char BOB_HELP_GETNICK[] = "getnick <TUNNELNAME> - Sets the nickname from the database.";
const char BOB_HELP_NEWKEYS[] = "newkeys - Generate a new keypair for the current nickname.";
const char BOB_HELP_GETKEYS[] = "getkeys - Return the keypair for the current nickname.";
const char BOB_HELP_SETKEYS[] = "setkeys <BASE64_KEYPAIR> - Sets the keypair for the current nickname.";
const char BOB_HELP_GETDEST[] = "getdest - Return the destination for the current nickname.";
const char BOB_HELP_OUTHOST[] = "outhost <HOSTNAME|IP> - Set the outhound hostname or IP.";
const char BOB_HELP_OUTPORT[] = "outport <PORT_NUMBER> - Set the outbound port that nickname contacts.";
const char BOB_HELP_INHOST[] = "inhost <HOSTNAME|IP> - Set the inbound hostname or IP.";
const char BOB_HELP_INPORT[] = "inport <PORT_NUMBER> - Set the inbound port number nickname listens on.";
const char BOB_HELP_QUIET[] = "quiet <True|False> - Whether to send the incoming destination.";
const char BOB_HELP_LOOKUP[] = "lookup <I2P_HOSTNAME> - Look up an I2P hostname.";
const char BOB_HELP_CLEAR[] = "clear - Clear the current nickname out of the list.";
const char BOB_HELP_LIST[] = "list - List all tunnels.";
const char BOB_HELP_OPTION[] = "option <KEY>=<VALUE> - Set an option. NOTE: Don't use any spaces.";
const char BOB_HELP_STATUS[] = "status <NICKNAME> - Display status of a nicknamed tunnel.";
const char BOB_HELP_HELP [] = "help <COMMAND> - Get help on a command.";
const char BOB_HELP_ZAP[] = "zap - Shuts down BOB.";
const char BOB_HELP_QUIT[] = "quit - Quits this session with BOB.";
const char BOB_HELP_START[] = "start - Starts the current nicknamed tunnel.";
const char BOB_HELP_STOP[] = "stop - Stops the current nicknamed tunnel.";
const char BOB_HELP_SETNICK[] = "setnick <NICKNAME> - Creates a new nickname.";
const char BOB_HELP_GETNICK[] = "getnick <TUNNELNAME> - Sets the nickname from the database.";
const char BOB_HELP_NEWKEYS[] = "newkeys - Generate a new keypair for the current nickname.";
const char BOB_HELP_GETKEYS[] = "getkeys - Return the keypair for the current nickname.";
const char BOB_HELP_SETKEYS[] = "setkeys <BASE64_KEYPAIR> - Sets the keypair for the current nickname.";
const char BOB_HELP_GETDEST[] = "getdest - Return the destination for the current nickname.";
const char BOB_HELP_OUTHOST[] = "outhost <HOSTNAME|IP> - Set the outhound hostname or IP.";
const char BOB_HELP_OUTPORT[] = "outport <PORT_NUMBER> - Set the outbound port that nickname contacts.";
const char BOB_HELP_INHOST[] = "inhost <HOSTNAME|IP> - Set the inbound hostname or IP.";
const char BOB_HELP_INPORT[] = "inport <PORT_NUMBER> - Set the inbound port number nickname listens on.";
const char BOB_HELP_QUIET[] = "quiet <True|False> - Whether to send the incoming destination.";
const char BOB_HELP_LOOKUP[] = "lookup <I2P_HOSTNAME> - Look up an I2P hostname.";
const char BOB_HELP_CLEAR[] = "clear - Clear the current nickname out of the list.";
const char BOB_HELP_LIST[] = "list - List all tunnels.";
const char BOB_HELP_OPTION[] = "option <KEY>=<VALUE> - Set an option. NOTE: Don't use any spaces.";
const char BOB_HELP_STATUS[] = "status <NICKNAME> - Display status of a nicknamed tunnel.";
const char BOB_HELP_HELP[] = "help <COMMAND> - Get help on a command.";
class BOBI2PTunnel: public I2PService
{
public:
class BOBI2PTunnel : public I2PService {
public:
BOBI2PTunnel (std::shared_ptr<ClientDestination> localDestination):
I2PService (localDestination) {};
BOBI2PTunnel(std::shared_ptr <ClientDestination> localDestination) :
I2PService(localDestination) {};
virtual void Start () {};
virtual void Stop () {};
};
virtual void Start() {};
class BOBI2PInboundTunnel: public BOBI2PTunnel
{
struct AddressReceiver
{
std::shared_ptr<boost::asio::ip::tcp::socket> socket;
char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address
uint8_t * data; // pointer to buffer
size_t dataLen, bufferOffset;
virtual void Stop() {};
};
AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {};
};
class BOBI2PInboundTunnel : public BOBI2PTunnel {
struct AddressReceiver {
std::shared_ptr <boost::asio::ip::tcp::socket> socket;
char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address
uint8_t *data; // pointer to buffer
size_t dataLen, bufferOffset;
public:
AddressReceiver() : data(nullptr), dataLen(0), bufferOffset(0) {};
};
BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr<ClientDestination> localDestination);
~BOBI2PInboundTunnel ();
public:
void Start ();
void Stop ();
BOBI2PInboundTunnel(const boost::asio::ip::tcp::endpoint &ep,
std::shared_ptr <ClientDestination> localDestination);
private:
~BOBI2PInboundTunnel();
void Accept ();
void HandleAccept (const boost::system::error_code& ecode, std::shared_ptr<AddressReceiver> receiver);
void Start();
void ReceiveAddress (std::shared_ptr<AddressReceiver> receiver);
void HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred,
std::shared_ptr<AddressReceiver> receiver);
void Stop();
void HandleDestinationRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, std::shared_ptr<AddressReceiver> receiver);
private:
void CreateConnection (std::shared_ptr<AddressReceiver> receiver, std::shared_ptr<const i2p::data::LeaseSet> leaseSet);
void Accept();
private:
void HandleAccept(const boost::system::error_code &ecode, std::shared_ptr <AddressReceiver> receiver);
boost::asio::ip::tcp::acceptor m_Acceptor;
};
void ReceiveAddress(std::shared_ptr <AddressReceiver> receiver);
class BOBI2POutboundTunnel: public BOBI2PTunnel
{
public:
void HandleReceivedAddress(const boost::system::error_code &ecode, std::size_t bytes_transferred,
std::shared_ptr <AddressReceiver> receiver);
BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr<ClientDestination> localDestination, bool quiet);
void HandleDestinationRequestComplete(std::shared_ptr <i2p::data::LeaseSet> leaseSet,
std::shared_ptr <AddressReceiver> receiver);
void Start ();
void Stop ();
void CreateConnection(std::shared_ptr <AddressReceiver> receiver,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet);
void SetQuiet () { m_IsQuiet = true; };
private:
private:
boost::asio::ip::tcp::acceptor m_Acceptor;
};
void Accept ();
void HandleAccept (std::shared_ptr<i2p::stream::Stream> stream);
class BOBI2POutboundTunnel : public BOBI2PTunnel {
public:
private:
BOBI2POutboundTunnel(const std::string &outhost, int port,
std::shared_ptr <ClientDestination> localDestination, bool quiet);
boost::asio::ip::tcp::endpoint m_Endpoint;
bool m_IsQuiet;
};
void Start();
void Stop();
void SetQuiet() { m_IsQuiet = true; };
private:
void Accept();
void HandleAccept(std::shared_ptr <i2p::stream::Stream> stream);
private:
boost::asio::ip::tcp::endpoint m_Endpoint;
bool m_IsQuiet;
};
class BOBDestination
{
public:
class BOBDestination {
public:
BOBDestination (std::shared_ptr<ClientDestination> localDestination,
const std::string &nickname, const std::string &inhost, const std::string &outhost,
const int inport, const int outport, const bool quiet);
~BOBDestination ();
BOBDestination(std::shared_ptr <ClientDestination> localDestination,
const std::string &nickname, const std::string &inhost, const std::string &outhost,
const int inport, const int outport, const bool quiet);
void Start ();
void Stop ();
void StopTunnels ();
void CreateInboundTunnel (int port, const std::string& inhost);
void CreateOutboundTunnel (const std::string& outhost, int port, bool quiet);
const std::string& GetNickname() const { return m_Nickname; }
const std::string& GetInHost() const { return m_InHost; }
const std::string& GetOutHost() const { return m_OutHost; }
int GetInPort() const { return m_InPort; }
int GetOutPort() const { return m_OutPort; }
bool GetQuiet() const { return m_Quiet; }
bool IsRunning() const { return m_IsRunning; }
const i2p::data::PrivateKeys& GetKeys () const { return m_LocalDestination->GetPrivateKeys (); };
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDestination; };
~BOBDestination();
private:
void Start();
std::shared_ptr<ClientDestination> m_LocalDestination;
BOBI2POutboundTunnel * m_OutboundTunnel;
BOBI2PInboundTunnel * m_InboundTunnel;
void Stop();
std::string m_Nickname;
std::string m_InHost, m_OutHost;
int m_InPort, m_OutPort;
bool m_Quiet;
bool m_IsRunning;
};
void StopTunnels();
class BOBCommandChannel;
class BOBCommandSession: public std::enable_shared_from_this<BOBCommandSession>
{
public:
void CreateInboundTunnel(int port, const std::string &inhost);
BOBCommandSession (BOBCommandChannel& owner);
~BOBCommandSession ();
void Terminate ();
void CreateOutboundTunnel(const std::string &outhost, int port, bool quiet);
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
void SendVersion ();
const std::string &GetNickname() const { return m_Nickname; }
// command handlers
void ZapCommandHandler (const char * operand, size_t len);
void QuitCommandHandler (const char * operand, size_t len);
void StartCommandHandler (const char * operand, size_t len);
void StopCommandHandler (const char * operand, size_t len);
void SetNickCommandHandler (const char * operand, size_t len);
void GetNickCommandHandler (const char * operand, size_t len);
void NewkeysCommandHandler (const char * operand, size_t len);
void SetkeysCommandHandler (const char * operand, size_t len);
void GetkeysCommandHandler (const char * operand, size_t len);
void GetdestCommandHandler (const char * operand, size_t len);
void OuthostCommandHandler (const char * operand, size_t len);
void OutportCommandHandler (const char * operand, size_t len);
void InhostCommandHandler (const char * operand, size_t len);
void InportCommandHandler (const char * operand, size_t len);
void QuietCommandHandler (const char * operand, size_t len);
void LookupCommandHandler (const char * operand, size_t len);
void LookupLocalCommandHandler (const char * operand, size_t len);
void ClearCommandHandler (const char * operand, size_t len);
void ListCommandHandler (const char * operand, size_t len);
void OptionCommandHandler (const char * operand, size_t len);
void StatusCommandHandler (const char * operand, size_t len);
void HelpCommandHandler (const char * operand, size_t len);
const std::string &GetInHost() const { return m_InHost; }
private:
const std::string &GetOutHost() const { return m_OutHost; }
void Receive ();
void HandleReceivedLine(const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
int GetInPort() const { return m_InPort; }
void Send ();
void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void SendReplyOK (const char * msg = nullptr);
void SendReplyError (const char * msg);
void SendRaw (const char * data);
int GetOutPort() const { return m_OutPort; }
void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out);
bool GetQuiet() const { return m_Quiet; }
private:
bool IsRunning() const { return m_IsRunning; }
BOBCommandChannel& m_Owner;
boost::asio::ip::tcp::socket m_Socket;
boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer;
bool m_IsOpen, m_IsQuiet, m_IsActive;
std::string m_Nickname, m_InHost, m_OutHost;
int m_InPort, m_OutPort;
i2p::data::PrivateKeys m_Keys;
std::map<std::string, std::string> m_Options;
BOBDestination * m_CurrentDestination;
};
typedef void (BOBCommandSession::*BOBCommandHandler)(const char * operand, size_t len);
const i2p::data::PrivateKeys &GetKeys() const { return m_LocalDestination->GetPrivateKeys(); };
class BOBCommandChannel: private i2p::util::RunnableService
{
public:
std::shared_ptr <ClientDestination> GetLocalDestination() const { return m_LocalDestination; };
BOBCommandChannel (const std::string& address, int port);
~BOBCommandChannel ();
private:
void Start ();
void Stop ();
std::shared_ptr <ClientDestination> m_LocalDestination;
BOBI2POutboundTunnel *m_OutboundTunnel;
BOBI2PInboundTunnel *m_InboundTunnel;
boost::asio::io_service& GetService () { return GetIOService (); };
void AddDestination (const std::string& name, BOBDestination * dest);
void DeleteDestination (const std::string& name);
BOBDestination * FindDestination (const std::string& name);
std::string m_Nickname;
std::string m_InHost, m_OutHost;
int m_InPort, m_OutPort;
bool m_Quiet;
bool m_IsRunning;
};
private:
class BOBCommandChannel;
void Accept ();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<BOBCommandSession> session);
class BOBCommandSession : public std::enable_shared_from_this<BOBCommandSession> {
public:
private:
BOBCommandSession(BOBCommandChannel &owner);
boost::asio::ip::tcp::acceptor m_Acceptor;
std::map<std::string, BOBDestination *> m_Destinations;
std::map<std::string, BOBCommandHandler> m_CommandHandlers;
std::map<std::string, std::string> m_HelpStrings;
~BOBCommandSession();
public:
void Terminate();
const decltype(m_CommandHandlers)& GetCommandHandlers () const { return m_CommandHandlers; };
const decltype(m_HelpStrings)& GetHelpStrings () const { return m_HelpStrings; };
const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; };
};
}
boost::asio::ip::tcp::socket &GetSocket() { return m_Socket; };
void SendVersion();
// command handlers
void ZapCommandHandler(const char *operand, size_t len);
void QuitCommandHandler(const char *operand, size_t len);
void StartCommandHandler(const char *operand, size_t len);
void StopCommandHandler(const char *operand, size_t len);
void SetNickCommandHandler(const char *operand, size_t len);
void GetNickCommandHandler(const char *operand, size_t len);
void NewkeysCommandHandler(const char *operand, size_t len);
void SetkeysCommandHandler(const char *operand, size_t len);
void GetkeysCommandHandler(const char *operand, size_t len);
void GetdestCommandHandler(const char *operand, size_t len);
void OuthostCommandHandler(const char *operand, size_t len);
void OutportCommandHandler(const char *operand, size_t len);
void InhostCommandHandler(const char *operand, size_t len);
void InportCommandHandler(const char *operand, size_t len);
void QuietCommandHandler(const char *operand, size_t len);
void LookupCommandHandler(const char *operand, size_t len);
void LookupLocalCommandHandler(const char *operand, size_t len);
void ClearCommandHandler(const char *operand, size_t len);
void ListCommandHandler(const char *operand, size_t len);
void OptionCommandHandler(const char *operand, size_t len);
void StatusCommandHandler(const char *operand, size_t len);
void HelpCommandHandler(const char *operand, size_t len);
private:
void Receive();
void HandleReceivedLine(const boost::system::error_code &ecode, std::size_t bytes_transferred);
void HandleReceived(const boost::system::error_code &ecode, std::size_t bytes_transferred);
void Send();
void HandleSent(const boost::system::error_code &ecode, std::size_t bytes_transferred);
void SendReplyOK(const char *msg = nullptr);
void SendReplyError(const char *msg);
void SendRaw(const char *data);
void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out);
private:
BOBCommandChannel &m_Owner;
boost::asio::ip::tcp::socket m_Socket;
boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer;
bool m_IsOpen, m_IsQuiet, m_IsActive;
std::string m_Nickname, m_InHost, m_OutHost;
int m_InPort, m_OutPort;
i2p::data::PrivateKeys m_Keys;
std::map <std::string, std::string> m_Options;
BOBDestination *m_CurrentDestination;
};
typedef void (BOBCommandSession::*BOBCommandHandler)(const char *operand, size_t len);
class BOBCommandChannel : private i2p::util::RunnableService {
public:
BOBCommandChannel(const std::string &address, int port);
~BOBCommandChannel();
void Start();
void Stop();
boost::asio::io_service &GetService() { return GetIOService(); };
void AddDestination(const std::string &name, BOBDestination *dest);
void DeleteDestination(const std::string &name);
BOBDestination *FindDestination(const std::string &name);
private:
void Accept();
void HandleAccept(const boost::system::error_code &ecode, std::shared_ptr <BOBCommandSession> session);
private:
boost::asio::ip::tcp::acceptor m_Acceptor;
std::map<std::string, BOBDestination *> m_Destinations;
std::map <std::string, BOBCommandHandler> m_CommandHandlers;
std::map <std::string, std::string> m_HelpStrings;
public:
const decltype(m_CommandHandlers)
&
GetCommandHandlers() const { return m_CommandHandlers; };
const decltype(m_HelpStrings)
&
GetHelpStrings() const { return m_HelpStrings; };
const decltype(m_Destinations)
&
GetDestinations() const { return m_Destinations; };
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -24,154 +24,197 @@
#include "AddressBook.h"
#include "I18N_langs.h"
namespace i2p
{
namespace client
{
const char I2P_TUNNELS_SECTION_TYPE[] = "type";
const char I2P_TUNNELS_SECTION_TYPE_CLIENT[] = "client";
const char I2P_TUNNELS_SECTION_TYPE_SERVER[] = "server";
const char I2P_TUNNELS_SECTION_TYPE_HTTP[] = "http";
const char I2P_TUNNELS_SECTION_TYPE_IRC[] = "irc";
const char I2P_TUNNELS_SECTION_TYPE_UDPCLIENT[] = "udpclient";
const char I2P_TUNNELS_SECTION_TYPE_UDPSERVER[] = "udpserver";
const char I2P_TUNNELS_SECTION_TYPE_SOCKS[] = "socks";
const char I2P_TUNNELS_SECTION_TYPE_WEBSOCKS[] = "websocks";
const char I2P_TUNNELS_SECTION_TYPE_HTTPPROXY[] = "httpproxy";
const char I2P_CLIENT_TUNNEL_PORT[] = "port";
const char I2P_CLIENT_TUNNEL_ADDRESS[] = "address";
const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination";
const char I2P_CLIENT_TUNNEL_KEYS[] = "keys";
const char I2P_CLIENT_TUNNEL_GZIP[] = "gzip";
const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
const char I2P_CLIENT_TUNNEL_CRYPTO_TYPE[] = "cryptotype";
const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";
const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels";
const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout";
const char I2P_CLIENT_TUNNEL_KEEP_ALIVE_INTERVAL[] = "keepaliveinterval";
const char I2P_SERVER_TUNNEL_HOST[] = "host";
const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
const char I2P_SERVER_TUNNEL_PORT[] = "port";
const char I2P_SERVER_TUNNEL_KEYS[] = "keys";
const char I2P_SERVER_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
const char I2P_SERVER_TUNNEL_INPORT[] = "inport";
const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist";
const char I2P_SERVER_TUNNEL_WHITE_LIST[] = "whitelist";
const char I2P_SERVER_TUNNEL_GZIP[] = "gzip";
const char I2P_SERVER_TUNNEL_WEBIRC_PASSWORD[] = "webircpassword";
const char I2P_SERVER_TUNNEL_ADDRESS[] = "address";
const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal";
namespace i2p {
namespace client {
const char I2P_TUNNELS_SECTION_TYPE[] = "type";
const char I2P_TUNNELS_SECTION_TYPE_CLIENT[] = "client";
const char I2P_TUNNELS_SECTION_TYPE_SERVER[] = "server";
const char I2P_TUNNELS_SECTION_TYPE_HTTP[] = "http";
const char I2P_TUNNELS_SECTION_TYPE_IRC[] = "irc";
const char I2P_TUNNELS_SECTION_TYPE_UDPCLIENT[] = "udpclient";
const char I2P_TUNNELS_SECTION_TYPE_UDPSERVER[] = "udpserver";
const char I2P_TUNNELS_SECTION_TYPE_SOCKS[] = "socks";
const char I2P_TUNNELS_SECTION_TYPE_WEBSOCKS[] = "websocks";
const char I2P_TUNNELS_SECTION_TYPE_HTTPPROXY[] = "httpproxy";
const char I2P_CLIENT_TUNNEL_PORT[] = "port";
const char I2P_CLIENT_TUNNEL_ADDRESS[] = "address";
const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination";
const char I2P_CLIENT_TUNNEL_KEYS[] = "keys";
const char I2P_CLIENT_TUNNEL_GZIP[] = "gzip";
const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
const char I2P_CLIENT_TUNNEL_CRYPTO_TYPE[] = "cryptotype";
const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";
const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels";
const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout";
const char I2P_CLIENT_TUNNEL_KEEP_ALIVE_INTERVAL[] = "keepaliveinterval";
const char I2P_SERVER_TUNNEL_HOST[] = "host";
const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
const char I2P_SERVER_TUNNEL_PORT[] = "port";
const char I2P_SERVER_TUNNEL_KEYS[] = "keys";
const char I2P_SERVER_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
const char I2P_SERVER_TUNNEL_INPORT[] = "inport";
const char I2P_SERVER_TUNNEL_ACCESS_LIST[] = "accesslist";
const char I2P_SERVER_TUNNEL_WHITE_LIST[] = "whitelist";
const char I2P_SERVER_TUNNEL_GZIP[] = "gzip";
const char I2P_SERVER_TUNNEL_WEBIRC_PASSWORD[] = "webircpassword";
const char I2P_SERVER_TUNNEL_ADDRESS[] = "address";
const char I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL[] = "enableuniquelocal";
class ClientContext
{
public:
class ClientContext {
public:
ClientContext ();
~ClientContext ();
ClientContext();
void Start ();
void Stop ();
~ClientContext();
void ReloadConfig ();
void Start();
std::shared_ptr<ClientDestination> GetSharedLocalDestination () const { return m_SharedLocalDestination; };
std::shared_ptr<ClientDestination> CreateNewLocalDestination (bool isPublic = false, // transient
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
const std::map<std::string, std::string> * params = nullptr); // used by SAM only
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
const std::map<std::string, std::string> * params = nullptr);
std::shared_ptr<ClientDestination> CreateNewLocalDestination (boost::asio::io_service& service,
const i2p::data::PrivateKeys& keys, bool isPublic = true,
const std::map<std::string, std::string> * params = nullptr); // same as previous but on external io_service
std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
const std::string & name, const std::map<std::string, std::string> * params = nullptr);
void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
void Stop();
AddressBook& GetAddressBook () { return m_AddressBook; };
const BOBCommandChannel * GetBOBCommandChannel () const { return m_BOBCommandChannel; };
const SAMBridge * GetSAMBridge () const { return m_SamBridge; };
const I2CPServer * GetI2CPServer () const { return m_I2CPServer; };
void ReloadConfig();
std::vector<std::shared_ptr<DatagramSessionInfo> > GetForwardInfosFor(const i2p::data::IdentHash & destination);
std::shared_ptr <ClientDestination> GetSharedLocalDestination() const { return m_SharedLocalDestination; };
// i18n
std::shared_ptr<const i2p::i18n::Locale> GetLanguage () { return m_Language; };
void SetLanguage (const std::shared_ptr<const i2p::i18n::Locale> language) { m_Language = language; };
std::shared_ptr <ClientDestination> CreateNewLocalDestination(bool isPublic = false, // transient
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
const std::map <std::string, std::string> *params = nullptr); // used by SAM only
std::shared_ptr <ClientDestination> CreateNewLocalDestination(boost::asio::io_service &service,
bool isPublic = false,
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
const std::map <std::string, std::string> *params = nullptr); // same as previous but on external io_service
std::shared_ptr <ClientDestination>
CreateNewLocalDestination(const i2p::data::PrivateKeys &keys, bool isPublic = true,
const std::map <std::string, std::string> *params = nullptr);
private:
std::shared_ptr <ClientDestination> CreateNewLocalDestination(boost::asio::io_service &service,
const i2p::data::PrivateKeys &keys,
bool isPublic = true,
const std::map <std::string, std::string> *params = nullptr); // same as previous but on external io_service
std::shared_ptr <ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
const std::string &name,
const std::map <std::string, std::string> *params = nullptr);
void ReadTunnels ();
void ReadTunnels (const std::string& tunConf, int& numClientTunnels, int& numServerTunnels);
void ReadHttpProxy ();
void ReadSocksProxy ();
template<typename Section, typename Type>
std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const;
template<typename Section>
std::string GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const; // GetI2CPOption with string default value
template<typename Section>
void ReadI2CPOptionsGroup (const Section& section, const std::string& group, std::map<std::string, std::string>& options) const;
template<typename Section>
void ReadI2CPOptions (const Section& section, bool isServer, std::map<std::string, std::string>& options) const; // for tunnels
void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const; // for HTTP and SOCKS proxy
void DeleteLocalDestination(std::shared_ptr <ClientDestination> destination);
void CleanupUDP(const boost::system::error_code & ecode);
void ScheduleCleanupUDP();
std::shared_ptr <ClientDestination> FindLocalDestination(const i2p::data::IdentHash &destination) const;
void VisitTunnels (bool clean);
bool LoadPrivateKeys(i2p::data::PrivateKeys &keys, const std::string &filename,
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
void CreateNewSharedLocalDestination ();
void AddLocalDestination (std::shared_ptr<ClientDestination> localDestination);
AddressBook &GetAddressBook() { return m_AddressBook; };
private:
const BOBCommandChannel *GetBOBCommandChannel() const { return m_BOBCommandChannel; };
std::mutex m_DestinationsMutex;
std::map<i2p::data::IdentHash, std::shared_ptr<ClientDestination> > m_Destinations;
std::shared_ptr<ClientDestination> m_SharedLocalDestination;
const SAMBridge *GetSAMBridge() const { return m_SamBridge; };
AddressBook m_AddressBook;
const I2CPServer *GetI2CPServer() const { return m_I2CPServer; };
i2p::proxy::HTTPProxy * m_HttpProxy;
i2p::proxy::SOCKSProxy * m_SocksProxy;
std::map<boost::asio::ip::tcp::endpoint, std::shared_ptr<I2PService> > m_ClientTunnels; // local endpoint -> tunnel
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PServerTunnel> > m_ServerTunnels; // <destination,port> -> tunnel
std::vector <std::shared_ptr<DatagramSessionInfo>>
GetForwardInfosFor(const i2p::data::IdentHash &destination);
std::mutex m_ForwardsMutex;
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<I2PUDPClientTunnel> > m_ClientForwards; // local endpoint -> udp tunnel
std::map<std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PUDPServerTunnel> > m_ServerForwards; // <destination,port> -> udp tunnel
// i18n
std::shared_ptr<const i2p::i18n::Locale> GetLanguage() { return m_Language; };
SAMBridge * m_SamBridge;
BOBCommandChannel * m_BOBCommandChannel;
I2CPServer * m_I2CPServer;
void SetLanguage(const std::shared_ptr<const i2p::i18n::Locale> language) { m_Language = language; };
std::unique_ptr<boost::asio::deadline_timer> m_CleanupUDPTimer;
private:
// i18n
std::shared_ptr<const i2p::i18n::Locale> m_Language;
void ReadTunnels();
public:
void ReadTunnels(const std::string &tunConf, int &numClientTunnels, int &numServerTunnels);
// for HTTP
const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; };
const decltype(m_ClientTunnels)& GetClientTunnels () const { return m_ClientTunnels; };
const decltype(m_ServerTunnels)& GetServerTunnels () const { return m_ServerTunnels; };
const decltype(m_ClientForwards)& GetClientForwards () const { return m_ClientForwards; }
const decltype(m_ServerForwards)& GetServerForwards () const { return m_ServerForwards; }
const i2p::proxy::HTTPProxy * GetHttpProxy () const { return m_HttpProxy; }
const i2p::proxy::SOCKSProxy * GetSocksProxy () const { return m_SocksProxy; }
};
void ReadHttpProxy();
extern ClientContext context;
}
void ReadSocksProxy();
template<typename Section, typename Type>
std::string GetI2CPOption(const Section &section, const std::string &name, const Type &value) const;
template<typename Section>
std::string GetI2CPStringOption(const Section &section, const std::string &name,
const std::string &value) const; // GetI2CPOption with string default value
template<typename Section>
void ReadI2CPOptionsGroup(const Section &section, const std::string &group,
std::map <std::string, std::string> &options) const;
template<typename Section>
void ReadI2CPOptions(const Section &section, bool isServer,
std::map <std::string, std::string> &options) const; // for tunnels
void ReadI2CPOptionsFromConfig(const std::string &prefix,
std::map <std::string, std::string> &options) const; // for HTTP and SOCKS proxy
void CleanupUDP(const boost::system::error_code &ecode);
void ScheduleCleanupUDP();
void VisitTunnels(bool clean);
void CreateNewSharedLocalDestination();
void AddLocalDestination(std::shared_ptr <ClientDestination> localDestination);
private:
std::mutex m_DestinationsMutex;
std::map <i2p::data::IdentHash, std::shared_ptr<ClientDestination>> m_Destinations;
std::shared_ptr <ClientDestination> m_SharedLocalDestination;
AddressBook m_AddressBook;
i2p::proxy::HTTPProxy *m_HttpProxy;
i2p::proxy::SOCKSProxy *m_SocksProxy;
std::map <boost::asio::ip::tcp::endpoint, std::shared_ptr<I2PService>> m_ClientTunnels; // local endpoint -> tunnel
std::map <std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PServerTunnel>> m_ServerTunnels; // <destination,port> -> tunnel
std::mutex m_ForwardsMutex;
std::map <boost::asio::ip::udp::endpoint, std::shared_ptr<I2PUDPClientTunnel>> m_ClientForwards; // local endpoint -> udp tunnel
std::map <std::pair<i2p::data::IdentHash, int>, std::shared_ptr<I2PUDPServerTunnel>> m_ServerForwards; // <destination,port> -> udp tunnel
SAMBridge *m_SamBridge;
BOBCommandChannel *m_BOBCommandChannel;
I2CPServer *m_I2CPServer;
std::unique_ptr <boost::asio::deadline_timer> m_CleanupUDPTimer;
// i18n
std::shared_ptr<const i2p::i18n::Locale> m_Language;
public:
// for HTTP
const decltype(m_Destinations)
&
GetDestinations() const { return m_Destinations; };
const decltype(m_ClientTunnels)
&
GetClientTunnels() const { return m_ClientTunnels; };
const decltype(m_ServerTunnels)
&
GetServerTunnels() const { return m_ServerTunnels; };
const decltype(m_ClientForwards)
&
GetClientForwards() const { return m_ClientForwards; }
const decltype(m_ServerForwards)
&
GetServerForwards() const { return m_ServerForwards; }
const i2p::proxy::HTTPProxy *GetHttpProxy() const { return m_HttpProxy; }
const i2p::proxy::SOCKSProxy *GetSocksProxy() const { return m_SocksProxy; }
};
extern ClientContext context;
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -10,32 +10,38 @@
#define HTTP_PROXY_H__
namespace i2p {
namespace proxy {
class HTTPProxy: public i2p::client::TCPIPAcceptor
{
public:
namespace proxy {
class HTTPProxy : public i2p::client::TCPIPAcceptor {
public:
HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, bool addresshelper, std::shared_ptr<i2p::client::ClientDestination> localDestination);
HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr) :
HTTPProxy(name, address, port, "", true, localDestination) {} ;
~HTTPProxy() {};
HTTPProxy(const std::string &name, const std::string &address, int port, const std::string &outproxy,
bool addresshelper, std::shared_ptr <i2p::client::ClientDestination> localDestination);
std::string GetOutproxyURL() const { return m_OutproxyUrl; }
bool GetHelperSupport() { return m_Addresshelper; }
HTTPProxy(const std::string &name, const std::string &address, int port,
std::shared_ptr <i2p::client::ClientDestination> localDestination = nullptr) :
HTTPProxy(name, address, port, "", true, localDestination) {};
protected:
~HTTPProxy() {};
// Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return m_Name.c_str (); }
std::string GetOutproxyURL() const { return m_OutproxyUrl; }
private:
bool GetHelperSupport() { return m_Addresshelper; }
std::string m_Name;
std::string m_OutproxyUrl;
bool m_Addresshelper;
};
} // http
protected:
// Implements TCPIPAcceptor
std::shared_ptr <i2p::client::I2PServiceHandler>
CreateHandler(std::shared_ptr <boost::asio::ip::tcp::socket> socket);
const char *GetName() { return m_Name.c_str(); }
private:
std::string m_Name;
std::string m_OutproxyUrl;
bool m_Addresshelper;
};
} // http
} // i2p
#endif

File diff suppressed because it is too large Load diff

View file

@ -19,233 +19,281 @@
#include "Destination.h"
#include "Streaming.h"
namespace i2p
{
namespace client
{
const uint8_t I2CP_PROTOCOL_BYTE = 0x2A;
const size_t I2CP_SESSION_BUFFER_SIZE = 4096;
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M
const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds
namespace i2p {
namespace client {
const uint8_t I2CP_PROTOCOL_BYTE = 0x2A;
const size_t I2CP_SESSION_BUFFER_SIZE = 4096;
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024 * 1024; // in bytes, 1M
const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4;
const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1;
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4;
const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1;
const uint8_t I2CP_GET_DATE_MESSAGE = 32;
const uint8_t I2CP_SET_DATE_MESSAGE = 33;
const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1;
const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2;
const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20;
const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3;
const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37;
const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4;
const uint8_t I2CP_CREATE_LEASESET2_MESSAGE = 41;
const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5;
const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36;
const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31;
const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22;
const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38;
const uint8_t I2CP_HOST_REPLY_MESSAGE = 39;
const uint8_t I2CP_DEST_LOOKUP_MESSAGE = 34;
const uint8_t I2CP_DEST_REPLY_MESSAGE = 35;
const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8;
const uint8_t I2CP_BANDWIDTH_LIMITS_MESSAGE = 23;
const uint8_t I2CP_GET_DATE_MESSAGE = 32;
const uint8_t I2CP_SET_DATE_MESSAGE = 33;
const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1;
const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2;
const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20;
const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3;
const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37;
const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4;
const uint8_t I2CP_CREATE_LEASESET2_MESSAGE = 41;
const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5;
const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36;
const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31;
const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22;
const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38;
const uint8_t I2CP_HOST_REPLY_MESSAGE = 39;
const uint8_t I2CP_DEST_LOOKUP_MESSAGE = 34;
const uint8_t I2CP_DEST_REPLY_MESSAGE = 35;
const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8;
const uint8_t I2CP_BANDWIDTH_LIMITS_MESSAGE = 23;
enum I2CPMessageStatus
{
eI2CPMessageStatusAccepted = 1,
eI2CPMessageStatusGuaranteedSuccess = 4,
eI2CPMessageStatusGuaranteedFailure = 5,
eI2CPMessageStatusNoLeaseSet = 21
};
enum I2CPMessageStatus {
eI2CPMessageStatusAccepted = 1,
eI2CPMessageStatusGuaranteedSuccess = 4,
eI2CPMessageStatusGuaranteedFailure = 5,
eI2CPMessageStatusNoLeaseSet = 21
};
enum I2CPSessionStatus
{
eI2CPSessionStatusDestroyed = 0,
eI2CPSessionStatusCreated = 1,
eI2CPSessionStatusUpdated = 2,
eI2CPSessionStatusInvalid = 3,
eI2CPSessionStatusRefused = 4
};
enum I2CPSessionStatus {
eI2CPSessionStatusDestroyed = 0,
eI2CPSessionStatusCreated = 1,
eI2CPSessionStatusUpdated = 2,
eI2CPSessionStatusInvalid = 3,
eI2CPSessionStatusRefused = 4
};
// params
const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability";
// params
const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability";
class I2CPSession;
class I2CPDestination: public LeaseSetDestination
{
public:
class I2CPSession;
I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params);
~I2CPDestination () {};
class I2CPDestination : public LeaseSetDestination {
public:
void Stop ();
I2CPDestination(boost::asio::io_service &service, std::shared_ptr <I2CPSession> owner,
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic,
const std::map <std::string, std::string> &params);
void SetEncryptionPrivateKey (const uint8_t * key);
void SetEncryptionType (i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; };
void SetECIESx25519EncryptionPrivateKey (const uint8_t * key);
void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession
void LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len); // called from I2CPSession
void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession
~I2CPDestination() {};
// implements LocalDestination
bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const;
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const;
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; // for 4 only
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Identity; };
void Stop();
protected:
void SetEncryptionPrivateKey(const uint8_t *key);
// I2CP
void HandleDataMessage (const uint8_t * buf, size_t len);
void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels);
void SetEncryptionType(i2p::data::CryptoKeyType keyType) { m_EncryptionKeyType = keyType; };
private:
void SetECIESx25519EncryptionPrivateKey(const uint8_t *key);
std::shared_ptr<I2CPDestination> GetSharedFromThis ()
{ return std::static_pointer_cast<I2CPDestination>(shared_from_this ()); }
bool SendMsg (std::shared_ptr<I2NPMessage> msg, std::shared_ptr<const i2p::data::LeaseSet> remote);
void LeaseSetCreated(const uint8_t *buf, size_t len); // called from I2CPSession
void LeaseSet2Created(uint8_t storeType, const uint8_t *buf, size_t len); // called from I2CPSession
void SendMsgTo(const uint8_t *payload, size_t len, const i2p::data::IdentHash &ident,
uint32_t nonce); // called from I2CPSession
void PostCreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels);
// implements LocalDestination
bool Decrypt(const uint8_t *encrypted, uint8_t *data, i2p::data::CryptoKeyType preferredCrypto) const;
private:
bool SupportsEncryptionType(i2p::data::CryptoKeyType keyType) const;
std::shared_ptr<I2CPSession> m_Owner;
std::shared_ptr<const i2p::data::IdentityEx> m_Identity;
i2p::data::CryptoKeyType m_EncryptionKeyType;
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor; // standard
std::shared_ptr<i2p::crypto::ECIESX25519AEADRatchetDecryptor> m_ECIESx25519Decryptor;
uint8_t m_ECIESx25519PrivateKey[32];
uint64_t m_LeaseSetExpirationTime;
bool m_IsCreatingLeaseSet;
boost::asio::deadline_timer m_LeaseSetCreationTimer;
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> > m_I2NPMsgsPool;
};
const uint8_t *GetEncryptionPublicKey(i2p::data::CryptoKeyType keyType) const; // for 4 only
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity() const { return m_Identity; };
class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination
{
public:
protected:
RunnableI2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity,
bool isPublic, const std::map<std::string, std::string>& params);
~RunnableI2CPDestination ();
// I2CP
void HandleDataMessage(const uint8_t *buf, size_t len);
void Start ();
void Stop ();
};
void CreateNewLeaseSet(const std::vector <std::shared_ptr<i2p::tunnel::InboundTunnel>> &tunnels);
class I2CPServer;
class I2CPSession: public std::enable_shared_from_this<I2CPSession>
{
public:
private:
I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
std::shared_ptr <I2CPDestination> GetSharedFromThis() {
return std::static_pointer_cast<I2CPDestination>(shared_from_this());
}
~I2CPSession ();
bool SendMsg(std::shared_ptr <I2NPMessage> msg, std::shared_ptr<const i2p::data::LeaseSet> remote);
void Start ();
void Stop ();
uint16_t GetSessionID () const { return m_SessionID; };
std::shared_ptr<const I2CPDestination> GetDestination () const { return m_Destination; };
void PostCreateNewLeaseSet(std::vector <std::shared_ptr<i2p::tunnel::InboundTunnel>> tunnels);
// called from I2CPDestination
void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len);
void SendMessagePayloadMessage (const uint8_t * payload, size_t len);
void SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status);
private:
// message handlers
void GetDateMessageHandler (const uint8_t * buf, size_t len);
void CreateSessionMessageHandler (const uint8_t * buf, size_t len);
void DestroySessionMessageHandler (const uint8_t * buf, size_t len);
void ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len);
void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len);
void CreateLeaseSet2MessageHandler (const uint8_t * buf, size_t len);
void SendMessageMessageHandler (const uint8_t * buf, size_t len);
void SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len);
void HostLookupMessageHandler (const uint8_t * buf, size_t len);
void DestLookupMessageHandler (const uint8_t * buf, size_t len);
void GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len);
std::shared_ptr <I2CPSession> m_Owner;
std::shared_ptr<const i2p::data::IdentityEx> m_Identity;
i2p::data::CryptoKeyType m_EncryptionKeyType;
std::shared_ptr <i2p::crypto::CryptoKeyDecryptor> m_Decryptor; // standard
std::shared_ptr <i2p::crypto::ECIESX25519AEADRatchetDecryptor> m_ECIESx25519Decryptor;
uint8_t m_ECIESx25519PrivateKey[32];
uint64_t m_LeaseSetExpirationTime;
bool m_IsCreatingLeaseSet;
boost::asio::deadline_timer m_LeaseSetCreationTimer;
i2p::util::MemoryPoolMt<I2NPMessageBuffer < I2NP_MAX_MESSAGE_SIZE> >
m_I2NPMsgsPool;
};
private:
class RunnableI2CPDestination : private i2p::util::RunnableService, public I2CPDestination {
public:
void ReadProtocolByte ();
void ReceiveHeader ();
void HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void ReceivePayload ();
void HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleMessage ();
void Terminate ();
RunnableI2CPDestination(std::shared_ptr <I2CPSession> owner,
std::shared_ptr<const i2p::data::IdentityEx> identity,
bool isPublic, const std::map <std::string, std::string> &params);
void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
~RunnableI2CPDestination();
std::string ExtractString (const uint8_t * buf, size_t len);
size_t PutString (uint8_t * buf, size_t len, const std::string& str);
void ExtractMapping (const uint8_t * buf, size_t len, std::map<std::string, std::string>& mapping);
void SendSessionStatusMessage (I2CPSessionStatus status);
void SendHostReplyMessage (uint32_t requestID, std::shared_ptr<const i2p::data::IdentityEx> identity);
void Start();
private:
void Stop();
};
I2CPServer& m_Owner;
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
uint8_t m_Header[I2CP_HEADER_SIZE], m_Payload[I2CP_MAX_MESSAGE_LENGTH];
size_t m_PayloadLen;
class I2CPServer;
std::shared_ptr<I2CPDestination> m_Destination;
uint16_t m_SessionID;
uint32_t m_MessageID;
bool m_IsSendAccepted;
class I2CPSession : public std::enable_shared_from_this<I2CPSession> {
public:
// to client
bool m_IsSending;
uint8_t m_SendBuffer[I2CP_MAX_MESSAGE_LENGTH];
i2p::stream::SendBufferQueue m_SendQueue;
};
typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len);
I2CPSession(I2CPServer &owner, std::shared_ptr <boost::asio::ip::tcp::socket> socket);
class I2CPServer: private i2p::util::RunnableService
{
public:
~I2CPSession();
I2CPServer (const std::string& interface, int port, bool isSingleThread);
~I2CPServer ();
void Start();
void Start ();
void Stop ();
boost::asio::io_service& GetService () { return GetIOService (); };
bool IsSingleThread () const { return m_IsSingleThread; };
void Stop();
bool InsertSession (std::shared_ptr<I2CPSession> session);
void RemoveSession (uint16_t sessionID);
std::shared_ptr<I2CPSession> FindSessionByIdentHash (const i2p::data::IdentHash& ident) const;
uint16_t GetSessionID() const { return m_SessionID; };
private:
std::shared_ptr<const I2CPDestination> GetDestination() const { return m_Destination; };
void Run ();
// called from I2CPDestination
void SendI2CPMessage(uint8_t type, const uint8_t *payload, size_t len);
void Accept ();
void SendMessagePayloadMessage(const uint8_t *payload, size_t len);
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
void SendMessageStatusMessage(uint32_t nonce, I2CPMessageStatus status);
private:
// message handlers
void GetDateMessageHandler(const uint8_t *buf, size_t len);
bool m_IsSingleThread;
I2CPMessageHandler m_MessagesHandlers[256];
std::map<uint16_t, std::shared_ptr<I2CPSession> > m_Sessions;
void CreateSessionMessageHandler(const uint8_t *buf, size_t len);
boost::asio::ip::tcp::acceptor m_Acceptor;
void DestroySessionMessageHandler(const uint8_t *buf, size_t len);
public:
void ReconfigureSessionMessageHandler(const uint8_t *buf, size_t len);
const decltype(m_MessagesHandlers)& GetMessagesHandlers () const { return m_MessagesHandlers; };
void CreateLeaseSetMessageHandler(const uint8_t *buf, size_t len);
// for HTTP
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
};
}
void CreateLeaseSet2MessageHandler(const uint8_t *buf, size_t len);
void SendMessageMessageHandler(const uint8_t *buf, size_t len);
void SendMessageExpiresMessageHandler(const uint8_t *buf, size_t len);
void HostLookupMessageHandler(const uint8_t *buf, size_t len);
void DestLookupMessageHandler(const uint8_t *buf, size_t len);
void GetBandwidthLimitsMessageHandler(const uint8_t *buf, size_t len);
private:
void ReadProtocolByte();
void ReceiveHeader();
void HandleReceivedHeader(const boost::system::error_code &ecode, std::size_t bytes_transferred);
void ReceivePayload();
void HandleReceivedPayload(const boost::system::error_code &ecode, std::size_t bytes_transferred);
void HandleMessage();
void Terminate();
void HandleI2CPMessageSent(const boost::system::error_code &ecode, std::size_t bytes_transferred);
std::string ExtractString(const uint8_t *buf, size_t len);
size_t PutString(uint8_t *buf, size_t len, const std::string &str);
void ExtractMapping(const uint8_t *buf, size_t len, std::map <std::string, std::string> &mapping);
void SendSessionStatusMessage(I2CPSessionStatus status);
void SendHostReplyMessage(uint32_t requestID, std::shared_ptr<const i2p::data::IdentityEx> identity);
private:
I2CPServer &m_Owner;
std::shared_ptr <boost::asio::ip::tcp::socket> m_Socket;
uint8_t m_Header[I2CP_HEADER_SIZE], m_Payload[I2CP_MAX_MESSAGE_LENGTH];
size_t m_PayloadLen;
std::shared_ptr <I2CPDestination> m_Destination;
uint16_t m_SessionID;
uint32_t m_MessageID;
bool m_IsSendAccepted;
// to client
bool m_IsSending;
uint8_t m_SendBuffer[I2CP_MAX_MESSAGE_LENGTH];
i2p::stream::SendBufferQueue m_SendQueue;
};
typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t *buf, size_t len);
class I2CPServer : private i2p::util::RunnableService {
public:
I2CPServer(const std::string &interface, int port, bool isSingleThread);
~I2CPServer();
void Start();
void Stop();
boost::asio::io_service &GetService() { return GetIOService(); };
bool IsSingleThread() const { return m_IsSingleThread; };
bool InsertSession(std::shared_ptr <I2CPSession> session);
void RemoveSession(uint16_t sessionID);
std::shared_ptr <I2CPSession> FindSessionByIdentHash(const i2p::data::IdentHash &ident) const;
private:
void Run();
void Accept();
void
HandleAccept(const boost::system::error_code &ecode, std::shared_ptr <boost::asio::ip::tcp::socket> socket);
private:
bool m_IsSingleThread;
I2CPMessageHandler m_MessagesHandlers[256];
std::map <uint16_t, std::shared_ptr<I2CPSession>> m_Sessions;
boost::asio::ip::tcp::acceptor m_Acceptor;
public:
const decltype(m_MessagesHandlers)
&
GetMessagesHandlers() const { return m_MessagesHandlers; };
// for HTTP
const decltype(m_Sessions)
&
GetSessions() const { return m_Sessions; };
};
}
}
#endif

View file

@ -12,331 +12,280 @@
#include "I2PService.h"
#include <boost/asio/error.hpp>
namespace i2p
{
namespace client
{
static const i2p::data::SigningKeyType I2P_SERVICE_DEFAULT_KEY_TYPE = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519;
namespace i2p {
namespace client {
static const i2p::data::SigningKeyType I2P_SERVICE_DEFAULT_KEY_TYPE = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519;
I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination):
m_LocalDestination (localDestination ? localDestination :
i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ReadyTimerTriggered(false),
m_ConnectTimeout(0),
isUpdated (true)
{
m_LocalDestination->Acquire ();
}
I2PService::I2PService(std::shared_ptr <ClientDestination> localDestination) :
m_LocalDestination(localDestination ? localDestination :
i2p::client::context.CreateNewLocalDestination(false, I2P_SERVICE_DEFAULT_KEY_TYPE)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ReadyTimerTriggered(false),
m_ConnectTimeout(0),
isUpdated(true) {
m_LocalDestination->Acquire();
}
I2PService::I2PService (i2p::data::SigningKeyType kt):
m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ConnectTimeout(0),
isUpdated (true)
{
m_LocalDestination->Acquire ();
}
I2PService::I2PService(i2p::data::SigningKeyType kt) :
m_LocalDestination(i2p::client::context.CreateNewLocalDestination(false, kt)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ConnectTimeout(0),
isUpdated(true) {
m_LocalDestination->Acquire();
}
I2PService::~I2PService ()
{
ClearHandlers ();
if (m_LocalDestination) m_LocalDestination->Release ();
}
I2PService::~I2PService() {
ClearHandlers();
if (m_LocalDestination) m_LocalDestination->Release();
}
void I2PService::ClearHandlers ()
{
if(m_ConnectTimeout)
m_ReadyTimer.cancel();
std::unique_lock<std::mutex> l(m_HandlersMutex);
for (auto it: m_Handlers)
it->Terminate ();
m_Handlers.clear();
}
void I2PService::ClearHandlers() {
if (m_ConnectTimeout)
m_ReadyTimer.cancel();
std::unique_lock <std::mutex> l(m_HandlersMutex);
for (auto it: m_Handlers)
it->Terminate();
m_Handlers.clear();
}
void I2PService::SetConnectTimeout(uint32_t timeout)
{
m_ConnectTimeout = timeout;
}
void I2PService::SetConnectTimeout(uint32_t timeout) {
m_ConnectTimeout = timeout;
}
void I2PService::AddReadyCallback(ReadyCallback cb)
{
uint32_t now = i2p::util::GetSecondsSinceEpoch();
uint32_t tm = (m_ConnectTimeout) ? now + m_ConnectTimeout : NEVER_TIMES_OUT;
void I2PService::AddReadyCallback(ReadyCallback cb) {
uint32_t now = i2p::util::GetSecondsSinceEpoch();
uint32_t tm = (m_ConnectTimeout) ? now + m_ConnectTimeout : NEVER_TIMES_OUT;
LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now);
m_ReadyCallbacks.push_back({cb, tm});
if (!m_ReadyTimerTriggered) TriggerReadyCheckTimer();
}
LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now);
m_ReadyCallbacks.push_back({cb, tm});
if (!m_ReadyTimerTriggered) TriggerReadyCheckTimer();
}
void I2PService::TriggerReadyCheckTimer()
{
m_ReadyTimer.expires_from_now(boost::posix_time::seconds (1));
m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, shared_from_this (), std::placeholders::_1));
m_ReadyTimerTriggered = true;
void I2PService::TriggerReadyCheckTimer() {
m_ReadyTimer.expires_from_now(boost::posix_time::seconds(1));
m_ReadyTimer.async_wait(
std::bind(&I2PService::HandleReadyCheckTimer, shared_from_this(), std::placeholders::_1));
m_ReadyTimerTriggered = true;
}
}
void I2PService::HandleReadyCheckTimer(const boost::system::error_code &ec)
{
if(ec || m_LocalDestination->IsReady())
{
for(auto & itr : m_ReadyCallbacks)
itr.first(ec);
m_ReadyCallbacks.clear();
}
else if(!m_LocalDestination->IsReady())
{
// expire timed out requests
uint32_t now = i2p::util::GetSecondsSinceEpoch ();
auto itr = m_ReadyCallbacks.begin();
while(itr != m_ReadyCallbacks.end())
{
if(itr->second != NEVER_TIMES_OUT && now >= itr->second)
{
itr->first(boost::asio::error::timed_out);
itr = m_ReadyCallbacks.erase(itr);
}
else
++itr;
}
}
if(!ec && m_ReadyCallbacks.size())
TriggerReadyCheckTimer();
else
m_ReadyTimerTriggered = false;
}
void I2PService::HandleReadyCheckTimer(const boost::system::error_code &ec) {
if (ec || m_LocalDestination->IsReady()) {
for (auto &itr: m_ReadyCallbacks)
itr.first(ec);
m_ReadyCallbacks.clear();
} else if (!m_LocalDestination->IsReady()) {
// expire timed out requests
uint32_t now = i2p::util::GetSecondsSinceEpoch();
auto itr = m_ReadyCallbacks.begin();
while (itr != m_ReadyCallbacks.end()) {
if (itr->second != NEVER_TIMES_OUT && now >= itr->second) {
itr->first(boost::asio::error::timed_out);
itr = m_ReadyCallbacks.erase(itr);
} else
++itr;
}
}
if (!ec && m_ReadyCallbacks.size())
TriggerReadyCheckTimer();
else
m_ReadyTimerTriggered = false;
}
void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) {
assert(streamRequestComplete);
auto address = i2p::client::context.GetAddressBook ().GetAddress (dest);
if (address)
CreateStream(streamRequestComplete, address, port);
else
{
LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest);
streamRequestComplete (nullptr);
}
}
void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, const std::string &dest, int port) {
assert(streamRequestComplete);
auto address = i2p::client::context.GetAddressBook().GetAddress(dest);
if (address)
CreateStream(streamRequestComplete, address, port);
else {
LogPrint(eLogWarning, "I2PService: Remote destination not found: ", dest);
streamRequestComplete(nullptr);
}
}
void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, std::shared_ptr<const Address> address, int port)
{
if(m_ConnectTimeout && !m_LocalDestination->IsReady())
{
AddReadyCallback([this, streamRequestComplete, address, port] (const boost::system::error_code & ec)
{
if(ec)
{
LogPrint(eLogWarning, "I2PService::CreateStream() ", ec.message());
streamRequestComplete(nullptr);
}
else
{
if (address->IsIdentHash ())
this->m_LocalDestination->CreateStream(streamRequestComplete, address->identHash, port);
else
this->m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port);
}
});
}
else
{
if (address->IsIdentHash ())
m_LocalDestination->CreateStream (streamRequestComplete, address->identHash, port);
else
m_LocalDestination->CreateStream (streamRequestComplete, address->blindedPublicKey, port);
}
}
void
I2PService::CreateStream(StreamRequestComplete streamRequestComplete, std::shared_ptr<const Address> address,
int port) {
if (m_ConnectTimeout && !m_LocalDestination->IsReady()) {
AddReadyCallback([this, streamRequestComplete, address, port](const boost::system::error_code &ec) {
if (ec) {
LogPrint(eLogWarning, "I2PService::CreateStream() ", ec.message());
streamRequestComplete(nullptr);
} else {
if (address->IsIdentHash())
this->m_LocalDestination->CreateStream(streamRequestComplete, address->identHash, port);
else
this->m_LocalDestination->CreateStream(streamRequestComplete, address->blindedPublicKey,
port);
}
});
} else {
if (address->IsIdentHash())
m_LocalDestination->CreateStream(streamRequestComplete, address->identHash, port);
else
m_LocalDestination->CreateStream(streamRequestComplete, address->blindedPublicKey, port);
}
}
TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream)
{
boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE);
upstream->set_option(option);
downstream->set_option(option);
}
TCPIPPipe::TCPIPPipe(I2PService *owner, std::shared_ptr <boost::asio::ip::tcp::socket> upstream,
std::shared_ptr <boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner),
m_up(upstream),
m_down(downstream) {
boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE);
upstream->set_option(option);
downstream->set_option(option);
}
TCPIPPipe::~TCPIPPipe()
{
Terminate();
}
TCPIPPipe::~TCPIPPipe() {
Terminate();
}
void TCPIPPipe::Start()
{
AsyncReceiveUpstream();
AsyncReceiveDownstream();
}
void TCPIPPipe::Start() {
AsyncReceiveUpstream();
AsyncReceiveDownstream();
}
void TCPIPPipe::Terminate()
{
if(Kill()) return;
if (m_up)
{
if (m_up->is_open())
m_up->close();
m_up = nullptr;
}
if (m_down)
{
if (m_down->is_open())
m_down->close();
m_down = nullptr;
}
Done(shared_from_this());
}
void TCPIPPipe::Terminate() {
if (Kill()) return;
if (m_up) {
if (m_up->is_open())
m_up->close();
m_up = nullptr;
}
if (m_down) {
if (m_down->is_open())
m_down->close();
m_down = nullptr;
}
Done(shared_from_this());
}
void TCPIPPipe::AsyncReceiveUpstream()
{
if (m_up)
{
m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
else
LogPrint(eLogError, "TCPIPPipe: Upstream receive: No socket");
}
void TCPIPPipe::AsyncReceiveUpstream() {
if (m_up) {
m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
} else
LogPrint(eLogError, "TCPIPPipe: Upstream receive: No socket");
}
void TCPIPPipe::AsyncReceiveDownstream()
{
if (m_down) {
m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
else
LogPrint(eLogError, "TCPIPPipe: Downstream receive: No socket");
}
void TCPIPPipe::AsyncReceiveDownstream() {
if (m_down) {
m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
} else
LogPrint(eLogError, "TCPIPPipe: Downstream receive: No socket");
}
void TCPIPPipe::UpstreamWrite(size_t len)
{
if (m_up)
{
LogPrint(eLogDebug, "TCPIPPipe: Upstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleUpstreamWrite,
shared_from_this(),
std::placeholders::_1));
}
else
LogPrint(eLogError, "TCPIPPipe: Upstream write: no socket");
}
void TCPIPPipe::UpstreamWrite(size_t len) {
if (m_up) {
LogPrint(eLogDebug, "TCPIPPipe: Upstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleUpstreamWrite,
shared_from_this(),
std::placeholders::_1));
} else
LogPrint(eLogError, "TCPIPPipe: Upstream write: no socket");
}
void TCPIPPipe::DownstreamWrite(size_t len)
{
if (m_down)
{
LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleDownstreamWrite,
shared_from_this(),
std::placeholders::_1));
}
else
LogPrint(eLogError, "TCPIPPipe: Downstream write: No socket");
}
void TCPIPPipe::DownstreamWrite(size_t len) {
if (m_down) {
LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleDownstreamWrite,
shared_from_this(),
std::placeholders::_1));
} else
LogPrint(eLogError, "TCPIPPipe: Downstream write: No socket");
}
void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
{
LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received");
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: Downstream read error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
if (bytes_transfered > 0 )
memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered);
UpstreamWrite(bytes_transfered);
}
}
void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code &ecode, std::size_t bytes_transfered) {
LogPrint(eLogDebug, "TCPIPPipe: Downstream: ", (int) bytes_transfered, " bytes received");
if (ecode) {
LogPrint(eLogError, "TCPIPPipe: Downstream read error:", ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
if (bytes_transfered > 0)
memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered);
UpstreamWrite(bytes_transfered);
}
}
void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: Downstream write error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
}
else
AsyncReceiveUpstream();
}
void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code &ecode) {
if (ecode) {
LogPrint(eLogError, "TCPIPPipe: Downstream write error:", ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else
AsyncReceiveUpstream();
}
void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: Upstream write error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
}
else
AsyncReceiveDownstream();
}
void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code &ecode) {
if (ecode) {
LogPrint(eLogError, "TCPIPPipe: Upstream write error:", ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else
AsyncReceiveDownstream();
}
void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
{
LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int)bytes_transfered, " bytes received");
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: Upstream read error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
if (bytes_transfered > 0 )
memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered);
DownstreamWrite(bytes_transfered);
}
}
void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code &ecode, std::size_t bytes_transfered) {
LogPrint(eLogDebug, "TCPIPPipe: Upstream ", (int) bytes_transfered, " bytes received");
if (ecode) {
LogPrint(eLogError, "TCPIPPipe: Upstream read error:", ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
if (bytes_transfered > 0)
memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered);
DownstreamWrite(bytes_transfered);
}
}
void TCPIPAcceptor::Start ()
{
m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint));
// update the local end point in case port has been set zero and got updated now
m_LocalEndpoint = m_Acceptor->local_endpoint();
m_Acceptor->listen ();
Accept ();
}
void TCPIPAcceptor::Start() {
m_Acceptor.reset(new boost::asio::ip::tcp::acceptor(GetService(), m_LocalEndpoint));
// update the local end point in case port has been set zero and got updated now
m_LocalEndpoint = m_Acceptor->local_endpoint();
m_Acceptor->listen();
Accept();
}
void TCPIPAcceptor::Stop ()
{
if (m_Acceptor)
{
m_Acceptor->close();
m_Acceptor.reset (nullptr);
}
m_Timer.cancel ();
ClearHandlers();
}
void TCPIPAcceptor::Stop() {
if (m_Acceptor) {
m_Acceptor->close();
m_Acceptor.reset(nullptr);
}
m_Timer.cancel();
ClearHandlers();
}
void TCPIPAcceptor::Accept ()
{
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (GetService ());
m_Acceptor->async_accept (*newSocket, std::bind (&TCPIPAcceptor::HandleAccept, this,
std::placeholders::_1, newSocket));
}
void TCPIPAcceptor::Accept() {
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket>(GetService());
m_Acceptor->async_accept(*newSocket, std::bind(&TCPIPAcceptor::HandleAccept, this,
std::placeholders::_1, newSocket));
}
void TCPIPAcceptor::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket)
{
if (!ecode)
{
LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted");
auto handler = CreateHandler(socket);
if (handler)
{
AddHandler(handler);
handler->Handle();
}
else
socket->close();
Accept();
}
else
{
if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
}
}
}
void TCPIPAcceptor::HandleAccept(const boost::system::error_code &ecode,
std::shared_ptr <boost::asio::ip::tcp::socket> socket) {
if (!ecode) {
LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted");
auto handler = CreateHandler(socket);
if (handler) {
AddHandler(handler);
handler->Handle();
} else
socket->close();
Accept();
} else {
if (ecode != boost::asio::error::operation_aborted)
LogPrint(eLogError, "I2PService: ", GetName(), " closing socket on accept because: ",
ecode.message());
}
}
}
}

View file

@ -18,174 +18,202 @@
#include "Identity.h"
#include "AddressBook.h"
namespace i2p
{
namespace client
{
class I2PServiceHandler;
class I2PService : public std::enable_shared_from_this<I2PService>
{
public:
namespace i2p {
namespace client {
class I2PServiceHandler;
typedef std::function<void(const boost::system::error_code &)> ReadyCallback;
class I2PService : public std::enable_shared_from_this<I2PService> {
public:
public:
typedef std::function<void(const boost::system::error_code &)> ReadyCallback;
I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr);
I2PService (i2p::data::SigningKeyType kt);
virtual ~I2PService ();
public:
inline void AddHandler (std::shared_ptr<I2PServiceHandler> conn)
{
std::unique_lock<std::mutex> l(m_HandlersMutex);
m_Handlers.insert(conn);
}
inline void RemoveHandler (std::shared_ptr<I2PServiceHandler> conn)
{
std::unique_lock<std::mutex> l(m_HandlersMutex);
m_Handlers.erase(conn);
}
void ClearHandlers ();
I2PService(std::shared_ptr <ClientDestination> localDestination = nullptr);
void SetConnectTimeout(uint32_t timeout);
I2PService(i2p::data::SigningKeyType kt);
void AddReadyCallback(ReadyCallback cb);
virtual ~I2PService();
inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; }
inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; }
inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest)
{
if (m_LocalDestination) m_LocalDestination->Release ();
if (dest) dest->Acquire ();
m_LocalDestination = dest;
}
void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0);
void CreateStream(StreamRequestComplete complete, std::shared_ptr<const Address> address, int port);
inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); }
inline void AddHandler(std::shared_ptr <I2PServiceHandler> conn) {
std::unique_lock <std::mutex> l(m_HandlersMutex);
m_Handlers.insert(conn);
}
virtual void Start () = 0;
virtual void Stop () = 0;
inline void RemoveHandler(std::shared_ptr <I2PServiceHandler> conn) {
std::unique_lock <std::mutex> l(m_HandlersMutex);
m_Handlers.erase(conn);
}
virtual const char* GetName() { return "Generic I2P Service"; }
void ClearHandlers();
private:
void SetConnectTimeout(uint32_t timeout);
void TriggerReadyCheckTimer();
void HandleReadyCheckTimer(const boost::system::error_code & ec);
void AddReadyCallback(ReadyCallback cb);
private:
inline std::shared_ptr <ClientDestination> GetLocalDestination() { return m_LocalDestination; }
std::shared_ptr<ClientDestination> m_LocalDestination;
std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers;
std::mutex m_HandlersMutex;
std::vector<std::pair<ReadyCallback, uint32_t> > m_ReadyCallbacks;
boost::asio::deadline_timer m_ReadyTimer;
bool m_ReadyTimerTriggered;
uint32_t m_ConnectTimeout;
inline std::shared_ptr<const ClientDestination> GetLocalDestination() const { return m_LocalDestination; }
const size_t NEVER_TIMES_OUT = 0;
inline void SetLocalDestination(std::shared_ptr <ClientDestination> dest) {
if (m_LocalDestination) m_LocalDestination->Release();
if (dest) dest->Acquire();
m_LocalDestination = dest;
}
public:
void CreateStream(StreamRequestComplete streamRequestComplete, const std::string &dest, int port = 0);
bool isUpdated; // transient, used during reload only
};
void CreateStream(StreamRequestComplete complete, std::shared_ptr<const Address> address, int port);
/*Simple interface for I2PHandlers, allows detection of finalization amongst other things */
class I2PServiceHandler
{
public:
inline boost::asio::io_service &GetService() { return m_LocalDestination->GetService(); }
I2PServiceHandler(I2PService * parent) : m_Service(parent), m_Dead(false) { }
virtual ~I2PServiceHandler() { }
//If you override this make sure you call it from the children
virtual void Handle() {}; //Start handling the socket
virtual void Start() = 0;
void Terminate () { Kill (); };
virtual void Stop() = 0;
protected:
virtual const char *GetName() { return "Generic I2P Service"; }
// Call when terminating or handing over to avoid race conditions
inline bool Kill () { return m_Dead.exchange(true); }
// Call to know if the handler is dead
inline bool Dead () { return m_Dead; }
// Call when done to clean up (make sure Kill is called first)
inline void Done (std::shared_ptr<I2PServiceHandler> me) { if(m_Service) m_Service->RemoveHandler(me); }
// Call to talk with the owner
inline I2PService * GetOwner() { return m_Service; }
private:
private:
void TriggerReadyCheckTimer();
I2PService *m_Service;
std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
};
void HandleReadyCheckTimer(const boost::system::error_code &ec);
const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8;
private:
// bidirectional pipe for 2 tcp/ip sockets
class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe>
{
public:
std::shared_ptr <ClientDestination> m_LocalDestination;
std::unordered_set <std::shared_ptr<I2PServiceHandler>> m_Handlers;
std::mutex m_HandlersMutex;
std::vector <std::pair<ReadyCallback, uint32_t>> m_ReadyCallbacks;
boost::asio::deadline_timer m_ReadyTimer;
bool m_ReadyTimerTriggered;
uint32_t m_ConnectTimeout;
TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream);
~TCPIPPipe();
void Start();
const size_t NEVER_TIMES_OUT = 0;
protected:
public:
void Terminate();
void AsyncReceiveUpstream();
void AsyncReceiveDownstream();
void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void HandleUpstreamWrite(const boost::system::error_code & ecode);
void HandleDownstreamWrite(const boost::system::error_code & ecode);
void UpstreamWrite(size_t len);
void DownstreamWrite(size_t len);
bool isUpdated; // transient, used during reload only
};
private:
/*Simple interface for I2PHandlers, allows detection of finalization amongst other things */
class I2PServiceHandler {
public:
uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down;
};
I2PServiceHandler(I2PService *parent) : m_Service(parent), m_Dead(false) {}
/* TODO: support IPv6 too */
//This is a service that listens for connections on the IP network and interacts with I2P
class TCPIPAcceptor: public I2PService
{
public:
virtual ~I2PServiceHandler() {}
TCPIPAcceptor (const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination = nullptr) :
I2PService(localDestination),
m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
m_Timer (GetService ()) {}
TCPIPAcceptor (const std::string& address, int port, i2p::data::SigningKeyType kt) :
I2PService(kt),
m_LocalEndpoint (boost::asio::ip::address::from_string(address), port),
m_Timer (GetService ()) {}
virtual ~TCPIPAcceptor () { TCPIPAcceptor::Stop(); }
//If you override this make sure you call it from the children
void Start ();
//If you override this make sure you call it from the children
void Stop ();
//If you override this make sure you call it from the children
virtual void Handle() {}; //Start handling the socket
const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
void Terminate() { Kill(); };
virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
protected:
protected:
// Call when terminating or handing over to avoid race conditions
inline bool Kill() { return m_Dead.exchange(true); }
virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0;
// Call to know if the handler is dead
inline bool Dead() { return m_Dead; }
private:
// Call when done to clean up (make sure Kill is called first)
inline void Done(std::shared_ptr <I2PServiceHandler> me) { if (m_Service) m_Service->RemoveHandler(me); }
void Accept();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
boost::asio::ip::tcp::endpoint m_LocalEndpoint;
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_Acceptor;
boost::asio::deadline_timer m_Timer;
};
}
// Call to talk with the owner
inline I2PService *GetOwner() { return m_Service; }
private:
I2PService *m_Service;
std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
};
const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8;
// bidirectional pipe for 2 tcp/ip sockets
class TCPIPPipe : public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe> {
public:
TCPIPPipe(I2PService *owner, std::shared_ptr <boost::asio::ip::tcp::socket> upstream,
std::shared_ptr <boost::asio::ip::tcp::socket> downstream);
~TCPIPPipe();
void Start();
protected:
void Terminate();
void AsyncReceiveUpstream();
void AsyncReceiveDownstream();
void HandleUpstreamReceived(const boost::system::error_code &ecode, std::size_t bytes_transferred);
void HandleDownstreamReceived(const boost::system::error_code &ecode, std::size_t bytes_transferred);
void HandleUpstreamWrite(const boost::system::error_code &ecode);
void HandleDownstreamWrite(const boost::system::error_code &ecode);
void UpstreamWrite(size_t len);
void DownstreamWrite(size_t len);
private:
uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
std::shared_ptr <boost::asio::ip::tcp::socket> m_up, m_down;
};
/* TODO: support IPv6 too */
//This is a service that listens for connections on the IP network and interacts with I2P
class TCPIPAcceptor : public I2PService {
public:
TCPIPAcceptor(const std::string &address, int port,
std::shared_ptr <ClientDestination> localDestination = nullptr) :
I2PService(localDestination),
m_LocalEndpoint(boost::asio::ip::address::from_string(address), port),
m_Timer(GetService()) {}
TCPIPAcceptor(const std::string &address, int port, i2p::data::SigningKeyType kt) :
I2PService(kt),
m_LocalEndpoint(boost::asio::ip::address::from_string(address), port),
m_Timer(GetService()) {}
virtual ~TCPIPAcceptor() { TCPIPAcceptor::Stop(); }
//If you override this make sure you call it from the children
void Start();
//If you override this make sure you call it from the children
void Stop();
const boost::asio::ip::tcp::endpoint &GetLocalEndpoint() const { return m_LocalEndpoint; };
virtual const char *GetName() { return "Generic TCP/IP accepting daemon"; }
protected:
virtual std::shared_ptr <I2PServiceHandler>
CreateHandler(std::shared_ptr <boost::asio::ip::tcp::socket> socket) = 0;
private:
void Accept();
void
HandleAccept(const boost::system::error_code &ecode, std::shared_ptr <boost::asio::ip::tcp::socket> socket);
boost::asio::ip::tcp::endpoint m_LocalEndpoint;
std::unique_ptr <boost::asio::ip::tcp::acceptor> m_Acceptor;
boost::asio::deadline_timer m_Timer;
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -23,390 +23,425 @@
#include "I2PService.h"
#include "AddressBook.h"
namespace i2p
{
namespace client
{
const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 65536;
const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
// for HTTP tunnels
const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64
const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192;
class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
{
public:
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API
I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, bool quiet = true); // from I2P
~I2PTunnelConnection ();
void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0);
void Connect (bool isUniqueLocal = true);
void Connect (const boost::asio::ip::address& localAddress);
namespace i2p {
namespace client {
const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 65536;
const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
// for HTTP tunnels
const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64
const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192;
protected:
class I2PTunnelConnection : public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection> {
public:
void Terminate ();
I2PTunnelConnection(I2PService *owner, std::shared_ptr <boost::asio::ip::tcp::socket> socket,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
I2PTunnelConnection(I2PService *owner, std::shared_ptr <boost::asio::ip::tcp::socket> socket,
std::shared_ptr <i2p::stream::Stream> stream); // to I2P using simplified API
I2PTunnelConnection(I2PService *owner, std::shared_ptr <i2p::stream::Stream> stream,
std::shared_ptr <boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint &target, bool quiet = true); // from I2P
~I2PTunnelConnection();
void Receive ();
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
void HandleWrite (const boost::system::error_code& ecode);
virtual void WriteToStream (const uint8_t * buf, size_t len); // can be overloaded
void I2PConnect(const uint8_t *msg = nullptr, size_t len = 0);
void StreamReceive ();
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleConnect (const boost::system::error_code& ecode);
void Connect(bool isUniqueLocal = true);
std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; };
void Connect(const boost::asio::ip::address &localAddress);
private:
protected:
uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
std::shared_ptr<i2p::stream::Stream> m_Stream;
boost::asio::ip::tcp::endpoint m_RemoteEndpoint;
bool m_IsQuiet; // don't send destination
};
void Terminate();
class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection
{
public:
void Receive();
I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<i2p::stream::Stream> stream):
I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false),
m_ConnectionSent (false), m_ProxyConnectionSent (false) {};
void HandleReceived(const boost::system::error_code &ecode, std::size_t bytes_transferred);
protected:
virtual void Write(const uint8_t *buf, size_t len); // can be overloaded
void HandleWrite(const boost::system::error_code &ecode);
void Write (const uint8_t * buf, size_t len);
virtual void WriteToStream(const uint8_t *buf, size_t len); // can be overloaded
private:
void StreamReceive();
std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
};
void HandleStreamReceive(const boost::system::error_code &ecode, std::size_t bytes_transferred);
class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection
{
public:
void HandleConnect(const boost::system::error_code &ecode);
I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& host);
std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket() const { return m_Socket; };
protected:
private:
void Write (const uint8_t * buf, size_t len);
void WriteToStream (const uint8_t * buf, size_t len);
uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
std::shared_ptr <boost::asio::ip::tcp::socket> m_Socket;
std::shared_ptr <i2p::stream::Stream> m_Stream;
boost::asio::ip::tcp::endpoint m_RemoteEndpoint;
bool m_IsQuiet; // don't send destination
};
private:
class I2PClientTunnelConnectionHTTP : public I2PTunnelConnection {
public:
std::string m_Host;
std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent, m_ResponseHeaderSent;
std::shared_ptr<const i2p::data::IdentityEx> m_From;
};
class I2PTunnelConnectionIRC: public I2PTunnelConnection
{
public:
I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
protected:
void Write (const uint8_t * buf, size_t len);
private:
std::shared_ptr<const i2p::data::IdentityEx> m_From;
std::stringstream m_OutPacket, m_InPacket;
bool m_NeedsWebIrc;
std::string m_WebircPass;
};
I2PClientTunnelConnectionHTTP(I2PService *owner, std::shared_ptr <boost::asio::ip::tcp::socket> socket,
std::shared_ptr <i2p::stream::Stream> stream) :
I2PTunnelConnection(owner, socket, stream), m_HeaderSent(false),
m_ConnectionSent(false), m_ProxyConnectionSent(false) {};
protected:
class I2PClientTunnel: public TCPIPAcceptor
{
protected:
void Write(const uint8_t *buf, size_t len);
// Implements TCPIPAcceptor
std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
private:
public:
std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
};
I2PClientTunnel (const std::string& name, const std::string& destination,
const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0);
~I2PClientTunnel () {}
class I2PServerTunnelConnectionHTTP : public I2PTunnelConnection {
public:
void Start ();
void Stop ();
I2PServerTunnelConnectionHTTP(I2PService *owner, std::shared_ptr <i2p::stream::Stream> stream,
std::shared_ptr <boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint &target, const std::string &host);
const char* GetName() { return m_Name.c_str (); }
void SetKeepAliveInterval (uint32_t keepAliveInterval);
protected:
private:
void Write(const uint8_t *buf, size_t len);
std::shared_ptr<const Address> GetAddress ();
void WriteToStream(const uint8_t *buf, size_t len);
void ScheduleKeepAliveTimer ();
void HandleKeepAliveTimer (const boost::system::error_code& ecode);
private:
private:
std::string m_Host;
std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent, m_ResponseHeaderSent;
std::shared_ptr<const i2p::data::IdentityEx> m_From;
};
std::string m_Name, m_Destination;
std::shared_ptr<const Address> m_Address;
int m_DestinationPort;
uint32_t m_KeepAliveInterval;
std::unique_ptr<boost::asio::deadline_timer> m_KeepAliveTimer;
};
class I2PTunnelConnectionIRC : public I2PTunnelConnection {
public:
I2PTunnelConnectionIRC(I2PService *owner, std::shared_ptr <i2p::stream::Stream> stream,
std::shared_ptr <boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint &target, const std::string &m_WebircPass);
/** 2 minute timeout for udp sessions */
const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2;
const uint64_t I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL = 100; // in milliseconds
protected:
/** max size for i2p udp */
const size_t I2P_UDP_MAX_MTU = 64*1024;
void Write(const uint8_t *buf, size_t len);
struct UDPSession
{
i2p::datagram::DatagramDestination * m_Destination;
boost::asio::ip::udp::socket IPSocket;
i2p::data::IdentHash Identity;
boost::asio::ip::udp::endpoint FromEndpoint;
boost::asio::ip::udp::endpoint SendEndpoint;
uint64_t LastActivity;
private:
uint16_t LocalPort;
uint16_t RemotePort;
uint8_t m_Buffer[I2P_UDP_MAX_MTU];
std::shared_ptr<const i2p::data::IdentityEx> m_From;
std::stringstream m_OutPacket, m_InPacket;
bool m_NeedsWebIrc;
std::string m_WebircPass;
};
UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident,
uint16_t ourPort, uint16_t theirPort);
void HandleReceived(const boost::system::error_code & ecode, std::size_t len);
void Receive();
};
class I2PClientTunnel : public TCPIPAcceptor {
protected:
/** read only info about a datagram session */
struct DatagramSessionInfo
{
/** the name of this forward */
std::string Name;
/** ident hash of local destination */
std::shared_ptr<const i2p::data::IdentHash> LocalIdent;
/** ident hash of remote destination */
std::shared_ptr<const i2p::data::IdentHash> RemoteIdent;
/** ident hash of IBGW in use currently in this session or nullptr if none is set */
std::shared_ptr<const i2p::data::IdentHash> CurrentIBGW;
/** ident hash of OBEP in use for this session or nullptr if none is set */
std::shared_ptr<const i2p::data::IdentHash> CurrentOBEP;
/** i2p router's udp endpoint */
boost::asio::ip::udp::endpoint LocalEndpoint;
/** client's udp endpoint */
boost::asio::ip::udp::endpoint RemoteEndpoint;
/** how long has this converstation been idle in ms */
uint64_t idle;
};
typedef std::shared_ptr<UDPSession> UDPSessionPtr;
/** server side udp tunnel, many i2p inbound to 1 ip outbound */
class I2PUDPServerTunnel
{
public:
I2PUDPServerTunnel (const std::string & name,
std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress,
boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip);
~I2PUDPServerTunnel ();
/** expire stale udp conversations */
void ExpireStale (const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
void Start ();
void Stop ();
const char * GetName () const { return m_Name.c_str(); }
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions ();
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
void SetUniqueLocal (bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
private:
void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
UDPSessionPtr ObtainUDPSession (const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
private:
bool m_IsUniqueLocal;
const std::string m_Name;
boost::asio::ip::address m_LocalAddress;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
std::mutex m_SessionsMutex;
std::vector<UDPSessionPtr> m_Sessions;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
UDPSessionPtr m_LastSession;
bool m_Gzip;
public:
bool isUpdated; // transient, used during reload only
};
class I2PUDPClientTunnel
{
public:
I2PUDPClientTunnel (const std::string & name, const std::string &remoteDest,
boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination,
uint16_t remotePort, bool gzip);
~I2PUDPClientTunnel ();
void Start ();
void Stop ();
const char * GetName () const { return m_Name.c_str(); }
std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions ();
bool IsLocalDestination (const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); }
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest)
{
if (m_LocalDest) m_LocalDest->Release ();
if (dest) dest->Acquire ();
m_LocalDest = dest;
}
void ExpireStale (const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
private:
typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
void RecvFromLocal ();
void HandleRecvFromLocal (const boost::system::error_code & e, std::size_t transferred);
void HandleRecvFromI2P (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void HandleRecvFromI2PRaw (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void TryResolving ();
private:
const std::string m_Name;
std::mutex m_SessionsMutex;
std::unordered_map<uint16_t, std::shared_ptr<UDPConvo> > m_Sessions; // maps i2p port -> local udp convo
const std::string m_RemoteDest;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
const boost::asio::ip::udp::endpoint m_LocalEndpoint;
i2p::data::IdentHash * m_RemoteIdent;
std::thread * m_ResolveThread;
std::unique_ptr<boost::asio::ip::udp::socket> m_LocalSocket;
boost::asio::ip::udp::endpoint m_RecvEndpoint;
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
uint16_t RemotePort, m_LastPort;
bool m_cancel_resolve;
bool m_Gzip;
std::shared_ptr<UDPConvo> m_LastSession;
// Implements TCPIPAcceptor
std::shared_ptr <I2PServiceHandler> CreateHandler(std::shared_ptr <boost::asio::ip::tcp::socket> socket);
public:
public:
bool isUpdated; // transient, used during reload only
};
I2PClientTunnel(const std::string &name, const std::string &destination,
const std::string &address, int port, std::shared_ptr <ClientDestination> localDestination,
int destinationPort = 0);
class I2PServerTunnel: public I2PService
{
public:
~I2PClientTunnel() {}
I2PServerTunnel (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);
void Start();
void Start ();
void Stop ();
void Stop();
void SetAccessList (const std::set<i2p::data::IdentHash>& accessList);
const char *GetName() { return m_Name.c_str(); }
void SetUniqueLocal (bool isUniqueLocal) { m_IsUniqueLocal = isUniqueLocal; }
bool IsUniqueLocal () const { return m_IsUniqueLocal; }
void SetKeepAliveInterval(uint32_t keepAliveInterval);
void SetLocalAddress (const std::string& localAddress);
private:
const std::string& GetAddress() const { return m_Address; }
int GetPort () const { return m_Port; };
uint16_t GetLocalPort () const { return m_PortDestination->GetLocalPort (); };
const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; }
std::shared_ptr<const Address> GetAddress();
const char* GetName() { return m_Name.c_str (); }
void ScheduleKeepAliveTimer();
private:
void HandleKeepAliveTimer(const boost::system::error_code &ecode);
void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
private:
void Accept ();
void HandleAccept (std::shared_ptr<i2p::stream::Stream> stream);
virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
std::string m_Name, m_Destination;
std::shared_ptr<const Address> m_Address;
int m_DestinationPort;
uint32_t m_KeepAliveInterval;
std::unique_ptr <boost::asio::deadline_timer> m_KeepAliveTimer;
};
private:
bool m_IsUniqueLocal;
std::string m_Name, m_Address;
int m_Port;
boost::asio::ip::tcp::endpoint m_Endpoint;
std::shared_ptr<i2p::stream::StreamingDestination> m_PortDestination;
std::set<i2p::data::IdentHash> m_AccessList;
bool m_IsAccessList;
std::unique_ptr<boost::asio::ip::address> m_LocalAddress;
};
/** 2 minute timeout for udp sessions */
const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2;
const uint64_t I2P_UDP_REPLIABLE_DATAGRAM_INTERVAL = 100; // in milliseconds
class I2PServerTunnelHTTP: public I2PServerTunnel
{
public:
/** max size for i2p udp */
const size_t I2P_UDP_MAX_MTU = 64 * 1024;
I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& host,
int inport = 0, bool gzip = true);
struct UDPSession {
i2p::datagram::DatagramDestination *m_Destination;
boost::asio::ip::udp::socket IPSocket;
i2p::data::IdentHash Identity;
boost::asio::ip::udp::endpoint FromEndpoint;
boost::asio::ip::udp::endpoint SendEndpoint;
uint64_t LastActivity;
private:
uint16_t LocalPort;
uint16_t RemotePort;
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
uint8_t m_Buffer[I2P_UDP_MAX_MTU];
private:
UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr <i2p::client::ClientDestination> &localDestination,
boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash *ident,
uint16_t ourPort, uint16_t theirPort);
std::string m_Host;
};
void HandleReceived(const boost::system::error_code &ecode, std::size_t len);
class I2PServerTunnelIRC: public I2PServerTunnel
{
public:
void Receive();
};
I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
int inport = 0, bool gzip = true);
private:
/** read only info about a datagram session */
struct DatagramSessionInfo {
/** the name of this forward */
std::string Name;
/** ident hash of local destination */
std::shared_ptr<const i2p::data::IdentHash> LocalIdent;
/** ident hash of remote destination */
std::shared_ptr<const i2p::data::IdentHash> RemoteIdent;
/** ident hash of IBGW in use currently in this session or nullptr if none is set */
std::shared_ptr<const i2p::data::IdentHash> CurrentIBGW;
/** ident hash of OBEP in use for this session or nullptr if none is set */
std::shared_ptr<const i2p::data::IdentHash> CurrentOBEP;
/** i2p router's udp endpoint */
boost::asio::ip::udp::endpoint LocalEndpoint;
/** client's udp endpoint */
boost::asio::ip::udp::endpoint RemoteEndpoint;
/** how long has this converstation been idle in ms */
uint64_t idle;
};
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
typedef std::shared_ptr <UDPSession> UDPSessionPtr;
private:
/** server side udp tunnel, many i2p inbound to 1 ip outbound */
class I2PUDPServerTunnel {
public:
std::string m_WebircPass;
};
}
I2PUDPServerTunnel(const std::string &name,
std::shared_ptr <i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress,
boost::asio::ip::udp::endpoint forwardTo, uint16_t port, bool gzip);
~I2PUDPServerTunnel();
/** expire stale udp conversations */
void ExpireStale(const uint64_t delta = I2P_UDP_SESSION_TIMEOUT);
void Start();
void Stop();
const char *GetName() const { return m_Name.c_str(); }
std::vector <std::shared_ptr<DatagramSessionInfo>> GetSessions();
std::shared_ptr <ClientDestination> GetLocalDestination() const { return m_LocalDest; }
void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
private:
void
HandleRecvFromI2P(const i2p::data::IdentityEx &from, uint16_t fromPort, uint16_t toPort, const uint8_t *buf,
size_t len);
void HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t *buf, size_t len);
UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx &from, uint16_t localPort, uint16_t remotePort);
private:
bool m_IsUniqueLocal;
const std::string m_Name;
boost::asio::ip::address m_LocalAddress;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
std::mutex m_SessionsMutex;
std::vector <UDPSessionPtr> m_Sessions;
std::shared_ptr <i2p::client::ClientDestination> m_LocalDest;
UDPSessionPtr m_LastSession;
bool m_Gzip;
public:
bool isUpdated; // transient, used during reload only
};
class I2PUDPClientTunnel {
public:
I2PUDPClientTunnel(const std::string &name, const std::string &remoteDest,
boost::asio::ip::udp::endpoint localEndpoint,
std::shared_ptr <i2p::client::ClientDestination> localDestination,
uint16_t remotePort, bool gzip);
~I2PUDPClientTunnel();
void Start();
void Stop();
const char *GetName() const { return m_Name.c_str(); }
std::vector <std::shared_ptr<DatagramSessionInfo>> GetSessions();
bool IsLocalDestination(const i2p::data::IdentHash &destination) const {
return destination == m_LocalDest->GetIdentHash();
}
std::shared_ptr <ClientDestination> GetLocalDestination() const { return m_LocalDest; }
inline void SetLocalDestination(std::shared_ptr <ClientDestination> dest) {
if (m_LocalDest) m_LocalDest->Release();
if (dest) dest->Acquire();
m_LocalDest = dest;
}
void ExpireStale(const uint64_t delta = I2P_UDP_SESSION_TIMEOUT);
private:
typedef std::pair <boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
void RecvFromLocal();
void HandleRecvFromLocal(const boost::system::error_code &e, std::size_t transferred);
void
HandleRecvFromI2P(const i2p::data::IdentityEx &from, uint16_t fromPort, uint16_t toPort, const uint8_t *buf,
size_t len);
void HandleRecvFromI2PRaw(uint16_t fromPort, uint16_t toPort, const uint8_t *buf, size_t len);
void TryResolving();
private:
const std::string m_Name;
std::mutex m_SessionsMutex;
std::unordered_map <uint16_t, std::shared_ptr<UDPConvo>> m_Sessions; // maps i2p port -> local udp convo
const std::string m_RemoteDest;
std::shared_ptr <i2p::client::ClientDestination> m_LocalDest;
const boost::asio::ip::udp::endpoint m_LocalEndpoint;
i2p::data::IdentHash *m_RemoteIdent;
std::thread *m_ResolveThread;
std::unique_ptr <boost::asio::ip::udp::socket> m_LocalSocket;
boost::asio::ip::udp::endpoint m_RecvEndpoint;
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
uint16_t RemotePort, m_LastPort;
bool m_cancel_resolve;
bool m_Gzip;
std::shared_ptr <UDPConvo> m_LastSession;
public:
bool isUpdated; // transient, used during reload only
};
class I2PServerTunnel : public I2PService {
public:
I2PServerTunnel(const std::string &name, const std::string &address, int port,
std::shared_ptr <ClientDestination> localDestination, int inport = 0, bool gzip = true);
void Start();
void Stop();
void SetAccessList(const std::set <i2p::data::IdentHash> &accessList);
void SetUniqueLocal(bool isUniqueLocal) { m_IsUniqueLocal = isUniqueLocal; }
bool IsUniqueLocal() const { return m_IsUniqueLocal; }
void SetLocalAddress(const std::string &localAddress);
const std::string &GetAddress() const { return m_Address; }
int GetPort() const { return m_Port; };
uint16_t GetLocalPort() const { return m_PortDestination->GetLocalPort(); };
const boost::asio::ip::tcp::endpoint &GetEndpoint() const { return m_Endpoint; }
const char *GetName() { return m_Name.c_str(); }
private:
void HandleResolve(const boost::system::error_code &ecode, boost::asio::ip::tcp::resolver::iterator it,
std::shared_ptr <boost::asio::ip::tcp::resolver> resolver);
void Accept();
void HandleAccept(std::shared_ptr <i2p::stream::Stream> stream);
virtual std::shared_ptr <I2PTunnelConnection>
CreateI2PConnection(std::shared_ptr <i2p::stream::Stream> stream);
private:
bool m_IsUniqueLocal;
std::string m_Name, m_Address;
int m_Port;
boost::asio::ip::tcp::endpoint m_Endpoint;
std::shared_ptr <i2p::stream::StreamingDestination> m_PortDestination;
std::set <i2p::data::IdentHash> m_AccessList;
bool m_IsAccessList;
std::unique_ptr <boost::asio::ip::address> m_LocalAddress;
};
class I2PServerTunnelHTTP : public I2PServerTunnel {
public:
I2PServerTunnelHTTP(const std::string &name, const std::string &address, int port,
std::shared_ptr <ClientDestination> localDestination, const std::string &host,
int inport = 0, bool gzip = true);
private:
std::shared_ptr <I2PTunnelConnection> CreateI2PConnection(std::shared_ptr <i2p::stream::Stream> stream);
private:
std::string m_Host;
};
class I2PServerTunnelIRC : public I2PServerTunnel {
public:
I2PServerTunnelIRC(const std::string &name, const std::string &address, int port,
std::shared_ptr <ClientDestination> localDestination, const std::string &webircpass,
int inport = 0, bool gzip = true);
private:
std::shared_ptr <I2PTunnelConnection> CreateI2PConnection(std::shared_ptr <i2p::stream::Stream> stream);
private:
std::string m_WebircPass;
};
}
}
#endif

View file

@ -11,97 +11,86 @@
#include "ClientContext.h"
namespace i2p
{
namespace client
{
MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys & keys, const std::string & remoteName, const std::map<std::string, std::string> * params)
: RunnableClientDestination(keys, false, params),
m_RemoteName(remoteName) {}
namespace i2p {
namespace client {
MatchedTunnelDestination::MatchedTunnelDestination(const i2p::data::PrivateKeys &keys,
const std::string &remoteName,
const std::map <std::string, std::string> *params)
: RunnableClientDestination(keys, false, params),
m_RemoteName(remoteName) {}
void MatchedTunnelDestination::ResolveCurrentLeaseSet()
{
auto addr = i2p::client::context.GetAddressBook().GetAddress (m_RemoteName);
if(addr && addr->IsIdentHash ())
{
m_RemoteIdent = addr->identHash;
auto ls = FindLeaseSet(m_RemoteIdent);
if(ls)
HandleFoundCurrentLeaseSet(ls);
else
RequestDestination(m_RemoteIdent, std::bind(&MatchedTunnelDestination::HandleFoundCurrentLeaseSet, this, std::placeholders::_1));
}
else
LogPrint(eLogWarning, "Destination: Failed to resolve ", m_RemoteName);
}
void MatchedTunnelDestination::ResolveCurrentLeaseSet() {
auto addr = i2p::client::context.GetAddressBook().GetAddress(m_RemoteName);
if (addr && addr->IsIdentHash()) {
m_RemoteIdent = addr->identHash;
auto ls = FindLeaseSet(m_RemoteIdent);
if (ls)
HandleFoundCurrentLeaseSet(ls);
else
RequestDestination(m_RemoteIdent,
std::bind(&MatchedTunnelDestination::HandleFoundCurrentLeaseSet, this,
std::placeholders::_1));
} else
LogPrint(eLogWarning, "Destination: Failed to resolve ", m_RemoteName);
}
void MatchedTunnelDestination::HandleFoundCurrentLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> ls)
{
if(ls)
{
LogPrint(eLogDebug, "Destination: Resolved remote lease set for ", m_RemoteName);
m_RemoteLeaseSet = ls;
}
else
{
m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1));
m_ResolveTimer->async_wait([&](const boost::system::error_code & ec) {
if(!ec) ResolveCurrentLeaseSet();
});
}
}
void MatchedTunnelDestination::HandleFoundCurrentLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> ls) {
if (ls) {
LogPrint(eLogDebug, "Destination: Resolved remote lease set for ", m_RemoteName);
m_RemoteLeaseSet = ls;
} else {
m_ResolveTimer->expires_from_now(boost::posix_time::seconds(1));
m_ResolveTimer->async_wait([&](const boost::system::error_code &ec) {
if (!ec) ResolveCurrentLeaseSet();
});
}
}
void MatchedTunnelDestination::Start()
{
ClientDestination::Start();
m_ResolveTimer = std::make_shared<boost::asio::deadline_timer>(GetService());
GetTunnelPool()->SetCustomPeerSelector(this);
ResolveCurrentLeaseSet();
}
void MatchedTunnelDestination::Start() {
ClientDestination::Start();
m_ResolveTimer = std::make_shared<boost::asio::deadline_timer>(GetService());
GetTunnelPool()->SetCustomPeerSelector(this);
ResolveCurrentLeaseSet();
}
void MatchedTunnelDestination::Stop()
{
ClientDestination::Stop();
if(m_ResolveTimer)
m_ResolveTimer->cancel();
}
void MatchedTunnelDestination::Stop() {
ClientDestination::Stop();
if (m_ResolveTimer)
m_ResolveTimer->cancel();
}
bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path & path, int hops, bool inbound)
{
auto pool = GetTunnelPool();
if(!i2p::tunnel::StandardSelectPeers(path, hops, inbound,
std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool, std::placeholders::_1, std::placeholders::_2)))
return false;
// more here for outbound tunnels
if(!inbound && m_RemoteLeaseSet)
{
if(m_RemoteLeaseSet->IsExpired())
ResolveCurrentLeaseSet();
if(m_RemoteLeaseSet && !m_RemoteLeaseSet->IsExpired())
{
// remote lease set is good
auto leases = m_RemoteLeaseSet->GetNonExpiredLeases();
// pick lease
std::shared_ptr<i2p::data::RouterInfo> obep;
while(!obep && leases.size() > 0)
{
auto idx = rand() % leases.size();
auto lease = leases[idx];
obep = i2p::data::netdb.FindRouter(lease->tunnelGateway);
leases.erase(leases.begin()+idx);
}
if(obep)
{
path.Add (obep);
LogPrint(eLogDebug, "Destination: Found OBEP matching IBGW");
} else
LogPrint(eLogWarning, "Destination: Could not find proper IBGW for matched outbound tunnel");
}
}
return true;
}
}
bool MatchedTunnelDestination::SelectPeers(i2p::tunnel::Path &path, int hops, bool inbound) {
auto pool = GetTunnelPool();
if (!i2p::tunnel::StandardSelectPeers(path, hops, inbound,
std::bind(&i2p::tunnel::TunnelPool::SelectNextHop, pool,
std::placeholders::_1, std::placeholders::_2)))
return false;
// more here for outbound tunnels
if (!inbound && m_RemoteLeaseSet) {
if (m_RemoteLeaseSet->IsExpired())
ResolveCurrentLeaseSet();
if (m_RemoteLeaseSet && !m_RemoteLeaseSet->IsExpired()) {
// remote lease set is good
auto leases = m_RemoteLeaseSet->GetNonExpiredLeases();
// pick lease
std::shared_ptr <i2p::data::RouterInfo> obep;
while (!obep && leases.size() > 0) {
auto idx = rand() % leases.size();
auto lease = leases[idx];
obep = i2p::data::netdb.FindRouter(lease->tunnelGateway);
leases.erase(leases.begin() + idx);
}
if (obep) {
path.Add(obep);
LogPrint(eLogDebug, "Destination: Found OBEP matching IBGW");
} else
LogPrint(eLogWarning, "Destination: Could not find proper IBGW for matched outbound tunnel");
}
}
return true;
}
}
}

View file

@ -8,40 +8,41 @@
#ifndef MATCHED_DESTINATION_H_
#define MATCHED_DESTINATION_H_
#include "Destination.h"
#include <string>
namespace i2p
{
namespace client
{
/**
* client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination
*/
class MatchedTunnelDestination : public RunnableClientDestination, public i2p::tunnel::ITunnelPeerSelector
{
public:
namespace i2p {
namespace client {
/**
* client tunnel that uses same OBEP as IBGW of each remote lease for a remote destination
*/
class MatchedTunnelDestination : public RunnableClientDestination, public i2p::tunnel::ITunnelPeerSelector {
public:
MatchedTunnelDestination(const i2p::data::PrivateKeys& keys, const std::string & remoteName,
const std::map<std::string, std::string> * params = nullptr);
void Start();
void Stop();
MatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string &remoteName,
const std::map <std::string, std::string> *params = nullptr);
bool SelectPeers(i2p::tunnel::Path & peers, int hops, bool inbound);
void Start();
private:
void Stop();
void ResolveCurrentLeaseSet();
void HandleFoundCurrentLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> ls);
bool SelectPeers(i2p::tunnel::Path &peers, int hops, bool inbound);
private:
private:
std::string m_RemoteName;
i2p::data::IdentHash m_RemoteIdent;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<boost::asio::deadline_timer> m_ResolveTimer;
};
}
void ResolveCurrentLeaseSet();
void HandleFoundCurrentLeaseSet(std::shared_ptr<const i2p::data::LeaseSet> ls);
private:
std::string m_RemoteName;
i2p::data::IdentHash m_RemoteIdent;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr <boost::asio::deadline_timer> m_ResolveTimer;
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -24,265 +24,318 @@
#include "Streaming.h"
#include "Destination.h"
namespace i2p
{
namespace client
{
const size_t SAM_SOCKET_BUFFER_SIZE = 8192;
const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds
const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds
const char SAM_HANDSHAKE[] = "HELLO VERSION";
const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n";
const char SAM_HANDSHAKE_NOVERSION[] = "HELLO REPLY RESULT=NOVERSION\n";
const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n";
const char SAM_SESSION_CREATE[] = "SESSION CREATE";
const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n";
const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n";
const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n";
const char SAM_SESSION_CREATE_INVALID_ID[] = "SESSION STATUS RESULT=INVALID_ID\n";
const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n";
const char SAM_SESSION_STATUS_I2P_ERROR[] = "SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n";
const char SAM_SESSION_ADD[] = "SESSION ADD";
const char SAM_SESSION_REMOVE[] = "SESSION REMOVE";
const char SAM_STREAM_CONNECT[] = "STREAM CONNECT";
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n";
const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n";
const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR\n";
const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT";
const char SAM_STREAM_FORWARD[] = "STREAM FORWARD";
const char SAM_DATAGRAM_SEND[] = "DATAGRAM SEND";
const char SAM_RAW_SEND[] = "RAW SEND";
const char SAM_DEST_GENERATE[] = "DEST GENERATE";
const char SAM_DEST_REPLY[] = "DEST REPLY PUB=%s PRIV=%s\n";
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=%s VALUE=%s\n";
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
const char SAM_RAW_RECEIVED[] = "RAW RECEIVED SIZE=%lu\n";
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=KEY_NOT_FOUND NAME=%s\n";
const char SAM_PARAM_MIN[] = "MIN";
const char SAM_PARAM_MAX[] = "MAX";
const char SAM_PARAM_STYLE[] = "STYLE";
const char SAM_PARAM_ID[] = "ID";
const char SAM_PARAM_SILENT[] = "SILENT";
const char SAM_PARAM_DESTINATION[] = "DESTINATION";
const char SAM_PARAM_NAME[] = "NAME";
const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE";
const char SAM_PARAM_CRYPTO_TYPE[] = "CRYPTO_TYPE";
const char SAM_PARAM_SIZE[] = "SIZE";
const char SAM_PARAM_HOST[] = "HOST";
const char SAM_PARAM_PORT[] = "PORT";
const char SAM_PARAM_FROM_PORT[] = "FROM_PORT";
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
const char SAM_VALUE_STREAM[] = "STREAM";
const char SAM_VALUE_DATAGRAM[] = "DATAGRAM";
const char SAM_VALUE_RAW[] = "RAW";
const char SAM_VALUE_MASTER[] = "MASTER";
const char SAM_VALUE_TRUE[] = "true";
const char SAM_VALUE_FALSE[] = "false";
namespace i2p {
namespace client {
const size_t SAM_SOCKET_BUFFER_SIZE = 8192;
const int SAM_SOCKET_CONNECTION_MAX_IDLE = 3600; // in seconds
const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds
const char SAM_HANDSHAKE[] = "HELLO VERSION";
const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n";
const char SAM_HANDSHAKE_NOVERSION[] = "HELLO REPLY RESULT=NOVERSION\n";
const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n";
const char SAM_SESSION_CREATE[] = "SESSION CREATE";
const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n";
const char SAM_SESSION_CREATE_DUPLICATED_ID[] = "SESSION STATUS RESULT=DUPLICATED_ID\n";
const char SAM_SESSION_CREATE_DUPLICATED_DEST[] = "SESSION STATUS RESULT=DUPLICATED_DEST\n";
const char SAM_SESSION_CREATE_INVALID_ID[] = "SESSION STATUS RESULT=INVALID_ID\n";
const char SAM_SESSION_STATUS_INVALID_KEY[] = "SESSION STATUS RESULT=INVALID_KEY\n";
const char SAM_SESSION_STATUS_I2P_ERROR[] = "SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"%s\"\n";
const char SAM_SESSION_ADD[] = "SESSION ADD";
const char SAM_SESSION_REMOVE[] = "SESSION REMOVE";
const char SAM_STREAM_CONNECT[] = "STREAM CONNECT";
const char SAM_STREAM_STATUS_OK[] = "STREAM STATUS RESULT=OK\n";
const char SAM_STREAM_STATUS_INVALID_ID[] = "STREAM STATUS RESULT=INVALID_ID\n";
const char SAM_STREAM_STATUS_INVALID_KEY[] = "STREAM STATUS RESULT=INVALID_KEY\n";
const char SAM_STREAM_STATUS_CANT_REACH_PEER[] = "STREAM STATUS RESULT=CANT_REACH_PEER\n";
const char SAM_STREAM_STATUS_I2P_ERROR[] = "STREAM STATUS RESULT=I2P_ERROR\n";
const char SAM_STREAM_ACCEPT[] = "STREAM ACCEPT";
const char SAM_STREAM_FORWARD[] = "STREAM FORWARD";
const char SAM_DATAGRAM_SEND[] = "DATAGRAM SEND";
const char SAM_RAW_SEND[] = "RAW SEND";
const char SAM_DEST_GENERATE[] = "DEST GENERATE";
const char SAM_DEST_REPLY[] = "DEST REPLY PUB=%s PRIV=%s\n";
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=%s VALUE=%s\n";
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
const char SAM_RAW_RECEIVED[] = "RAW RECEIVED SIZE=%lu\n";
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=KEY_NOT_FOUND NAME=%s\n";
const char SAM_PARAM_MIN[] = "MIN";
const char SAM_PARAM_MAX[] = "MAX";
const char SAM_PARAM_STYLE[] = "STYLE";
const char SAM_PARAM_ID[] = "ID";
const char SAM_PARAM_SILENT[] = "SILENT";
const char SAM_PARAM_DESTINATION[] = "DESTINATION";
const char SAM_PARAM_NAME[] = "NAME";
const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE";
const char SAM_PARAM_CRYPTO_TYPE[] = "CRYPTO_TYPE";
const char SAM_PARAM_SIZE[] = "SIZE";
const char SAM_PARAM_HOST[] = "HOST";
const char SAM_PARAM_PORT[] = "PORT";
const char SAM_PARAM_FROM_PORT[] = "FROM_PORT";
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
const char SAM_VALUE_STREAM[] = "STREAM";
const char SAM_VALUE_DATAGRAM[] = "DATAGRAM";
const char SAM_VALUE_RAW[] = "RAW";
const char SAM_VALUE_MASTER[] = "MASTER";
const char SAM_VALUE_TRUE[] = "true";
const char SAM_VALUE_FALSE[] = "false";
enum SAMSocketType
{
eSAMSocketTypeUnknown,
eSAMSocketTypeSession,
eSAMSocketTypeStream,
eSAMSocketTypeAcceptor,
eSAMSocketTypeForward,
eSAMSocketTypeTerminated
};
enum SAMSocketType {
eSAMSocketTypeUnknown,
eSAMSocketTypeSession,
eSAMSocketTypeStream,
eSAMSocketTypeAcceptor,
eSAMSocketTypeForward,
eSAMSocketTypeTerminated
};
class SAMBridge;
struct SAMSession;
class SAMSocket: public std::enable_shared_from_this<SAMSocket>
{
public:
class SAMBridge;
typedef boost::asio::ip::tcp::socket Socket_t;
SAMSocket (SAMBridge& owner);
~SAMSocket ();
struct SAMSession;
Socket_t& GetSocket () { return m_Socket; };
void ReceiveHandshake ();
void SetSocketType (SAMSocketType socketType) { m_SocketType = socketType; };
SAMSocketType GetSocketType () const { return m_SocketType; };
class SAMSocket : public std::enable_shared_from_this<SAMSocket> {
public:
void Terminate (const char* reason);
typedef boost::asio::ip::tcp::socket Socket_t;
bool IsSession(const std::string & id) const;
SAMSocket(SAMBridge &owner);
private:
~SAMSocket();
void TerminateClose() { Terminate(nullptr); }
Socket_t &GetSocket() { return m_Socket; };
void HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleHandshakeReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleMessage (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void SendMessageReply (const char * msg, size_t len, bool close);
void HandleMessageReplySent (const boost::system::error_code& ecode, std::size_t bytes_transferred, bool close);
void Receive ();
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void ReceiveHandshake();
void I2PReceive ();
void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleI2PAccept (std::shared_ptr<i2p::stream::Stream> stream);
void HandleI2PForward (std::shared_ptr<i2p::stream::Stream> stream, boost::asio::ip::tcp::endpoint ep);
void HandleWriteI2PData (const boost::system::error_code& ecode, size_t sz);
void HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void HandleI2PRawDatagramReceive (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void SetSocketType(SAMSocketType socketType) { m_SocketType = socketType; };
void ProcessSessionCreate (char * buf, size_t len);
void ProcessStreamConnect (char * buf, size_t len, size_t rem);
void ProcessStreamAccept (char * buf, size_t len);
void ProcessStreamForward (char * buf, size_t len);
void ProcessDestGenerate (char * buf, size_t len);
void ProcessNamingLookup (char * buf, size_t len);
void ProcessSessionAdd (char * buf, size_t len);
void ProcessSessionRemove (char * buf, size_t len);
void SendI2PError(const std::string & msg);
size_t ProcessDatagramSend (char * buf, size_t len, const char * data); // from SAM 1.0
void ExtractParams (char * buf, std::map<std::string, std::string>& params);
SAMSocketType GetSocketType() const { return m_SocketType; };
void Connect (std::shared_ptr<const i2p::data::LeaseSet> remote, std::shared_ptr<SAMSession> session = nullptr);
void HandleConnectLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet);
void SendNamingLookupReply (const std::string& name, std::shared_ptr<const i2p::data::IdentityEx> identity);
void HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, std::string name);
void HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode);
void SendSessionCreateReplyOk ();
void Terminate(const char *reason);
void WriteI2PData(size_t sz);
void WriteI2PDataImmediate(uint8_t * ptr, size_t sz);
bool IsSession(const std::string &id) const;
void HandleWriteI2PDataImmediate(const boost::system::error_code & ec, uint8_t * buff);
void HandleStreamSend(const boost::system::error_code & ec);
private:
private:
void TerminateClose() { Terminate(nullptr); }
SAMBridge& m_Owner;
Socket_t m_Socket;
boost::asio::deadline_timer m_Timer;
char m_Buffer[SAM_SOCKET_BUFFER_SIZE + 1];
size_t m_BufferOffset;
uint8_t m_StreamBuffer[SAM_SOCKET_BUFFER_SIZE];
SAMSocketType m_SocketType;
std::string m_ID; // nickname
bool m_IsSilent;
bool m_IsAccepting; // for eSAMSocketTypeAcceptor only
std::shared_ptr<i2p::stream::Stream> m_Stream;
};
void HandleHandshakeReceived(const boost::system::error_code &ecode, std::size_t bytes_transferred);
enum SAMSessionType
{
eSAMSessionTypeUnknown,
eSAMSessionTypeStream,
eSAMSessionTypeDatagram,
eSAMSessionTypeRaw,
eSAMSessionTypeMaster
};
void HandleHandshakeReplySent(const boost::system::error_code &ecode, std::size_t bytes_transferred);
struct SAMSession
{
SAMBridge & m_Bridge;
std::string Name;
SAMSessionType Type;
std::shared_ptr<boost::asio::ip::udp::endpoint> UDPEndpoint; // TODO: move
void HandleMessage(const boost::system::error_code &ecode, std::size_t bytes_transferred);
SAMSession (SAMBridge & parent, const std::string & name, SAMSessionType type);
virtual ~SAMSession () {};
void SendMessageReply(const char *msg, size_t len, bool close);
virtual std::shared_ptr<ClientDestination> GetLocalDestination () = 0;
virtual void StopLocalDestination () = 0;
virtual void Close () { CloseStreams (); };
void
HandleMessageReplySent(const boost::system::error_code &ecode, std::size_t bytes_transferred, bool close);
void CloseStreams ();
};
void Receive();
struct SAMSingleSession: public SAMSession
{
std::shared_ptr<ClientDestination> localDestination;
void HandleReceived(const boost::system::error_code &ecode, std::size_t bytes_transferred);
SAMSingleSession (SAMBridge & parent, const std::string & name, SAMSessionType type, std::shared_ptr<ClientDestination> dest);
~SAMSingleSession ();
void I2PReceive();
std::shared_ptr<ClientDestination> GetLocalDestination () { return localDestination; };
void StopLocalDestination ();
};
void HandleI2PReceive(const boost::system::error_code &ecode, std::size_t bytes_transferred);
struct SAMMasterSession: public SAMSingleSession
{
std::set<std::string> subsessions;
SAMMasterSession (SAMBridge & parent, const std::string & name, std::shared_ptr<ClientDestination> dest):
SAMSingleSession (parent, name, eSAMSessionTypeMaster, dest) {};
void Close ();
};
void HandleI2PAccept(std::shared_ptr <i2p::stream::Stream> stream);
struct SAMSubSession: public SAMSession
{
std::shared_ptr<SAMMasterSession> masterSession;
int inPort;
void HandleI2PForward(std::shared_ptr <i2p::stream::Stream> stream, boost::asio::ip::tcp::endpoint ep);
SAMSubSession (std::shared_ptr<SAMMasterSession> master, const std::string& name, SAMSessionType type, int port);
// implements SAMSession
std::shared_ptr<ClientDestination> GetLocalDestination ();
void StopLocalDestination ();
};
void HandleWriteI2PData(const boost::system::error_code &ecode, size_t sz);
class SAMBridge: private i2p::util::RunnableService
{
public:
void HandleI2PDatagramReceive(const i2p::data::IdentityEx &from, uint16_t fromPort, uint16_t toPort,
const uint8_t *buf, size_t len);
SAMBridge (const std::string& address, int port, bool singleThread);
~SAMBridge ();
void HandleI2PRawDatagramReceive(uint16_t fromPort, uint16_t toPort, const uint8_t *buf, size_t len);
void Start ();
void Stop ();
void ProcessSessionCreate(char *buf, size_t len);
boost::asio::io_service& GetService () { return GetIOService (); };
std::shared_ptr<SAMSession> CreateSession (const std::string& id, SAMSessionType type, const std::string& destination, // empty string means transient
const std::map<std::string, std::string> * params);
bool AddSession (std::shared_ptr<SAMSession> session);
void CloseSession (const std::string& id);
std::shared_ptr<SAMSession> FindSession (const std::string& id) const;
void ProcessStreamConnect(char *buf, size_t len, size_t rem);
std::list<std::shared_ptr<SAMSocket> > ListSockets(const std::string & id) const;
void ProcessStreamAccept(char *buf, size_t len);
/** send raw data to remote endpoint from our UDP Socket */
void SendTo (const std::vector<boost::asio::const_buffer>& bufs, const boost::asio::ip::udp::endpoint& ep);
void ProcessStreamForward(char *buf, size_t len);
void AddSocket(std::shared_ptr<SAMSocket> socket);
void RemoveSocket(const std::shared_ptr<SAMSocket> & socket);
void ProcessDestGenerate(char *buf, size_t len);
bool ResolveSignatureType (const std::string& name, i2p::data::SigningKeyType& type) const;
void ProcessNamingLookup(char *buf, size_t len);
private:
void ProcessSessionAdd(char *buf, size_t len);
void Accept ();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<SAMSocket> socket);
void ProcessSessionRemove(char *buf, size_t len);
void ReceiveDatagram ();
void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void SendI2PError(const std::string &msg);
private:
size_t ProcessDatagramSend(char *buf, size_t len, const char *data); // from SAM 1.0
void ExtractParams(char *buf, std::map <std::string, std::string> &params);
bool m_IsSingleThread;
boost::asio::ip::tcp::acceptor m_Acceptor;
boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint;
boost::asio::ip::udp::socket m_DatagramSocket;
mutable std::mutex m_SessionsMutex;
std::map<std::string, std::shared_ptr<SAMSession> > m_Sessions;
mutable std::mutex m_OpenSocketsMutex;
std::list<std::shared_ptr<SAMSocket> > m_OpenSockets;
uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1];
std::map<std::string, i2p::data::SigningKeyType> m_SignatureTypes;
void
Connect(std::shared_ptr<const i2p::data::LeaseSet> remote, std::shared_ptr <SAMSession> session = nullptr);
public:
void HandleConnectLeaseSetRequestComplete(std::shared_ptr <i2p::data::LeaseSet> leaseSet);
// for HTTP
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
};
}
void SendNamingLookupReply(const std::string &name, std::shared_ptr<const i2p::data::IdentityEx> identity);
void
HandleNamingLookupLeaseSetRequestComplete(std::shared_ptr <i2p::data::LeaseSet> leaseSet, std::string name);
void HandleSessionReadinessCheckTimer(const boost::system::error_code &ecode);
void SendSessionCreateReplyOk();
void WriteI2PData(size_t sz);
void WriteI2PDataImmediate(uint8_t *ptr, size_t sz);
void HandleWriteI2PDataImmediate(const boost::system::error_code &ec, uint8_t *buff);
void HandleStreamSend(const boost::system::error_code &ec);
private:
SAMBridge &m_Owner;
Socket_t m_Socket;
boost::asio::deadline_timer m_Timer;
char m_Buffer[SAM_SOCKET_BUFFER_SIZE + 1];
size_t m_BufferOffset;
uint8_t m_StreamBuffer[SAM_SOCKET_BUFFER_SIZE];
SAMSocketType m_SocketType;
std::string m_ID; // nickname
bool m_IsSilent;
bool m_IsAccepting; // for eSAMSocketTypeAcceptor only
std::shared_ptr <i2p::stream::Stream> m_Stream;
};
enum SAMSessionType {
eSAMSessionTypeUnknown,
eSAMSessionTypeStream,
eSAMSessionTypeDatagram,
eSAMSessionTypeRaw,
eSAMSessionTypeMaster
};
struct SAMSession {
SAMBridge &m_Bridge;
std::string Name;
SAMSessionType Type;
std::shared_ptr <boost::asio::ip::udp::endpoint> UDPEndpoint; // TODO: move
SAMSession(SAMBridge &parent, const std::string &name, SAMSessionType type);
virtual ~SAMSession() {};
virtual std::shared_ptr <ClientDestination> GetLocalDestination() = 0;
virtual void StopLocalDestination() = 0;
virtual void Close() { CloseStreams(); };
void CloseStreams();
};
struct SAMSingleSession : public SAMSession {
std::shared_ptr <ClientDestination> localDestination;
SAMSingleSession(SAMBridge &parent, const std::string &name, SAMSessionType type,
std::shared_ptr <ClientDestination> dest);
~SAMSingleSession();
std::shared_ptr <ClientDestination> GetLocalDestination() { return localDestination; };
void StopLocalDestination();
};
struct SAMMasterSession : public SAMSingleSession {
std::set <std::string> subsessions;
SAMMasterSession(SAMBridge &parent, const std::string &name, std::shared_ptr <ClientDestination> dest) :
SAMSingleSession(parent, name, eSAMSessionTypeMaster, dest) {};
void Close();
};
struct SAMSubSession : public SAMSession {
std::shared_ptr <SAMMasterSession> masterSession;
int inPort;
SAMSubSession(std::shared_ptr <SAMMasterSession> master, const std::string &name, SAMSessionType type,
int port);
// implements SAMSession
std::shared_ptr <ClientDestination> GetLocalDestination();
void StopLocalDestination();
};
class SAMBridge : private i2p::util::RunnableService {
public:
SAMBridge(const std::string &address, int port, bool singleThread);
~SAMBridge();
void Start();
void Stop();
boost::asio::io_service &GetService() { return GetIOService(); };
std::shared_ptr <SAMSession> CreateSession(const std::string &id, SAMSessionType type,
const std::string &destination, // empty string means transient
const std::map <std::string, std::string> *params);
bool AddSession(std::shared_ptr <SAMSession> session);
void CloseSession(const std::string &id);
std::shared_ptr <SAMSession> FindSession(const std::string &id) const;
std::list <std::shared_ptr<SAMSocket>> ListSockets(const std::string &id) const;
/** send raw data to remote endpoint from our UDP Socket */
void SendTo(const std::vector <boost::asio::const_buffer> &bufs, const boost::asio::ip::udp::endpoint &ep);
void AddSocket(std::shared_ptr <SAMSocket> socket);
void RemoveSocket(const std::shared_ptr <SAMSocket> &socket);
bool ResolveSignatureType(const std::string &name, i2p::data::SigningKeyType &type) const;
private:
void Accept();
void HandleAccept(const boost::system::error_code &ecode, std::shared_ptr <SAMSocket> socket);
void ReceiveDatagram();
void HandleReceivedDatagram(const boost::system::error_code &ecode, std::size_t bytes_transferred);
private:
bool m_IsSingleThread;
boost::asio::ip::tcp::acceptor m_Acceptor;
boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint;
boost::asio::ip::udp::socket m_DatagramSocket;
mutable std::mutex m_SessionsMutex;
std::map <std::string, std::shared_ptr<SAMSession>> m_Sessions;
mutable std::mutex m_OpenSocketsMutex;
std::list <std::shared_ptr<SAMSocket>> m_OpenSockets;
uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE + 1];
std::map <std::string, i2p::data::SigningKeyType> m_SignatureTypes;
public:
// for HTTP
const decltype(m_Sessions)
&
GetSessions() const { return m_Sessions; };
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -15,35 +15,36 @@
#include <mutex>
#include "I2PService.h"
namespace i2p
{
namespace proxy
{
class SOCKSServer: public i2p::client::TCPIPAcceptor
{
public:
namespace i2p {
namespace proxy {
class SOCKSServer : public i2p::client::TCPIPAcceptor {
public:
SOCKSServer(const std::string& name, const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort,
std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr);
~SOCKSServer() {};
SOCKSServer(const std::string &name, const std::string &address, int port, bool outEnable,
const std::string &outAddress, uint16_t outPort,
std::shared_ptr <i2p::client::ClientDestination> localDestination = nullptr);
void SetUpstreamProxy(const std::string & addr, const uint16_t port);
~SOCKSServer() {};
protected:
void SetUpstreamProxy(const std::string &addr, const uint16_t port);
// Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return m_Name.c_str (); }
protected:
private:
// Implements TCPIPAcceptor
std::shared_ptr <i2p::client::I2PServiceHandler>
CreateHandler(std::shared_ptr <boost::asio::ip::tcp::socket> socket);
std::string m_Name;
std::string m_UpstreamProxyAddress;
uint16_t m_UpstreamProxyPort;
bool m_UseUpstreamProxy;
};
const char *GetName() { return m_Name.c_str(); }
typedef SOCKSServer SOCKSProxy;
}
private:
std::string m_Name;
std::string m_UpstreamProxyAddress;
uint16_t m_UpstreamProxyPort;
bool m_UseUpstreamProxy;
};
typedef SOCKSServer SOCKSProxy;
}
}
#endif