Compare commits

...

10 Commits

33 changed files with 441 additions and 93 deletions

4
.gitignore vendored
View File

@ -1,3 +1,7 @@
build build
*.pyc *.pyc
venv venv
ixsnake/ixsnake/.certs/
site/
ws/.certs/
ws/.srl

View File

@ -1,4 +1,4 @@
FROM alpine:edge as build FROM alpine:3.11 as build
RUN apk add --no-cache gcc g++ musl-dev linux-headers cmake openssl-dev RUN apk add --no-cache gcc g++ musl-dev linux-headers cmake openssl-dev
RUN apk add --no-cache make RUN apk add --no-cache make
@ -16,7 +16,7 @@ WORKDIR /opt
USER app USER app
RUN [ "make", "ws_install" ] RUN [ "make", "ws_install" ]
FROM alpine:edge as runtime FROM alpine:3.11 as runtime
RUN apk add --no-cache libstdc++ RUN apk add --no-cache libstdc++
RUN apk add --no-cache strace RUN apk add --no-cache strace

View File

@ -1,6 +1,34 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [7.6.3] - 2019-12-20
(tls) add a simple description of the TLS configuration routine for debugging
## [7.6.2] - 2019-12-20
(mbedtls) correct support for using own certificate and private key
## [7.6.1] - 2019-12-20
(ws commands) in websocket proxy, disable automatic reconnections + in Dockerfile, use alpine 3.11
## [7.6.0] - 2019-12-19
(cobra) Add TLS options to all cobra commands and classes. Add example to the doc.
## [7.5.8] - 2019-12-18
(cobra-to-sentry) capture application version from device field
## [7.5.7] - 2019-12-18
(tls) Experimental TLS server support with mbedtls (windows) + process cert tlsoption (client + server)
## [7.5.6] - 2019-12-18
(tls servers) Make it clear that apple ssl and mbedtls backends do not support SSL in server mode
## [7.5.5] - 2019-12-17 ## [7.5.5] - 2019-12-17
(tls options client) TLSOptions struct _validated member should be initialized to false (tls options client) TLSOptions struct _validated member should be initialized to false

View File

@ -243,6 +243,127 @@ Options:
--transfer-timeout INT Transfer timeout --transfer-timeout INT Transfer timeout
``` ```
## Cobra Client ## Cobra client and server
[cobra](https://github.com/machinezone/cobra) is a real time messenging server. ws has a sub-command to interact with cobra. [cobra](https://github.com/machinezone/cobra) is a real time messenging server. ws has several sub-command to interact with cobra. There is also a minimal cobra compatible server named snake available.
Below are examples on running a snake server and clients with TLS enabled (the server only works with the OpenSSL backend for now).
First, generate certificates.
```
$ cd /path/to/IXWebSocket
$ cd ixsnake/ixsnake
$ bash ../../ws/generate_certs.sh
Generating RSA private key, 2048 bit long modulus
.....+++
.................+++
e is 65537 (0x10001)
generated ./.certs/trusted-ca-key.pem
generated ./.certs/trusted-ca-crt.pem
Generating RSA private key, 2048 bit long modulus
..+++
.......................................+++
e is 65537 (0x10001)
generated ./.certs/trusted-server-key.pem
Signature ok
subject=/O=machinezone/O=IXWebSocket/CN=trusted-server
Getting CA Private Key
generated ./.certs/trusted-server-crt.pem
Generating RSA private key, 2048 bit long modulus
...................................+++
..................................................+++
e is 65537 (0x10001)
generated ./.certs/trusted-client-key.pem
Signature ok
subject=/O=machinezone/O=IXWebSocket/CN=trusted-client
Getting CA Private Key
generated ./.certs/trusted-client-crt.pem
Generating RSA private key, 2048 bit long modulus
..............+++
.......................................+++
e is 65537 (0x10001)
generated ./.certs/untrusted-ca-key.pem
generated ./.certs/untrusted-ca-crt.pem
Generating RSA private key, 2048 bit long modulus
..........+++
................................................+++
e is 65537 (0x10001)
generated ./.certs/untrusted-client-key.pem
Signature ok
subject=/O=machinezone/O=IXWebSocket/CN=untrusted-client
Getting CA Private Key
generated ./.certs/untrusted-client-crt.pem
Generating RSA private key, 2048 bit long modulus
.....................................................................................+++
...........+++
e is 65537 (0x10001)
generated ./.certs/selfsigned-client-key.pem
Signature ok
subject=/O=machinezone/O=IXWebSocket/CN=selfsigned-client
Getting Private key
generated ./.certs/selfsigned-client-crt.pem
```
Now run the snake server.
```
$ export certs=.certs
$ ws snake --tls --port 8765 --cert-file ${certs}/trusted-server-crt.pem --key-file ${certs}/trusted-server-key.pem --ca-file ${certs}/trusted-ca-crt.pem
{
"apps": {
"FC2F10139A2BAc53BB72D9db967b024f": {
"roles": {
"_sub": {
"secret": "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba"
},
"_pub": {
"secret": "1c04DB8fFe76A4EeFE3E318C72d771db"
}
}
}
}
}
redis host: 127.0.0.1
redis password:
redis port: 6379
```
As a new connection comes in, such output should be printed
```
[2019-12-19 20:27:19.724] [info] New connection
id: 0
Uri: /v2?appkey=_health
Headers:
Connection: Upgrade
Host: 127.0.0.1:8765
Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=15; client_max_window_bits=15
Sec-WebSocket-Key: d747B0fE61Db73f7Eh47c0==
Sec-WebSocket-Protocol: json
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: ixwebsocket/7.5.8 macos ssl/OpenSSL OpenSSL 1.0.2q 20 Nov 2018 zlib 1.2.11
```
To connect and publish a message, do:
```
$ export certs=.certs
$ cd /path/to/ws/folder
$ ls cobraMetricsSample.json
cobraMetricsSample.json
$ ws cobra_publish --endpoint wss://127.0.0.1:8765 --appkey FC2F10139A2BAc53BB72D9db967b024f --rolename _pub --rolesecret 1c04DB8fFe76A4EeFE3E318C72d771db --channel foo --cert-file ${certs}/trusted-client-crt.pem --key-file ${certs}/trusted-client-key.pem --ca-file ${certs}/trusted-ca-crt.pem cobraMetricsSample.json
[2019-12-19 20:46:42.656] [info] Publisher connected
[2019-12-19 20:46:42.657] [info] Connection: Upgrade
[2019-12-19 20:46:42.657] [info] Sec-WebSocket-Accept: rs99IFThoBrhSg+k8G4ixH9yaq4=
[2019-12-19 20:46:42.657] [info] Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=15; client_max_window_bits=15
[2019-12-19 20:46:42.657] [info] Server: ixwebsocket/7.5.8 macos ssl/OpenSSL OpenSSL 1.0.2q 20 Nov 2018 zlib 1.2.11
[2019-12-19 20:46:42.657] [info] Upgrade: websocket
[2019-12-19 20:46:42.658] [info] Publisher authenticated
[2019-12-19 20:46:42.658] [info] Published msg 3
[2019-12-19 20:46:42.659] [info] Published message id 3 acked
```
To use OpenSSL on macOS, compile with `make ws_openssl`. First you will have to install OpenSSL libraries, which can be done with Homebrew.

View File

@ -7,6 +7,7 @@
#include "IXCobraConnection.h" #include "IXCobraConnection.h"
#include <ixcrypto/IXHMac.h> #include <ixcrypto/IXHMac.h>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXSocketTLSOptions.h>
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
@ -244,7 +245,8 @@ namespace ix
const std::string& endpoint, const std::string& endpoint,
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions) const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
const SocketTLSOptions& socketTLSOptions)
{ {
_roleName = rolename; _roleName = rolename;
_roleSecret = rolesecret; _roleSecret = rolesecret;
@ -257,6 +259,7 @@ namespace ix
std::string url = ss.str(); std::string url = ss.str();
_webSocket->setUrl(url); _webSocket->setUrl(url);
_webSocket->setPerMessageDeflateOptions(webSocketPerMessageDeflateOptions); _webSocket->setPerMessageDeflateOptions(webSocketPerMessageDeflateOptions);
_webSocket->setTLSOptions(socketTLSOptions);
} }
// //

View File

@ -20,6 +20,7 @@
namespace ix namespace ix
{ {
class WebSocket; class WebSocket;
struct SocketTLSOptions;
enum CobraConnectionEventType enum CobraConnectionEventType
{ {
@ -62,7 +63,8 @@ namespace ix
const std::string& endpoint, const std::string& endpoint,
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions); const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
const SocketTLSOptions& socketTLSOptions);
/// Set the traffic tracker callback /// Set the traffic tracker callback
static void setTrafficTrackerCallback(const TrafficTrackerCallback& callback); static void setTrafficTrackerCallback(const TrafficTrackerCallback& callback);

View File

@ -5,6 +5,7 @@
*/ */
#include "IXCobraMetricsPublisher.h" #include "IXCobraMetricsPublisher.h"
#include <ixwebsocket/IXSocketTLSOptions.h>
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
@ -31,14 +32,15 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
bool enablePerMessageDeflate) bool enablePerMessageDeflate,
const SocketTLSOptions& socketTLSOptions)
{ {
// Configure the satori connection and start its publish background thread // Configure the satori connection and start its publish background thread
_cobra_metrics_theaded_publisher.start(); _cobra_metrics_theaded_publisher.start();
_cobra_metrics_theaded_publisher.configure(appkey, endpoint, channel, _cobra_metrics_theaded_publisher.configure(appkey, endpoint, channel,
rolename, rolesecret, rolename, rolesecret,
enablePerMessageDeflate); enablePerMessageDeflate, socketTLSOptions);
} }
Json::Value& CobraMetricsPublisher::getGenericAttributes() Json::Value& CobraMetricsPublisher::getGenericAttributes()

View File

@ -15,6 +15,8 @@
namespace ix namespace ix
{ {
struct SocketTLSOptions;
class CobraMetricsPublisher class CobraMetricsPublisher
{ {
public: public:
@ -43,7 +45,8 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
bool enablePerMessageDeflate); bool enablePerMessageDeflate,
const SocketTLSOptions& socketTLSOptions);
/// Setter for the list of blacklisted metrics ids. /// Setter for the list of blacklisted metrics ids.
/// That list is sorted internally for fast lookups /// That list is sorted internally for fast lookups

View File

@ -6,6 +6,7 @@
#include "IXCobraMetricsThreadedPublisher.h" #include "IXCobraMetricsThreadedPublisher.h"
#include <ixwebsocket/IXSetThreadName.h> #include <ixwebsocket/IXSetThreadName.h>
#include <ixwebsocket/IXSocketTLSOptions.h>
#include <ixcore/utils/IXCoreLogger.h> #include <ixcore/utils/IXCoreLogger.h>
#include <algorithm> #include <algorithm>
@ -92,14 +93,17 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
bool enablePerMessageDeflate) bool enablePerMessageDeflate,
const SocketTLSOptions& socketTLSOptions)
{ {
_channel = channel; _channel = channel;
ix::IXCoreLogger::Log(socketTLSOptions.getDescription().c_str());
ix::WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(enablePerMessageDeflate); ix::WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(enablePerMessageDeflate);
_cobra_connection.configure(appkey, endpoint, _cobra_connection.configure(appkey, endpoint,
rolename, rolesecret, rolename, rolesecret,
webSocketPerMessageDeflateOptions); webSocketPerMessageDeflateOptions, socketTLSOptions);
} }
void CobraMetricsThreadedPublisher::pushMessage(MessageKind messageKind) void CobraMetricsThreadedPublisher::pushMessage(MessageKind messageKind)

View File

@ -18,6 +18,8 @@
namespace ix namespace ix
{ {
struct SocketTLSOptions;
class CobraMetricsThreadedPublisher class CobraMetricsThreadedPublisher
{ {
public: public:
@ -30,7 +32,8 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
bool enablePerMessageDeflate); bool enablePerMessageDeflate,
const SocketTLSOptions& socketTLSOptions);
/// Start the worker thread, used for background publishing /// Start the worker thread, used for background publishing
void start(); void start();

View File

@ -182,7 +182,6 @@ namespace ix
Json::Value extra; Json::Value extra;
extra["cobra_event"] = msg; extra["cobra_event"] = msg;
extra["cobra_event"] = msg;
// Builtin tags // Builtin tags
Json::Value gameTag; Json::Value gameTag;
@ -200,6 +199,11 @@ namespace ix
environmentTag.append(msg["device"]["environment"]); environmentTag.append(msg["device"]["environment"]);
tags.append(environmentTag); tags.append(environmentTag);
Json::Value clientVersionTag;
clientVersionTag.append("client_version");
clientVersionTag.append(msg["device"]["app_version"]);
tags.append(clientVersionTag);
payload["tags"] = tags; payload["tags"] = tags;
return _jsonWriter.write(payload); return _jsonWriter.write(payload);

View File

@ -9,6 +9,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
#include <ixwebsocket/IXSocketTLSOptions.h>
namespace snake namespace snake
{ {
@ -26,6 +27,9 @@ namespace snake
// AppKeys // AppKeys
nlohmann::json apps; nlohmann::json apps;
// TLS options
ix::SocketTLSOptions socketTLSOptions;
// Misc // Misc
bool verbose; bool verbose;
}; };

View File

@ -20,7 +20,7 @@ namespace snake
: _appConfig(appConfig) : _appConfig(appConfig)
, _server(appConfig.port, appConfig.hostname) , _server(appConfig.port, appConfig.hostname)
{ {
; _server.setTLSOptions(appConfig.socketTLSOptions);
} }
// //

View File

@ -117,8 +117,7 @@ namespace
{ {
char localBuffer[128]; char localBuffer[128];
Boolean success; Boolean success;
success = success = CFStringGetCString(message, localBuffer, 128, kCFStringEncodingUTF8);
CFStringGetCString(message, localBuffer, 128, kCFStringEncodingUTF8);
if (success) if (success)
{ {
errMsg = localBuffer; errMsg = localBuffer;
@ -148,6 +147,12 @@ namespace ix
SocketAppleSSL::close(); SocketAppleSSL::close();
} }
bool SocketAppleSSL::accept(std::string& errMsg)
{
errMsg = "TLS not supported yet in server mode with apple ssl backend";
return false;
}
// No wait support // No wait support
bool SocketAppleSSL::connect(const std::string& host, bool SocketAppleSSL::connect(const std::string& host,
int port, int port,

View File

@ -21,6 +21,8 @@ namespace ix
SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd = -1); SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd = -1);
~SocketAppleSSL(); ~SocketAppleSSL();
virtual bool accept(std::string& errMsg) final;
virtual bool connect(const std::string& host, virtual bool connect(const std::string& host,
int port, int port,
std::string& errMsg, std::string& errMsg,

View File

@ -38,9 +38,10 @@ namespace ix
mbedtls_ctr_drbg_init(&_ctr_drbg); mbedtls_ctr_drbg_init(&_ctr_drbg);
mbedtls_entropy_init(&_entropy); mbedtls_entropy_init(&_entropy);
mbedtls_x509_crt_init(&_cacert); mbedtls_x509_crt_init(&_cacert);
mbedtls_x509_crt_init(&_cert);
} }
bool SocketMbedTLS::init(const std::string& host, std::string& errMsg) bool SocketMbedTLS::init(const std::string& host, bool isClient, std::string& errMsg)
{ {
initMBedTLS(); initMBedTLS();
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
@ -58,7 +59,7 @@ namespace ix
} }
if (mbedtls_ssl_config_defaults(&_conf, if (mbedtls_ssl_config_defaults(&_conf,
MBEDTLS_SSL_IS_CLIENT, (isClient) ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT) != 0) MBEDTLS_SSL_PRESET_DEFAULT) != 0)
{ {
@ -68,13 +69,27 @@ namespace ix
mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg);
if (_tlsOptions.hasCertAndKey())
{
if (mbedtls_x509_crt_parse_file(&_cert, _tlsOptions.certFile.c_str()) < 0)
{
errMsg = "Cannot parse cert file '" + _tlsOptions.certFile + "'";
return false;
}
if (mbedtls_pk_parse_keyfile(&_pkey, _tlsOptions.keyFile.c_str(), "") < 0)
{
errMsg = "Cannot parse key file '" + _tlsOptions.keyFile + "'";
return false;
}
}
if (_tlsOptions.isPeerVerifyDisabled()) if (_tlsOptions.isPeerVerifyDisabled())
{ {
mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_NONE);
} }
else else
{ {
mbedtls_ssl_conf_ca_chain(&_conf, &_cacert, NULL); mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
// FIXME: should we call mbedtls_ssl_conf_verify ? // FIXME: should we call mbedtls_ssl_conf_verify ?
@ -87,7 +102,13 @@ namespace ix
errMsg = "Cannot parse CA file '" + _tlsOptions.caFile + "'"; errMsg = "Cannot parse CA file '" + _tlsOptions.caFile + "'";
return false; return false;
} }
mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_ca_chain(&_conf, &_cacert, NULL);
if (_tlsOptions.hasCertAndKey())
{
mbedtls_ssl_conf_own_cert(&_conf, &_cert, &_pkey);
}
} }
if (mbedtls_ssl_setup(&_ssl, &_conf) != 0) if (mbedtls_ssl_setup(&_ssl, &_conf) != 0)
@ -96,7 +117,7 @@ namespace ix
return false; return false;
} }
if (mbedtls_ssl_set_hostname(&_ssl, host.c_str()) != 0) if (!host.empty() && mbedtls_ssl_set_hostname(&_ssl, host.c_str()) != 0)
{ {
errMsg = "SNI setup failed"; errMsg = "SNI setup failed";
return false; return false;
@ -105,6 +126,50 @@ namespace ix
return true; return true;
} }
bool SocketMbedTLS::accept(std::string& errMsg)
{
bool isClient = false;
bool initialized = init(std::string(), isClient, errMsg);
if (!initialized)
{
close();
return false;
}
mbedtls_ssl_set_bio(&_ssl, &_sockfd, mbedtls_net_send, mbedtls_net_recv, NULL);
int res;
do
{
std::lock_guard<std::mutex> lock(_mutex);
res = mbedtls_ssl_handshake(&_ssl);
} while (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE);
if (res != 0)
{
char buf[256];
mbedtls_strerror(res, buf, sizeof(buf));
errMsg = "error in handshake : ";
errMsg += buf;
if (res == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED)
{
char verifyBuf[512];
uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl);
mbedtls_x509_crt_verify_info(verifyBuf, sizeof(verifyBuf), " ! ", flags);
errMsg += " : ";
errMsg += verifyBuf;
}
close();
return false;
}
return true;
}
bool SocketMbedTLS::connect(const std::string& host, bool SocketMbedTLS::connect(const std::string& host,
int port, int port,
std::string& errMsg, std::string& errMsg,
@ -116,7 +181,8 @@ namespace ix
if (_sockfd == -1) return false; if (_sockfd == -1) return false;
} }
bool initialized = init(host, errMsg); bool isClient = true;
bool initialized = init(host, isClient, errMsg);
if (!initialized) if (!initialized)
{ {
close(); close();
@ -156,6 +222,7 @@ namespace ix
mbedtls_ctr_drbg_free(&_ctr_drbg); mbedtls_ctr_drbg_free(&_ctr_drbg);
mbedtls_entropy_free(&_entropy); mbedtls_entropy_free(&_entropy);
mbedtls_x509_crt_free(&_cacert); mbedtls_x509_crt_free(&_cacert);
mbedtls_x509_crt_free(&_cert);
Socket::close(); Socket::close();
} }

View File

@ -26,6 +26,8 @@ namespace ix
SocketMbedTLS(const SocketTLSOptions& tlsOptions, int fd = -1); SocketMbedTLS(const SocketTLSOptions& tlsOptions, int fd = -1);
~SocketMbedTLS(); ~SocketMbedTLS();
virtual bool accept(std::string& errMsg) final;
virtual bool connect(const std::string& host, virtual bool connect(const std::string& host,
int port, int port,
std::string& errMsg, std::string& errMsg,
@ -42,11 +44,13 @@ namespace ix
mbedtls_entropy_context _entropy; mbedtls_entropy_context _entropy;
mbedtls_ctr_drbg_context _ctr_drbg; mbedtls_ctr_drbg_context _ctr_drbg;
mbedtls_x509_crt _cacert; mbedtls_x509_crt _cacert;
mbedtls_x509_crt _cert;
mbedtls_pk_context _pkey;
std::mutex _mutex; std::mutex _mutex;
SocketTLSOptions _tlsOptions; SocketTLSOptions _tlsOptions;
bool init(const std::string& host, std::string& errMsg); bool init(const std::string& host, bool isClient, std::string& errMsg);
void initMBedTLS(); void initMBedTLS();
}; };

View File

@ -8,6 +8,7 @@
#include <assert.h> #include <assert.h>
#include <fstream> #include <fstream>
#include <sstream>
namespace ix namespace ix
{ {
@ -71,4 +72,15 @@ namespace ix
{ {
return _errMsg; return _errMsg;
} }
std::string SocketTLSOptions::getDescription() const
{
std::stringstream ss;
ss << "TLS Options:" << std::endl;
ss << " certFile = " << certFile << std::endl;
ss << " keyFile = " << keyFile << std::endl;
ss << " caFile = " << caFile << std::endl;
ss << " ciphers = " << ciphers << std::endl;
return ss.str();
}
} // namespace ix } // namespace ix

View File

@ -43,6 +43,8 @@ namespace ix
const std::string& getErrorMsg() const; const std::string& getErrorMsg() const;
std::string getDescription() const;
private: private:
mutable std::string _errMsg; mutable std::string _errMsg;
mutable bool _validated = false; mutable bool _validated = false;

View File

@ -6,4 +6,4 @@
#pragma once #pragma once
#define IX_WEBSOCKET_VERSION "7.5.5" #define IX_WEBSOCKET_VERSION "7.6.3"

View File

@ -34,10 +34,10 @@ namespace
}); });
} }
class SatoriChat class CobraChat
{ {
public: public:
SatoriChat(const std::string& user, CobraChat(const std::string& user,
const std::string& session, const std::string& session,
const std::string& endpoint); const std::string& endpoint);
@ -72,9 +72,9 @@ namespace
std::mutex _logMutex; std::mutex _logMutex;
}; };
SatoriChat::SatoriChat(const std::string& user, CobraChat::CobraChat(const std::string& user,
const std::string& session, const std::string& session,
const std::string& endpoint) const std::string& endpoint)
: _user(user) : _user(user)
, _session(session) , _session(session)
, _endpoint(endpoint) , _endpoint(endpoint)
@ -83,34 +83,34 @@ namespace
{ {
} }
void SatoriChat::start() void CobraChat::start()
{ {
_thread = std::thread(&SatoriChat::run, this); _thread = std::thread(&CobraChat::run, this);
} }
void SatoriChat::stop() void CobraChat::stop()
{ {
_stop = true; _stop = true;
_thread.join(); _thread.join();
} }
bool SatoriChat::isReady() const bool CobraChat::isReady() const
{ {
return _connectedAndSubscribed; return _connectedAndSubscribed;
} }
size_t SatoriChat::getReceivedMessagesCount() const size_t CobraChat::getReceivedMessagesCount() const
{ {
return _receivedQueue.size(); return _receivedQueue.size();
} }
bool SatoriChat::hasPendingMessages() const bool CobraChat::hasPendingMessages() const
{ {
std::unique_lock<std::mutex> lock(_queue_mutex); std::unique_lock<std::mutex> lock(_queue_mutex);
return !_publish_queue.empty(); return !_publish_queue.empty();
} }
Json::Value SatoriChat::popMessage() Json::Value CobraChat::popMessage()
{ {
std::unique_lock<std::mutex> lock(_queue_mutex); std::unique_lock<std::mutex> lock(_queue_mutex);
auto msg = _publish_queue.front(); auto msg = _publish_queue.front();
@ -121,7 +121,7 @@ namespace
// //
// Callback to handle received messages, that are printed on the console // Callback to handle received messages, that are printed on the console
// //
void SatoriChat::subscribe(const std::string& channel) void CobraChat::subscribe(const std::string& channel)
{ {
std::string filter; std::string filter;
_conn.subscribe(channel, filter, [this](const Json::Value& msg) { _conn.subscribe(channel, filter, [this](const Json::Value& msg) {
@ -151,7 +151,7 @@ namespace
}); });
} }
void SatoriChat::sendMessage(const std::string& text) void CobraChat::sendMessage(const std::string& text)
{ {
Json::Value msg; Json::Value msg;
msg["user"] = _user; msg["user"] = _user;
@ -166,16 +166,21 @@ namespace
// Do satori communication on a background thread, where we can have // Do satori communication on a background thread, where we can have
// something like an event loop that publish, poll and receive data // something like an event loop that publish, poll and receive data
// //
void SatoriChat::run() void CobraChat::run()
{ {
// "chat" conf // "chat" conf
std::string appkey("FC2F10139A2BAc53BB72D9db967b024f"); std::string appkey("FC2F10139A2BAc53BB72D9db967b024f");
std::string channel = _session; std::string channel = _session;
std::string role = "_sub"; std::string role = "_sub";
std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba"; std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba";
SocketTLSOptions socketTLSOptions;
_conn.configure( _conn.configure(appkey,
appkey, _endpoint, role, secret, ix::WebSocketPerMessageDeflateOptions(true)); _endpoint,
role,
secret,
ix::WebSocketPerMessageDeflateOptions(true),
socketTLSOptions);
_conn.connect(); _conn.connect();
_conn.setEventCallback([this, channel](ix::CobraConnectionEventType eventType, _conn.setEventCallback([this, channel](ix::CobraConnectionEventType eventType,
@ -280,8 +285,8 @@ TEST_CASE("Cobra_chat", "[cobra_chat]")
ss << "ws://localhost:" << port; ss << "ws://localhost:" << port;
std::string endpoint = ss.str(); std::string endpoint = ss.str();
SatoriChat chatA("jean", session, endpoint); CobraChat chatA("jean", session, endpoint);
SatoriChat chatB("paul", session, endpoint); CobraChat chatB("paul", session, endpoint);
chatA.start(); chatA.start();
chatB.start(); chatB.start();

View File

@ -62,11 +62,14 @@ namespace
gMessageCount = 0; gMessageCount = 0;
ix::CobraConnection conn; ix::CobraConnection conn;
SocketTLSOptions socketTLSOptions;
conn.configure(APPKEY, conn.configure(APPKEY,
endpoint, endpoint,
SUBSCRIBER_ROLE, SUBSCRIBER_ROLE,
SUBSCRIBER_SECRET, SUBSCRIBER_SECRET,
ix::WebSocketPerMessageDeflateOptions(true)); ix::WebSocketPerMessageDeflateOptions(true),
socketTLSOptions);
conn.connect(); conn.connect();
conn.setEventCallback([&conn](ix::CobraConnectionEventType eventType, conn.setEventCallback([&conn](ix::CobraConnectionEventType eventType,
@ -202,9 +205,15 @@ TEST_CASE("Cobra_Metrics_Publisher", "[cobra]")
ix::CobraMetricsPublisher cobraMetricsPublisher; ix::CobraMetricsPublisher cobraMetricsPublisher;
SocketTLSOptions socketTLSOptions;
bool perMessageDeflate = true; bool perMessageDeflate = true;
cobraMetricsPublisher.configure( cobraMetricsPublisher.configure(APPKEY,
APPKEY, endpoint, CHANNEL, PUBLISHER_ROLE, PUBLISHER_SECRET, perMessageDeflate); endpoint,
CHANNEL,
PUBLISHER_ROLE,
PUBLISHER_SECRET,
perMessageDeflate,
socketTLSOptions);
cobraMetricsPublisher.setSession(uuid4()); cobraMetricsPublisher.setSession(uuid4());
cobraMetricsPublisher.enable(true); // disabled by default, needs to be enabled to be active cobraMetricsPublisher.enable(true); // disabled by default, needs to be enabled to be active

View File

@ -53,7 +53,7 @@ done
# Start a receiver # Start a receiver
mkdir -p /tmp/ws_test/receive mkdir -p /tmp/ws_test/receive
cd /tmp/ws_test/receive cd /tmp/ws_test/receive
ws receive "${protocol}127.0.0.1:8090" ${delay} --pidfile /tmp/ws_test/pidfile.receive ${server_tls} & ws receive "${protocol}127.0.0.1:8090" ${delay} --pidfile /tmp/ws_test/pidfile.receive ${client_tls} &
mkdir -p /tmp/ws_test/send mkdir -p /tmp/ws_test/send
cd /tmp/ws_test/send cd /tmp/ws_test/send

View File

@ -218,6 +218,7 @@ int main(int argc, char** argv)
cobraSubscribeApp->add_option("--pidfile", pidfile, "Pid file"); cobraSubscribeApp->add_option("--pidfile", pidfile, "Pid file");
cobraSubscribeApp->add_option("--filter", filter, "Stream SQL Filter"); cobraSubscribeApp->add_option("--filter", filter, "Stream SQL Filter");
cobraSubscribeApp->add_flag("-q", quiet, "Quiet / only display stats"); cobraSubscribeApp->add_flag("-q", quiet, "Quiet / only display stats");
addTLSOptions(cobraSubscribeApp);
CLI::App* cobraPublish = app.add_subcommand("cobra_publish", "Cobra publisher"); CLI::App* cobraPublish = app.add_subcommand("cobra_publish", "Cobra publisher");
cobraPublish->add_option("--appkey", appkey, "Appkey")->required(); cobraPublish->add_option("--appkey", appkey, "Appkey")->required();
@ -229,6 +230,7 @@ int main(int argc, char** argv)
cobraPublish->add_option("path", path, "Path to the file to send") cobraPublish->add_option("path", path, "Path to the file to send")
->required() ->required()
->check(CLI::ExistingPath); ->check(CLI::ExistingPath);
addTLSOptions(cobraPublish);
CLI::App* cobraMetricsPublish = CLI::App* cobraMetricsPublish =
app.add_subcommand("cobra_metrics_publish", "Cobra metrics publisher"); app.add_subcommand("cobra_metrics_publish", "Cobra metrics publisher");
@ -242,6 +244,7 @@ int main(int argc, char** argv)
->required() ->required()
->check(CLI::ExistingPath); ->check(CLI::ExistingPath);
cobraMetricsPublish->add_flag("--stress", stress, "Stress mode"); cobraMetricsPublish->add_flag("--stress", stress, "Stress mode");
addTLSOptions(cobraMetricsPublish);
CLI::App* cobra2statsd = app.add_subcommand("cobra_to_statsd", "Cobra metrics to statsd"); CLI::App* cobra2statsd = app.add_subcommand("cobra_to_statsd", "Cobra metrics to statsd");
cobra2statsd->add_option("--appkey", appkey, "Appkey"); cobra2statsd->add_option("--appkey", appkey, "Appkey");
@ -256,6 +259,7 @@ int main(int argc, char** argv)
cobra2statsd->add_flag("-v", verbose, "Verbose"); cobra2statsd->add_flag("-v", verbose, "Verbose");
cobra2statsd->add_option("--pidfile", pidfile, "Pid file"); cobra2statsd->add_option("--pidfile", pidfile, "Pid file");
cobra2statsd->add_option("--filter", filter, "Stream SQL Filter"); cobra2statsd->add_option("--filter", filter, "Stream SQL Filter");
addTLSOptions(cobra2statsd);
CLI::App* cobra2sentry = app.add_subcommand("cobra_to_sentry", "Cobra metrics to sentry"); CLI::App* cobra2sentry = app.add_subcommand("cobra_to_sentry", "Cobra metrics to sentry");
cobra2sentry->add_option("--appkey", appkey, "Appkey")->required(); cobra2sentry->add_option("--appkey", appkey, "Appkey")->required();
@ -269,6 +273,7 @@ int main(int argc, char** argv)
cobra2sentry->add_flag("-s", strict, "Strict mode. Error out when sending to sentry fails"); cobra2sentry->add_flag("-s", strict, "Strict mode. Error out when sending to sentry fails");
cobra2sentry->add_option("--pidfile", pidfile, "Pid file"); cobra2sentry->add_option("--pidfile", pidfile, "Pid file");
cobra2sentry->add_option("--filter", filter, "Stream SQL Filter"); cobra2sentry->add_option("--filter", filter, "Stream SQL Filter");
addTLSOptions(cobra2sentry);
CLI::App* cobra2redisApp = CLI::App* cobra2redisApp =
app.add_subcommand("cobra_metrics_to_redis", "Cobra metrics to redis"); app.add_subcommand("cobra_metrics_to_redis", "Cobra metrics to redis");
@ -282,17 +287,19 @@ int main(int argc, char** argv)
cobra2redisApp->add_option("--hostname", hostname, "Redis hostname"); cobra2redisApp->add_option("--hostname", hostname, "Redis hostname");
cobra2redisApp->add_option("--port", redisPort, "Redis port"); cobra2redisApp->add_option("--port", redisPort, "Redis port");
cobra2redisApp->add_flag("-q", quiet, "Quiet / only display stats"); cobra2redisApp->add_flag("-q", quiet, "Quiet / only display stats");
addTLSOptions(cobra2redisApp);
CLI::App* runApp = app.add_subcommand("snake", "Snake server"); CLI::App* snakeApp = app.add_subcommand("snake", "Snake server");
runApp->add_option("--port", port, "Connection url"); snakeApp->add_option("--port", port, "Connection url");
runApp->add_option("--host", hostname, "Hostname"); snakeApp->add_option("--host", hostname, "Hostname");
runApp->add_option("--pidfile", pidfile, "Pid file"); snakeApp->add_option("--pidfile", pidfile, "Pid file");
runApp->add_option("--redis_hosts", redisHosts, "Redis hosts"); snakeApp->add_option("--redis_hosts", redisHosts, "Redis hosts");
runApp->add_option("--redis_port", redisPort, "Redis hosts"); snakeApp->add_option("--redis_port", redisPort, "Redis hosts");
runApp->add_option("--redis_password", redisPassword, "Redis password"); snakeApp->add_option("--redis_password", redisPassword, "Redis password");
runApp->add_option("--apps_config_path", appsConfigPath, "Path to auth data") snakeApp->add_option("--apps_config_path", appsConfigPath, "Path to auth data")
->check(CLI::ExistingPath); ->check(CLI::ExistingPath);
runApp->add_flag("-v", verbose, "Verbose"); snakeApp->add_flag("-v", verbose, "Verbose");
addTLSOptions(snakeApp);
CLI::App* httpServerApp = app.add_subcommand("httpd", "HTTP server"); CLI::App* httpServerApp = app.add_subcommand("httpd", "HTTP server");
httpServerApp->add_option("--port", port, "Port"); httpServerApp->add_option("--port", port, "Port");
@ -314,6 +321,7 @@ int main(int argc, char** argv)
proxyServerApp->add_option("--host", hostname, "Hostname"); proxyServerApp->add_option("--host", hostname, "Hostname");
proxyServerApp->add_option("--remote_host", remoteHost, "Remote Hostname"); proxyServerApp->add_option("--remote_host", remoteHost, "Remote Hostname");
proxyServerApp->add_flag("-v", verbose, "Verbose"); proxyServerApp->add_flag("-v", verbose, "Verbose");
addTLSOptions(proxyServerApp);
CLI::App* minidumpApp = app.add_subcommand("upload_minidump", "Upload a minidump to sentry"); CLI::App* minidumpApp = app.add_subcommand("upload_minidump", "Upload a minidump to sentry");
minidumpApp->add_option("--minidump", minidump, "Minidump path")->check(CLI::ExistingPath); minidumpApp->add_option("--minidump", minidump, "Minidump path")->check(CLI::ExistingPath);
@ -408,16 +416,17 @@ int main(int argc, char** argv)
else if (app.got_subcommand("cobra_subscribe")) else if (app.got_subcommand("cobra_subscribe"))
{ {
ret = ix::ws_cobra_subscribe_main( ret = ix::ws_cobra_subscribe_main(
appkey, endpoint, rolename, rolesecret, channel, filter, quiet); appkey, endpoint, rolename, rolesecret, channel, filter, quiet, tlsOptions);
} }
else if (app.got_subcommand("cobra_publish")) else if (app.got_subcommand("cobra_publish"))
{ {
ret = ix::ws_cobra_publish_main(appkey, endpoint, rolename, rolesecret, channel, path); ret = ix::ws_cobra_publish_main(
appkey, endpoint, rolename, rolesecret, channel, path, tlsOptions);
} }
else if (app.got_subcommand("cobra_metrics_publish")) else if (app.got_subcommand("cobra_metrics_publish"))
{ {
ret = ix::ws_cobra_metrics_publish_main( ret = ix::ws_cobra_metrics_publish_main(
appkey, endpoint, rolename, rolesecret, channel, path, stress); appkey, endpoint, rolename, rolesecret, channel, path, stress, tlsOptions);
} }
else if (app.got_subcommand("cobra_to_statsd")) else if (app.got_subcommand("cobra_to_statsd"))
{ {
@ -431,22 +440,39 @@ int main(int argc, char** argv)
statsdPort, statsdPort,
prefix, prefix,
fields, fields,
verbose); verbose,
tlsOptions);
} }
else if (app.got_subcommand("cobra_to_sentry")) else if (app.got_subcommand("cobra_to_sentry"))
{ {
ret = ix::ws_cobra_to_sentry_main( ret = ix::ws_cobra_to_sentry_main(appkey,
appkey, endpoint, rolename, rolesecret, channel, filter, dsn, verbose, strict, jobs); endpoint,
rolename,
rolesecret,
channel,
filter,
dsn,
verbose,
strict,
jobs,
tlsOptions);
} }
else if (app.got_subcommand("cobra_metrics_to_redis")) else if (app.got_subcommand("cobra_metrics_to_redis"))
{ {
ret = ix::ws_cobra_metrics_to_redis( ret = ix::ws_cobra_metrics_to_redis(appkey,
appkey, endpoint, rolename, rolesecret, channel, filter, hostname, redisPort); endpoint,
rolename,
rolesecret,
channel,
filter,
hostname,
redisPort,
tlsOptions);
} }
else if (app.got_subcommand("snake")) else if (app.got_subcommand("snake"))
{ {
ret = ix::ws_snake_main( ret = ix::ws_snake_main(
port, hostname, redisHosts, redisPort, redisPassword, verbose, appsConfigPath); port, hostname, redisHosts, redisPort, redisPassword, verbose, appsConfigPath, tlsOptions);
} }
else if (app.got_subcommand("httpd")) else if (app.got_subcommand("httpd"))
{ {

21
ws/ws.h
View File

@ -76,14 +76,16 @@ namespace ix
const std::string& rolesecret, const std::string& rolesecret,
const std::string& channel, const std::string& channel,
const std::string& filter, const std::string& filter,
bool quiet); bool quiet,
const ix::SocketTLSOptions& tlsOptions);
int ws_cobra_publish_main(const std::string& appkey, int ws_cobra_publish_main(const std::string& appkey,
const std::string& endpoint, const std::string& endpoint,
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
const std::string& channel, const std::string& channel,
const std::string& path); const std::string& path,
const ix::SocketTLSOptions& tlsOptions);
int ws_cobra_metrics_publish_main(const std::string& appkey, int ws_cobra_metrics_publish_main(const std::string& appkey,
const std::string& endpoint, const std::string& endpoint,
@ -91,7 +93,8 @@ namespace ix
const std::string& rolesecret, const std::string& rolesecret,
const std::string& channel, const std::string& channel,
const std::string& path, const std::string& path,
bool stress); bool stress,
const ix::SocketTLSOptions& tlsOptions);
int ws_cobra_to_statsd_main(const std::string& appkey, int ws_cobra_to_statsd_main(const std::string& appkey,
const std::string& endpoint, const std::string& endpoint,
@ -103,7 +106,8 @@ namespace ix
int port, int port,
const std::string& prefix, const std::string& prefix,
const std::string& fields, const std::string& fields,
bool verbose); bool verbose,
const ix::SocketTLSOptions& tlsOptions);
int ws_cobra_to_sentry_main(const std::string& appkey, int ws_cobra_to_sentry_main(const std::string& appkey,
const std::string& endpoint, const std::string& endpoint,
@ -114,7 +118,8 @@ namespace ix
const std::string& dsn, const std::string& dsn,
bool verbose, bool verbose,
bool strict, bool strict,
int jobs); int jobs,
const ix::SocketTLSOptions& tlsOptions);
int ws_cobra_metrics_to_redis(const std::string& appkey, int ws_cobra_metrics_to_redis(const std::string& appkey,
const std::string& endpoint, const std::string& endpoint,
@ -123,7 +128,8 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& filter, const std::string& filter,
const std::string& host, const std::string& host,
int port); int port,
const ix::SocketTLSOptions& tlsOptions);
int ws_snake_main(int port, int ws_snake_main(int port,
const std::string& hostname, const std::string& hostname,
@ -131,7 +137,8 @@ namespace ix
int redisPort, int redisPort,
const std::string& redisPassword, const std::string& redisPassword,
bool verbose, bool verbose,
const std::string& appsConfigPath); const std::string& appsConfigPath,
const ix::SocketTLSOptions& tlsOptions);
int ws_httpd_main(int port, int ws_httpd_main(int port,
const std::string& hostname, const std::string& hostname,

View File

@ -22,7 +22,8 @@ namespace ix
const std::string& rolesecret, const std::string& rolesecret,
const std::string& channel, const std::string& channel,
const std::string& path, const std::string& path,
bool stress) bool stress,
const ix::SocketTLSOptions& tlsOptions)
{ {
std::atomic<int> sentMessages(0); std::atomic<int> sentMessages(0);
std::atomic<int> ackedMessages(0); std::atomic<int> ackedMessages(0);
@ -37,7 +38,7 @@ namespace ix
bool enablePerMessageDeflate = true; bool enablePerMessageDeflate = true;
cobraMetricsPublisher.configure( cobraMetricsPublisher.configure(
appkey, endpoint, channel, rolename, rolesecret, enablePerMessageDeflate); appkey, endpoint, channel, rolename, rolesecret, enablePerMessageDeflate, tlsOptions);
while (!cobraMetricsPublisher.isAuthenticated()) while (!cobraMetricsPublisher.isAuthenticated())
; ;

View File

@ -25,11 +25,16 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& filter, const std::string& filter,
const std::string& host, const std::string& host,
int port) int port,
const ix::SocketTLSOptions& tlsOptions)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure( conn.configure(appkey,
appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); endpoint,
rolename,
rolesecret,
ix::WebSocketPerMessageDeflateOptions(true),
tlsOptions);
conn.connect(); conn.connect();
// Display incoming messages // Display incoming messages

View File

@ -22,7 +22,8 @@ namespace ix
const std::string& rolename, const std::string& rolename,
const std::string& rolesecret, const std::string& rolesecret,
const std::string& channel, const std::string& channel,
const std::string& path) const std::string& path,
const ix::SocketTLSOptions& tlsOptions)
{ {
std::ifstream f(path); std::ifstream f(path);
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
@ -36,8 +37,12 @@ namespace ix
} }
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure( conn.configure(appkey,
appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); endpoint,
rolename,
rolesecret,
ix::WebSocketPerMessageDeflateOptions(true),
tlsOptions);
conn.connect(); conn.connect();
// Display incoming messages // Display incoming messages

View File

@ -20,11 +20,16 @@ namespace ix
const std::string& rolesecret, const std::string& rolesecret,
const std::string& channel, const std::string& channel,
const std::string& filter, const std::string& filter,
bool quiet) bool quiet,
const ix::SocketTLSOptions& tlsOptions)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure( conn.configure(appkey,
appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); endpoint,
rolename,
rolesecret,
ix::WebSocketPerMessageDeflateOptions(true),
tlsOptions);
conn.connect(); conn.connect();
Json::FastWriter jsonWriter; Json::FastWriter jsonWriter;

View File

@ -28,11 +28,16 @@ namespace ix
const std::string& dsn, const std::string& dsn,
bool verbose, bool verbose,
bool strict, bool strict,
int jobs) int jobs,
const ix::SocketTLSOptions& tlsOptions)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure( conn.configure(appkey,
appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); endpoint,
rolename,
rolesecret,
ix::WebSocketPerMessageDeflateOptions(true),
tlsOptions);
conn.connect(); conn.connect();
Json::FastWriter jsonWriter; Json::FastWriter jsonWriter;
@ -132,11 +137,13 @@ namespace ix
{ {
seconds = 30; seconds = 30;
spdlog::warn("Error parsing Retry-After header. " spdlog::warn("Error parsing Retry-After header. "
"Using {} for the sleep duration", seconds); "Using {} for the sleep duration",
seconds);
} }
spdlog::warn("Error 429 - Too Many Requests. ws will sleep " spdlog::warn("Error 429 - Too Many Requests. ws will sleep "
"and retry after {} seconds", retryAfter); "and retry after {} seconds",
retryAfter);
throttled = true; throttled = true;
auto duration = std::chrono::seconds(seconds); auto duration = std::chrono::seconds(seconds);

View File

@ -66,11 +66,16 @@ namespace ix
int port, int port,
const std::string& prefix, const std::string& prefix,
const std::string& fields, const std::string& fields,
bool verbose) bool verbose,
const ix::SocketTLSOptions& tlsOptions)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure( conn.configure(appkey,
appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); endpoint,
rolename,
rolesecret,
ix::WebSocketPerMessageDeflateOptions(true),
tlsOptions);
conn.connect(); conn.connect();
auto tokens = parseFields(fields); auto tokens = parseFields(fields);

View File

@ -61,7 +61,7 @@ namespace ix
// Server connection // Server connection
state->webSocket().setOnMessageCallback([webSocket, state, verbose]( state->webSocket().setOnMessageCallback([webSocket, state, verbose](
const WebSocketMessagePtr& msg) { const WebSocketMessagePtr& msg) {
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
std::cerr << "New connection" << std::endl; std::cerr << "New connection" << std::endl;
@ -120,6 +120,7 @@ namespace ix
std::string url(remoteUrl); std::string url(remoteUrl);
url += msg->openInfo.uri; url += msg->openInfo.uri;
state->webSocket().setUrl(url); state->webSocket().setUrl(url);
state->webSocket().disableAutomaticReconnection();
state->webSocket().start(); state->webSocket().start();
// we should sleep here for a bit until we've established the // we should sleep here for a bit until we've established the

View File

@ -43,7 +43,8 @@ namespace ix
int redisPort, int redisPort,
const std::string& redisPassword, const std::string& redisPassword,
bool verbose, bool verbose,
const std::string& appsConfigPath) const std::string& appsConfigPath,
const SocketTLSOptions& socketTLSOptions)
{ {
snake::AppConfig appConfig; snake::AppConfig appConfig;
appConfig.port = port; appConfig.port = port;
@ -51,6 +52,7 @@ namespace ix
appConfig.verbose = verbose; appConfig.verbose = verbose;
appConfig.redisPort = redisPort; appConfig.redisPort = redisPort;
appConfig.redisPassword = redisPassword; appConfig.redisPassword = redisPassword;
appConfig.socketTLSOptions = socketTLSOptions;
// Parse config file // Parse config file
auto str = readAsString(appsConfigPath); auto str = readAsString(appsConfigPath);