Compare commits

..

25 Commits

Author SHA1 Message Date
c1403df74a (cmake) default TLS back to mbedtls on Windows Universal Platform 2020-05-08 09:31:53 -07:00
3912e22b28 give websocket_subprotocol test more time to establish a connection 2020-05-08 09:26:05 -07:00
c9d5b4a581 Moved fPIC option to the top of the CMakeLists (#197)
The fPIC option was not properly registered before
2020-05-08 08:00:51 -07:00
9f8643032d fix dumb compile error 2020-05-06 22:07:47 -07:00
0772ef7ef5 (cobra bots) add a --heartbeat_timeout option to specify when the bot should terminate because no events are received 2020-05-06 22:01:48 -07:00
c030a62c8b openSSLLockingCallback should be static 2020-05-06 16:57:53 -07:00
931530b101 only register the crypto lock callback if no-one has registered them before us 2020-05-06 16:49:04 -07:00
6c205b983e (openssl tls) when OpenSSL is older than 1.1, register the crypto locking callback to be thread safe. Should fix lots of CI failures 2020-05-06 16:26:30 -07:00
a65b334961 assert that the timeout is non zero in makeCancellationRequestWithTimeout 2020-05-06 15:53:27 -07:00
2de8aafcbc another windows build error in IXUdpSocket ... 2020-05-05 08:29:39 -07:00
f075f586e1 fix windows compile error with UdpSocket::recvfrom 2020-05-05 08:15:01 -07:00
93cb898989 fix compile error with UdpSocket::recvfrom 2020-05-05 08:03:04 -07:00
e4da62547b add reference to multiple projects using IXWebSocket 2020-05-05 07:52:02 -07:00
2b4c06e6d2 UdpSocket::recvfrom last argument does not have to be a uint32_t 2020-05-05 07:49:07 -07:00
7337ed34a6 Added asynchronous udp receive function (#193)
* Added asynchronous udp receive function

* Remove receive_async and added low level recv, which is non-blocking.

* Remove thread include

* Moved unix include to IXNetSystem.h
2020-05-05 07:47:41 -07:00
15355188d5 (http client) rework a bit PATCH pull request, fix compile error with setForceBody and initialize _forceBody to false 2020-05-05 07:43:55 -07:00
8760c87635 add PATCH and add option to enforce a http request body write (#195)
* add PATCH and add option to enforce a http request body write

* remove private bool prop
2020-05-05 07:38:55 -07:00
2786631e3b clang-format 2020-05-04 17:19:25 -07:00
1b30061a4d remove unused variable 2020-05-04 17:18:21 -07:00
af003fc79b (ixbots) fix tsan data race error when accessing verbose parameter 2020-05-04 17:15:35 -07:00
4f17cd5e74 (cobra bots) do not use a queue to store messages pending processing, let the bot handle queuing 2020-05-04 15:45:11 -07:00
b04764489c (doc) add link to a project using ixwebsocket #187 2020-05-04 09:21:39 -07:00
fc4a4bfb7c fix #194 / linux needs to built with position independant code 2020-05-03 12:19:58 -07:00
9e54fd5f1a Fix CMake/zlibstatic-related regression (#192)
* cmake: add export() and install(EXPORT) for easier packageability

Enable the package to be more readily packageable as a system-wide
install or as a third-party dependency to another CMake-base project

This does not change CMake version requirements AFAICT

* CMake: link-in OpenSSL::Crypto

* CMake: explicitly manage dependencies. Fixes building with zlibstatic
2020-05-02 22:08:58 -07:00
1096f62196 cmake: add export() and install(EXPORT) for easier packageability (#190)
* cmake: add export() and install(EXPORT) for easier packageability

Enable the package to be more readily packageable as a system-wide
install or as a third-party dependency to another CMake-base project

This does not change CMake version requirements AFAICT

* CMake: link-in OpenSSL::Crypto
2020-05-02 20:20:59 -07:00
32 changed files with 246 additions and 346 deletions

View File

@ -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 uwp (universal windows platform) if nothing is configured
elseif (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore")
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)
@ -144,6 +153,8 @@ add_library( ixwebsocket STATIC
${IXWEBSOCKET_HEADERS} ${IXWEBSOCKET_HEADERS}
) )
add_library ( ixwebsocket::ixwebsocket ALIAS ixwebsocket )
if (USE_TLS) if (USE_TLS)
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_TLS) target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_TLS)
if (USE_MBED_TLS) if (USE_MBED_TLS)
@ -165,26 +176,28 @@ 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
if (NOT OPENSSL_FOUND) if (NOT OPENSSL_FOUND)
find_package(OpenSSL REQUIRED) include(FindOpenSSL)
endif() endif()
message(STATUS "OpenSSL: " ${OPENSSL_VERSION}) message(STATUS "OpenSSL: " ${OPENSSL_VERSION})
add_definitions(${OPENSSL_DEFINITIONS}) target_link_libraries(ixwebsocket PUBLIC OpenSSL::SSL OpenSSL::Crypto)
target_include_directories(ixwebsocket PUBLIC ${OPENSSL_INCLUDE_DIR})
target_link_libraries(ixwebsocket ${OPENSSL_LIBRARIES})
elseif (USE_MBED_TLS) elseif (USE_MBED_TLS)
message(STATUS "TLS configured to use mbedtls") message(STATUS "TLS configured to use mbedtls")
find_package(MbedTLS REQUIRED) find_package(MbedTLS REQUIRED)
target_include_directories(ixwebsocket PUBLIC ${MBEDTLS_INCLUDE_DIRS}) target_include_directories(ixwebsocket PUBLIC ${MBEDTLS_INCLUDE_DIRS})
target_link_libraries(ixwebsocket ${MBEDTLS_LIBRARIES}) target_link_libraries(ixwebsocket PUBLIC ${MBEDTLS_LIBRARIES})
elseif (USE_SECURE_TRANSPORT) elseif (USE_SECURE_TRANSPORT)
message(STATUS "TLS configured to use secure transport") message(STATUS "TLS configured to use secure transport")
target_link_libraries(ixwebsocket "-framework foundation" "-framework security") target_link_libraries(ixwebsocket PUBLIC "-framework foundation" "-framework security")
endif() endif()
endif() endif()
@ -194,25 +207,25 @@ if (NOT ZLIB_FOUND)
endif() endif()
if (ZLIB_FOUND) if (ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIRS}) include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries(ixwebsocket ${ZLIB_LIBRARIES}) target_link_libraries(ixwebsocket PUBLIC ${ZLIB_LIBRARIES})
else() else()
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) add_subdirectory(third_party/zlib EXCLUDE_FROM_ALL)
target_link_libraries(ixwebsocket zlibstatic) target_link_libraries(ixwebsocket PRIVATE $<LINK_ONLY:zlibstatic>)
endif() endif()
if (WIN32) if (WIN32)
target_link_libraries(ixwebsocket wsock32 ws2_32 shlwapi) target_link_libraries(ixwebsocket PUBLIC wsock32 ws2_32 shlwapi)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS)
if (USE_TLS) if (USE_TLS)
target_link_libraries(ixwebsocket Crypt32) target_link_libraries(ixwebsocket PUBLIC Crypt32)
endif() endif()
endif() endif()
if (UNIX) if (UNIX)
find_package(Threads) find_package(Threads)
target_link_libraries(ixwebsocket ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(ixwebsocket PUBLIC ${CMAKE_THREAD_LIBS_INIT})
endif() endif()
@ -225,15 +238,18 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_compile_options(ixwebsocket PRIVATE /MP) target_compile_options(ixwebsocket PRIVATE /MP)
endif() endif()
target_include_directories(ixwebsocket PUBLIC ${IXWEBSOCKET_INCLUDE_DIRS}) target_include_directories(ixwebsocket PUBLIC $<BUILD_INTERFACE:${IXWEBSOCKET_INCLUDE_DIRS}> $<INSTALL_INTERFACE:include/ixwebsocket>)
set_target_properties(ixwebsocket PROPERTIES PUBLIC_HEADER "${IXWEBSOCKET_HEADERS}") set_target_properties(ixwebsocket PROPERTIES PUBLIC_HEADER "${IXWEBSOCKET_HEADERS}")
install(TARGETS ixwebsocket install(TARGETS ixwebsocket EXPORT ixwebsocket
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ixwebsocket/ PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ixwebsocket/
) )
install(EXPORT ixwebsocket NAMESPACE ixwebsocket:: DESTINATION lib/cmake/ixwebsocket)
export(EXPORT ixwebsocket NAMESPACE ixwebsocket:: FILE ixwebsocketConfig.cmake)
if (USE_WS OR USE_TEST) if (USE_WS OR USE_TEST)
add_subdirectory(ixcore) add_subdirectory(ixcore)
add_subdirectory(ixcrypto) add_subdirectory(ixcrypto)

View File

@ -45,3 +45,6 @@ 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)
- [dis-light](https://gitlab.com/HCInk/dis-light), a discord library with a node frontend.
- [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

View File

@ -1,9 +1,21 @@
# 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.5.4] - 2020-05-01 ## [9.5.7] - 2020-05-08
(windows) fix build for universal windows platform (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 ## [9.5.3] - 2020-04-29

View File

@ -8,7 +8,6 @@ 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
) )
@ -17,7 +16,6 @@ set (IXBOTS_HEADERS
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
) )

View File

@ -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>
@ -22,17 +21,14 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& filter, const std::string& filter,
const std::string& position, const std::string& position,
bool verbose,
size_t maxQueueSize,
bool useQueue,
bool enableHeartbeat, bool enableHeartbeat,
int heartBeatTimeout,
int runtime) int runtime)
{ {
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);
@ -43,8 +39,6 @@ namespace ix
std::atomic<bool> throttled(false); std::atomic<bool> throttled(false);
std::atomic<bool> fatalCobraError(false); std::atomic<bool> fatalCobraError(false);
QueueManager queueManager(maxQueueSize);
auto timer = [&sentCount, auto timer = [&sentCount,
&receivedCount, &receivedCount,
&sentCountTotal, &sentCountTotal,
@ -85,7 +79,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 +95,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 +109,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 +116,9 @@ namespace ix
&channel, &channel,
&filter, &filter,
&subscriptionPosition, &subscriptionPosition,
&jsonWriter,
verbose,
&throttled, &throttled,
&receivedCount, &receivedCount,
&fatalCobraError, &fatalCobraError,
&useQueue,
&queueManager,
&sentCount](const CobraEventPtr& event) { &sentCount](const CobraEventPtr& event) {
if (event->type == ix::CobraEventType::Open) if (event->type == ix::CobraEventType::Open)
{ {
@ -186,21 +143,11 @@ namespace ix
filter, filter,
subscriptionPosition, subscriptionPosition,
[this, [this,
&jsonWriter,
verbose,
&throttled, &throttled,
&receivedCount, &receivedCount,
&queueManager,
&useQueue,
&subscriptionPosition, &subscriptionPosition,
&fatalCobraError, &fatalCobraError,
&sentCount](const Json::Value& msg, const std::string& position) { &sentCount](const Json::Value& msg, const std::string& position) {
if (verbose)
{
CoreLogger::info("Subscriber received message "
+ position + " -> " + jsonWriter.write(msg));
}
subscriptionPosition = position; subscriptionPosition = position;
// If we cannot send to sentry fast enough, drop the message // If we cannot send to sentry fast enough, drop the message
@ -211,28 +158,9 @@ namespace ix
++receivedCount; ++receivedCount;
if (useQueue) _onBotMessageCallback(
{ msg, position, throttled,
queueManager.add(msg, position); fatalCobraError, sentCount);
}
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 +236,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;
} }

View File

@ -14,11 +14,11 @@
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
{ {
@ -29,10 +29,8 @@ namespace ix
const std::string& channel, const std::string& channel,
const std::string& filter, const std::string& filter,
const std::string& position, const std::string& position,
bool verbose,
size_t maxQueueSize,
bool useQueue,
bool enableHeartbeat, bool enableHeartbeat,
int heartBeatTimeout,
int runtime); int runtime);
void setOnBotMessageCallback(const OnBotMessageCallback& callback); void setOnBotMessageCallback(const OnBotMessageCallback& callback);

View File

@ -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>
@ -23,95 +22,67 @@ namespace ix
const std::string& position, const std::string& position,
SentryClient& sentryClient, SentryClient& sentryClient,
bool verbose, bool verbose,
size_t maxQueueSize,
bool enableHeartbeat, bool enableHeartbeat,
int heartBeatTimeout,
int runtime) 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, channel,
filter, filter,
position, position,
verbose,
maxQueueSize,
useQueue,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
} }
} // namespace ix } // namespace ix

View File

@ -18,7 +18,7 @@ namespace ix
const std::string& position, const std::string& position,
SentryClient& sentryClient, SentryClient& sentryClient,
bool verbose, bool verbose,
size_t maxQueueSize,
bool enableHeartbeat, bool enableHeartbeat,
int heartBeatTimeout,
int runtime); int runtime);
} // namespace ix } // namespace ix

View File

@ -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>
@ -63,8 +62,8 @@ namespace ix
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, bool enableHeartbeat,
int heartBeatTimeout,
int runtime) int runtime)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
@ -75,11 +74,11 @@ namespace ix
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 +121,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 +139,15 @@ namespace ix
} }
} }
return true; sentCount++;
}); });
bool useQueue = true;
return bot.run(config, return bot.run(config,
channel, channel,
filter, filter,
position, position,
verbose,
maxQueueSize,
useQueue,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
} }
} // namespace ix } // namespace ix

View File

@ -22,7 +22,7 @@ namespace ix
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, bool enableHeartbeat,
int heartBeatTimeout,
int runtime); int runtime);
} // namespace ix } // namespace ix

View File

@ -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>
@ -70,9 +69,8 @@ namespace ix
const std::string& position, const std::string& position,
bool fluentd, bool fluentd,
bool quiet, bool quiet,
bool verbose,
size_t maxQueueSize,
bool enableHeartbeat, bool enableHeartbeat,
int heartBeatTimeout,
int runtime) int runtime)
{ {
CobraBot bot; CobraBot bot;
@ -81,27 +79,22 @@ 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, channel,
filter, filter,
position, position,
verbose,
maxQueueSize,
useQueue,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
} }
} // namespace ix } // namespace ix

View File

@ -18,8 +18,7 @@ namespace ix
const std::string& position, const std::string& position,
bool fluentd, bool fluentd,
bool quiet, bool quiet,
bool verbose,
size_t maxQueueSize,
bool enableHeartbeat, bool enableHeartbeat,
int heartBeatTimeout,
int runtime); int runtime);
} // namespace ix } // namespace ix

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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();

View File

@ -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);

View File

@ -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";
@ -241,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, _stop);
if (args->verbose) if (args->verbose)
{ {
@ -561,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;

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -6,4 +6,4 @@
#pragma once #pragma once
#define IX_WEBSOCKET_VERSION "9.5.4" #define IX_WEBSOCKET_VERSION "9.5.7"

View File

@ -148,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)

View File

@ -141,8 +141,8 @@ TEST_CASE("Cobra_to_sentry_bot", "[cobra_bots]")
std::string filter; std::string filter;
std::string position("$"); std::string position("$");
bool verbose = true; bool verbose = true;
size_t maxQueueSize = 10;
bool enableHeartbeat = false; bool enableHeartbeat = false;
int heartBeatTimeout = 60;
// 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
@ -166,8 +166,8 @@ TEST_CASE("Cobra_to_sentry_bot", "[cobra_bots]")
position, position,
sentryClient, sentryClient,
verbose, verbose,
maxQueueSize,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
// //
// We want at least 2 messages to be sent // We want at least 2 messages to be sent

View File

@ -90,8 +90,8 @@ TEST_CASE("Cobra_to_statsd_bot", "[cobra_bots]")
std::string filter; std::string filter;
std::string position("$"); std::string position("$");
bool verbose = true; bool verbose = true;
size_t maxQueueSize = 10;
bool enableHeartbeat = false; bool enableHeartbeat = false;
int heartBeatTimeout = 60;
// Only run the bot for 3 seconds // Only run the bot for 3 seconds
int runtime = 3; int runtime = 3;
@ -123,8 +123,8 @@ TEST_CASE("Cobra_to_statsd_bot", "[cobra_bots]")
gauge, gauge,
timer, timer,
verbose, verbose,
maxQueueSize,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
// //
// We want at least 2 messages to be sent // We want at least 2 messages to be sent

View File

@ -87,10 +87,9 @@ TEST_CASE("Cobra_to_stdout_bot", "[cobra_bots]")
std::string filter; std::string filter;
std::string position("$"); std::string position("$");
bool verbose = true;
bool quiet = false; bool quiet = false;
size_t maxQueueSize = 10;
bool enableHeartbeat = false; bool enableHeartbeat = false;
int heartBeatTimeout = 60;
// Only run the bot for 3 seconds // Only run the bot for 3 seconds
int runtime = 3; int runtime = 3;
@ -104,9 +103,8 @@ TEST_CASE("Cobra_to_stdout_bot", "[cobra_bots]")
position, position,
fluentd, fluentd,
quiet, quiet,
verbose,
maxQueueSize,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
// //
// We want at least 2 messages to be sent // We want at least 2 messages to be sent

View File

@ -4,7 +4,7 @@
* 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 // Using inet_addr will trigger an error on uwp without this
// FIXME: use a different api // FIXME: use a different api
#ifdef _WIN32 #ifdef _WIN32
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS

View File

@ -96,7 +96,7 @@ TEST_CASE("subprotocol", "[websocket_subprotocol]")
int attempts = 0; int attempts = 0;
while (!connected) while (!connected)
{ {
REQUIRE(attempts++ < 10); REQUIRE(attempts++ < 100);
ix::msleep(10); ix::msleep(10);
} }

View File

@ -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>
@ -148,9 +148,9 @@ 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 int runtime = -1; // run indefinitely
int heartBeatTimeout = 60;
auto addTLSOptions = [&tlsOptions, &verifyNone](CLI::App* app) { auto addTLSOptions = [&tlsOptions, &verifyNone](CLI::App* app) {
app->add_option( app->add_option(
@ -288,6 +288,7 @@ int main(int argc, char** argv)
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"); cobraSubscribeApp->add_option("--runtime", runtime, "Runtime in seconds");
cobraSubscribeApp->add_option("--heartbeat_timeout", heartBeatTimeout, "Heartbeat timeout");
addTLSOptions(cobraSubscribeApp); addTLSOptions(cobraSubscribeApp);
addCobraConfig(cobraSubscribeApp); addCobraConfig(cobraSubscribeApp);
@ -328,25 +329,21 @@ 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");
cobra2statsd->add_option("--position", position, "Stream position"); 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"); cobra2statsd->add_option("--runtime", runtime, "Runtime in seconds");
cobra2statsd->add_option("--heartbeat_timeout", heartBeatTimeout, "Heartbeat timeout");
addTLSOptions(cobra2statsd); addTLSOptions(cobra2statsd);
addCobraConfig(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->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_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("--filter", filter, "Stream SQL Filter");
cobra2sentry->add_option("--position", position, "Stream position"); cobra2sentry->add_option("--position", position, "Stream position");
cobra2sentry->add_option("--runtime", runtime, "Runtime in seconds"); cobra2sentry->add_option("--runtime", runtime, "Runtime in seconds");
cobra2sentry->add_option("--heartbeat_timeout", heartBeatTimeout, "Heartbeat timeout");
addTLSOptions(cobra2sentry); addTLSOptions(cobra2sentry);
addCobraConfig(cobra2sentry); addCobraConfig(cobra2sentry);
@ -535,9 +532,8 @@ int main(int argc, char** argv)
position, position,
fluentd, fluentd,
quiet, quiet,
verbose,
maxQueueSize,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
ret = (int) sentCount; ret = (int) sentCount;
} }
@ -580,8 +576,8 @@ int main(int argc, char** argv)
gauge, gauge,
timer, timer,
verbose, verbose,
maxQueueSize,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
} }
} }
@ -598,8 +594,8 @@ int main(int argc, char** argv)
position, position,
sentryClient, sentryClient,
verbose, verbose,
maxQueueSize,
enableHeartbeat, enableHeartbeat,
heartBeatTimeout,
runtime); runtime);
} }
else if (app.got_subcommand("cobra_metrics_to_redis")) else if (app.got_subcommand("cobra_metrics_to_redis"))