Compare commits
	
		
			18 Commits
		
	
	
		
			v7.5.5
			...
			feature/ma
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8192da790f | ||
| 
						 | 
					33e7271b85 | ||
| 
						 | 
					d72e5e70f6 | ||
| 
						 | 
					e2c5f751bd | ||
| 
						 | 
					351b86e266 | ||
| 
						 | 
					d0cbff4f4e | ||
| 
						 | 
					cbfc9b9f94 | ||
| 
						 | 
					ca816d801f | ||
| 
						 | 
					2f354d31eb | ||
| 
						 | 
					2c6c1edd37 | ||
| 
						 | 
					9799e7e84b | ||
| 
						 | 
					81be970679 | ||
| 
						 | 
					52221906f6 | ||
| 
						 | 
					3e786fe23a | ||
| 
						 | 
					de24aac7d5 | ||
| 
						 | 
					cd4b0ccf6f | ||
| 
						 | 
					4e1888ac19 | ||
| 
						 | 
					237ede56aa | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,7 @@
 | 
			
		||||
build
 | 
			
		||||
*.pyc
 | 
			
		||||
venv
 | 
			
		||||
ixsnake/ixsnake/.certs/
 | 
			
		||||
site/
 | 
			
		||||
ws/.certs/
 | 
			
		||||
ws/.srl
 | 
			
		||||
 
 | 
			
		||||
@@ -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 make
 | 
			
		||||
@@ -16,7 +16,7 @@ WORKDIR /opt
 | 
			
		||||
USER app
 | 
			
		||||
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 strace
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,40 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
All notable changes to this project will be documented in this file.
 | 
			
		||||
All changes to this project will be documented in this file.
 | 
			
		||||
 | 
			
		||||
## [7.6.4] - 2019-12-22
 | 
			
		||||
 | 
			
		||||
(client) error handling, quote url in error case when failing to parse one
 | 
			
		||||
(ws) ws_cobra_publish: register callbacks before connecting
 | 
			
		||||
(doc) mention mbedtls in supported ssl server backend
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										125
									
								
								docs/ws.md
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								docs/ws.md
									
									
									
									
									
								
							@@ -243,6 +243,127 @@ Options:
 | 
			
		||||
  --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 and the Mbed TLS 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. Use `make ws_mbedtls` accordingly to use MbedTLS.
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include "IXCobraConnection.h"
 | 
			
		||||
#include <ixcrypto/IXHMac.h>
 | 
			
		||||
#include <ixwebsocket/IXWebSocket.h>
 | 
			
		||||
#include <ixwebsocket/IXSocketTLSOptions.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
@@ -244,7 +245,8 @@ namespace ix
 | 
			
		||||
                                    const std::string& endpoint,
 | 
			
		||||
                                    const std::string& rolename,
 | 
			
		||||
                                    const std::string& rolesecret,
 | 
			
		||||
                                    const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions)
 | 
			
		||||
                                    const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
 | 
			
		||||
                                    const SocketTLSOptions& socketTLSOptions)
 | 
			
		||||
    {
 | 
			
		||||
        _roleName = rolename;
 | 
			
		||||
        _roleSecret = rolesecret;
 | 
			
		||||
@@ -257,6 +259,7 @@ namespace ix
 | 
			
		||||
        std::string url = ss.str();
 | 
			
		||||
        _webSocket->setUrl(url);
 | 
			
		||||
        _webSocket->setPerMessageDeflateOptions(webSocketPerMessageDeflateOptions);
 | 
			
		||||
        _webSocket->setTLSOptions(socketTLSOptions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    class WebSocket;
 | 
			
		||||
    struct SocketTLSOptions;
 | 
			
		||||
 | 
			
		||||
    enum CobraConnectionEventType
 | 
			
		||||
    {
 | 
			
		||||
@@ -62,7 +63,8 @@ namespace ix
 | 
			
		||||
                       const std::string& endpoint,
 | 
			
		||||
                       const std::string& rolename,
 | 
			
		||||
                       const std::string& rolesecret,
 | 
			
		||||
                       const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions);
 | 
			
		||||
                       const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
 | 
			
		||||
                       const SocketTLSOptions& socketTLSOptions);
 | 
			
		||||
 | 
			
		||||
        /// Set the traffic tracker callback
 | 
			
		||||
        static void setTrafficTrackerCallback(const TrafficTrackerCallback& callback);
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "IXCobraMetricsPublisher.h"
 | 
			
		||||
#include <ixwebsocket/IXSocketTLSOptions.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
@@ -31,14 +32,15 @@ namespace ix
 | 
			
		||||
                                          const std::string& channel,
 | 
			
		||||
                                          const std::string& rolename,
 | 
			
		||||
                                          const std::string& rolesecret,
 | 
			
		||||
                                          bool enablePerMessageDeflate)
 | 
			
		||||
                                          bool enablePerMessageDeflate,
 | 
			
		||||
                                          const SocketTLSOptions& socketTLSOptions)
 | 
			
		||||
    {
 | 
			
		||||
        // Configure the satori connection and start its publish background thread
 | 
			
		||||
        _cobra_metrics_theaded_publisher.start();
 | 
			
		||||
 | 
			
		||||
        _cobra_metrics_theaded_publisher.configure(appkey, endpoint, channel,
 | 
			
		||||
                                                   rolename, rolesecret,
 | 
			
		||||
                                                   enablePerMessageDeflate);
 | 
			
		||||
                                                   enablePerMessageDeflate, socketTLSOptions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Json::Value& CobraMetricsPublisher::getGenericAttributes()
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,8 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    struct SocketTLSOptions;
 | 
			
		||||
 | 
			
		||||
    class CobraMetricsPublisher
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
@@ -43,7 +45,8 @@ namespace ix
 | 
			
		||||
                       const std::string& channel,
 | 
			
		||||
                       const std::string& rolename,
 | 
			
		||||
                       const std::string& rolesecret,
 | 
			
		||||
                       bool enablePerMessageDeflate);
 | 
			
		||||
                       bool enablePerMessageDeflate,
 | 
			
		||||
                       const SocketTLSOptions& socketTLSOptions);
 | 
			
		||||
 | 
			
		||||
        /// Setter for the list of blacklisted metrics ids.
 | 
			
		||||
        /// That list is sorted internally for fast lookups
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
 | 
			
		||||
#include "IXCobraMetricsThreadedPublisher.h"
 | 
			
		||||
#include <ixwebsocket/IXSetThreadName.h>
 | 
			
		||||
#include <ixwebsocket/IXSocketTLSOptions.h>
 | 
			
		||||
#include <ixcore/utils/IXCoreLogger.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
@@ -92,14 +93,17 @@ namespace ix
 | 
			
		||||
                                                  const std::string& channel,
 | 
			
		||||
                                                  const std::string& rolename,
 | 
			
		||||
                                                  const std::string& rolesecret,
 | 
			
		||||
                                                  bool enablePerMessageDeflate)
 | 
			
		||||
                                                  bool enablePerMessageDeflate,
 | 
			
		||||
                                                  const SocketTLSOptions& socketTLSOptions)
 | 
			
		||||
    {
 | 
			
		||||
        _channel = channel;
 | 
			
		||||
 | 
			
		||||
        ix::IXCoreLogger::Log(socketTLSOptions.getDescription().c_str());
 | 
			
		||||
 | 
			
		||||
        ix::WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(enablePerMessageDeflate);
 | 
			
		||||
        _cobra_connection.configure(appkey, endpoint,
 | 
			
		||||
                                    rolename, rolesecret,
 | 
			
		||||
                                    webSocketPerMessageDeflateOptions);
 | 
			
		||||
                                    webSocketPerMessageDeflateOptions, socketTLSOptions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CobraMetricsThreadedPublisher::pushMessage(MessageKind messageKind)
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,8 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    struct SocketTLSOptions;
 | 
			
		||||
 | 
			
		||||
    class CobraMetricsThreadedPublisher
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
@@ -30,7 +32,8 @@ namespace ix
 | 
			
		||||
                       const std::string& channel,
 | 
			
		||||
                       const std::string& rolename,
 | 
			
		||||
                       const std::string& rolesecret,
 | 
			
		||||
                       bool enablePerMessageDeflate);
 | 
			
		||||
                       bool enablePerMessageDeflate,
 | 
			
		||||
                       const SocketTLSOptions& socketTLSOptions);
 | 
			
		||||
 | 
			
		||||
        /// Start the worker thread, used for background publishing
 | 
			
		||||
        void start();
 | 
			
		||||
 
 | 
			
		||||
@@ -182,7 +182,6 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        Json::Value extra;
 | 
			
		||||
        extra["cobra_event"] = msg;
 | 
			
		||||
        extra["cobra_event"] = msg;
 | 
			
		||||
 | 
			
		||||
        // Builtin tags
 | 
			
		||||
        Json::Value gameTag;
 | 
			
		||||
@@ -200,6 +199,11 @@ namespace ix
 | 
			
		||||
        environmentTag.append(msg["device"]["environment"]);
 | 
			
		||||
        tags.append(environmentTag);
 | 
			
		||||
 | 
			
		||||
        Json::Value clientVersionTag;
 | 
			
		||||
        clientVersionTag.append("client_version");
 | 
			
		||||
        clientVersionTag.append(msg["device"]["app_version"]);
 | 
			
		||||
        tags.append(clientVersionTag);
 | 
			
		||||
 | 
			
		||||
        payload["tags"] = tags;
 | 
			
		||||
 | 
			
		||||
        return _jsonWriter.write(payload);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@
 | 
			
		||||
#include <nlohmann/json.hpp>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <ixwebsocket/IXSocketTLSOptions.h>
 | 
			
		||||
 | 
			
		||||
namespace snake
 | 
			
		||||
{
 | 
			
		||||
@@ -26,6 +27,9 @@ namespace snake
 | 
			
		||||
        // AppKeys
 | 
			
		||||
        nlohmann::json apps;
 | 
			
		||||
 | 
			
		||||
        // TLS options
 | 
			
		||||
        ix::SocketTLSOptions socketTLSOptions;
 | 
			
		||||
 | 
			
		||||
        // Misc
 | 
			
		||||
        bool verbose;
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ namespace snake
 | 
			
		||||
        : _appConfig(appConfig)
 | 
			
		||||
        , _server(appConfig.port, appConfig.hostname)
 | 
			
		||||
    {
 | 
			
		||||
        ;
 | 
			
		||||
        _server.setTLSOptions(appConfig.socketTLSOptions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,47 @@
 | 
			
		||||
 | 
			
		||||
#include <Security/SecureTransport.h>
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    OSStatus read_from_socket(SSLConnectionRef connection, void* data, size_t* len)
 | 
			
		||||
    SocketAppleSSL::SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd)
 | 
			
		||||
        : Socket(fd)
 | 
			
		||||
        , _sslContext(nullptr)
 | 
			
		||||
        , _tlsOptions(tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SocketAppleSSL::~SocketAppleSSL()
 | 
			
		||||
    {
 | 
			
		||||
        SocketAppleSSL::close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string SocketAppleSSL::getSSLErrorDescription(OSStatus status)
 | 
			
		||||
    {
 | 
			
		||||
        std::string errMsg("Unknown SSL error.");
 | 
			
		||||
 | 
			
		||||
        CFErrorRef error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, status, NULL);
 | 
			
		||||
        if (error)
 | 
			
		||||
        {
 | 
			
		||||
            CFStringRef message = CFErrorCopyDescription(error);
 | 
			
		||||
            if (message)
 | 
			
		||||
            {
 | 
			
		||||
                char localBuffer[128];
 | 
			
		||||
                Boolean success;
 | 
			
		||||
                success = CFStringGetCString(message, localBuffer, 128, kCFStringEncodingUTF8);
 | 
			
		||||
                if (success)
 | 
			
		||||
                {
 | 
			
		||||
                    errMsg = localBuffer;
 | 
			
		||||
                }
 | 
			
		||||
                CFRelease(message);
 | 
			
		||||
            }
 | 
			
		||||
            CFRelease(error);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return errMsg;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    OSStatus SocketAppleSSL::readFromSocket(SSLConnectionRef connection, void* data, size_t* len)
 | 
			
		||||
    {
 | 
			
		||||
        int fd = (int) (long) connection;
 | 
			
		||||
        if (fd < 0) return errSSLInternal;
 | 
			
		||||
@@ -67,7 +105,7 @@ namespace
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    OSStatus write_to_socket(SSLConnectionRef connection, const void* data, size_t* len)
 | 
			
		||||
    OSStatus SocketAppleSSL::writeToSocket(SSLConnectionRef connection, const void* data, size_t* len)
 | 
			
		||||
    {
 | 
			
		||||
        int fd = (int) (long) connection;
 | 
			
		||||
        if (fd < 0) return errSSLInternal;
 | 
			
		||||
@@ -105,47 +143,55 @@ namespace
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string getSSLErrorDescription(OSStatus status)
 | 
			
		||||
    {
 | 
			
		||||
        std::string errMsg("Unknown SSL error.");
 | 
			
		||||
 | 
			
		||||
        CFErrorRef error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, status, NULL);
 | 
			
		||||
        if (error)
 | 
			
		||||
    bool SocketAppleSSL::accept(std::string& errMsg)
 | 
			
		||||
    {
 | 
			
		||||
            CFStringRef message = CFErrorCopyDescription(error);
 | 
			
		||||
            if (message)
 | 
			
		||||
        OSStatus status;
 | 
			
		||||
        {
 | 
			
		||||
                char localBuffer[128];
 | 
			
		||||
                Boolean success;
 | 
			
		||||
                success =
 | 
			
		||||
                    CFStringGetCString(message, localBuffer, 128, kCFStringEncodingUTF8);
 | 
			
		||||
                if (success)
 | 
			
		||||
            std::lock_guard<std::mutex> lock(_mutex);
 | 
			
		||||
 | 
			
		||||
            _sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
 | 
			
		||||
 | 
			
		||||
            SSLSetIOFuncs(_sslContext, SocketAppleSSL::readFromSocket, SocketAppleSSL::writeToSocket);
 | 
			
		||||
            SSLSetConnection(_sslContext, (SSLConnectionRef)(long) _sockfd);
 | 
			
		||||
            SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
 | 
			
		||||
 | 
			
		||||
            if (_tlsOptions.isPeerVerifyDisabled())
 | 
			
		||||
            {
 | 
			
		||||
                    errMsg = localBuffer;
 | 
			
		||||
                Boolean option(1);
 | 
			
		||||
                SSLSetSessionOption(_sslContext, kSSLSessionOptionBreakOnServerAuth, option);
 | 
			
		||||
 | 
			
		||||
                do
 | 
			
		||||
                {
 | 
			
		||||
                    status = SSLHandshake(_sslContext);
 | 
			
		||||
                } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status);
 | 
			
		||||
 | 
			
		||||
                if (status == errSSLServerAuthCompleted)
 | 
			
		||||
                {
 | 
			
		||||
                    // proceed with the handshake
 | 
			
		||||
                    do
 | 
			
		||||
                    {
 | 
			
		||||
                        status = SSLHandshake(_sslContext);
 | 
			
		||||
                    } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status);
 | 
			
		||||
                }
 | 
			
		||||
                CFRelease(message);
 | 
			
		||||
            }
 | 
			
		||||
            CFRelease(error);
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                do
 | 
			
		||||
                {
 | 
			
		||||
                    status = SSLHandshake(_sslContext);
 | 
			
		||||
                } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return errMsg;
 | 
			
		||||
        if (noErr != status)
 | 
			
		||||
        {
 | 
			
		||||
            errMsg = getSSLErrorDescription(status);
 | 
			
		||||
            close();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
} // anonymous namespace
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    SocketAppleSSL::SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd)
 | 
			
		||||
        : Socket(fd)
 | 
			
		||||
        , _sslContext(nullptr)
 | 
			
		||||
        , _tlsOptions(tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SocketAppleSSL::~SocketAppleSSL()
 | 
			
		||||
    {
 | 
			
		||||
        SocketAppleSSL::close();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // No wait support
 | 
			
		||||
@@ -163,7 +209,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
            _sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
 | 
			
		||||
 | 
			
		||||
            SSLSetIOFuncs(_sslContext, read_from_socket, write_to_socket);
 | 
			
		||||
            SSLSetIOFuncs(_sslContext, SocketAppleSSL::readFromSocket, SocketAppleSSL::writeToSocket);
 | 
			
		||||
            SSLSetConnection(_sslContext, (SSLConnectionRef)(long) _sockfd);
 | 
			
		||||
            SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
 | 
			
		||||
            SSLSetPeerDomainName(_sslContext, host.c_str(), host.size());
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,8 @@ namespace ix
 | 
			
		||||
        SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd = -1);
 | 
			
		||||
        ~SocketAppleSSL();
 | 
			
		||||
 | 
			
		||||
        virtual bool accept(std::string& errMsg) final;
 | 
			
		||||
 | 
			
		||||
        virtual bool connect(const std::string& host,
 | 
			
		||||
                             int port,
 | 
			
		||||
                             std::string& errMsg,
 | 
			
		||||
@@ -32,6 +34,10 @@ namespace ix
 | 
			
		||||
        virtual ssize_t recv(void* buffer, size_t length) final;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        static std::string getSSLErrorDescription(OSStatus status);
 | 
			
		||||
        static OSStatus writeToSocket(SSLConnectionRef connection, const void* data, size_t* len);
 | 
			
		||||
        static OSStatus readFromSocket(SSLConnectionRef connection, void* data, size_t* len);
 | 
			
		||||
 | 
			
		||||
        SSLContextRef _sslContext;
 | 
			
		||||
        mutable std::mutex _mutex; // AppleSSL routines are not thread-safe
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,9 +38,10 @@ namespace ix
 | 
			
		||||
        mbedtls_ctr_drbg_init(&_ctr_drbg);
 | 
			
		||||
        mbedtls_entropy_init(&_entropy);
 | 
			
		||||
        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();
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_mutex);
 | 
			
		||||
@@ -58,7 +59,7 @@ namespace ix
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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_PRESET_DEFAULT) != 0)
 | 
			
		||||
        {
 | 
			
		||||
@@ -68,13 +69,27 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        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())
 | 
			
		||||
        {
 | 
			
		||||
            mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_NONE);
 | 
			
		||||
        }
 | 
			
		||||
        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 ?
 | 
			
		||||
 | 
			
		||||
@@ -87,7 +102,13 @@ namespace ix
 | 
			
		||||
                errMsg = "Cannot parse CA file '" + _tlsOptions.caFile + "'";
 | 
			
		||||
                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)
 | 
			
		||||
@@ -96,7 +117,7 @@ namespace ix
 | 
			
		||||
            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";
 | 
			
		||||
            return false;
 | 
			
		||||
@@ -105,6 +126,50 @@ namespace ix
 | 
			
		||||
        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,
 | 
			
		||||
                                int port,
 | 
			
		||||
                                std::string& errMsg,
 | 
			
		||||
@@ -116,7 +181,8 @@ namespace ix
 | 
			
		||||
            if (_sockfd == -1) return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool initialized = init(host, errMsg);
 | 
			
		||||
        bool isClient = true;
 | 
			
		||||
        bool initialized = init(host, isClient, errMsg);
 | 
			
		||||
        if (!initialized)
 | 
			
		||||
        {
 | 
			
		||||
            close();
 | 
			
		||||
@@ -156,6 +222,7 @@ namespace ix
 | 
			
		||||
        mbedtls_ctr_drbg_free(&_ctr_drbg);
 | 
			
		||||
        mbedtls_entropy_free(&_entropy);
 | 
			
		||||
        mbedtls_x509_crt_free(&_cacert);
 | 
			
		||||
        mbedtls_x509_crt_free(&_cert);
 | 
			
		||||
 | 
			
		||||
        Socket::close();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@ namespace ix
 | 
			
		||||
        SocketMbedTLS(const SocketTLSOptions& tlsOptions, int fd = -1);
 | 
			
		||||
        ~SocketMbedTLS();
 | 
			
		||||
 | 
			
		||||
        virtual bool accept(std::string& errMsg) final;
 | 
			
		||||
 | 
			
		||||
        virtual bool connect(const std::string& host,
 | 
			
		||||
                             int port,
 | 
			
		||||
                             std::string& errMsg,
 | 
			
		||||
@@ -42,11 +44,13 @@ namespace ix
 | 
			
		||||
        mbedtls_entropy_context _entropy;
 | 
			
		||||
        mbedtls_ctr_drbg_context _ctr_drbg;
 | 
			
		||||
        mbedtls_x509_crt _cacert;
 | 
			
		||||
        mbedtls_x509_crt _cert;
 | 
			
		||||
        mbedtls_pk_context _pkey;
 | 
			
		||||
 | 
			
		||||
        std::mutex _mutex;
 | 
			
		||||
        SocketTLSOptions _tlsOptions;
 | 
			
		||||
 | 
			
		||||
        bool init(const std::string& host, std::string& errMsg);
 | 
			
		||||
        bool init(const std::string& host, bool isClient, std::string& errMsg);
 | 
			
		||||
        void initMBedTLS();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
@@ -71,4 +72,16 @@ namespace ix
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
        ss << "  ciphers  = " << ciphers << std::endl;
 | 
			
		||||
        return ss.str();
 | 
			
		||||
    }
 | 
			
		||||
} // namespace ix
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,8 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        const std::string& getErrorMsg() const;
 | 
			
		||||
 | 
			
		||||
        std::string getDescription() const;
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        mutable std::string _errMsg;
 | 
			
		||||
        mutable bool _validated = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -144,7 +144,9 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        if (!UrlParser::parse(url, protocol, host, path, query, port))
 | 
			
		||||
        {
 | 
			
		||||
            return WebSocketInitResult(false, 0, std::string("Could not parse URL ") + url);
 | 
			
		||||
            std::stringstream ss;
 | 
			
		||||
            ss << "Could not parse url: '" << url << "'";
 | 
			
		||||
            return WebSocketInitResult(false, 0, ss.str());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string errorMsg;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,4 +6,4 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define IX_WEBSOCKET_VERSION "7.5.5"
 | 
			
		||||
#define IX_WEBSOCKET_VERSION "7.6.4"
 | 
			
		||||
 
 | 
			
		||||
@@ -34,10 +34,10 @@ namespace
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class SatoriChat
 | 
			
		||||
    class CobraChat
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        SatoriChat(const std::string& user,
 | 
			
		||||
        CobraChat(const std::string& user,
 | 
			
		||||
                   const std::string& session,
 | 
			
		||||
                   const std::string& endpoint);
 | 
			
		||||
 | 
			
		||||
@@ -72,7 +72,7 @@ namespace
 | 
			
		||||
        std::mutex _logMutex;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SatoriChat::SatoriChat(const std::string& user,
 | 
			
		||||
    CobraChat::CobraChat(const std::string& user,
 | 
			
		||||
                         const std::string& session,
 | 
			
		||||
                         const std::string& endpoint)
 | 
			
		||||
        : _user(user)
 | 
			
		||||
@@ -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;
 | 
			
		||||
        _thread.join();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool SatoriChat::isReady() const
 | 
			
		||||
    bool CobraChat::isReady() const
 | 
			
		||||
    {
 | 
			
		||||
        return _connectedAndSubscribed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t SatoriChat::getReceivedMessagesCount() const
 | 
			
		||||
    size_t CobraChat::getReceivedMessagesCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return _receivedQueue.size();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool SatoriChat::hasPendingMessages() const
 | 
			
		||||
    bool CobraChat::hasPendingMessages() const
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_queue_mutex);
 | 
			
		||||
        return !_publish_queue.empty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Json::Value SatoriChat::popMessage()
 | 
			
		||||
    Json::Value CobraChat::popMessage()
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_queue_mutex);
 | 
			
		||||
        auto msg = _publish_queue.front();
 | 
			
		||||
@@ -121,7 +121,7 @@ namespace
 | 
			
		||||
    //
 | 
			
		||||
    // 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;
 | 
			
		||||
        _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;
 | 
			
		||||
        msg["user"] = _user;
 | 
			
		||||
@@ -166,16 +166,21 @@ namespace
 | 
			
		||||
    // Do satori communication on a background thread, where we can have
 | 
			
		||||
    // something like an event loop that publish, poll and receive data
 | 
			
		||||
    //
 | 
			
		||||
    void SatoriChat::run()
 | 
			
		||||
    void CobraChat::run()
 | 
			
		||||
    {
 | 
			
		||||
        // "chat" conf
 | 
			
		||||
        std::string appkey("FC2F10139A2BAc53BB72D9db967b024f");
 | 
			
		||||
        std::string channel = _session;
 | 
			
		||||
        std::string role = "_sub";
 | 
			
		||||
        std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba";
 | 
			
		||||
        SocketTLSOptions socketTLSOptions;
 | 
			
		||||
 | 
			
		||||
        _conn.configure(
 | 
			
		||||
            appkey, _endpoint, role, secret, ix::WebSocketPerMessageDeflateOptions(true));
 | 
			
		||||
        _conn.configure(appkey,
 | 
			
		||||
                        _endpoint,
 | 
			
		||||
                        role,
 | 
			
		||||
                        secret,
 | 
			
		||||
                        ix::WebSocketPerMessageDeflateOptions(true),
 | 
			
		||||
                        socketTLSOptions);
 | 
			
		||||
        _conn.connect();
 | 
			
		||||
 | 
			
		||||
        _conn.setEventCallback([this, channel](ix::CobraConnectionEventType eventType,
 | 
			
		||||
@@ -280,8 +285,8 @@ TEST_CASE("Cobra_chat", "[cobra_chat]")
 | 
			
		||||
        ss << "ws://localhost:" << port;
 | 
			
		||||
        std::string endpoint = ss.str();
 | 
			
		||||
 | 
			
		||||
        SatoriChat chatA("jean", session, endpoint);
 | 
			
		||||
        SatoriChat chatB("paul", session, endpoint);
 | 
			
		||||
        CobraChat chatA("jean", session, endpoint);
 | 
			
		||||
        CobraChat chatB("paul", session, endpoint);
 | 
			
		||||
 | 
			
		||||
        chatA.start();
 | 
			
		||||
        chatB.start();
 | 
			
		||||
 
 | 
			
		||||
@@ -62,11 +62,14 @@ namespace
 | 
			
		||||
        gMessageCount = 0;
 | 
			
		||||
 | 
			
		||||
        ix::CobraConnection conn;
 | 
			
		||||
        SocketTLSOptions socketTLSOptions;
 | 
			
		||||
 | 
			
		||||
        conn.configure(APPKEY,
 | 
			
		||||
                       endpoint,
 | 
			
		||||
                       SUBSCRIBER_ROLE,
 | 
			
		||||
                       SUBSCRIBER_SECRET,
 | 
			
		||||
                       ix::WebSocketPerMessageDeflateOptions(true));
 | 
			
		||||
                       ix::WebSocketPerMessageDeflateOptions(true),
 | 
			
		||||
                       socketTLSOptions);
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        conn.setEventCallback([&conn](ix::CobraConnectionEventType eventType,
 | 
			
		||||
@@ -202,9 +205,15 @@ TEST_CASE("Cobra_Metrics_Publisher", "[cobra]")
 | 
			
		||||
 | 
			
		||||
    ix::CobraMetricsPublisher cobraMetricsPublisher;
 | 
			
		||||
 | 
			
		||||
    SocketTLSOptions socketTLSOptions;
 | 
			
		||||
    bool perMessageDeflate = true;
 | 
			
		||||
    cobraMetricsPublisher.configure(
 | 
			
		||||
        APPKEY, endpoint, CHANNEL, PUBLISHER_ROLE, PUBLISHER_SECRET, perMessageDeflate);
 | 
			
		||||
    cobraMetricsPublisher.configure(APPKEY,
 | 
			
		||||
                                    endpoint,
 | 
			
		||||
                                    CHANNEL,
 | 
			
		||||
                                    PUBLISHER_ROLE,
 | 
			
		||||
                                    PUBLISHER_SECRET,
 | 
			
		||||
                                    perMessageDeflate,
 | 
			
		||||
                                    socketTLSOptions);
 | 
			
		||||
    cobraMetricsPublisher.setSession(uuid4());
 | 
			
		||||
    cobraMetricsPublisher.enable(true); // disabled by default, needs to be enabled to be active
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ done
 | 
			
		||||
# Start a receiver
 | 
			
		||||
mkdir -p /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
 | 
			
		||||
cd /tmp/ws_test/send
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								ws/ws.cpp
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								ws/ws.cpp
									
									
									
									
									
								
							@@ -218,6 +218,7 @@ int main(int argc, char** argv)
 | 
			
		||||
    cobraSubscribeApp->add_option("--pidfile", pidfile, "Pid file");
 | 
			
		||||
    cobraSubscribeApp->add_option("--filter", filter, "Stream SQL Filter");
 | 
			
		||||
    cobraSubscribeApp->add_flag("-q", quiet, "Quiet / only display stats");
 | 
			
		||||
    addTLSOptions(cobraSubscribeApp);
 | 
			
		||||
 | 
			
		||||
    CLI::App* cobraPublish = app.add_subcommand("cobra_publish", "Cobra publisher");
 | 
			
		||||
    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")
 | 
			
		||||
        ->required()
 | 
			
		||||
        ->check(CLI::ExistingPath);
 | 
			
		||||
    addTLSOptions(cobraPublish);
 | 
			
		||||
 | 
			
		||||
    CLI::App* cobraMetricsPublish =
 | 
			
		||||
        app.add_subcommand("cobra_metrics_publish", "Cobra metrics publisher");
 | 
			
		||||
@@ -242,6 +244,7 @@ int main(int argc, char** argv)
 | 
			
		||||
        ->required()
 | 
			
		||||
        ->check(CLI::ExistingPath);
 | 
			
		||||
    cobraMetricsPublish->add_flag("--stress", stress, "Stress mode");
 | 
			
		||||
    addTLSOptions(cobraMetricsPublish);
 | 
			
		||||
 | 
			
		||||
    CLI::App* cobra2statsd = app.add_subcommand("cobra_to_statsd", "Cobra metrics to statsd");
 | 
			
		||||
    cobra2statsd->add_option("--appkey", appkey, "Appkey");
 | 
			
		||||
@@ -256,6 +259,7 @@ int main(int argc, char** argv)
 | 
			
		||||
    cobra2statsd->add_flag("-v", verbose, "Verbose");
 | 
			
		||||
    cobra2statsd->add_option("--pidfile", pidfile, "Pid file");
 | 
			
		||||
    cobra2statsd->add_option("--filter", filter, "Stream SQL Filter");
 | 
			
		||||
    addTLSOptions(cobra2statsd);
 | 
			
		||||
 | 
			
		||||
    CLI::App* cobra2sentry = app.add_subcommand("cobra_to_sentry", "Cobra metrics to sentry");
 | 
			
		||||
    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_option("--pidfile", pidfile, "Pid file");
 | 
			
		||||
    cobra2sentry->add_option("--filter", filter, "Stream SQL Filter");
 | 
			
		||||
    addTLSOptions(cobra2sentry);
 | 
			
		||||
 | 
			
		||||
    CLI::App* cobra2redisApp =
 | 
			
		||||
        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("--port", redisPort, "Redis port");
 | 
			
		||||
    cobra2redisApp->add_flag("-q", quiet, "Quiet / only display stats");
 | 
			
		||||
    addTLSOptions(cobra2redisApp);
 | 
			
		||||
 | 
			
		||||
    CLI::App* runApp = app.add_subcommand("snake", "Snake server");
 | 
			
		||||
    runApp->add_option("--port", port, "Connection url");
 | 
			
		||||
    runApp->add_option("--host", hostname, "Hostname");
 | 
			
		||||
    runApp->add_option("--pidfile", pidfile, "Pid file");
 | 
			
		||||
    runApp->add_option("--redis_hosts", redisHosts, "Redis hosts");
 | 
			
		||||
    runApp->add_option("--redis_port", redisPort, "Redis hosts");
 | 
			
		||||
    runApp->add_option("--redis_password", redisPassword, "Redis password");
 | 
			
		||||
    runApp->add_option("--apps_config_path", appsConfigPath, "Path to auth data")
 | 
			
		||||
    CLI::App* snakeApp = app.add_subcommand("snake", "Snake server");
 | 
			
		||||
    snakeApp->add_option("--port", port, "Connection url");
 | 
			
		||||
    snakeApp->add_option("--host", hostname, "Hostname");
 | 
			
		||||
    snakeApp->add_option("--pidfile", pidfile, "Pid file");
 | 
			
		||||
    snakeApp->add_option("--redis_hosts", redisHosts, "Redis hosts");
 | 
			
		||||
    snakeApp->add_option("--redis_port", redisPort, "Redis hosts");
 | 
			
		||||
    snakeApp->add_option("--redis_password", redisPassword, "Redis password");
 | 
			
		||||
    snakeApp->add_option("--apps_config_path", appsConfigPath, "Path to auth data")
 | 
			
		||||
        ->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");
 | 
			
		||||
    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("--remote_host", remoteHost, "Remote Hostname");
 | 
			
		||||
    proxyServerApp->add_flag("-v", verbose, "Verbose");
 | 
			
		||||
    addTLSOptions(proxyServerApp);
 | 
			
		||||
 | 
			
		||||
    CLI::App* minidumpApp = app.add_subcommand("upload_minidump", "Upload a minidump to sentry");
 | 
			
		||||
    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"))
 | 
			
		||||
    {
 | 
			
		||||
        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"))
 | 
			
		||||
    {
 | 
			
		||||
        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"))
 | 
			
		||||
    {
 | 
			
		||||
        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"))
 | 
			
		||||
    {
 | 
			
		||||
@@ -431,22 +440,39 @@ int main(int argc, char** argv)
 | 
			
		||||
                                          statsdPort,
 | 
			
		||||
                                          prefix,
 | 
			
		||||
                                          fields,
 | 
			
		||||
                                          verbose);
 | 
			
		||||
                                          verbose,
 | 
			
		||||
                                          tlsOptions);
 | 
			
		||||
    }
 | 
			
		||||
    else if (app.got_subcommand("cobra_to_sentry"))
 | 
			
		||||
    {
 | 
			
		||||
        ret = ix::ws_cobra_to_sentry_main(
 | 
			
		||||
            appkey, endpoint, rolename, rolesecret, channel, filter, dsn, verbose, strict, jobs);
 | 
			
		||||
        ret = ix::ws_cobra_to_sentry_main(appkey,
 | 
			
		||||
                                          endpoint,
 | 
			
		||||
                                          rolename,
 | 
			
		||||
                                          rolesecret,
 | 
			
		||||
                                          channel,
 | 
			
		||||
                                          filter,
 | 
			
		||||
                                          dsn,
 | 
			
		||||
                                          verbose,
 | 
			
		||||
                                          strict,
 | 
			
		||||
                                          jobs,
 | 
			
		||||
                                          tlsOptions);
 | 
			
		||||
    }
 | 
			
		||||
    else if (app.got_subcommand("cobra_metrics_to_redis"))
 | 
			
		||||
    {
 | 
			
		||||
        ret = ix::ws_cobra_metrics_to_redis(
 | 
			
		||||
            appkey, endpoint, rolename, rolesecret, channel, filter, hostname, redisPort);
 | 
			
		||||
        ret = ix::ws_cobra_metrics_to_redis(appkey,
 | 
			
		||||
                                            endpoint,
 | 
			
		||||
                                            rolename,
 | 
			
		||||
                                            rolesecret,
 | 
			
		||||
                                            channel,
 | 
			
		||||
                                            filter,
 | 
			
		||||
                                            hostname,
 | 
			
		||||
                                            redisPort,
 | 
			
		||||
                                            tlsOptions);
 | 
			
		||||
    }
 | 
			
		||||
    else if (app.got_subcommand("snake"))
 | 
			
		||||
    {
 | 
			
		||||
        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"))
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								ws/ws.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								ws/ws.h
									
									
									
									
									
								
							@@ -76,14 +76,16 @@ namespace ix
 | 
			
		||||
                                const std::string& rolesecret,
 | 
			
		||||
                                const std::string& channel,
 | 
			
		||||
                                const std::string& filter,
 | 
			
		||||
                                bool quiet);
 | 
			
		||||
                                bool quiet,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions);
 | 
			
		||||
 | 
			
		||||
    int ws_cobra_publish_main(const std::string& appkey,
 | 
			
		||||
                              const std::string& endpoint,
 | 
			
		||||
                              const std::string& rolename,
 | 
			
		||||
                              const std::string& rolesecret,
 | 
			
		||||
                              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,
 | 
			
		||||
                                      const std::string& endpoint,
 | 
			
		||||
@@ -91,7 +93,8 @@ namespace ix
 | 
			
		||||
                                      const std::string& rolesecret,
 | 
			
		||||
                                      const std::string& channel,
 | 
			
		||||
                                      const std::string& path,
 | 
			
		||||
                                      bool stress);
 | 
			
		||||
                                      bool stress,
 | 
			
		||||
                                      const ix::SocketTLSOptions& tlsOptions);
 | 
			
		||||
 | 
			
		||||
    int ws_cobra_to_statsd_main(const std::string& appkey,
 | 
			
		||||
                                const std::string& endpoint,
 | 
			
		||||
@@ -103,7 +106,8 @@ namespace ix
 | 
			
		||||
                                int port,
 | 
			
		||||
                                const std::string& prefix,
 | 
			
		||||
                                const std::string& fields,
 | 
			
		||||
                                bool verbose);
 | 
			
		||||
                                bool verbose,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions);
 | 
			
		||||
 | 
			
		||||
    int ws_cobra_to_sentry_main(const std::string& appkey,
 | 
			
		||||
                                const std::string& endpoint,
 | 
			
		||||
@@ -114,7 +118,8 @@ namespace ix
 | 
			
		||||
                                const std::string& dsn,
 | 
			
		||||
                                bool verbose,
 | 
			
		||||
                                bool strict,
 | 
			
		||||
                                int jobs);
 | 
			
		||||
                                int jobs,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions);
 | 
			
		||||
 | 
			
		||||
    int ws_cobra_metrics_to_redis(const std::string& appkey,
 | 
			
		||||
                                  const std::string& endpoint,
 | 
			
		||||
@@ -123,7 +128,8 @@ namespace ix
 | 
			
		||||
                                  const std::string& channel,
 | 
			
		||||
                                  const std::string& filter,
 | 
			
		||||
                                  const std::string& host,
 | 
			
		||||
                                  int port);
 | 
			
		||||
                                  int port,
 | 
			
		||||
                                  const ix::SocketTLSOptions& tlsOptions);
 | 
			
		||||
 | 
			
		||||
    int ws_snake_main(int port,
 | 
			
		||||
                      const std::string& hostname,
 | 
			
		||||
@@ -131,7 +137,8 @@ namespace ix
 | 
			
		||||
                      int redisPort,
 | 
			
		||||
                      const std::string& redisPassword,
 | 
			
		||||
                      bool verbose,
 | 
			
		||||
                      const std::string& appsConfigPath);
 | 
			
		||||
                      const std::string& appsConfigPath,
 | 
			
		||||
                      const ix::SocketTLSOptions& tlsOptions);
 | 
			
		||||
 | 
			
		||||
    int ws_httpd_main(int port,
 | 
			
		||||
                      const std::string& hostname,
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,8 @@ namespace ix
 | 
			
		||||
                                      const std::string& rolesecret,
 | 
			
		||||
                                      const std::string& channel,
 | 
			
		||||
                                      const std::string& path,
 | 
			
		||||
                                      bool stress)
 | 
			
		||||
                                      bool stress,
 | 
			
		||||
                                      const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        std::atomic<int> sentMessages(0);
 | 
			
		||||
        std::atomic<int> ackedMessages(0);
 | 
			
		||||
@@ -37,7 +38,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        bool enablePerMessageDeflate = true;
 | 
			
		||||
        cobraMetricsPublisher.configure(
 | 
			
		||||
            appkey, endpoint, channel, rolename, rolesecret, enablePerMessageDeflate);
 | 
			
		||||
            appkey, endpoint, channel, rolename, rolesecret, enablePerMessageDeflate, tlsOptions);
 | 
			
		||||
 | 
			
		||||
        while (!cobraMetricsPublisher.isAuthenticated())
 | 
			
		||||
            ;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,11 +25,16 @@ namespace ix
 | 
			
		||||
                                  const std::string& channel,
 | 
			
		||||
                                  const std::string& filter,
 | 
			
		||||
                                  const std::string& host,
 | 
			
		||||
                                  int port)
 | 
			
		||||
                                  int port,
 | 
			
		||||
                                  const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        ix::CobraConnection conn;
 | 
			
		||||
        conn.configure(
 | 
			
		||||
            appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
 | 
			
		||||
        conn.configure(appkey,
 | 
			
		||||
                       endpoint,
 | 
			
		||||
                       rolename,
 | 
			
		||||
                       rolesecret,
 | 
			
		||||
                       ix::WebSocketPerMessageDeflateOptions(true),
 | 
			
		||||
                       tlsOptions);
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        // Display incoming messages
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,8 @@ namespace ix
 | 
			
		||||
                              const std::string& rolename,
 | 
			
		||||
                              const std::string& rolesecret,
 | 
			
		||||
                              const std::string& channel,
 | 
			
		||||
                              const std::string& path)
 | 
			
		||||
                              const std::string& path,
 | 
			
		||||
                              const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        std::ifstream f(path);
 | 
			
		||||
        std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
 | 
			
		||||
@@ -36,9 +37,12 @@ namespace ix
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ix::CobraConnection conn;
 | 
			
		||||
        conn.configure(
 | 
			
		||||
            appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
 | 
			
		||||
        conn.connect();
 | 
			
		||||
        conn.configure(appkey,
 | 
			
		||||
                       endpoint,
 | 
			
		||||
                       rolename,
 | 
			
		||||
                       rolesecret,
 | 
			
		||||
                       ix::WebSocketPerMessageDeflateOptions(true),
 | 
			
		||||
                       tlsOptions);
 | 
			
		||||
 | 
			
		||||
        // Display incoming messages
 | 
			
		||||
        std::atomic<bool> authenticated(false);
 | 
			
		||||
@@ -89,6 +93,8 @@ namespace ix
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        while (!authenticated)
 | 
			
		||||
            ;
 | 
			
		||||
        while (!messageAcked)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,16 @@ namespace ix
 | 
			
		||||
                                const std::string& rolesecret,
 | 
			
		||||
                                const std::string& channel,
 | 
			
		||||
                                const std::string& filter,
 | 
			
		||||
                                bool quiet)
 | 
			
		||||
                                bool quiet,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        ix::CobraConnection conn;
 | 
			
		||||
        conn.configure(
 | 
			
		||||
            appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
 | 
			
		||||
        conn.configure(appkey,
 | 
			
		||||
                       endpoint,
 | 
			
		||||
                       rolename,
 | 
			
		||||
                       rolesecret,
 | 
			
		||||
                       ix::WebSocketPerMessageDeflateOptions(true),
 | 
			
		||||
                       tlsOptions);
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        Json::FastWriter jsonWriter;
 | 
			
		||||
 
 | 
			
		||||
@@ -28,11 +28,16 @@ namespace ix
 | 
			
		||||
                                const std::string& dsn,
 | 
			
		||||
                                bool verbose,
 | 
			
		||||
                                bool strict,
 | 
			
		||||
                                int jobs)
 | 
			
		||||
                                int jobs,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        ix::CobraConnection conn;
 | 
			
		||||
        conn.configure(
 | 
			
		||||
            appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
 | 
			
		||||
        conn.configure(appkey,
 | 
			
		||||
                       endpoint,
 | 
			
		||||
                       rolename,
 | 
			
		||||
                       rolesecret,
 | 
			
		||||
                       ix::WebSocketPerMessageDeflateOptions(true),
 | 
			
		||||
                       tlsOptions);
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        Json::FastWriter jsonWriter;
 | 
			
		||||
@@ -132,11 +137,13 @@ namespace ix
 | 
			
		||||
                        {
 | 
			
		||||
                            seconds = 30;
 | 
			
		||||
                            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 "
 | 
			
		||||
                                     "and retry after {} seconds", retryAfter);
 | 
			
		||||
                                     "and retry after {} seconds",
 | 
			
		||||
                                     retryAfter);
 | 
			
		||||
 | 
			
		||||
                        throttled = true;
 | 
			
		||||
                        auto duration = std::chrono::seconds(seconds);
 | 
			
		||||
 
 | 
			
		||||
@@ -66,11 +66,16 @@ namespace ix
 | 
			
		||||
                                int port,
 | 
			
		||||
                                const std::string& prefix,
 | 
			
		||||
                                const std::string& fields,
 | 
			
		||||
                                bool verbose)
 | 
			
		||||
                                bool verbose,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        ix::CobraConnection conn;
 | 
			
		||||
        conn.configure(
 | 
			
		||||
            appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
 | 
			
		||||
        conn.configure(appkey,
 | 
			
		||||
                       endpoint,
 | 
			
		||||
                       rolename,
 | 
			
		||||
                       rolesecret,
 | 
			
		||||
                       ix::WebSocketPerMessageDeflateOptions(true),
 | 
			
		||||
                       tlsOptions);
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        auto tokens = parseFields(fields);
 | 
			
		||||
 
 | 
			
		||||
@@ -120,6 +120,7 @@ namespace ix
 | 
			
		||||
                    std::string url(remoteUrl);
 | 
			
		||||
                    url += msg->openInfo.uri;
 | 
			
		||||
                    state->webSocket().setUrl(url);
 | 
			
		||||
                    state->webSocket().disableAutomaticReconnection();
 | 
			
		||||
                    state->webSocket().start();
 | 
			
		||||
 | 
			
		||||
                    // we should sleep here for a bit until we've established the
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,8 @@ namespace ix
 | 
			
		||||
                      int redisPort,
 | 
			
		||||
                      const std::string& redisPassword,
 | 
			
		||||
                      bool verbose,
 | 
			
		||||
                      const std::string& appsConfigPath)
 | 
			
		||||
                      const std::string& appsConfigPath,
 | 
			
		||||
                      const SocketTLSOptions& socketTLSOptions)
 | 
			
		||||
    {
 | 
			
		||||
        snake::AppConfig appConfig;
 | 
			
		||||
        appConfig.port = port;
 | 
			
		||||
@@ -51,6 +52,7 @@ namespace ix
 | 
			
		||||
        appConfig.verbose = verbose;
 | 
			
		||||
        appConfig.redisPort = redisPort;
 | 
			
		||||
        appConfig.redisPassword = redisPassword;
 | 
			
		||||
        appConfig.socketTLSOptions = socketTLSOptions;
 | 
			
		||||
 | 
			
		||||
        // Parse config file
 | 
			
		||||
        auto str = readAsString(appsConfigPath);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user