Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
332ffb0603 | |||
90df3d1805 | |||
bda1bb6ab4 | |||
d4e1f71e3c | |||
adf6aa1d6c | |||
cb1f9f5a44 | |||
83ae105edb | |||
7642ccc99e | |||
cb1ec7dc96 | |||
09b9483ddf | |||
27a8ae309f | |||
3df7c942d7 | |||
6a4d69afc5 | |||
0a11132b07 | |||
cb9f0cb968 | |||
b1f30bb40f | |||
4ef04b8339 | |||
e581f29b42 | |||
a42f115f79 | |||
5ce1a596cf | |||
21db7b6c5b | |||
e15a2900e7 | |||
140a21c8b3 | |||
6d0c568aaa | |||
c96abcef1c | |||
4a9b0b9dfd | |||
8837d5e784 | |||
242c945400 | |||
feab4dee0f | |||
8175829b4b | |||
4c66a7561e | |||
111475e65c |
2
.github/workflows/ccpp.yml
vendored
2
.github/workflows/ccpp.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: C/C++ CI
|
name: unittest
|
||||||
|
|
||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
|
19
CMake/FindSpdLog.cmake
Normal file
19
CMake/FindSpdLog.cmake
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Find package structure taken from libcurl
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_path(SPDLOG_INCLUDE_DIRS spdlog/spdlog.h)
|
||||||
|
find_library(JSONCPP_LIBRARY spdlog)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(SPDLOG
|
||||||
|
FOUND_VAR
|
||||||
|
SPDLOG_FOUND
|
||||||
|
REQUIRED_VARS
|
||||||
|
SPDLOG_LIBRARY
|
||||||
|
SPDLOG_INCLUDE_DIRS
|
||||||
|
FAIL_MESSAGE
|
||||||
|
"Could NOT find spdlog"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SPDLOG_INCLUDE_DIRS ${SPDLOG_INCLUDE_DIRS})
|
||||||
|
set(SPDLOG_LIBRARIES ${SPDLOG_LIBRARY})
|
@ -201,8 +201,8 @@ if (ZLIB_FOUND)
|
|||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
target_link_libraries(ixwebsocket ${ZLIB_LIBRARIES})
|
target_link_libraries(ixwebsocket ${ZLIB_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
add_subdirectory(third_party/zlib)
|
|
||||||
include_directories(third_party/zlib ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib)
|
include_directories(third_party/zlib ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib)
|
||||||
|
add_subdirectory(third_party/zlib)
|
||||||
target_link_libraries(ixwebsocket zlibstatic)
|
target_link_libraries(ixwebsocket zlibstatic)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -230,6 +230,7 @@ if (USE_WS OR USE_TEST)
|
|||||||
add_subdirectory(ixcobra)
|
add_subdirectory(ixcobra)
|
||||||
add_subdirectory(ixsnake)
|
add_subdirectory(ixsnake)
|
||||||
add_subdirectory(ixsentry)
|
add_subdirectory(ixsentry)
|
||||||
|
add_subdirectory(ixbots)
|
||||||
|
|
||||||
add_subdirectory(third_party/spdlog spdlog)
|
add_subdirectory(third_party/spdlog spdlog)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Hello world
|
## Hello world
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
IXWebSocket is a C++ library for WebSocket client and server development. It has minimal dependencies (no boost), is very simple to use and support everything you'll likely need for websocket dev (SSL, deflate compression, compiles on most platforms, etc...). HTTP client and server code is also available, but it hasn't received as much testing.
|
IXWebSocket is a C++ library for WebSocket client and server development. It has minimal dependencies (no boost), is very simple to use and support everything you'll likely need for websocket dev (SSL, deflate compression, compiles on most platforms, etc...). HTTP client and server code is also available, but it hasn't received as much testing.
|
||||||
|
|
||||||
|
@ -1,6 +1,58 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All changes to this project will be documented in this file.
|
All changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [8.2.3] - 2020-03-13
|
||||||
|
|
||||||
|
(cobra client) pass the message position to the subscription data callback
|
||||||
|
|
||||||
|
## [8.2.2] - 2020-03-12
|
||||||
|
|
||||||
|
(openssl tls backend) Fix a hand in OpenSSL when using TLS v1.3 ... by disabling TLS v1.3
|
||||||
|
|
||||||
|
## [8.2.1] - 2020-03-11
|
||||||
|
|
||||||
|
(cobra) IXCobraConfig struct has tlsOptions and per message deflate options
|
||||||
|
|
||||||
|
## [8.2.0] - 2020-03-11
|
||||||
|
|
||||||
|
(cobra) add IXCobraConfig struct to pass cobra config around
|
||||||
|
|
||||||
|
## [8.1.9] - 2020-03-09
|
||||||
|
|
||||||
|
(ws cobra_subscribe) add a --fluentd option to wrap a message in an enveloppe so that fluentd can recognize it
|
||||||
|
|
||||||
|
## [8.1.8] - 2020-03-02
|
||||||
|
|
||||||
|
(websocket server) fix regression with disabling zlib extension on the server side. If a client does not support this extension the server will handle it fine. We still need to figure out how to disable the option.
|
||||||
|
|
||||||
|
## [8.1.7] - 2020-02-26
|
||||||
|
|
||||||
|
(websocket) traffic tracker received bytes is message size while it should be wire size
|
||||||
|
|
||||||
|
## [8.1.6] - 2020-02-26
|
||||||
|
|
||||||
|
(ws_connect) display sent/received bytes statistics on exit
|
||||||
|
|
||||||
|
## [8.1.5] - 2020-02-23
|
||||||
|
|
||||||
|
(server) give thread name to some usual worker threads / unittest is broken !!
|
||||||
|
|
||||||
|
## [8.1.4] - 2020-02-22
|
||||||
|
|
||||||
|
(websocket server) fix regression from 8.1.2, where per-deflate message compression was always disabled
|
||||||
|
|
||||||
|
## [8.1.3] - 2020-02-21
|
||||||
|
|
||||||
|
(client + server) Fix #155 / http header parser should treat the space(s) after the : delimiter as optional. Fixing this bug made us discover that websocket sub-protocols are not properly serialiazed, but start with a ,
|
||||||
|
|
||||||
|
## [8.1.2] - 2020-02-18
|
||||||
|
|
||||||
|
(WebSocketServer) add option to disable deflate compression, exposed with the -x option to ws echo_server
|
||||||
|
|
||||||
|
## [8.1.1] - 2020-02-18
|
||||||
|
|
||||||
|
(ws cobra to statsd and sentry sender) exit if no messages are received for one minute, which is a sign that something goes wrong on the server side. That should be changed to be configurable in the future
|
||||||
|
|
||||||
## [8.1.0] - 2020-02-13
|
## [8.1.0] - 2020-02-13
|
||||||
|
|
||||||
(http client + sentry minidump upload) Multipart stream closing boundary is invalid + mark some options as mandatory in the command line tools
|
(http client + sentry minidump upload) Multipart stream closing boundary is invalid + mark some options as mandatory in the command line tools
|
||||||
|
@ -6,7 +6,7 @@ The per message deflate compression option is supported. It can lead to very nic
|
|||||||
|
|
||||||
### TLS/SSL
|
### TLS/SSL
|
||||||
|
|
||||||
Connections can be optionally secured and encrypted with TLS/SSL when using a wss:// endpoint, or using normal un-encrypted socket with ws:// endpoints. AppleSSL is used on iOS and macOS, OpenSSL is used on Android and Linux, mbedTLS is used on Windows.
|
Connections can be optionally secured and encrypted with TLS/SSL when using a wss:// endpoint, or using normal un-encrypted socket with ws:// endpoints. AppleSSL is used on iOS and macOS, OpenSSL and mbedTLS can be used on Android, Linux and Windows.
|
||||||
|
|
||||||
### Polling and background thread work
|
### Polling and background thread work
|
||||||
|
|
||||||
|
45
ixbots/CMakeLists.txt
Normal file
45
ixbots/CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#
|
||||||
|
# Author: Benjamin Sergeant
|
||||||
|
# Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
set (IXBOTS_SOURCES
|
||||||
|
ixbots/IXCobraToSentryBot.cpp
|
||||||
|
ixbots/IXCobraToStatsdBot.cpp
|
||||||
|
ixbots/IXQueueManager.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set (IXBOTS_HEADERS
|
||||||
|
ixbots/IXCobraToSentryBot.h
|
||||||
|
ixbots/IXCobraToStatsdBot.h
|
||||||
|
ixbots/IXQueueManager.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(ixbots STATIC
|
||||||
|
${IXBOTS_SOURCES}
|
||||||
|
${IXBOTS_HEADERS}
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(JsonCpp)
|
||||||
|
if (NOT JSONCPP_FOUND)
|
||||||
|
set(JSONCPP_INCLUDE_DIRS ../third_party/jsoncpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(SpdLog)
|
||||||
|
if (NOT SPDLOG_FOUND)
|
||||||
|
set(SPDLOG_INCLUDE_DIRS ../third_party/spdlog/include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(STATSD_CLIENT_INCLUDE_DIRS ../third_party/statsd-client-cpp/src)
|
||||||
|
|
||||||
|
set(IXBOTS_INCLUDE_DIRS
|
||||||
|
.
|
||||||
|
..
|
||||||
|
../ixcore
|
||||||
|
../ixcobra
|
||||||
|
../ixsentry
|
||||||
|
${JSONCPP_INCLUDE_DIRS}
|
||||||
|
${SPDLOG_INCLUDE_DIRS}
|
||||||
|
${STATSD_CLIENT_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
target_include_directories( ixbots PUBLIC ${IXBOTS_INCLUDE_DIRS} )
|
@ -1,17 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* ws_cobra_to_sentry.cpp
|
* IXCobraToSentryBot.cpp
|
||||||
* Author: Benjamin Sergeant
|
* Author: Benjamin Sergeant
|
||||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <atomic>
|
#include "IXCobraToSentryBot.h"
|
||||||
|
#include "IXQueueManager.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
|
||||||
#include <ixcobra/IXCobraConnection.h>
|
#include <ixcobra/IXCobraConnection.h>
|
||||||
#include <ixsentry/IXSentryClient.h>
|
|
||||||
#include <map>
|
|
||||||
#include <mutex>
|
|
||||||
#include <queue>
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@ -19,99 +16,18 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
class QueueManager
|
int cobra_to_sentry_bot(const CobraConfig& config,
|
||||||
{
|
const std::string& channel,
|
||||||
public:
|
const std::string& filter,
|
||||||
QueueManager(size_t maxQueueSize, std::atomic<bool>& stop)
|
SentryClient& sentryClient,
|
||||||
: _maxQueueSize(maxQueueSize)
|
bool verbose,
|
||||||
, _stop(stop)
|
bool strict,
|
||||||
{
|
size_t maxQueueSize,
|
||||||
}
|
bool enableHeartbeat,
|
||||||
|
int runtime)
|
||||||
Json::Value pop();
|
|
||||||
void add(Json::Value msg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<std::string, std::queue<Json::Value>> _queues;
|
|
||||||
std::mutex _mutex;
|
|
||||||
std::condition_variable _condition;
|
|
||||||
size_t _maxQueueSize;
|
|
||||||
std::atomic<bool>& _stop;
|
|
||||||
};
|
|
||||||
|
|
||||||
Json::Value QueueManager::pop()
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
|
||||||
|
|
||||||
if (_queues.empty())
|
|
||||||
{
|
|
||||||
Json::Value val;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> games;
|
|
||||||
for (auto it : _queues)
|
|
||||||
{
|
|
||||||
games.push_back(it.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::random_shuffle(games.begin(), games.end());
|
|
||||||
std::string game = games[0];
|
|
||||||
|
|
||||||
_condition.wait(lock, [this] { return !_stop; });
|
|
||||||
|
|
||||||
if (_queues[game].empty())
|
|
||||||
{
|
|
||||||
Json::Value val;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto msg = _queues[game].front();
|
|
||||||
_queues[game].pop();
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QueueManager::add(Json::Value msg)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
|
||||||
|
|
||||||
std::string game;
|
|
||||||
if (msg.isMember("device") && msg["device"].isMember("game"))
|
|
||||||
{
|
|
||||||
game = msg["device"]["game"].asString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game.empty()) return;
|
|
||||||
|
|
||||||
// if the sending is not fast enough there is no point
|
|
||||||
// in queuing too many events.
|
|
||||||
if (_queues[game].size() < _maxQueueSize)
|
|
||||||
{
|
|
||||||
_queues[game].push(msg);
|
|
||||||
_condition.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ws_cobra_to_sentry_main(const std::string& appkey,
|
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
const std::string& rolesecret,
|
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& dsn,
|
|
||||||
bool verbose,
|
|
||||||
bool strict,
|
|
||||||
int jobs,
|
|
||||||
size_t maxQueueSize,
|
|
||||||
const ix::SocketTLSOptions& tlsOptions)
|
|
||||||
{
|
{
|
||||||
ix::CobraConnection conn;
|
ix::CobraConnection conn;
|
||||||
conn.configure(appkey,
|
conn.configure(config);
|
||||||
endpoint,
|
|
||||||
rolename,
|
|
||||||
rolesecret,
|
|
||||||
ix::WebSocketPerMessageDeflateOptions(true),
|
|
||||||
tlsOptions);
|
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
Json::FastWriter jsonWriter;
|
Json::FastWriter jsonWriter;
|
||||||
@ -123,28 +39,58 @@ namespace ix
|
|||||||
|
|
||||||
QueueManager queueManager(maxQueueSize, stop);
|
QueueManager queueManager(maxQueueSize, stop);
|
||||||
|
|
||||||
auto timer = [&sentCount, &receivedCount] {
|
auto timer = [&sentCount, &receivedCount, &stop] {
|
||||||
while (true)
|
while (!stop)
|
||||||
{
|
{
|
||||||
spdlog::info("messages received {} sent {}", receivedCount, sentCount);
|
spdlog::info("messages received {} sent {}", receivedCount, sentCount);
|
||||||
|
|
||||||
auto duration = std::chrono::seconds(1);
|
auto duration = std::chrono::seconds(1);
|
||||||
std::this_thread::sleep_for(duration);
|
std::this_thread::sleep_for(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spdlog::info("timer thread done");
|
||||||
};
|
};
|
||||||
|
|
||||||
std::thread t1(timer);
|
std::thread t1(timer);
|
||||||
|
|
||||||
|
auto heartbeat = [&sentCount, &receivedCount, &stop, &enableHeartbeat] {
|
||||||
|
std::string state("na");
|
||||||
|
|
||||||
|
if (!enableHeartbeat) return;
|
||||||
|
|
||||||
|
while (!stop)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "messages received " << receivedCount;
|
||||||
|
ss << "messages sent " << sentCount;
|
||||||
|
|
||||||
|
std::string currentState = ss.str();
|
||||||
|
|
||||||
|
if (currentState == state)
|
||||||
|
{
|
||||||
|
spdlog::error("no messages received or sent for 1 minute, exiting");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
state = currentState;
|
||||||
|
|
||||||
|
auto duration = std::chrono::minutes(1);
|
||||||
|
std::this_thread::sleep_for(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("heartbeat thread done");
|
||||||
|
};
|
||||||
|
|
||||||
|
std::thread t2(heartbeat);
|
||||||
|
|
||||||
auto sentrySender =
|
auto sentrySender =
|
||||||
[&queueManager, verbose, &errorSending, &sentCount, &stop, &throttled, &dsn] {
|
[&queueManager, verbose, &errorSending, &sentCount, &stop, &throttled, &sentryClient] {
|
||||||
SentryClient sentryClient(dsn);
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Json::Value msg = queueManager.pop();
|
Json::Value msg = queueManager.pop();
|
||||||
|
|
||||||
|
if (stop) break;
|
||||||
if (msg.isNull()) continue;
|
if (msg.isNull()) continue;
|
||||||
if (stop) return;
|
|
||||||
|
|
||||||
auto ret = sentryClient.send(msg, verbose);
|
auto ret = sentryClient.send(msg, verbose);
|
||||||
HttpResponsePtr response = ret.first;
|
HttpResponsePtr response = ret.first;
|
||||||
@ -216,17 +162,13 @@ namespace ix
|
|||||||
++sentCount;
|
++sentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stop) return;
|
if (stop) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spdlog::info("sentrySender thread done");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a thread pool
|
std::thread t3(sentrySender);
|
||||||
spdlog::info("Starting {} sentry sender jobs", jobs);
|
|
||||||
std::vector<std::thread> pool;
|
|
||||||
for (int i = 0; i < jobs; i++)
|
|
||||||
{
|
|
||||||
pool.push_back(std::thread(sentrySender));
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.setEventCallback([&conn,
|
conn.setEventCallback([&conn,
|
||||||
&channel,
|
&channel,
|
||||||
@ -259,10 +201,10 @@ namespace ix
|
|||||||
conn.subscribe(channel,
|
conn.subscribe(channel,
|
||||||
filter,
|
filter,
|
||||||
[&jsonWriter, verbose, &throttled, &receivedCount, &queueManager](
|
[&jsonWriter, verbose, &throttled, &receivedCount, &queueManager](
|
||||||
const Json::Value& msg) {
|
const Json::Value& msg, const std::string& position) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
spdlog::info(jsonWriter.write(msg));
|
spdlog::info("Subscriber received message {} -> {}", position, jsonWriter.write(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we cannot send to sentry fast enough, drop the message
|
// If we cannot send to sentry fast enough, drop the message
|
||||||
@ -297,24 +239,42 @@ namespace ix
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
while (true)
|
// Run forever
|
||||||
|
if (runtime == -1)
|
||||||
{
|
{
|
||||||
auto duration = std::chrono::seconds(1);
|
while (true)
|
||||||
std::this_thread::sleep_for(duration);
|
{
|
||||||
|
auto duration = std::chrono::seconds(1);
|
||||||
|
std::this_thread::sleep_for(duration);
|
||||||
|
|
||||||
if (strict && errorSending) break;
|
if (strict && errorSending) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Run for a duration, used by unittesting now
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0 ; i < runtime; ++i)
|
||||||
|
{
|
||||||
|
auto duration = std::chrono::seconds(1);
|
||||||
|
std::this_thread::sleep_for(duration);
|
||||||
|
|
||||||
|
if (strict && errorSending) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.disconnect();
|
//
|
||||||
|
// Cleanup.
|
||||||
// join all the bg threads and stop them.
|
// join all the bg threads and stop them.
|
||||||
|
//
|
||||||
|
conn.disconnect();
|
||||||
stop = true;
|
stop = true;
|
||||||
for (int i = 0; i < jobs; i++)
|
|
||||||
{
|
|
||||||
spdlog::error("joining thread {}", i);
|
|
||||||
pool[i].join();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (strict && errorSending) ? 1 : 0;
|
t1.join();
|
||||||
|
if (t2.joinable()) t2.join();
|
||||||
|
spdlog::info("heartbeat thread done");
|
||||||
|
|
||||||
|
t3.join();
|
||||||
|
|
||||||
|
return (strict && errorSending) ? -1 : (int) sentCount;
|
||||||
}
|
}
|
||||||
} // namespace ix
|
} // namespace ix
|
23
ixbots/ixbots/IXCobraToSentryBot.h
Normal file
23
ixbots/ixbots/IXCobraToSentryBot.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* IXCobraToSentryBot.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ixcobra/IXCobraConfig.h>
|
||||||
|
#include <ixsentry/IXSentryClient.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
int cobra_to_sentry_bot(const CobraConfig& config,
|
||||||
|
const std::string& channel,
|
||||||
|
const std::string& filter,
|
||||||
|
SentryClient& sentryClient,
|
||||||
|
bool verbose,
|
||||||
|
bool strict,
|
||||||
|
size_t maxQueueSize,
|
||||||
|
bool enableHeartbeat,
|
||||||
|
int runtime);
|
||||||
|
} // namespace ix
|
@ -1,9 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* ws_cobra_to_statsd.cpp
|
* IXCobraToStatsdBot.cpp
|
||||||
* Author: Benjamin Sergeant
|
* Author: Benjamin Sergeant
|
||||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "IXCobraToStatsdBot.h"
|
||||||
|
#include "IXQueueManager.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@ -17,59 +20,6 @@
|
|||||||
#include <statsd_client.h>
|
#include <statsd_client.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class QueueManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QueueManager(size_t maxQueueSize, std::atomic<bool>& stop)
|
|
||||||
: _maxQueueSize(maxQueueSize)
|
|
||||||
, _stop(stop)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Json::Value pop();
|
|
||||||
void add(Json::Value msg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::queue<Json::Value> _queue;
|
|
||||||
std::mutex _mutex;
|
|
||||||
std::condition_variable _condition;
|
|
||||||
size_t _maxQueueSize;
|
|
||||||
std::atomic<bool>& _stop;
|
|
||||||
};
|
|
||||||
|
|
||||||
Json::Value QueueManager::pop()
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
|
||||||
|
|
||||||
if (_queue.empty())
|
|
||||||
{
|
|
||||||
Json::Value val;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
_condition.wait(lock, [this] { return !_stop; });
|
|
||||||
|
|
||||||
auto msg = _queue.front();
|
|
||||||
_queue.pop();
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QueueManager::add(Json::Value msg)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
|
||||||
|
|
||||||
// if the sending is not fast enough there is no point
|
|
||||||
// in queuing too many events.
|
|
||||||
if (_queue.size() < _maxQueueSize)
|
|
||||||
{
|
|
||||||
_queue.push(msg);
|
|
||||||
_condition.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
// fields are command line argument that can be specified multiple times
|
// fields are command line argument that can be specified multiple times
|
||||||
@ -109,26 +59,17 @@ namespace ix
|
|||||||
return val.asString();
|
return val.asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ws_cobra_to_statsd_main(const std::string& appkey,
|
int cobra_to_statsd_bot(const ix::CobraConfig& config,
|
||||||
const std::string& endpoint,
|
const std::string& channel,
|
||||||
const std::string& rolename,
|
const std::string& filter,
|
||||||
const std::string& rolesecret,
|
const std::string& host,
|
||||||
const std::string& channel,
|
int port,
|
||||||
const std::string& filter,
|
const std::string& prefix,
|
||||||
const std::string& host,
|
const std::string& fields,
|
||||||
int port,
|
bool verbose)
|
||||||
const std::string& prefix,
|
|
||||||
const std::string& fields,
|
|
||||||
bool verbose,
|
|
||||||
const ix::SocketTLSOptions& tlsOptions)
|
|
||||||
{
|
{
|
||||||
ix::CobraConnection conn;
|
ix::CobraConnection conn;
|
||||||
conn.configure(appkey,
|
conn.configure(config);
|
||||||
endpoint,
|
|
||||||
rolename,
|
|
||||||
rolesecret,
|
|
||||||
ix::WebSocketPerMessageDeflateOptions(true),
|
|
||||||
tlsOptions);
|
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
auto tokens = parseFields(fields);
|
auto tokens = parseFields(fields);
|
||||||
@ -153,6 +94,31 @@ namespace ix
|
|||||||
|
|
||||||
std::thread t1(timer);
|
std::thread t1(timer);
|
||||||
|
|
||||||
|
auto heartbeat = [&sentCount, &receivedCount] {
|
||||||
|
std::string state("na");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "messages received " << receivedCount;
|
||||||
|
ss << "messages sent " << sentCount;
|
||||||
|
|
||||||
|
std::string currentState = ss.str();
|
||||||
|
|
||||||
|
if (currentState == state)
|
||||||
|
{
|
||||||
|
spdlog::error("no messages received or sent for 1 minute, exiting");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
state = currentState;
|
||||||
|
|
||||||
|
auto duration = std::chrono::minutes(1);
|
||||||
|
std::this_thread::sleep_for(duration);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::thread t2(heartbeat);
|
||||||
|
|
||||||
auto statsdSender = [&queueManager, &host, &port, &sentCount, &tokens, &prefix, &stop] {
|
auto statsdSender = [&queueManager, &host, &port, &sentCount, &tokens, &prefix, &stop] {
|
||||||
// statsd client
|
// statsd client
|
||||||
// test with netcat as a server: `nc -ul 8125`
|
// test with netcat as a server: `nc -ul 8125`
|
||||||
@ -184,7 +150,7 @@ namespace ix
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::thread t2(statsdSender);
|
std::thread t3(statsdSender);
|
||||||
|
|
||||||
conn.setEventCallback(
|
conn.setEventCallback(
|
||||||
[&conn, &channel, &filter, &jsonWriter, verbose, &queueManager, &receivedCount](
|
[&conn, &channel, &filter, &jsonWriter, verbose, &queueManager, &receivedCount](
|
||||||
@ -212,10 +178,10 @@ namespace ix
|
|||||||
conn.subscribe(channel,
|
conn.subscribe(channel,
|
||||||
filter,
|
filter,
|
||||||
[&jsonWriter, &queueManager, verbose, &receivedCount](
|
[&jsonWriter, &queueManager, verbose, &receivedCount](
|
||||||
const Json::Value& msg) {
|
const Json::Value& msg, const std::string& position) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
spdlog::info(jsonWriter.write(msg));
|
spdlog::info("Subscriber received message {} -> {}", position, jsonWriter.write(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
receivedCount++;
|
receivedCount++;
|
22
ixbots/ixbots/IXCobraToStatsdBot.h
Normal file
22
ixbots/ixbots/IXCobraToStatsdBot.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* IXCobraToStatsdBot.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ixcobra/IXCobraConfig.h>
|
||||||
|
#include <string>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
int cobra_to_statsd_bot(const ix::CobraConfig& config,
|
||||||
|
const std::string& channel,
|
||||||
|
const std::string& filter,
|
||||||
|
const std::string& host,
|
||||||
|
int port,
|
||||||
|
const std::string& prefix,
|
||||||
|
const std::string& fields,
|
||||||
|
bool verbose);
|
||||||
|
} // namespace ix
|
66
ixbots/ixbots/IXQueueManager.cpp
Normal file
66
ixbots/ixbots/IXQueueManager.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* IXQueueManager.cpp
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IXQueueManager.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
Json::Value QueueManager::pop()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
|
||||||
|
if (_queues.empty())
|
||||||
|
{
|
||||||
|
Json::Value val;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> games;
|
||||||
|
for (auto it : _queues)
|
||||||
|
{
|
||||||
|
games.push_back(it.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::random_shuffle(games.begin(), games.end());
|
||||||
|
std::string game = games[0];
|
||||||
|
|
||||||
|
auto duration = std::chrono::seconds(1);
|
||||||
|
_condition.wait_for(lock, duration);
|
||||||
|
|
||||||
|
if (_queues[game].empty())
|
||||||
|
{
|
||||||
|
Json::Value val;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto msg = _queues[game].front();
|
||||||
|
_queues[game].pop();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueueManager::add(Json::Value msg)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
|
||||||
|
std::string game;
|
||||||
|
if (msg.isMember("device") && msg["device"].isMember("game"))
|
||||||
|
{
|
||||||
|
game = msg["device"]["game"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.empty()) return;
|
||||||
|
|
||||||
|
// if the sending is not fast enough there is no point
|
||||||
|
// in queuing too many events.
|
||||||
|
if (_queues[game].size() < _maxQueueSize)
|
||||||
|
{
|
||||||
|
_queues[game].push(msg);
|
||||||
|
_condition.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
ixbots/ixbots/IXQueueManager.h
Normal file
38
ixbots/ixbots/IXQueueManager.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* IXQueueManager.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <atomic>
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <queue>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
class QueueManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QueueManager(size_t maxQueueSize, std::atomic<bool>& stop)
|
||||||
|
: _maxQueueSize(maxQueueSize)
|
||||||
|
, _stop(stop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value pop();
|
||||||
|
void add(Json::Value msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::queue<Json::Value>> _queues;
|
||||||
|
std::mutex _mutex;
|
||||||
|
std::condition_variable _condition;
|
||||||
|
size_t _maxQueueSize;
|
||||||
|
std::atomic<bool>& _stop;
|
||||||
|
};
|
||||||
|
}
|
@ -13,6 +13,7 @@ set (IXCOBRA_HEADERS
|
|||||||
ixcobra/IXCobraConnection.h
|
ixcobra/IXCobraConnection.h
|
||||||
ixcobra/IXCobraMetricsThreadedPublisher.h
|
ixcobra/IXCobraMetricsThreadedPublisher.h
|
||||||
ixcobra/IXCobraMetricsPublisher.h
|
ixcobra/IXCobraMetricsPublisher.h
|
||||||
|
ixcobra/IXCobraConfig.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(ixcobra STATIC
|
add_library(ixcobra STATIC
|
||||||
|
35
ixcobra/ixcobra/IXCobraConfig.h
Normal file
35
ixcobra/ixcobra/IXCobraConfig.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* IXCobraConfig.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ixwebsocket/IXWebSocketPerMessageDeflateOptions.h>
|
||||||
|
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
struct CobraConfig
|
||||||
|
{
|
||||||
|
std::string appkey;
|
||||||
|
std::string endpoint;
|
||||||
|
std::string rolename;
|
||||||
|
std::string rolesecret;
|
||||||
|
WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions;
|
||||||
|
SocketTLSOptions socketTLSOptions;
|
||||||
|
|
||||||
|
CobraConfig(const std::string& a = std::string(),
|
||||||
|
const std::string& e = std::string(),
|
||||||
|
const std::string& r = std::string(),
|
||||||
|
const std::string& s = std::string())
|
||||||
|
: appkey(a)
|
||||||
|
, endpoint(e)
|
||||||
|
, rolename(r)
|
||||||
|
, rolesecret(s)
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace ix
|
@ -276,6 +276,16 @@ namespace ix
|
|||||||
_webSocket->setPingTimeout(3 * kPingIntervalSecs);
|
_webSocket->setPingTimeout(3 * kPingIntervalSecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CobraConnection::configure(const ix::CobraConfig& config)
|
||||||
|
{
|
||||||
|
configure(config.appkey,
|
||||||
|
config.endpoint,
|
||||||
|
config.rolename,
|
||||||
|
config.rolesecret,
|
||||||
|
config.webSocketPerMessageDeflateOptions,
|
||||||
|
config.socketTLSOptions);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handshake message schema.
|
// Handshake message schema.
|
||||||
//
|
//
|
||||||
@ -431,9 +441,12 @@ namespace ix
|
|||||||
if (!body.isMember("messages")) return false;
|
if (!body.isMember("messages")) return false;
|
||||||
Json::Value messages = body["messages"];
|
Json::Value messages = body["messages"];
|
||||||
|
|
||||||
|
if (!body.isMember("position")) return false;
|
||||||
|
std::string position = body["position"].asString();
|
||||||
|
|
||||||
for (auto&& msg : messages)
|
for (auto&& msg : messages)
|
||||||
{
|
{
|
||||||
cb->second(msg);
|
cb->second(msg, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#include "IXCobraConfig.h"
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
class WebSocket;
|
class WebSocket;
|
||||||
@ -40,7 +42,7 @@ namespace ix
|
|||||||
CobraConnection_PublishMode_Batch = 1
|
CobraConnection_PublishMode_Batch = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
using SubscriptionCallback = std::function<void(const Json::Value&)>;
|
using SubscriptionCallback = std::function<void(const Json::Value&, const std::string&)>;
|
||||||
using EventCallback = std::function<void(CobraConnectionEventType,
|
using EventCallback = std::function<void(CobraConnectionEventType,
|
||||||
const std::string&,
|
const std::string&,
|
||||||
const WebSocketHttpHeaders&,
|
const WebSocketHttpHeaders&,
|
||||||
@ -67,6 +69,8 @@ namespace ix
|
|||||||
const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
|
const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
|
||||||
const SocketTLSOptions& socketTLSOptions);
|
const SocketTLSOptions& socketTLSOptions);
|
||||||
|
|
||||||
|
void configure(const ix::CobraConfig& config);
|
||||||
|
|
||||||
/// Set the traffic tracker callback
|
/// Set the traffic tracker callback
|
||||||
static void setTrafficTrackerCallback(const TrafficTrackerCallback& callback);
|
static void setTrafficTrackerCallback(const TrafficTrackerCallback& callback);
|
||||||
|
|
||||||
|
@ -40,6 +40,11 @@ namespace ix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SentryClient::setTLSOptions(const SocketTLSOptions& tlsOptions)
|
||||||
|
{
|
||||||
|
_httpClient->setTLSOptions(tlsOptions);
|
||||||
|
}
|
||||||
|
|
||||||
int64_t SentryClient::getTimestamp()
|
int64_t SentryClient::getTimestamp()
|
||||||
{
|
{
|
||||||
const auto tp = std::chrono::system_clock::now();
|
const auto tp = std::chrono::system_clock::now();
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ixwebsocket/IXHttpClient.h>
|
#include <ixwebsocket/IXHttpClient.h>
|
||||||
|
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -24,6 +25,9 @@ namespace ix
|
|||||||
|
|
||||||
Json::Value parseLuaStackTrace(const std::string& stack);
|
Json::Value parseLuaStackTrace(const std::string& stack);
|
||||||
|
|
||||||
|
// Mostly for testing
|
||||||
|
void setTLSOptions(const SocketTLSOptions& tlsOptions);
|
||||||
|
|
||||||
void uploadMinidump(
|
void uploadMinidump(
|
||||||
const std::string& sentryMetadata,
|
const std::string& sentryMetadata,
|
||||||
const std::string& minidumpBytes,
|
const std::string& minidumpBytes,
|
||||||
|
@ -189,7 +189,7 @@ namespace snake
|
|||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"action", "rtm/subscription/data"},
|
{"action", "rtm/subscription/data"},
|
||||||
{"id", id++},
|
{"id", id++},
|
||||||
{"body", {{"subscription_id", subscriptionId}, {"messages", {msg}}}}};
|
{"body", {{"subscription_id", subscriptionId}, {"position", "0-0"}, {"messages", {msg}}}}};
|
||||||
|
|
||||||
ws->sendText(response.dump());
|
ws->sendText(response.dump());
|
||||||
};
|
};
|
||||||
|
@ -42,7 +42,8 @@ namespace
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
HttpServer::HttpServer(int port, const std::string& host, int backlog, size_t maxConnections, int addressFamily)
|
HttpServer::HttpServer(
|
||||||
|
int port, const std::string& host, int backlog, size_t maxConnections, int addressFamily)
|
||||||
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
||||||
, _connectedClientsCount(0)
|
, _connectedClientsCount(0)
|
||||||
{
|
{
|
||||||
|
@ -131,8 +131,14 @@ namespace ix
|
|||||||
SSL_CTX_set_mode(ctx,
|
SSL_CTX_set_mode(ctx,
|
||||||
SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||||
|
|
||||||
SSL_CTX_set_options(
|
int options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_CIPHER_SERVER_PREFERENCE;
|
||||||
ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_CIPHER_SERVER_PREFERENCE);
|
|
||||||
|
#ifdef SSL_OP_NO_TLSv1_3
|
||||||
|
// (partially?) work around hang in openssl 1.1.1b, by disabling TLS V1.3
|
||||||
|
// https://github.com/openssl/openssl/issues/7967
|
||||||
|
options |= SSL_OP_NO_TLSv1_3;
|
||||||
|
#endif
|
||||||
|
SSL_CTX_set_options(ctx, options);
|
||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "IXSocketServer.h"
|
#include "IXSocketServer.h"
|
||||||
|
|
||||||
#include "IXNetSystem.h"
|
#include "IXNetSystem.h"
|
||||||
|
#include "IXSetThreadName.h"
|
||||||
#include "IXSocket.h"
|
#include "IXSocket.h"
|
||||||
#include "IXSocketConnect.h"
|
#include "IXSocketConnect.h"
|
||||||
#include "IXSocketFactory.h"
|
#include "IXSocketFactory.h"
|
||||||
@ -23,11 +24,8 @@ namespace ix
|
|||||||
const size_t SocketServer::kDefaultMaxConnections(32);
|
const size_t SocketServer::kDefaultMaxConnections(32);
|
||||||
const int SocketServer::kDefaultAddressFamily(AF_INET);
|
const int SocketServer::kDefaultAddressFamily(AF_INET);
|
||||||
|
|
||||||
SocketServer::SocketServer(int port,
|
SocketServer::SocketServer(
|
||||||
const std::string& host,
|
int port, const std::string& host, int backlog, size_t maxConnections, int addressFamily)
|
||||||
int backlog,
|
|
||||||
size_t maxConnections,
|
|
||||||
int addressFamily)
|
|
||||||
: _port(port)
|
: _port(port)
|
||||||
, _host(host)
|
, _host(host)
|
||||||
, _backlog(backlog)
|
, _backlog(backlog)
|
||||||
@ -97,7 +95,8 @@ namespace ix
|
|||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "SocketServer::listen() error calling inet_pton "
|
ss << "SocketServer::listen() error calling inet_pton "
|
||||||
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
|
<< "at address " << _host << ":" << _port << " : "
|
||||||
|
<< strerror(Socket::getErrno());
|
||||||
|
|
||||||
Socket::closeSocket(_serverFd);
|
Socket::closeSocket(_serverFd);
|
||||||
return std::make_pair(false, ss.str());
|
return std::make_pair(false, ss.str());
|
||||||
@ -108,7 +107,8 @@ namespace ix
|
|||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "SocketServer::listen() error calling bind "
|
ss << "SocketServer::listen() error calling bind "
|
||||||
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
|
<< "at address " << _host << ":" << _port << " : "
|
||||||
|
<< strerror(Socket::getErrno());
|
||||||
|
|
||||||
Socket::closeSocket(_serverFd);
|
Socket::closeSocket(_serverFd);
|
||||||
return std::make_pair(false, ss.str());
|
return std::make_pair(false, ss.str());
|
||||||
@ -124,7 +124,8 @@ namespace ix
|
|||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "SocketServer::listen() error calling inet_pton "
|
ss << "SocketServer::listen() error calling inet_pton "
|
||||||
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
|
<< "at address " << _host << ":" << _port << " : "
|
||||||
|
<< strerror(Socket::getErrno());
|
||||||
|
|
||||||
Socket::closeSocket(_serverFd);
|
Socket::closeSocket(_serverFd);
|
||||||
return std::make_pair(false, ss.str());
|
return std::make_pair(false, ss.str());
|
||||||
@ -135,7 +136,8 @@ namespace ix
|
|||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "SocketServer::listen() error calling bind "
|
ss << "SocketServer::listen() error calling bind "
|
||||||
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
|
<< "at address " << _host << ":" << _port << " : "
|
||||||
|
<< strerror(Socket::getErrno());
|
||||||
|
|
||||||
Socket::closeSocket(_serverFd);
|
Socket::closeSocket(_serverFd);
|
||||||
return std::make_pair(false, ss.str());
|
return std::make_pair(false, ss.str());
|
||||||
@ -246,6 +248,8 @@ namespace ix
|
|||||||
// Set the socket to non blocking mode, so that accept calls are not blocking
|
// Set the socket to non blocking mode, so that accept calls are not blocking
|
||||||
SocketConnect::configure(_serverFd);
|
SocketConnect::configure(_serverFd);
|
||||||
|
|
||||||
|
setThreadName("SocketServer::listen");
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (_stop) return;
|
if (_stop) return;
|
||||||
@ -346,6 +350,8 @@ namespace ix
|
|||||||
|
|
||||||
void SocketServer::runGC()
|
void SocketServer::runGC()
|
||||||
{
|
{
|
||||||
|
setThreadName("SocketServer::GC");
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Garbage collection to shutdown/join threads for closed connections.
|
// Garbage collection to shutdown/join threads for closed connections.
|
||||||
|
@ -134,6 +134,13 @@ namespace ix
|
|||||||
_enablePong = false;
|
_enablePong = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocket::enablePerMessageDeflate()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_configMutex);
|
||||||
|
WebSocketPerMessageDeflateOptions perMessageDeflateOptions(true);
|
||||||
|
_perMessageDeflateOptions = perMessageDeflateOptions;
|
||||||
|
}
|
||||||
|
|
||||||
void WebSocket::disablePerMessageDeflate()
|
void WebSocket::disablePerMessageDeflate()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_configMutex);
|
std::lock_guard<std::mutex> lock(_configMutex);
|
||||||
@ -191,9 +198,19 @@ namespace ix
|
|||||||
auto subProtocols = getSubProtocols();
|
auto subProtocols = getSubProtocols();
|
||||||
if (!subProtocols.empty())
|
if (!subProtocols.empty())
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Sub Protocol strings are comma separated.
|
||||||
|
// Python code to do that is:
|
||||||
|
// >>> ','.join(['json', 'msgpack'])
|
||||||
|
// 'json,msgpack'
|
||||||
|
//
|
||||||
|
int i = 0;
|
||||||
for (auto subProtocol : subProtocols)
|
for (auto subProtocol : subProtocols)
|
||||||
{
|
{
|
||||||
subProtocolsHeader += ",";
|
if (i++ != 0)
|
||||||
|
{
|
||||||
|
subProtocolsHeader += ",";
|
||||||
|
}
|
||||||
subProtocolsHeader += subProtocol;
|
subProtocolsHeader += subProtocol;
|
||||||
}
|
}
|
||||||
headers["Sec-WebSocket-Protocol"] = subProtocolsHeader;
|
headers["Sec-WebSocket-Protocol"] = subProtocolsHeader;
|
||||||
@ -395,7 +412,7 @@ namespace ix
|
|||||||
WebSocketCloseInfo(),
|
WebSocketCloseInfo(),
|
||||||
binary));
|
binary));
|
||||||
|
|
||||||
WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
|
WebSocket::invokeTrafficTrackerCallback(wireSize, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
#include "IXWebSocketSendInfo.h"
|
#include "IXWebSocketSendInfo.h"
|
||||||
#include "IXWebSocketTransport.h"
|
#include "IXWebSocketTransport.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <condition_variable>
|
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
@ -57,6 +57,7 @@ namespace ix
|
|||||||
void setPingTimeout(int pingTimeoutSecs);
|
void setPingTimeout(int pingTimeoutSecs);
|
||||||
void enablePong();
|
void enablePong();
|
||||||
void disablePong();
|
void disablePong();
|
||||||
|
void enablePerMessageDeflate();
|
||||||
void disablePerMessageDeflate();
|
void disablePerMessageDeflate();
|
||||||
void addSubProtocol(const std::string& subProtocol);
|
void addSubProtocol(const std::string& subProtocol);
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ namespace ix
|
|||||||
WebSocketInitResult connect(int timeoutSecs);
|
WebSocketInitResult connect(int timeoutSecs);
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
// send is in binary mode by default
|
// send is in text mode by default
|
||||||
WebSocketSendInfo send(const std::string& data,
|
WebSocketSendInfo send(const std::string& data,
|
||||||
bool binary = false,
|
bool binary = false,
|
||||||
const OnProgressCallback& onProgressCallback = nullptr);
|
const OnProgressCallback& onProgressCallback = nullptr);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "IXUserAgent.h"
|
#include "IXUserAgent.h"
|
||||||
#include "libwshandshake.hpp"
|
#include "libwshandshake.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@ -335,7 +336,7 @@ namespace ix
|
|||||||
std::string header = headers["sec-websocket-extensions"];
|
std::string header = headers["sec-websocket-extensions"];
|
||||||
WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(header);
|
WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(header);
|
||||||
|
|
||||||
// If the client has requested that extension, enable it.
|
// If the client has requested that extension,
|
||||||
if (webSocketPerMessageDeflateOptions.enabled())
|
if (webSocketPerMessageDeflateOptions.enabled())
|
||||||
{
|
{
|
||||||
_enablePerMessageDeflate = true;
|
_enablePerMessageDeflate = true;
|
||||||
|
@ -66,12 +66,23 @@ namespace ix
|
|||||||
{
|
{
|
||||||
line[i] = '\0';
|
line[i] = '\0';
|
||||||
std::string lineStr(line);
|
std::string lineStr(line);
|
||||||
// colon is ':', colon+1 is ' ', colon+2 is the start of the value.
|
// colon is ':', usually colon+1 is ' ', and colon+2 is the start of the value.
|
||||||
|
// some webservers do not put a space after the colon character, so
|
||||||
|
// the start of the value might be farther than colon+2.
|
||||||
|
// The spec says that space after the : should be discarded.
|
||||||
// i is end of string (\0), i-colon is length of string minus key;
|
// i is end of string (\0), i-colon is length of string minus key;
|
||||||
// subtract 1 for '\0', 1 for '\n', 1 for '\r',
|
// subtract 1 for '\0', 1 for '\n', 1 for '\r',
|
||||||
// 1 for the ' ' after the ':', and total is -4
|
// 1 for the ' ' after the ':', and total is -4
|
||||||
|
// since we use an std::string later on and don't account for '\0',
|
||||||
|
// plus the optional first space, total is -2
|
||||||
|
int start = colon + 1;
|
||||||
|
while (lineStr[start] == ' ')
|
||||||
|
{
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
|
||||||
std::string name(lineStr.substr(0, colon));
|
std::string name(lineStr.substr(0, colon));
|
||||||
std::string value(lineStr.substr(colon + 2, i - colon - 4));
|
std::string value(lineStr.substr(start, lineStr.size() - start - 2));
|
||||||
|
|
||||||
headers[name] = value;
|
headers[name] = value;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "IXWebSocketServer.h"
|
#include "IXWebSocketServer.h"
|
||||||
|
|
||||||
#include "IXNetSystem.h"
|
#include "IXNetSystem.h"
|
||||||
|
#include "IXSetThreadName.h"
|
||||||
#include "IXSocketConnect.h"
|
#include "IXSocketConnect.h"
|
||||||
#include "IXWebSocket.h"
|
#include "IXWebSocket.h"
|
||||||
#include "IXWebSocketTransport.h"
|
#include "IXWebSocketTransport.h"
|
||||||
@ -28,6 +29,7 @@ namespace ix
|
|||||||
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
||||||
, _handshakeTimeoutSecs(handshakeTimeoutSecs)
|
, _handshakeTimeoutSecs(handshakeTimeoutSecs)
|
||||||
, _enablePong(kDefaultEnablePong)
|
, _enablePong(kDefaultEnablePong)
|
||||||
|
, _enablePerMessageDeflate(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +61,11 @@ namespace ix
|
|||||||
_enablePong = false;
|
_enablePong = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::disablePerMessageDeflate()
|
||||||
|
{
|
||||||
|
_enablePerMessageDeflate = false;
|
||||||
|
}
|
||||||
|
|
||||||
void WebSocketServer::setOnConnectionCallback(const OnConnectionCallback& callback)
|
void WebSocketServer::setOnConnectionCallback(const OnConnectionCallback& callback)
|
||||||
{
|
{
|
||||||
_onConnectionCallback = callback;
|
_onConnectionCallback = callback;
|
||||||
@ -67,15 +74,21 @@ namespace ix
|
|||||||
void WebSocketServer::handleConnection(std::shared_ptr<Socket> socket,
|
void WebSocketServer::handleConnection(std::shared_ptr<Socket> socket,
|
||||||
std::shared_ptr<ConnectionState> connectionState)
|
std::shared_ptr<ConnectionState> connectionState)
|
||||||
{
|
{
|
||||||
|
setThreadName("WebSocketServer::" + connectionState->getId());
|
||||||
|
|
||||||
auto webSocket = std::make_shared<WebSocket>();
|
auto webSocket = std::make_shared<WebSocket>();
|
||||||
_onConnectionCallback(webSocket, connectionState);
|
_onConnectionCallback(webSocket, connectionState);
|
||||||
|
|
||||||
webSocket->disableAutomaticReconnection();
|
webSocket->disableAutomaticReconnection();
|
||||||
|
|
||||||
if (_enablePong)
|
if (_enablePong)
|
||||||
|
{
|
||||||
webSocket->enablePong();
|
webSocket->enablePong();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
webSocket->disablePong();
|
webSocket->disablePong();
|
||||||
|
}
|
||||||
|
|
||||||
// Add this client to our client set
|
// Add this client to our client set
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,7 @@ namespace ix
|
|||||||
|
|
||||||
void enablePong();
|
void enablePong();
|
||||||
void disablePong();
|
void disablePong();
|
||||||
|
void disablePerMessageDeflate();
|
||||||
|
|
||||||
void setOnConnectionCallback(const OnConnectionCallback& callback);
|
void setOnConnectionCallback(const OnConnectionCallback& callback);
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ namespace ix
|
|||||||
// Member variables
|
// Member variables
|
||||||
int _handshakeTimeoutSecs;
|
int _handshakeTimeoutSecs;
|
||||||
bool _enablePong;
|
bool _enablePong;
|
||||||
|
bool _enablePerMessageDeflate;
|
||||||
|
|
||||||
OnConnectionCallback _onConnectionCallback;
|
OnConnectionCallback _onConnectionCallback;
|
||||||
|
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IX_WEBSOCKET_VERSION "8.1.0"
|
#define IX_WEBSOCKET_VERSION "8.2.3"
|
||||||
|
20
test/.certs/selfsigned-client-crt.pem
Normal file
20
test/.certs/selfsigned-client-crt.pem
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDQTCCAimgAwIBAgIUNJBwOQdDle1TI/MHGd+cSpxIllwwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwSDEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29ja2V0
|
||||||
|
MRowGAYDVQQDDBFzZWxmc2lnbmVkLWNsaWVudDAeFw0yMDAzMTIyMzA0MzdaFw0y
|
||||||
|
MTAzMTIyMzA0MzdaMEgxFDASBgNVBAoMC21hY2hpbmV6b25lMRQwEgYDVQQKDAtJ
|
||||||
|
WFdlYlNvY2tldDEaMBgGA1UEAwwRc2VsZnNpZ25lZC1jbGllbnQwggEiMA0GCSqG
|
||||||
|
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7q6W0f5vRSHaNOuM1VQpY0rC0a5u04J5Z
|
||||||
|
nssUD1QfgilY1UEaaR/4K6ILE4oClqeDsQy/7+04Wt6i/ttceB/k1Jk6n0kgdtvA
|
||||||
|
CsX1H+nA7JL7ANBZvQ6W2E1mwJieTDSVDgL4YB9qzJQu3PdwZJgm5GTlVK66DMr1
|
||||||
|
IH2EYwu73M/ZwOzfgyd7m0TcgkRV8OHiD1dVDERNQR9gzDUsBtCoWPmzXxgPMOSE
|
||||||
|
Oq1sEhNC0bPaG3zTDvCv0t4Hti33po/U8PZwOtz2b8StSjS5BnvEDnksAtEZuNEu
|
||||||
|
4B3KJN4Oxrtgh7DYdiF7S9Gh0dN6yqtRfDWkGyC9WkyoqpFKCM4fAgMBAAGjIzAh
|
||||||
|
MB8GA1UdEQQYMBaCCWxvY2FsaG9zdIIJMTI3LjAuMC4xMA0GCSqGSIb3DQEBCwUA
|
||||||
|
A4IBAQB4oIutDYbCRfsyWRAiAY+D9rhYsJYlsQjyml1q2+pCv7BJ1kWsKk7m2VMX
|
||||||
|
Tl6CM+PI0zXPpLN6Ot79jf/jxEbDMvqrBgGpYfddvLhyTFnzIZpG8d63RvzPADF6
|
||||||
|
lV3x34eZf/EdtrWgZAHK+5oZjtzePGHwKDFIPva9nvJXYIxNwKYWGRX8HSm0OZi2
|
||||||
|
FQiaOt6WYLo7ZdefNPS9nugFRM6hfztJe6WvvglKm+BTnHbCSKj5xRuT9iA80+jX
|
||||||
|
Zij7po8opY3S+zEZ0eNUCHxMBQ+2Jdq3HxggJ2cFQVRHdvKfwzmavVeGgni75d16
|
||||||
|
+xFD5nS3g3eIEME+lZ8c8GbL0AJ4
|
||||||
|
-----END CERTIFICATE-----
|
27
test/.certs/selfsigned-client-key.pem
Normal file
27
test/.certs/selfsigned-client-key.pem
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAu6ultH+b0Uh2jTrjNVUKWNKwtGubtOCeWZ7LFA9UH4IpWNVB
|
||||||
|
Gmkf+CuiCxOKApang7EMv+/tOFreov7bXHgf5NSZOp9JIHbbwArF9R/pwOyS+wDQ
|
||||||
|
Wb0OlthNZsCYnkw0lQ4C+GAfasyULtz3cGSYJuRk5VSuugzK9SB9hGMLu9zP2cDs
|
||||||
|
34Mne5tE3IJEVfDh4g9XVQxETUEfYMw1LAbQqFj5s18YDzDkhDqtbBITQtGz2ht8
|
||||||
|
0w7wr9LeB7Yt96aP1PD2cDrc9m/ErUo0uQZ7xA55LALRGbjRLuAdyiTeDsa7YIew
|
||||||
|
2HYhe0vRodHTesqrUXw1pBsgvVpMqKqRSgjOHwIDAQABAoIBAQC2q7IESj2x7TWv
|
||||||
|
7ITiEZ+bq6DiTOfnnMeldkI3iWAZt0lltVXETlUW6+mznFY2hMwTDE/bt78Qnqqc
|
||||||
|
vzNoA2kQBLwNaqP0XJ0zhYkAOwr9hYjflwA2iSZdP7e/b3JeitCX0WakunN6Mh1+
|
||||||
|
rAiRtui+2os3CkF0yST4iqKCLSJrvSvvK5fU92aKEaE3k9kznBljvVOJIIRQBUPz
|
||||||
|
G8tvtPgpLALrT7XMnGfaCyGS8c1IbFMm84KTxAlVV0bnuGgeYQ2VupqUmZpJjcJ0
|
||||||
|
B08hr7vPfxz3UXSOKwYY8TRfmF3X370ky5Ov2I9ddg27V1QoeRTWlL7VMxRtiSer
|
||||||
|
hoM5SPKpAoGBAO0vBd1Z6425wGT0PClUbJAVm2OBYMDnl2RmhBK5TAxrKjs9ag08
|
||||||
|
65jfVCMD8wDMDhEbvbmzkgRa9BC6AY97JBmyr4m9oGfA7oenuou+a9LYAKqtO0ts
|
||||||
|
hxHf2LnpC1HCyh4+l5gohjlUG7gSVu/oBhNTJNKmqUKuQ8v1b6My/JR9AoGBAMqP
|
||||||
|
DugL9DusECncKHQbaIEzvEBe+QErcUxXxq+G4LLvFTZVvthHbrZ/0cxm5Ve6rfd2
|
||||||
|
krqjYFA3WPOuTcKEUouNeRK2A4V6PbnSdpf0kagN6KbEjK66ZSZs8wnWitghqo7J
|
||||||
|
n2IHcSDEEACTyjS7K8HjPx0fQGU1tzkG/7/xs3vLAoGAI61JEoyuE/l26TibvBPI
|
||||||
|
6Lt3TjZt2VZ8vUt2XmKk/9E23wZT533canhdbY7whJQtIYGsvjw2oJUV1VZFWdHK
|
||||||
|
EluAcBWoBTNOLfWa595S1bpMD2BTZPsELjofnYdifn/wazA7GVYvKnxuVvfbP+cE
|
||||||
|
0u9UwKL1HuSbqhhXHJNUzvkCgYAeFRLsqWHTPuGDpfuoCq4BijJqCPDIGLCR2vNZ
|
||||||
|
/BkA2fr3f9KBAlLR7be1uI5U8heGCekOqNbT8vRV9Ev+GHK94PvbKIbrWtUx9KzC
|
||||||
|
MoMzRyWHJueRx4LgKwwJKQCjypQu8oimIV7Os++AdnJwVF/SQrKL26lPnqOgZ4ax
|
||||||
|
9e5m8wKBgQCF626EmJk34+WTGEa5gdTx567Y+1EAbag+7fQSskwiRPvRN2fcg3H8
|
||||||
|
ynUAtIgWbrecgKhblXxc7zwJrl41P71uQzCFspgvOPXMxL2xqN+tnTfuz84OXk26
|
||||||
|
h1xSdS3e+JYsWUIxqbH1W59S+dC7KtklBAcUxb8DNpDoVjVBeAEqzw==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
21
test/.certs/trusted-ca-crt.pem
Normal file
21
test/.certs/trusted-ca-crt.pem
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDYzCCAkugAwIBAgIUD0V1mxoZF9TNpsoyvuHU2zhrg0wwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwQTEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29ja2V0
|
||||||
|
MRMwEQYDVQQDDAp0cnVzdGVkLWNhMB4XDTIwMDMxMjIzMDQzN1oXDTMwMDMxMDIz
|
||||||
|
MDQzN1owQTEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29j
|
||||||
|
a2V0MRMwEQYDVQQDDAp0cnVzdGVkLWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||||
|
MIIBCgKCAQEAr2nVpfIzxsxK76Va+HaBfZ7aqjk90zipzH3/CWuMMN9wzBhg2HPE
|
||||||
|
cRreq1vKm2M/L9CZH6y6fnr68n8lW4rDATmbH0GeY4OqI9jw/mfjL4jUsAxwRi4X
|
||||||
|
kkk4G2nz1G81LvWLFXXAZlOxeHSZtpPh5OP1tNGiJNL4eGVxjlwFJIFwDvweJ/tW
|
||||||
|
J7dh/FTzO0jqh8FheJTeJO64Gflqfln64WRUOPSpO7v4KmyesM/BGwGMfZjcwhs/
|
||||||
|
KZT+OKXpPgYhdmAZJE24ftwWTP84DP9wnJbNqTRt0r5ud+q8EusKIjw/Pbf/tPUF
|
||||||
|
7J0bkMp4y5/+7MMuIxeZ+s2uHdp6hmwdJQIDAQABo1MwUTAdBgNVHQ4EFgQUPARq
|
||||||
|
Vm19yGgWqEnpNT1ILIkfWhEwHwYDVR0jBBgwFoAUPARqVm19yGgWqEnpNT1ILIkf
|
||||||
|
WhEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAEIsTvJhs6r2r
|
||||||
|
x1xrHKaGo4sSuywJiZqMabvC9g22Xw3Cno5qGVFYWi4k0qjX/j9DN36DyOY1rei+
|
||||||
|
kNBnOnLdtdNDltcvaLeA/9SeIhxRYOwjXpPzy9AqHpGZPui988qtptA+DI+IOLAm
|
||||||
|
mQyssYC4doDcohMXaI7KumKHojTDAPrF2INJRTF9zWgbsFjvSWU5CY5CNERWCydh
|
||||||
|
OXfzFylifScNOppioZL9VTa6At7R+MGg834kMi6WDIvtD6Ibn+pw0bV60aiMhBe8
|
||||||
|
8qgZ8lxjGOHlvQrjqdk65smhfaECJcFJxybOSA3Z1f+Y9j/p0e0hyUJM/b/NouaE
|
||||||
|
64H6vXczLQ==
|
||||||
|
-----END CERTIFICATE-----
|
1
test/.certs/trusted-ca-crt.srl
Normal file
1
test/.certs/trusted-ca-crt.srl
Normal file
@ -0,0 +1 @@
|
|||||||
|
297E3BFAD1F1F96A60A2AF0F48B092E705C0C68A
|
27
test/.certs/trusted-ca-key.pem
Normal file
27
test/.certs/trusted-ca-key.pem
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAr2nVpfIzxsxK76Va+HaBfZ7aqjk90zipzH3/CWuMMN9wzBhg
|
||||||
|
2HPEcRreq1vKm2M/L9CZH6y6fnr68n8lW4rDATmbH0GeY4OqI9jw/mfjL4jUsAxw
|
||||||
|
Ri4Xkkk4G2nz1G81LvWLFXXAZlOxeHSZtpPh5OP1tNGiJNL4eGVxjlwFJIFwDvwe
|
||||||
|
J/tWJ7dh/FTzO0jqh8FheJTeJO64Gflqfln64WRUOPSpO7v4KmyesM/BGwGMfZjc
|
||||||
|
whs/KZT+OKXpPgYhdmAZJE24ftwWTP84DP9wnJbNqTRt0r5ud+q8EusKIjw/Pbf/
|
||||||
|
tPUF7J0bkMp4y5/+7MMuIxeZ+s2uHdp6hmwdJQIDAQABAoIBAH4sPkUTJjMEl5Iw
|
||||||
|
+nJlq1bUgKyYZ+QaiehRaLU56qjsz5G+p0qKWu6QSUIw0Fdc2AJopPunnq2DgCYV
|
||||||
|
VqW19fZXnUCqTmd+OU93qEEWMM/sODA5gji4xrOufvEZEQ3ov/R7IgPZov73jFv8
|
||||||
|
YuR1ErM1VXMuptad+aOANGIVxo0ubDEXKK/zhOfUUXQy7ZsEruJCCIpigULU159r
|
||||||
|
sVOq2lwgLz+hClFBIq0IKAKqiPWpw2GtHtU5WtAo3qZEMJkNM5SppjDmS2Wy3qN6
|
||||||
|
Gq6sXtlAmLFZAyVpXXklQK3mCaAs5gcV94nm+r++F884obaOtJ126uDdIKlL+A6k
|
||||||
|
l41DXwECgYEA4KAswbdoa18J1Ql2QtwW3+knEaUO62JH11RO5VV02uiYv4v4mHmA
|
||||||
|
prnl1jsfgbc3qfIlZWDLlNRovKCfQSj/HzOe4Hd+gEPiSYjA77PRqQeYTPXTf0Ml
|
||||||
|
IQ3j9z1CdBWNoKJ18CEiIncvjpDYkdFf3RsawcnYXklXRjmm6kIJJzUCgYEAx+oA
|
||||||
|
gm/xXK28P/CFksZzsseF5i/1MPdniyP3oY34DlEmDvl9ZA1Z52De8vojfNd9X12M
|
||||||
|
ccjiGMMGgknJqncCB+uTWYFy2pWnr9dVVxf+oirAlT1Z03AkT5gxmIZ3FUQw8VkB
|
||||||
|
HjKJYD1mpTwoSlc+DR3R0xNdl84nkUI2hxGErDECgYEAjdsZ6MyXGRfP8cYj9V1g
|
||||||
|
5M8taStAHM7YZ9hKavJo9cZmkLEoscIpySElUQHNh/HZKW5Ox5M1fiwWaOlXKaNm
|
||||||
|
WqIS99b/AKneQmomzjpVcdXmDNRCWOBilllbWkxJp13lL0jqClgiYnm6guJeotgD
|
||||||
|
HnN7ll6OUh0nDKZkDxTdCvECgYEAtlQZet2WCKz70GURrjgJNbj7ymFbAvniGekH
|
||||||
|
5PSSlJw2Vdn+Hs5+fKTBMmIpE6eF1QCBIxXQAD1/Jj0eDLbVx1t33F5P3kQ32AxQ
|
||||||
|
7UoZFtZfJr35uvnAZEeulCmvWloDOVuvxVbaLEhT4cfoB0VidpwHzrcO2XFQbQ8y
|
||||||
|
pCW6F0ECgYBbO0NU/Jlu3acIzGwAv69CMo8udwnWrhzGStZD67swdQ/yxHVpx2RH
|
||||||
|
0sNk6UfLku8Mal7Pp+RglAmsOZEjSgk1V92J9lXYjYD8IUNwNyRRCpQ8xu0KPgDM
|
||||||
|
XGeUca/Ao7jRVcsPOiqFH7wgfEjyzpO85X/K9BoBnA0EcUTOScaqmw==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
20
test/.certs/trusted-client-crt.pem
Normal file
20
test/.certs/trusted-client-crt.pem
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDNzCCAh+gAwIBAgIUKX47+tHx+Wpgoq8PSLCS5wXAxoowDQYJKoZIhvcNAQEL
|
||||||
|
BQAwQTEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29ja2V0
|
||||||
|
MRMwEQYDVQQDDAp0cnVzdGVkLWNhMB4XDTIwMDMxMjIzMDQzN1oXDTIxMDMxMjIz
|
||||||
|
MDQzN1owRTEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29j
|
||||||
|
a2V0MRcwFQYDVQQDDA50cnVzdGVkLWNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggEPADCCAQoCggEBALijaV0JhdoRAXnD5fX5W/9nZFb6jor6lIGW56Mdn+11ICYw
|
||||||
|
GoJ7ATnygUwfBMepoD5RfJ5pkNxYewo8N5JR+8rb4V9atJCSYQLT8P7Dm2YNMtkq
|
||||||
|
mNiRuRLrTqoPYajEzz5ENWSNnsjUB1GMGEpcCvRDgsTF24OsVV9BmLV166BEye7w
|
||||||
|
ah+jk1YYJHbEnNT4wzr4drJSGEYh2aRO72yY+ROe49Tz/GVVXfCamcj88z5hOS/+
|
||||||
|
+nCF/odLLB9Ij4xhR8WwTrwE/TxlkIQRBBPTsNetZjvMQZT+TkKw9nNjdoHiDlz9
|
||||||
|
BLOYxovUIB8OtOQQfour8V7nwZ2bL9Pp51mnmBsCAwEAAaMjMCEwHwYDVR0RBBgw
|
||||||
|
FoIJbG9jYWxob3N0ggkxMjcuMC4wLjEwDQYJKoZIhvcNAQELBQADggEBAFTus7o2
|
||||||
|
fQuSMk52qXUESVWG4ygvd2scV58zRrLxZL7Ug9p4DIJo0cY59l3Vhwn2xDSYlAFi
|
||||||
|
1h/qSEGkR2a0U2LzMK7BPSkqqYceSwnUvnwHvCwgH9aL1Rvk/4f1sFfsKegjScle
|
||||||
|
wraYsRmpidEZJYICvokHev36mX3fHaZZEU+WIoTvChgu0OtD+qkI4DECywLgtB92
|
||||||
|
/geabKC3C5JgiW0Jz8AScWoO2uKHFeuD2nfI1SiAbfMIAmG3RTanbZ8JMEVomVep
|
||||||
|
txMNGnojun923KTEScnH3cQfnkJjm2AM5yKgT6I/OHELe9Gg7R0IOJbiPmSru7/k
|
||||||
|
x5tBp3iMsZZ26VE=
|
||||||
|
-----END CERTIFICATE-----
|
27
test/.certs/trusted-client-key.pem
Normal file
27
test/.certs/trusted-client-key.pem
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAuKNpXQmF2hEBecPl9flb/2dkVvqOivqUgZbnox2f7XUgJjAa
|
||||||
|
gnsBOfKBTB8Ex6mgPlF8nmmQ3Fh7Cjw3klH7ytvhX1q0kJJhAtPw/sObZg0y2SqY
|
||||||
|
2JG5EutOqg9hqMTPPkQ1ZI2eyNQHUYwYSlwK9EOCxMXbg6xVX0GYtXXroETJ7vBq
|
||||||
|
H6OTVhgkdsSc1PjDOvh2slIYRiHZpE7vbJj5E57j1PP8ZVVd8JqZyPzzPmE5L/76
|
||||||
|
cIX+h0ssH0iPjGFHxbBOvAT9PGWQhBEEE9Ow161mO8xBlP5OQrD2c2N2geIOXP0E
|
||||||
|
s5jGi9QgHw605BB+i6vxXufBnZsv0+nnWaeYGwIDAQABAoIBAFQ2XAEOLdmW9ghW
|
||||||
|
fBUjRX2I56/wGYFz5rXwYPf5tA625BHm0MCAX7/RRn20jBaQ3EBwJBmQZnzJclzp
|
||||||
|
uCLpd6E/hlxaX46s5MhIaFuaVc9G59E653mnhTUG09smptE16pwouf2BxlEsu6XK
|
||||||
|
8u0/a9Oa0xLydztoJ4wJvB/Ph8eRsbdbfL/ZAe+vk+bEp9ugyec3B5KTc+hWRneH
|
||||||
|
BRfe239OX4mEhxNoO1tPJz1hJLjJH5F/iE1wkjSzLr1SI/cSbcbnyYj/kyXmktZw
|
||||||
|
uaeFptkT6rB9GO0YunEPzzuQ4EEPpK9F63uu74dGqyW56STq26km7diAHhEpFdp1
|
||||||
|
7X0rfHECgYEA5YPtjdqKEn5pQEdehqFnzi3IIu593o7baM6qEyFpMsTP53QCjUKX
|
||||||
|
rrImyr2opfFKrXrI0IYXlDgOZApb2sKLoeP/wpfZiGSyqrzj+Y49cNRHjH643ClL
|
||||||
|
Ri5eO6TRBukAW1gQFwuVBPbcnswaU6Ah85uTxqj+hO0g18rkuVdf72MCgYEAzfHH
|
||||||
|
lb9TMf4DZEoL7GMpc4gDG9V66UWWzXyJB4CWHd6QX1vl6Ow5wE7q3fewD4SNgvDs
|
||||||
|
DHZ8oqK2OMKJH/h/tqxyu+g1huajOhPqy1TIt5ncMjS0sguQ+7bQeHASKLxHhjPC
|
||||||
|
YdqGMxOBQI5olWGq5U9Td5TYE95qk50KoIyNnekCgYEAkhMwa1tPC0w3UrjZuZga
|
||||||
|
yEetHEZsB+0mSgNWjYxzNuO6atYUFbHvdjlepSSmpM74t4bxLn5ZnXU7+4H4SjgN
|
||||||
|
xMCm9EPPKJbme/Jyqk9UXW5OB2ZT45PIm+dBBHb2ro43MuvOecxeUOWJLuw6SUUe
|
||||||
|
trwrBoJiU1nU0GMKxceNgH8CgYEAzeNMpDG9S7ply6qXVwEf3Kd6bCY1leaDR/Wb
|
||||||
|
zMtJyJzL+vmV1RHs/ownFDfeZPUgwGp5olAGdFV1FTOvAS5fB9JJdgBFGxOS1ao5
|
||||||
|
zoN5kswYLn0wtNsJXAy9R9rK3Ly2SL2QNGHSTlfOnSqB9e3JeyyeBmvgxaRTKjYS
|
||||||
|
/MTng5kCgYAIL79seoBnd9ZSp8A7QUBighxBn6DwrvLgexaysmC0zYqxbatczHk9
|
||||||
|
iFbQRmPnFHhUt4URhxyhCoTgd7F0JpxklQODNfseVwtDiDMj8Fu8Tfmn6+9GdFRv
|
||||||
|
0QEU+dR3gi98bO6G4IuAFGO9emXho3Snu6odRmh4HZVNOdLCuQe1Cw==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
20
test/.certs/trusted-server-crt.pem
Normal file
20
test/.certs/trusted-server-crt.pem
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDNzCCAh+gAwIBAgIUKX47+tHx+Wpgoq8PSLCS5wXAxokwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwQTEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29ja2V0
|
||||||
|
MRMwEQYDVQQDDAp0cnVzdGVkLWNhMB4XDTIwMDMxMjIzMDQzN1oXDTIxMDMxMjIz
|
||||||
|
MDQzN1owRTEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29j
|
||||||
|
a2V0MRcwFQYDVQQDDA50cnVzdGVkLXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggEPADCCAQoCggEBAMK5XAcHJwVSor1SfoMM5H5aNfNnM4JKq8kfAOl6KlXCsgs3
|
||||||
|
bBcrJ24gEG6/goxkgLxhC1SXdbebt3Jay2lxAa9/7Uj87yztozSsctMkxXE0u3R+
|
||||||
|
ih+9sP7ctpZ1hrF2Gv+ztd49/mXe1iRLPhkPijGpPlNsfie/TYybrw3WQlGH8jUm
|
||||||
|
MnW12QUOzoBrIOCO6uIxFBJ1qiMq5mIBLlYOMj+MQubnQdvaQPNf1zaZWsCVGyTv
|
||||||
|
95roHAb/s70Ie4r4ATcubtZs/ftjvzSmJegodTprPAedkrJ/k6Od9as7hpL37605
|
||||||
|
haBU5pMyPNMWYi1MwYc9k0R0IpCKdyeX0huHfpkCAwEAAaMjMCEwHwYDVR0RBBgw
|
||||||
|
FoIJbG9jYWxob3N0ggkxMjcuMC4wLjEwDQYJKoZIhvcNAQELBQADggEBAI41ZI4Z
|
||||||
|
WbPFB1e+wIWQE7O2rJMeTEImjBOtcJEN3bqhsdE3Zqk0fPaE6jNz0Fp4IXqUYXzo
|
||||||
|
SGsgBroV6sgknuLo8HdcTLcg8p9qZ3FGFHFQD1QYINn4ykupJZE2KcrIV8BZ/Tiv
|
||||||
|
ciFrJ7i/qwpOrTRBV/w47yP3WZ3v8UdBnj5URD0v/yaAfkaReDO59Dlht/wyItQi
|
||||||
|
GkDczMqMF1GTqcLqBwZdfpHq7B/UI8sp58a6eR9lOgryYCr+QJn7TcZrYzkcSWzg
|
||||||
|
KE6VuzK6+NElvtg1hSST2Rc/RuuKzexsO/PLesVzaU/6NdDwXmpuSxeCiWm1mosA
|
||||||
|
xfQZ9fSOQG6reFk=
|
||||||
|
-----END CERTIFICATE-----
|
27
test/.certs/trusted-server-key.pem
Normal file
27
test/.certs/trusted-server-key.pem
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAwrlcBwcnBVKivVJ+gwzkflo182czgkqryR8A6XoqVcKyCzds
|
||||||
|
FysnbiAQbr+CjGSAvGELVJd1t5u3clrLaXEBr3/tSPzvLO2jNKxy0yTFcTS7dH6K
|
||||||
|
H72w/ty2lnWGsXYa/7O13j3+Zd7WJEs+GQ+KMak+U2x+J79NjJuvDdZCUYfyNSYy
|
||||||
|
dbXZBQ7OgGsg4I7q4jEUEnWqIyrmYgEuVg4yP4xC5udB29pA81/XNplawJUbJO/3
|
||||||
|
mugcBv+zvQh7ivgBNy5u1mz9+2O/NKYl6Ch1Oms8B52Ssn+To531qzuGkvfvrTmF
|
||||||
|
oFTmkzI80xZiLUzBhz2TRHQikIp3J5fSG4d+mQIDAQABAoIBACFw4dwXH11rpqUq
|
||||||
|
4K0y7p7AcVl+1LrAhiYBHA/8uf6GdDs25mpIL/paqVfLrejcbbtsUxzQ8hd5N5T9
|
||||||
|
AMf371kreB27ynuFyCyInSOjwgDCFJtaC/CNjDMIxpaqUlpxtQtK2qXzMZhfH5mW
|
||||||
|
DnERWSNUNG7xR+0djnziU7rlm/gSOxUA2gS/5ik9JXAx0yoML7HWlBbk0PJ5o8Ac
|
||||||
|
sy6w/YwJVZAjXyUuYptPy2bK8WpGAsthw6RmW1fdOdDAUC3wz7TIKLuPD0AP9g7j
|
||||||
|
u8grDYtD+U3ls1Z1Grow2UUG8CedotzVE8KIhDWi35aNiGIuaMFnnLf2OO/Mgd6G
|
||||||
|
V82kkLECgYEA4sBtNsmlfFteFmHPS0s8wzg7lzLN15yifk7kO9GQcsbymXVSgU93
|
||||||
|
XnvADAflly382pyMpr7Fb6V126iOx+YQhr6ya116S4UtAKq4kCau3Im6OedKefwx
|
||||||
|
B71rST+vuAlUcv2ZcAVRJK8GtQQvwcAeI24ShPOXC+vyFAaaZ5eZo/0CgYEA29dZ
|
||||||
|
LcREVlv2Tgy/YJVnZ7EYRGiheuF0rl0d0+Stggj34fSS1cexv3gMF13HBk2HpXfW
|
||||||
|
3LfJyj2iGRZE9OUjN0ozVIVZWgZS/cwZbEUyl3o6IK0kPE4fZBaE16Onh4OGXKwr
|
||||||
|
XTG+EjmIJRVRawECbLMONj5rHQLdcy+5YIH28c0CgYEA1XSL2y2MCTsBoVRGDf0v
|
||||||
|
oB7JihYbTEN5fCnMFLu8nS/HpMqa9nvWRS19plWwvdZe13TTuwyPVACQqE1Oy8M5
|
||||||
|
/354+zUuMPWXXa9YuuqPZbCJjIS8yYSsqzqXSocXZcnyo6Uz0g5PSpcxWyorwtqW
|
||||||
|
BIhUCrA8ms5sPonQxIAj9AkCgYBd/6g7722g11VrbfvuWjOKnKhZp7tUBU6Ut2/n
|
||||||
|
iCHANgF3ddHK4sXXrobM/uX4hfH4CFOwsEzx0oSa4XC+nbL/ExT7kMDxwz59EmXU
|
||||||
|
a4oERtjP2/hgaK73ZsGKSol5Yf1zZpJsGLbCqCLUaFcVv6q/u5faDbpS/0Sc2c0T
|
||||||
|
vL5QCQKBgQCL6ySxvEb5+zst/kRxXcnefXjoB+LSYsU4zy8WfkcP4r38AAQ2Hn+F
|
||||||
|
f3/9BUX+2gNr99VDMjI+TUEf+NdQA/nFu4RbFvJ9Wpw9pXkIJpJkZ9g3Why4Ziji
|
||||||
|
h0IrXm5JCet71+EIMwP0LhKJKrXZudlzP4DYMWmA7Avqb3HIdPXd7Q==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
21
test/.certs/untrusted-ca-crt.pem
Normal file
21
test/.certs/untrusted-ca-crt.pem
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDZzCCAk+gAwIBAgIUBEbp5x1IlwAV6OcQ/4xHk1Y+K4UwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwQzEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29ja2V0
|
||||||
|
MRUwEwYDVQQDDAx1bnRydXN0ZWQtY2EwHhcNMjAwMzEyMjMwNDM3WhcNMzAwMzEw
|
||||||
|
MjMwNDM3WjBDMRQwEgYDVQQKDAttYWNoaW5lem9uZTEUMBIGA1UECgwLSVhXZWJT
|
||||||
|
b2NrZXQxFTATBgNVBAMMDHVudHJ1c3RlZC1jYTCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggEPADCCAQoCggEBAMmmYROZf/Kg46b/0Zvq4pUY8ghUEA+eYit8dLyUZ/onoW4l
|
||||||
|
xl3CK5NhJIer62Olv7QIu8WhU/hYoeE+8lLva9v0HaJgGjKmPQ3tyej319PzIc7o
|
||||||
|
uKatrQ0BAi/KReBQOoqAGqa+DBIGAHoi29x4wZ/ZGSjeVManNb58Lz3+caFlZRCW
|
||||||
|
8vcrE5J8OcpD+0O/CKM1UJDlTVFSBJS229my5WjxQnfNZeuxRnMxOCah/qaJsZZr
|
||||||
|
FdRd0th2mRZtpjM8vZfXuoUcK+XVSENuJKdqFR4hXQU5Xq62ofxz+IiToPHO24zi
|
||||||
|
S1lp7ggeIrgZXaz2I+7LmIy6gnZWP6oXE8XcyW8CAwEAAaNTMFEwHQYDVR0OBBYE
|
||||||
|
FJLe6w7SsBTwFnIQYjjjH16p/3zDMB8GA1UdIwQYMBaAFJLe6w7SsBTwFnIQYjjj
|
||||||
|
H16p/3zDMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGrHNKNe
|
||||||
|
5UqrNPdIXlGwpabOdrhmAc9yN/tXiB386lByktIeOShS6pvD+UuV14PcTXUFGCwW
|
||||||
|
2o8I5OE/+O8w+InyWyV7qC7dgeWyEL4qDAuIYmxs71T2VOv/eekYp1Zq/o3kL3hI
|
||||||
|
f0oxonJVZXkR4p39L4TCS3z6EiWRJxWlI4LVNcvWgkwJB8w7wIxSbql0Y/EO9yoU
|
||||||
|
07u8QHVj7Nth7YteacOpj8jEy42SuWq5sdW7ccMgEfptRSYiVAmgD7mOCaELCBHz
|
||||||
|
NVqyLRPkvWqX7apqDy9vR3ZnMiHWEpTPeQqK12GJbVMW53AVEDWKiL0bhrjnY/uS
|
||||||
|
dwnpMp7fEUJLXQk=
|
||||||
|
-----END CERTIFICATE-----
|
1
test/.certs/untrusted-ca-crt.srl
Normal file
1
test/.certs/untrusted-ca-crt.srl
Normal file
@ -0,0 +1 @@
|
|||||||
|
5CB637D0B24622D344F4C956FE5930B22CF87221
|
27
test/.certs/untrusted-ca-key.pem
Normal file
27
test/.certs/untrusted-ca-key.pem
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpQIBAAKCAQEAyaZhE5l/8qDjpv/Rm+rilRjyCFQQD55iK3x0vJRn+iehbiXG
|
||||||
|
XcIrk2Ekh6vrY6W/tAi7xaFT+Fih4T7yUu9r2/QdomAaMqY9De3J6PfX0/Mhzui4
|
||||||
|
pq2tDQECL8pF4FA6ioAapr4MEgYAeiLb3HjBn9kZKN5Uxqc1vnwvPf5xoWVlEJby
|
||||||
|
9ysTknw5ykP7Q78IozVQkOVNUVIElLbb2bLlaPFCd81l67FGczE4JqH+pomxlmsV
|
||||||
|
1F3S2HaZFm2mMzy9l9e6hRwr5dVIQ24kp2oVHiFdBTlerrah/HP4iJOg8c7bjOJL
|
||||||
|
WWnuCB4iuBldrPYj7suYjLqCdlY/qhcTxdzJbwIDAQABAoIBAQCWRBLRLTDoWDZs
|
||||||
|
6vODEczZOGacCDCTwv3609qV8K1u/3tPfnzMv3YDdH9pTpaxggFSIrPyeN7/EOVI
|
||||||
|
2cRwQxQIK2it6Jl9Jt4WdB1jKtW9js+hxVBcfM2ZBChh/oSFvKNzNDUoDjUmdSyD
|
||||||
|
11gpeh8ng/s4tj1Mb6wgD6CQvPxmPLsJZ3swxdSFgR5hpXXELtAK+oOlP0Y6SFpi
|
||||||
|
d5AyiaMP9imBKQV7qgJSiKWVtSAvMhfCOPaeYM9wPCA9nha6dYGC8Fgh9FklOf2+
|
||||||
|
fj+0dqmbWwa3xuEBfZ7oS+uKnzzcBvTxtNz/U8b9bPzTtoJU6Z6P3wLIB5x8DgQ3
|
||||||
|
NcDqVbtRAoGBAOnEl1hfHsm1Ni0flugvNSY5pRF9CGQjbTk2tQxEfsPc7LiNZxjF
|
||||||
|
NFyJK2wVs17bsCI4PUO9nnMjnCi86SMKj0ifVoroYlMkt4ruY9iQPTLbrJpTBF/X
|
||||||
|
LkU77s6TSeOQdzUlVPcIXfTCYwguicpIP6kOcohHplmzdurWtl723GqHAoGBANzT
|
||||||
|
1G2h8dS7UtR0GRO4u9QM8jhRFszariovI6eOEKPaVhBhPeiwwcWRq40un7koCLzU
|
||||||
|
WA5CV6h1fGQVvN8pjpZdXYUAa26jlnISQLvNgNvwD2b5UjRi4tH2QuV0LOAMiMGs
|
||||||
|
vcQtpjM12RNfii/Tdun0mYZ9pcb65T4p5VubM9vZAoGADl4i3y+ZeNRGbCeQ4txj
|
||||||
|
6+GHH7gLl/wFborKPeLH18nwUrd+KquUOEvF+3Kp/56JCNFkEpHI91Ks+mQCAEFZ
|
||||||
|
5SDF9Ourf2i2Tzevs1PKLyIJTcLkde+HzIGOf+vVksMCUKXmvvgori50X8Bcf65J
|
||||||
|
G17j8zRUKRc6q9xegR+zFGkCgYEAtA2UG3/76nSCaO/wsn/hxlh39ytG5+k2MPcW
|
||||||
|
nzvanX8cxWZEUEIu/KR1uDvXx+S4mx6YXagCSTziG8kNovgDZt7hrdxVvHRt6ryv
|
||||||
|
Q3GgK7RlGpUXTdeDEac1jFlZbaVKrH/oitidtwuk34L67VwCjWf+9gXk8YUI/dKz
|
||||||
|
TCoT8qECgYEAyUbioIZuc6iWF2oIk3VuPdWHUvhuhzvYr+gb++P/xIXraEUMI81c
|
||||||
|
UFUDOw+jVVF6H0aioD1rRUczF9vJVE1pUZrXHbAViPECr6QgZTl1mluHtxnT8Asq
|
||||||
|
7sXS69HdlV+k+P+YZ51qRXRLKZsjwSJwn8fCRWS+7HPdQ3ogIWp1Q+A=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
20
test/.certs/untrusted-client-crt.pem
Normal file
20
test/.certs/untrusted-client-crt.pem
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDOzCCAiOgAwIBAgIUXLY30LJGItNE9MlW/lkwsiz4ciEwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwQzEUMBIGA1UECgwLbWFjaGluZXpvbmUxFDASBgNVBAoMC0lYV2ViU29ja2V0
|
||||||
|
MRUwEwYDVQQDDAx1bnRydXN0ZWQtY2EwHhcNMjAwMzEyMjMwNDM3WhcNMjEwMzEy
|
||||||
|
MjMwNDM3WjBHMRQwEgYDVQQKDAttYWNoaW5lem9uZTEUMBIGA1UECgwLSVhXZWJT
|
||||||
|
b2NrZXQxGTAXBgNVBAMMEHVudHJ1c3RlZC1jbGllbnQwggEiMA0GCSqGSIb3DQEB
|
||||||
|
AQUAA4IBDwAwggEKAoIBAQC5SOVG06/37lekGxkBJUt7AN3Xw708jN8XI7DR1sq+
|
||||||
|
NPeGN/wEfCUSIHJXQq1fqBJQkYKpyYa9EkvQs2RhrOXahul3ZdX1kP3zxQLvvbxU
|
||||||
|
EcB2gMS4B61EqnmBHRMsj+dI91++YSEFE1hkolD3+gQtm0+FVbPoXt5Y3rBAF/l0
|
||||||
|
UMvrBsgraB12OHUlqqj8WkUIul37u8XcnsnPWKoigWb2k+/W47LCGsd+haRnulIK
|
||||||
|
ADQOsjNs7wy3IV9d8zCifEV0YUT5ZPBg2K2f1lpYfOSobK7JLqgV03HVrkROQfej
|
||||||
|
FTvMRtDAxlsa6bHLrGUeBhCNaO7SLj16oo5nMCq4DnTjAgMBAAGjIzAhMB8GA1Ud
|
||||||
|
EQQYMBaCCWxvY2FsaG9zdIIJMTI3LjAuMC4xMA0GCSqGSIb3DQEBCwUAA4IBAQDH
|
||||||
|
7XbX6dCzUCGj91835gvTPr5FgKrTqocVQ+EtCxJxRVvqB4zj7/80SHxByyWz9XJQ
|
||||||
|
IBZmDz298nVqfW6uegq3qU29sG9OAOOg6I0SpWOL9qq/ZKMoEqRv6fHnjHhRiOwT
|
||||||
|
isqdZISh1vhoIvcUpNsm1PwpaDxerjeE3oPyuNO0P0lKI5jykO3orDANGvyC8fzx
|
||||||
|
jxlDsSXCgmcaPh99752vBe8UlY1M8t4GxsJAV8DXxdDZCYIWMe+/C5aQ2xDvj3+l
|
||||||
|
vYht9+yc6ebl5uGOttgWSYPxdryCynDKsdBfXxet9Ix/qdsLF9hwU2JokVDh50J+
|
||||||
|
er36eML3WvEO2HuBKTq8
|
||||||
|
-----END CERTIFICATE-----
|
27
test/.certs/untrusted-client-key.pem
Normal file
27
test/.certs/untrusted-client-key.pem
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAuUjlRtOv9+5XpBsZASVLewDd18O9PIzfFyOw0dbKvjT3hjf8
|
||||||
|
BHwlEiByV0KtX6gSUJGCqcmGvRJL0LNkYazl2obpd2XV9ZD988UC7728VBHAdoDE
|
||||||
|
uAetRKp5gR0TLI/nSPdfvmEhBRNYZKJQ9/oELZtPhVWz6F7eWN6wQBf5dFDL6wbI
|
||||||
|
K2gddjh1Jaqo/FpFCLpd+7vF3J7Jz1iqIoFm9pPv1uOywhrHfoWkZ7pSCgA0DrIz
|
||||||
|
bO8MtyFfXfMwonxFdGFE+WTwYNitn9ZaWHzkqGyuyS6oFdNx1a5ETkH3oxU7zEbQ
|
||||||
|
wMZbGumxy6xlHgYQjWju0i49eqKOZzAquA504wIDAQABAoIBAHle6OG2dUShmkNj
|
||||||
|
hMOdXI5ciPV3wRRS6yhLNt6eJvzl0WbYcXu2nsn6+ytyAAPzItwoFUGHQ33C6Grz
|
||||||
|
uEPLcF3vliuiR7+ulMwEN+I3lZA0eLCntTUfwj6CtUkAdLjyIv1HHi6ljW23uGVj
|
||||||
|
dkqaOfZuEG81Lr5+toPci/PQQJYR4btVJJHCXJ6KVx6w8i++fwcRwby9riNhWAzk
|
||||||
|
8OhUiSTTsx9sioBk62QRB8Qs0LVR5tGbDSrpQW5Ns9KnH7sayInwEN94PTsPKcqY
|
||||||
|
i/oNNZG+qvSf8jG8QiIMdyGx/goVKuQVx5Gev8my5mnfuVM/oXB20T56z2iII64V
|
||||||
|
kNh/sNECgYEA3qjAPqTY0rnu2tmvQN1PwAfyENz3XmTVWpVtBvedPj3qiV3mXJGZ
|
||||||
|
qQoS0wb/2t/D05GhTxBJARk8foorNzGchMVtECMlGxDAs1vBw6dwSK5hJnw47PQQ
|
||||||
|
Q68Vz/zwvrzJgmeijPow87PdpomYECgerTa6BynH8W0ffuSNIJC8Ke8CgYEA1Qd2
|
||||||
|
FpwFjUFqhYbcvR3VG8qAMIF8RKLzmQDDZh7liKMeHLypdXRz1ZEa6NFkvsg7qRZh
|
||||||
|
ahe/ULubnRhdOxs0JVyZPS0dU3ZmHT9bBcIuLzC//5e1ictXUZspFzIHE9T4suLC
|
||||||
|
Xnh2vqQzlEy3iZLx5B6FMzc3ws7LM7q7L2AfqE0CgYAMkvEQWJTaCaAAgeyQuC7J
|
||||||
|
xGkaJLBfh0g5LlkS3Kbnne2Bxmi874gC8MuxWSLXxG01pHK8mUnWIwu0ha79FfMl
|
||||||
|
2FRZZfKxfZe0SUk++FSx9g8MclVwpDPK7rdHoJwj2Vtz3tBiL7rV+GFbB0gsGWfq
|
||||||
|
Fj4ZK3XcH3J44wVJQoMtxwKBgQDM/ZkMuKY+/yvZwaS39vUTARHJm1BRW9y85pcg
|
||||||
|
tap6iTx4urL2a1Drue4DCzu+uj9uvjKPPLrEnUNpMADG166eJTTwQXFu1wf8LPMR
|
||||||
|
34FBt8+JzBrMtfcYeA5aW7Gjy9Rljv8qmRDq8mcP1aLnp5dMxHG4jvIBa6zt4kot
|
||||||
|
lHniIQKBgQDWuMWA2Q1kcKKy7OJszp60jO+ftq306QMoDsPNFLUUUtCxNSrpAeC2
|
||||||
|
MVvI4kzIn+6hYsMdRsqDSadosuKE4ZzCPIfuyadiAKTAO5esBJs7KAQFMJXSnfY7
|
||||||
|
+Zs1QUcdLZAWivO7j3ZASbR8L/1mawlBMgyIaT9YKp1+iW+uzaYgUQ==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
@ -56,6 +56,7 @@ set (SOURCES
|
|||||||
IXWebSocketSubProtocolTest.cpp
|
IXWebSocketSubProtocolTest.cpp
|
||||||
IXSentryClientTest.cpp
|
IXSentryClientTest.cpp
|
||||||
IXWebSocketChatTest.cpp
|
IXWebSocketChatTest.cpp
|
||||||
|
IXCobraToSentryBotTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Some unittest don't work on windows yet
|
# Some unittest don't work on windows yet
|
||||||
@ -99,6 +100,7 @@ target_link_libraries(ixwebsocket_unittest ixwebsocket)
|
|||||||
target_link_libraries(ixwebsocket_unittest ixcrypto)
|
target_link_libraries(ixwebsocket_unittest ixcrypto)
|
||||||
target_link_libraries(ixwebsocket_unittest ixcore)
|
target_link_libraries(ixwebsocket_unittest ixcore)
|
||||||
target_link_libraries(ixwebsocket_unittest ixsentry)
|
target_link_libraries(ixwebsocket_unittest ixsentry)
|
||||||
|
target_link_libraries(ixwebsocket_unittest ixbots)
|
||||||
|
|
||||||
target_link_libraries(ixwebsocket_unittest spdlog)
|
target_link_libraries(ixwebsocket_unittest spdlog)
|
||||||
|
|
||||||
|
@ -122,31 +122,32 @@ namespace
|
|||||||
void CobraChat::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(
|
||||||
spdlog::info("receive {}", msg.toStyledString());
|
channel, filter, [this](const Json::Value& msg, const std::string& /*position*/) {
|
||||||
|
spdlog::info("receive {}", msg.toStyledString());
|
||||||
|
|
||||||
if (!msg.isObject()) return;
|
if (!msg.isObject()) return;
|
||||||
if (!msg.isMember("user")) return;
|
if (!msg.isMember("user")) return;
|
||||||
if (!msg.isMember("text")) return;
|
if (!msg.isMember("text")) return;
|
||||||
if (!msg.isMember("session")) return;
|
if (!msg.isMember("session")) return;
|
||||||
|
|
||||||
std::string msg_user = msg["user"].asString();
|
std::string msg_user = msg["user"].asString();
|
||||||
std::string msg_text = msg["text"].asString();
|
std::string msg_text = msg["text"].asString();
|
||||||
std::string msg_session = msg["session"].asString();
|
std::string msg_session = msg["session"].asString();
|
||||||
|
|
||||||
// We are not interested in messages
|
// We are not interested in messages
|
||||||
// from a different session.
|
// from a different session.
|
||||||
if (msg_session != _session) return;
|
if (msg_session != _session) return;
|
||||||
|
|
||||||
// We are not interested in our own messages
|
// We are not interested in our own messages
|
||||||
if (msg_user == _user) return;
|
if (msg_user == _user) return;
|
||||||
|
|
||||||
_receivedQueue.push(msg);
|
_receivedQueue.push(msg);
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::endl << msg_user << " > " << msg_text << std::endl << _user << " > ";
|
ss << std::endl << msg_user << " > " << msg_text << std::endl << _user << " > ";
|
||||||
log(ss.str());
|
log(ss.str());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CobraChat::sendMessage(const std::string& text)
|
void CobraChat::sendMessage(const std::string& text)
|
||||||
@ -218,7 +219,7 @@ namespace
|
|||||||
}
|
}
|
||||||
else if (eventType == ix::CobraConnection_EventType_Published)
|
else if (eventType == ix::CobraConnection_EventType_Published)
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber: published message acked: " << msgId;
|
TLogger() << "Subscriber: published message acked: " << msgId;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ namespace
|
|||||||
CobraConnection::MsgId msgId) {
|
CobraConnection::MsgId msgId) {
|
||||||
if (eventType == ix::CobraConnection_EventType_Open)
|
if (eventType == ix::CobraConnection_EventType_Open)
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber connected:";
|
TLogger() << "Subscriber connected:";
|
||||||
for (auto&& it : headers)
|
for (auto&& it : headers)
|
||||||
{
|
{
|
||||||
log("Headers " + it.first + " " + it.second);
|
log("Headers " + it.first + " " + it.second);
|
||||||
@ -87,47 +87,48 @@ namespace
|
|||||||
}
|
}
|
||||||
if (eventType == ix::CobraConnection_EventType_Error)
|
if (eventType == ix::CobraConnection_EventType_Error)
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber error:" << errMsg;
|
TLogger() << "Subscriber error:" << errMsg;
|
||||||
}
|
}
|
||||||
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
||||||
{
|
{
|
||||||
log("Subscriber authenticated");
|
log("Subscriber authenticated");
|
||||||
std::string filter;
|
std::string filter;
|
||||||
conn.subscribe(CHANNEL, filter, [](const Json::Value& msg) {
|
conn.subscribe(
|
||||||
log(msg.toStyledString());
|
CHANNEL, filter, [](const Json::Value& msg, const std::string& /*position*/) {
|
||||||
|
log(msg.toStyledString());
|
||||||
|
|
||||||
std::string id = msg["id"].asString();
|
std::string id = msg["id"].asString();
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(gProtectIds);
|
std::lock_guard<std::mutex> guard(gProtectIds);
|
||||||
gIds.insert(id);
|
gIds.insert(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
gMessageCount++;
|
gMessageCount++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber: subscribed to channel " << subscriptionId;
|
TLogger() << "Subscriber: subscribed to channel " << subscriptionId;
|
||||||
if (subscriptionId == CHANNEL)
|
if (subscriptionId == CHANNEL)
|
||||||
{
|
{
|
||||||
gSubscriberConnectedAndSubscribed = true;
|
gSubscriberConnectedAndSubscribed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber: unexpected channel " << subscriptionId;
|
TLogger() << "Subscriber: unexpected channel " << subscriptionId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber: ununexpected from channel " << subscriptionId;
|
TLogger() << "Subscriber: ununexpected from channel " << subscriptionId;
|
||||||
if (subscriptionId != CHANNEL)
|
if (subscriptionId != CHANNEL)
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber: unexpected channel " << subscriptionId;
|
TLogger() << "Subscriber: unexpected channel " << subscriptionId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eventType == ix::CobraConnection_EventType_Published)
|
else if (eventType == ix::CobraConnection_EventType_Published)
|
||||||
{
|
{
|
||||||
Logger() << "Subscriber: published message acked: " << msgId;
|
TLogger() << "Subscriber: published message acked: " << msgId;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
211
test/IXCobraToSentryBotTest.cpp
Normal file
211
test/IXCobraToSentryBotTest.cpp
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* cmd_satori_chat.cpp
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2017 Machine Zone. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IXTest.h"
|
||||||
|
#include "catch.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <ixbots/IXCobraToSentryBot.h>
|
||||||
|
#include <ixcobra/IXCobraConnection.h>
|
||||||
|
#include <ixcobra/IXCobraMetricsPublisher.h>
|
||||||
|
#include <ixcrypto/IXUuid.h>
|
||||||
|
#include <ixsentry/IXSentryClient.h>
|
||||||
|
#include <ixsnake/IXRedisServer.h>
|
||||||
|
#include <ixsnake/IXSnakeServer.h>
|
||||||
|
#include <ixwebsocket/IXHttpServer.h>
|
||||||
|
#include <ixwebsocket/IXUserAgent.h>
|
||||||
|
|
||||||
|
using namespace ix;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::atomic<size_t> incomingBytes(0);
|
||||||
|
std::atomic<size_t> outgoingBytes(0);
|
||||||
|
|
||||||
|
void setupTrafficTrackerCallback()
|
||||||
|
{
|
||||||
|
ix::CobraConnection::setTrafficTrackerCallback([](size_t size, bool incoming) {
|
||||||
|
if (incoming)
|
||||||
|
{
|
||||||
|
incomingBytes += size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outgoingBytes += size;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void runPublisher(const ix::CobraConfig& config, const std::string& channel)
|
||||||
|
{
|
||||||
|
ix::CobraMetricsPublisher cobraMetricsPublisher;
|
||||||
|
|
||||||
|
SocketTLSOptions socketTLSOptions;
|
||||||
|
bool perMessageDeflate = true;
|
||||||
|
cobraMetricsPublisher.configure(config.appkey,
|
||||||
|
config.endpoint,
|
||||||
|
channel,
|
||||||
|
config.rolename,
|
||||||
|
config.rolesecret,
|
||||||
|
perMessageDeflate,
|
||||||
|
socketTLSOptions);
|
||||||
|
cobraMetricsPublisher.setSession(uuid4());
|
||||||
|
cobraMetricsPublisher.enable(true); // disabled by default, needs to be enabled to be active
|
||||||
|
|
||||||
|
Json::Value msg;
|
||||||
|
msg["fps"] = 60;
|
||||||
|
|
||||||
|
cobraMetricsPublisher.setGenericAttributes("game", "ody");
|
||||||
|
|
||||||
|
// Wait a bit
|
||||||
|
ix::msleep(500);
|
||||||
|
|
||||||
|
// publish some messages
|
||||||
|
cobraMetricsPublisher.push("sms_metric_A_id", msg); // (msg #1)
|
||||||
|
cobraMetricsPublisher.push("sms_metric_B_id", msg); // (msg #2)
|
||||||
|
ix::msleep(500);
|
||||||
|
|
||||||
|
cobraMetricsPublisher.push("sms_metric_A_id", msg); // (msg #3)
|
||||||
|
cobraMetricsPublisher.push("sms_metric_D_id", msg); // (msg #4)
|
||||||
|
ix::msleep(500);
|
||||||
|
|
||||||
|
cobraMetricsPublisher.push("sms_metric_A_id", msg); // (msg #4)
|
||||||
|
cobraMetricsPublisher.push("sms_metric_F_id", msg); // (msg #5)
|
||||||
|
ix::msleep(500);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("Cobra_to_sentry_bot", "[foo]")
|
||||||
|
{
|
||||||
|
SECTION("Exchange and count sent/received messages.")
|
||||||
|
{
|
||||||
|
int port = getFreePort();
|
||||||
|
snake::AppConfig appConfig = makeSnakeServerConfig(port);
|
||||||
|
|
||||||
|
// Start a redis server
|
||||||
|
ix::RedisServer redisServer(appConfig.redisPort);
|
||||||
|
auto res = redisServer.listen();
|
||||||
|
REQUIRE(res.first);
|
||||||
|
redisServer.start();
|
||||||
|
|
||||||
|
// Start a snake server
|
||||||
|
snake::SnakeServer snakeServer(appConfig);
|
||||||
|
snakeServer.run();
|
||||||
|
|
||||||
|
// Start a fake sentry http server
|
||||||
|
SocketTLSOptions tlsOptionsServer;
|
||||||
|
tlsOptionsServer.certFile = ".certs/trusted-server-crt.pem";
|
||||||
|
tlsOptionsServer.keyFile = ".certs/trusted-server-key.pem";
|
||||||
|
tlsOptionsServer.caFile = ".certs/trusted-ca-crt.pem";
|
||||||
|
|
||||||
|
int sentryPort = getFreePort();
|
||||||
|
ix::HttpServer sentryServer(sentryPort, "127.0.0.1");
|
||||||
|
sentryServer.setTLSOptions(tlsOptionsServer);
|
||||||
|
|
||||||
|
sentryServer.setOnConnectionCallback(
|
||||||
|
[](HttpRequestPtr request,
|
||||||
|
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr {
|
||||||
|
WebSocketHttpHeaders headers;
|
||||||
|
headers["Server"] = userAgent();
|
||||||
|
|
||||||
|
// Log request
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << request->method << " " << request->headers["User-Agent"] << " "
|
||||||
|
<< request->uri;
|
||||||
|
|
||||||
|
if (request->method == "POST")
|
||||||
|
{
|
||||||
|
return std::make_shared<HttpResponse>(
|
||||||
|
200, "OK", HttpErrorCode::Ok, headers, std::string());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::make_shared<HttpResponse>(
|
||||||
|
405, "OK", HttpErrorCode::Invalid, headers, std::string("Invalid method"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res = sentryServer.listen();
|
||||||
|
REQUIRE(res.first);
|
||||||
|
sentryServer.start();
|
||||||
|
|
||||||
|
setupTrafficTrackerCallback();
|
||||||
|
|
||||||
|
// Run the bot for a small amount of time
|
||||||
|
std::string channel = ix::generateSessionId();
|
||||||
|
std::string appkey("FC2F10139A2BAc53BB72D9db967b024f");
|
||||||
|
std::string role = "_sub";
|
||||||
|
std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba";
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "ws://localhost:" << port;
|
||||||
|
std::string endpoint = ss.str();
|
||||||
|
|
||||||
|
ix::CobraConfig config;
|
||||||
|
config.endpoint = endpoint;
|
||||||
|
config.appkey = appkey;
|
||||||
|
config.rolename = role;
|
||||||
|
config.rolesecret = secret;
|
||||||
|
|
||||||
|
std::thread publisherThread(runPublisher, config, channel);
|
||||||
|
|
||||||
|
std::string filter;
|
||||||
|
bool verbose = true;
|
||||||
|
bool strict = true;
|
||||||
|
size_t maxQueueSize = 10;
|
||||||
|
bool enableHeartbeat = false;
|
||||||
|
|
||||||
|
// FIXME: try to get this working with https instead of http
|
||||||
|
// to regress the TLS 1.3 OpenSSL bug
|
||||||
|
// -> https://github.com/openssl/openssl/issues/7967
|
||||||
|
// https://xxxxx:yyyyyy@sentry.io/1234567
|
||||||
|
std::stringstream oss;
|
||||||
|
std::string scheme("http://");
|
||||||
|
|
||||||
|
oss << scheme << "xxxxxxx:yyyyyyy@localhost:" << sentryPort << "/1234567";
|
||||||
|
std::string dsn = oss.str();
|
||||||
|
|
||||||
|
SocketTLSOptions tlsOptionsClient;
|
||||||
|
tlsOptionsClient.certFile = ".certs/trusted-client-crt.pem";
|
||||||
|
tlsOptionsClient.keyFile = ".certs/trusted-client-key.pem";
|
||||||
|
tlsOptionsClient.caFile = ".certs/trusted-ca-crt.pem";
|
||||||
|
|
||||||
|
SentryClient sentryClient(dsn);
|
||||||
|
sentryClient.setTLSOptions(tlsOptionsClient);
|
||||||
|
|
||||||
|
// Only run the bot for 3 seconds
|
||||||
|
int runtime = 3;
|
||||||
|
|
||||||
|
int sentCount = cobra_to_sentry_bot(config,
|
||||||
|
channel,
|
||||||
|
filter,
|
||||||
|
sentryClient,
|
||||||
|
verbose,
|
||||||
|
strict,
|
||||||
|
maxQueueSize,
|
||||||
|
enableHeartbeat,
|
||||||
|
runtime);
|
||||||
|
//
|
||||||
|
// We want at least 2 messages to be sent
|
||||||
|
//
|
||||||
|
REQUIRE(sentCount >= 2);
|
||||||
|
|
||||||
|
// Give us 1s for all messages to be received
|
||||||
|
ix::msleep(1000);
|
||||||
|
|
||||||
|
spdlog::info("Incoming bytes {}", incomingBytes);
|
||||||
|
spdlog::info("Outgoing bytes {}", outgoingBytes);
|
||||||
|
|
||||||
|
spdlog::info("Stopping snake server...");
|
||||||
|
snakeServer.stop();
|
||||||
|
|
||||||
|
spdlog::info("Stopping redis server...");
|
||||||
|
redisServer.stop();
|
||||||
|
|
||||||
|
publisherThread.join();
|
||||||
|
sentryServer.stop();
|
||||||
|
}
|
||||||
|
}
|
@ -59,10 +59,14 @@ TEST_CASE("http server", "[httpd]")
|
|||||||
|
|
||||||
REQUIRE(response->errorCode == HttpErrorCode::Ok);
|
REQUIRE(response->errorCode == HttpErrorCode::Ok);
|
||||||
REQUIRE(response->statusCode == 200);
|
REQUIRE(response->statusCode == 200);
|
||||||
|
REQUIRE(response->headers["Accept-Encoding"] == "gzip");
|
||||||
|
|
||||||
server.stop();
|
server.stop();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("http server redirection", "[httpd_redirect]")
|
||||||
|
{
|
||||||
SECTION("Connect to a local HTTP server, with redirection enabled")
|
SECTION("Connect to a local HTTP server, with redirection enabled")
|
||||||
{
|
{
|
||||||
int port = getFreePort();
|
int port = getFreePort();
|
||||||
|
@ -29,17 +29,17 @@ namespace ix
|
|||||||
makeCancellationRequestWithTimeout(timeoutSecs, requestInitCancellation);
|
makeCancellationRequestWithTimeout(timeoutSecs, requestInitCancellation);
|
||||||
|
|
||||||
bool success = socket->connect(host, port, errMsg, isCancellationRequested);
|
bool success = socket->connect(host, port, errMsg, isCancellationRequested);
|
||||||
Logger() << "errMsg: " << errMsg;
|
TLogger() << "errMsg: " << errMsg;
|
||||||
REQUIRE(success);
|
REQUIRE(success);
|
||||||
|
|
||||||
Logger() << "Sending request: " << request << "to " << host << ":" << port;
|
TLogger() << "Sending request: " << request << "to " << host << ":" << port;
|
||||||
REQUIRE(socket->writeBytes(request, isCancellationRequested));
|
REQUIRE(socket->writeBytes(request, isCancellationRequested));
|
||||||
|
|
||||||
auto lineResult = socket->readLine(isCancellationRequested);
|
auto lineResult = socket->readLine(isCancellationRequested);
|
||||||
auto lineValid = lineResult.first;
|
auto lineValid = lineResult.first;
|
||||||
auto line = lineResult.second;
|
auto line = lineResult.second;
|
||||||
|
|
||||||
Logger() << "read error: " << strerror(Socket::getErrno());
|
TLogger() << "read error: " << strerror(Socket::getErrno());
|
||||||
|
|
||||||
REQUIRE(lineValid);
|
REQUIRE(lineValid);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace ix
|
|||||||
{
|
{
|
||||||
std::atomic<size_t> incomingBytes(0);
|
std::atomic<size_t> incomingBytes(0);
|
||||||
std::atomic<size_t> outgoingBytes(0);
|
std::atomic<size_t> outgoingBytes(0);
|
||||||
std::mutex Logger::_mutex;
|
std::mutex TLogger::_mutex;
|
||||||
std::stack<int> freePorts;
|
std::stack<int> freePorts;
|
||||||
|
|
||||||
void setupWebSocketTrafficTrackerCallback()
|
void setupWebSocketTrafficTrackerCallback()
|
||||||
@ -43,9 +43,9 @@ namespace ix
|
|||||||
|
|
||||||
void reportWebSocketTraffic()
|
void reportWebSocketTraffic()
|
||||||
{
|
{
|
||||||
Logger() << incomingBytes;
|
TLogger() << incomingBytes;
|
||||||
Logger() << "Incoming bytes: " << incomingBytes;
|
TLogger() << "Incoming bytes: " << incomingBytes;
|
||||||
Logger() << "Outgoing bytes: " << outgoingBytes;
|
TLogger() << "Outgoing bytes: " << outgoingBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void msleep(int ms)
|
void msleep(int ms)
|
||||||
@ -65,7 +65,7 @@ namespace ix
|
|||||||
|
|
||||||
void log(const std::string& msg)
|
void log(const std::string& msg)
|
||||||
{
|
{
|
||||||
Logger() << msg;
|
TLogger() << msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hexDump(const std::string& prefix, const std::string& s)
|
void hexDump(const std::string& prefix, const std::string& s)
|
||||||
@ -90,17 +90,17 @@ namespace ix
|
|||||||
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
|
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
|
||||||
if (msg->type == ix::WebSocketMessageType::Open)
|
if (msg->type == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New connection";
|
TLogger() << "New connection";
|
||||||
Logger() << "Uri: " << msg->openInfo.uri;
|
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto it : msg->openInfo.headers)
|
for (auto it : msg->openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||||
{
|
{
|
||||||
Logger() << "Closed connection";
|
TLogger() << "Closed connection";
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||||
{
|
{
|
||||||
@ -118,7 +118,7 @@ namespace ix
|
|||||||
auto res = server.listen();
|
auto res = server.listen();
|
||||||
if (!res.first)
|
if (!res.first)
|
||||||
{
|
{
|
||||||
Logger() << res.second;
|
TLogger() << res.second;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ namespace ix
|
|||||||
void setupWebSocketTrafficTrackerCallback();
|
void setupWebSocketTrafficTrackerCallback();
|
||||||
void reportWebSocketTraffic();
|
void reportWebSocketTraffic();
|
||||||
|
|
||||||
struct Logger
|
struct TLogger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Logger& operator<<(T const& obj)
|
TLogger& operator<<(T const& obj)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
|
||||||
|
@ -199,13 +199,13 @@ namespace
|
|||||||
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
|
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
|
||||||
if (msg->type == ix::WebSocketMessageType::Open)
|
if (msg->type == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New connection";
|
TLogger() << "New connection";
|
||||||
Logger() << "id: " << connectionState->getId();
|
TLogger() << "id: " << connectionState->getId();
|
||||||
Logger() << "Uri: " << msg->openInfo.uri;
|
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto it : msg->openInfo.headers)
|
for (auto it : msg->openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||||
|
@ -180,13 +180,13 @@ namespace
|
|||||||
&mutexWrite](const ix::WebSocketMessagePtr& msg) {
|
&mutexWrite](const ix::WebSocketMessagePtr& msg) {
|
||||||
if (msg->type == ix::WebSocketMessageType::Open)
|
if (msg->type == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New server connection";
|
TLogger() << "New server connection";
|
||||||
Logger() << "id: " << connectionState->getId();
|
TLogger() << "id: " << connectionState->getId();
|
||||||
Logger() << "Uri: " << msg->openInfo.uri;
|
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto it : msg->openInfo.headers)
|
for (auto it : msg->openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||||
|
@ -23,23 +23,23 @@ namespace
|
|||||||
[connectionState, &server](const WebSocketMessagePtr& msg) {
|
[connectionState, &server](const WebSocketMessagePtr& msg) {
|
||||||
if (msg->type == ix::WebSocketMessageType::Open)
|
if (msg->type == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New connection";
|
TLogger() << "New connection";
|
||||||
connectionState->computeId();
|
connectionState->computeId();
|
||||||
Logger() << "id: " << connectionState->getId();
|
TLogger() << "id: " << connectionState->getId();
|
||||||
Logger() << "Uri: " << msg->openInfo.uri;
|
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto&& it : msg->openInfo.headers)
|
for (auto&& it : msg->openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||||
{
|
{
|
||||||
Logger() << "Closed connection";
|
TLogger() << "Closed connection";
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||||
{
|
{
|
||||||
Logger() << "Message received: " << msg->str;
|
TLogger() << "Message received: " << msg->str;
|
||||||
|
|
||||||
for (auto&& client : server.getClients())
|
for (auto&& client : server.getClients())
|
||||||
{
|
{
|
||||||
@ -52,7 +52,7 @@ namespace
|
|||||||
auto res = server.listen();
|
auto res = server.listen();
|
||||||
if (!res.first)
|
if (!res.first)
|
||||||
{
|
{
|
||||||
Logger() << res.second;
|
TLogger() << res.second;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,13 +140,13 @@ namespace
|
|||||||
const ix::WebSocketCloseInfo& closeInfo) {
|
const ix::WebSocketCloseInfo& closeInfo) {
|
||||||
if (messageType == ix::WebSocketMessageType::Open)
|
if (messageType == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New server connection";
|
TLogger() << "New server connection";
|
||||||
Logger() << "id: " << connectionState->getId();
|
TLogger() << "id: " << connectionState->getId();
|
||||||
Logger() << "Uri: " << openInfo.uri;
|
TLogger() << "Uri: " << openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto it : openInfo.headers)
|
for (auto it : openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (messageType == ix::WebSocketMessageType::Close)
|
else if (messageType == ix::WebSocketMessageType::Close)
|
||||||
|
@ -169,13 +169,13 @@ namespace
|
|||||||
const ix::WebSocketCloseInfo& closeInfo) {
|
const ix::WebSocketCloseInfo& closeInfo) {
|
||||||
if (messageType == ix::WebSocketMessageType::Open)
|
if (messageType == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New server connection";
|
TLogger() << "New server connection";
|
||||||
Logger() << "id: " << connectionState->getId();
|
TLogger() << "id: " << connectionState->getId();
|
||||||
Logger() << "Uri: " << openInfo.uri;
|
TLogger() << "Uri: " << openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto it : openInfo.headers)
|
for (auto it : openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (messageType == ix::WebSocketMessageType::Close)
|
else if (messageType == ix::WebSocketMessageType::Close)
|
||||||
|
@ -40,21 +40,21 @@ namespace ix
|
|||||||
const ix::WebSocketMessagePtr& msg) {
|
const ix::WebSocketMessagePtr& msg) {
|
||||||
if (msg->type == ix::WebSocketMessageType::Open)
|
if (msg->type == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New connection";
|
TLogger() << "New connection";
|
||||||
connectionState->computeId();
|
connectionState->computeId();
|
||||||
Logger() << "id: " << connectionState->getId();
|
TLogger() << "id: " << connectionState->getId();
|
||||||
Logger() << "Uri: " << msg->openInfo.uri;
|
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto it : msg->openInfo.headers)
|
for (auto it : msg->openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionId = connectionState->getId();
|
connectionId = connectionState->getId();
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||||
{
|
{
|
||||||
Logger() << "Closed connection";
|
TLogger() << "Closed connection";
|
||||||
}
|
}
|
||||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@ namespace ix
|
|||||||
auto res = server.listen();
|
auto res = server.listen();
|
||||||
if (!res.first)
|
if (!res.first)
|
||||||
{
|
{
|
||||||
Logger() << res.second;
|
TLogger() << res.second;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
|
|||||||
bool success = socket->connect(host, port, errMsg, isCancellationRequested);
|
bool success = socket->connect(host, port, errMsg, isCancellationRequested);
|
||||||
REQUIRE(success);
|
REQUIRE(success);
|
||||||
|
|
||||||
Logger() << "writeBytes";
|
TLogger() << "writeBytes";
|
||||||
socket->writeBytes("GET /\r\n", isCancellationRequested);
|
socket->writeBytes("GET /\r\n", isCancellationRequested);
|
||||||
|
|
||||||
auto lineResult = socket->readLine(isCancellationRequested);
|
auto lineResult = socket->readLine(isCancellationRequested);
|
||||||
|
@ -23,13 +23,13 @@ bool startServer(ix::WebSocketServer& server, std::string& subProtocols)
|
|||||||
const ix::WebSocketMessagePtr& msg) {
|
const ix::WebSocketMessagePtr& msg) {
|
||||||
if (msg->type == ix::WebSocketMessageType::Open)
|
if (msg->type == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
Logger() << "New connection";
|
TLogger() << "New connection";
|
||||||
Logger() << "id: " << connectionState->getId();
|
TLogger() << "id: " << connectionState->getId();
|
||||||
Logger() << "Uri: " << msg->openInfo.uri;
|
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||||
Logger() << "Headers:";
|
TLogger() << "Headers:";
|
||||||
for (auto it : msg->openInfo.headers)
|
for (auto it : msg->openInfo.headers)
|
||||||
{
|
{
|
||||||
Logger() << it.first << ": " << it.second;
|
TLogger() << it.first << ": " << it.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
subProtocols = msg->openInfo.headers["Sec-WebSocket-Protocol"];
|
subProtocols = msg->openInfo.headers["Sec-WebSocket-Protocol"];
|
||||||
|
11
test/compatibility/node/echo_server.js
Normal file
11
test/compatibility/node/echo_server.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const WebSocket = require('ws');
|
||||||
|
|
||||||
|
const wss = new WebSocket.Server({ port: 8080 });
|
||||||
|
|
||||||
|
wss.on('connection', function connection(ws) {
|
||||||
|
ws.on('message', function incoming(message) {
|
||||||
|
console.log('received: %s', message);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.send('something');
|
||||||
|
});
|
11
test/compatibility/node/echo_server_permessagedeflate.js
Normal file
11
test/compatibility/node/echo_server_permessagedeflate.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const WebSocket = require('ws');
|
||||||
|
|
||||||
|
const wss = new WebSocket.Server({ port: 8080, perMessageDeflate: true });
|
||||||
|
|
||||||
|
wss.on('connection', function connection(ws) {
|
||||||
|
ws.on('message', function incoming(message) {
|
||||||
|
console.log('received: %s', message);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.send('something');
|
||||||
|
});
|
25
test/compatibility/python/websockets/echo_client.py
Normal file
25
test/compatibility/python/websockets/echo_client.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# websocket send client
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import asyncio
|
||||||
|
import websockets
|
||||||
|
|
||||||
|
|
||||||
|
async def send(url):
|
||||||
|
async with websockets.connect(url) as ws:
|
||||||
|
while True:
|
||||||
|
message = input('> ')
|
||||||
|
print('Sending message...')
|
||||||
|
await ws.send(message)
|
||||||
|
print('Message sent.')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser(description='websocket proxy.')
|
||||||
|
parser.add_argument('--url', help='Remote websocket url',
|
||||||
|
default='wss://echo.websocket.org')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
asyncio.get_event_loop().run_until_complete(send(args.url))
|
@ -8,9 +8,10 @@ import websockets
|
|||||||
|
|
||||||
|
|
||||||
async def echo(websocket, path):
|
async def echo(websocket, path):
|
||||||
msg = await websocket.recv()
|
while True:
|
||||||
print(f'Received {len(msg)} bytes')
|
msg = await websocket.recv()
|
||||||
await websocket.send(msg)
|
print(f'Received {len(msg)} bytes')
|
||||||
|
await websocket.send(msg)
|
||||||
|
|
||||||
host = os.getenv('BIND_HOST', 'localhost')
|
host = os.getenv('BIND_HOST', 'localhost')
|
||||||
print(f'Serving on {host}:8766')
|
print(f'Serving on {host}:8766')
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# WS server example
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
import websockets
|
||||||
|
|
||||||
|
|
||||||
|
async def echo(websocket, path):
|
||||||
|
while True:
|
||||||
|
msg = await websocket.recv()
|
||||||
|
print(f'Received {len(msg)} bytes')
|
||||||
|
await websocket.send(msg)
|
||||||
|
|
||||||
|
host = os.getenv('BIND_HOST', 'localhost')
|
||||||
|
print(f'Serving on {host}:8766')
|
||||||
|
|
||||||
|
start_server = websockets.serve(echo, host, 8766, max_size=2 ** 30)
|
||||||
|
|
||||||
|
asyncio.get_event_loop().run_until_complete(start_server)
|
||||||
|
asyncio.get_event_loop().run_forever()
|
0
test/compatibility/python/websockets/empty_file
Normal file
0
test/compatibility/python/websockets/empty_file
Normal file
@ -58,8 +58,6 @@ add_executable(ws
|
|||||||
ws_cobra_subscribe.cpp
|
ws_cobra_subscribe.cpp
|
||||||
ws_cobra_metrics_publish.cpp
|
ws_cobra_metrics_publish.cpp
|
||||||
ws_cobra_publish.cpp
|
ws_cobra_publish.cpp
|
||||||
ws_cobra_to_statsd.cpp
|
|
||||||
ws_cobra_to_sentry.cpp
|
|
||||||
ws_cobra_metrics_to_redis.cpp
|
ws_cobra_metrics_to_redis.cpp
|
||||||
ws_httpd.cpp
|
ws_httpd.cpp
|
||||||
ws_autobahn.cpp
|
ws_autobahn.cpp
|
||||||
@ -74,6 +72,7 @@ target_link_libraries(ws ixwebsocket)
|
|||||||
target_link_libraries(ws ixcrypto)
|
target_link_libraries(ws ixcrypto)
|
||||||
target_link_libraries(ws ixcore)
|
target_link_libraries(ws ixcore)
|
||||||
target_link_libraries(ws ixsentry)
|
target_link_libraries(ws ixsentry)
|
||||||
|
target_link_libraries(ws ixbots)
|
||||||
|
|
||||||
target_link_libraries(ws spdlog)
|
target_link_libraries(ws spdlog)
|
||||||
|
|
||||||
|
123
ws/ws.cpp
123
ws/ws.cpp
@ -11,7 +11,10 @@
|
|||||||
|
|
||||||
#include <cli11/CLI11.hpp>
|
#include <cli11/CLI11.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <ixbots/IXCobraToSentryBot.h>
|
||||||
|
#include <ixbots/IXCobraToStatsdBot.h>
|
||||||
#include <ixcore/utils/IXCoreLogger.h>
|
#include <ixcore/utils/IXCoreLogger.h>
|
||||||
|
#include <ixsentry/IXSentryClient.h>
|
||||||
#include <ixwebsocket/IXNetSystem.h>
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
#include <ixwebsocket/IXSocket.h>
|
#include <ixwebsocket/IXSocket.h>
|
||||||
#include <ixwebsocket/IXUserAgent.h>
|
#include <ixwebsocket/IXUserAgent.h>
|
||||||
@ -64,10 +67,6 @@ int main(int argc, char** argv)
|
|||||||
std::string filter;
|
std::string filter;
|
||||||
std::string message;
|
std::string message;
|
||||||
std::string password;
|
std::string password;
|
||||||
std::string appkey;
|
|
||||||
std::string endpoint;
|
|
||||||
std::string rolename;
|
|
||||||
std::string rolesecret;
|
|
||||||
std::string prefix("ws.test.v0");
|
std::string prefix("ws.test.v0");
|
||||||
std::string fields;
|
std::string fields;
|
||||||
std::string dsn;
|
std::string dsn;
|
||||||
@ -81,6 +80,7 @@ int main(int argc, char** argv)
|
|||||||
std::string project;
|
std::string project;
|
||||||
std::string key;
|
std::string key;
|
||||||
ix::SocketTLSOptions tlsOptions;
|
ix::SocketTLSOptions tlsOptions;
|
||||||
|
ix::CobraConfig cobraConfig;
|
||||||
std::string ciphers;
|
std::string ciphers;
|
||||||
std::string redirectUrl;
|
std::string redirectUrl;
|
||||||
bool headersOnly = false;
|
bool headersOnly = false;
|
||||||
@ -88,6 +88,7 @@ int main(int argc, char** argv)
|
|||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool save = false;
|
bool save = false;
|
||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
|
bool fluentd = false;
|
||||||
bool compress = false;
|
bool compress = false;
|
||||||
bool strict = false;
|
bool strict = false;
|
||||||
bool stress = false;
|
bool stress = false;
|
||||||
@ -108,7 +109,6 @@ int main(int argc, char** argv)
|
|||||||
int maxRedirects = 5;
|
int maxRedirects = 5;
|
||||||
int delayMs = -1;
|
int delayMs = -1;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
int jobs = 4;
|
|
||||||
uint32_t maxWaitBetweenReconnectionRetries;
|
uint32_t maxWaitBetweenReconnectionRetries;
|
||||||
size_t maxQueueSize = 100;
|
size_t maxQueueSize = 100;
|
||||||
|
|
||||||
@ -127,6 +127,13 @@ int main(int argc, char** argv)
|
|||||||
app->add_flag("--verify_none", verifyNone, "Disable peer cert verification");
|
app->add_flag("--verify_none", verifyNone, "Disable peer cert verification");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto addCobraConfig = [&cobraConfig](CLI::App* app) {
|
||||||
|
app->add_option("--appkey", cobraConfig.appkey, "Appkey")->required();
|
||||||
|
app->add_option("--endpoint", cobraConfig.endpoint, "Endpoint")->required();
|
||||||
|
app->add_option("--rolename", cobraConfig.rolename, "Role name")->required();
|
||||||
|
app->add_option("--rolesecret", cobraConfig.rolesecret, "Role secret")->required();
|
||||||
|
};
|
||||||
|
|
||||||
app.add_flag("--version", version, "Print ws version");
|
app.add_flag("--version", version, "Print ws version");
|
||||||
|
|
||||||
CLI::App* sendApp = app.add_subcommand("send", "Send a file");
|
CLI::App* sendApp = app.add_subcommand("send", "Send a file");
|
||||||
@ -174,6 +181,7 @@ int main(int argc, char** argv)
|
|||||||
echoServerApp->add_option("--host", hostname, "Hostname");
|
echoServerApp->add_option("--host", hostname, "Hostname");
|
||||||
echoServerApp->add_flag("-g", greetings, "Verbose");
|
echoServerApp->add_flag("-g", greetings, "Verbose");
|
||||||
echoServerApp->add_flag("-6", ipv6, "IpV6");
|
echoServerApp->add_flag("-6", ipv6, "IpV6");
|
||||||
|
echoServerApp->add_flag("-x", disablePerMessageDeflate, "Disable per message deflate");
|
||||||
addTLSOptions(echoServerApp);
|
addTLSOptions(echoServerApp);
|
||||||
|
|
||||||
CLI::App* broadcastServerApp = app.add_subcommand("broadcast_server", "Broadcasting server");
|
CLI::App* broadcastServerApp = app.add_subcommand("broadcast_server", "Broadcasting server");
|
||||||
@ -218,34 +226,25 @@ int main(int argc, char** argv)
|
|||||||
redisSubscribeApp->add_option("--pidfile", pidfile, "Pid file");
|
redisSubscribeApp->add_option("--pidfile", pidfile, "Pid file");
|
||||||
|
|
||||||
CLI::App* cobraSubscribeApp = app.add_subcommand("cobra_subscribe", "Cobra subscriber");
|
CLI::App* cobraSubscribeApp = app.add_subcommand("cobra_subscribe", "Cobra subscriber");
|
||||||
cobraSubscribeApp->add_option("--appkey", appkey, "Appkey")->required();
|
|
||||||
cobraSubscribeApp->add_option("--endpoint", endpoint, "Endpoint")->required();
|
|
||||||
cobraSubscribeApp->add_option("--rolename", rolename, "Role name")->required();
|
|
||||||
cobraSubscribeApp->add_option("--rolesecret", rolesecret, "Role secret")->required();
|
|
||||||
cobraSubscribeApp->add_option("--channel", channel, "Channel")->required();
|
cobraSubscribeApp->add_option("--channel", channel, "Channel")->required();
|
||||||
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");
|
||||||
|
cobraSubscribeApp->add_flag("--fluentd", fluentd, "Write fluentd prefix");
|
||||||
addTLSOptions(cobraSubscribeApp);
|
addTLSOptions(cobraSubscribeApp);
|
||||||
|
addCobraConfig(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("--endpoint", endpoint, "Endpoint")->required();
|
|
||||||
cobraPublish->add_option("--rolename", rolename, "Role name")->required();
|
|
||||||
cobraPublish->add_option("--rolesecret", rolesecret, "Role secret")->required();
|
|
||||||
cobraPublish->add_option("--channel", channel, "Channel")->required();
|
cobraPublish->add_option("--channel", channel, "Channel")->required();
|
||||||
cobraPublish->add_option("--pidfile", pidfile, "Pid file");
|
cobraPublish->add_option("--pidfile", pidfile, "Pid file");
|
||||||
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);
|
addTLSOptions(cobraPublish);
|
||||||
|
addCobraConfig(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");
|
||||||
cobraMetricsPublish->add_option("--appkey", appkey, "Appkey");
|
|
||||||
cobraMetricsPublish->add_option("--endpoint", endpoint, "Endpoint");
|
|
||||||
cobraMetricsPublish->add_option("--rolename", rolename, "Role name");
|
|
||||||
cobraMetricsPublish->add_option("--rolesecret", rolesecret, "Role secret");
|
|
||||||
cobraMetricsPublish->add_option("--channel", channel, "Channel")->required();
|
cobraMetricsPublish->add_option("--channel", channel, "Channel")->required();
|
||||||
cobraMetricsPublish->add_option("--pidfile", pidfile, "Pid file");
|
cobraMetricsPublish->add_option("--pidfile", pidfile, "Pid file");
|
||||||
cobraMetricsPublish->add_option("path", path, "Path to the file to send")
|
cobraMetricsPublish->add_option("path", path, "Path to the file to send")
|
||||||
@ -253,12 +252,9 @@ int main(int argc, char** argv)
|
|||||||
->check(CLI::ExistingPath);
|
->check(CLI::ExistingPath);
|
||||||
cobraMetricsPublish->add_flag("--stress", stress, "Stress mode");
|
cobraMetricsPublish->add_flag("--stress", stress, "Stress mode");
|
||||||
addTLSOptions(cobraMetricsPublish);
|
addTLSOptions(cobraMetricsPublish);
|
||||||
|
addCobraConfig(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("--endpoint", endpoint, "Endpoint");
|
|
||||||
cobra2statsd->add_option("--rolename", rolename, "Role name");
|
|
||||||
cobra2statsd->add_option("--rolesecret", rolesecret, "Role secret");
|
|
||||||
cobra2statsd->add_option("--host", hostname, "Statsd host");
|
cobra2statsd->add_option("--host", hostname, "Statsd host");
|
||||||
cobra2statsd->add_option("--port", statsdPort, "Statsd port");
|
cobra2statsd->add_option("--port", statsdPort, "Statsd port");
|
||||||
cobra2statsd->add_option("--prefix", prefix, "Statsd prefix");
|
cobra2statsd->add_option("--prefix", prefix, "Statsd prefix");
|
||||||
@ -268,14 +264,10 @@ int main(int argc, char** argv)
|
|||||||
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);
|
addTLSOptions(cobra2statsd);
|
||||||
|
addCobraConfig(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("--endpoint", endpoint, "Endpoint")->required();
|
|
||||||
cobra2sentry->add_option("--rolename", rolename, "Role name")->required();
|
|
||||||
cobra2sentry->add_option("--rolesecret", rolesecret, "Role secret")->required();
|
|
||||||
cobra2sentry->add_option("--dsn", dsn, "Sentry DSN");
|
cobra2sentry->add_option("--dsn", dsn, "Sentry DSN");
|
||||||
cobra2sentry->add_option("--jobs", jobs, "Number of thread sending events to Sentry");
|
|
||||||
cobra2sentry->add_option("--queue_size",
|
cobra2sentry->add_option("--queue_size",
|
||||||
maxQueueSize,
|
maxQueueSize,
|
||||||
"Size of the queue to hold messages before they are sent to Sentry");
|
"Size of the queue to hold messages before they are sent to Sentry");
|
||||||
@ -285,13 +277,10 @@ int main(int argc, char** argv)
|
|||||||
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);
|
addTLSOptions(cobra2sentry);
|
||||||
|
addCobraConfig(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");
|
||||||
cobra2redisApp->add_option("--appkey", appkey, "Appkey")->required();
|
|
||||||
cobra2redisApp->add_option("--endpoint", endpoint, "Endpoint")->required();
|
|
||||||
cobra2redisApp->add_option("--rolename", rolename, "Role name")->required();
|
|
||||||
cobra2redisApp->add_option("--rolesecret", rolesecret, "Role secret")->required();
|
|
||||||
cobra2redisApp->add_option("channel", channel, "Channel")->required();
|
cobra2redisApp->add_option("channel", channel, "Channel")->required();
|
||||||
cobra2redisApp->add_option("--pidfile", pidfile, "Pid file");
|
cobra2redisApp->add_option("--pidfile", pidfile, "Pid file");
|
||||||
cobra2redisApp->add_option("--filter", filter, "Stream SQL Filter");
|
cobra2redisApp->add_option("--filter", filter, "Stream SQL Filter");
|
||||||
@ -299,6 +288,7 @@ int main(int argc, char** argv)
|
|||||||
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);
|
addTLSOptions(cobra2redisApp);
|
||||||
|
addCobraConfig(cobra2redisApp);
|
||||||
|
|
||||||
CLI::App* snakeApp = app.add_subcommand("snake", "Snake server");
|
CLI::App* snakeApp = app.add_subcommand("snake", "Snake server");
|
||||||
snakeApp->add_option("--port", port, "Connection url");
|
snakeApp->add_option("--port", port, "Connection url");
|
||||||
@ -336,8 +326,12 @@ int main(int argc, char** argv)
|
|||||||
addTLSOptions(proxyServerApp);
|
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")->required()->check(CLI::ExistingPath);
|
minidumpApp->add_option("--minidump", minidump, "Minidump path")
|
||||||
minidumpApp->add_option("--metadata", metadata, "Metadata path")->required()->check(CLI::ExistingPath);
|
->required()
|
||||||
|
->check(CLI::ExistingPath);
|
||||||
|
minidumpApp->add_option("--metadata", metadata, "Metadata path")
|
||||||
|
->required()
|
||||||
|
->check(CLI::ExistingPath);
|
||||||
minidumpApp->add_option("--project", project, "Sentry Project")->required();
|
minidumpApp->add_option("--project", project, "Sentry Project")->required();
|
||||||
minidumpApp->add_option("--key", key, "Sentry Key")->required();
|
minidumpApp->add_option("--key", key, "Sentry Key")->required();
|
||||||
minidumpApp->add_flag("-v", verbose, "Verbose");
|
minidumpApp->add_flag("-v", verbose, "Verbose");
|
||||||
@ -363,6 +357,10 @@ int main(int argc, char** argv)
|
|||||||
tlsOptions.caFile = "NONE";
|
tlsOptions.caFile = "NONE";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cobra config
|
||||||
|
cobraConfig.webSocketPerMessageDeflateOptions = ix::WebSocketPerMessageDeflateOptions(true);
|
||||||
|
cobraConfig.socketTLSOptions = tlsOptions;
|
||||||
|
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
if (app.got_subcommand("transfer"))
|
if (app.got_subcommand("transfer"))
|
||||||
{
|
{
|
||||||
@ -394,7 +392,8 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else if (app.got_subcommand("echo_server"))
|
else if (app.got_subcommand("echo_server"))
|
||||||
{
|
{
|
||||||
ret = ix::ws_echo_server_main(port, greetings, hostname, tlsOptions, ipv6);
|
ret = ix::ws_echo_server_main(
|
||||||
|
port, greetings, hostname, tlsOptions, ipv6, disablePerMessageDeflate);
|
||||||
}
|
}
|
||||||
else if (app.got_subcommand("broadcast_server"))
|
else if (app.got_subcommand("broadcast_server"))
|
||||||
{
|
{
|
||||||
@ -430,60 +429,40 @@ 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(cobraConfig, channel, filter, quiet, fluentd);
|
||||||
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(
|
ret = ix::ws_cobra_publish_main(cobraConfig, channel, path);
|
||||||
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(cobraConfig, 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"))
|
||||||
{
|
{
|
||||||
ret = ix::ws_cobra_to_statsd_main(appkey,
|
ret = ix::cobra_to_statsd_bot(
|
||||||
endpoint,
|
cobraConfig, channel, filter, hostname, statsdPort, prefix, fields, verbose);
|
||||||
rolename,
|
|
||||||
rolesecret,
|
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
hostname,
|
|
||||||
statsdPort,
|
|
||||||
prefix,
|
|
||||||
fields,
|
|
||||||
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(appkey,
|
bool enableHeartbeat = true;
|
||||||
endpoint,
|
int runtime = -1;
|
||||||
rolename,
|
ix::SentryClient sentryClient(dsn);
|
||||||
rolesecret,
|
|
||||||
channel,
|
ret = ix::cobra_to_sentry_bot(cobraConfig,
|
||||||
filter,
|
channel,
|
||||||
dsn,
|
filter,
|
||||||
verbose,
|
sentryClient,
|
||||||
strict,
|
verbose,
|
||||||
jobs,
|
strict,
|
||||||
maxQueueSize,
|
maxQueueSize,
|
||||||
tlsOptions);
|
enableHeartbeat,
|
||||||
|
runtime);
|
||||||
}
|
}
|
||||||
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(appkey,
|
ret = ix::ws_cobra_metrics_to_redis(cobraConfig, channel, filter, hostname, redisPort);
|
||||||
endpoint,
|
|
||||||
rolename,
|
|
||||||
rolesecret,
|
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
hostname,
|
|
||||||
redisPort,
|
|
||||||
tlsOptions);
|
|
||||||
}
|
}
|
||||||
else if (app.got_subcommand("snake"))
|
else if (app.got_subcommand("snake"))
|
||||||
{
|
{
|
||||||
|
61
ws/ws.h
61
ws/ws.h
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ixcobra/IXCobraConfig.h>
|
||||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -30,7 +31,8 @@ namespace ix
|
|||||||
bool greetings,
|
bool greetings,
|
||||||
const std::string& hostname,
|
const std::string& hostname,
|
||||||
const ix::SocketTLSOptions& tlsOptions,
|
const ix::SocketTLSOptions& tlsOptions,
|
||||||
bool ipv6);
|
bool ipv6,
|
||||||
|
bool disablePerMessageDeflate);
|
||||||
|
|
||||||
int ws_broadcast_server_main(int port,
|
int ws_broadcast_server_main(int port,
|
||||||
const std::string& hostname,
|
const std::string& hostname,
|
||||||
@ -73,67 +75,26 @@ namespace ix
|
|||||||
const std::string& channel,
|
const std::string& channel,
|
||||||
bool verbose);
|
bool verbose);
|
||||||
|
|
||||||
int ws_cobra_subscribe_main(const std::string& appkey,
|
int ws_cobra_subscribe_main(const ix::CobraConfig& config,
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
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);
|
bool fluentd);
|
||||||
|
|
||||||
int ws_cobra_publish_main(const std::string& appkey,
|
int ws_cobra_publish_main(const ix::CobraConfig& appkey,
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
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 ix::CobraConfig& config,
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
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_metrics_to_redis(const ix::CobraConfig& config,
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
const std::string& rolesecret,
|
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& host,
|
|
||||||
int port,
|
|
||||||
const std::string& prefix,
|
|
||||||
const std::string& fields,
|
|
||||||
bool verbose,
|
|
||||||
const ix::SocketTLSOptions& tlsOptions);
|
|
||||||
|
|
||||||
int ws_cobra_to_sentry_main(const std::string& appkey,
|
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
const std::string& rolesecret,
|
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& dsn,
|
|
||||||
bool verbose,
|
|
||||||
bool strict,
|
|
||||||
int jobs,
|
|
||||||
size_t maxQueueSize,
|
|
||||||
const ix::SocketTLSOptions& tlsOptions);
|
|
||||||
|
|
||||||
int ws_cobra_metrics_to_redis(const std::string& appkey,
|
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
const std::string& rolesecret,
|
|
||||||
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,
|
||||||
|
@ -15,14 +15,10 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int ws_cobra_metrics_publish_main(const std::string& appkey,
|
int ws_cobra_metrics_publish_main(const ix::CobraConfig& config,
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
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);
|
||||||
@ -36,8 +32,13 @@ namespace ix
|
|||||||
cobraMetricsPublisher.enable(true);
|
cobraMetricsPublisher.enable(true);
|
||||||
|
|
||||||
bool enablePerMessageDeflate = true;
|
bool enablePerMessageDeflate = true;
|
||||||
cobraMetricsPublisher.configure(
|
cobraMetricsPublisher.configure(config.appkey,
|
||||||
appkey, endpoint, channel, rolename, rolesecret, enablePerMessageDeflate, tlsOptions);
|
config.endpoint,
|
||||||
|
channel,
|
||||||
|
config.rolename,
|
||||||
|
config.rolesecret,
|
||||||
|
enablePerMessageDeflate,
|
||||||
|
config.socketTLSOptions);
|
||||||
|
|
||||||
while (!cobraMetricsPublisher.isAuthenticated())
|
while (!cobraMetricsPublisher.isAuthenticated())
|
||||||
;
|
;
|
||||||
|
@ -17,23 +17,14 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int ws_cobra_metrics_to_redis(const std::string& appkey,
|
int ws_cobra_metrics_to_redis(const ix::CobraConfig& config,
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
const std::string& rolesecret,
|
|
||||||
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(appkey,
|
conn.configure(config);
|
||||||
endpoint,
|
|
||||||
rolename,
|
|
||||||
rolesecret,
|
|
||||||
ix::WebSocketPerMessageDeflateOptions(true),
|
|
||||||
tlsOptions);
|
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
// Display incoming messages
|
// Display incoming messages
|
||||||
@ -135,7 +126,7 @@ namespace ix
|
|||||||
channel,
|
channel,
|
||||||
filter,
|
filter,
|
||||||
[&msgPerSeconds, &msgCount, &conditionVariableMutex, &condition, &queue](
|
[&msgPerSeconds, &msgCount, &conditionVariableMutex, &condition, &queue](
|
||||||
const Json::Value& msg) {
|
const Json::Value& msg, const std::string& /*position*/) {
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(conditionVariableMutex);
|
std::unique_lock<std::mutex> lock(conditionVariableMutex);
|
||||||
queue.push(msg);
|
queue.push(msg);
|
||||||
|
@ -16,13 +16,9 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int ws_cobra_publish_main(const std::string& appkey,
|
int ws_cobra_publish_main(const ix::CobraConfig& config,
|
||||||
const std::string& endpoint,
|
|
||||||
const std::string& rolename,
|
|
||||||
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,12 +32,7 @@ namespace ix
|
|||||||
}
|
}
|
||||||
|
|
||||||
ix::CobraConnection conn;
|
ix::CobraConnection conn;
|
||||||
conn.configure(appkey,
|
conn.configure(config);
|
||||||
endpoint,
|
|
||||||
rolename,
|
|
||||||
rolesecret,
|
|
||||||
ix::WebSocketPerMessageDeflateOptions(true),
|
|
||||||
tlsOptions);
|
|
||||||
|
|
||||||
// Display incoming messages
|
// Display incoming messages
|
||||||
std::atomic<bool> authenticated(false);
|
std::atomic<bool> authenticated(false);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
#include <ixcobra/IXCobraConnection.h>
|
#include <ixcobra/IXCobraConnection.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -13,22 +14,38 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int ws_cobra_subscribe_main(const std::string& appkey,
|
void writeToStdout(bool fluentd,
|
||||||
const std::string& endpoint,
|
Json::FastWriter& jsonWriter,
|
||||||
const std::string& rolename,
|
const Json::Value& msg,
|
||||||
const std::string& rolesecret,
|
const std::string& position)
|
||||||
|
{
|
||||||
|
Json::Value enveloppe;
|
||||||
|
if (fluentd)
|
||||||
|
{
|
||||||
|
enveloppe["producer"] = "cobra";
|
||||||
|
enveloppe["consumer"] = "fluentd";
|
||||||
|
|
||||||
|
Json::Value msgWithPosition(msg);
|
||||||
|
msgWithPosition["position"] = position;
|
||||||
|
enveloppe["message"] = msgWithPosition;
|
||||||
|
|
||||||
|
std::cout << jsonWriter.write(enveloppe);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enveloppe = msg;
|
||||||
|
std::cout << position << " " << jsonWriter.write(enveloppe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ws_cobra_subscribe_main(const ix::CobraConfig& config,
|
||||||
const std::string& channel,
|
const std::string& channel,
|
||||||
const std::string& filter,
|
const std::string& filter,
|
||||||
bool quiet,
|
bool quiet,
|
||||||
const ix::SocketTLSOptions& tlsOptions)
|
bool fluentd)
|
||||||
{
|
{
|
||||||
ix::CobraConnection conn;
|
ix::CobraConnection conn;
|
||||||
conn.configure(appkey,
|
conn.configure(config);
|
||||||
endpoint,
|
|
||||||
rolename,
|
|
||||||
rolesecret,
|
|
||||||
ix::WebSocketPerMessageDeflateOptions(true),
|
|
||||||
tlsOptions);
|
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
Json::FastWriter jsonWriter;
|
Json::FastWriter jsonWriter;
|
||||||
@ -51,7 +68,7 @@ namespace ix
|
|||||||
std::thread t(timer);
|
std::thread t(timer);
|
||||||
|
|
||||||
conn.setEventCallback(
|
conn.setEventCallback(
|
||||||
[&conn, &channel, &jsonWriter, &filter, &msgCount, &msgPerSeconds, &quiet](
|
[&conn, &channel, &jsonWriter, &filter, &msgCount, &msgPerSeconds, &quiet, &fluentd](
|
||||||
ix::CobraConnectionEventType eventType,
|
ix::CobraConnectionEventType eventType,
|
||||||
const std::string& errMsg,
|
const std::string& errMsg,
|
||||||
const ix::WebSocketHttpHeaders& headers,
|
const ix::WebSocketHttpHeaders& headers,
|
||||||
@ -69,18 +86,18 @@ namespace ix
|
|||||||
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
||||||
{
|
{
|
||||||
spdlog::info("Subscriber authenticated");
|
spdlog::info("Subscriber authenticated");
|
||||||
conn.subscribe(
|
conn.subscribe(channel,
|
||||||
channel,
|
filter,
|
||||||
filter,
|
[&jsonWriter, &quiet, &msgPerSeconds, &msgCount, &fluentd](
|
||||||
[&jsonWriter, &quiet, &msgPerSeconds, &msgCount](const Json::Value& msg) {
|
const Json::Value& msg, const std::string& position) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
{
|
{
|
||||||
spdlog::info(jsonWriter.write(msg));
|
writeToStdout(fluentd, jsonWriter, msg, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
msgPerSeconds++;
|
msgPerSeconds++;
|
||||||
msgCount++;
|
msgCount++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,15 @@ namespace ix
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
int getSentBytes()
|
||||||
|
{
|
||||||
|
return _sentBytes;
|
||||||
|
}
|
||||||
|
int getReceivedBytes()
|
||||||
|
{
|
||||||
|
return _receivedBytes;
|
||||||
|
}
|
||||||
|
|
||||||
void sendMessage(const std::string& text);
|
void sendMessage(const std::string& text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -38,6 +47,8 @@ namespace ix
|
|||||||
ix::WebSocket _webSocket;
|
ix::WebSocket _webSocket;
|
||||||
bool _disablePerMessageDeflate;
|
bool _disablePerMessageDeflate;
|
||||||
bool _binaryMode;
|
bool _binaryMode;
|
||||||
|
std::atomic<int> _receivedBytes;
|
||||||
|
std::atomic<int> _sentBytes;
|
||||||
|
|
||||||
void log(const std::string& msg);
|
void log(const std::string& msg);
|
||||||
WebSocketHttpHeaders parseHeaders(const std::string& data);
|
WebSocketHttpHeaders parseHeaders(const std::string& data);
|
||||||
@ -54,6 +65,8 @@ namespace ix
|
|||||||
: _url(url)
|
: _url(url)
|
||||||
, _disablePerMessageDeflate(disablePerMessageDeflate)
|
, _disablePerMessageDeflate(disablePerMessageDeflate)
|
||||||
, _binaryMode(binaryMode)
|
, _binaryMode(binaryMode)
|
||||||
|
, _receivedBytes(0)
|
||||||
|
, _sentBytes(0)
|
||||||
{
|
{
|
||||||
if (disableAutomaticReconnection)
|
if (disableAutomaticReconnection)
|
||||||
{
|
{
|
||||||
@ -68,6 +81,17 @@ namespace ix
|
|||||||
{
|
{
|
||||||
_webSocket.addSubProtocol(subprotocol);
|
_webSocket.addSubProtocol(subprotocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebSocket::setTrafficTrackerCallback([this](int size, bool incoming) {
|
||||||
|
if (incoming)
|
||||||
|
{
|
||||||
|
_receivedBytes += size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sentBytes += size;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketConnect::log(const std::string& msg)
|
void WebSocketConnect::log(const std::string& msg)
|
||||||
@ -246,6 +270,9 @@ namespace ix
|
|||||||
spdlog::info("");
|
spdlog::info("");
|
||||||
webSocketChat.stop();
|
webSocketChat.stop();
|
||||||
|
|
||||||
|
spdlog::info("Received {} bytes", webSocketChat.getReceivedBytes());
|
||||||
|
spdlog::info("Sent {} bytes", webSocketChat.getSentBytes());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <ixwebsocket/IXDNSLookup.h>
|
||||||
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <ixwebsocket/IXNetSystem.h>
|
|
||||||
#include <ixwebsocket/IXDNSLookup.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ixwebsocket/IXWebSocketServer.h>
|
|
||||||
#include <ixwebsocket/IXNetSystem.h>
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketServer.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@ -15,7 +15,8 @@ namespace ix
|
|||||||
bool greetings,
|
bool greetings,
|
||||||
const std::string& hostname,
|
const std::string& hostname,
|
||||||
const ix::SocketTLSOptions& tlsOptions,
|
const ix::SocketTLSOptions& tlsOptions,
|
||||||
bool ipv6)
|
bool ipv6,
|
||||||
|
bool disablePerMessageDeflate)
|
||||||
{
|
{
|
||||||
spdlog::info("Listening on {}:{}", hostname, port);
|
spdlog::info("Listening on {}:{}", hostname, port);
|
||||||
|
|
||||||
@ -28,6 +29,12 @@ namespace ix
|
|||||||
|
|
||||||
server.setTLSOptions(tlsOptions);
|
server.setTLSOptions(tlsOptions);
|
||||||
|
|
||||||
|
if (disablePerMessageDeflate)
|
||||||
|
{
|
||||||
|
spdlog::info("Disable per message deflate");
|
||||||
|
server.disablePerMessageDeflate();
|
||||||
|
}
|
||||||
|
|
||||||
server.setOnConnectionCallback(
|
server.setOnConnectionCallback(
|
||||||
[greetings](std::shared_ptr<ix::WebSocket> webSocket,
|
[greetings](std::shared_ptr<ix::WebSocket> webSocket,
|
||||||
std::shared_ptr<ConnectionState> connectionState) {
|
std::shared_ptr<ConnectionState> connectionState) {
|
||||||
|
Reference in New Issue
Block a user