Compare commits
	
		
			17 Commits
		
	
	
		
			v7.5.5
			...
			feature/ma
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 84361c16a9 | ||
|  | 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 | build | ||||||
| *.pyc | *.pyc | ||||||
| venv | 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 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 | ||||||
|   | |||||||
| @@ -1,5 +1,40 @@ | |||||||
| # Changelog | # 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 | ## [7.5.5] - 2019-12-17 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										125
									
								
								docs/ws.md
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								docs/ws.md
									
									
									
									
									
								
							| @@ -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 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 "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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // |     // | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -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() | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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(); | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -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; | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ namespace snake | |||||||
|         : _appConfig(appConfig) |         : _appConfig(appConfig) | ||||||
|         , _server(appConfig.port, appConfig.hostname) |         , _server(appConfig.port, appConfig.hostname) | ||||||
|     { |     { | ||||||
|         ; |         _server.setTLSOptions(appConfig.socketTLSOptions); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // |     // | ||||||
|   | |||||||
| @@ -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; | ||||||
| @@ -131,6 +130,104 @@ namespace | |||||||
|         return errMsg; |         return errMsg; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #undef CURL_BUILD_IOS | ||||||
|  |     OSStatus CopyIdentityFromPKCS12File( | ||||||
|  |         const char *cPath, | ||||||
|  |         const char *cPassword, | ||||||
|  |         SecIdentityRef *out_cert_and_key) | ||||||
|  |     { | ||||||
|  |         OSStatus status = errSecItemNotFound; | ||||||
|  |         CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation( | ||||||
|  |             NULL, (const UInt8 *)cPath, strlen(cPath), false); | ||||||
|  |         CFStringRef password = cPassword ? CFStringCreateWithCString(NULL, | ||||||
|  |             cPassword, kCFStringEncodingUTF8) : NULL; | ||||||
|  |         CFDataRef pkcs_data = NULL; | ||||||
|  |  | ||||||
|  |         /* We can import P12 files on iOS or OS X 10.7 or later: */ | ||||||
|  |         /* These constants are documented as having first appeared in 10.6 but they | ||||||
|  |            raise linker errors when used on that cat for some reason. */ | ||||||
|  |         if (CFURLCreateDataAndPropertiesFromResource( | ||||||
|  |             NULL, pkcs_url, &pkcs_data, NULL, NULL, &status)) { | ||||||
|  |             CFArrayRef items = NULL; | ||||||
|  |  | ||||||
|  |             /* On iOS SecPKCS12Import will never add the client certificate to the | ||||||
|  |              * Keychain. | ||||||
|  |              * | ||||||
|  |              * It gives us back a SecIdentityRef that we can use directly. */ | ||||||
|  | #if CURL_BUILD_IOS | ||||||
|  |             const void *cKeys[] = {kSecImportExportPassphrase}; | ||||||
|  |             const void *cValues[] = {password}; | ||||||
|  |             CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, | ||||||
|  |                     password ? 1L : 0L, NULL, NULL); | ||||||
|  |  | ||||||
|  |             if (options != NULL) { | ||||||
|  |                 status = SecPKCS12Import(pkcs_data, options, &items); | ||||||
|  |                 CFRelease(options); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             /* On macOS SecPKCS12Import will always add the client certificate to | ||||||
|  |              * the Keychain. | ||||||
|  |              * | ||||||
|  |              * As this doesn't match iOS, and apps may not want to see their client | ||||||
|  |              * certificate saved in the the user's keychain, we use SecItemImport | ||||||
|  |              * with a NULL keychain to avoid importing it. | ||||||
|  |              * | ||||||
|  |              * This returns a SecCertificateRef from which we can construct a | ||||||
|  |              * SecIdentityRef. | ||||||
|  |              */ | ||||||
|  | #else | ||||||
|  |             SecItemImportExportKeyParameters keyParams; | ||||||
|  |             SecExternalFormat inputFormat = kSecFormatPKCS12; | ||||||
|  |             SecExternalItemType inputType = kSecItemTypeCertificate; | ||||||
|  |  | ||||||
|  |             memset(&keyParams, 0x00, sizeof(keyParams)); | ||||||
|  |             keyParams.version    = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; | ||||||
|  |             keyParams.passphrase = password; | ||||||
|  |  | ||||||
|  |             status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType, | ||||||
|  |                                    0, &keyParams, NULL, &items); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |             /* Extract the SecIdentityRef */ | ||||||
|  |             if (status == errSecSuccess && items && CFArrayGetCount(items)) | ||||||
|  |             { | ||||||
|  |                 CFIndex i, count; | ||||||
|  |                 count = CFArrayGetCount(items); | ||||||
|  |  | ||||||
|  |                 for (i = 0; i < count; i++) | ||||||
|  |                 { | ||||||
|  |                     CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i); | ||||||
|  |                     CFTypeID  itemID = CFGetTypeID(item); | ||||||
|  |  | ||||||
|  |                     if (itemID == CFDictionaryGetTypeID()) | ||||||
|  |                     { | ||||||
|  |                         CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue( | ||||||
|  |                                 (CFDictionaryRef) item, | ||||||
|  |                                 kSecImportItemIdentity); | ||||||
|  |                         CFRetain(identity); | ||||||
|  |                         *out_cert_and_key = (SecIdentityRef) identity; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     else if (itemID == SecCertificateGetTypeID()) | ||||||
|  |                     { | ||||||
|  |                         status = SecIdentityCreateWithCertificate(NULL, | ||||||
|  |                                 (SecCertificateRef) item, | ||||||
|  |                                 out_cert_and_key); | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (items) CFRelease(items); | ||||||
|  |             CFRelease(pkcs_data); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (password) CFRelease(password); | ||||||
|  |         CFRelease(pkcs_url); | ||||||
|  |         return status; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| } // anonymous namespace | } // anonymous namespace | ||||||
|  |  | ||||||
| namespace ix | namespace ix | ||||||
| @@ -148,6 +245,69 @@ 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool SocketAppleSSL::handleTLSOptions(std::string& errMsg) | ||||||
|  |     { | ||||||
|  |         SecIdentityRef cert_and_key = NULL; | ||||||
|  |  | ||||||
|  |         const char* ssl_cert = _tlsOptions.certFile.c_str(); | ||||||
|  |  | ||||||
|  |         OSStatus err = CopyIdentityFromPKCS12File(ssl_cert, "foobar", &cert_and_key); | ||||||
|  |  | ||||||
|  |         if (err == noErr && cert_and_key) | ||||||
|  |         { | ||||||
|  |             SecCertificateRef cert = NULL; | ||||||
|  |             CFTypeRef certs_c[1]; | ||||||
|  |             CFArrayRef certs; | ||||||
|  |  | ||||||
|  |             err = SecIdentityCopyCertificate(cert_and_key, &cert); | ||||||
|  |  | ||||||
|  |             certs_c[0] = cert_and_key; | ||||||
|  |             certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, | ||||||
|  |                     &kCFTypeArrayCallBacks); | ||||||
|  |             err = SSLSetCertificate(_sslContext, certs); | ||||||
|  |             if (err != noErr) | ||||||
|  |             { | ||||||
|  |                 errMsg = "SSLSetCertificate failed"; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             switch(err) { | ||||||
|  |                 case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ | ||||||
|  |                     errMsg = "SSL: Incorrect password for the certificate \"%s\" " | ||||||
|  |                             "and its private key."; // , ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ | ||||||
|  |                     errMsg = "SSL: Couldn't make sense of the data in the " | ||||||
|  |                             "certificate \"%s\" and its private key."; | ||||||
|  |                             ; // ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 case -25260: /* errSecPassphraseRequired */ | ||||||
|  |                     errMsg = "SSL The certificate \"%s\" requires a password."; | ||||||
|  |                             // ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 case errSecItemNotFound: | ||||||
|  |                     errMsg = "SSL: Can't find the certificate \"%s\" and its private " | ||||||
|  |                             "key in the Keychain."; // , ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     errMsg = "SSL: Can't load the certificate \"%s\" and its private " | ||||||
|  |                             "key: OSStatus %d" ; // , ssl_cert, err); | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // No wait support |     // No wait support | ||||||
|     bool SocketAppleSSL::connect(const std::string& host, |     bool SocketAppleSSL::connect(const std::string& host, | ||||||
|                                  int port, |                                  int port, | ||||||
| @@ -168,6 +328,8 @@ namespace ix | |||||||
|             SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12); |             SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12); | ||||||
|             SSLSetPeerDomainName(_sslContext, host.c_str(), host.size()); |             SSLSetPeerDomainName(_sslContext, host.c_str(), host.size()); | ||||||
|  |  | ||||||
|  |             if (!handleTLSOptions(errMsg)) return false; // FIXME not calling close() | ||||||
|  |  | ||||||
|             if (_tlsOptions.isPeerVerifyDisabled()) |             if (_tlsOptions.isPeerVerifyDisabled()) | ||||||
|             { |             { | ||||||
|                 Boolean option(1); |                 Boolean option(1); | ||||||
|   | |||||||
| @@ -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, | ||||||
| @@ -32,6 +34,8 @@ namespace ix | |||||||
|         virtual ssize_t recv(void* buffer, size_t length) final; |         virtual ssize_t recv(void* buffer, size_t length) final; | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |         bool handleTLSOptions(std::string& errMsg); | ||||||
|  |  | ||||||
|         SSLContextRef _sslContext; |         SSLContextRef _sslContext; | ||||||
|         mutable std::mutex _mutex; // AppleSSL routines are not thread-safe |         mutable std::mutex _mutex; // AppleSSL routines are not thread-safe | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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(); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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(); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
|  |  | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <fstream> | #include <fstream> | ||||||
|  | #include <sstream> | ||||||
|  |  | ||||||
| namespace ix | namespace ix | ||||||
| { | { | ||||||
| @@ -71,4 +72,16 @@ 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; | ||||||
|  |         ss << "  ciphers  = " << ciphers << std::endl; | ||||||
|  |         return ss.str(); | ||||||
|  |     } | ||||||
| } // namespace ix | } // namespace ix | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -144,7 +144,9 @@ namespace ix | |||||||
|  |  | ||||||
|         if (!UrlParser::parse(url, protocol, host, path, query, port)) |         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; |         std::string errorMsg; | ||||||
|   | |||||||
| @@ -6,4 +6,4 @@ | |||||||
|  |  | ||||||
| #pragma once | #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: |     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(); | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
							
								
								
									
										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("--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
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								ws/ws.h
									
									
									
									
									
								
							| @@ -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, | ||||||
|   | |||||||
| @@ -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()) | ||||||
|             ; |             ; | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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,9 +37,12 @@ namespace ix | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         ix::CobraConnection conn; |         ix::CobraConnection conn; | ||||||
|         conn.configure( |         conn.configure(appkey, | ||||||
|             appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); |                        endpoint, | ||||||
|         conn.connect(); |                        rolename, | ||||||
|  |                        rolesecret, | ||||||
|  |                        ix::WebSocketPerMessageDeflateOptions(true), | ||||||
|  |                        tlsOptions); | ||||||
|  |  | ||||||
|         // Display incoming messages |         // Display incoming messages | ||||||
|         std::atomic<bool> authenticated(false); |         std::atomic<bool> authenticated(false); | ||||||
| @@ -89,6 +93,8 @@ namespace ix | |||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         conn.connect(); | ||||||
|  |  | ||||||
|         while (!authenticated) |         while (!authenticated) | ||||||
|             ; |             ; | ||||||
|         while (!messageAcked) |         while (!messageAcked) | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user