Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
16eb269e1e | |||
2319dec278 | |||
f1be48aff1 | |||
93fd44813a | |||
54d4d81bf4 | |||
ea207d8199 | |||
e8287e91e4 | |||
c0505ac7fb | |||
1af39bf0eb | |||
2e904801a0 | |||
cc72494b63 | |||
fa9a4660c6 | |||
4773af8f2f | |||
c1403df74a | |||
3912e22b28 | |||
c9d5b4a581 | |||
9f8643032d | |||
0772ef7ef5 | |||
c030a62c8b | |||
931530b101 | |||
6c205b983e | |||
a65b334961 | |||
2de8aafcbc | |||
f075f586e1 | |||
93cb898989 | |||
e4da62547b | |||
2b4c06e6d2 | |||
7337ed34a6 | |||
15355188d5 | |||
8760c87635 | |||
2786631e3b | |||
1b30061a4d | |||
af003fc79b | |||
4f17cd5e74 | |||
b04764489c | |||
fc4a4bfb7c | |||
9e54fd5f1a | |||
1096f62196 | |||
b34d9f6a06 | |||
b21e2506bf | |||
303f99a432 | |||
a42ccea8dd | |||
beb26bc096 | |||
b45980f0f6 |
17
.github/workflows/ccpp.yml
vendored
17
.github/workflows/ccpp.yml
vendored
@ -9,8 +9,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: make test
|
- name: make test_make
|
||||||
run: make test
|
run: make test_make
|
||||||
|
|
||||||
mac_tsan_sectransport:
|
mac_tsan_sectransport:
|
||||||
runs-on: macOS-latest
|
runs-on: macOS-latest
|
||||||
@ -37,7 +37,7 @@ jobs:
|
|||||||
- name: make test
|
- name: make test
|
||||||
run: make test_tsan_mbedtls
|
run: make test_tsan_mbedtls
|
||||||
|
|
||||||
windows_openssl:
|
windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
@ -52,6 +52,17 @@ jobs:
|
|||||||
#- run: ../build/test/ixwebsocket_unittest.exe
|
#- run: ../build/test/ixwebsocket_unittest.exe
|
||||||
# working-directory: test
|
# working-directory: test
|
||||||
|
|
||||||
|
uwp:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||||
|
- run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0" -DCMAKE_CXX_COMPILER=cl.exe -DUSE_TEST=1 ..
|
||||||
|
- run: cmake --build build
|
||||||
|
|
||||||
#
|
#
|
||||||
# Windows with OpenSSL is working but disabled as it takes 13 minutes (10 for openssl) to build with vcpkg
|
# Windows with OpenSSL is working but disabled as it takes 13 minutes (10 for openssl) to build with vcpkg
|
||||||
#
|
#
|
||||||
|
@ -12,6 +12,10 @@ set (CMAKE_CXX_STANDARD 14)
|
|||||||
set (CXX_STANDARD_REQUIRED ON)
|
set (CXX_STANDARD_REQUIRED ON)
|
||||||
set (CMAKE_CXX_EXTENSIONS OFF)
|
set (CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
|
||||||
endif()
|
endif()
|
||||||
@ -119,6 +123,11 @@ if (USE_TLS)
|
|||||||
if (NOT USE_MBED_TLS AND NOT USE_OPEN_SSL) # unless we want something else
|
if (NOT USE_MBED_TLS AND NOT USE_OPEN_SSL) # unless we want something else
|
||||||
set(USE_SECURE_TRANSPORT ON)
|
set(USE_SECURE_TRANSPORT ON)
|
||||||
endif()
|
endif()
|
||||||
|
# default to mbedtls on windows if nothing is configured
|
||||||
|
elseif (WIN32)
|
||||||
|
if (NOT USE_OPEN_SSL) # unless we want something else
|
||||||
|
set(USE_MBED_TLS ON)
|
||||||
|
endif()
|
||||||
else() # default to OpenSSL on all other platforms
|
else() # default to OpenSSL on all other platforms
|
||||||
if (NOT USE_MBED_TLS) # Unless mbedtls is requested
|
if (NOT USE_MBED_TLS) # Unless mbedtls is requested
|
||||||
set(USE_OPEN_SSL ON)
|
set(USE_OPEN_SSL ON)
|
||||||
@ -165,6 +174,10 @@ if (USE_TLS)
|
|||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /usr/local/opt/openssl/lib)
|
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /usr/local/opt/openssl/lib)
|
||||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr/local/opt/openssl/include)
|
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr/local/opt/openssl/include)
|
||||||
|
|
||||||
|
# This is for MacPort OpenSSL 1.0
|
||||||
|
# set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /opt/local/lib/openssl-1.0)
|
||||||
|
# set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /opt/local/include/openssl-1.0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# This OPENSSL_FOUND check is to help find a cmake manually configured OpenSSL
|
# This OPENSSL_FOUND check is to help find a cmake manually configured OpenSSL
|
||||||
|
@ -45,3 +45,7 @@ IXWebSocket client code is autobahn compliant beginning with the 6.0.0 version.
|
|||||||
If your company or project is using this library, feel free to open an issue or PR to amend this list.
|
If your company or project is using this library, feel free to open an issue or PR to amend this list.
|
||||||
|
|
||||||
- [Machine Zone](https://www.mz.com)
|
- [Machine Zone](https://www.mz.com)
|
||||||
|
- [Tokio](https://gitlab.com/HCInk/tokio), a discord library focused on audio playback with node bindings.
|
||||||
|
- [libDiscordBot](https://github.com/tostc/libDiscordBot/tree/master), a work in progress discord library
|
||||||
|
- [gwebsocket](https://github.com/norrbotten/gwebsocket), a websocket (lua) module for Garry's Mod
|
||||||
|
- [DisCPP](https://github.com/DisCPP/DisCPP), a simple but feature rich Discord API wrapper
|
||||||
|
@ -2,7 +2,7 @@ FROM alpine:3.11 as build
|
|||||||
|
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
gcc g++ musl-dev linux-headers \
|
gcc g++ musl-dev linux-headers \
|
||||||
cmake mbedtls-dev make zlib-dev
|
cmake mbedtls-dev make zlib-dev ninja
|
||||||
|
|
||||||
RUN addgroup -S app && \
|
RUN addgroup -S app && \
|
||||||
adduser -S -G app app && \
|
adduser -S -G app app && \
|
||||||
|
@ -1,6 +1,54 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All changes to this project will be documented in this file.
|
All changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [9.6.4] - 2020-05-20
|
||||||
|
|
||||||
|
(compiler fix) support clang 5 and earlier (contributed by @LunarWatcher)
|
||||||
|
|
||||||
|
## [9.6.3] - 2020-05-18
|
||||||
|
|
||||||
|
(cmake) revert CMake changes to fix #203 and be able to use an external OpenSSL
|
||||||
|
|
||||||
|
## [9.6.2] - 2020-05-17
|
||||||
|
|
||||||
|
(cmake) make install cmake files optional to not conflict with vcpkg
|
||||||
|
|
||||||
|
## [9.6.1] - 2020-05-17
|
||||||
|
|
||||||
|
(windows + tls) mbedtls is the default windows tls backend + add ability to load system certificates with mbdetls on windows
|
||||||
|
|
||||||
|
## [9.6.0] - 2020-05-12
|
||||||
|
|
||||||
|
(ixbots) add options to limit how many messages per minute should be processed
|
||||||
|
|
||||||
|
## [9.5.9] - 2020-05-12
|
||||||
|
|
||||||
|
(ixbots) add new class to configure a bot to simplify passing options around
|
||||||
|
|
||||||
|
## [9.5.8] - 2020-05-08
|
||||||
|
|
||||||
|
(openssl tls) (openssl < 1.1) logic inversion - crypto locking callback are not registered properly
|
||||||
|
|
||||||
|
## [9.5.7] - 2020-05-08
|
||||||
|
|
||||||
|
(cmake) default TLS back to mbedtls on Windows Universal Platform
|
||||||
|
|
||||||
|
## [9.5.6] - 2020-05-06
|
||||||
|
|
||||||
|
(cobra bots) add a --heartbeat_timeout option to specify when the bot should terminate because no events are received
|
||||||
|
|
||||||
|
## [9.5.5] - 2020-05-06
|
||||||
|
|
||||||
|
(openssl tls) when OpenSSL is older than 1.1, register the crypto locking callback to be thread safe. Should fix lots of CI failures
|
||||||
|
|
||||||
|
## [9.5.4] - 2020-05-04
|
||||||
|
|
||||||
|
(cobra bots) do not use a queue to store messages pending processing, let the bot handle queuing
|
||||||
|
|
||||||
|
## [9.5.3] - 2020-04-29
|
||||||
|
|
||||||
|
(http client) better current request cancellation support when the HttpClient destructor is invoked (see #189)
|
||||||
|
|
||||||
## [9.5.2] - 2020-04-27
|
## [9.5.2] - 2020-04-27
|
||||||
|
|
||||||
(cmake) fix cmake broken tls option parsing
|
(cmake) fix cmake broken tls option parsing
|
||||||
|
@ -42,6 +42,19 @@ It is possible to get IXWebSocket through Microsoft [vcpkg](https://github.com/m
|
|||||||
```
|
```
|
||||||
vcpkg install ixwebsocket
|
vcpkg install ixwebsocket
|
||||||
```
|
```
|
||||||
|
To use the installed package within a cmake project, use the following:
|
||||||
|
```cmake
|
||||||
|
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") # this is super important in order for cmake to include the vcpkg search/lib paths!
|
||||||
|
|
||||||
|
# find library and its headers
|
||||||
|
find_path(IXWEBSOCKET_INCLUDE_DIR ixwebsocket/IXWebSocket.h)
|
||||||
|
find_library(IXWEBSOCKET_LIBRARY ixwebsocket)
|
||||||
|
# include headers
|
||||||
|
include_directories(${IXWEBSOCKET_INCLUDE_DIR})
|
||||||
|
# ...
|
||||||
|
target_link_libraries(${PROJECT_NAME} ... ${IXWEBSOCKET_LIBRARY}) # Cmake will automatically fail the generation if the lib was not found, i.e is set to NOTFOUNS
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
### Conan
|
### Conan
|
||||||
|
|
||||||
|
@ -8,16 +8,15 @@ set (IXBOTS_SOURCES
|
|||||||
ixbots/IXCobraToSentryBot.cpp
|
ixbots/IXCobraToSentryBot.cpp
|
||||||
ixbots/IXCobraToStatsdBot.cpp
|
ixbots/IXCobraToStatsdBot.cpp
|
||||||
ixbots/IXCobraToStdoutBot.cpp
|
ixbots/IXCobraToStdoutBot.cpp
|
||||||
ixbots/IXQueueManager.cpp
|
|
||||||
ixbots/IXStatsdClient.cpp
|
ixbots/IXStatsdClient.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set (IXBOTS_HEADERS
|
set (IXBOTS_HEADERS
|
||||||
ixbots/IXCobraBot.h
|
ixbots/IXCobraBot.h
|
||||||
|
ixbots/IXCobraBotConfig.h
|
||||||
ixbots/IXCobraToSentryBot.h
|
ixbots/IXCobraToSentryBot.h
|
||||||
ixbots/IXCobraToStatsdBot.h
|
ixbots/IXCobraToStatsdBot.h
|
||||||
ixbots/IXCobraToStdoutBot.h
|
ixbots/IXCobraToStdoutBot.h
|
||||||
ixbots/IXQueueManager.h
|
|
||||||
ixbots/IXStatsdClient.h
|
ixbots/IXStatsdClient.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#include "IXCobraBot.h"
|
#include "IXCobraBot.h"
|
||||||
|
|
||||||
#include "IXQueueManager.h"
|
|
||||||
#include <ixcobra/IXCobraConnection.h>
|
#include <ixcobra/IXCobraConnection.h>
|
||||||
#include <ixcore/utils/IXCoreLogger.h>
|
#include <ixcore/utils/IXCoreLogger.h>
|
||||||
|
|
||||||
@ -18,32 +17,33 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int64_t CobraBot::run(const CobraConfig& config,
|
int64_t CobraBot::run(const CobraBotConfig& botConfig)
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
bool verbose,
|
|
||||||
size_t maxQueueSize,
|
|
||||||
bool useQueue,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime)
|
|
||||||
{
|
{
|
||||||
|
auto config = botConfig.cobraConfig;
|
||||||
|
auto channel = botConfig.channel;
|
||||||
|
auto filter = botConfig.filter;
|
||||||
|
auto position = botConfig.position;
|
||||||
|
auto enableHeartbeat = botConfig.enableHeartbeat;
|
||||||
|
auto heartBeatTimeout = botConfig.heartBeatTimeout;
|
||||||
|
auto runtime = botConfig.runtime;
|
||||||
|
auto maxEventsPerMinute = botConfig.maxEventsPerMinute;
|
||||||
|
auto limitReceivedEvents = botConfig.limitReceivedEvents;
|
||||||
|
|
||||||
ix::CobraConnection conn;
|
ix::CobraConnection conn;
|
||||||
conn.configure(config);
|
conn.configure(config);
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
Json::FastWriter jsonWriter;
|
|
||||||
std::atomic<uint64_t> sentCount(0);
|
std::atomic<uint64_t> sentCount(0);
|
||||||
std::atomic<uint64_t> receivedCount(0);
|
std::atomic<uint64_t> receivedCount(0);
|
||||||
uint64_t sentCountTotal(0);
|
uint64_t sentCountTotal(0);
|
||||||
uint64_t receivedCountTotal(0);
|
uint64_t receivedCountTotal(0);
|
||||||
uint64_t sentCountPerSecs(0);
|
uint64_t sentCountPerSecs(0);
|
||||||
uint64_t receivedCountPerSecs(0);
|
uint64_t receivedCountPerSecs(0);
|
||||||
|
std::atomic<int> receivedCountPerMinutes(0);
|
||||||
std::atomic<bool> stop(false);
|
std::atomic<bool> stop(false);
|
||||||
std::atomic<bool> throttled(false);
|
std::atomic<bool> throttled(false);
|
||||||
std::atomic<bool> fatalCobraError(false);
|
std::atomic<bool> fatalCobraError(false);
|
||||||
|
int minuteCounter = 0;
|
||||||
QueueManager queueManager(maxQueueSize);
|
|
||||||
|
|
||||||
auto timer = [&sentCount,
|
auto timer = [&sentCount,
|
||||||
&receivedCount,
|
&receivedCount,
|
||||||
@ -51,6 +51,8 @@ namespace ix
|
|||||||
&receivedCountTotal,
|
&receivedCountTotal,
|
||||||
&sentCountPerSecs,
|
&sentCountPerSecs,
|
||||||
&receivedCountPerSecs,
|
&receivedCountPerSecs,
|
||||||
|
&receivedCountPerMinutes,
|
||||||
|
&minuteCounter,
|
||||||
&stop] {
|
&stop] {
|
||||||
while (!stop)
|
while (!stop)
|
||||||
{
|
{
|
||||||
@ -71,13 +73,19 @@ namespace ix
|
|||||||
CoreLogger::info(ss.str());
|
CoreLogger::info(ss.str());
|
||||||
|
|
||||||
receivedCountPerSecs = receivedCount - receivedCountTotal;
|
receivedCountPerSecs = receivedCount - receivedCountTotal;
|
||||||
sentCountPerSecs = sentCount - receivedCountTotal;
|
sentCountPerSecs = sentCount - sentCountTotal;
|
||||||
|
|
||||||
receivedCountTotal += receivedCountPerSecs;
|
receivedCountTotal += receivedCountPerSecs;
|
||||||
sentCountTotal += sentCountPerSecs;
|
sentCountTotal += sentCountPerSecs;
|
||||||
|
|
||||||
auto duration = std::chrono::seconds(1);
|
auto duration = std::chrono::seconds(1);
|
||||||
std::this_thread::sleep_for(duration);
|
std::this_thread::sleep_for(duration);
|
||||||
|
|
||||||
|
if (minuteCounter++ == 60)
|
||||||
|
{
|
||||||
|
receivedCountPerMinutes = 0;
|
||||||
|
minuteCounter = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreLogger::info("timer thread done");
|
CoreLogger::info("timer thread done");
|
||||||
@ -85,7 +93,7 @@ namespace ix
|
|||||||
|
|
||||||
std::thread t1(timer);
|
std::thread t1(timer);
|
||||||
|
|
||||||
auto heartbeat = [&sentCount, &receivedCount, &stop, &enableHeartbeat] {
|
auto heartbeat = [&sentCount, &receivedCount, &stop, &enableHeartbeat, &heartBeatTimeout, &fatalCobraError] {
|
||||||
std::string state("na");
|
std::string state("na");
|
||||||
|
|
||||||
if (!enableHeartbeat) return;
|
if (!enableHeartbeat) return;
|
||||||
@ -101,11 +109,12 @@ namespace ix
|
|||||||
if (currentState == state)
|
if (currentState == state)
|
||||||
{
|
{
|
||||||
CoreLogger::error("no messages received or sent for 1 minute, exiting");
|
CoreLogger::error("no messages received or sent for 1 minute, exiting");
|
||||||
exit(1);
|
fatalCobraError = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
state = currentState;
|
state = currentState;
|
||||||
|
|
||||||
auto duration = std::chrono::minutes(1);
|
auto duration = std::chrono::seconds(heartBeatTimeout);
|
||||||
std::this_thread::sleep_for(duration);
|
std::this_thread::sleep_for(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,40 +123,6 @@ namespace ix
|
|||||||
|
|
||||||
std::thread t2(heartbeat);
|
std::thread t2(heartbeat);
|
||||||
|
|
||||||
auto sender =
|
|
||||||
[this, &queueManager, verbose, &sentCount, &stop, &throttled, &fatalCobraError] {
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
auto data = queueManager.pop();
|
|
||||||
Json::Value msg = data.first;
|
|
||||||
std::string position = data.second;
|
|
||||||
|
|
||||||
if (stop) break;
|
|
||||||
if (msg.isNull()) continue;
|
|
||||||
|
|
||||||
if (_onBotMessageCallback &&
|
|
||||||
_onBotMessageCallback(msg, position, verbose, throttled, fatalCobraError))
|
|
||||||
{
|
|
||||||
// That might be too noisy
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
CoreLogger::info("cobra bot: sending succesfull");
|
|
||||||
}
|
|
||||||
++sentCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CoreLogger::error("cobra bot: error sending");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stop) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreLogger::info("sender thread done");
|
|
||||||
};
|
|
||||||
|
|
||||||
std::thread t3(sender);
|
|
||||||
|
|
||||||
std::string subscriptionPosition(position);
|
std::string subscriptionPosition(position);
|
||||||
|
|
||||||
conn.setEventCallback([this,
|
conn.setEventCallback([this,
|
||||||
@ -155,13 +130,12 @@ namespace ix
|
|||||||
&channel,
|
&channel,
|
||||||
&filter,
|
&filter,
|
||||||
&subscriptionPosition,
|
&subscriptionPosition,
|
||||||
&jsonWriter,
|
|
||||||
verbose,
|
|
||||||
&throttled,
|
&throttled,
|
||||||
&receivedCount,
|
&receivedCount,
|
||||||
|
&receivedCountPerMinutes,
|
||||||
|
maxEventsPerMinute,
|
||||||
|
limitReceivedEvents,
|
||||||
&fatalCobraError,
|
&fatalCobraError,
|
||||||
&useQueue,
|
|
||||||
&queueManager,
|
|
||||||
&sentCount](const CobraEventPtr& event) {
|
&sentCount](const CobraEventPtr& event) {
|
||||||
if (event->type == ix::CobraEventType::Open)
|
if (event->type == ix::CobraEventType::Open)
|
||||||
{
|
{
|
||||||
@ -182,58 +156,34 @@ namespace ix
|
|||||||
CoreLogger::info("Subscribing to " + channel);
|
CoreLogger::info("Subscribing to " + channel);
|
||||||
CoreLogger::info("Subscribing at position " + subscriptionPosition);
|
CoreLogger::info("Subscribing at position " + subscriptionPosition);
|
||||||
CoreLogger::info("Subscribing with filter " + filter);
|
CoreLogger::info("Subscribing with filter " + filter);
|
||||||
conn.subscribe(channel,
|
conn.subscribe(channel, filter, subscriptionPosition,
|
||||||
filter,
|
[&sentCount, &receivedCountPerMinutes,
|
||||||
subscriptionPosition,
|
maxEventsPerMinute, limitReceivedEvents,
|
||||||
[this,
|
&throttled, &receivedCount,
|
||||||
&jsonWriter,
|
&subscriptionPosition, &fatalCobraError,
|
||||||
verbose,
|
this](const Json::Value& msg, const std::string& position) {
|
||||||
&throttled,
|
subscriptionPosition = position;
|
||||||
&receivedCount,
|
++receivedCount;
|
||||||
&queueManager,
|
|
||||||
&useQueue,
|
|
||||||
&subscriptionPosition,
|
|
||||||
&fatalCobraError,
|
|
||||||
&sentCount](const Json::Value& msg, const std::string& position) {
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
CoreLogger::info("Subscriber received message "
|
|
||||||
+ position + " -> " + jsonWriter.write(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
subscriptionPosition = position;
|
++receivedCountPerMinutes;
|
||||||
|
if (limitReceivedEvents)
|
||||||
|
{
|
||||||
|
if (receivedCountPerMinutes > maxEventsPerMinute)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we cannot send to sentry fast enough, drop the message
|
// If we cannot send to sentry fast enough, drop the message
|
||||||
if (throttled)
|
if (throttled)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++receivedCount;
|
_onBotMessageCallback(
|
||||||
|
msg, position, throttled,
|
||||||
if (useQueue)
|
fatalCobraError, sentCount);
|
||||||
{
|
});
|
||||||
queueManager.add(msg, position);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_onBotMessageCallback &&
|
|
||||||
_onBotMessageCallback(
|
|
||||||
msg, position, verbose, throttled, fatalCobraError))
|
|
||||||
{
|
|
||||||
// That might be too noisy
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
CoreLogger::info("cobra bot: sending succesfull");
|
|
||||||
}
|
|
||||||
++sentCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CoreLogger::error("cobra bot: error sending");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else if (event->type == ix::CobraEventType::Subscribed)
|
else if (event->type == ix::CobraEventType::Subscribed)
|
||||||
{
|
{
|
||||||
@ -308,9 +258,6 @@ namespace ix
|
|||||||
// heartbeat thread
|
// heartbeat thread
|
||||||
if (t2.joinable()) t2.join();
|
if (t2.joinable()) t2.join();
|
||||||
|
|
||||||
// sentry sender thread
|
|
||||||
t3.join();
|
|
||||||
|
|
||||||
return fatalCobraError ? -1 : (int64_t) sentCount;
|
return fatalCobraError ? -1 : (int64_t) sentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,33 +8,24 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <ixcobra/IXCobraConfig.h>
|
#include "IXCobraBotConfig.h"
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
using OnBotMessageCallback = std::function<bool(const Json::Value&,
|
using OnBotMessageCallback = std::function<void(const Json::Value&,
|
||||||
const std::string&,
|
const std::string&,
|
||||||
const bool verbose,
|
|
||||||
std::atomic<bool>&,
|
std::atomic<bool>&,
|
||||||
std::atomic<bool>&)>;
|
std::atomic<bool>&,
|
||||||
|
std::atomic<uint64_t>&)>;
|
||||||
|
|
||||||
class CobraBot
|
class CobraBot
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CobraBot() = default;
|
CobraBot() = default;
|
||||||
|
|
||||||
int64_t run(const CobraConfig& config,
|
int64_t run(const CobraBotConfig& botConfig);
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
bool verbose,
|
|
||||||
size_t maxQueueSize,
|
|
||||||
bool useQueue,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime);
|
|
||||||
|
|
||||||
void setOnBotMessageCallback(const OnBotMessageCallback& callback);
|
void setOnBotMessageCallback(const OnBotMessageCallback& callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
31
ixbots/ixbots/IXCobraBotConfig.h
Normal file
31
ixbots/ixbots/IXCobraBotConfig.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* IXCobraBotConfig.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <limits>
|
||||||
|
#include <ixcobra/IXCobraConfig.h>
|
||||||
|
|
||||||
|
#ifdef max
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
struct CobraBotConfig
|
||||||
|
{
|
||||||
|
CobraConfig cobraConfig;
|
||||||
|
std::string channel;
|
||||||
|
std::string filter;
|
||||||
|
std::string position = std::string("$");
|
||||||
|
bool enableHeartbeat = true;
|
||||||
|
int heartBeatTimeout = 60;
|
||||||
|
int runtime = -1;
|
||||||
|
int maxEventsPerMinute = std::numeric_limits<int>::max();
|
||||||
|
bool limitReceivedEvents = false;
|
||||||
|
};
|
||||||
|
} // namespace ix
|
@ -7,7 +7,6 @@
|
|||||||
#include "IXCobraToSentryBot.h"
|
#include "IXCobraToSentryBot.h"
|
||||||
|
|
||||||
#include "IXCobraBot.h"
|
#include "IXCobraBot.h"
|
||||||
#include "IXQueueManager.h"
|
|
||||||
#include <ixcobra/IXCobraConnection.h>
|
#include <ixcobra/IXCobraConnection.h>
|
||||||
#include <ixcore/utils/IXCoreLogger.h>
|
#include <ixcore/utils/IXCoreLogger.h>
|
||||||
|
|
||||||
@ -17,101 +16,61 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int64_t cobra_to_sentry_bot(const CobraConfig& config,
|
int64_t cobra_to_sentry_bot(const CobraBotConfig& config,
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
SentryClient& sentryClient,
|
SentryClient& sentryClient,
|
||||||
bool verbose,
|
bool verbose)
|
||||||
size_t maxQueueSize,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime)
|
|
||||||
{
|
{
|
||||||
CobraBot bot;
|
CobraBot bot;
|
||||||
bot.setOnBotMessageCallback([&sentryClient](const Json::Value& msg,
|
bot.setOnBotMessageCallback([&sentryClient, &verbose](const Json::Value& msg,
|
||||||
const std::string& /*position*/,
|
const std::string& /*position*/,
|
||||||
const bool verbose,
|
|
||||||
std::atomic<bool>& throttled,
|
std::atomic<bool>& throttled,
|
||||||
std::atomic<bool> &
|
std::atomic<bool>& /*fatalCobraError*/,
|
||||||
/*fatalCobraError*/) -> bool {
|
std::atomic<uint64_t>& sentCount) -> void {
|
||||||
auto ret = sentryClient.send(msg, verbose);
|
sentryClient.send(msg, verbose,
|
||||||
HttpResponsePtr response = ret.first;
|
[&sentCount, &throttled](const HttpResponsePtr& response) {
|
||||||
|
if (!response)
|
||||||
if (!response)
|
|
||||||
{
|
|
||||||
CoreLogger::warn("Null HTTP Response");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
for (auto it : response->headers)
|
|
||||||
{
|
{
|
||||||
CoreLogger::info(it.first + ": " + it.second);
|
CoreLogger::warn("Null HTTP Response");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreLogger::info("Upload size: " + std::to_string(response->uploadSize));
|
if (response->statusCode == 200)
|
||||||
CoreLogger::info("Download size: " + std::to_string(response->downloadSize));
|
|
||||||
|
|
||||||
CoreLogger::info("Status: " + std::to_string(response->statusCode));
|
|
||||||
if (response->errorCode != HttpErrorCode::Ok)
|
|
||||||
{
|
{
|
||||||
CoreLogger::info("error message: " + response->errorMsg);
|
sentCount++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (response->headers["Content-Type"] != "application/octet-stream")
|
|
||||||
{
|
{
|
||||||
CoreLogger::info("payload: " + response->payload);
|
CoreLogger::error("Error sending data to sentry: " + std::to_string(response->statusCode));
|
||||||
}
|
CoreLogger::error("Response: " + response->payload);
|
||||||
}
|
|
||||||
|
|
||||||
bool success = response->statusCode == 200;
|
// Error 429 Too Many Requests
|
||||||
|
if (response->statusCode == 429)
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
CoreLogger::error("Error sending data to sentry: " + std::to_string(response->statusCode));
|
|
||||||
CoreLogger::error("Body: " + ret.second);
|
|
||||||
CoreLogger::error("Response: " + response->payload);
|
|
||||||
|
|
||||||
// Error 429 Too Many Requests
|
|
||||||
if (response->statusCode == 429)
|
|
||||||
{
|
|
||||||
auto retryAfter = response->headers["Retry-After"];
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << retryAfter;
|
|
||||||
int seconds;
|
|
||||||
ss >> seconds;
|
|
||||||
|
|
||||||
if (!ss.eof() || ss.fail())
|
|
||||||
{
|
{
|
||||||
seconds = 30;
|
auto retryAfter = response->headers["Retry-After"];
|
||||||
CoreLogger::warn("Error parsing Retry-After header. "
|
std::stringstream ss;
|
||||||
"Using " + retryAfter + " for the sleep duration");
|
ss << retryAfter;
|
||||||
|
int seconds;
|
||||||
|
ss >> seconds;
|
||||||
|
|
||||||
|
if (!ss.eof() || ss.fail())
|
||||||
|
{
|
||||||
|
seconds = 30;
|
||||||
|
CoreLogger::warn("Error parsing Retry-After header. "
|
||||||
|
"Using " + retryAfter + " for the sleep duration");
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreLogger::warn("Error 429 - Too Many Requests. ws will sleep "
|
||||||
|
"and retry after " + retryAfter + " seconds");
|
||||||
|
|
||||||
|
throttled = true;
|
||||||
|
auto duration = std::chrono::seconds(seconds);
|
||||||
|
std::this_thread::sleep_for(duration);
|
||||||
|
throttled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreLogger::warn("Error 429 - Too Many Requests. ws will sleep "
|
|
||||||
"and retry after " + retryAfter + " seconds");
|
|
||||||
|
|
||||||
throttled = true;
|
|
||||||
auto duration = std::chrono::seconds(seconds);
|
|
||||||
std::this_thread::sleep_for(duration);
|
|
||||||
throttled = false;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return success;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
bool useQueue = true;
|
return bot.run(config);
|
||||||
|
|
||||||
return bot.run(config,
|
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
useQueue,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
}
|
}
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -6,19 +6,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ixcobra/IXCobraConfig.h>
|
#include "IXCobraBotConfig.h"
|
||||||
#include <ixsentry/IXSentryClient.h>
|
#include <ixsentry/IXSentryClient.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int64_t cobra_to_sentry_bot(const CobraConfig& config,
|
int64_t cobra_to_sentry_bot(const CobraBotConfig& config,
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
SentryClient& sentryClient,
|
SentryClient& sentryClient,
|
||||||
bool verbose,
|
bool verbose);
|
||||||
size_t maxQueueSize,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime);
|
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "IXCobraToStatsdBot.h"
|
#include "IXCobraToStatsdBot.h"
|
||||||
|
|
||||||
#include "IXCobraBot.h"
|
#include "IXCobraBot.h"
|
||||||
#include "IXQueueManager.h"
|
|
||||||
#include "IXStatsdClient.h"
|
#include "IXStatsdClient.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <ixcobra/IXCobraConnection.h>
|
#include <ixcobra/IXCobraConnection.h>
|
||||||
@ -54,32 +53,22 @@ namespace ix
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t cobra_to_statsd_bot(const ix::CobraConfig& config,
|
int64_t cobra_to_statsd_bot(const ix::CobraBotConfig& config,
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
StatsdClient& statsdClient,
|
StatsdClient& statsdClient,
|
||||||
const std::string& fields,
|
const std::string& fields,
|
||||||
const std::string& gauge,
|
const std::string& gauge,
|
||||||
const std::string& timer,
|
const std::string& timer,
|
||||||
bool verbose,
|
bool verbose)
|
||||||
size_t maxQueueSize,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime)
|
|
||||||
{
|
{
|
||||||
ix::CobraConnection conn;
|
|
||||||
conn.configure(config);
|
|
||||||
conn.connect();
|
|
||||||
|
|
||||||
auto tokens = parseFields(fields);
|
auto tokens = parseFields(fields);
|
||||||
|
|
||||||
CobraBot bot;
|
CobraBot bot;
|
||||||
bot.setOnBotMessageCallback(
|
bot.setOnBotMessageCallback(
|
||||||
[&statsdClient, &tokens, &gauge, &timer](const Json::Value& msg,
|
[&statsdClient, &tokens, &gauge, &timer, &verbose](const Json::Value& msg,
|
||||||
const std::string& /*position*/,
|
const std::string& /*position*/,
|
||||||
const bool verbose,
|
|
||||||
std::atomic<bool>& /*throttled*/,
|
std::atomic<bool>& /*throttled*/,
|
||||||
std::atomic<bool>& fatalCobraError) -> bool {
|
std::atomic<bool>& fatalCobraError,
|
||||||
|
std::atomic<uint64_t>& sentCount) -> void {
|
||||||
std::string id;
|
std::string id;
|
||||||
for (auto&& attr : tokens)
|
for (auto&& attr : tokens)
|
||||||
{
|
{
|
||||||
@ -122,7 +111,7 @@ namespace ix
|
|||||||
{
|
{
|
||||||
CoreLogger::error("Gauge " + gauge + " is not a numeric type");
|
CoreLogger::error("Gauge " + gauge + " is not a numeric type");
|
||||||
fatalCobraError = true;
|
fatalCobraError = true;
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -140,19 +129,9 @@ namespace ix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
sentCount++;
|
||||||
});
|
});
|
||||||
|
|
||||||
bool useQueue = true;
|
return bot.run(config);
|
||||||
|
|
||||||
return bot.run(config,
|
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
useQueue,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
}
|
}
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -7,22 +7,16 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ixbots/IXStatsdClient.h>
|
#include <ixbots/IXStatsdClient.h>
|
||||||
#include <ixcobra/IXCobraConfig.h>
|
#include "IXCobraBotConfig.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int64_t cobra_to_statsd_bot(const ix::CobraConfig& config,
|
int64_t cobra_to_statsd_bot(const ix::CobraBotConfig& config,
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
StatsdClient& statsdClient,
|
StatsdClient& statsdClient,
|
||||||
const std::string& fields,
|
const std::string& fields,
|
||||||
const std::string& gauge,
|
const std::string& gauge,
|
||||||
const std::string& timer,
|
const std::string& timer,
|
||||||
bool verbose,
|
bool verbose);
|
||||||
size_t maxQueueSize,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime);
|
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "IXCobraToStdoutBot.h"
|
#include "IXCobraToStdoutBot.h"
|
||||||
|
|
||||||
#include "IXCobraBot.h"
|
#include "IXCobraBot.h"
|
||||||
#include "IXQueueManager.h"
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -64,16 +63,9 @@ namespace ix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t cobra_to_stdout_bot(const CobraConfig& config,
|
int64_t cobra_to_stdout_bot(const ix::CobraBotConfig& config,
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
bool fluentd,
|
bool fluentd,
|
||||||
bool quiet,
|
bool quiet)
|
||||||
bool verbose,
|
|
||||||
size_t maxQueueSize,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime)
|
|
||||||
{
|
{
|
||||||
CobraBot bot;
|
CobraBot bot;
|
||||||
auto jsonWriter = makeStreamWriter();
|
auto jsonWriter = makeStreamWriter();
|
||||||
@ -81,27 +73,16 @@ namespace ix
|
|||||||
bot.setOnBotMessageCallback(
|
bot.setOnBotMessageCallback(
|
||||||
[&fluentd, &quiet, &jsonWriter](const Json::Value& msg,
|
[&fluentd, &quiet, &jsonWriter](const Json::Value& msg,
|
||||||
const std::string& position,
|
const std::string& position,
|
||||||
const bool /*verbose*/,
|
|
||||||
std::atomic<bool>& /*throttled*/,
|
std::atomic<bool>& /*throttled*/,
|
||||||
std::atomic<bool> &
|
std::atomic<bool>& /*fatalCobraError*/,
|
||||||
/*fatalCobraError*/) -> bool {
|
std::atomic<uint64_t>& sentCount) -> void {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
{
|
{
|
||||||
writeToStdout(fluentd, jsonWriter, msg, position);
|
writeToStdout(fluentd, jsonWriter, msg, position);
|
||||||
}
|
}
|
||||||
return true;
|
sentCount++;
|
||||||
});
|
});
|
||||||
|
|
||||||
bool useQueue = false;
|
return bot.run(config);
|
||||||
|
|
||||||
return bot.run(config,
|
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
useQueue,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
}
|
}
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -6,20 +6,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ixcobra/IXCobraConfig.h>
|
#include "IXCobraBotConfig.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
int64_t cobra_to_stdout_bot(const ix::CobraConfig& config,
|
int64_t cobra_to_stdout_bot(const ix::CobraBotConfig& config,
|
||||||
const std::string& channel,
|
|
||||||
const std::string& filter,
|
|
||||||
const std::string& position,
|
|
||||||
bool fluentd,
|
bool fluentd,
|
||||||
bool quiet,
|
bool quiet);
|
||||||
bool verbose,
|
|
||||||
size_t maxQueueSize,
|
|
||||||
bool enableHeartbeat,
|
|
||||||
int runtime);
|
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* IXQueueManager.cpp
|
|
||||||
* Author: Benjamin Sergeant
|
|
||||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "IXQueueManager.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace ix
|
|
||||||
{
|
|
||||||
std::pair<Json::Value, std::string> QueueManager::pop()
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
|
||||||
|
|
||||||
if (_queues.empty())
|
|
||||||
{
|
|
||||||
Json::Value val;
|
|
||||||
return std::make_pair(val, std::string());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 std::make_pair(val, std::string());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto msg = _queues[game].front();
|
|
||||||
_queues[game].pop();
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QueueManager::add(const Json::Value& msg, const std::string& position)
|
|
||||||
{
|
|
||||||
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(std::make_pair(msg, position));
|
|
||||||
_condition.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace ix
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* IXQueueManager.h
|
|
||||||
* Author: Benjamin Sergeant
|
|
||||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <json/json.h>
|
|
||||||
#include <map>
|
|
||||||
#include <mutex>
|
|
||||||
#include <queue>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
namespace ix
|
|
||||||
{
|
|
||||||
class QueueManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QueueManager(size_t maxQueueSize)
|
|
||||||
: _maxQueueSize(maxQueueSize)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Json::Value, std::string> pop();
|
|
||||||
void add(const Json::Value& msg, const std::string& position);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<std::string, std::queue<std::pair<Json::Value, std::string>>> _queues;
|
|
||||||
std::mutex _mutex;
|
|
||||||
std::condition_variable _condition;
|
|
||||||
size_t _maxQueueSize;
|
|
||||||
};
|
|
||||||
} // namespace ix
|
|
@ -226,20 +226,23 @@ namespace ix
|
|||||||
return _jsonWriter.write(payload);
|
return _jsonWriter.write(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<HttpResponsePtr, std::string> SentryClient::send(const Json::Value& msg, bool verbose)
|
void SentryClient::send(
|
||||||
|
const Json::Value& msg,
|
||||||
|
bool verbose,
|
||||||
|
const OnResponseCallback& onResponseCallback)
|
||||||
{
|
{
|
||||||
auto args = _httpClient->createRequest();
|
auto args = _httpClient->createRequest();
|
||||||
|
args->url = _url;
|
||||||
|
args->verb = HttpClient::kPost;
|
||||||
args->extraHeaders["X-Sentry-Auth"] = SentryClient::computeAuthHeader();
|
args->extraHeaders["X-Sentry-Auth"] = SentryClient::computeAuthHeader();
|
||||||
args->connectTimeout = 60;
|
args->connectTimeout = 60;
|
||||||
args->transferTimeout = 5 * 60;
|
args->transferTimeout = 5 * 60;
|
||||||
args->followRedirects = true;
|
args->followRedirects = true;
|
||||||
args->verbose = verbose;
|
args->verbose = verbose;
|
||||||
args->logger = [](const std::string& msg) { CoreLogger::log(msg.c_str()); };
|
args->logger = [](const std::string& msg) { CoreLogger::log(msg.c_str()); };
|
||||||
|
args->body = computePayload(msg);
|
||||||
|
|
||||||
std::string body = computePayload(msg);
|
_httpClient->performRequest(args, onResponseCallback);
|
||||||
HttpResponsePtr response = _httpClient->post(_url, body, args);
|
|
||||||
|
|
||||||
return std::make_pair(response, body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://sentry.io/api/12345/minidump?sentry_key=abcdefgh");
|
// https://sentry.io/api/12345/minidump?sentry_key=abcdefgh");
|
||||||
|
@ -21,12 +21,9 @@ namespace ix
|
|||||||
SentryClient(const std::string& dsn);
|
SentryClient(const std::string& dsn);
|
||||||
~SentryClient() = default;
|
~SentryClient() = default;
|
||||||
|
|
||||||
std::pair<HttpResponsePtr, std::string> send(const Json::Value& msg, bool verbose);
|
void send(const Json::Value& msg,
|
||||||
|
bool verbose,
|
||||||
Json::Value parseLuaStackTrace(const std::string& stack);
|
const OnResponseCallback& onResponseCallback);
|
||||||
|
|
||||||
// Mostly for testing
|
|
||||||
void setTLSOptions(const SocketTLSOptions& tlsOptions);
|
|
||||||
|
|
||||||
void uploadMinidump(const std::string& sentryMetadata,
|
void uploadMinidump(const std::string& sentryMetadata,
|
||||||
const std::string& minidumpBytes,
|
const std::string& minidumpBytes,
|
||||||
@ -39,6 +36,12 @@ namespace ix
|
|||||||
bool verbose,
|
bool verbose,
|
||||||
const OnResponseCallback& onResponseCallback);
|
const OnResponseCallback& onResponseCallback);
|
||||||
|
|
||||||
|
Json::Value parseLuaStackTrace(const std::string& stack);
|
||||||
|
|
||||||
|
// Mostly for testing
|
||||||
|
void setTLSOptions(const SocketTLSOptions& tlsOptions);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t getTimestamp();
|
int64_t getTimestamp();
|
||||||
std::string computeAuthHeader();
|
std::string computeAuthHeader();
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "IXCancellationRequest.h"
|
#include "IXCancellationRequest.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
@ -13,6 +14,8 @@ namespace ix
|
|||||||
CancellationRequest makeCancellationRequestWithTimeout(
|
CancellationRequest makeCancellationRequestWithTimeout(
|
||||||
int secs, std::atomic<bool>& requestInitCancellation)
|
int secs, std::atomic<bool>& requestInitCancellation)
|
||||||
{
|
{
|
||||||
|
assert(secs > 0);
|
||||||
|
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
auto timeout = std::chrono::seconds(secs);
|
auto timeout = std::chrono::seconds(secs);
|
||||||
|
|
||||||
|
@ -4,6 +4,19 @@
|
|||||||
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// On Windows Universal Platform (uwp), gai_strerror defaults behavior is to returns wchar_t
|
||||||
|
// which is different from all other platforms. We want the non unicode version.
|
||||||
|
// See https://github.com/microsoft/vcpkg/pull/11030
|
||||||
|
// We could do this in IXNetSystem.cpp but so far we are only using gai_strerror in here.
|
||||||
|
//
|
||||||
|
#ifdef _UNICODE
|
||||||
|
#undef _UNICODE
|
||||||
|
#endif
|
||||||
|
#ifdef UNICODE
|
||||||
|
#undef UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "IXDNSLookup.h"
|
#include "IXDNSLookup.h"
|
||||||
|
|
||||||
#include "IXNetSystem.h"
|
#include "IXNetSystem.h"
|
||||||
|
@ -25,10 +25,12 @@ namespace ix
|
|||||||
const std::string HttpClient::kHead = "HEAD";
|
const std::string HttpClient::kHead = "HEAD";
|
||||||
const std::string HttpClient::kDel = "DEL";
|
const std::string HttpClient::kDel = "DEL";
|
||||||
const std::string HttpClient::kPut = "PUT";
|
const std::string HttpClient::kPut = "PUT";
|
||||||
|
const std::string HttpClient::kPatch = "PATCH";
|
||||||
|
|
||||||
HttpClient::HttpClient(bool async)
|
HttpClient::HttpClient(bool async)
|
||||||
: _async(async)
|
: _async(async)
|
||||||
, _stop(false)
|
, _stop(false)
|
||||||
|
, _forceBody(false)
|
||||||
{
|
{
|
||||||
if (!_async) return;
|
if (!_async) return;
|
||||||
|
|
||||||
@ -49,6 +51,11 @@ namespace ix
|
|||||||
_tlsOptions = tlsOptions;
|
_tlsOptions = tlsOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpClient::setForceBody(bool value)
|
||||||
|
{
|
||||||
|
_forceBody = value;
|
||||||
|
}
|
||||||
|
|
||||||
HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, const std::string& verb)
|
HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, const std::string& verb)
|
||||||
{
|
{
|
||||||
auto request = std::make_shared<HttpRequestArgs>();
|
auto request = std::make_shared<HttpRequestArgs>();
|
||||||
@ -192,7 +199,7 @@ namespace ix
|
|||||||
ss << "User-Agent: " << userAgent() << "\r\n";
|
ss << "User-Agent: " << userAgent() << "\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verb == kPost || verb == kPut)
|
if (verb == kPost || verb == kPut || verb == kPatch || _forceBody)
|
||||||
{
|
{
|
||||||
ss << "Content-Length: " << body.size() << "\r\n";
|
ss << "Content-Length: " << body.size() << "\r\n";
|
||||||
|
|
||||||
@ -220,11 +227,10 @@ namespace ix
|
|||||||
|
|
||||||
std::string req(ss.str());
|
std::string req(ss.str());
|
||||||
std::string errMsg;
|
std::string errMsg;
|
||||||
std::atomic<bool> requestInitCancellation(false);
|
|
||||||
|
|
||||||
// Make a cancellation object dealing with connection timeout
|
// Make a cancellation object dealing with connection timeout
|
||||||
auto isCancellationRequested =
|
auto isCancellationRequested =
|
||||||
makeCancellationRequestWithTimeout(args->connectTimeout, requestInitCancellation);
|
makeCancellationRequestWithTimeout(args->connectTimeout, _stop);
|
||||||
|
|
||||||
bool success = _socket->connect(host, port, errMsg, isCancellationRequested);
|
bool success = _socket->connect(host, port, errMsg, isCancellationRequested);
|
||||||
if (!success)
|
if (!success)
|
||||||
@ -242,8 +248,7 @@ namespace ix
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make a new cancellation object dealing with transfer timeout
|
// Make a new cancellation object dealing with transfer timeout
|
||||||
isCancellationRequested =
|
isCancellationRequested = makeCancellationRequestWithTimeout(args->transferTimeout, _stop);
|
||||||
makeCancellationRequestWithTimeout(args->transferTimeout, requestInitCancellation);
|
|
||||||
|
|
||||||
if (args->verbose)
|
if (args->verbose)
|
||||||
{
|
{
|
||||||
@ -562,6 +567,20 @@ namespace ix
|
|||||||
return request(url, kPut, body, args);
|
return request(url, kPut, body, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpResponsePtr HttpClient::patch(const std::string& url,
|
||||||
|
const HttpParameters& httpParameters,
|
||||||
|
HttpRequestArgsPtr args)
|
||||||
|
{
|
||||||
|
return request(url, kPatch, serializeHttpParameters(httpParameters), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponsePtr HttpClient::patch(const std::string& url,
|
||||||
|
const std::string& body,
|
||||||
|
const HttpRequestArgsPtr args)
|
||||||
|
{
|
||||||
|
return request(url, kPatch, body, args);
|
||||||
|
}
|
||||||
|
|
||||||
std::string HttpClient::urlEncode(const std::string& value)
|
std::string HttpClient::urlEncode(const std::string& value)
|
||||||
{
|
{
|
||||||
std::ostringstream escaped;
|
std::ostringstream escaped;
|
||||||
|
@ -46,12 +46,19 @@ namespace ix
|
|||||||
const std::string& body,
|
const std::string& body,
|
||||||
HttpRequestArgsPtr args);
|
HttpRequestArgsPtr args);
|
||||||
|
|
||||||
|
HttpResponsePtr patch(const std::string& url,
|
||||||
|
const HttpParameters& httpParameters,
|
||||||
|
HttpRequestArgsPtr args);
|
||||||
|
HttpResponsePtr patch(const std::string& url,
|
||||||
|
const std::string& body,
|
||||||
|
HttpRequestArgsPtr args);
|
||||||
|
|
||||||
HttpResponsePtr request(const std::string& url,
|
HttpResponsePtr request(const std::string& url,
|
||||||
const std::string& verb,
|
const std::string& verb,
|
||||||
const std::string& body,
|
const std::string& body,
|
||||||
HttpRequestArgsPtr args,
|
HttpRequestArgsPtr args,
|
||||||
int redirects = 0);
|
int redirects = 0);
|
||||||
|
void setForceBody(bool value);
|
||||||
// Async API
|
// Async API
|
||||||
HttpRequestArgsPtr createRequest(const std::string& url = std::string(),
|
HttpRequestArgsPtr createRequest(const std::string& url = std::string(),
|
||||||
const std::string& verb = HttpClient::kGet);
|
const std::string& verb = HttpClient::kGet);
|
||||||
@ -78,6 +85,7 @@ namespace ix
|
|||||||
const static std::string kHead;
|
const static std::string kHead;
|
||||||
const static std::string kDel;
|
const static std::string kDel;
|
||||||
const static std::string kPut;
|
const static std::string kPut;
|
||||||
|
const static std::string kPatch;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void log(const std::string& msg, HttpRequestArgsPtr args);
|
void log(const std::string& msg, HttpRequestArgsPtr args);
|
||||||
@ -86,7 +94,6 @@ namespace ix
|
|||||||
|
|
||||||
// Async API background thread runner
|
// Async API background thread runner
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
// Async API
|
// Async API
|
||||||
bool _async;
|
bool _async;
|
||||||
std::queue<std::pair<HttpRequestArgsPtr, OnResponseCallback>> _queue;
|
std::queue<std::pair<HttpRequestArgsPtr, OnResponseCallback>> _queue;
|
||||||
@ -99,5 +106,7 @@ namespace ix
|
|||||||
std::mutex _mutex; // to protect accessing the _socket (only one socket per client)
|
std::mutex _mutex; // to protect accessing the _socket (only one socket per client)
|
||||||
|
|
||||||
SocketTLSOptions _tlsOptions;
|
SocketTLSOptions _tlsOptions;
|
||||||
|
|
||||||
|
bool _forceBody;
|
||||||
};
|
};
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -19,6 +19,7 @@ typedef unsigned long int nfds_t;
|
|||||||
#else
|
#else
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
|
@ -43,6 +43,55 @@ namespace ix
|
|||||||
mbedtls_pk_init(&_pkey);
|
mbedtls_pk_init(&_pkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SocketMbedTLS::loadSystemCertificates(std::string& errorMsg)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD flags = CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG |
|
||||||
|
CERT_SYSTEM_STORE_CURRENT_USER;
|
||||||
|
HCERTSTORE systemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, flags, L"Root");
|
||||||
|
|
||||||
|
if (!systemStore)
|
||||||
|
{
|
||||||
|
errorMsg = "CertOpenStore failed with ";
|
||||||
|
errorMsg += std::to_string(GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCCERT_CONTEXT certificateIterator = NULL;
|
||||||
|
|
||||||
|
int certificateCount = 0;
|
||||||
|
while (certificateIterator = CertEnumCertificatesInStore(systemStore, certificateIterator))
|
||||||
|
{
|
||||||
|
if (certificateIterator->dwCertEncodingType & X509_ASN_ENCODING)
|
||||||
|
{
|
||||||
|
int ret = mbedtls_x509_crt_parse(&_cacert,
|
||||||
|
certificateIterator->pbCertEncoded,
|
||||||
|
certificateIterator->cbCertEncoded);
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
++certificateCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CertFreeCertificateContext(certificateIterator);
|
||||||
|
CertCloseStore(systemStore, 0);
|
||||||
|
|
||||||
|
if (certificateCount == 0)
|
||||||
|
{
|
||||||
|
errorMsg = "No certificates found";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
// On macOS we can query the system cert location from the keychain
|
||||||
|
// On Linux we could try to fetch some local files based on the distribution
|
||||||
|
// On Android we could use JNI to get to the system certs
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool SocketMbedTLS::init(const std::string& host, bool isClient, std::string& errMsg)
|
bool SocketMbedTLS::init(const std::string& host, bool isClient, std::string& errMsg)
|
||||||
{
|
{
|
||||||
initMBedTLS();
|
initMBedTLS();
|
||||||
@ -96,13 +145,15 @@ namespace ix
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
|
||||||
|
|
||||||
// FIXME: should we call mbedtls_ssl_conf_verify ?
|
// FIXME: should we call mbedtls_ssl_conf_verify ?
|
||||||
|
mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||||
|
|
||||||
if (_tlsOptions.isUsingSystemDefaults())
|
if (_tlsOptions.isUsingSystemDefaults())
|
||||||
{
|
{
|
||||||
; // FIXME
|
if (!loadSystemCertificates(errMsg))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -52,6 +52,7 @@ namespace ix
|
|||||||
|
|
||||||
bool init(const std::string& host, bool isClient, std::string& errMsg);
|
bool init(const std::string& host, bool isClient, std::string& errMsg);
|
||||||
void initMBedTLS();
|
void initMBedTLS();
|
||||||
|
bool loadSystemCertificates(std::string& errMsg);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -85,6 +85,8 @@ namespace ix
|
|||||||
|
|
||||||
std::atomic<bool> SocketOpenSSL::_openSSLInitializationSuccessful(false);
|
std::atomic<bool> SocketOpenSSL::_openSSLInitializationSuccessful(false);
|
||||||
std::once_flag SocketOpenSSL::_openSSLInitFlag;
|
std::once_flag SocketOpenSSL::_openSSLInitFlag;
|
||||||
|
std::unique_ptr<std::mutex[]> SocketOpenSSL::_openSSLMutexes =
|
||||||
|
std::make_unique<std::mutex[]>(CRYPTO_num_locks());
|
||||||
|
|
||||||
SocketOpenSSL::SocketOpenSSL(const SocketTLSOptions& tlsOptions, int fd)
|
SocketOpenSSL::SocketOpenSSL(const SocketTLSOptions& tlsOptions, int fd)
|
||||||
: Socket(fd)
|
: Socket(fd)
|
||||||
@ -106,6 +108,11 @@ namespace ix
|
|||||||
if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, nullptr)) return;
|
if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, nullptr)) return;
|
||||||
#else
|
#else
|
||||||
(void) OPENSSL_config(nullptr);
|
(void) OPENSSL_config(nullptr);
|
||||||
|
|
||||||
|
if (CRYPTO_get_locking_callback() == nullptr)
|
||||||
|
{
|
||||||
|
CRYPTO_set_locking_callback(SocketOpenSSL::openSSLLockingCallback);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
(void) OpenSSL_add_ssl_algorithms();
|
(void) OpenSSL_add_ssl_algorithms();
|
||||||
@ -114,6 +121,21 @@ namespace ix
|
|||||||
_openSSLInitializationSuccessful = true;
|
_openSSLInitializationSuccessful = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SocketOpenSSL::openSSLLockingCallback(int mode,
|
||||||
|
int type,
|
||||||
|
const char* /*file*/,
|
||||||
|
int /*line*/)
|
||||||
|
{
|
||||||
|
if (mode & CRYPTO_LOCK)
|
||||||
|
{
|
||||||
|
_openSSLMutexes[type].lock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_openSSLMutexes[type].unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string SocketOpenSSL::getSSLError(int ret)
|
std::string SocketOpenSSL::getSSLError(int ret)
|
||||||
{
|
{
|
||||||
unsigned long e;
|
unsigned long e;
|
||||||
|
@ -49,6 +49,9 @@ namespace ix
|
|||||||
bool handleTLSOptions(std::string& errMsg);
|
bool handleTLSOptions(std::string& errMsg);
|
||||||
bool openSSLServerHandshake(std::string& errMsg);
|
bool openSSLServerHandshake(std::string& errMsg);
|
||||||
|
|
||||||
|
// Required for OpenSSL < 1.1
|
||||||
|
static void openSSLLockingCallback(int mode, int type, const char* /*file*/, int /*line*/);
|
||||||
|
|
||||||
SSL* _ssl_connection;
|
SSL* _ssl_connection;
|
||||||
SSL_CTX* _ssl_context;
|
SSL_CTX* _ssl_context;
|
||||||
const SSL_METHOD* _ssl_method;
|
const SSL_METHOD* _ssl_method;
|
||||||
@ -58,6 +61,7 @@ namespace ix
|
|||||||
|
|
||||||
static std::once_flag _openSSLInitFlag;
|
static std::once_flag _openSSLInitFlag;
|
||||||
static std::atomic<bool> _openSSLInitializationSuccessful;
|
static std::atomic<bool> _openSSLInitializationSuccessful;
|
||||||
|
static std::unique_ptr<std::mutex[]> _openSSLMutexes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -44,6 +44,18 @@ namespace ix
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UdpSocket::isWaitNeeded()
|
||||||
|
{
|
||||||
|
int err = getErrno();
|
||||||
|
|
||||||
|
if (err == EWOULDBLOCK || err == EAGAIN || err == EINPROGRESS)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void UdpSocket::closeSocket(int fd)
|
void UdpSocket::closeSocket(int fd)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -62,6 +74,13 @@ namespace ix
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
unsigned long nonblocking = 1;
|
||||||
|
ioctlsocket(_sockfd, FIONBIO, &nonblocking);
|
||||||
|
#else
|
||||||
|
fcntl(_sockfd, F_SETFL, O_NONBLOCK); // make socket non blocking
|
||||||
|
#endif
|
||||||
|
|
||||||
memset(&_server, 0, sizeof(_server));
|
memset(&_server, 0, sizeof(_server));
|
||||||
_server.sin_family = AF_INET;
|
_server.sin_family = AF_INET;
|
||||||
_server.sin_port = htons(port);
|
_server.sin_port = htons(port);
|
||||||
@ -93,4 +112,15 @@ namespace ix
|
|||||||
return (ssize_t)::sendto(
|
return (ssize_t)::sendto(
|
||||||
_sockfd, buffer.data(), buffer.size(), 0, (struct sockaddr*) &_server, sizeof(_server));
|
_sockfd, buffer.data(), buffer.size(), 0, (struct sockaddr*) &_server, sizeof(_server));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t UdpSocket::recvfrom(char* buffer, size_t length)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
int addressLen = (int) sizeof(_server);
|
||||||
|
#else
|
||||||
|
socklen_t addressLen = (socklen_t) sizeof(_server);
|
||||||
|
#endif
|
||||||
|
return (ssize_t)::recvfrom(
|
||||||
|
_sockfd, buffer, length, 0, (struct sockaddr*) &_server, &addressLen);
|
||||||
|
}
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -28,9 +28,12 @@ namespace ix
|
|||||||
// Virtual methods
|
// Virtual methods
|
||||||
bool init(const std::string& host, int port, std::string& errMsg);
|
bool init(const std::string& host, int port, std::string& errMsg);
|
||||||
ssize_t sendto(const std::string& buffer);
|
ssize_t sendto(const std::string& buffer);
|
||||||
|
ssize_t recvfrom(char* buffer, size_t length);
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
static int getErrno();
|
static int getErrno();
|
||||||
|
static bool isWaitNeeded();
|
||||||
static void closeSocket(int fd);
|
static void closeSocket(int fd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IX_WEBSOCKET_VERSION "9.5.2"
|
#define IX_WEBSOCKET_VERSION "9.6.4"
|
||||||
|
10
makefile
10
makefile
@ -20,13 +20,13 @@ install: brew
|
|||||||
# Release, Debug, MinSizeRel, RelWithDebInfo are the build types
|
# Release, Debug, MinSizeRel, RelWithDebInfo are the build types
|
||||||
#
|
#
|
||||||
brew:
|
brew:
|
||||||
mkdir -p build && (cd build ; cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4 install)
|
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
|
||||||
|
|
||||||
# Docker default target. We've add problem with OpenSSL and TLS 1.3 (on the
|
# Docker default target. We've add problem with OpenSSL and TLS 1.3 (on the
|
||||||
# server side ?) and I can't work-around it easily, so we're using mbedtls on
|
# server side ?) and I can't work-around it easily, so we're using mbedtls on
|
||||||
# Linux for the SSL backend, which works great.
|
# Linux for the SSL backend, which works great.
|
||||||
ws_mbedtls_install:
|
ws_mbedtls_install:
|
||||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4 install)
|
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
|
||||||
|
|
||||||
ws:
|
ws:
|
||||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j 4)
|
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j 4)
|
||||||
@ -103,6 +103,10 @@ test_server:
|
|||||||
# env TEST=Websocket_chat make test
|
# env TEST=Websocket_chat make test
|
||||||
# env TEST=heartbeat make test
|
# env TEST=heartbeat make test
|
||||||
test:
|
test:
|
||||||
|
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
|
||||||
|
(cd test ; python2.7 run.py -r)
|
||||||
|
|
||||||
|
test_make:
|
||||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4)
|
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4)
|
||||||
(cd test ; python2.7 run.py -r)
|
(cd test ; python2.7 run.py -r)
|
||||||
|
|
||||||
@ -144,7 +148,7 @@ test_tsan_mbedtls:
|
|||||||
(cd test ; python2.7 run.py -r)
|
(cd test ; python2.7 run.py -r)
|
||||||
|
|
||||||
build_test_openssl:
|
build_test_openssl:
|
||||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPEN_SSL=1 -DUSE_TEST=1 .. ; make -j 4)
|
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPEN_SSL=1 -DUSE_TEST=1 .. ; ninja install)
|
||||||
|
|
||||||
test_openssl: build_test_openssl
|
test_openssl: build_test_openssl
|
||||||
(cd test ; python2.7 run.py -r)
|
(cd test ; python2.7 run.py -r)
|
||||||
|
@ -138,11 +138,12 @@ TEST_CASE("Cobra_to_sentry_bot", "[cobra_bots]")
|
|||||||
|
|
||||||
std::thread publisherThread(runPublisher, config, channel);
|
std::thread publisherThread(runPublisher, config, channel);
|
||||||
|
|
||||||
std::string filter;
|
ix::CobraBotConfig cobraBotConfig;
|
||||||
std::string position("$");
|
cobraBotConfig.cobraConfig = config;
|
||||||
|
cobraBotConfig.channel = channel;
|
||||||
|
cobraBotConfig.runtime = 3; // Only run the bot for 3 seconds
|
||||||
|
cobraBotConfig.enableHeartbeat = false;
|
||||||
bool verbose = true;
|
bool verbose = true;
|
||||||
size_t maxQueueSize = 10;
|
|
||||||
bool enableHeartbeat = false;
|
|
||||||
|
|
||||||
// FIXME: try to get this working with https instead of http
|
// FIXME: try to get this working with https instead of http
|
||||||
// to regress the TLS 1.3 OpenSSL bug
|
// to regress the TLS 1.3 OpenSSL bug
|
||||||
@ -157,18 +158,7 @@ TEST_CASE("Cobra_to_sentry_bot", "[cobra_bots]")
|
|||||||
SentryClient sentryClient(dsn);
|
SentryClient sentryClient(dsn);
|
||||||
sentryClient.setTLSOptions(tlsOptionsClient);
|
sentryClient.setTLSOptions(tlsOptionsClient);
|
||||||
|
|
||||||
// Only run the bot for 3 seconds
|
int64_t sentCount = cobra_to_sentry_bot(cobraBotConfig, sentryClient, verbose);
|
||||||
int runtime = 3;
|
|
||||||
|
|
||||||
int64_t sentCount = cobra_to_sentry_bot(config,
|
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
sentryClient,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
//
|
//
|
||||||
// We want at least 2 messages to be sent
|
// We want at least 2 messages to be sent
|
||||||
//
|
//
|
||||||
|
@ -87,14 +87,11 @@ TEST_CASE("Cobra_to_statsd_bot", "[cobra_bots]")
|
|||||||
|
|
||||||
std::thread publisherThread(runPublisher, config, channel);
|
std::thread publisherThread(runPublisher, config, channel);
|
||||||
|
|
||||||
std::string filter;
|
ix::CobraBotConfig cobraBotConfig;
|
||||||
std::string position("$");
|
cobraBotConfig.cobraConfig = config;
|
||||||
bool verbose = true;
|
cobraBotConfig.channel = channel;
|
||||||
size_t maxQueueSize = 10;
|
cobraBotConfig.runtime = 3; // Only run the bot for 3 seconds
|
||||||
bool enableHeartbeat = false;
|
cobraBotConfig.enableHeartbeat = false;
|
||||||
|
|
||||||
// Only run the bot for 3 seconds
|
|
||||||
int runtime = 3;
|
|
||||||
|
|
||||||
std::string hostname("127.0.0.1");
|
std::string hostname("127.0.0.1");
|
||||||
// std::string hostname("www.google.com");
|
// std::string hostname("www.google.com");
|
||||||
@ -113,19 +110,10 @@ TEST_CASE("Cobra_to_statsd_bot", "[cobra_bots]")
|
|||||||
std::string fields("device.game\ndevice.os_name");
|
std::string fields("device.game\ndevice.os_name");
|
||||||
std::string gauge;
|
std::string gauge;
|
||||||
std::string timer;
|
std::string timer;
|
||||||
|
bool verbose = true;
|
||||||
|
|
||||||
int64_t sentCount = ix::cobra_to_statsd_bot(config,
|
int64_t sentCount =
|
||||||
channel,
|
ix::cobra_to_statsd_bot(cobraBotConfig, statsdClient, fields, gauge, timer, verbose);
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
statsdClient,
|
|
||||||
fields,
|
|
||||||
gauge,
|
|
||||||
timer,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
//
|
//
|
||||||
// We want at least 2 messages to be sent
|
// We want at least 2 messages to be sent
|
||||||
//
|
//
|
||||||
|
@ -85,29 +85,17 @@ TEST_CASE("Cobra_to_stdout_bot", "[cobra_bots]")
|
|||||||
|
|
||||||
std::thread publisherThread(runPublisher, config, channel);
|
std::thread publisherThread(runPublisher, config, channel);
|
||||||
|
|
||||||
std::string filter;
|
ix::CobraBotConfig cobraBotConfig;
|
||||||
std::string position("$");
|
cobraBotConfig.cobraConfig = config;
|
||||||
bool verbose = true;
|
cobraBotConfig.channel = channel;
|
||||||
|
cobraBotConfig.runtime = 3; // Only run the bot for 3 seconds
|
||||||
|
cobraBotConfig.enableHeartbeat = false;
|
||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
size_t maxQueueSize = 10;
|
|
||||||
bool enableHeartbeat = false;
|
|
||||||
|
|
||||||
// Only run the bot for 3 seconds
|
|
||||||
int runtime = 3;
|
|
||||||
|
|
||||||
// We could try to capture the output ... not sure how.
|
// We could try to capture the output ... not sure how.
|
||||||
bool fluentd = true;
|
bool fluentd = true;
|
||||||
|
|
||||||
int64_t sentCount = ix::cobra_to_stdout_bot(config,
|
int64_t sentCount = ix::cobra_to_stdout_bot(cobraBotConfig, fluentd, quiet);
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
fluentd,
|
|
||||||
quiet,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
//
|
//
|
||||||
// We want at least 2 messages to be sent
|
// We want at least 2 messages to be sent
|
||||||
//
|
//
|
||||||
|
@ -4,6 +4,14 @@
|
|||||||
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Using inet_addr will trigger an error on uwp without this
|
||||||
|
// FIXME: use a different api
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "IXGetFreePort.h"
|
#include "IXGetFreePort.h"
|
||||||
|
|
||||||
#include <ixwebsocket/IXNetSystem.h>
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
|
@ -93,10 +93,11 @@ TEST_CASE("subprotocol", "[websocket_subprotocol]")
|
|||||||
webSocket.setUrl(url);
|
webSocket.setUrl(url);
|
||||||
webSocket.start();
|
webSocket.start();
|
||||||
|
|
||||||
|
// Give us 3 seconds to connect
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
while (!connected)
|
while (!connected)
|
||||||
{
|
{
|
||||||
REQUIRE(attempts++ < 10);
|
REQUIRE(attempts++ < 300);
|
||||||
ix::msleep(10);
|
ix::msleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
89
ws/ws.cpp
89
ws/ws.cpp
@ -19,8 +19,8 @@
|
|||||||
#include <ixwebsocket/IXNetSystem.h>
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
#include <ixwebsocket/IXSocket.h>
|
#include <ixwebsocket/IXSocket.h>
|
||||||
#include <ixwebsocket/IXUserAgent.h>
|
#include <ixwebsocket/IXUserAgent.h>
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
#include <spdlog/sinks/basic_file_sink.h>
|
#include <spdlog/sinks/basic_file_sink.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -120,6 +120,7 @@ int main(int argc, char** argv)
|
|||||||
std::string logfile;
|
std::string logfile;
|
||||||
ix::SocketTLSOptions tlsOptions;
|
ix::SocketTLSOptions tlsOptions;
|
||||||
ix::CobraConfig cobraConfig;
|
ix::CobraConfig cobraConfig;
|
||||||
|
ix::CobraBotConfig cobraBotConfig;
|
||||||
std::string ciphers;
|
std::string ciphers;
|
||||||
std::string redirectUrl;
|
std::string redirectUrl;
|
||||||
bool headersOnly = false;
|
bool headersOnly = false;
|
||||||
@ -148,9 +149,7 @@ int main(int argc, char** argv)
|
|||||||
int delayMs = -1;
|
int delayMs = -1;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
uint32_t maxWaitBetweenReconnectionRetries;
|
uint32_t maxWaitBetweenReconnectionRetries;
|
||||||
size_t maxQueueSize = 100;
|
|
||||||
int pingIntervalSecs = 30;
|
int pingIntervalSecs = 30;
|
||||||
int runtime = -1; // run indefinitely
|
|
||||||
|
|
||||||
auto addTLSOptions = [&tlsOptions, &verifyNone](CLI::App* app) {
|
auto addTLSOptions = [&tlsOptions, &verifyNone](CLI::App* app) {
|
||||||
app->add_option(
|
app->add_option(
|
||||||
@ -174,6 +173,24 @@ int main(int argc, char** argv)
|
|||||||
app->add_option("--rolesecret", cobraConfig.rolesecret, "Role secret")->required();
|
app->add_option("--rolesecret", cobraConfig.rolesecret, "Role secret")->required();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto addCobraBotConfig = [&cobraBotConfig](CLI::App* app) {
|
||||||
|
app->add_option("--appkey", cobraBotConfig.cobraConfig.appkey, "Appkey")->required();
|
||||||
|
app->add_option("--endpoint", cobraBotConfig.cobraConfig.endpoint, "Endpoint")->required();
|
||||||
|
app->add_option("--rolename", cobraBotConfig.cobraConfig.rolename, "Role name")->required();
|
||||||
|
app->add_option("--rolesecret", cobraBotConfig.cobraConfig.rolesecret, "Role secret")
|
||||||
|
->required();
|
||||||
|
app->add_option("--channel", cobraBotConfig.channel, "Channel")->required();
|
||||||
|
app->add_option("--filter", cobraBotConfig.filter, "Filter");
|
||||||
|
app->add_option("--position", cobraBotConfig.position, "Position");
|
||||||
|
app->add_option("--runtime", cobraBotConfig.runtime, "Runtime");
|
||||||
|
app->add_option("--heartbeat", cobraBotConfig.enableHeartbeat, "Runtime");
|
||||||
|
app->add_option("--heartbeat_timeout", cobraBotConfig.heartBeatTimeout, "Runtime");
|
||||||
|
app->add_flag(
|
||||||
|
"--limit_received_events", cobraBotConfig.limitReceivedEvents, "Max events per minute");
|
||||||
|
app->add_option(
|
||||||
|
"--max_events_per_minute", cobraBotConfig.maxEventsPerMinute, "Max events per minute");
|
||||||
|
};
|
||||||
|
|
||||||
app.add_flag("--version", version, "Print ws version");
|
app.add_flag("--version", version, "Print ws version");
|
||||||
app.add_option("--logfile", logfile, "path where all logs will be redirected");
|
app.add_option("--logfile", logfile, "path where all logs will be redirected");
|
||||||
|
|
||||||
@ -281,15 +298,11 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
CLI::App* cobraSubscribeApp = app.add_subcommand("cobra_subscribe", "Cobra subscriber");
|
CLI::App* cobraSubscribeApp = app.add_subcommand("cobra_subscribe", "Cobra subscriber");
|
||||||
cobraSubscribeApp->fallthrough();
|
cobraSubscribeApp->fallthrough();
|
||||||
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("--position", position, "Stream position");
|
|
||||||
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");
|
cobraSubscribeApp->add_flag("--fluentd", fluentd, "Write fluentd prefix");
|
||||||
cobraSubscribeApp->add_option("--runtime", runtime, "Runtime in seconds");
|
|
||||||
addTLSOptions(cobraSubscribeApp);
|
addTLSOptions(cobraSubscribeApp);
|
||||||
addCobraConfig(cobraSubscribeApp);
|
addCobraBotConfig(cobraSubscribeApp);
|
||||||
|
|
||||||
CLI::App* cobraPublish = app.add_subcommand("cobra_publish", "Cobra publisher");
|
CLI::App* cobraPublish = app.add_subcommand("cobra_publish", "Cobra publisher");
|
||||||
cobraPublish->fallthrough();
|
cobraPublish->fallthrough();
|
||||||
@ -323,32 +336,18 @@ int main(int argc, char** argv)
|
|||||||
->join();
|
->join();
|
||||||
cobra2statsd->add_option("--timer", timer, "Value to extract, and use as a statsd timer")
|
cobra2statsd->add_option("--timer", timer, "Value to extract, and use as a statsd timer")
|
||||||
->join();
|
->join();
|
||||||
cobra2statsd->add_option("channel", channel, "Channel")->required();
|
|
||||||
cobra2statsd->add_flag("-v", verbose, "Verbose");
|
cobra2statsd->add_flag("-v", verbose, "Verbose");
|
||||||
cobra2statsd->add_option("--pidfile", pidfile, "Pid file");
|
cobra2statsd->add_option("--pidfile", pidfile, "Pid file");
|
||||||
cobra2statsd->add_option("--filter", filter, "Stream SQL Filter");
|
|
||||||
cobra2statsd->add_option("--position", position, "Stream position");
|
|
||||||
cobra2statsd->add_option("--queue_size",
|
|
||||||
maxQueueSize,
|
|
||||||
"Size of the queue to hold messages before they are sent to Sentry");
|
|
||||||
cobra2statsd->add_option("--runtime", runtime, "Runtime in seconds");
|
|
||||||
addTLSOptions(cobra2statsd);
|
addTLSOptions(cobra2statsd);
|
||||||
addCobraConfig(cobra2statsd);
|
addCobraBotConfig(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->fallthrough();
|
cobra2sentry->fallthrough();
|
||||||
cobra2sentry->add_option("--dsn", dsn, "Sentry DSN");
|
cobra2sentry->add_option("--dsn", dsn, "Sentry DSN");
|
||||||
cobra2sentry->add_option("--queue_size",
|
|
||||||
maxQueueSize,
|
|
||||||
"Size of the queue to hold messages before they are sent to Sentry");
|
|
||||||
cobra2sentry->add_option("channel", channel, "Channel")->required();
|
|
||||||
cobra2sentry->add_flag("-v", verbose, "Verbose");
|
cobra2sentry->add_flag("-v", verbose, "Verbose");
|
||||||
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("--position", position, "Stream position");
|
|
||||||
cobra2sentry->add_option("--runtime", runtime, "Runtime in seconds");
|
|
||||||
addTLSOptions(cobra2sentry);
|
addTLSOptions(cobra2sentry);
|
||||||
addCobraConfig(cobra2sentry);
|
addCobraBotConfig(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");
|
||||||
@ -459,6 +458,10 @@ int main(int argc, char** argv)
|
|||||||
cobraConfig.webSocketPerMessageDeflateOptions = ix::WebSocketPerMessageDeflateOptions(true);
|
cobraConfig.webSocketPerMessageDeflateOptions = ix::WebSocketPerMessageDeflateOptions(true);
|
||||||
cobraConfig.socketTLSOptions = tlsOptions;
|
cobraConfig.socketTLSOptions = tlsOptions;
|
||||||
|
|
||||||
|
cobraBotConfig.cobraConfig.webSocketPerMessageDeflateOptions =
|
||||||
|
ix::WebSocketPerMessageDeflateOptions(true);
|
||||||
|
cobraBotConfig.cobraConfig.socketTLSOptions = tlsOptions;
|
||||||
|
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
if (app.got_subcommand("transfer"))
|
if (app.got_subcommand("transfer"))
|
||||||
{
|
{
|
||||||
@ -528,17 +531,7 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else if (app.got_subcommand("cobra_subscribe"))
|
else if (app.got_subcommand("cobra_subscribe"))
|
||||||
{
|
{
|
||||||
bool enableHeartbeat = true;
|
int64_t sentCount = ix::cobra_to_stdout_bot(cobraBotConfig, fluentd, quiet);
|
||||||
int64_t sentCount = ix::cobra_to_stdout_bot(cobraConfig,
|
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
fluentd,
|
|
||||||
quiet,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
ret = (int) sentCount;
|
ret = (int) sentCount;
|
||||||
}
|
}
|
||||||
else if (app.got_subcommand("cobra_publish"))
|
else if (app.got_subcommand("cobra_publish"))
|
||||||
@ -559,7 +552,6 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool enableHeartbeat = true;
|
|
||||||
ix::StatsdClient statsdClient(hostname, statsdPort, prefix);
|
ix::StatsdClient statsdClient(hostname, statsdPort, prefix);
|
||||||
|
|
||||||
std::string errMsg;
|
std::string errMsg;
|
||||||
@ -571,36 +563,17 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = (int) ix::cobra_to_statsd_bot(cobraConfig,
|
ret = (int) ix::cobra_to_statsd_bot(
|
||||||
channel,
|
cobraBotConfig, statsdClient, fields, gauge, timer, verbose);
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
statsdClient,
|
|
||||||
fields,
|
|
||||||
gauge,
|
|
||||||
timer,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (app.got_subcommand("cobra_to_sentry"))
|
else if (app.got_subcommand("cobra_to_sentry"))
|
||||||
{
|
{
|
||||||
bool enableHeartbeat = true;
|
|
||||||
ix::SentryClient sentryClient(dsn);
|
ix::SentryClient sentryClient(dsn);
|
||||||
sentryClient.setTLSOptions(tlsOptions);
|
sentryClient.setTLSOptions(tlsOptions);
|
||||||
|
|
||||||
ret = (int) ix::cobra_to_sentry_bot(cobraConfig,
|
ret = (int) ix::cobra_to_sentry_bot(cobraBotConfig, sentryClient, verbose);
|
||||||
channel,
|
|
||||||
filter,
|
|
||||||
position,
|
|
||||||
sentryClient,
|
|
||||||
verbose,
|
|
||||||
maxQueueSize,
|
|
||||||
enableHeartbeat,
|
|
||||||
runtime);
|
|
||||||
}
|
}
|
||||||
else if (app.got_subcommand("cobra_metrics_to_redis"))
|
else if (app.got_subcommand("cobra_metrics_to_redis"))
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user