Compare commits

...

19 Commits

Author SHA1 Message Date
0c5a4af722 trigger github actions on pull requests 2021-08-13 05:03:08 -07:00
3baf59a031 (ws) bump CLI command line parsing library from 1.8 to 2.0 2021-07-27 20:48:25 +02:00
b5804c2082 cmake tweak 2021-06-09 10:46:31 -07:00
30bcddb99f (ws) ws connect has a -g option to gzip decompress messages for API such as the websocket Huobi Global. 2021-06-08 09:49:27 -07:00
47fd04e210 (websocket client + server) WebSocketMessage class tweak to fix unsafe patterns 2021-06-08 09:47:53 -07:00
4f5b0c4f07 Noexcept ix web socket per message deflate options (#299)
* Fix unsafe calls and safeguard WebSocketMessage from being called w/
temporaries

* Use unnamed namespace to express internal linkage

* Avoid returning references that are mutex protected
Motivation for this MR

The antipattern of returning references to mutex protected members was
removed. Since a caller can hold the reference it would make all class
level locking meaningless.

Instead values are returned. The IXWebSocketPerMessageDeflateOptions
class was shrunk by 7 bytes (1 padding + 2*3) after changing the int
members to the used uint8_t; side effects of that were handled.

An inefficient "string -> int" was replaced by standard library. As
seen here http://coliru.stacked-crooked.com/a/46b5990bafb9c626 this
gives an order of magnitude better performance.

* noexcept string to integer conversion
2021-06-07 11:19:52 -07:00
c2d497abc5 Avoid returning references that are mutex protected (#297)
* Fix unsafe calls and safeguard WebSocketMessage from being called w/
temporaries

* Use unnamed namespace to express internal linkage

* Avoid returning references that are mutex protected
Motivation for this MR

The antipattern of returning references to mutex protected members was
removed. Since a caller can hold the reference it would make all class
level locking meaningless.

Instead values are returned. The IXWebSocketPerMessageDeflateOptions
class was shrunk by 7 bytes (1 padding + 2*3) after changing the int
members to the used uint8_t; side effects of that were handled.

An inefficient "string -> int" was replaced by standard library. As
seen here http://coliru.stacked-crooked.com/a/46b5990bafb9c626 this
gives an order of magnitude better performance.
2021-06-05 11:23:18 -07:00
bbe2ae6dd3 fix: check the request's headers rather than the empty response's headers for User-Agent and Accept (#296) 2021-06-05 11:19:53 -07:00
26897b2425 Fix unsafe calls and safeguard WebSocketMessage (#294)
* Fix unsafe calls and safeguard WebSocketMessage from being called w/
temporaries

* Use unnamed namespace to express internal linkage
2021-06-03 18:39:38 -07:00
e3c98a03cc (websocket server) Handle and accept firefox browser special upgrade value (keep-alive, Upgrade) 2021-05-27 10:54:21 -07:00
97fedf9482 (Windows) move EINVAL (re)definition from IXSocket.h to IXNetSystem.h (fix #289) 2021-05-27 10:54:21 -07:00
ae187c0e98 Readme: Add mingw to build matrix 2021-05-18 11:15:21 -07:00
0f21a20fe3 Move errno windows definitions to IXNetSystem.h 2021-05-17 19:04:02 -07:00
54db6ec8bb add notes about ssl configuration in demo program 2021-05-09 13:45:01 -07:00
0e0a748037 Remove warnings (#284) 2021-04-19 09:25:06 -07:00
3b19b0eeca http client: DEL is not a verb, but DELETE is, fix #281 2021-04-04 23:27:28 -07:00
dbfe3104e8 Fixed example code for the new API of IXWebSocketServer (#279) 2021-03-26 23:55:34 -07:00
68fd8c20d6 change CI mkdocs invocation 2021-03-25 11:12:59 -07:00
d932af8568 (cmake) install IXUniquePtr.h 2021-03-25 10:55:59 -07:00
31 changed files with 3976 additions and 1719 deletions

View File

@ -21,5 +21,7 @@ jobs:
pip install pygments
- name: Build doc
run: |
git clean -dfx .
git fetch
git pull
mkdocs gh-deploy

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
linux:

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
linux:

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
mac_tsan_mbedtls:

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
mac_tsan_openssl:

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
mac_tsan_sectransport:

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
uwp:

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
windows:

View File

@ -3,6 +3,7 @@ on:
push:
paths-ignore:
- 'docs/**'
pull_request:
jobs:
windows:

View File

@ -88,6 +88,7 @@ set( IXWEBSOCKET_HEADERS
ixwebsocket/IXSocketTLSOptions.h
ixwebsocket/IXStrCaseCompare.h
ixwebsocket/IXUdpSocket.h
ixwebsocket/IXUniquePtr.h
ixwebsocket/IXUrlParser.h
ixwebsocket/IXUuid.h
ixwebsocket/IXUtf8Validator.h

View File

@ -24,6 +24,7 @@ A bad security bug affecting users compiling with SSL enabled and OpenSSL as the
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXUserAgent.h>
#include <iostream>
int main()
@ -34,6 +35,8 @@ int main()
// Our websocket object
ix::WebSocket webSocket;
// Connect to a server with encryption
// See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration
std::string url("wss://echo.websocket.org");
webSocket.setUrl(url);
@ -53,6 +56,12 @@ int main()
std::cout << "Connection established" << std::endl;
std::cout << "> " << std::flush;
}
else if (msg->type == ix::WebSocketMessageType::Error)
{
// Maybe SSL is not configured properly
std::cout << "Connection error: " << msg->errorInfo.reason << std::endl;
std::cout << "> " << std::flush;
}
}
);
@ -123,6 +132,7 @@ To check the performance of a websocket library, you can look at the [autoroute]
| Windows | Disabled | None | [![Build2][5]][0] |
| UWP | Disabled | None | [![Build2][6]][0] |
| Linux | OpenSSL | Address Sanitizer | [![Build2][7]][0] |
| Mingw | Disabled | None | [![Build2][8]][0] |
* ASAN fails on Linux because of a known problem, we need a
* Some tests are disabled on Windows/UWP because of a pathing problem
@ -136,4 +146,5 @@ To check the performance of a websocket library, you can look at the [autoroute]
[5]: https://github.com/machinezone/IXWebSocket/workflows/windows/badge.svg
[6]: https://github.com/machinezone/IXWebSocket/workflows/uwp/badge.svg
[7]: https://github.com/machinezone/IXWebSocket/workflows/linux_asan/badge.svg
[8]: https://github.com/machinezone/IXWebSocket/workflows/unittest_windows_gcc/badge.svg

View File

@ -2,6 +2,34 @@
All changes to this project will be documented in this file.
## [11.2.10] - 2021-07-27
(ws) bump CLI command line parsing library from 1.8 to 2.0
## [11.2.9] - 2021-06-08
(ws) ws connect has a -g option to gzip decompress messages for API such as the websocket Huobi Global.
## [11.2.8] - 2021-06-03
(websocket client + server) WebSocketMessage class tweak to fix unsafe patterns
## [11.2.7] - 2021-05-27
(websocket server) Handle and accept firefox browser special upgrade value (keep-alive, Upgrade)
## [11.2.6] - 2021-05-18
(Windows) move EINVAL (re)definition from IXSocket.h to IXNetSystem.h (fix #289)
## [11.2.5] - 2021-04-04
(http client) DEL is not an HTTP method name, but DELETE is
## [11.2.4] - 2021-03-25
(cmake) install IXUniquePtr.h
## [11.2.3] - 2021-03-24
(ssl + windows) missing include for CertOpenStore function

View File

@ -374,13 +374,10 @@ The webSocket reference is guaranteed to be always valid ; by design the callbac
// Bound host name, max connections and listen backlog can also be passed in as parameters.
ix::WebSocketServer server(port);
server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionState,
WebSocket& webSocket,
const WebSocketMessagePtr& msg)
{
server.setOnClientMessageCallback([](std::shared_ptr<ix::ConnectionState> connectionState, ix::WebSocket & webSocket, const ix::WebSocketMessagePtr & msg) {
// The ConnectionState object contains information about the connection,
// at this point only the client ip address and the port.
std::cout << "Remote ip: " << connectionState->getRemoteIp();
std::cout << "Remote ip: " << connectionState->getRemoteIp() << std::endl;
if (msg->type == ix::WebSocketMessageType::Open)
{
@ -398,7 +395,7 @@ server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionSta
std::cout << "Headers:" << std::endl;
for (auto it : msg->openInfo.headers)
{
std::cout << it.first << ": " << it.second << std::endl;
std::cout << "\t" << it.first << ": " << it.second << std::endl;
}
}
else if (msg->type == ix::WebSocketMessageType::Message)
@ -407,9 +404,11 @@ server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionSta
// All connected clients are available in an std::set. See the broadcast cpp example.
// Second parameter tells whether we are sending the message in binary or text mode.
// Here we send it in the same mode as it was received.
std::cout << "Received: " << msg->str << std::endl;
webSocket.send(msg->str, msg->binary);
}
);
});
auto res = server.listen();
if (!res.first)

View File

@ -137,7 +137,7 @@ namespace ix
{
contentLength = std::stoi(headers["Content-Length"]);
}
catch (std::exception)
catch (const std::exception&)
{
return std::make_tuple(
false, "Error parsing HTTP Header 'Content-Length'", httpRequest);

View File

@ -20,10 +20,11 @@
namespace ix
{
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
const std::string HttpClient::kPost = "POST";
const std::string HttpClient::kGet = "GET";
const std::string HttpClient::kHead = "HEAD";
const std::string HttpClient::kDel = "DEL";
const std::string HttpClient::kDelete = "DELETE";
const std::string HttpClient::kPut = "PUT";
const std::string HttpClient::kPatch = "PATCH";
@ -189,14 +190,14 @@ namespace ix
}
// Set a default Accept header if none is present
if (headers.find("Accept") == headers.end())
if (args->extraHeaders.find("Accept") == args->extraHeaders.end())
{
ss << "Accept: */*"
<< "\r\n";
}
// Set a default User agent if none is present
if (headers.find("User-Agent") == headers.end())
if (args->extraHeaders.find("User-Agent") == args->extraHeaders.end())
{
ss << "User-Agent: " << userAgent() << "\r\n";
}
@ -557,9 +558,9 @@ namespace ix
return request(url, kHead, std::string(), args);
}
HttpResponsePtr HttpClient::del(const std::string& url, HttpRequestArgsPtr args)
HttpResponsePtr HttpClient::Delete(const std::string& url, HttpRequestArgsPtr args)
{
return request(url, kDel, std::string(), args);
return request(url, kDelete, std::string(), args);
}
HttpResponsePtr HttpClient::request(const std::string& url,

View File

@ -30,7 +30,7 @@ namespace ix
HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args);
HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args);
HttpResponsePtr del(const std::string& url, HttpRequestArgsPtr args);
HttpResponsePtr Delete(const std::string& url, HttpRequestArgsPtr args);
HttpResponsePtr post(const std::string& url,
const HttpParameters& httpParameters,
@ -94,7 +94,7 @@ namespace ix
const static std::string kPost;
const static std::string kGet;
const static std::string kHead;
const static std::string kDel;
const static std::string kDelete;
const static std::string kPut;
const static std::string kPatch;

View File

@ -193,6 +193,7 @@ namespace ix
#endif
}
#if defined(_WIN32) && defined(__GNUC__)
static int hexval(unsigned c)
{
if (c - '0' < 10) return c - '0';
@ -200,6 +201,7 @@ namespace ix
if (c - 'a' < 6) return c - 'a' + 10;
return -1;
}
#endif
//
// mingw does not have inet_pton, which were taken as is from the musl C library.

View File

@ -18,6 +18,19 @@
#include <io.h>
#include <ws2def.h>
#undef EWOULDBLOCK
#undef EAGAIN
#undef EINPROGRESS
#undef EBADF
#undef EINVAL
// map to WSA error codes
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EAGAIN WSATRY_AGAIN
#define EINPROGRESS WSAEINPROGRESS
#define EBADF WSAEBADF
#define EINVAL WSAEINVAL
// Define our own poll on Windows, as a wrapper on top of select
typedef unsigned long int nfds_t;

View File

@ -15,20 +15,6 @@
#ifdef _WIN32
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#undef EWOULDBLOCK
#undef EAGAIN
#undef EINPROGRESS
#undef EBADF
#undef EINVAL
// map to WSA error codes
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EAGAIN WSATRY_AGAIN
#define EINPROGRESS WSAEINPROGRESS
#define EBADF WSAEBADF
#define EINVAL WSAEINVAL
#endif
#include "IXCancellationRequest.h"

View File

@ -15,6 +15,12 @@
#include <cmath>
namespace
{
const std::string emptyMsg;
} // namespace
namespace ix
{
OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr;
@ -38,7 +44,7 @@ namespace ix
[this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) {
_onMessageCallback(
ix::make_unique<WebSocketMessage>(WebSocketMessageType::Close,
"",
emptyMsg,
wireSize,
WebSocketErrorInfo(),
WebSocketOpenInfo(),
@ -69,7 +75,7 @@ namespace ix
_extraHeaders = headers;
}
const std::string& WebSocket::getUrl() const
const std::string WebSocket::getUrl() const
{
std::lock_guard<std::mutex> lock(_configMutex);
return _url;
@ -88,7 +94,7 @@ namespace ix
_socketTLSOptions = socketTLSOptions;
}
const WebSocketPerMessageDeflateOptions& WebSocket::getPerMessageDeflateOptions() const
const WebSocketPerMessageDeflateOptions WebSocket::getPerMessageDeflateOptions() const
{
std::lock_guard<std::mutex> lock(_configMutex);
return _perMessageDeflateOptions;
@ -217,7 +223,7 @@ namespace ix
_onMessageCallback(ix::make_unique<WebSocketMessage>(
WebSocketMessageType::Open,
"",
emptyMsg,
0,
WebSocketErrorInfo(),
WebSocketOpenInfo(status.uri, status.headers, status.protocol),
@ -251,7 +257,7 @@ namespace ix
_onMessageCallback(
ix::make_unique<WebSocketMessage>(WebSocketMessageType::Open,
"",
emptyMsg,
0,
WebSocketErrorInfo(),
WebSocketOpenInfo(status.uri, status.headers),
@ -338,7 +344,7 @@ namespace ix
connectErr.http_status = status.http_status;
_onMessageCallback(ix::make_unique<WebSocketMessage>(WebSocketMessageType::Error,
"",
emptyMsg,
0,
connectErr,
WebSocketOpenInfo(),

View File

@ -92,8 +92,8 @@ namespace ix
ReadyState getReadyState() const;
static std::string readyStateToString(ReadyState readyState);
const std::string& getUrl() const;
const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
const std::string getUrl() const;
const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const;
int getPingInterval() const;
size_t bufferedAmount() const;

View File

@ -204,6 +204,9 @@ namespace ix
// Check the value of the connection field
// Some websocket servers (Go/Gorilla?) send lowercase values for the
// connection header, so do a case insensitive comparison
//
// See https://github.com/apache/thrift/commit/7c4bdf9914fcba6c89e0f69ae48b9675578f084a
//
if (!insensitiveStringCompare(headers["connection"], "Upgrade"))
{
std::stringstream ss;
@ -296,7 +299,8 @@ namespace ix
return sendErrorResponse(400, "Missing Upgrade header");
}
if (!insensitiveStringCompare(headers["upgrade"], "WebSocket"))
if (!insensitiveStringCompare(headers["upgrade"], "WebSocket") &&
headers["Upgrade"] != "keep-alive, Upgrade") // special case for firefox
{
return sendErrorResponse(400,
"Invalid Upgrade header, "

View File

@ -42,6 +42,18 @@ namespace ix
{
;
}
/**
* @brief Deleted overload to prevent binding `str` to a temporary, which would cause
* undefined behavior since class members don't extend lifetime beyond the constructor call.
*/
WebSocketMessage(WebSocketMessageType t,
std::string&& s,
size_t w,
WebSocketErrorInfo e,
WebSocketOpenInfo o,
WebSocketCloseInfo c,
bool b = false) = delete;
};
using WebSocketMessagePtr = std::unique_ptr<WebSocketMessage>;

View File

@ -14,12 +14,12 @@ namespace ix
{
/// Default values as defined in the RFC
const uint8_t WebSocketPerMessageDeflateOptions::kDefaultServerMaxWindowBits = 15;
static const int minServerMaxWindowBits = 8;
static const int maxServerMaxWindowBits = 15;
static const uint8_t minServerMaxWindowBits = 8;
static const uint8_t maxServerMaxWindowBits = 15;
const uint8_t WebSocketPerMessageDeflateOptions::kDefaultClientMaxWindowBits = 15;
static const int minClientMaxWindowBits = 8;
static const int maxClientMaxWindowBits = 15;
static const uint8_t minClientMaxWindowBits = 8;
static const uint8_t maxClientMaxWindowBits = 15;
WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions(
bool enabled,
@ -85,11 +85,7 @@ namespace ix
if (startsWith(token, "server_max_window_bits="))
{
std::string val = token.substr(token.find_last_of("=") + 1);
std::stringstream ss;
ss << val;
int x;
ss >> x;
uint8_t x = strtol(token.substr(token.find_last_of("=") + 1).c_str(), nullptr, 10);
// Sanitize values to be in the proper range [8, 15] in
// case a server would give us bogus values
@ -99,11 +95,7 @@ namespace ix
if (startsWith(token, "client_max_window_bits="))
{
std::string val = token.substr(token.find_last_of("=") + 1);
std::stringstream ss;
ss << val;
int x;
ss >> x;
uint8_t x = strtol(token.substr(token.find_last_of("=") + 1).c_str(), nullptr, 10);
// Sanitize values to be in the proper range [8, 15] in
// case a server would give us bogus values

View File

@ -39,8 +39,8 @@ namespace ix
bool _enabled;
bool _clientNoContextTakeover;
bool _serverNoContextTakeover;
int _clientMaxWindowBits;
int _serverMaxWindowBits;
uint8_t _clientMaxWindowBits;
uint8_t _serverMaxWindowBits;
void sanitizeClientMaxWindowBits();
};

View File

@ -191,7 +191,6 @@ namespace ix
// Make sure the OS send buffer is flushed before moving on
do
{
size_t bufferedAmount = client->bufferedAmount();
std::chrono::duration<double, std::milli> duration(500);
std::this_thread::sleep_for(duration);
} while (client->bufferedAmount() != 0);

View File

@ -6,4 +6,4 @@
#pragma once
#define IX_WEBSOCKET_VERSION "11.2.3"
#define IX_WEBSOCKET_VERSION "11.2.10"

View File

@ -15,6 +15,7 @@
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXUserAgent.h>
#include <iostream>
int main()
@ -25,9 +26,12 @@ int main()
// Our websocket object
ix::WebSocket webSocket;
// Connect to a server with encryption
// See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration
std::string url("wss://echo.websocket.org");
webSocket.setUrl(url);
std::cout << ix::userAgent() << std::endl;
std::cout << "Connecting to " << url << "..." << std::endl;
// Setup a callback to be fired (in a background thread, watch out for race conditions !)
@ -44,6 +48,12 @@ int main()
std::cout << "Connection established" << std::endl;
std::cout << "> " << std::flush;
}
else if (msg->type == ix::WebSocketMessageType::Error)
{
// Maybe SSL is not configured properly
std::cout << "Connection error: " << msg->errorInfo.reason << std::endl;
std::cout << "> " << std::flush;
}
}
);

View File

@ -22,37 +22,37 @@ install: brew
# Default rule does not use python as that requires first time users to have Python3 installed
#
brew:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=OFF -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
# Docker default target. We've had problems with OpenSSL and TLS 1.3 (on the
# server side ?) and I can't work-around it easily, so we're using mbedtls on
# Linux for the SSL backend, which works great.
ws_mbedtls_install:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_ZLIB=OFF -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_ZLIB=OFF -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
ws:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
ws_unity:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
ws_install:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install)
ws_install_release:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install)
ws_openssl_install:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; ninja install)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; ninja install)
ws_mbedtls:
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4)
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4)
ws_no_ssl:
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4)
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4)
ws_no_python:
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j4 install)
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j4 install)
uninstall:
xargs rm -fv < build/install_manifest.txt
@ -111,27 +111,27 @@ test_server:
(cd test && npm i ws && node broadcast-server.js)
test:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 ..)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 ..)
(cd build ; ninja)
(cd build ; ninja -v test)
test_asan:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer")
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer")
(cd build ; ninja)
(cd build ; ctest -V .)
test_tsan_mbedtls:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
(cd build ; ninja)
(cd build ; ninja test)
test_tsan_openssl:
mkdir -p build && (cd build ; cmake -GNinja --DCMAKE_UNITY_BUILD=ON DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
(cd build ; ninja)
(cd build ; ninja test)
test_tsan_sectransport:
mkdir -p build && (cd build ; cmake -GNinja --DCMAKE_UNITY_BUILD=ON DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
(cd build ; ninja)
(cd build ; ninja test)

File diff suppressed because it is too large Load Diff

View File

@ -632,7 +632,8 @@ namespace ix
uint32_t maxWaitBetweenReconnectionRetries,
const ix::SocketTLSOptions& tlsOptions,
const std::string& subprotocol,
int pingIntervalSecs);
int pingIntervalSecs,
bool decompressGzipMessages);
void subscribe(const std::string& channel);
void start();
@ -657,6 +658,7 @@ namespace ix
bool _binaryMode;
std::atomic<int> _receivedBytes;
std::atomic<int> _sentBytes;
bool _decompressGzipMessages;
void log(const std::string& msg);
WebSocketHttpHeaders parseHeaders(const std::string& data);
@ -670,12 +672,14 @@ namespace ix
uint32_t maxWaitBetweenReconnectionRetries,
const ix::SocketTLSOptions& tlsOptions,
const std::string& subprotocol,
int pingIntervalSecs)
int pingIntervalSecs,
bool decompressGzipMessages)
: _url(url)
, _disablePerMessageDeflate(disablePerMessageDeflate)
, _binaryMode(binaryMode)
, _receivedBytes(0)
, _sentBytes(0)
, _decompressGzipMessages(decompressGzipMessages)
{
if (disableAutomaticReconnection)
{
@ -784,7 +788,21 @@ namespace ix
{
spdlog::info("Received {} bytes", msg->wireSize);
ss << "ws_connect: received message: " << msg->str;
std::string payload = msg->str;
if (_decompressGzipMessages)
{
std::string decompressedBytes;
if (gzipDecompress(payload, decompressedBytes))
{
payload = decompressedBytes;
}
else
{
spdlog::error("Error decompressing: {}", payload);
}
}
ss << "ws_connect: received message: " << payload;
log(ss.str());
}
else if (msg->type == ix::WebSocketMessageType::Error)
@ -837,7 +855,8 @@ namespace ix
uint32_t maxWaitBetweenReconnectionRetries,
const ix::SocketTLSOptions& tlsOptions,
const std::string& subprotocol,
int pingIntervalSecs)
int pingIntervalSecs,
bool decompressGzipMessages)
{
std::cout << "Type Ctrl-D to exit prompt..." << std::endl;
WebSocketConnect webSocketChat(url,
@ -848,7 +867,8 @@ namespace ix
maxWaitBetweenReconnectionRetries,
tlsOptions,
subprotocol,
pingIntervalSecs);
pingIntervalSecs,
decompressGzipMessages);
webSocketChat.start();
while (true)
@ -2490,6 +2510,7 @@ int main(int argc, char** argv)
uint32_t maxWaitBetweenReconnectionRetries = 10 * 1000; // 10 seconds
int pingIntervalSecs = 30;
int runCount = 1;
bool decompressGzipMessages = false;
auto addGenericOptions = [&pidfile](CLI::App* app) {
app->add_option("--pidfile", pidfile, "Pid file");
@ -2552,6 +2573,7 @@ int main(int argc, char** argv)
"Max Wait Time between reconnection retries");
connectApp->add_option("--ping_interval", pingIntervalSecs, "Interval between sending pings");
connectApp->add_option("--subprotocol", subprotocol, "Subprotocol");
connectApp->add_flag("-g", decompressGzipMessages, "Decompress gziped messages");
addGenericOptions(connectApp);
addTLSOptions(connectApp);
@ -2740,7 +2762,8 @@ int main(int argc, char** argv)
maxWaitBetweenReconnectionRetries,
tlsOptions,
subprotocol,
pingIntervalSecs);
pingIntervalSecs,
decompressGzipMessages);
}
else if (app.got_subcommand("autoroute"))
{