2015-01-18 05:57:16 -05:00
|
|
|
|
|
|
|
// TCPLinkImpl.h
|
|
|
|
|
|
|
|
// Declares the cTCPLinkImpl class implementing the TCP link functionality
|
|
|
|
|
|
|
|
// This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "Network.h"
|
|
|
|
#include <event2/event.h>
|
|
|
|
#include <event2/bufferevent.h>
|
2016-08-22 13:53:34 -04:00
|
|
|
#include "../PolarSSL++/SslContext.h"
|
2015-01-18 05:57:16 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fwd:
|
|
|
|
class cServerHandleImpl;
|
2015-01-23 17:01:18 -05:00
|
|
|
typedef SharedPtr<cServerHandleImpl> cServerHandleImplPtr;
|
2015-01-18 05:57:16 -05:00
|
|
|
class cTCPLinkImpl;
|
|
|
|
typedef SharedPtr<cTCPLinkImpl> cTCPLinkImplPtr;
|
|
|
|
typedef std::vector<cTCPLinkImplPtr> cTCPLinkImplPtrs;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cTCPLinkImpl:
|
|
|
|
public cTCPLink
|
|
|
|
{
|
|
|
|
typedef cTCPLink super;
|
|
|
|
|
|
|
|
public:
|
|
|
|
/** Creates a new link based on the given socket.
|
|
|
|
Used for connections accepted in a server using cNetwork::Listen().
|
2015-01-22 07:00:32 -05:00
|
|
|
a_Address and a_AddrLen describe the remote peer that has connected.
|
|
|
|
The link is created disabled, you need to call Enable() to start the regular communication. */
|
2015-01-23 17:01:18 -05:00
|
|
|
cTCPLinkImpl(evutil_socket_t a_Socket, cCallbacksPtr a_LinkCallbacks, cServerHandleImplPtr a_Server, const sockaddr * a_Address, socklen_t a_AddrLen);
|
2015-01-18 05:57:16 -05:00
|
|
|
|
|
|
|
/** Destroys the LibEvent handle representing the link. */
|
|
|
|
~cTCPLinkImpl();
|
|
|
|
|
|
|
|
/** Queues a connection request to the specified host.
|
|
|
|
a_ConnectCallbacks must be valid.
|
|
|
|
Returns a link that has the connection request queued, or NULL for failure. */
|
|
|
|
static cTCPLinkImplPtr Connect(const AString & a_Host, UInt16 a_Port, cTCPLink::cCallbacksPtr a_LinkCallbacks, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks);
|
|
|
|
|
2015-01-22 07:00:32 -05:00
|
|
|
/** Enables communication over the link.
|
|
|
|
Links are created with communication disabled, so that creation callbacks can be called first.
|
2015-01-23 17:01:18 -05:00
|
|
|
This function then enables the regular communication to be reported.
|
|
|
|
The a_Self parameter is used so that the socket can keep itself alive as long as the callbacks are coming. */
|
|
|
|
void Enable(cTCPLinkImplPtr a_Self);
|
2015-01-22 07:00:32 -05:00
|
|
|
|
2015-01-18 05:57:16 -05:00
|
|
|
// cTCPLink overrides:
|
|
|
|
virtual bool Send(const void * a_Data, size_t a_Length) override;
|
|
|
|
virtual AString GetLocalIP(void) const override { return m_LocalIP; }
|
|
|
|
virtual UInt16 GetLocalPort(void) const override { return m_LocalPort; }
|
|
|
|
virtual AString GetRemoteIP(void) const override { return m_RemoteIP; }
|
|
|
|
virtual UInt16 GetRemotePort(void) const override { return m_RemotePort; }
|
|
|
|
virtual void Shutdown(void) override;
|
|
|
|
virtual void Close(void) override;
|
2016-08-22 13:53:34 -04:00
|
|
|
virtual AString StartTLSClient(
|
|
|
|
cX509CertPtr a_OwnCert,
|
|
|
|
cCryptoKeyPtr a_OwnPrivKey
|
|
|
|
) override;
|
|
|
|
virtual AString StartTLSServer(
|
|
|
|
cX509CertPtr a_OwnCert,
|
|
|
|
cCryptoKeyPtr a_OwnPrivKey,
|
|
|
|
const AString & a_StartTLSData
|
|
|
|
) override;
|
2015-01-18 05:57:16 -05:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
2016-08-22 13:53:34 -04:00
|
|
|
// fwd:
|
|
|
|
class cLinkTlsContext;
|
|
|
|
typedef SharedPtr<cLinkTlsContext> cLinkTlsContextPtr;
|
|
|
|
typedef WeakPtr<cLinkTlsContext> cLinkTlsContextWPtr;
|
|
|
|
|
|
|
|
/** Wrapper around cSslContext that is used when this link is being encrypted by SSL. */
|
|
|
|
class cLinkTlsContext :
|
|
|
|
public cSslContext
|
|
|
|
{
|
|
|
|
cTCPLinkImpl & m_Link;
|
|
|
|
|
|
|
|
/** Buffer for storing the incoming encrypted data until it is requested by the SSL decryptor. */
|
|
|
|
AString m_EncryptedData;
|
|
|
|
|
|
|
|
/** Buffer for storing the outgoing cleartext data until the link has finished handshaking. */
|
|
|
|
AString m_CleartextData;
|
|
|
|
|
|
|
|
/** Shared ownership of self, so that this object can keep itself alive for as long as it needs. */
|
|
|
|
cLinkTlsContextWPtr m_Self;
|
|
|
|
|
|
|
|
public:
|
|
|
|
cLinkTlsContext(cTCPLinkImpl & a_Link);
|
|
|
|
|
|
|
|
/** Shares ownership of self, so that this object can keep itself alive for as long as it needs. */
|
|
|
|
void SetSelf(cLinkTlsContextWPtr a_Self);
|
|
|
|
|
|
|
|
/** Removes the self ownership so that we can detect the SSL closure. */
|
|
|
|
void ResetSelf(void);
|
|
|
|
|
|
|
|
/** Stores the specified block of data into the buffer of the data to be decrypted (incoming from remote).
|
|
|
|
Also flushes the SSL buffers by attempting to read any data through the SSL context. */
|
|
|
|
void StoreReceivedData(const char * a_Data, size_t a_NumBytes);
|
|
|
|
|
|
|
|
/** Tries to read any cleartext data available through the SSL, reports it in the link. */
|
|
|
|
void FlushBuffers(void);
|
|
|
|
|
|
|
|
/** Tries to finish handshaking the SSL. */
|
|
|
|
void TryFinishHandshaking(void);
|
|
|
|
|
|
|
|
/** Sends the specified cleartext data over the SSL to the remote peer.
|
|
|
|
If the handshake hasn't been completed yet, queues the data for sending when it completes. */
|
|
|
|
void Send(const void * a_Data, size_t a_Length);
|
|
|
|
|
|
|
|
// cSslContext overrides:
|
|
|
|
virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override;
|
|
|
|
virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override;
|
|
|
|
|
|
|
|
/** Returns true if the context's associated TCP link is the same link as a_Link. */
|
|
|
|
bool IsLink(cTCPLinkImpl * a_Link)
|
|
|
|
{
|
|
|
|
return (a_Link == &m_Link);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-18 05:57:16 -05:00
|
|
|
/** Callbacks to call when the connection is established.
|
|
|
|
May be NULL if not used. Only used for outgoing connections (cNetwork::Connect()). */
|
|
|
|
cNetwork::cConnectCallbacksPtr m_ConnectCallbacks;
|
|
|
|
|
|
|
|
/** The LibEvent handle representing this connection. */
|
|
|
|
bufferevent * m_BufferEvent;
|
|
|
|
|
|
|
|
/** The server handle that has created this link.
|
2015-01-23 17:01:18 -05:00
|
|
|
Only valid for incoming connections, nullptr for outgoing connections. */
|
|
|
|
cServerHandleImplPtr m_Server;
|
2015-01-18 05:57:16 -05:00
|
|
|
|
|
|
|
/** The IP address of the local endpoint. Valid only after the socket has been connected. */
|
|
|
|
AString m_LocalIP;
|
|
|
|
|
|
|
|
/** The port of the local endpoint. Valid only after the socket has been connected. */
|
|
|
|
UInt16 m_LocalPort;
|
|
|
|
|
|
|
|
/** The IP address of the remote endpoint. Valid only after the socket has been connected. */
|
|
|
|
AString m_RemoteIP;
|
|
|
|
|
|
|
|
/** The port of the remote endpoint. Valid only after the socket has been connected. */
|
|
|
|
UInt16 m_RemotePort;
|
|
|
|
|
2015-01-23 17:01:18 -05:00
|
|
|
/** SharedPtr to self, used to keep this object alive as long as the callbacks are coming.
|
|
|
|
Initialized in Enable(), cleared in Close() and EventCallback(RemoteClosed). */
|
|
|
|
cTCPLinkImplPtr m_Self;
|
|
|
|
|
2015-02-14 07:55:54 -05:00
|
|
|
/** If true, Shutdown() has been called and is in queue.
|
|
|
|
No more data is allowed to be sent via Send() and after all the currently buffered
|
|
|
|
data is sent to the OS TCP stack, the socket gets shut down. */
|
|
|
|
bool m_ShouldShutdown;
|
|
|
|
|
2016-08-22 13:53:34 -04:00
|
|
|
/** The SSL context used for encryption, if this link uses SSL.
|
|
|
|
If valid, the link uses encryption through this context. */
|
|
|
|
cLinkTlsContextPtr m_TlsContext;
|
|
|
|
|
2015-01-18 05:57:16 -05:00
|
|
|
|
|
|
|
/** Creates a new link to be queued to connect to a specified host:port.
|
|
|
|
Used for outgoing connections created using cNetwork::Connect().
|
2015-01-22 07:00:32 -05:00
|
|
|
To be used only by the Connect() factory function.
|
|
|
|
The link is created disabled, you need to call Enable() to start the regular communication. */
|
2015-01-18 05:57:16 -05:00
|
|
|
cTCPLinkImpl(const cCallbacksPtr a_LinkCallbacks);
|
|
|
|
|
|
|
|
/** Callback that LibEvent calls when there's data available from the remote peer. */
|
|
|
|
static void ReadCallback(bufferevent * a_BufferEvent, void * a_Self);
|
|
|
|
|
2015-02-14 07:55:54 -05:00
|
|
|
/** Callback that LibEvent calls when the remote peer can receive more data. */
|
|
|
|
static void WriteCallback(bufferevent * a_BufferEvent, void * a_Self);
|
|
|
|
|
2015-01-18 05:57:16 -05:00
|
|
|
/** Callback that LibEvent calls when there's a non-data-related event on the socket. */
|
|
|
|
static void EventCallback(bufferevent * a_BufferEvent, short a_What, void * a_Self);
|
|
|
|
|
|
|
|
/** Sets a_IP and a_Port to values read from a_Address, based on the correct address family. */
|
2015-01-18 09:40:39 -05:00
|
|
|
static void UpdateAddress(const sockaddr * a_Address, socklen_t a_AddrLen, AString & a_IP, UInt16 & a_Port);
|
2015-01-18 05:57:16 -05:00
|
|
|
|
|
|
|
/** Updates m_LocalIP and m_LocalPort based on the metadata read from the socket. */
|
|
|
|
void UpdateLocalAddress(void);
|
|
|
|
|
|
|
|
/** Updates m_RemoteIP and m_RemotePort based on the metadata read from the socket. */
|
|
|
|
void UpdateRemoteAddress(void);
|
2015-02-14 07:55:54 -05:00
|
|
|
|
|
|
|
/** Calls shutdown on the link and disables LibEvent writing.
|
|
|
|
Called after all data from LibEvent buffers is sent to the OS TCP stack and shutdown() has been called before. */
|
|
|
|
void DoActualShutdown(void);
|
2016-08-22 13:53:34 -04:00
|
|
|
|
|
|
|
/** Sends the data directly to the socket (without the optional TLS). */
|
|
|
|
bool SendRaw(const void * a_Data, size_t a_Length);
|
|
|
|
|
|
|
|
/** Called by the TLS when it has decoded a piece of incoming cleartext data from the socket. */
|
|
|
|
void ReceivedCleartextData(const char * a_Data, size_t a_Length);
|
2015-01-18 05:57:16 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|