2#if defined(HAVE_CONFIG_H)
9#include <openssl/err.h>
10#include <openssl/opensslv.h>
11#include <openssl/x509.h>
12#include <openssl/x509v3.h>
20#define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
28 mSocket(ioService, context),
30 mHandshakeTimer(ioService),
31 mServerHandshakeDone(false),
32 mValidateServerCertificateHostname(validateServerCertificateHostname)
39 return (
unsigned int)
mSocket.lowest_layer().native_handle();
60 std::placeholders::_1,
61 std::placeholders::_2));
66 const asio::ip::tcp::resolver::results_type& endpoints)
87 if (!hostname.empty() && !isIpAddress && SSL_set_tlsext_host_name(ssl, hostname.c_str()) != 1)
89 WarningLog(<<
"Failed to set SNI " << hostname <<
", continuing without it");
100 ok = X509_VERIFY_PARAM_set1_ip_asc(SSL_get0_param(ssl), hostname.c_str()) == 1;
104 SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
105 ok = !hostname.empty() && SSL_set1_host(ssl, hostname.c_str()) == 1;
109 ErrLog(<<
"Unable to validate the server certificate against <" << hostname <<
">");
123 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
124 InfoLog(<<
"TLS session set up with " << hostname <<
": " << SSL_get_version(ssl)
125 <<
" " << (cipher ? SSL_CIPHER_get_name(cipher) :
"unknown cipher"));
127 else if (SSL_get_verify_result(ssl) != X509_V_OK)
130 WarningLog(<<
"TLS handshake with " << hostname <<
" failed, server certificate rejected: "
131 << X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
137 const asio::ip::tcp::endpoint& endpoint)
148 mSocket.async_handshake(asio::ssl::stream_base::client,
150 std::placeholders::_1, endpoint));
160 const asio::ip::tcp::endpoint& endpoint)
181 if (timeoutSeconds > 0)
184 std::shared_ptr<AsyncSocketBase> self = shared_from_this();
185 mHandshakeTimer.expires_after(std::chrono::seconds(timeoutSeconds));
186 mHandshakeTimer.async_wait([
this, self](
const asio::error_code& e)
188 if (e != asio::error::operation_aborted && !mServerHandshakeDone)
190 WarningLog(<<
"TLS handshake not completed in time, closing the connection");
192 mSocket.lowest_layer().close(ec);
196 mSocket.async_handshake(asio::ssl::stream_base::server,
203 mServerHandshakeDone =
true;
204 mHandshakeTimer.cancel();
235 asio::async_write(
mSocket, buffers,
264 mSocket.lowest_layer().close(ec);
284 dataLen = ntohs(dataLen);
304 WarningLog(<<
"Receive buffer (" <<
RECEIVE_BUFFER_SIZE <<
") is not large enough to accommodate incoming framed data (" << dataLen+4 <<
") closing connection.");
308 else if (e != asio::error::operation_aborted)
310 if(e != asio::error::eof && e != asio::error::connection_reset)
312 WarningLog(<<
"Read header error: " << e.value() <<
"-" << e.message());
constexpr size_t RECEIVE_BUFFER_SIZE
#define WarningLog(args_)
virtual void handleReceive(const asio::error_code &e, size_t bytesTransferred)
asio::ip::tcp::endpoint mLocalTcpEndpoint
asio::error_code openAndBind(asio::ip::tcp::socket &socket)
For TCP and TLS client sockets.
virtual void handleTcpResolve(const asio::error_code &ec, const asio::ip::tcp::resolver::results_type &endpoints)
BeforeClosedHandler mOnBeforeSocketCloseFp
Provides an opportunity for the app to clean up, e.g., QoS-related data or resources just before the ...
static size_t channelDataPadding(size_t length)
Over TCP and TLS, a TURN ChannelData message is padded to a multiple of 4 bytes, the padding not coun...
virtual void handleClientHandshake(const asio::error_code &ec, const asio::ip::tcp::endpoint &endpoint)
virtual void onConnectFailure(const asio::error_code &e)
virtual void onConnectSuccess()
Class override callbacks.
unsigned short mConnectedPort
virtual void handleSend(const asio::error_code &e)
Handle completion of a sendData operation.
virtual void handleReadHeader(const asio::error_code &e)
void asyncConnect(asio::ip::tcp::socket &socket, const asio::ip::tcp::resolver::results_type &endpoints)
std::shared_ptr< DataBuffer > mReceiveBuffer
Receive Buffer and state.
virtual void handleServerHandshake(const asio::error_code &e)
asio::ip::address mConnectedAddress
Connected Info and State.
asio::ip::address getSenderEndpointAddress() override
asio::ip::tcp::resolver mResolver
asio::ssl::stream< asio::ip::tcp::socket > mSocket
void transportSend(const StunTuple &destination, std::vector< asio::const_buffer > &buffers) override
void handleServerHandshake(const asio::error_code &e) override
void handleReadHeader(const asio::error_code &e) override
void transportFramedReceive() override
void transportReceive() override
virtual void onServerHandshakeFailure(const asio::error_code &e)
static bool setupClientSsl(SSL *ssl, const std::string &hostname, bool validateHostname)
Sets up a client SSL to connect to hostname (a host name or IP address): SNI for a host name,...
virtual void onServerHandshakeSuccess()
unsigned int getSocketDescriptor() override
void handleConnect(const asio::error_code &ec, const asio::ip::tcp::endpoint &endpoint) override
unsigned short getSenderEndpointPort() override
void handleTcpResolve(const asio::error_code &ec, const asio::ip::tcp::resolver::results_type &endpoints) override
static void logClientHandshakeResult(SSL *ssl, const std::string &hostname, const asio::error_code &ec)
Logs a client handshake's outcome: the TLS version and cipher, or why the server certificate was reje...
void doHandshake(unsigned int timeoutSeconds=0)
Starts the server side handshake.
AsyncTlsSocketBase(asio::io_context &ioService, asio::ssl::context &context, bool validateServerCertificateHostname)
void connect(const std::string &address, unsigned short port) override
asio::error_code bind(const asio::ip::address &address, unsigned short port) override
Note: The following API's are thread safe and queue the request to be handled by the ioService thread...
void transportClose() override
void handleClientHandshake(const asio::error_code &ec, const asio::ip::tcp::endpoint &endpoint) override
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
const char * c_str() const
Returns a null-terminated string representing.
static bool isIpAddress(const Data &ipAddress)