WIP: support configurable certificates/keys, and root trust CAs (#114)

* wip: tls options implemented in openssl

* update naming, remove #define guard

* assert compiled with USE_TLS for tls options

* apply autoformatter

* include tls options impl

* style cleanup; auto ssl_err

* ssl_err -> sslErr

* be explicit about SSL_VERIFY_NONE
This commit is contained in:
Matt DeBoer 2019-09-22 18:06:15 -07:00 committed by Benjamin Sergeant
parent 1769199d32
commit dd01f734c6
11 changed files with 222 additions and 70 deletions

View File

@ -35,6 +35,7 @@ set( IXWEBSOCKET_SOURCES
ixwebsocket/IXSocketConnect.cpp ixwebsocket/IXSocketConnect.cpp
ixwebsocket/IXSocketFactory.cpp ixwebsocket/IXSocketFactory.cpp
ixwebsocket/IXSocketServer.cpp ixwebsocket/IXSocketServer.cpp
ixwebsocket/IXSocketTLSOptions.cpp
ixwebsocket/IXUrlParser.cpp ixwebsocket/IXUrlParser.cpp
ixwebsocket/IXUserAgent.cpp ixwebsocket/IXUserAgent.cpp
ixwebsocket/IXWebSocket.cpp ixwebsocket/IXWebSocket.cpp
@ -67,6 +68,7 @@ set( IXWEBSOCKET_HEADERS
ixwebsocket/IXSocketConnect.h ixwebsocket/IXSocketConnect.h
ixwebsocket/IXSocketFactory.h ixwebsocket/IXSocketFactory.h
ixwebsocket/IXSocketServer.h ixwebsocket/IXSocketServer.h
ixwebsocket/IXSocketTLSOptions.h
ixwebsocket/IXUrlParser.h ixwebsocket/IXUrlParser.h
ixwebsocket/IXUtf8Validator.h ixwebsocket/IXUtf8Validator.h
ixwebsocket/IXUserAgent.h ixwebsocket/IXUserAgent.h

View File

@ -8,15 +8,15 @@
#ifdef IXWEBSOCKET_USE_TLS #ifdef IXWEBSOCKET_USE_TLS
# ifdef IXWEBSOCKET_USE_MBED_TLS #ifdef IXWEBSOCKET_USE_MBED_TLS
# include <ixwebsocket/IXSocketMbedTLS.h> #include <ixwebsocket/IXSocketMbedTLS.h>
# elif __APPLE__ #elif __APPLE__
# include <ixwebsocket/IXSocketAppleSSL.h> #include <ixwebsocket/IXSocketAppleSSL.h>
# elif defined(_WIN32) #elif defined(_WIN32)
# include <ixwebsocket/IXSocketSChannel.h> #include <ixwebsocket/IXSocketSChannel.h>
# elif defined(IXWEBSOCKET_USE_OPEN_SSL) #elif defined(IXWEBSOCKET_USE_OPEN_SSL)
# include <ixwebsocket/IXSocketOpenSSL.h> #include <ixwebsocket/IXSocketOpenSSL.h>
# endif #endif
#else #else
@ -27,7 +27,8 @@
namespace ix namespace ix
{ {
std::shared_ptr<Socket> createSocket(bool tls, std::shared_ptr<Socket> createSocket(bool tls,
std::string& errorMsg) std::string& errorMsg,
const SocketTLSOptions& tlsOptions)
{ {
errorMsg.clear(); errorMsg.clear();
std::shared_ptr<Socket> socket; std::shared_ptr<Socket> socket;
@ -39,15 +40,15 @@ namespace ix
else else
{ {
#ifdef IXWEBSOCKET_USE_TLS #ifdef IXWEBSOCKET_USE_TLS
# if defined(IXWEBSOCKET_USE_MBED_TLS) #if defined(IXWEBSOCKET_USE_MBED_TLS)
socket = std::make_shared<SocketMbedTLS>(); socket = std::make_shared<SocketMbedTLS>(tlsOptions);
# elif defined(__APPLE__) #elif defined(__APPLE__)
socket = std::make_shared<SocketAppleSSL>(); socket = std::make_shared<SocketAppleSSL>(tlsOptions);
# elif defined(_WIN32) #elif defined(_WIN32)
socket = std::make_shared<SocketSChannel>(); socket = std::make_shared<SocketSChannel>(tlsOptions);
# else #else
socket = std::make_shared<SocketOpenSSL>(); socket = std::make_shared<SocketOpenSSL>(tlsOptions);
# endif #endif
#else #else
errorMsg = "TLS support is not enabled on this platform."; errorMsg = "TLS support is not enabled on this platform.";
return nullptr; return nullptr;
@ -62,8 +63,7 @@ namespace ix
return socket; return socket;
} }
std::shared_ptr<Socket> createSocket(int fd, std::shared_ptr<Socket> createSocket(int fd, std::string& errorMsg)
std::string& errorMsg)
{ {
errorMsg.clear(); errorMsg.clear();
@ -75,4 +75,4 @@ namespace ix
return socket; return socket;
} }
} } // namespace ix

View File

@ -10,10 +10,12 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "IXSocketTLSOptions.h"
namespace ix namespace ix
{ {
class Socket; class Socket;
std::shared_ptr<Socket> createSocket(bool tls, std::string& errorMsg); std::shared_ptr<Socket> createSocket(bool tls, std::string& errorMsg, const SocketTLSOptions& tlsOptions);
std::shared_ptr<Socket> createSocket(int fd, std::string& errorMsg); std::shared_ptr<Socket> createSocket(int fd, std::string& errorMsg);
} // namespace ix } // namespace ix

View File

@ -7,14 +7,12 @@
*/ */
#include "IXSocketOpenSSL.h" #include "IXSocketOpenSSL.h"
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include <cassert> #include <cassert>
#include <openssl/x509v3.h>
#include <fnmatch.h>
#include <errno.h> #include <errno.h>
#include <fnmatch.h>
#include <openssl/x509v3.h>
#define socketerrno errno #define socketerrno errno
namespace ix namespace ix
@ -22,9 +20,10 @@ namespace ix
std::atomic<bool> SocketOpenSSL::_openSSLInitializationSuccessful(false); std::atomic<bool> SocketOpenSSL::_openSSLInitializationSuccessful(false);
std::once_flag SocketOpenSSL::_openSSLInitFlag; std::once_flag SocketOpenSSL::_openSSLInitFlag;
SocketOpenSSL::SocketOpenSSL(int fd) : Socket(fd), SocketOpenSSL::SocketOpenSSL(const SocketTLSOptions& tlsOptions, int fd)
_ssl_connection(nullptr), : Socket(fd)
_ssl_context(nullptr) , _ssl_connection(nullptr)
, _ssl_context(nullptr)
{ {
std::call_once(_openSSLInitFlag, &SocketOpenSSL::openSSLInitialize, this); std::call_once(_openSSLInitFlag, &SocketOpenSSL::openSSLInitialize, this);
} }
@ -114,14 +113,17 @@ namespace ix
SSL_CTX* ctx = SSL_CTX_new(_ssl_method); SSL_CTX* ctx = SSL_CTX_new(_ssl_method);
if (ctx) if (ctx)
{ {
// To skip verification, pass in SSL_VERIFY_NONE if (!_tlsOptions.isPeerVerifyDisabled())
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, {
[](int preverify, X509_STORE_CTX*) -> int SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, [](int preverify, X509_STORE_CTX*) -> int {
{ return preverify;
return preverify; });
});
SSL_CTX_set_verify_depth(ctx, 4);
} else {
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
}
SSL_CTX_set_verify_depth(ctx, 4);
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
} }
return ctx; return ctx;
@ -130,16 +132,16 @@ namespace ix
/** /**
* Check whether a hostname matches a pattern * Check whether a hostname matches a pattern
*/ */
bool SocketOpenSSL::checkHost(const std::string& host, const char *pattern) bool SocketOpenSSL::checkHost(const std::string& host, const char* pattern)
{ {
return fnmatch(pattern, host.c_str(), 0) != FNM_NOMATCH; return fnmatch(pattern, host.c_str(), 0) != FNM_NOMATCH;
} }
bool SocketOpenSSL::openSSLCheckServerCert(SSL *ssl, bool SocketOpenSSL::openSSLCheckServerCert(SSL* ssl,
const std::string& hostname, const std::string& hostname,
std::string& errMsg) std::string& errMsg)
{ {
X509 *server_cert = SSL_get_peer_certificate(ssl); X509* server_cert = SSL_get_peer_certificate(ssl);
if (server_cert == nullptr) if (server_cert == nullptr)
{ {
errMsg = "OpenSSL failed - peer didn't present a X509 certificate."; errMsg = "OpenSSL failed - peer didn't present a X509 certificate.";
@ -149,18 +151,17 @@ namespace ix
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L
// Check server name // Check server name
bool hostname_verifies_ok = false; bool hostname_verifies_ok = false;
STACK_OF(GENERAL_NAME) *san_names = STACK_OF(GENERAL_NAME)* san_names = (STACK_OF(GENERAL_NAME)*) X509_get_ext_d2i(
(STACK_OF(GENERAL_NAME)*) X509_get_ext_d2i((X509 *)server_cert, (X509*) server_cert, NID_subject_alt_name, NULL, NULL);
NID_subject_alt_name, NULL, NULL);
if (san_names) if (san_names)
{ {
for (int i=0; i<sk_GENERAL_NAME_num(san_names); i++) for (int i = 0; i < sk_GENERAL_NAME_num(san_names); i++)
{ {
const GENERAL_NAME *sk_name = sk_GENERAL_NAME_value(san_names, i); const GENERAL_NAME* sk_name = sk_GENERAL_NAME_value(san_names, i);
if (sk_name->type == GEN_DNS) if (sk_name->type == GEN_DNS)
{ {
char *name = (char *)ASN1_STRING_data(sk_name->d.dNSName); char* name = (char*) ASN1_STRING_data(sk_name->d.dNSName);
if ((size_t)ASN1_STRING_length(sk_name->d.dNSName) == strlen(name) && if ((size_t) ASN1_STRING_length(sk_name->d.dNSName) == strlen(name) &&
checkHost(hostname, name)) checkHost(hostname, name))
{ {
hostname_verifies_ok = true; hostname_verifies_ok = true;
@ -173,20 +174,20 @@ namespace ix
if (!hostname_verifies_ok) if (!hostname_verifies_ok)
{ {
int cn_pos = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *)server_cert), int cn_pos = X509_NAME_get_index_by_NID(
NID_commonName, -1); X509_get_subject_name((X509*) server_cert), NID_commonName, -1);
if (cn_pos) if (cn_pos)
{ {
X509_NAME_ENTRY *cn_entry = X509_NAME_get_entry( X509_NAME_ENTRY* cn_entry =
X509_get_subject_name((X509 *)server_cert), cn_pos); X509_NAME_get_entry(X509_get_subject_name((X509*) server_cert), cn_pos);
if (cn_entry) if (cn_entry)
{ {
ASN1_STRING *cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry); ASN1_STRING* cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry);
char *cn = (char *)ASN1_STRING_data(cn_asn1); char* cn = (char*) ASN1_STRING_data(cn_asn1);
if ((size_t)ASN1_STRING_length(cn_asn1) == strlen(cn) && if ((size_t) ASN1_STRING_length(cn_asn1) == strlen(cn) &&
checkHost(hostname, cn)) checkHost(hostname, cn))
{ {
hostname_verifies_ok = true; hostname_verifies_ok = true;
} }
@ -265,12 +266,63 @@ namespace ix
} }
ERR_clear_error(); ERR_clear_error();
int cert_load_result = SSL_CTX_set_default_verify_paths(_ssl_context); if (_tlsOptions.isUsingClientCert())
if (cert_load_result == 0)
{ {
unsigned long ssl_err = ERR_get_error(); if (SSL_CTX_use_certificate_chain_file(_ssl_context,
errMsg = "OpenSSL failed - SSL_CTX_default_verify_paths loading failed: "; _tlsOptions.certFile.c_str()) != 1)
errMsg += ERR_error_string(ssl_err, nullptr); {
auto sslErr = ERR_get_error();
errMsg = "OpenSSL failed - SSL_CTX_use_certificate_chain_file(\"" +
_tlsOptions.certFile + "\") failed: ";
errMsg += ERR_error_string(sslErr, nullptr);
}
else if (SSL_CTX_use_PrivateKey_file(
_ssl_context, _tlsOptions.keyFile.c_str(), SSL_FILETYPE_PEM) != 1)
{
auto sslErr = ERR_get_error();
errMsg = "OpenSSL failed - SSL_CTX_use_PrivateKey_file(\"" +
_tlsOptions.keyFile + "\") failed: ";
errMsg += ERR_error_string(sslErr, nullptr);
}
}
ERR_clear_error();
if (!_tlsOptions.isPeerVerifyDisabled())
{
if (_tlsOptions.isUsingSystemDefaults())
{
if (SSL_CTX_set_default_verify_paths(_ssl_context) == 0)
{
auto sslErr = ERR_get_error();
errMsg = "OpenSSL failed - SSL_CTX_default_verify_paths loading failed: ";
errMsg += ERR_error_string(sslErr, nullptr);
}
}
else
{
const char* root_ca_file = _tlsOptions.caFile.c_str();
STACK_OF(X509_NAME) * rootCAs;
rootCAs = SSL_load_client_CA_file(root_ca_file);
if (rootCAs == NULL)
{
auto sslErr = ERR_get_error();
errMsg = "OpenSSL failed - SSL_load_client_CA_file('" + _tlsOptions.caFile +
"') failed: ";
errMsg += ERR_error_string(sslErr, nullptr);
}
else
{
SSL_CTX_set_client_CA_list(_ssl_context, rootCAs);
if (SSL_CTX_load_verify_locations(_ssl_context, root_ca_file, NULL) != 1)
{
auto sslErr = ERR_get_error();
errMsg = "OpenSSL failed - SSL_CTX_load_verify_locations(\"" +
_tlsOptions.caFile + "\") failed: ";
errMsg += ERR_error_string(sslErr, nullptr);
}
}
}
} }
_ssl_connection = SSL_new(_ssl_context); _ssl_connection = SSL_new(_ssl_context);
@ -291,10 +343,9 @@ namespace ix
// (The docs say that this should work from 1.0.2, and is the default from // (The docs say that this should work from 1.0.2, and is the default from
// 1.1.0, but it does not. To be on the safe side, the manual test below is // 1.1.0, but it does not. To be on the safe side, the manual test below is
// enabled for all versions prior to 1.1.0.) // enabled for all versions prior to 1.1.0.)
X509_VERIFY_PARAM *param = SSL_get0_param(_ssl_connection); X509_VERIFY_PARAM* param = SSL_get0_param(_ssl_connection);
X509_VERIFY_PARAM_set1_host(param, host.c_str(), 0); X509_VERIFY_PARAM_set1_host(param, host.c_str(), 0);
#endif #endif
handshakeSuccessful = openSSLHandshake(host, errMsg); handshakeSuccessful = openSSLHandshake(host, errMsg);
} }
@ -342,13 +393,18 @@ namespace ix
ssize_t write_result = SSL_write(_ssl_connection, buf + sent, (int) nbyte); ssize_t write_result = SSL_write(_ssl_connection, buf + sent, (int) nbyte);
int reason = SSL_get_error(_ssl_connection, (int) write_result); int reason = SSL_get_error(_ssl_connection, (int) write_result);
if (reason == SSL_ERROR_NONE) { if (reason == SSL_ERROR_NONE)
{
nbyte -= write_result; nbyte -= write_result;
sent += write_result; sent += write_result;
} else if (reason == SSL_ERROR_WANT_READ || reason == SSL_ERROR_WANT_WRITE) { }
else if (reason == SSL_ERROR_WANT_READ || reason == SSL_ERROR_WANT_WRITE)
{
errno = EWOULDBLOCK; errno = EWOULDBLOCK;
return -1; return -1;
} else { }
else
{
return -1; return -1;
} }
} }
@ -357,7 +413,7 @@ namespace ix
ssize_t SocketOpenSSL::send(const std::string& buffer) ssize_t SocketOpenSSL::send(const std::string& buffer)
{ {
return send((char*)&buffer[0], buffer.size()); return send((char*) &buffer[0], buffer.size());
} }
ssize_t SocketOpenSSL::recv(void* buf, size_t nbyte) ssize_t SocketOpenSSL::recv(void* buf, size_t nbyte)
@ -389,4 +445,4 @@ namespace ix
} }
} }
} } // namespace ix

View File

@ -8,6 +8,7 @@
#include "IXCancellationRequest.h" #include "IXCancellationRequest.h"
#include "IXSocket.h" #include "IXSocket.h"
#include "IXSocketTLSOptions.h"
#include <mutex> #include <mutex>
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/conf.h> #include <openssl/conf.h>
@ -20,7 +21,7 @@ namespace ix
class SocketOpenSSL final : public Socket class SocketOpenSSL final : public Socket
{ {
public: public:
SocketOpenSSL(int fd = -1); SocketOpenSSL(const SocketTLSOptions& tlsOptions, int fd = -1);
~SocketOpenSSL(); ~SocketOpenSSL();
virtual bool connect(const std::string& host, virtual bool connect(const std::string& host,
@ -44,6 +45,8 @@ namespace ix
SSL* _ssl_connection; SSL* _ssl_connection;
SSL_CTX* _ssl_context; SSL_CTX* _ssl_context;
const SSL_METHOD* _ssl_method; const SSL_METHOD* _ssl_method;
SocketTLSOptions _tlsOptions;
mutable std::mutex _mutex; // OpenSSL routines are not thread-safe mutable std::mutex _mutex; // OpenSSL routines are not thread-safe
static std::once_flag _openSSLInitFlag; static std::once_flag _openSSLInitFlag;

View File

@ -0,0 +1,34 @@
/*
* IXSocketTLSOptions.h
* Author: Benjamin Sergeant
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/
#include <assert.h>
#include "IXSocketTLSOptions.h"
namespace ix
{
SocketTLSOptions::SocketTLSOptions() {
#ifndef IXWEBSOCKET_USE_TLS
assert(false && "To use TLS features the library must be compiled with USE_TLS");
#endif
}
bool SocketTLSOptions::isUsingClientCert() const
{
return !certFile.empty() && !keyFile.empty();
}
bool SocketTLSOptions::isUsingSystemDefaults() const
{
return caFile == "SYSTEM";
}
bool SocketTLSOptions::isPeerVerifyDisabled() const
{
return caFile != "NONE";
}
} // namespace ix

View File

@ -0,0 +1,32 @@
/*
* IXSocketTLSOptions.h
* Author: Benjamin Sergeant
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/
#pragma once
#include <string>
namespace ix
{
struct SocketTLSOptions
{
SocketTLSOptions();
// the certificate presented to peers
std::string certFile;
// the key used for signing/encryption
std::string keyFile;
// the ca certificate (or certificate bundle) file containing
// certificates to be trusted by peers; use 'SYSTEM' to
// leverage the system defaults, use 'NONE' to disable peer verification
std::string caFile = "SYSTEM";
bool isUsingClientCert() const;
bool isUsingSystemDefaults() const;
bool isPeerVerifyDisabled() const;
};
} // namespace ix

View File

@ -73,6 +73,12 @@ namespace ix
_perMessageDeflateOptions = perMessageDeflateOptions; _perMessageDeflateOptions = perMessageDeflateOptions;
} }
void WebSocket::setTLSOptions(const SocketTLSOptions& socketTLSOptions)
{
std::lock_guard<std::mutex> lock(_configMutex);
_socketTLSOptions = socketTLSOptions;
}
const WebSocketPerMessageDeflateOptions& WebSocket::getPerMessageDeflateOptions() const const WebSocketPerMessageDeflateOptions& WebSocket::getPerMessageDeflateOptions() const
{ {
std::lock_guard<std::mutex> lock(_configMutex); std::lock_guard<std::mutex> lock(_configMutex);
@ -173,6 +179,7 @@ namespace ix
{ {
std::lock_guard<std::mutex> lock(_configMutex); std::lock_guard<std::mutex> lock(_configMutex);
_ws.configure(_perMessageDeflateOptions, _ws.configure(_perMessageDeflateOptions,
_socketTLSOptions,
_enablePong, _enablePong,
_pingIntervalSecs, _pingIntervalSecs,
_pingTimeoutSecs); _pingTimeoutSecs);
@ -198,6 +205,7 @@ namespace ix
{ {
std::lock_guard<std::mutex> lock(_configMutex); std::lock_guard<std::mutex> lock(_configMutex);
_ws.configure(_perMessageDeflateOptions, _ws.configure(_perMessageDeflateOptions,
_socketTLSOptions,
_enablePong, _enablePong,
_pingIntervalSecs, _pingIntervalSecs,
_pingTimeoutSecs); _pingTimeoutSecs);

View File

@ -10,6 +10,9 @@
#pragma once #pragma once
#include "IXProgressCallback.h" #include "IXProgressCallback.h"
#ifdef IXWEBSOCKET_USE_TLS
#include "IXSocketTLSOptions.h"
#endif
#include "IXWebSocketCloseConstants.h" #include "IXWebSocketCloseConstants.h"
#include "IXWebSocketErrorInfo.h" #include "IXWebSocketErrorInfo.h"
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"
@ -49,6 +52,7 @@ namespace ix
void setExtraHeaders(const WebSocketHttpHeaders& headers); void setExtraHeaders(const WebSocketHttpHeaders& headers);
void setPerMessageDeflateOptions( void setPerMessageDeflateOptions(
const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
void setHeartBeatPeriod(int heartBeatPeriodSecs); void setHeartBeatPeriod(int heartBeatPeriodSecs);
void setPingInterval(int pingIntervalSecs); // alias of setHeartBeatPeriod void setPingInterval(int pingIntervalSecs); // alias of setHeartBeatPeriod
void setPingTimeout(int pingTimeoutSecs); void setPingTimeout(int pingTimeoutSecs);
@ -119,6 +123,9 @@ namespace ix
WebSocketHttpHeaders _extraHeaders; WebSocketHttpHeaders _extraHeaders;
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
SocketTLSOptions _socketTLSOptions;
mutable std::mutex _configMutex; // protect all config variables access mutable std::mutex _configMutex; // protect all config variables access
OnMessageCallback _onMessageCallback; OnMessageCallback _onMessageCallback;

View File

@ -32,6 +32,7 @@
// Adapted from https://github.com/dhbaird/easywsclient // Adapted from https://github.com/dhbaird/easywsclient
// //
#include "IXSocketTLSOptions.h"
#include "IXWebSocketTransport.h" #include "IXWebSocketTransport.h"
#include "IXWebSocketHandshake.h" #include "IXWebSocketHandshake.h"
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"
@ -103,12 +104,14 @@ namespace ix
} }
void WebSocketTransport::configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, void WebSocketTransport::configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
const SocketTLSOptions& socketTLSOptions,
bool enablePong, bool enablePong,
int pingIntervalSecs, int pingIntervalSecs,
int pingTimeoutSecs) int pingTimeoutSecs)
{ {
_perMessageDeflateOptions = perMessageDeflateOptions; _perMessageDeflateOptions = perMessageDeflateOptions;
_enablePerMessageDeflate = _perMessageDeflateOptions.enabled(); _enablePerMessageDeflate = _perMessageDeflateOptions.enabled();
_socketTLSOptions = socketTLSOptions;
_enablePong = enablePong; _enablePong = enablePong;
_pingIntervalSecs = pingIntervalSecs; _pingIntervalSecs = pingIntervalSecs;
_pingTimeoutSecs = pingTimeoutSecs; _pingTimeoutSecs = pingTimeoutSecs;
@ -147,7 +150,7 @@ namespace ix
std::string errorMsg; std::string errorMsg;
bool tls = protocol == "wss"; bool tls = protocol == "wss";
_socket = createSocket(tls, errorMsg); _socket = createSocket(tls, errorMsg, _socketTLSOptions);
if (!_socket) if (!_socket)
{ {

View File

@ -12,6 +12,7 @@
#include "IXCancellationRequest.h" #include "IXCancellationRequest.h"
#include "IXProgressCallback.h" #include "IXProgressCallback.h"
#include "IXSocketTLSOptions.h"
#include "IXWebSocketCloseConstants.h" #include "IXWebSocketCloseConstants.h"
#include "IXWebSocketHandshake.h" #include "IXWebSocketHandshake.h"
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"
@ -72,6 +73,7 @@ namespace ix
~WebSocketTransport(); ~WebSocketTransport();
void configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, void configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
const SocketTLSOptions& socketTLSOptions,
bool enablePong, bool enablePong,
int pingIntervalSecs, int pingIntervalSecs,
int pingTimeoutSecs); int pingTimeoutSecs);
@ -181,6 +183,9 @@ namespace ix
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
std::atomic<bool> _enablePerMessageDeflate; std::atomic<bool> _enablePerMessageDeflate;
// Used to control TLS connection behavior
SocketTLSOptions _socketTLSOptions;
// Used to cancel dns lookup + socket connect + http upgrade // Used to cancel dns lookup + socket connect + http upgrade
std::atomic<bool> _requestInitCancellation; std::atomic<bool> _requestInitCancellation;