Compare commits
45 Commits
feature/we
...
feature/wi
Author | SHA1 | Date | |
---|---|---|---|
bf2145eb8a | |||
a35f8f2250 | |||
fbca513008 | |||
33ebd00932 | |||
fbe5e74109 | |||
a9f5d5353f | |||
22e0083832 | |||
5632360fbd | |||
20294841b3 | |||
74efdfebba | |||
0ab04f51fe | |||
4ed7968b05 | |||
287e48962f | |||
953c680eee | |||
2802cad8c4 | |||
9f770b10c0 | |||
677f79b0ea | |||
646b18bf28 | |||
0670954faf | |||
2469d7102e | |||
79acb915ce | |||
bad3adb6b4 | |||
e3dd4e60c0 | |||
c70f1d09a8 | |||
4b2b133c10 | |||
cd5fae6a5b | |||
5860c5c80b | |||
36257cbfe4 | |||
68ee57a6a7 | |||
9d79596629 | |||
0b6fd989f5 | |||
1c19a57fef | |||
a2abe861d3 | |||
0f5d15aa11 | |||
ccfd196863 | |||
9b8cfa0a37 | |||
85f6b1e0b7 | |||
64754df66c | |||
71a421eefc | |||
386ef3ab04 | |||
2c4bf8f4bd | |||
3a2c446225 | |||
35630fe7ed | |||
bea582c208 | |||
783d1d92dd |
39
.github/workflows/ccpp.yml
vendored
39
.github/workflows/ccpp.yml
vendored
@ -5,50 +5,15 @@ on:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make test
|
||||
run: make test
|
||||
|
||||
mac_tsan_sectransport:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make test_tsan
|
||||
run: make test_tsan
|
||||
|
||||
mac_tsan_openssl:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install openssl
|
||||
run: brew install openssl
|
||||
- name: make test
|
||||
run: make test_tsan_openssl
|
||||
|
||||
mac_tsan_mbedtls:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install mbedtls
|
||||
run: brew install mbedtls
|
||||
- name: make test
|
||||
run: make test_tsan_mbedtls
|
||||
|
||||
windows_mbedtls:
|
||||
windows_openssl:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||
- run: |
|
||||
vcpkg install zlib:x64-windows
|
||||
vcpkg install mbedtls:x64-windows
|
||||
- run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_COMPILER=cl.exe -DUSE_MBED_TLS=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 ..
|
||||
cmake -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0" -DCMAKE_CXX_COMPILER=cl.exe -DUSE_WS=1 -DUSE_TEST=1 ..
|
||||
- run: cmake --build build
|
||||
|
||||
# Running the unittest does not work, the binary cannot be found
|
||||
|
@ -1,7 +1,12 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.3.0
|
||||
rev: v2.5.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/pocc/pre-commit-hooks
|
||||
rev: v1.1.1
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: [-i, -style=file]
|
||||
|
105
CMakeLists.txt
105
CMakeLists.txt
@ -49,7 +49,6 @@ set( IXWEBSOCKET_SOURCES
|
||||
ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp
|
||||
ixwebsocket/IXWebSocketServer.cpp
|
||||
ixwebsocket/IXWebSocketTransport.cpp
|
||||
ixwebsocket/LUrlParser.cpp
|
||||
)
|
||||
|
||||
set( IXWEBSOCKET_HEADERS
|
||||
@ -80,6 +79,7 @@ set( IXWEBSOCKET_HEADERS
|
||||
ixwebsocket/IXWebSocketCloseInfo.h
|
||||
ixwebsocket/IXWebSocketErrorInfo.h
|
||||
ixwebsocket/IXWebSocketHandshake.h
|
||||
ixwebsocket/IXWebSocketHandshakeKeyGen.h
|
||||
ixwebsocket/IXWebSocketHttpHeaders.h
|
||||
ixwebsocket/IXWebSocketInitResult.h
|
||||
ixwebsocket/IXWebSocketMessage.h
|
||||
@ -92,8 +92,6 @@ set( IXWEBSOCKET_HEADERS
|
||||
ixwebsocket/IXWebSocketServer.h
|
||||
ixwebsocket/IXWebSocketTransport.h
|
||||
ixwebsocket/IXWebSocketVersion.h
|
||||
ixwebsocket/LUrlParser.h
|
||||
ixwebsocket/libwshandshake.hpp
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
@ -111,31 +109,33 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/freebsd/IXSetThreadName_freebsd.cpp)
|
||||
else()
|
||||
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/linux/IXSetThreadName_linux.cpp)
|
||||
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSelectInterruptEventFd.cpp)
|
||||
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSelectInterruptEventFd.h)
|
||||
endif()
|
||||
|
||||
option(USE_TLS "Enable TLS support" FALSE)
|
||||
|
||||
if (USE_TLS)
|
||||
option(USE_MBED_TLS "Use Mbed TLS" OFF)
|
||||
option(USE_OPEN_SSL "Use OpenSSL" OFF)
|
||||
|
||||
# default to mbedtls on windows if nothing is configured
|
||||
if (WIN32 AND NOT USE_OPEN_SSL AND NOT USE_MBED_TLS)
|
||||
option(USE_MBED_TLS "Use Mbed TLS" ON)
|
||||
# default to securetranport on Apple if nothing is configured
|
||||
if (APPLE)
|
||||
if (NOT USE_MBED_TLS AND NOT USE_OPEN_SSL) # unless we want something else
|
||||
set(USE_SECURE_TRANSPORT ON)
|
||||
endif()
|
||||
else() # default to OpenSSL on all other platforms
|
||||
if (NOT USE_MBED_TLS) # Unless mbedtls is requested
|
||||
set(USE_OPEN_SSL ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (USE_MBED_TLS)
|
||||
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketMbedTLS.h)
|
||||
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketMbedTLS.cpp)
|
||||
elseif (APPLE AND NOT USE_OPEN_SSL)
|
||||
elseif (USE_SECURE_TRANSPORT)
|
||||
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketAppleSSL.h)
|
||||
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketAppleSSL.cpp)
|
||||
else()
|
||||
set(USE_OPEN_SSL ON)
|
||||
elseif (USE_OPEN_SSL)
|
||||
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketOpenSSL.h)
|
||||
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketOpenSSL.cpp)
|
||||
else()
|
||||
message(FATAL_ERROR "TLS Configuration error: unknown backend")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -150,55 +150,45 @@ if (USE_TLS)
|
||||
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_MBED_TLS)
|
||||
elseif (USE_OPEN_SSL)
|
||||
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_OPEN_SSL)
|
||||
elseif (USE_SECURE_TRANSPORT)
|
||||
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_SECURE_TRANSPORT)
|
||||
else()
|
||||
message(FATAL_ERROR "TLS Configuration error: unknown backend")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (APPLE AND USE_TLS AND NOT USE_MBED_TLS AND NOT USE_OPEN_SSL)
|
||||
target_link_libraries(ixwebsocket "-framework foundation" "-framework security")
|
||||
endif()
|
||||
if (USE_TLS)
|
||||
if (USE_OPEN_SSL)
|
||||
message(STATUS "TLS configured to use openssl")
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(ixwebsocket wsock32 ws2_32 shlwapi)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
# Help finding Homebrew's OpenSSL on macOS
|
||||
if (APPLE)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /usr/local/opt/openssl/lib)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr/local/opt/openssl/include)
|
||||
endif()
|
||||
|
||||
if (UNIX)
|
||||
find_package(Threads)
|
||||
target_link_libraries(ixwebsocket ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
# This OPENSSL_FOUND check is to help find a cmake manually configured OpenSSL
|
||||
if (NOT OPENSSL_FOUND)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
message(STATUS "OpenSSL: " ${OPENSSL_VERSION})
|
||||
|
||||
if (USE_TLS AND USE_OPEN_SSL)
|
||||
add_definitions(${OPENSSL_DEFINITIONS})
|
||||
target_include_directories(ixwebsocket PUBLIC ${OPENSSL_INCLUDE_DIR})
|
||||
target_link_libraries(ixwebsocket ${OPENSSL_LIBRARIES})
|
||||
elseif (USE_MBED_TLS)
|
||||
message(STATUS "TLS configured to use mbedtls")
|
||||
|
||||
# Help finding Homebrew's OpenSSL on macOS
|
||||
if (APPLE)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /usr/local/opt/openssl/lib)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr/local/opt/openssl/include)
|
||||
endif()
|
||||
|
||||
if(NOT OPENSSL_FOUND)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
add_definitions(${OPENSSL_DEFINITIONS})
|
||||
message(STATUS "OpenSSL: " ${OPENSSL_VERSION})
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
target_link_libraries(ixwebsocket ${OPENSSL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (USE_TLS AND USE_MBED_TLS)
|
||||
# FIXME I'm not too sure that this USE_VENDORED_THIRD_PARTY thing works
|
||||
if (USE_VENDORED_THIRD_PARTY)
|
||||
set (ENABLE_PROGRAMS OFF)
|
||||
add_subdirectory(third_party/mbedtls)
|
||||
include_directories(third_party/mbedtls/include)
|
||||
|
||||
target_link_libraries(ixwebsocket mbedtls)
|
||||
else()
|
||||
find_package(MbedTLS REQUIRED)
|
||||
target_include_directories(ixwebsocket PUBLIC ${MBEDTLS_INCLUDE_DIRS})
|
||||
target_link_libraries(ixwebsocket ${MBEDTLS_LIBRARIES})
|
||||
elseif (USE_SECURE_TRANSPORT)
|
||||
message(STATUS "TLS configured to use secure transport")
|
||||
target_link_libraries(ixwebsocket "-framework foundation" "-framework security")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This ZLIB_FOUND check is to help find a cmake manually configured zlib
|
||||
if (NOT ZLIB_FOUND)
|
||||
find_package(ZLIB)
|
||||
endif()
|
||||
@ -211,6 +201,21 @@ else()
|
||||
target_link_libraries(ixwebsocket zlibstatic)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(ixwebsocket wsock32 ws2_32 shlwapi)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if (USE_TLS)
|
||||
target_link_libraries(ixwebsocket Crypt32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (UNIX)
|
||||
find_package(Threads)
|
||||
target_link_libraries(ixwebsocket ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
|
||||
set( IXWEBSOCKET_INCLUDE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
@ -1,6 +1,58 @@
|
||||
# Changelog
|
||||
All changes to this project will be documented in this file.
|
||||
|
||||
## [9.5.2] - 2020-04-27
|
||||
|
||||
(cmake) fix cmake broken tls option parsing
|
||||
|
||||
## [9.5.1] - 2020-04-27
|
||||
|
||||
(http client) Set default values for most HttpRequestArgs struct members (fix #185)
|
||||
|
||||
## [9.5.0] - 2020-04-25
|
||||
|
||||
(ssl) Default to OpenSSL on Windows, since it can load the system certificates by default
|
||||
|
||||
## [9.4.1] - 2020-04-25
|
||||
|
||||
(header) Add a space between header name and header value since most http parsers expects it, although it it not required. Cf #184 and #155
|
||||
|
||||
## [9.4.0] - 2020-04-24
|
||||
|
||||
(ssl) Add support for supplying SSL CA from memory, for OpenSSL and MbedTLS backends
|
||||
|
||||
## [9.3.3] - 2020-04-17
|
||||
|
||||
(ixbots) display sent/receive message, per seconds as accumulated
|
||||
|
||||
## [9.3.2] - 2020-04-17
|
||||
|
||||
(ws) add a --logfile option to configure all logs to go to a file
|
||||
|
||||
## [9.3.1] - 2020-04-16
|
||||
|
||||
(cobra bots) add a utility class to factor out the common bots features (heartbeat) and move all bots to used it + convert cobra_subscribe to be a bot and add a unittest for it
|
||||
|
||||
## [9.3.0] - 2020-04-15
|
||||
|
||||
(websocket) add a positive number to the heartbeat message sent, incremented each time the heartbeat is sent
|
||||
|
||||
## [9.2.9] - 2020-04-15
|
||||
|
||||
(ixcobra) change cobra event callback to use a struct instead of several objects, which is more flexible/extensible
|
||||
|
||||
## [9.2.8] - 2020-04-15
|
||||
|
||||
(ixcobra) make CobraConnection_EventType an enum class (CobraEventType)
|
||||
|
||||
## [9.2.7] - 2020-04-14
|
||||
|
||||
(ixsentry) add a library method to upload a payload directly to sentry
|
||||
|
||||
## [9.2.6] - 2020-04-14
|
||||
|
||||
(ixcobra) snake server / handle invalid incoming json messages + cobra subscriber in fluentd mode insert a created_at timestamp entry
|
||||
|
||||
## [9.2.5] - 2020-04-13
|
||||
|
||||
(websocket) WebSocketMessagePtr is a unique_ptr instead of a shared_ptr
|
||||
|
@ -18,10 +18,12 @@ There is a unittest which can be executed by typing `make test`.
|
||||
Options for building:
|
||||
|
||||
* `-DUSE_TLS=1` will enable TLS support
|
||||
* `-DUSE_MBED_TLS=1` will use [mbedlts](https://tls.mbed.org/) for the TLS support (default on Windows)
|
||||
* `-DUSE_OPEN_SSL=1` will use [openssl](https://www.openssl.org/) for the TLS support (default on Linux and Windows)
|
||||
* `-DUSE_MBED_TLS=1` will use [mbedlts](https://tls.mbed.org/) for the TLS support
|
||||
* `-DUSE_WS=1` will build the ws interactive command line tool
|
||||
* `-DUSE_TEST=1` will build the unittest
|
||||
|
||||
If you are on Windows, look at the [appveyor](https://github.com/machinezone/IXWebSocket/blob/master/appveyor.yml) file that has instructions for building dependencies.
|
||||
If you are on Windows, look at the [appveyor](https://github.com/machinezone/IXWebSocket/blob/master/appveyor.yml) file (not maintained much though) or rather the [github actions](https://github.com/machinezone/IXWebSocket/blob/master/.github/workflows/ccpp.yml#L40) which have instructions for building dependencies.
|
||||
|
||||
It is also possible to externally include the project, so that everything is fetched over the wire when you build like so:
|
||||
|
||||
@ -59,7 +61,7 @@ Note that the version listed here might not be the latest one. See Bintray or th
|
||||
There is a Dockerfile for running the unittest on Linux, and to run the `ws` tool. It is also available on the docker registry.
|
||||
|
||||
```
|
||||
docker run bsergean/ws
|
||||
docker run docker.pkg.github.com/machinezone/ixwebsocket/ws:latest --help
|
||||
```
|
||||
|
||||
To use docker-compose you must make a docker container first.
|
||||
|
@ -38,8 +38,7 @@ The regression test is running after each commit on github actions for multiple
|
||||
|
||||
## Limitations
|
||||
|
||||
* On Windows and Android certificate validation needs to be setup so that SocketTLSOptions.caFile point to a pem file, such as the one distributed by Firefox. Unless that setup is done connecting to a wss endpoint will display an error. On Windows with mbedtls the message will contain `error in handshake : X509 - Certificate verification failed, e.g. CRL, CA or signature check failed`.
|
||||
* There is no convenient way to embed a ca cert.
|
||||
* On some configuration (mostly Android) certificate validation needs to be setup so that SocketTLSOptions.caFile point to a pem file, such as the one distributed by Firefox. Unless that setup is done connecting to a wss endpoint will display an error. With mbedtls the message will contain `error in handshake : X509 - Certificate verification failed, e.g. CRL, CA or signature check failed`.
|
||||
* Automatic reconnection works at the TCP socket level, and will detect remote end disconnects. However, if the device/computer network become unreachable (by turning off wifi), it is quite hard to reliably and timely detect it at the socket level using `recv` and `send` error codes. [Here](https://stackoverflow.com/questions/14782143/linux-socket-how-to-detect-disconnected-network-in-a-client-program) is a good discussion on the subject. This behavior is consistent with other runtimes such as node.js. One way to detect a disconnected device with low level C code is to do a name resolution with DNS but this can be expensive. Mobile devices have good and reliable API to do that.
|
||||
* The server code is using select to detect incoming data, and creates one OS thread per connection. This is not as scalable as strategies using epoll or kqueue.
|
||||
|
||||
|
@ -4,7 +4,7 @@ Notes on how we can update the different packages for ixwebsocket.
|
||||
|
||||
Visit the [releases](https://github.com/machinezone/IXWebSocket/releases) page on Github. A tag must have been made first.
|
||||
|
||||
Download the latest entry.
|
||||
Download the latest entry.
|
||||
|
||||
```
|
||||
$ cd /tmp
|
||||
|
@ -447,7 +447,7 @@ Additional TLS options can be configured by passing a `ix::SocketTLSOptions` ins
|
||||
webSocket.setTLSOptions({
|
||||
.certFile = "path/to/cert/file.pem",
|
||||
.keyFile = "path/to/key/file.pem",
|
||||
.caFile = "path/to/trust/bundle/file.pem",
|
||||
.caFile = "path/to/trust/bundle/file.pem", // as a file, or in memory buffer in PEM format
|
||||
.tls = true // required in server mode
|
||||
});
|
||||
```
|
||||
@ -461,6 +461,7 @@ On a server, this is necessary for TLS support.
|
||||
Specifying `caFile` configures the trusted roots bundle file (in PEM format) that will be used to verify peer certificates.
|
||||
- The special value of `SYSTEM` (the default) indicates that the system-configured trust bundle should be used; this is generally what you want when connecting to any publicly exposed API/server.
|
||||
- The special value of `NONE` can be used to disable peer verification; this is only recommended to rule out certificate verification when testing connectivity.
|
||||
- If the value contain the special value `-----BEGIN CERTIFICATE-----`, the value will be read from memory, and not from a file. This is convenient on platforms like Android where reading / writing to the file system can be challenging without proper permissions, or without knowing the location of a temp directory.
|
||||
|
||||
For a client, specifying `caFile` can be used if connecting to a server that uses a self-signed cert, or when using a custom CA in an internal environment.
|
||||
|
||||
|
@ -4,15 +4,19 @@
|
||||
#
|
||||
|
||||
set (IXBOTS_SOURCES
|
||||
ixbots/IXCobraBot.cpp
|
||||
ixbots/IXCobraToSentryBot.cpp
|
||||
ixbots/IXCobraToStatsdBot.cpp
|
||||
ixbots/IXCobraToStdoutBot.cpp
|
||||
ixbots/IXQueueManager.cpp
|
||||
ixbots/IXStatsdClient.cpp
|
||||
)
|
||||
|
||||
set (IXBOTS_HEADERS
|
||||
ixbots/IXCobraBot.h
|
||||
ixbots/IXCobraToSentryBot.h
|
||||
ixbots/IXCobraToStatsdBot.h
|
||||
ixbots/IXCobraToStdoutBot.h
|
||||
ixbots/IXQueueManager.h
|
||||
ixbots/IXStatsdClient.h
|
||||
)
|
||||
@ -27,11 +31,6 @@ if (NOT JSONCPP_FOUND)
|
||||
set(JSONCPP_INCLUDE_DIRS ../third_party/jsoncpp)
|
||||
endif()
|
||||
|
||||
find_package(SpdLog)
|
||||
if (NOT SPDLOG_FOUND)
|
||||
set(SPDLOG_INCLUDE_DIRS ../third_party/spdlog/include)
|
||||
endif()
|
||||
|
||||
set(IXBOTS_INCLUDE_DIRS
|
||||
.
|
||||
..
|
||||
|
321
ixbots/ixbots/IXCobraBot.cpp
Normal file
321
ixbots/ixbots/IXCobraBot.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* IXCobraBot.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
|
||||
#include "IXQueueManager.h"
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int64_t CobraBot::run(const CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool useQueue,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
ix::CobraConnection conn;
|
||||
conn.configure(config);
|
||||
conn.connect();
|
||||
|
||||
Json::FastWriter jsonWriter;
|
||||
std::atomic<uint64_t> sentCount(0);
|
||||
std::atomic<uint64_t> receivedCount(0);
|
||||
uint64_t sentCountTotal(0);
|
||||
uint64_t receivedCountTotal(0);
|
||||
uint64_t sentCountPerSecs(0);
|
||||
uint64_t receivedCountPerSecs(0);
|
||||
std::atomic<bool> stop(false);
|
||||
std::atomic<bool> throttled(false);
|
||||
std::atomic<bool> fatalCobraError(false);
|
||||
|
||||
QueueManager queueManager(maxQueueSize);
|
||||
|
||||
auto timer = [&sentCount,
|
||||
&receivedCount,
|
||||
&sentCountTotal,
|
||||
&receivedCountTotal,
|
||||
&sentCountPerSecs,
|
||||
&receivedCountPerSecs,
|
||||
&stop] {
|
||||
while (!stop)
|
||||
{
|
||||
//
|
||||
// We cannot write to sentCount and receivedCount
|
||||
// as those are used externally, so we need to introduce
|
||||
// our own counters
|
||||
//
|
||||
std::stringstream ss;
|
||||
ss << "messages received "
|
||||
<< receivedCountPerSecs
|
||||
<< " "
|
||||
<< receivedCountTotal
|
||||
<< " sent "
|
||||
<< sentCountPerSecs
|
||||
<< " "
|
||||
<< sentCountTotal;
|
||||
CoreLogger::info(ss.str());
|
||||
|
||||
receivedCountPerSecs = receivedCount - receivedCountTotal;
|
||||
sentCountPerSecs = sentCount - receivedCountTotal;
|
||||
|
||||
receivedCountTotal += receivedCountPerSecs;
|
||||
sentCountTotal += sentCountPerSecs;
|
||||
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
}
|
||||
|
||||
CoreLogger::info("timer thread done");
|
||||
};
|
||||
|
||||
std::thread t1(timer);
|
||||
|
||||
auto heartbeat = [&sentCount, &receivedCount, &stop, &enableHeartbeat] {
|
||||
std::string state("na");
|
||||
|
||||
if (!enableHeartbeat) return;
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "messages received " << receivedCount;
|
||||
ss << "messages sent " << sentCount;
|
||||
|
||||
std::string currentState = ss.str();
|
||||
|
||||
if (currentState == state)
|
||||
{
|
||||
CoreLogger::error("no messages received or sent for 1 minute, exiting");
|
||||
exit(1);
|
||||
}
|
||||
state = currentState;
|
||||
|
||||
auto duration = std::chrono::minutes(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
}
|
||||
|
||||
CoreLogger::info("heartbeat thread done");
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
conn.setEventCallback([this,
|
||||
&conn,
|
||||
&channel,
|
||||
&filter,
|
||||
&subscriptionPosition,
|
||||
&jsonWriter,
|
||||
verbose,
|
||||
&throttled,
|
||||
&receivedCount,
|
||||
&fatalCobraError,
|
||||
&useQueue,
|
||||
&queueManager,
|
||||
&sentCount](const CobraEventPtr& event) {
|
||||
if (event->type == ix::CobraEventType::Open)
|
||||
{
|
||||
CoreLogger::info("Subscriber connected");
|
||||
|
||||
for (auto&& it : event->headers)
|
||||
{
|
||||
CoreLogger::info(it.first + "::" + it.second);
|
||||
}
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Closed)
|
||||
{
|
||||
CoreLogger::info("Subscriber closed: {}" + event->errMsg);
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Authenticated)
|
||||
{
|
||||
CoreLogger::info("Subscriber authenticated");
|
||||
CoreLogger::info("Subscribing to " + channel);
|
||||
CoreLogger::info("Subscribing at position " + subscriptionPosition);
|
||||
CoreLogger::info("Subscribing with filter " + filter);
|
||||
conn.subscribe(channel,
|
||||
filter,
|
||||
subscriptionPosition,
|
||||
[this,
|
||||
&jsonWriter,
|
||||
verbose,
|
||||
&throttled,
|
||||
&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;
|
||||
|
||||
// If we cannot send to sentry fast enough, drop the message
|
||||
if (throttled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++receivedCount;
|
||||
|
||||
if (useQueue)
|
||||
{
|
||||
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)
|
||||
{
|
||||
CoreLogger::info("Subscriber: subscribed to channel " + event->subscriptionId);
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::UnSubscribed)
|
||||
{
|
||||
CoreLogger::info("Subscriber: unsubscribed from channel " + event->subscriptionId);
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Error)
|
||||
{
|
||||
CoreLogger::error("Subscriber: error " + event->errMsg);
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Published)
|
||||
{
|
||||
CoreLogger::error("Published message hacked: " + std::to_string(event->msgId));
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Pong)
|
||||
{
|
||||
CoreLogger::info("Received websocket pong: " + event->errMsg);
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::HandshakeError)
|
||||
{
|
||||
CoreLogger::error("Subscriber: Handshake error: " + event->errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::AuthenticationError)
|
||||
{
|
||||
CoreLogger::error("Subscriber: Authentication error: " + event->errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::SubscriptionError)
|
||||
{
|
||||
CoreLogger::error("Subscriber: Subscription error: " + event->errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Run forever
|
||||
if (runtime == -1)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
|
||||
if (fatalCobraError) break;
|
||||
}
|
||||
}
|
||||
// Run for a duration, used by unittesting now
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < runtime; ++i)
|
||||
{
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
|
||||
if (fatalCobraError) break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Cleanup.
|
||||
// join all the bg threads and stop them.
|
||||
//
|
||||
conn.disconnect();
|
||||
stop = true;
|
||||
|
||||
// progress thread
|
||||
t1.join();
|
||||
|
||||
// heartbeat thread
|
||||
if (t2.joinable()) t2.join();
|
||||
|
||||
// sentry sender thread
|
||||
t3.join();
|
||||
|
||||
return fatalCobraError ? -1 : (int64_t) sentCount;
|
||||
}
|
||||
|
||||
void CobraBot::setOnBotMessageCallback(const OnBotMessageCallback& callback)
|
||||
{
|
||||
_onBotMessageCallback = callback;
|
||||
}
|
||||
} // namespace ix
|
43
ixbots/ixbots/IXCobraBot.h
Normal file
43
ixbots/ixbots/IXCobraBot.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* IXCobraBot.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <ixcobra/IXCobraConfig.h>
|
||||
#include <json/json.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
using OnBotMessageCallback = std::function<bool(const Json::Value&,
|
||||
const std::string&,
|
||||
const bool verbose,
|
||||
std::atomic<bool>&,
|
||||
std::atomic<bool>&)>;
|
||||
|
||||
class CobraBot
|
||||
{
|
||||
public:
|
||||
CobraBot() = default;
|
||||
|
||||
int64_t run(const CobraConfig& config,
|
||||
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);
|
||||
|
||||
private:
|
||||
OnBotMessageCallback _onBotMessageCallback;
|
||||
};
|
||||
} // namespace ix
|
@ -5,301 +5,113 @@
|
||||
*/
|
||||
|
||||
#include "IXCobraToSentryBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXQueueManager.h"
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int cobra_to_sentry_bot(const CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
SentryClient& sentryClient,
|
||||
bool verbose,
|
||||
bool strict,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
int64_t cobra_to_sentry_bot(const CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
SentryClient& sentryClient,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
ix::CobraConnection conn;
|
||||
conn.configure(config);
|
||||
conn.connect();
|
||||
CobraBot bot;
|
||||
bot.setOnBotMessageCallback([&sentryClient](const Json::Value& msg,
|
||||
const std::string& /*position*/,
|
||||
const bool verbose,
|
||||
std::atomic<bool>& throttled,
|
||||
std::atomic<bool> &
|
||||
/*fatalCobraError*/) -> bool {
|
||||
auto ret = sentryClient.send(msg, verbose);
|
||||
HttpResponsePtr response = ret.first;
|
||||
|
||||
Json::FastWriter jsonWriter;
|
||||
std::atomic<uint64_t> sentCount(0);
|
||||
std::atomic<uint64_t> receivedCount(0);
|
||||
std::atomic<bool> errorSending(false);
|
||||
std::atomic<bool> stop(false);
|
||||
std::atomic<bool> throttled(false);
|
||||
std::atomic<bool> fatalCobraError(false);
|
||||
|
||||
QueueManager queueManager(maxQueueSize);
|
||||
|
||||
auto timer = [&sentCount, &receivedCount, &stop] {
|
||||
while (!stop)
|
||||
if (!response)
|
||||
{
|
||||
spdlog::info("messages received {} sent {}", receivedCount, sentCount);
|
||||
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
CoreLogger::warn("Null HTTP Response");
|
||||
return false;
|
||||
}
|
||||
|
||||
spdlog::info("timer thread done");
|
||||
};
|
||||
|
||||
std::thread t1(timer);
|
||||
|
||||
auto heartbeat = [&sentCount, &receivedCount, &stop, &enableHeartbeat] {
|
||||
std::string state("na");
|
||||
|
||||
if (!enableHeartbeat) return;
|
||||
|
||||
while (!stop)
|
||||
if (verbose)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "messages received " << receivedCount;
|
||||
ss << "messages sent " << sentCount;
|
||||
|
||||
std::string currentState = ss.str();
|
||||
|
||||
if (currentState == state)
|
||||
for (auto it : response->headers)
|
||||
{
|
||||
spdlog::error("no messages received or sent for 1 minute, exiting");
|
||||
exit(1);
|
||||
}
|
||||
state = currentState;
|
||||
|
||||
auto duration = std::chrono::minutes(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
}
|
||||
|
||||
spdlog::info("heartbeat thread done");
|
||||
};
|
||||
|
||||
std::thread t2(heartbeat);
|
||||
|
||||
auto sentrySender =
|
||||
[&queueManager, verbose, &errorSending, &sentCount, &stop, &throttled, &sentryClient] {
|
||||
|
||||
while (true)
|
||||
{
|
||||
Json::Value msg = queueManager.pop();
|
||||
|
||||
if (stop) break;
|
||||
if (msg.isNull()) continue;
|
||||
|
||||
auto ret = sentryClient.send(msg, verbose);
|
||||
HttpResponsePtr response = ret.first;
|
||||
|
||||
if (!response)
|
||||
{
|
||||
spdlog::warn("Null HTTP Response");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
for (auto it : response->headers)
|
||||
{
|
||||
spdlog::info("{}: {}", it.first, it.second);
|
||||
}
|
||||
|
||||
spdlog::info("Upload size: {}", response->uploadSize);
|
||||
spdlog::info("Download size: {}", response->downloadSize);
|
||||
|
||||
spdlog::info("Status: {}", response->statusCode);
|
||||
if (response->errorCode != HttpErrorCode::Ok)
|
||||
{
|
||||
spdlog::info("error message: {}", response->errorMsg);
|
||||
}
|
||||
|
||||
if (response->headers["Content-Type"] != "application/octet-stream")
|
||||
{
|
||||
spdlog::info("payload: {}", response->payload);
|
||||
}
|
||||
}
|
||||
|
||||
if (response->statusCode != 200)
|
||||
{
|
||||
spdlog::error("Error sending data to sentry: {}", response->statusCode);
|
||||
spdlog::error("Body: {}", ret.second);
|
||||
spdlog::error("Response: {}", response->payload);
|
||||
errorSending = true;
|
||||
|
||||
// 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;
|
||||
spdlog::warn("Error parsing Retry-After header. "
|
||||
"Using {} for the sleep duration",
|
||||
seconds);
|
||||
}
|
||||
|
||||
spdlog::warn("Error 429 - Too Many Requests. ws will sleep "
|
||||
"and retry after {} seconds",
|
||||
retryAfter);
|
||||
|
||||
throttled = true;
|
||||
auto duration = std::chrono::seconds(seconds);
|
||||
std::this_thread::sleep_for(duration);
|
||||
throttled = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++sentCount;
|
||||
}
|
||||
|
||||
if (stop) break;
|
||||
CoreLogger::info(it.first + ": " + it.second);
|
||||
}
|
||||
|
||||
spdlog::info("sentrySender thread done");
|
||||
};
|
||||
CoreLogger::info("Upload size: " + std::to_string(response->uploadSize));
|
||||
CoreLogger::info("Download size: " + std::to_string(response->downloadSize));
|
||||
|
||||
std::thread t3(sentrySender);
|
||||
|
||||
conn.setEventCallback([&conn,
|
||||
&channel,
|
||||
&filter,
|
||||
&position,
|
||||
&jsonWriter,
|
||||
verbose,
|
||||
&throttled,
|
||||
&receivedCount,
|
||||
&fatalCobraError,
|
||||
&queueManager](ix::CobraConnectionEventType eventType,
|
||||
const std::string& errMsg,
|
||||
const ix::WebSocketHttpHeaders& headers,
|
||||
const std::string& subscriptionId,
|
||||
CobraConnection::MsgId msgId) {
|
||||
if (eventType == ix::CobraConnection_EventType_Open)
|
||||
{
|
||||
spdlog::info("Subscriber connected");
|
||||
|
||||
for (auto it : headers)
|
||||
CoreLogger::info("Status: " + std::to_string(response->statusCode));
|
||||
if (response->errorCode != HttpErrorCode::Ok)
|
||||
{
|
||||
spdlog::info("{}: {}", it.first, it.second);
|
||||
CoreLogger::info("error message: " + response->errorMsg);
|
||||
}
|
||||
|
||||
if (response->headers["Content-Type"] != "application/octet-stream")
|
||||
{
|
||||
CoreLogger::info("payload: " + response->payload);
|
||||
}
|
||||
}
|
||||
if (eventType == ix::CobraConnection_EventType_Closed)
|
||||
{
|
||||
spdlog::info("Subscriber closed");
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
||||
{
|
||||
spdlog::info("Subscriber authenticated");
|
||||
conn.subscribe(channel,
|
||||
filter,
|
||||
position,
|
||||
[&jsonWriter, verbose, &throttled, &receivedCount, &queueManager](
|
||||
const Json::Value& msg, const std::string& position) {
|
||||
if (verbose)
|
||||
{
|
||||
spdlog::info("Subscriber received message {} -> {}", position, jsonWriter.write(msg));
|
||||
}
|
||||
|
||||
// If we cannot send to sentry fast enough, drop the message
|
||||
if (throttled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool success = response->statusCode == 200;
|
||||
|
||||
++receivedCount;
|
||||
queueManager.add(msg);
|
||||
});
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
||||
if (!success)
|
||||
{
|
||||
spdlog::info("Subscriber: subscribed to channel {}", subscriptionId);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
||||
{
|
||||
spdlog::info("Subscriber: unsubscribed from channel {}", subscriptionId);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: error {}", errMsg);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Published)
|
||||
{
|
||||
spdlog::error("Published message hacked: {}", msgId);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Pong)
|
||||
{
|
||||
spdlog::info("Received websocket pong");
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Handshake_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: Handshake error: {}", errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Authentication_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: Authentication error: {}", errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Subscription_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: Subscription error: {}", errMsg);
|
||||
fatalCobraError = true;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
});
|
||||
|
||||
// Run forever
|
||||
if (runtime == -1)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
bool useQueue = true;
|
||||
|
||||
if (strict && errorSending) break;
|
||||
if (fatalCobraError) break;
|
||||
}
|
||||
}
|
||||
// Run for a duration, used by unittesting now
|
||||
else
|
||||
{
|
||||
for (int i = 0 ; i < runtime; ++i)
|
||||
{
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
|
||||
if (strict && errorSending) break;
|
||||
if (fatalCobraError) break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Cleanup.
|
||||
// join all the bg threads and stop them.
|
||||
//
|
||||
conn.disconnect();
|
||||
stop = true;
|
||||
|
||||
// progress thread
|
||||
t1.join();
|
||||
|
||||
// heartbeat thread
|
||||
if (t2.joinable()) t2.join();
|
||||
|
||||
// sentry sender thread
|
||||
t3.join();
|
||||
|
||||
return ((strict && errorSending) || fatalCobraError) ? -1 : (int) sentCount;
|
||||
return bot.run(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
useQueue,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
}
|
||||
} // namespace ix
|
||||
|
@ -5,20 +5,20 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <ixcobra/IXCobraConfig.h>
|
||||
#include <ixsentry/IXSentryClient.h>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int cobra_to_sentry_bot(const CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
SentryClient& sentryClient,
|
||||
bool verbose,
|
||||
bool strict,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
int64_t cobra_to_sentry_bot(const CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
SentryClient& sentryClient,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
} // namespace ix
|
||||
|
@ -5,16 +5,14 @@
|
||||
*/
|
||||
|
||||
#include "IXCobraToStatsdBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXQueueManager.h"
|
||||
#include "IXStatsdClient.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace ix
|
||||
@ -56,18 +54,18 @@ namespace ix
|
||||
return val;
|
||||
}
|
||||
|
||||
int cobra_to_statsd_bot(const ix::CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
StatsdClient& statsdClient,
|
||||
const std::string& fields,
|
||||
const std::string& gauge,
|
||||
const std::string& timer,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
int64_t cobra_to_statsd_bot(const ix::CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
StatsdClient& statsdClient,
|
||||
const std::string& fields,
|
||||
const std::string& gauge,
|
||||
const std::string& timer,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
ix::CobraConnection conn;
|
||||
conn.configure(config);
|
||||
@ -75,65 +73,13 @@ namespace ix
|
||||
|
||||
auto tokens = parseFields(fields);
|
||||
|
||||
Json::FastWriter jsonWriter;
|
||||
std::atomic<uint64_t> sentCount(0);
|
||||
std::atomic<uint64_t> receivedCount(0);
|
||||
std::atomic<bool> stop(false);
|
||||
std::atomic<bool> fatalCobraError(false);
|
||||
|
||||
QueueManager queueManager(maxQueueSize);
|
||||
|
||||
auto progress = [&sentCount, &receivedCount, &stop] {
|
||||
while (!stop)
|
||||
{
|
||||
spdlog::info("messages received {} sent {}", receivedCount, sentCount);
|
||||
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
}
|
||||
|
||||
spdlog::info("timer thread done");
|
||||
};
|
||||
|
||||
std::thread t1(progress);
|
||||
|
||||
auto heartbeat = [&sentCount, &receivedCount, &stop, &enableHeartbeat] {
|
||||
std::string state("na");
|
||||
|
||||
if (!enableHeartbeat) return;
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "messages received " << receivedCount;
|
||||
ss << "messages sent " << sentCount;
|
||||
|
||||
std::string currentState = ss.str();
|
||||
|
||||
if (currentState == state)
|
||||
{
|
||||
spdlog::error("no messages received or sent for 1 minute, exiting");
|
||||
exit(1);
|
||||
}
|
||||
state = currentState;
|
||||
|
||||
auto duration = std::chrono::minutes(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
}
|
||||
|
||||
spdlog::info("heartbeat thread done");
|
||||
};
|
||||
|
||||
std::thread t2(heartbeat);
|
||||
|
||||
auto statsdSender = [&statsdClient, &queueManager, &sentCount, &tokens, &stop, &gauge, &timer, &fatalCobraError, &verbose] {
|
||||
while (true)
|
||||
{
|
||||
Json::Value msg = queueManager.pop();
|
||||
|
||||
if (stop) return;
|
||||
if (msg.isNull()) continue;
|
||||
|
||||
CobraBot bot;
|
||||
bot.setOnBotMessageCallback(
|
||||
[&statsdClient, &tokens, &gauge, &timer](const Json::Value& msg,
|
||||
const std::string& /*position*/,
|
||||
const bool verbose,
|
||||
std::atomic<bool>& /*throttled*/,
|
||||
std::atomic<bool>& fatalCobraError) -> bool {
|
||||
std::string id;
|
||||
for (auto&& attr : tokens)
|
||||
{
|
||||
@ -174,14 +120,14 @@ namespace ix
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::error("Gauge {} is not a numberic type", gauge);
|
||||
CoreLogger::error("Gauge " + gauge + " is not a numeric type");
|
||||
fatalCobraError = true;
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
spdlog::info("{} - {} -> {}", id, attrName, x);
|
||||
CoreLogger::info(id + " - " + attrName + " -> " + std::to_string(x));
|
||||
}
|
||||
|
||||
if (!gauge.empty())
|
||||
@ -194,127 +140,19 @@ namespace ix
|
||||
}
|
||||
}
|
||||
|
||||
sentCount += 1;
|
||||
}
|
||||
};
|
||||
|
||||
std::thread t3(statsdSender);
|
||||
|
||||
conn.setEventCallback(
|
||||
[&conn, &channel, &filter, &position, &jsonWriter, verbose, &queueManager, &receivedCount, &fatalCobraError](
|
||||
ix::CobraConnectionEventType eventType,
|
||||
const std::string& errMsg,
|
||||
const ix::WebSocketHttpHeaders& headers,
|
||||
const std::string& subscriptionId,
|
||||
CobraConnection::MsgId msgId) {
|
||||
if (eventType == ix::CobraConnection_EventType_Open)
|
||||
{
|
||||
spdlog::info("Subscriber connected");
|
||||
|
||||
for (auto it : headers)
|
||||
{
|
||||
spdlog::info("{}: {}", it.first, it.second);
|
||||
}
|
||||
}
|
||||
if (eventType == ix::CobraConnection_EventType_Closed)
|
||||
{
|
||||
spdlog::info("Subscriber closed");
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
||||
{
|
||||
spdlog::info("Subscriber authenticated");
|
||||
conn.subscribe(channel,
|
||||
filter,
|
||||
position,
|
||||
[&jsonWriter, &queueManager, verbose, &receivedCount](
|
||||
const Json::Value& msg, const std::string& position) {
|
||||
if (verbose)
|
||||
{
|
||||
spdlog::info("Subscriber received message {} -> {}", position, jsonWriter.write(msg));
|
||||
}
|
||||
|
||||
receivedCount++;
|
||||
|
||||
++receivedCount;
|
||||
queueManager.add(msg);
|
||||
});
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
||||
{
|
||||
spdlog::info("Subscriber: subscribed to channel {}", subscriptionId);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
||||
{
|
||||
spdlog::info("Subscriber: unsubscribed from channel {}", subscriptionId);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: error {}", errMsg);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Published)
|
||||
{
|
||||
spdlog::error("Published message hacked: {}", msgId);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Pong)
|
||||
{
|
||||
spdlog::info("Received websocket pong");
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Handshake_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: Handshake error: {}", errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Authentication_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: Authentication error: {}", errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Subscription_Error)
|
||||
{
|
||||
spdlog::error("Subscriber: Subscription error: {}", errMsg);
|
||||
fatalCobraError = true;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Run forever
|
||||
if (runtime == -1)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
bool useQueue = true;
|
||||
|
||||
if (fatalCobraError) break;
|
||||
}
|
||||
}
|
||||
// Run for a duration, used by unittesting now
|
||||
else
|
||||
{
|
||||
for (int i = 0 ; i < runtime; ++i)
|
||||
{
|
||||
auto duration = std::chrono::seconds(1);
|
||||
std::this_thread::sleep_for(duration);
|
||||
|
||||
if (fatalCobraError) break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Cleanup.
|
||||
// join all the bg threads and stop them.
|
||||
//
|
||||
conn.disconnect();
|
||||
stop = true;
|
||||
|
||||
// progress thread
|
||||
t1.join();
|
||||
|
||||
// heartbeat thread
|
||||
if (t2.joinable()) t2.join();
|
||||
|
||||
// statsd sender thread
|
||||
t3.join();
|
||||
|
||||
return fatalCobraError ? -1 : (int) sentCount;
|
||||
return bot.run(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
useQueue,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
}
|
||||
} // namespace ix
|
||||
|
@ -5,23 +5,24 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ixcobra/IXCobraConfig.h>
|
||||
#include <cstdint>
|
||||
#include <ixbots/IXStatsdClient.h>
|
||||
#include <string>
|
||||
#include <ixcobra/IXCobraConfig.h>
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int cobra_to_statsd_bot(const ix::CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
StatsdClient& statsdClient,
|
||||
const std::string& fields,
|
||||
const std::string& gauge,
|
||||
const std::string& timer,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
int64_t cobra_to_statsd_bot(const ix::CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
StatsdClient& statsdClient,
|
||||
const std::string& fields,
|
||||
const std::string& gauge,
|
||||
const std::string& timer,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
} // namespace ix
|
||||
|
107
ixbots/ixbots/IXCobraToStdoutBot.cpp
Normal file
107
ixbots/ixbots/IXCobraToStdoutBot.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* IXCobraToStdoutBot.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXCobraToStdoutBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXQueueManager.h"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
using StreamWriterPtr = std::unique_ptr<Json::StreamWriter>;
|
||||
|
||||
StreamWriterPtr makeStreamWriter()
|
||||
{
|
||||
Json::StreamWriterBuilder builder;
|
||||
builder["commentStyle"] = "None";
|
||||
builder["indentation"] = ""; // will make the JSON object compact
|
||||
std::unique_ptr<Json::StreamWriter> jsonWriter(builder.newStreamWriter());
|
||||
return jsonWriter;
|
||||
}
|
||||
|
||||
std::string timeSinceEpoch()
|
||||
{
|
||||
std::chrono::system_clock::time_point tp = std::chrono::system_clock::now();
|
||||
std::chrono::system_clock::duration dtn = tp.time_since_epoch();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << dtn.count() * std::chrono::system_clock::period::num /
|
||||
std::chrono::system_clock::period::den;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void writeToStdout(bool fluentd,
|
||||
const StreamWriterPtr& jsonWriter,
|
||||
const Json::Value& msg,
|
||||
const std::string& position)
|
||||
{
|
||||
Json::Value enveloppe;
|
||||
if (fluentd)
|
||||
{
|
||||
enveloppe["producer"] = "cobra";
|
||||
enveloppe["consumer"] = "fluentd";
|
||||
|
||||
Json::Value nestedMessage(msg);
|
||||
nestedMessage["position"] = position;
|
||||
nestedMessage["created_at"] = timeSinceEpoch();
|
||||
enveloppe["message"] = nestedMessage;
|
||||
|
||||
jsonWriter->write(enveloppe, &std::cout);
|
||||
std::cout << std::endl; // add lf and flush
|
||||
}
|
||||
else
|
||||
{
|
||||
enveloppe = msg;
|
||||
std::cout << position << " ";
|
||||
jsonWriter->write(enveloppe, &std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t cobra_to_stdout_bot(const CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
bool fluentd,
|
||||
bool quiet,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime)
|
||||
{
|
||||
CobraBot bot;
|
||||
auto jsonWriter = makeStreamWriter();
|
||||
|
||||
bot.setOnBotMessageCallback(
|
||||
[&fluentd, &quiet, &jsonWriter](const Json::Value& msg,
|
||||
const std::string& position,
|
||||
const bool /*verbose*/,
|
||||
std::atomic<bool>& /*throttled*/,
|
||||
std::atomic<bool> &
|
||||
/*fatalCobraError*/) -> bool {
|
||||
if (!quiet)
|
||||
{
|
||||
writeToStdout(fluentd, jsonWriter, msg, position);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
bool useQueue = false;
|
||||
|
||||
return bot.run(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
useQueue,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
}
|
||||
} // namespace ix
|
25
ixbots/ixbots/IXCobraToStdoutBot.h
Normal file
25
ixbots/ixbots/IXCobraToStdoutBot.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* IXCobraToStdoutBot.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <ixcobra/IXCobraConfig.h>
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int64_t cobra_to_stdout_bot(const ix::CobraConfig& config,
|
||||
const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
bool fluentd,
|
||||
bool quiet,
|
||||
bool verbose,
|
||||
size_t maxQueueSize,
|
||||
bool enableHeartbeat,
|
||||
int runtime);
|
||||
} // namespace ix
|
@ -5,19 +5,20 @@
|
||||
*/
|
||||
|
||||
#include "IXQueueManager.h"
|
||||
#include <vector>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
Json::Value QueueManager::pop()
|
||||
std::pair<Json::Value, std::string> QueueManager::pop()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
|
||||
if (_queues.empty())
|
||||
{
|
||||
Json::Value val;
|
||||
return val;
|
||||
return std::make_pair(val, std::string());
|
||||
}
|
||||
|
||||
std::vector<std::string> games;
|
||||
@ -35,7 +36,7 @@ namespace ix
|
||||
if (_queues[game].empty())
|
||||
{
|
||||
Json::Value val;
|
||||
return val;
|
||||
return std::make_pair(val, std::string());
|
||||
}
|
||||
|
||||
auto msg = _queues[game].front();
|
||||
@ -43,7 +44,7 @@ namespace ix
|
||||
return msg;
|
||||
}
|
||||
|
||||
void QueueManager::add(Json::Value msg)
|
||||
void QueueManager::add(const Json::Value& msg, const std::string& position)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
|
||||
@ -59,8 +60,8 @@ namespace ix
|
||||
// in queuing too many events.
|
||||
if (_queues[game].size() < _maxQueueSize)
|
||||
{
|
||||
_queues[game].push(msg);
|
||||
_queues[game].push(std::make_pair(msg, position));
|
||||
_condition.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ix
|
||||
|
@ -6,12 +6,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <json/json.h>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <queue>
|
||||
#include <json/json.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
@ -23,13 +23,13 @@ namespace ix
|
||||
{
|
||||
}
|
||||
|
||||
Json::Value pop();
|
||||
void add(Json::Value msg);
|
||||
std::pair<Json::Value, std::string> pop();
|
||||
void add(const Json::Value& msg, const std::string& position);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::queue<Json::Value>> _queues;
|
||||
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
|
||||
|
@ -39,24 +39,21 @@
|
||||
|
||||
#include "IXStatsdClient.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
StatsdClient::StatsdClient(const std::string& host,
|
||||
int port,
|
||||
const std::string& prefix)
|
||||
: _host(host)
|
||||
, _port(port)
|
||||
, _prefix(prefix)
|
||||
, _stop(false)
|
||||
StatsdClient::StatsdClient(const std::string& host, int port, const std::string& prefix)
|
||||
: _host(host)
|
||||
, _port(port)
|
||||
, _prefix(prefix)
|
||||
, _stop(false)
|
||||
{
|
||||
_thread = std::thread([this]
|
||||
{
|
||||
_thread = std::thread([this] {
|
||||
while (!_stop)
|
||||
{
|
||||
flushQueue();
|
||||
@ -119,8 +116,8 @@ namespace ix
|
||||
cleanup(key);
|
||||
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf), "%s%s:%zd|%s\n",
|
||||
_prefix.c_str(), key.c_str(), value, type.c_str());
|
||||
snprintf(
|
||||
buf, sizeof(buf), "%s%s:%zd|%s\n", _prefix.c_str(), key.c_str(), value, type.c_str());
|
||||
|
||||
enqueue(buf);
|
||||
return 0;
|
||||
@ -142,9 +139,7 @@ namespace ix
|
||||
auto ret = _socket.sendto(message);
|
||||
if (ret != 0)
|
||||
{
|
||||
std::cerr << "error: "
|
||||
<< strerror(UdpSocket::getErrno())
|
||||
<< std::endl;
|
||||
std::cerr << "error: " << strerror(UdpSocket::getErrno()) << std::endl;
|
||||
}
|
||||
_queue.pop_front();
|
||||
}
|
||||
|
@ -6,21 +6,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <ixwebsocket/IXUdpSocket.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
class StatsdClient
|
||||
{
|
||||
public:
|
||||
StatsdClient(const std::string& host="127.0.0.1",
|
||||
int port=8125,
|
||||
StatsdClient(const std::string& host = "127.0.0.1",
|
||||
int port = 8125,
|
||||
const std::string& prefix = "");
|
||||
~StatsdClient();
|
||||
|
||||
|
@ -14,6 +14,7 @@ set (IXCOBRA_HEADERS
|
||||
ixcobra/IXCobraMetricsThreadedPublisher.h
|
||||
ixcobra/IXCobraMetricsPublisher.h
|
||||
ixcobra/IXCobraConfig.h
|
||||
ixcobra/IXCobraEventType.h
|
||||
)
|
||||
|
||||
add_library(ixcobra STATIC
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ixwebsocket/IXWebSocketPerMessageDeflateOptions.h>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <ixwebsocket/IXWebSocketPerMessageDeflateOptions.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
|
@ -5,17 +5,17 @@
|
||||
*/
|
||||
|
||||
#include "IXCobraConnection.h"
|
||||
#include <ixcrypto/IXHMac.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <ixcrypto/IXHMac.h>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace ix
|
||||
@ -26,12 +26,12 @@ namespace ix
|
||||
constexpr CobraConnection::MsgId CobraConnection::kInvalidMsgId;
|
||||
constexpr int CobraConnection::kPingIntervalSecs;
|
||||
|
||||
CobraConnection::CobraConnection() :
|
||||
_webSocket(new WebSocket()),
|
||||
_publishMode(CobraConnection_PublishMode_Immediate),
|
||||
_authenticated(false),
|
||||
_eventCallback(nullptr),
|
||||
_id(1)
|
||||
CobraConnection::CobraConnection()
|
||||
: _webSocket(new WebSocket())
|
||||
, _publishMode(CobraConnection_PublishMode_Immediate)
|
||||
, _authenticated(false)
|
||||
, _eventCallback(nullptr)
|
||||
, _id(1)
|
||||
{
|
||||
_pdu["action"] = "rtm/publish";
|
||||
|
||||
@ -87,7 +87,7 @@ namespace ix
|
||||
_eventCallback = eventCallback;
|
||||
}
|
||||
|
||||
void CobraConnection::invokeEventCallback(ix::CobraConnectionEventType eventType,
|
||||
void CobraConnection::invokeEventCallback(ix::CobraEventType eventType,
|
||||
const std::string& errorMsg,
|
||||
const WebSocketHttpHeaders& headers,
|
||||
const std::string& subscriptionId,
|
||||
@ -96,7 +96,8 @@ namespace ix
|
||||
std::lock_guard<std::mutex> lock(_eventCallbackMutex);
|
||||
if (_eventCallback)
|
||||
{
|
||||
_eventCallback(eventType, errorMsg, headers, subscriptionId, msgId);
|
||||
_eventCallback(
|
||||
std::make_unique<CobraEvent>(eventType, errorMsg, headers, subscriptionId, msgId));
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,7 +106,7 @@ namespace ix
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << errorMsg << " : received pdu => " << serializedPdu;
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Error, ss.str());
|
||||
invokeEventCallback(ix::CobraEventType::Error, ss.str());
|
||||
}
|
||||
|
||||
void CobraConnection::disconnect()
|
||||
@ -116,126 +117,119 @@ namespace ix
|
||||
|
||||
void CobraConnection::initWebSocketOnMessageCallback()
|
||||
{
|
||||
_webSocket->setOnMessageCallback(
|
||||
[this](const ix::WebSocketMessagePtr& msg)
|
||||
_webSocket->setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
|
||||
CobraConnection::invokeTrafficTrackerCallback(msg->wireSize, true);
|
||||
|
||||
std::stringstream ss;
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
CobraConnection::invokeTrafficTrackerCallback(msg->wireSize, true);
|
||||
invokeEventCallback(ix::CobraEventType::Open, std::string(), msg->openInfo.headers);
|
||||
sendHandshakeMessage();
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
_authenticated = false;
|
||||
|
||||
std::stringstream ss;
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
ss << "Close code " << msg->closeInfo.code;
|
||||
ss << " reason " << msg->closeInfo.reason;
|
||||
invokeEventCallback(ix::CobraEventType::Closed, ss.str());
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||
{
|
||||
Json::Value data;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(msg->str, data))
|
||||
{
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Open,
|
||||
std::string(),
|
||||
msg->openInfo.headers);
|
||||
sendHandshakeMessage();
|
||||
invokeErrorCallback("Invalid json", msg->str);
|
||||
return;
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
_authenticated = false;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Close code " << msg->closeInfo.code;
|
||||
ss << " reason " << msg->closeInfo.reason;
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Closed,
|
||||
ss.str());
|
||||
if (!data.isMember("action"))
|
||||
{
|
||||
invokeErrorCallback("Missing action", msg->str);
|
||||
return;
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||
|
||||
auto action = data["action"].asString();
|
||||
|
||||
if (action == "auth/handshake/ok")
|
||||
{
|
||||
Json::Value data;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(msg->str, data))
|
||||
if (!handleHandshakeResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Invalid json", msg->str);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.isMember("action"))
|
||||
{
|
||||
invokeErrorCallback("Missing action", msg->str);
|
||||
return;
|
||||
}
|
||||
|
||||
auto action = data["action"].asString();
|
||||
|
||||
if (action == "auth/handshake/ok")
|
||||
{
|
||||
if (!handleHandshakeResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Error extracting nonce from handshake response", msg->str);
|
||||
}
|
||||
}
|
||||
else if (action == "auth/handshake/error")
|
||||
{
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Handshake_Error,
|
||||
invokeErrorCallback("Error extracting nonce from handshake response",
|
||||
msg->str);
|
||||
}
|
||||
else if (action == "auth/authenticate/ok")
|
||||
{
|
||||
_authenticated = true;
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Authenticated);
|
||||
flushQueue();
|
||||
}
|
||||
else if (action == "auth/authenticate/error")
|
||||
{
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Authentication_Error,
|
||||
msg->str);
|
||||
}
|
||||
else if (action == "rtm/subscription/data")
|
||||
{
|
||||
handleSubscriptionData(data);
|
||||
}
|
||||
else if (action == "rtm/subscribe/ok")
|
||||
{
|
||||
if (!handleSubscriptionResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Error processing subscribe response", msg->str);
|
||||
}
|
||||
}
|
||||
else if (action == "rtm/subscribe/error")
|
||||
{
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Subscription_Error,
|
||||
msg->str);
|
||||
}
|
||||
else if (action == "rtm/unsubscribe/ok")
|
||||
{
|
||||
if (!handleUnsubscriptionResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Error processing unsubscribe response", msg->str);
|
||||
}
|
||||
}
|
||||
else if (action == "rtm/unsubscribe/error")
|
||||
{
|
||||
invokeErrorCallback("Unsubscription error", msg->str);
|
||||
}
|
||||
else if (action == "rtm/publish/ok")
|
||||
{
|
||||
if (!handlePublishResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Error processing publish response", msg->str);
|
||||
}
|
||||
}
|
||||
else if (action == "rtm/publish/error")
|
||||
{
|
||||
invokeErrorCallback("Publish error", msg->str);
|
||||
}
|
||||
else
|
||||
{
|
||||
invokeErrorCallback("Un-handled message type", msg->str);
|
||||
}
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Error)
|
||||
else if (action == "auth/handshake/error")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Connection error: " << msg->errorInfo.reason << std::endl;
|
||||
ss << "#retries: " << msg->errorInfo.retries << std::endl;
|
||||
ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
|
||||
ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
|
||||
invokeErrorCallback(ss.str(), std::string());
|
||||
invokeEventCallback(ix::CobraEventType::HandshakeError, msg->str);
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Pong)
|
||||
else if (action == "auth/authenticate/ok")
|
||||
{
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Pong);
|
||||
_authenticated = true;
|
||||
invokeEventCallback(ix::CobraEventType::Authenticated);
|
||||
flushQueue();
|
||||
}
|
||||
else if (action == "auth/authenticate/error")
|
||||
{
|
||||
invokeEventCallback(ix::CobraEventType::AuthenticationError, msg->str);
|
||||
}
|
||||
else if (action == "rtm/subscription/data")
|
||||
{
|
||||
handleSubscriptionData(data);
|
||||
}
|
||||
else if (action == "rtm/subscribe/ok")
|
||||
{
|
||||
if (!handleSubscriptionResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Error processing subscribe response", msg->str);
|
||||
}
|
||||
}
|
||||
else if (action == "rtm/subscribe/error")
|
||||
{
|
||||
invokeEventCallback(ix::CobraEventType::SubscriptionError, msg->str);
|
||||
}
|
||||
else if (action == "rtm/unsubscribe/ok")
|
||||
{
|
||||
if (!handleUnsubscriptionResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Error processing unsubscribe response", msg->str);
|
||||
}
|
||||
}
|
||||
else if (action == "rtm/unsubscribe/error")
|
||||
{
|
||||
invokeErrorCallback("Unsubscription error", msg->str);
|
||||
}
|
||||
else if (action == "rtm/publish/ok")
|
||||
{
|
||||
if (!handlePublishResponse(data))
|
||||
{
|
||||
invokeErrorCallback("Error processing publish response", msg->str);
|
||||
}
|
||||
}
|
||||
else if (action == "rtm/publish/error")
|
||||
{
|
||||
invokeErrorCallback("Publish error", msg->str);
|
||||
}
|
||||
else
|
||||
{
|
||||
invokeErrorCallback("Un-handled message type", msg->str);
|
||||
}
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Error)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Connection error: " << msg->errorInfo.reason << std::endl;
|
||||
ss << "#retries: " << msg->errorInfo.retries << std::endl;
|
||||
ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
|
||||
ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
|
||||
invokeErrorCallback(ss.str(), std::string());
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Pong)
|
||||
{
|
||||
invokeEventCallback(ix::CobraEventType::Pong, msg->str);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -249,12 +243,13 @@ namespace ix
|
||||
return _publishMode;
|
||||
}
|
||||
|
||||
void CobraConnection::configure(const std::string& appkey,
|
||||
const std::string& endpoint,
|
||||
const std::string& rolename,
|
||||
const std::string& rolesecret,
|
||||
const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
|
||||
const SocketTLSOptions& socketTLSOptions)
|
||||
void CobraConnection::configure(
|
||||
const std::string& appkey,
|
||||
const std::string& endpoint,
|
||||
const std::string& rolename,
|
||||
const std::string& rolesecret,
|
||||
const WebSocketPerMessageDeflateOptions& webSocketPerMessageDeflateOptions,
|
||||
const SocketTLSOptions& socketTLSOptions)
|
||||
{
|
||||
_roleName = rolename;
|
||||
_roleSecret = rolesecret;
|
||||
@ -396,8 +391,9 @@ namespace ix
|
||||
|
||||
if (!subscriptionId.isString()) return false;
|
||||
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Subscribed,
|
||||
std::string(), WebSocketHttpHeaders(),
|
||||
invokeEventCallback(ix::CobraEventType::Subscribed,
|
||||
std::string(),
|
||||
WebSocketHttpHeaders(),
|
||||
subscriptionId.asString());
|
||||
return true;
|
||||
}
|
||||
@ -414,8 +410,9 @@ namespace ix
|
||||
|
||||
if (!subscriptionId.isString()) return false;
|
||||
|
||||
invokeEventCallback(ix::CobraConnection_EventType_UnSubscribed,
|
||||
std::string(), WebSocketHttpHeaders(),
|
||||
invokeEventCallback(ix::CobraEventType::UnSubscribed,
|
||||
std::string(),
|
||||
WebSocketHttpHeaders(),
|
||||
subscriptionId.asString());
|
||||
return true;
|
||||
}
|
||||
@ -462,9 +459,11 @@ namespace ix
|
||||
|
||||
uint64_t msgId = id.asUInt64();
|
||||
|
||||
invokeEventCallback(ix::CobraConnection_EventType_Published,
|
||||
std::string(), WebSocketHttpHeaders(),
|
||||
std::string(), msgId);
|
||||
invokeEventCallback(ix::CobraEventType::Published,
|
||||
std::string(),
|
||||
WebSocketHttpHeaders(),
|
||||
std::string(),
|
||||
msgId);
|
||||
|
||||
invokePublishTrackerCallback(false, true);
|
||||
|
||||
@ -494,9 +493,7 @@ namespace ix
|
||||
}
|
||||
|
||||
std::pair<CobraConnection::MsgId, std::string> CobraConnection::prePublish(
|
||||
const Json::Value& channels,
|
||||
const Json::Value& msg,
|
||||
bool addToQueue)
|
||||
const Json::Value& channels, const Json::Value& msg, bool addToQueue)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_prePublishMutex);
|
||||
|
||||
@ -662,8 +659,7 @@ namespace ix
|
||||
bool CobraConnection::publishMessage(const std::string& serializedJson)
|
||||
{
|
||||
auto webSocketSendInfo = _webSocket->send(serializedJson);
|
||||
CobraConnection::invokeTrafficTrackerCallback(webSocketSendInfo.wireSize,
|
||||
false);
|
||||
CobraConnection::invokeTrafficTrackerCallback(webSocketSendInfo.wireSize, false);
|
||||
return webSocketSendInfo.success;
|
||||
}
|
||||
|
||||
|
@ -6,18 +6,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXCobraConfig.h"
|
||||
#include "IXCobraEvent.h"
|
||||
#include "IXCobraEventType.h"
|
||||
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
|
||||
#include <ixwebsocket/IXWebSocketPerMessageDeflateOptions.h>
|
||||
#include <json/json.h>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <limits>
|
||||
|
||||
#include "IXCobraConfig.h"
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
@ -28,21 +29,6 @@ namespace ix
|
||||
class WebSocket;
|
||||
struct SocketTLSOptions;
|
||||
|
||||
enum CobraConnectionEventType
|
||||
{
|
||||
CobraConnection_EventType_Authenticated = 0,
|
||||
CobraConnection_EventType_Error = 1,
|
||||
CobraConnection_EventType_Open = 2,
|
||||
CobraConnection_EventType_Closed = 3,
|
||||
CobraConnection_EventType_Subscribed = 4,
|
||||
CobraConnection_EventType_UnSubscribed = 5,
|
||||
CobraConnection_EventType_Published = 6,
|
||||
CobraConnection_EventType_Pong = 7,
|
||||
CobraConnection_EventType_Handshake_Error = 8,
|
||||
CobraConnection_EventType_Authentication_Error = 9,
|
||||
CobraConnection_EventType_Subscription_Error = 10
|
||||
};
|
||||
|
||||
enum CobraConnectionPublishMode
|
||||
{
|
||||
CobraConnection_PublishMode_Immediate = 0,
|
||||
@ -50,11 +36,7 @@ namespace ix
|
||||
};
|
||||
|
||||
using SubscriptionCallback = std::function<void(const Json::Value&, const std::string&)>;
|
||||
using EventCallback = std::function<void(CobraConnectionEventType,
|
||||
const std::string&,
|
||||
const WebSocketHttpHeaders&,
|
||||
const std::string&,
|
||||
uint64_t msgId)>;
|
||||
using EventCallback = std::function<void(const CobraEventPtr&)>;
|
||||
|
||||
using TrafficTrackerCallback = std::function<void(size_t size, bool incoming)>;
|
||||
using PublishTrackerCallback = std::function<void(bool sent, bool acked)>;
|
||||
@ -138,10 +120,9 @@ namespace ix
|
||||
|
||||
/// Prepare a message for transmission
|
||||
/// (update the pdu, compute a msgId, serialize json to a string)
|
||||
std::pair<CobraConnection::MsgId, std::string> prePublish(
|
||||
const Json::Value& channels,
|
||||
const Json::Value& msg,
|
||||
bool addToQueue);
|
||||
std::pair<CobraConnection::MsgId, std::string> prePublish(const Json::Value& channels,
|
||||
const Json::Value& msg,
|
||||
bool addToQueue);
|
||||
|
||||
/// Attempt to send next message from the internal queue
|
||||
bool publishNext();
|
||||
@ -171,7 +152,7 @@ namespace ix
|
||||
static void invokePublishTrackerCallback(bool sent, bool acked);
|
||||
|
||||
/// Invoke event callbacks
|
||||
void invokeEventCallback(CobraConnectionEventType eventType,
|
||||
void invokeEventCallback(CobraEventType eventType,
|
||||
const std::string& errorMsg = std::string(),
|
||||
const WebSocketHttpHeaders& headers = WebSocketHttpHeaders(),
|
||||
const std::string& subscriptionId = std::string(),
|
||||
|
41
ixcobra/ixcobra/IXCobraEvent.h
Normal file
41
ixcobra/ixcobra/IXCobraEvent.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* IXCobraEvent.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXCobraEventType.h"
|
||||
#include <cstdint>
|
||||
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
struct CobraEvent
|
||||
{
|
||||
ix::CobraEventType type;
|
||||
const std::string& errMsg;
|
||||
const ix::WebSocketHttpHeaders& headers;
|
||||
const std::string& subscriptionId;
|
||||
uint64_t msgId; // CobraConnection::MsgId
|
||||
|
||||
CobraEvent(ix::CobraEventType t,
|
||||
const std::string& e,
|
||||
const ix::WebSocketHttpHeaders& h,
|
||||
const std::string& s,
|
||||
uint64_t m)
|
||||
: type(t)
|
||||
, errMsg(e)
|
||||
, headers(h)
|
||||
, subscriptionId(s)
|
||||
, msgId(m)
|
||||
{
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
using CobraEventPtr = std::unique_ptr<CobraEvent>;
|
||||
} // namespace ix
|
25
ixcobra/ixcobra/IXCobraEventType.h
Normal file
25
ixcobra/ixcobra/IXCobraEventType.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* IXCobraEventType.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ix
|
||||
{
|
||||
enum class CobraEventType
|
||||
{
|
||||
Authenticated = 0,
|
||||
Error = 1,
|
||||
Open = 2,
|
||||
Closed = 3,
|
||||
Subscribed = 4,
|
||||
UnSubscribed = 5,
|
||||
Published = 6,
|
||||
Pong = 7,
|
||||
HandshakeError = 8,
|
||||
AuthenticationError = 9,
|
||||
SubscriptionError = 10
|
||||
};
|
||||
}
|
@ -5,9 +5,9 @@
|
||||
*/
|
||||
|
||||
#include "IXCobraMetricsPublisher.h"
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
@ -17,8 +17,8 @@ namespace ix
|
||||
const std::string CobraMetricsPublisher::kSetRateControlId = "sms_set_rate_control_id";
|
||||
const std::string CobraMetricsPublisher::kSetBlacklistId = "sms_set_blacklist_id";
|
||||
|
||||
CobraMetricsPublisher::CobraMetricsPublisher() :
|
||||
_enabled(true)
|
||||
CobraMetricsPublisher::CobraMetricsPublisher()
|
||||
: _enabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
@ -27,8 +27,7 @@ namespace ix
|
||||
;
|
||||
}
|
||||
|
||||
void CobraMetricsPublisher::configure(const CobraConfig& config,
|
||||
const std::string& channel)
|
||||
void CobraMetricsPublisher::configure(const CobraConfig& config, const std::string& channel)
|
||||
{
|
||||
// Configure the satori connection and start its publish background thread
|
||||
_cobra_metrics_theaded_publisher.configure(config, channel);
|
||||
@ -42,7 +41,7 @@ namespace ix
|
||||
}
|
||||
|
||||
void CobraMetricsPublisher::setGenericAttributes(const std::string& attrName,
|
||||
const Json::Value& value)
|
||||
const Json::Value& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_device_mutex);
|
||||
_device[attrName] = value;
|
||||
@ -107,8 +106,7 @@ namespace ix
|
||||
auto last_update = _last_update.find(id);
|
||||
if (last_update == _last_update.end()) return false;
|
||||
|
||||
auto timeDeltaFromLastSend =
|
||||
std::chrono::steady_clock::now() - last_update->second;
|
||||
auto timeDeltaFromLastSend = std::chrono::steady_clock::now() - last_update->second;
|
||||
|
||||
return timeDeltaFromLastSend < std::chrono::seconds(rate_control_it->second);
|
||||
}
|
||||
@ -123,8 +121,7 @@ namespace ix
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto ms =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now.time_since_epoch()).count();
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
|
||||
|
||||
return ms;
|
||||
}
|
||||
@ -165,10 +162,9 @@ namespace ix
|
||||
return true;
|
||||
}
|
||||
|
||||
CobraConnection::MsgId CobraMetricsPublisher::push(
|
||||
const std::string& id,
|
||||
const Json::Value& data,
|
||||
bool shouldPushTest)
|
||||
CobraConnection::MsgId CobraMetricsPublisher::push(const std::string& id,
|
||||
const Json::Value& data,
|
||||
bool shouldPushTest)
|
||||
{
|
||||
if (shouldPushTest && !shouldPush(id)) return CobraConnection::kInvalidMsgId;
|
||||
|
||||
|
@ -40,8 +40,7 @@ namespace ix
|
||||
|
||||
/// Configuration / set keys, etc...
|
||||
/// All input data but the channel name is encrypted with rc4
|
||||
void configure(const CobraConfig& config,
|
||||
const std::string& channel);
|
||||
void configure(const CobraConfig& config, const std::string& channel);
|
||||
|
||||
/// Setter for the list of blacklisted metrics ids.
|
||||
/// That list is sorted internally for fast lookups
|
||||
@ -68,10 +67,14 @@ namespace ix
|
||||
/// shouldPush method for places where we want to be as lightweight as possible when
|
||||
/// collecting metrics. When set to false, it is used so that we don't do double work when
|
||||
/// computing whether a metrics should be sent or not.
|
||||
CobraConnection::MsgId push(const std::string& id, const Json::Value& data, bool shouldPushTest = true);
|
||||
CobraConnection::MsgId push(const std::string& id,
|
||||
const Json::Value& data,
|
||||
bool shouldPushTest = true);
|
||||
|
||||
/// Interface used by lua. msg is a json encoded string.
|
||||
CobraConnection::MsgId push(const std::string& id, const std::string& data, bool shouldPushTest = true);
|
||||
CobraConnection::MsgId push(const std::string& id,
|
||||
const std::string& data,
|
||||
bool shouldPushTest = true);
|
||||
|
||||
/// Tells whether a metric can be pushed.
|
||||
/// A metric can be pushed if it satisfies those conditions:
|
||||
@ -89,10 +92,16 @@ namespace ix
|
||||
void setGenericAttributes(const std::string& attrName, const Json::Value& value);
|
||||
|
||||
/// Set a unique id for the session. A uuid can be used.
|
||||
void setSession(const std::string& session) { _session = session; }
|
||||
void setSession(const std::string& session)
|
||||
{
|
||||
_session = session;
|
||||
}
|
||||
|
||||
/// Get the unique id used to identify the current session
|
||||
const std::string& getSession() const { return _session; }
|
||||
const std::string& getSession() const
|
||||
{
|
||||
return _session;
|
||||
}
|
||||
|
||||
/// Return the number of milliseconds since the epoch (~1970)
|
||||
uint64_t getMillisecondsSinceEpoch() const;
|
||||
|
@ -5,72 +5,77 @@
|
||||
*/
|
||||
|
||||
#include "IXCobraMetricsThreadedPublisher.h"
|
||||
#include <ixwebsocket/IXSetThreadName.h>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <ixwebsocket/IXSetThreadName.h>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace ix
|
||||
{
|
||||
CobraMetricsThreadedPublisher::CobraMetricsThreadedPublisher() :
|
||||
_stop(false)
|
||||
CobraMetricsThreadedPublisher::CobraMetricsThreadedPublisher()
|
||||
: _stop(false)
|
||||
{
|
||||
_cobra_connection.setEventCallback(
|
||||
[]
|
||||
(ix::CobraConnectionEventType eventType,
|
||||
const std::string& errMsg,
|
||||
const ix::WebSocketHttpHeaders& headers,
|
||||
const std::string& subscriptionId,
|
||||
CobraConnection::MsgId msgId)
|
||||
_cobra_connection.setEventCallback([](const CobraEventPtr& event) {
|
||||
std::stringstream ss;
|
||||
|
||||
if (event->type == ix::CobraEventType::Open)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Handshake headers" << std::endl;
|
||||
|
||||
if (eventType == ix::CobraConnection_EventType_Open)
|
||||
for (auto&& it : event->headers)
|
||||
{
|
||||
ss << "Handshake headers" << std::endl;
|
||||
ss << it.first << ": " << it.second << std::endl;
|
||||
}
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Authenticated)
|
||||
{
|
||||
ss << "Authenticated";
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Error)
|
||||
{
|
||||
ss << "Error: " << event->errMsg;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Closed)
|
||||
{
|
||||
ss << "Connection closed: " << event->errMsg;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Subscribed)
|
||||
{
|
||||
ss << "Subscribed through subscription id: " << event->subscriptionId;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::UnSubscribed)
|
||||
{
|
||||
ss << "Unsubscribed through subscription id: " << event->subscriptionId;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Published)
|
||||
{
|
||||
ss << "Published message " << event->msgId << " acked";
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Pong)
|
||||
{
|
||||
ss << "Received websocket pong";
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::HandshakeError)
|
||||
{
|
||||
ss << "Handshake error: " << event->errMsg;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::AuthenticationError)
|
||||
{
|
||||
ss << "Authentication error: " << event->errMsg;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::SubscriptionError)
|
||||
{
|
||||
ss << "Subscription error: " << event->errMsg;
|
||||
}
|
||||
|
||||
for (auto it : headers)
|
||||
{
|
||||
ss << it.first << ": " << it.second << std::endl;
|
||||
}
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
||||
{
|
||||
ss << "Authenticated";
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Error)
|
||||
{
|
||||
ss << "Error: " << errMsg;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Closed)
|
||||
{
|
||||
ss << "Connection closed: " << errMsg;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
||||
{
|
||||
ss << "Subscribed through subscription id: " << subscriptionId;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
||||
{
|
||||
ss << "Unsubscribed through subscription id: " << subscriptionId;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Published)
|
||||
{
|
||||
ss << "Published message " << msgId << " acked";
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Pong)
|
||||
{
|
||||
ss << "Received websocket pong";
|
||||
}
|
||||
|
||||
ix::IXCoreLogger::Log(ss.str().c_str());
|
||||
CoreLogger::log(ss.str().c_str());
|
||||
});
|
||||
}
|
||||
|
||||
@ -95,11 +100,10 @@ namespace ix
|
||||
void CobraMetricsThreadedPublisher::configure(const CobraConfig& config,
|
||||
const std::string& channel)
|
||||
{
|
||||
ix::IXCoreLogger::Log(config.socketTLSOptions.getDescription().c_str());
|
||||
CoreLogger::log(config.socketTLSOptions.getDescription().c_str());
|
||||
|
||||
_channel = channel;
|
||||
_cobra_connection.configure(config);
|
||||
|
||||
}
|
||||
|
||||
void CobraMetricsThreadedPublisher::pushMessage(MessageKind messageKind)
|
||||
@ -157,13 +161,15 @@ namespace ix
|
||||
{
|
||||
_cobra_connection.suspend();
|
||||
continue;
|
||||
}; break;
|
||||
};
|
||||
break;
|
||||
|
||||
case MessageKind::Resume:
|
||||
{
|
||||
_cobra_connection.resume();
|
||||
continue;
|
||||
}; break;
|
||||
};
|
||||
break;
|
||||
|
||||
case MessageKind::Message:
|
||||
{
|
||||
@ -171,7 +177,8 @@ namespace ix
|
||||
{
|
||||
_cobra_connection.publishNext();
|
||||
}
|
||||
}; break;
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,7 @@ namespace ix
|
||||
~CobraMetricsThreadedPublisher();
|
||||
|
||||
/// Configuration / set keys, etc...
|
||||
void configure(const CobraConfig& config,
|
||||
const std::string& channel);
|
||||
void configure(const CobraConfig& config, const std::string& channel);
|
||||
|
||||
/// Start the worker thread, used for background publishing
|
||||
void start();
|
||||
|
@ -1,14 +1,44 @@
|
||||
#include "ixcore/utils/IXCoreLogger.h"
|
||||
/*
|
||||
* IXCoreLogger.cpp
|
||||
* Author: Thomas Wells, Benjamin Sergeant
|
||||
* Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "ixcore/utils/IXCoreLogger.h"
|
||||
|
||||
namespace ix
|
||||
{
|
||||
// Default do nothing logger
|
||||
IXCoreLogger::LogFunc IXCoreLogger::_currentLogger = [](const char* /*msg*/){};
|
||||
// Default do a no-op logger
|
||||
CoreLogger::LogFunc CoreLogger::_currentLogger = [](const char*, LogLevel) {};
|
||||
|
||||
void IXCoreLogger::Log(const char* msg)
|
||||
{
|
||||
_currentLogger(msg);
|
||||
}
|
||||
void CoreLogger::log(const char* msg, LogLevel level)
|
||||
{
|
||||
_currentLogger(msg, level);
|
||||
}
|
||||
|
||||
} // ix
|
||||
void CoreLogger::debug(const std::string& msg)
|
||||
{
|
||||
_currentLogger(msg.c_str(), LogLevel::Debug);
|
||||
}
|
||||
|
||||
void CoreLogger::info(const std::string& msg)
|
||||
{
|
||||
_currentLogger(msg.c_str(), LogLevel::Info);
|
||||
}
|
||||
|
||||
void CoreLogger::warn(const std::string& msg)
|
||||
{
|
||||
_currentLogger(msg.c_str(), LogLevel::Warning);
|
||||
}
|
||||
|
||||
void CoreLogger::error(const std::string& msg)
|
||||
{
|
||||
_currentLogger(msg.c_str(), LogLevel::Error);
|
||||
}
|
||||
|
||||
void CoreLogger::critical(const std::string& msg)
|
||||
{
|
||||
_currentLogger(msg.c_str(), LogLevel::Critical);
|
||||
}
|
||||
|
||||
} // namespace ix
|
||||
|
@ -1,15 +1,41 @@
|
||||
/*
|
||||
* IXCoreLogger.h
|
||||
* Author: Thomas Wells, Benjamin Sergeant
|
||||
* Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
class IXCoreLogger
|
||||
enum class LogLevel
|
||||
{
|
||||
Debug = 0,
|
||||
Info = 1,
|
||||
Warning = 2,
|
||||
Error = 3,
|
||||
Critical = 4
|
||||
};
|
||||
|
||||
class CoreLogger
|
||||
{
|
||||
public:
|
||||
using LogFunc = std::function<void(const char*)>;
|
||||
static void Log(const char* msg);
|
||||
using LogFunc = std::function<void(const char*, LogLevel level)>;
|
||||
|
||||
static void setLogFunction(LogFunc& func) { _currentLogger = func; }
|
||||
static void log(const char* msg, LogLevel level = LogLevel::Debug);
|
||||
|
||||
static void debug(const std::string& msg);
|
||||
static void info(const std::string& msg);
|
||||
static void warn(const std::string& msg);
|
||||
static void error(const std::string& msg);
|
||||
static void critical(const std::string& msg);
|
||||
|
||||
static void setLogFunction(LogFunc& func)
|
||||
{
|
||||
_currentLogger = func;
|
||||
}
|
||||
|
||||
private:
|
||||
static LogFunc _currentLogger;
|
||||
|
@ -29,10 +29,9 @@
|
||||
|
||||
namespace ix
|
||||
{
|
||||
static const std::string base64_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
std::string base64_encode(const std::string& data, size_t len)
|
||||
{
|
||||
@ -50,26 +49,26 @@ namespace ix
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while(len--)
|
||||
while (len--)
|
||||
{
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if(i == 3)
|
||||
if (i == 3)
|
||||
{
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
for (i = 0; (i < 4); i++)
|
||||
ret += base64_chars[char_array_4[i]];
|
||||
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(i)
|
||||
if (i)
|
||||
{
|
||||
for(j = i; j < 3; j++)
|
||||
for (j = i; j < 3; j++)
|
||||
char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
@ -77,12 +76,11 @@ namespace ix
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(j = 0; (j < i + 1); j++)
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
ret += base64_chars[char_array_4[j]];
|
||||
|
||||
while((i++ < 3))
|
||||
while ((i++ < 3))
|
||||
ret += '=';
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -95,7 +93,7 @@ namespace ix
|
||||
|
||||
std::string base64_decode(const std::string& encoded_string)
|
||||
{
|
||||
int in_len = (int)encoded_string.size();
|
||||
int in_len = (int) encoded_string.size();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
@ -103,40 +101,42 @@ namespace ix
|
||||
std::string ret;
|
||||
ret.reserve(((in_len + 3) / 4) * 3);
|
||||
|
||||
while(in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_]))
|
||||
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_]))
|
||||
{
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
if(i ==4)
|
||||
char_array_4[i++] = encoded_string[in_];
|
||||
in_++;
|
||||
if (i == 4)
|
||||
{
|
||||
for(i = 0; i <4; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
char_array_4[i] = base64_chars.find(char_array_4[i]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for(i = 0; (i < 3); i++)
|
||||
for (i = 0; (i < 3); i++)
|
||||
ret += char_array_3[i];
|
||||
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(i)
|
||||
if (i)
|
||||
{
|
||||
for(j = i; j <4; j++)
|
||||
for (j = i; j < 4; j++)
|
||||
char_array_4[j] = 0;
|
||||
|
||||
for(j = 0; j <4; j++)
|
||||
for (j = 0; j < 4; j++)
|
||||
char_array_4[j] = base64_chars.find(char_array_4[j]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for(j = 0; (j < i - 1); j++) ret += char_array_3[j];
|
||||
for (j = 0; (j < i - 1); j++)
|
||||
ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} // namespace ix
|
||||
|
@ -5,16 +5,17 @@
|
||||
*/
|
||||
|
||||
#include "IXHMac.h"
|
||||
|
||||
#include "IXBase64.h"
|
||||
|
||||
#if defined(IXCRYPTO_USE_MBED_TLS)
|
||||
# include <mbedtls/md.h>
|
||||
#include <mbedtls/md.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <CommonCrypto/CommonHMAC.h>
|
||||
#include <CommonCrypto/CommonHMAC.h>
|
||||
#elif defined(IXCRYPTO_USE_OPEN_SSL)
|
||||
# include <openssl/hmac.h>
|
||||
#include <openssl/hmac.h>
|
||||
#else
|
||||
# include <assert.h>
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
namespace ix
|
||||
@ -26,19 +27,21 @@ namespace ix
|
||||
|
||||
#if defined(IXCRYPTO_USE_MBED_TLS)
|
||||
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_MD5),
|
||||
(unsigned char *) key.c_str(), key.size(),
|
||||
(unsigned char *) data.c_str(), data.size(),
|
||||
(unsigned char *) &hash);
|
||||
(unsigned char*) key.c_str(),
|
||||
key.size(),
|
||||
(unsigned char*) data.c_str(),
|
||||
data.size(),
|
||||
(unsigned char*) &hash);
|
||||
#elif defined(__APPLE__)
|
||||
CCHmac(kCCHmacAlgMD5,
|
||||
key.c_str(), key.size(),
|
||||
data.c_str(), data.size(),
|
||||
&hash);
|
||||
CCHmac(kCCHmacAlgMD5, key.c_str(), key.size(), data.c_str(), data.size(), &hash);
|
||||
#elif defined(IXCRYPTO_USE_OPEN_SSL)
|
||||
HMAC(EVP_md5(),
|
||||
key.c_str(), (int) key.size(),
|
||||
(unsigned char *) data.c_str(), (int) data.size(),
|
||||
(unsigned char *) hash, nullptr);
|
||||
key.c_str(),
|
||||
(int) key.size(),
|
||||
(unsigned char*) data.c_str(),
|
||||
(int) data.size(),
|
||||
(unsigned char*) hash,
|
||||
nullptr);
|
||||
#else
|
||||
assert(false && "hmac not implemented on this platform");
|
||||
#endif
|
||||
@ -47,4 +50,4 @@ namespace ix
|
||||
|
||||
return base64_encode(hashString, (uint32_t) hashString.size());
|
||||
}
|
||||
}
|
||||
} // namespace ix
|
||||
|
@ -19,4 +19,4 @@ namespace ix
|
||||
|
||||
return hashAddress;
|
||||
}
|
||||
}
|
||||
} // namespace ix
|
||||
|
@ -16,23 +16,23 @@
|
||||
|
||||
#include "IXUuid.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace ix
|
||||
{
|
||||
class Uuid
|
||||
{
|
||||
public:
|
||||
Uuid();
|
||||
std::string toString() const;
|
||||
public:
|
||||
Uuid();
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
uint64_t _ab;
|
||||
uint64_t _cd;
|
||||
private:
|
||||
uint64_t _ab;
|
||||
uint64_t _cd;
|
||||
};
|
||||
|
||||
Uuid::Uuid()
|
||||
@ -60,7 +60,7 @@ namespace ix
|
||||
ss << std::setw(8) << (a);
|
||||
ss << std::setw(4) << (b >> 16);
|
||||
ss << std::setw(4) << (b & 0xFFFF);
|
||||
ss << std::setw(4) << (c >> 16 );
|
||||
ss << std::setw(4) << (c >> 16);
|
||||
ss << std::setw(4) << (c & 0xFFFF);
|
||||
ss << std::setw(8) << d;
|
||||
|
||||
@ -72,4 +72,4 @@ namespace ix
|
||||
Uuid id;
|
||||
return id.toString();
|
||||
}
|
||||
}
|
||||
} // namespace ix
|
||||
|
@ -7,12 +7,12 @@
|
||||
#include "IXSentryClient.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
|
||||
#include <ixwebsocket/IXWebSocketVersion.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace ix
|
||||
@ -64,7 +64,8 @@ namespace ix
|
||||
std::string SentryClient::computeAuthHeader()
|
||||
{
|
||||
std::string securityHeader("Sentry sentry_version=5");
|
||||
securityHeader += ",sentry_client=ws/1.0.0";
|
||||
securityHeader += ",sentry_client=ws/";
|
||||
securityHeader += std::string(IX_WEBSOCKET_VERSION);
|
||||
securityHeader += ",sentry_timestamp=" + std::to_string(SentryClient::getTimestamp());
|
||||
securityHeader += ",sentry_key=" + _publicKey;
|
||||
securityHeader += ",sentry_secret=" + _secretKey;
|
||||
@ -233,7 +234,7 @@ namespace ix
|
||||
args->transferTimeout = 5 * 60;
|
||||
args->followRedirects = true;
|
||||
args->verbose = verbose;
|
||||
args->logger = [](const std::string& msg) { ix::IXCoreLogger::Log(msg.c_str()); };
|
||||
args->logger = [](const std::string& msg) { CoreLogger::log(msg.c_str()); };
|
||||
|
||||
std::string body = computePayload(msg);
|
||||
HttpResponsePtr response = _httpClient->post(_url, body, args);
|
||||
@ -245,24 +246,21 @@ namespace ix
|
||||
std::string SentryClient::computeUrl(const std::string& project, const std::string& key)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "https://sentry.io/api/"
|
||||
<< project
|
||||
<< "/minidump?sentry_key="
|
||||
<< key;
|
||||
ss << "https://sentry.io/api/" << project << "/minidump?sentry_key=" << key;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
//
|
||||
// curl -v -X POST -F upload_file_minidump=@ws/crash.dmp 'https://sentry.io/api/123456/minidump?sentry_key=12344567890'
|
||||
// curl -v -X POST -F upload_file_minidump=@ws/crash.dmp
|
||||
// 'https://sentry.io/api/123456/minidump?sentry_key=12344567890'
|
||||
//
|
||||
void SentryClient::uploadMinidump(
|
||||
const std::string& sentryMetadata,
|
||||
const std::string& minidumpBytes,
|
||||
const std::string& project,
|
||||
const std::string& key,
|
||||
bool verbose,
|
||||
const OnResponseCallback& onResponseCallback)
|
||||
void SentryClient::uploadMinidump(const std::string& sentryMetadata,
|
||||
const std::string& minidumpBytes,
|
||||
const std::string& project,
|
||||
const std::string& key,
|
||||
bool verbose,
|
||||
const OnResponseCallback& onResponseCallback)
|
||||
{
|
||||
std::string multipartBoundary = _httpClient->generateMultipartBoundary();
|
||||
|
||||
@ -273,7 +271,7 @@ namespace ix
|
||||
args->followRedirects = true;
|
||||
args->verbose = verbose;
|
||||
args->multipartBoundary = multipartBoundary;
|
||||
args->logger = [](const std::string& msg) { ix::IXCoreLogger::Log(msg.c_str()); };
|
||||
args->logger = [](const std::string& msg) { CoreLogger::log(msg.c_str()); };
|
||||
|
||||
HttpFormDataParameters httpFormDataParameters;
|
||||
httpFormDataParameters["upload_file_minidump"] = minidumpBytes;
|
||||
@ -282,7 +280,27 @@ namespace ix
|
||||
httpParameters["sentry"] = sentryMetadata;
|
||||
|
||||
args->url = computeUrl(project, key);
|
||||
args->body = _httpClient->serializeHttpFormDataParameters(multipartBoundary, httpFormDataParameters, httpParameters);
|
||||
args->body = _httpClient->serializeHttpFormDataParameters(
|
||||
multipartBoundary, httpFormDataParameters, httpParameters);
|
||||
|
||||
_httpClient->performRequest(args, onResponseCallback);
|
||||
}
|
||||
|
||||
void SentryClient::uploadPayload(const Json::Value& payload,
|
||||
bool verbose,
|
||||
const OnResponseCallback& onResponseCallback)
|
||||
{
|
||||
auto args = _httpClient->createRequest();
|
||||
args->extraHeaders["X-Sentry-Auth"] = SentryClient::computeAuthHeader();
|
||||
args->verb = HttpClient::kPost;
|
||||
args->connectTimeout = 60;
|
||||
args->transferTimeout = 5 * 60;
|
||||
args->followRedirects = true;
|
||||
args->verbose = verbose;
|
||||
args->logger = [](const std::string& msg) { CoreLogger::log(msg.c_str()); };
|
||||
|
||||
args->url = _url;
|
||||
args->body = _jsonWriter.write(payload);
|
||||
|
||||
_httpClient->performRequest(args, onResponseCallback);
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include <ixwebsocket/IXHttpClient.h>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <json/json.h>
|
||||
#include <regex>
|
||||
#include <memory>
|
||||
#include <regex>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
@ -28,13 +28,16 @@ namespace ix
|
||||
// Mostly for testing
|
||||
void setTLSOptions(const SocketTLSOptions& tlsOptions);
|
||||
|
||||
void uploadMinidump(
|
||||
const std::string& sentryMetadata,
|
||||
const std::string& minidumpBytes,
|
||||
const std::string& project,
|
||||
const std::string& key,
|
||||
bool verbose,
|
||||
const OnResponseCallback& onResponseCallback);
|
||||
void uploadMinidump(const std::string& sentryMetadata,
|
||||
const std::string& minidumpBytes,
|
||||
const std::string& project,
|
||||
const std::string& key,
|
||||
bool verbose,
|
||||
const OnResponseCallback& onResponseCallback);
|
||||
|
||||
void uploadPayload(const Json::Value& payload,
|
||||
bool verbose,
|
||||
const OnResponseCallback& onResponseCallback);
|
||||
|
||||
private:
|
||||
int64_t getTimestamp();
|
||||
|
@ -6,10 +6,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
|
||||
namespace snake
|
||||
{
|
||||
|
@ -28,10 +28,7 @@ namespace ix
|
||||
return false;
|
||||
}
|
||||
|
||||
CancellationRequest cancellationRequest = []() -> bool
|
||||
{
|
||||
return false;
|
||||
};
|
||||
CancellationRequest cancellationRequest = []() -> bool { return false; };
|
||||
|
||||
std::string errMsg;
|
||||
return _socket->connect(hostname, port, errMsg, cancellationRequest);
|
||||
@ -252,9 +249,8 @@ namespace ix
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string RedisClient::prepareXaddCommand(
|
||||
const std::string& stream,
|
||||
const std::string& message)
|
||||
std::string RedisClient::prepareXaddCommand(const std::string& stream,
|
||||
const std::string& message)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "*5\r\n";
|
||||
@ -328,7 +324,9 @@ namespace ix
|
||||
return streamId;
|
||||
}
|
||||
|
||||
bool RedisClient::sendCommand(const std::string& commands, int commandsCount, std::string& errMsg)
|
||||
bool RedisClient::sendCommand(const std::string& commands,
|
||||
int commandsCount,
|
||||
std::string& errMsg)
|
||||
{
|
||||
bool sent = _socket->writeBytes(commands, nullptr);
|
||||
if (!sent)
|
||||
|
@ -8,11 +8,10 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
class RedisClient
|
||||
@ -39,14 +38,11 @@ namespace ix
|
||||
const OnRedisSubscribeCallback& callback);
|
||||
|
||||
// XADD
|
||||
std::string xadd(
|
||||
const std::string& channel,
|
||||
const std::string& message,
|
||||
std::string& errMsg);
|
||||
std::string xadd(const std::string& channel,
|
||||
const std::string& message,
|
||||
std::string& errMsg);
|
||||
|
||||
std::string prepareXaddCommand(
|
||||
const std::string& stream,
|
||||
const std::string& message);
|
||||
std::string prepareXaddCommand(const std::string& stream, const std::string& message);
|
||||
|
||||
std::string readXaddReply(std::string& errMsg);
|
||||
|
||||
|
@ -6,17 +6,18 @@
|
||||
|
||||
#include "IXRedisServer.h"
|
||||
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <ixwebsocket/IXSocketConnect.h>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <ixwebsocket/IXCancellationRequest.h>
|
||||
#include <fstream>
|
||||
#include <ixwebsocket/IXCancellationRequest.h>
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <ixwebsocket/IXSocketConnect.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
RedisServer::RedisServer(int port, const std::string& host, int backlog, size_t maxConnections, int addressFamily)
|
||||
RedisServer::RedisServer(
|
||||
int port, const std::string& host, int backlog, size_t maxConnections, int addressFamily)
|
||||
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
||||
, _connectedClientsCount(0)
|
||||
, _stopHandlingConnections(false)
|
||||
@ -114,8 +115,7 @@ namespace ix
|
||||
for (auto it : _subscribers)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Subscription id: " << it.first
|
||||
<< " #subscribers: " << it.second.size();
|
||||
ss << "Subscription id: " << it.first << " #subscribers: " << it.second.size();
|
||||
|
||||
logInfo(ss.str());
|
||||
}
|
||||
@ -126,8 +126,7 @@ namespace ix
|
||||
return _connectedClientsCount;
|
||||
}
|
||||
|
||||
bool RedisServer::startsWith(const std::string& str,
|
||||
const std::string& start)
|
||||
bool RedisServer::startsWith(const std::string& str, const std::string& start)
|
||||
{
|
||||
return str.compare(0, start.length(), start) == 0;
|
||||
}
|
||||
@ -144,9 +143,8 @@ namespace ix
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool RedisServer::parseRequest(
|
||||
std::unique_ptr<Socket>& socket,
|
||||
std::vector<std::string>& tokens)
|
||||
bool RedisServer::parseRequest(std::unique_ptr<Socket>& socket,
|
||||
std::vector<std::string>& tokens)
|
||||
{
|
||||
// Parse first line
|
||||
auto cb = makeCancellationRequestWithTimeout(30, _stopHandlingConnections);
|
||||
@ -190,9 +188,8 @@ namespace ix
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RedisServer::handleCommand(
|
||||
std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens)
|
||||
bool RedisServer::handleCommand(std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens)
|
||||
{
|
||||
if (tokens.size() != 1) return false;
|
||||
|
||||
@ -207,31 +204,30 @@ namespace ix
|
||||
//
|
||||
ss << "*6\r\n";
|
||||
ss << writeString("publish"); // 1
|
||||
ss << ":3\r\n"; // 2
|
||||
ss << "*0\r\n"; // 3
|
||||
ss << ":1\r\n"; // 4
|
||||
ss << ":2\r\n"; // 5
|
||||
ss << ":1\r\n"; // 6
|
||||
ss << ":3\r\n"; // 2
|
||||
ss << "*0\r\n"; // 3
|
||||
ss << ":1\r\n"; // 4
|
||||
ss << ":2\r\n"; // 5
|
||||
ss << ":1\r\n"; // 6
|
||||
|
||||
//
|
||||
// subscribe
|
||||
//
|
||||
ss << "*6\r\n";
|
||||
ss << writeString("subscribe"); // 1
|
||||
ss << ":2\r\n"; // 2
|
||||
ss << "*0\r\n"; // 3
|
||||
ss << ":1\r\n"; // 4
|
||||
ss << ":1\r\n"; // 5
|
||||
ss << ":1\r\n"; // 6
|
||||
ss << ":2\r\n"; // 2
|
||||
ss << "*0\r\n"; // 3
|
||||
ss << ":1\r\n"; // 4
|
||||
ss << ":1\r\n"; // 5
|
||||
ss << ":1\r\n"; // 6
|
||||
|
||||
socket->writeBytes(ss.str(), cb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RedisServer::handleSubscribe(
|
||||
std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens)
|
||||
bool RedisServer::handleSubscribe(std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens)
|
||||
{
|
||||
if (tokens.size() != 2) return false;
|
||||
|
||||
@ -250,9 +246,8 @@ namespace ix
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RedisServer::handlePublish(
|
||||
std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens)
|
||||
bool RedisServer::handlePublish(std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens)
|
||||
{
|
||||
if (tokens.size() != 3) return false;
|
||||
|
||||
@ -281,9 +276,7 @@ namespace ix
|
||||
|
||||
// return the number of clients that received the message.
|
||||
std::stringstream ss;
|
||||
ss << ":"
|
||||
<< std::to_string(subscribers.size())
|
||||
<< "\r\n";
|
||||
ss << ":" << std::to_string(subscribers.size()) << "\r\n";
|
||||
socket->writeBytes(ss.str(), cb);
|
||||
|
||||
return true;
|
||||
|
@ -6,13 +6,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXSocketServer.h"
|
||||
#include "IXSocket.h"
|
||||
#include "IXSocketServer.h"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility> // pair
|
||||
@ -50,18 +50,14 @@ namespace ix
|
||||
bool startsWith(const std::string& str, const std::string& start);
|
||||
std::string writeString(const std::string& str);
|
||||
|
||||
bool parseRequest(
|
||||
std::unique_ptr<Socket>& socket,
|
||||
std::vector<std::string>& tokens);
|
||||
bool parseRequest(std::unique_ptr<Socket>& socket, std::vector<std::string>& tokens);
|
||||
|
||||
bool handlePublish(std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens);
|
||||
bool handlePublish(std::unique_ptr<Socket>& socket, const std::vector<std::string>& tokens);
|
||||
|
||||
bool handleSubscribe(std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens);
|
||||
|
||||
bool handleCommand(std::unique_ptr<Socket>& socket,
|
||||
const std::vector<std::string>& tokens);
|
||||
bool handleCommand(std::unique_ptr<Socket>& socket, const std::vector<std::string>& tokens);
|
||||
|
||||
void cleanupSubscribers(std::unique_ptr<Socket>& socket);
|
||||
};
|
||||
|
@ -10,9 +10,9 @@
|
||||
#include "IXSnakeConnectionState.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <iostream>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <ixcrypto/IXHMac.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace snake
|
||||
@ -189,7 +189,8 @@ namespace snake
|
||||
nlohmann::json response = {
|
||||
{"action", "rtm/subscription/data"},
|
||||
{"id", id++},
|
||||
{"body", {{"subscription_id", subscriptionId}, {"position", "0-0"}, {"messages", {msg}}}}};
|
||||
{"body",
|
||||
{{"subscription_id", subscriptionId}, {"position", "0-0"}, {"messages", {msg}}}}};
|
||||
|
||||
ws->sendText(response.dump());
|
||||
};
|
||||
@ -197,7 +198,7 @@ namespace snake
|
||||
auto responseCallback = [ws, pdu, &subscriptionId](const std::string& redisResponse) {
|
||||
std::stringstream ss;
|
||||
ss << "Redis Response: " << redisResponse << "...";
|
||||
ix::IXCoreLogger::Log(ss.str().c_str());
|
||||
ix::CoreLogger::log(ss.str().c_str());
|
||||
|
||||
// Success
|
||||
nlohmann::json response = {{"action", "rtm/subscribe/ok"},
|
||||
@ -209,7 +210,7 @@ namespace snake
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Subscribing to " << appChannel << "...";
|
||||
ix::IXCoreLogger::Log(ss.str().c_str());
|
||||
ix::CoreLogger::log(ss.str().c_str());
|
||||
}
|
||||
|
||||
if (!redisClient.subscribe(appChannel, responseCallback, callback))
|
||||
@ -251,7 +252,21 @@ namespace snake
|
||||
const AppConfig& appConfig,
|
||||
const std::string& str)
|
||||
{
|
||||
auto pdu = nlohmann::json::parse(str);
|
||||
nlohmann::json pdu;
|
||||
try
|
||||
{
|
||||
pdu = nlohmann::json::parse(str);
|
||||
}
|
||||
catch (const nlohmann::json::parse_error& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "malformed json pdu: " << e.what() << " -> " << str << "";
|
||||
|
||||
nlohmann::json response = {{"body", {{"error", "invalid_json"}, {"reason", ss.str()}}}};
|
||||
ws->sendText(response.dump());
|
||||
return;
|
||||
}
|
||||
|
||||
auto action = pdu["action"];
|
||||
|
||||
if (action == "auth/handshake")
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include "IXSnakeConnectionState.h"
|
||||
#include "IXSnakeProtocol.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace snake
|
||||
@ -29,7 +29,7 @@ namespace snake
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Listening on " << appConfig.hostname << ":" << appConfig.port;
|
||||
ix::IXCoreLogger::Log(ss.str().c_str());
|
||||
ix::CoreLogger::log(ss.str().c_str());
|
||||
}
|
||||
|
||||
//
|
||||
@ -67,6 +67,7 @@ namespace snake
|
||||
webSocket->setOnMessageCallback(
|
||||
[this, webSocket, state](const ix::WebSocketMessagePtr& msg) {
|
||||
std::stringstream ss;
|
||||
ix::LogLevel logLevel = ix::LogLevel::Debug;
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
ss << "New connection" << std::endl;
|
||||
@ -86,6 +87,7 @@ namespace snake
|
||||
_appConfig.redisPort))
|
||||
{
|
||||
ss << "Cannot connect to redis host" << std::endl;
|
||||
logLevel = ix::LogLevel::Error;
|
||||
}
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||
@ -101,6 +103,7 @@ namespace snake
|
||||
ss << "#retries: " << msg->errorInfo.retries << std::endl;
|
||||
ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
|
||||
ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
|
||||
logLevel = ix::LogLevel::Error;
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Fragment)
|
||||
{
|
||||
@ -112,7 +115,7 @@ namespace snake
|
||||
processCobraMessage(state, webSocket, _appConfig, msg->str);
|
||||
}
|
||||
|
||||
ix::IXCoreLogger::Log(ss.str().c_str());
|
||||
ix::CoreLogger::log(ss.str().c_str(), logLevel);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -78,12 +78,12 @@ namespace ix
|
||||
WebSocketHttpHeaders extraHeaders;
|
||||
std::string body;
|
||||
std::string multipartBoundary;
|
||||
int connectTimeout;
|
||||
int transferTimeout;
|
||||
bool followRedirects;
|
||||
int maxRedirects;
|
||||
bool verbose;
|
||||
bool compress;
|
||||
int connectTimeout = 60;
|
||||
int transferTimeout = 1800;
|
||||
bool followRedirects = true;
|
||||
int maxRedirects = 5;
|
||||
bool verbose = false;
|
||||
bool compress = true;
|
||||
Logger logger;
|
||||
OnProgressCallback onProgressCallback;
|
||||
};
|
||||
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* IXSelectInterruptEventFd.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
//
|
||||
// On Linux we use eventd to wake up select.
|
||||
//
|
||||
|
||||
//
|
||||
// Linux/Android has a special type of virtual files. select(2) will react
|
||||
// when reading/writing to those files, unlike closing sockets.
|
||||
//
|
||||
// https://linux.die.net/man/2/eventfd
|
||||
// http://www.sourcexr.com/articles/2013/10/26/lightweight-inter-process-signaling-with-eventfd
|
||||
//
|
||||
// eventfd was added in Linux kernel 2.x, and our oldest Android (Kitkat 4.4)
|
||||
// is on Kernel 3.x
|
||||
//
|
||||
// cf Android/Kernel table here
|
||||
// https://android.stackexchange.com/questions/51651/which-android-runs-which-linux-kernel
|
||||
//
|
||||
// On macOS we use UNIX pipes to wake up select.
|
||||
//
|
||||
|
||||
#include "IXSelectInterruptEventFd.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sstream>
|
||||
#include <string.h> // for strerror
|
||||
#include <sys/eventfd.h>
|
||||
#include <unistd.h> // for write
|
||||
|
||||
namespace ix
|
||||
{
|
||||
SelectInterruptEventFd::SelectInterruptEventFd()
|
||||
{
|
||||
_eventfd = -1;
|
||||
}
|
||||
|
||||
SelectInterruptEventFd::~SelectInterruptEventFd()
|
||||
{
|
||||
::close(_eventfd);
|
||||
}
|
||||
|
||||
bool SelectInterruptEventFd::init(std::string& errorMsg)
|
||||
{
|
||||
// calling init twice is a programming error
|
||||
assert(_eventfd == -1);
|
||||
|
||||
_eventfd = eventfd(0, 0);
|
||||
if (_eventfd < 0)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "SelectInterruptEventFd::init() failed in eventfd()"
|
||||
<< " : " << strerror(errno);
|
||||
errorMsg = ss.str();
|
||||
|
||||
_eventfd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fcntl(_eventfd, F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "SelectInterruptEventFd::init() failed in fcntl() call"
|
||||
<< " : " << strerror(errno);
|
||||
errorMsg = ss.str();
|
||||
|
||||
_eventfd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SelectInterruptEventFd::notify(uint64_t value)
|
||||
{
|
||||
int fd = _eventfd;
|
||||
|
||||
if (fd == -1) return false;
|
||||
|
||||
// we should write 8 bytes for an uint64_t
|
||||
return write(fd, &value, sizeof(value)) == 8;
|
||||
}
|
||||
|
||||
// TODO: return max uint64_t for errors ?
|
||||
uint64_t SelectInterruptEventFd::read()
|
||||
{
|
||||
int fd = _eventfd;
|
||||
|
||||
uint64_t value = 0;
|
||||
::read(fd, &value, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool SelectInterruptEventFd::clear()
|
||||
{
|
||||
if (_eventfd == -1) return false;
|
||||
|
||||
// 0 is a special value ; select will not wake up
|
||||
uint64_t value = 0;
|
||||
|
||||
// we should write 8 bytes for an uint64_t
|
||||
return write(_eventfd, &value, sizeof(value)) == 8;
|
||||
}
|
||||
|
||||
int SelectInterruptEventFd::getFd() const
|
||||
{
|
||||
return _eventfd;
|
||||
}
|
||||
} // namespace ix
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* IXSelectInterruptEventFd.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXSelectInterrupt.h"
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
class SelectInterruptEventFd final : public SelectInterrupt
|
||||
{
|
||||
public:
|
||||
SelectInterruptEventFd();
|
||||
virtual ~SelectInterruptEventFd();
|
||||
|
||||
bool init(std::string& errorMsg) final;
|
||||
|
||||
bool notify(uint64_t value) final;
|
||||
bool clear() final;
|
||||
uint64_t read() final;
|
||||
int getFd() const final;
|
||||
|
||||
private:
|
||||
int _eventfd;
|
||||
};
|
||||
} // namespace ix
|
@ -376,7 +376,8 @@ namespace ix
|
||||
{
|
||||
if (isCancellationRequested && isCancellationRequested())
|
||||
{
|
||||
return std::make_pair(false, std::string());
|
||||
const std::string errorMsg("Cancellation Requested");
|
||||
return std::make_pair(false, errorMsg);
|
||||
}
|
||||
|
||||
size_t size = std::min(kChunkSize, length - output.size());
|
||||
@ -388,7 +389,8 @@ namespace ix
|
||||
}
|
||||
else if (ret <= 0 && !Socket::isWaitNeeded())
|
||||
{
|
||||
return std::make_pair(false, std::string());
|
||||
const std::string errorMsg("Recv Error");
|
||||
return std::make_pair(false, errorMsg);
|
||||
}
|
||||
|
||||
if (onProgressCallback) onProgressCallback((int) output.size(), (int) length);
|
||||
@ -397,7 +399,8 @@ namespace ix
|
||||
// This way we are not busy looping
|
||||
if (isReadyToRead(1) == PollResultType::Error)
|
||||
{
|
||||
return std::make_pair(false, std::string());
|
||||
const std::string errorMsg("Poll Error");
|
||||
return std::make_pair(false, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
/*
|
||||
* IXSocketAppleSSL.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved.
|
||||
*
|
||||
* Adapted from Satori SDK Apple SSL code.
|
||||
*/
|
||||
#ifdef IXWEBSOCKET_USE_SECURE_TRANSPORT
|
||||
|
||||
#include "IXSocketAppleSSL.h"
|
||||
|
||||
#include "IXSocketConnect.h"
|
||||
@ -307,3 +309,5 @@ namespace ix
|
||||
}
|
||||
|
||||
} // namespace ix
|
||||
|
||||
#endif // IXWEBSOCKET_USE_SECURE_TRANSPORT
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*
|
||||
* IXSocketAppleSSL.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
#ifdef IXWEBSOCKET_USE_SECURE_TRANSPORT
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -47,3 +48,5 @@ namespace ix
|
||||
};
|
||||
|
||||
} // namespace ix
|
||||
|
||||
#endif // IXWEBSOCKET_USE_SECURE_TRANSPORT
|
||||
|
@ -1,12 +1,13 @@
|
||||
/*
|
||||
* IXSocketMbedTLS.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||
* Author: Benjamin Sergeant, Max Weisel
|
||||
* Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved.
|
||||
*
|
||||
* Some code taken from
|
||||
* https://github.com/rottor12/WsClientLib/blob/master/lib/src/WsClientLib.cpp
|
||||
* and mini_client.c example from mbedtls
|
||||
*/
|
||||
#ifdef IXWEBSOCKET_USE_MBED_TLS
|
||||
|
||||
#include "IXSocketMbedTLS.h"
|
||||
|
||||
@ -103,10 +104,26 @@ namespace ix
|
||||
{
|
||||
; // FIXME
|
||||
}
|
||||
else if (mbedtls_x509_crt_parse_file(&_cacert, _tlsOptions.caFile.c_str()) < 0)
|
||||
else
|
||||
{
|
||||
errMsg = "Cannot parse CA file '" + _tlsOptions.caFile + "'";
|
||||
return false;
|
||||
if (_tlsOptions.isUsingInMemoryCAs())
|
||||
{
|
||||
const char* buffer = _tlsOptions.caFile.c_str();
|
||||
size_t bufferSize =
|
||||
_tlsOptions.caFile.size() + 1; // Needs to include null terminating
|
||||
// character otherwise mbedtls will fail.
|
||||
if (mbedtls_x509_crt_parse(
|
||||
&_cacert, (const unsigned char*) buffer, bufferSize) < 0)
|
||||
{
|
||||
errMsg = "Cannot parse CA from memory.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (mbedtls_x509_crt_parse_file(&_cacert, _tlsOptions.caFile.c_str()) < 0)
|
||||
{
|
||||
errMsg = "Cannot parse CA file '" + _tlsOptions.caFile + "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&_conf, &_cacert, NULL);
|
||||
@ -280,3 +297,5 @@ namespace ix
|
||||
}
|
||||
|
||||
} // namespace ix
|
||||
|
||||
#endif // IXWEBSOCKET_USE_MBED_TLS
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*
|
||||
* IXSocketMbedTLS.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||
* Copyright (c) 2019-2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
#ifdef IXWEBSOCKET_USE_MBED_TLS
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -54,3 +55,5 @@ namespace ix
|
||||
};
|
||||
|
||||
} // namespace ix
|
||||
|
||||
#endif // IXWEBSOCKET_USE_MBED_TLS
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* IXSocketOpenSSL.cpp
|
||||
* Author: Benjamin Sergeant, Matt DeBoer
|
||||
* Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved.
|
||||
* Author: Benjamin Sergeant, Matt DeBoer, Max Weisel
|
||||
* Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved.
|
||||
*
|
||||
* Adapted from Satori SDK OpenSSL code.
|
||||
*/
|
||||
#ifdef IXWEBSOCKET_USE_OPEN_SSL
|
||||
|
||||
#include "IXSocketOpenSSL.h"
|
||||
|
||||
@ -194,6 +195,66 @@ namespace ix
|
||||
return ctx;
|
||||
}
|
||||
|
||||
bool SocketOpenSSL::openSSLAddCARootsFromString(const std::string roots)
|
||||
{
|
||||
// Create certificate store
|
||||
X509_STORE* certificate_store = SSL_CTX_get_cert_store(_ssl_context);
|
||||
if (certificate_store == nullptr) return false;
|
||||
|
||||
// Configure to allow intermediate certs
|
||||
X509_STORE_set_flags(certificate_store,
|
||||
X509_V_FLAG_TRUSTED_FIRST | X509_V_FLAG_PARTIAL_CHAIN);
|
||||
|
||||
// Create a new buffer and populate it with the roots
|
||||
BIO* buffer = BIO_new_mem_buf((void*) roots.c_str(), static_cast<int>(roots.length()));
|
||||
if (buffer == nullptr) return false;
|
||||
|
||||
// Read each root in the buffer and add to the certificate store
|
||||
bool success = true;
|
||||
size_t number_of_roots = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Read the next root in the buffer
|
||||
X509* root = PEM_read_bio_X509_AUX(buffer, nullptr, nullptr, (void*) "");
|
||||
if (root == nullptr)
|
||||
{
|
||||
// No more certs left in the buffer, we're done.
|
||||
ERR_clear_error();
|
||||
break;
|
||||
}
|
||||
|
||||
// Try adding the root to the certificate store
|
||||
ERR_clear_error();
|
||||
if (!X509_STORE_add_cert(certificate_store, root))
|
||||
{
|
||||
// Failed to add. If the error is unrelated to the x509 lib or the cert already
|
||||
// exists, we're safe to continue.
|
||||
unsigned long error = ERR_get_error();
|
||||
if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
|
||||
ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
|
||||
{
|
||||
// Failed. Clean up and bail.
|
||||
success = false;
|
||||
X509_free(root);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up and loop
|
||||
X509_free(root);
|
||||
number_of_roots++;
|
||||
}
|
||||
|
||||
// Clean up buffer
|
||||
BIO_free(buffer);
|
||||
|
||||
// Make sure we loaded at least one certificate.
|
||||
if (number_of_roots == 0) success = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a hostname matches a pattern
|
||||
*/
|
||||
@ -402,20 +463,32 @@ namespace ix
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (SSL_CTX_load_verify_locations(
|
||||
_ssl_context, _tlsOptions.caFile.c_str(), NULL) != 1)
|
||||
else
|
||||
{
|
||||
auto sslErr = ERR_get_error();
|
||||
errMsg = "OpenSSL failed - SSL_CTX_load_verify_locations(\"" + _tlsOptions.caFile +
|
||||
"\") failed: ";
|
||||
errMsg += ERR_error_string(sslErr, nullptr);
|
||||
return false;
|
||||
}
|
||||
if (_tlsOptions.isUsingInMemoryCAs())
|
||||
{
|
||||
// Load from memory
|
||||
openSSLAddCARootsFromString(_tlsOptions.caFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SSL_CTX_load_verify_locations(
|
||||
_ssl_context, _tlsOptions.caFile.c_str(), NULL) != 1)
|
||||
{
|
||||
auto sslErr = ERR_get_error();
|
||||
errMsg = "OpenSSL failed - SSL_CTX_load_verify_locations(\"" +
|
||||
_tlsOptions.caFile + "\") failed: ";
|
||||
errMsg += ERR_error_string(sslErr, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
SSL_CTX_set_verify(_ssl_context,
|
||||
SSL_VERIFY_PEER,
|
||||
[](int preverify, X509_STORE_CTX*) -> int { return preverify; });
|
||||
SSL_CTX_set_verify_depth(_ssl_context, 4);
|
||||
SSL_CTX_set_verify(
|
||||
_ssl_context, SSL_VERIFY_PEER, [](int preverify, X509_STORE_CTX*) -> int {
|
||||
return preverify;
|
||||
});
|
||||
SSL_CTX_set_verify_depth(_ssl_context, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -525,26 +598,35 @@ namespace ix
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* root_ca_file = _tlsOptions.caFile.c_str();
|
||||
STACK_OF(X509_NAME) * rootCAs;
|
||||
rootCAs = SSL_load_client_CA_file(root_ca_file);
|
||||
if (rootCAs == NULL)
|
||||
if (_tlsOptions.isUsingInMemoryCAs())
|
||||
{
|
||||
auto sslErr = ERR_get_error();
|
||||
errMsg = "OpenSSL failed - SSL_load_client_CA_file('" + _tlsOptions.caFile +
|
||||
"') failed: ";
|
||||
errMsg += ERR_error_string(sslErr, nullptr);
|
||||
// Load from memory
|
||||
openSSLAddCARootsFromString(_tlsOptions.caFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
SSL_CTX_set_client_CA_list(_ssl_context, rootCAs);
|
||||
if (SSL_CTX_load_verify_locations(_ssl_context, root_ca_file, nullptr) != 1)
|
||||
const char* root_ca_file = _tlsOptions.caFile.c_str();
|
||||
STACK_OF(X509_NAME) * rootCAs;
|
||||
rootCAs = SSL_load_client_CA_file(root_ca_file);
|
||||
if (rootCAs == NULL)
|
||||
{
|
||||
auto sslErr = ERR_get_error();
|
||||
errMsg = "OpenSSL failed - SSL_CTX_load_verify_locations(\"" +
|
||||
_tlsOptions.caFile + "\") failed: ";
|
||||
errMsg = "OpenSSL failed - SSL_load_client_CA_file('" +
|
||||
_tlsOptions.caFile + "') failed: ";
|
||||
errMsg += ERR_error_string(sslErr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SSL_CTX_set_client_CA_list(_ssl_context, rootCAs);
|
||||
if (SSL_CTX_load_verify_locations(
|
||||
_ssl_context, root_ca_file, nullptr) != 1)
|
||||
{
|
||||
auto sslErr = ERR_get_error();
|
||||
errMsg = "OpenSSL failed - SSL_CTX_load_verify_locations(\"" +
|
||||
_tlsOptions.caFile + "\") failed: ";
|
||||
errMsg += ERR_error_string(sslErr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -731,3 +813,5 @@ namespace ix
|
||||
}
|
||||
|
||||
} // namespace ix
|
||||
|
||||
#endif // IXWEBSOCKET_USE_OPEN_SSL
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*
|
||||
* IXSocketOpenSSL.h
|
||||
* Author: Benjamin Sergeant, Matt DeBoer
|
||||
* Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved.
|
||||
* Copyright (c) 2017-2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
#ifdef IXWEBSOCKET_USE_OPEN_SSL
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -39,6 +40,7 @@ namespace ix
|
||||
void openSSLInitialize();
|
||||
std::string getSSLError(int ret);
|
||||
SSL_CTX* openSSLCreateContext(std::string& errMsg);
|
||||
bool openSSLAddCARootsFromString(const std::string roots);
|
||||
bool openSSLClientHandshake(const std::string& hostname,
|
||||
std::string& errMsg,
|
||||
const CancellationRequest& isCancellationRequested);
|
||||
@ -59,3 +61,5 @@ namespace ix
|
||||
};
|
||||
|
||||
} // namespace ix
|
||||
|
||||
#endif // IXWEBSOCKET_USE_OPEN_SSL
|
||||
|
@ -15,6 +15,7 @@ namespace ix
|
||||
const char* kTLSCAFileUseSystemDefaults = "SYSTEM";
|
||||
const char* kTLSCAFileDisableVerify = "NONE";
|
||||
const char* kTLSCiphersUseDefault = "DEFAULT";
|
||||
const char* kTLSInMemoryMarker = "-----BEGIN CERTIFICATE-----";
|
||||
|
||||
bool SocketTLSOptions::isValid() const
|
||||
{
|
||||
@ -58,6 +59,11 @@ namespace ix
|
||||
return caFile == kTLSCAFileUseSystemDefaults;
|
||||
}
|
||||
|
||||
bool SocketTLSOptions::isUsingInMemoryCAs() const
|
||||
{
|
||||
return caFile.find(kTLSInMemoryMarker) != std::string::npos;
|
||||
}
|
||||
|
||||
bool SocketTLSOptions::isPeerVerifyDisabled() const
|
||||
{
|
||||
return caFile == kTLSCAFileDisableVerify;
|
||||
|
@ -37,6 +37,8 @@ namespace ix
|
||||
|
||||
bool isUsingSystemDefaults() const;
|
||||
|
||||
bool isUsingInMemoryCAs() const;
|
||||
|
||||
bool isPeerVerifyDisabled() const;
|
||||
|
||||
bool isUsingDefaultCiphers() const;
|
||||
|
@ -1,4 +1,29 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* IXUrlParser.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
|
||||
@ -6,7 +31,308 @@
|
||||
|
||||
#include "IXUrlParser.h"
|
||||
|
||||
#include "LUrlParser.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
namespace
|
||||
{
|
||||
enum LUrlParserError
|
||||
{
|
||||
LUrlParserError_Ok = 0,
|
||||
LUrlParserError_Uninitialized = 1,
|
||||
LUrlParserError_NoUrlCharacter = 2,
|
||||
LUrlParserError_InvalidSchemeName = 3,
|
||||
LUrlParserError_NoDoubleSlash = 4,
|
||||
LUrlParserError_NoAtSign = 5,
|
||||
LUrlParserError_UnexpectedEndOfLine = 6,
|
||||
LUrlParserError_NoSlash = 7,
|
||||
};
|
||||
|
||||
class clParseURL
|
||||
{
|
||||
public:
|
||||
LUrlParserError m_ErrorCode;
|
||||
std::string m_Scheme;
|
||||
std::string m_Host;
|
||||
std::string m_Port;
|
||||
std::string m_Path;
|
||||
std::string m_Query;
|
||||
std::string m_Fragment;
|
||||
std::string m_UserName;
|
||||
std::string m_Password;
|
||||
|
||||
clParseURL()
|
||||
: m_ErrorCode(LUrlParserError_Uninitialized)
|
||||
{
|
||||
}
|
||||
|
||||
/// return 'true' if the parsing was successful
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_ErrorCode == LUrlParserError_Ok;
|
||||
}
|
||||
|
||||
/// helper to convert the port number to int, return 'true' if the port is valid (within the
|
||||
/// 0..65535 range)
|
||||
bool GetPort(int* OutPort) const;
|
||||
|
||||
/// parse the URL
|
||||
static clParseURL ParseURL(const std::string& URL);
|
||||
|
||||
private:
|
||||
explicit clParseURL(LUrlParserError ErrorCode)
|
||||
: m_ErrorCode(ErrorCode)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static bool IsSchemeValid(const std::string& SchemeName)
|
||||
{
|
||||
for (auto c : SchemeName)
|
||||
{
|
||||
if (!isalpha(c) && c != '+' && c != '-' && c != '.') return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool clParseURL::GetPort(int* OutPort) const
|
||||
{
|
||||
if (!IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Port = atoi(m_Port.c_str());
|
||||
|
||||
if (Port <= 0 || Port > 65535)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OutPort)
|
||||
{
|
||||
*OutPort = Port;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// based on RFC 1738 and RFC 3986
|
||||
clParseURL clParseURL::ParseURL(const std::string& URL)
|
||||
{
|
||||
clParseURL Result;
|
||||
|
||||
const char* CurrentString = URL.c_str();
|
||||
|
||||
/*
|
||||
* <scheme>:<scheme-specific-part>
|
||||
* <scheme> := [a-z\+\-\.]+
|
||||
* For resiliency, programs interpreting URLs should treat upper case letters as
|
||||
*equivalent to lower case in scheme names
|
||||
*/
|
||||
|
||||
// try to read scheme
|
||||
{
|
||||
const char* LocalString = strchr(CurrentString, ':');
|
||||
|
||||
if (!LocalString)
|
||||
{
|
||||
return clParseURL(LUrlParserError_NoUrlCharacter);
|
||||
}
|
||||
|
||||
// save the scheme name
|
||||
Result.m_Scheme = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
if (!IsSchemeValid(Result.m_Scheme))
|
||||
{
|
||||
return clParseURL(LUrlParserError_InvalidSchemeName);
|
||||
}
|
||||
|
||||
// scheme should be lowercase
|
||||
std::transform(
|
||||
Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower);
|
||||
|
||||
// skip ':'
|
||||
CurrentString = LocalString + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* //<user>:<password>@<host>:<port>/<url-path>
|
||||
* any ":", "@" and "/" must be normalized
|
||||
*/
|
||||
|
||||
// skip "//"
|
||||
if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash);
|
||||
if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash);
|
||||
|
||||
// check if the user name and password are specified
|
||||
bool bHasUserName = false;
|
||||
|
||||
const char* LocalString = CurrentString;
|
||||
|
||||
while (*LocalString)
|
||||
{
|
||||
if (*LocalString == '@')
|
||||
{
|
||||
// user name and password are specified
|
||||
bHasUserName = true;
|
||||
break;
|
||||
}
|
||||
else if (*LocalString == '/')
|
||||
{
|
||||
// end of <host>:<port> specification
|
||||
bHasUserName = false;
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
// user name and password
|
||||
LocalString = CurrentString;
|
||||
|
||||
if (bHasUserName)
|
||||
{
|
||||
// read user name
|
||||
while (*LocalString && *LocalString != ':' && *LocalString != '@')
|
||||
LocalString++;
|
||||
|
||||
Result.m_UserName = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
// proceed with the current pointer
|
||||
CurrentString = LocalString;
|
||||
|
||||
if (*CurrentString == ':')
|
||||
{
|
||||
// skip ':'
|
||||
CurrentString++;
|
||||
|
||||
// read password
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '@')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Password = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// skip '@'
|
||||
if (*CurrentString != '@')
|
||||
{
|
||||
return clParseURL(LUrlParserError_NoAtSign);
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
}
|
||||
|
||||
bool bHasBracket = (*CurrentString == '[');
|
||||
|
||||
// go ahead, read the host name
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString)
|
||||
{
|
||||
if (bHasBracket && *LocalString == ']')
|
||||
{
|
||||
// end of IPv6 address
|
||||
LocalString++;
|
||||
break;
|
||||
}
|
||||
else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/'))
|
||||
{
|
||||
// port number is specified
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
Result.m_Host = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// is port number specified?
|
||||
if (*CurrentString == ':')
|
||||
{
|
||||
CurrentString++;
|
||||
|
||||
// read port number
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '/')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Port = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// end of string
|
||||
if (!*CurrentString)
|
||||
{
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
// skip '/'
|
||||
if (*CurrentString != '/')
|
||||
{
|
||||
return clParseURL(LUrlParserError_NoSlash);
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
|
||||
// parse the path
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '#' && *LocalString != '?')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Path = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// check for query
|
||||
if (*CurrentString == '?')
|
||||
{
|
||||
// skip '?'
|
||||
CurrentString++;
|
||||
|
||||
// read query
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '#')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Query = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// check for fragment
|
||||
if (*CurrentString == '#')
|
||||
{
|
||||
// skip '#'
|
||||
CurrentString++;
|
||||
|
||||
// read fragment
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString)
|
||||
LocalString++;
|
||||
|
||||
Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString);
|
||||
}
|
||||
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace ix
|
||||
{
|
||||
@ -17,7 +343,7 @@ namespace ix
|
||||
std::string& query,
|
||||
int& port)
|
||||
{
|
||||
LUrlParser::clParseURL res = LUrlParser::clParseURL::ParseURL(url);
|
||||
clParseURL res = clParseURL::ParseURL(url);
|
||||
|
||||
if (!res.IsValid())
|
||||
{
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
struct WebSocketCloseInfo
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "IXSocketConnect.h"
|
||||
#include "IXUrlParser.h"
|
||||
#include "IXUserAgent.h"
|
||||
#include "libwshandshake.hpp"
|
||||
#include "IXWebSocketHandshakeKeyGen.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
@ -133,7 +133,7 @@ namespace ix
|
||||
|
||||
for (auto& it : extraHeaders)
|
||||
{
|
||||
ss << it.first << ":" << it.second << "\r\n";
|
||||
ss << it.first << ": " << it.second << "\r\n";
|
||||
}
|
||||
|
||||
if (_enablePerMessageDeflate)
|
||||
|
171
ixwebsocket/IXWebSocketHandshakeKeyGen.h
Normal file
171
ixwebsocket/IXWebSocketHandshakeKeyGen.h
Normal file
@ -0,0 +1,171 @@
|
||||
// Copyright (c) 2016 Alex Hultman and contributors
|
||||
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgement in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
class WebSocketHandshakeKeyGen
|
||||
{
|
||||
template<int N, typename T>
|
||||
struct static_for
|
||||
{
|
||||
void operator()(uint32_t* a, uint32_t* b)
|
||||
{
|
||||
static_for<N - 1, T>()(a, b);
|
||||
T::template f<N - 1>(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct static_for<0, T>
|
||||
{
|
||||
void operator()(uint32_t* /*a*/, uint32_t* /*hash*/)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<int state>
|
||||
struct Sha1Loop
|
||||
{
|
||||
static inline uint32_t rol(uint32_t value, size_t bits)
|
||||
{
|
||||
return (value << bits) | (value >> (32 - bits));
|
||||
}
|
||||
static inline uint32_t blk(uint32_t b[16], size_t i)
|
||||
{
|
||||
return rol(b[(i + 13) & 15] ^ b[(i + 8) & 15] ^ b[(i + 2) & 15] ^ b[i], 1);
|
||||
}
|
||||
|
||||
template<int i>
|
||||
static inline void f(uint32_t* a, uint32_t* b)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case 1:
|
||||
a[i % 5] +=
|
||||
((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) +
|
||||
b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 2:
|
||||
b[i] = blk(b, i);
|
||||
a[(1 + i) % 5] +=
|
||||
((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) +
|
||||
b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5);
|
||||
a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30);
|
||||
break;
|
||||
case 3:
|
||||
b[(i + 4) % 16] = blk(b, (i + 4) % 16);
|
||||
a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) +
|
||||
b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 4:
|
||||
b[(i + 8) % 16] = blk(b, (i + 8) % 16);
|
||||
a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) |
|
||||
(a[(3 + i) % 5] & a[(2 + i) % 5])) +
|
||||
b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 5:
|
||||
b[(i + 12) % 16] = blk(b, (i + 12) % 16);
|
||||
a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) +
|
||||
b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 6: b[i] += a[4 - i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static inline void sha1(uint32_t hash[5], uint32_t b[16])
|
||||
{
|
||||
uint32_t a[5] = {hash[4], hash[3], hash[2], hash[1], hash[0]};
|
||||
static_for<16, Sha1Loop<1>>()(a, b);
|
||||
static_for<4, Sha1Loop<2>>()(a, b);
|
||||
static_for<20, Sha1Loop<3>>()(a, b);
|
||||
static_for<20, Sha1Loop<4>>()(a, b);
|
||||
static_for<20, Sha1Loop<5>>()(a, b);
|
||||
static_for<5, Sha1Loop<6>>()(a, hash);
|
||||
}
|
||||
|
||||
static inline void base64(unsigned char* src, char* dst)
|
||||
{
|
||||
const char* b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
for (int i = 0; i < 18; i += 3)
|
||||
{
|
||||
*dst++ = b64[(src[i] >> 2) & 63];
|
||||
*dst++ = b64[((src[i] & 3) << 4) | ((src[i + 1] & 240) >> 4)];
|
||||
*dst++ = b64[((src[i + 1] & 15) << 2) | ((src[i + 2] & 192) >> 6)];
|
||||
*dst++ = b64[src[i + 2] & 63];
|
||||
}
|
||||
*dst++ = b64[(src[18] >> 2) & 63];
|
||||
*dst++ = b64[((src[18] & 3) << 4) | ((src[19] & 240) >> 4)];
|
||||
*dst++ = b64[((src[19] & 15) << 2)];
|
||||
*dst++ = '=';
|
||||
}
|
||||
|
||||
public:
|
||||
static inline void generate(const std::string& inputStr, char output[28])
|
||||
{
|
||||
char input[25] = {};
|
||||
strncpy(input, inputStr.c_str(), 25 - 1);
|
||||
input[25 - 1] = '\0';
|
||||
|
||||
uint32_t b_output[5] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0};
|
||||
uint32_t b_input[16] = {0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x32353845,
|
||||
0x41464135,
|
||||
0x2d453931,
|
||||
0x342d3437,
|
||||
0x44412d39,
|
||||
0x3543412d,
|
||||
0x43354142,
|
||||
0x30444338,
|
||||
0x35423131,
|
||||
0x80000000};
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
b_input[i] = (input[4 * i + 3] & 0xff) | (input[4 * i + 2] & 0xff) << 8 |
|
||||
(input[4 * i + 1] & 0xff) << 16 | (input[4 * i + 0] & 0xff) << 24;
|
||||
}
|
||||
sha1(b_output, b_input);
|
||||
uint32_t last_b[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480};
|
||||
sha1(b_output, last_b);
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
uint32_t tmp = b_output[i];
|
||||
char* bytes = (char*) &b_output[i];
|
||||
bytes[3] = tmp & 0xff;
|
||||
bytes[2] = (tmp >> 8) & 0xff;
|
||||
bytes[1] = (tmp >> 16) & 0xff;
|
||||
bytes[0] = (tmp >> 24) & 0xff;
|
||||
}
|
||||
base64((unsigned char*) b_output, output);
|
||||
}
|
||||
};
|
@ -6,6 +6,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXWebSocketHttpHeaders.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
struct WebSocketOpenInfo
|
||||
|
@ -74,6 +74,7 @@ namespace ix
|
||||
, _enablePong(kDefaultEnablePong)
|
||||
, _pingIntervalSecs(kDefaultPingIntervalSecs)
|
||||
, _pongReceived(false)
|
||||
, _pingCount(0)
|
||||
, _lastSendPingTimePoint(std::chrono::steady_clock::now())
|
||||
{
|
||||
_readbuf.resize(kChunkSize);
|
||||
@ -221,7 +222,8 @@ namespace ix
|
||||
{
|
||||
_pongReceived = false;
|
||||
std::stringstream ss;
|
||||
ss << kPingMessage << "::" << _pingIntervalSecs << "s";
|
||||
ss << kPingMessage << "::" << _pingIntervalSecs << "s"
|
||||
<< "::" << _pingCount++;
|
||||
return sendPing(ss.str());
|
||||
}
|
||||
|
||||
@ -515,8 +517,10 @@ namespace ix
|
||||
//
|
||||
if (ws.fin && _chunks.empty())
|
||||
{
|
||||
emitMessage(
|
||||
_fragmentedMessageKind, frameData, _receivedMessageCompressed, onMessageCallback);
|
||||
emitMessage(_fragmentedMessageKind,
|
||||
frameData,
|
||||
_receivedMessageCompressed,
|
||||
onMessageCallback);
|
||||
|
||||
_receivedMessageCompressed = false;
|
||||
}
|
||||
|
@ -212,6 +212,7 @@ namespace ix
|
||||
|
||||
static const int kDefaultPingIntervalSecs;
|
||||
static const std::string kPingMessage;
|
||||
std::atomic<uint64_t> _pingCount;
|
||||
|
||||
// We record when ping are being sent so that we can know when to send the next one
|
||||
mutable std::mutex _lastSendPingTimePointMutex;
|
||||
|
@ -6,4 +6,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IX_WEBSOCKET_VERSION "9.2.5"
|
||||
#define IX_WEBSOCKET_VERSION "9.5.2"
|
||||
|
@ -1,280 +0,0 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "LUrlParser.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
|
||||
// check if the scheme name is valid
|
||||
static bool IsSchemeValid(const std::string& SchemeName)
|
||||
{
|
||||
for (auto c : SchemeName)
|
||||
{
|
||||
if (!isalpha(c) && c != '+' && c != '-' && c != '.') return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LUrlParser::clParseURL::GetPort(int* OutPort) const
|
||||
{
|
||||
if (!IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Port = atoi(m_Port.c_str());
|
||||
|
||||
if (Port <= 0 || Port > 65535)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OutPort)
|
||||
{
|
||||
*OutPort = Port;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// based on RFC 1738 and RFC 3986
|
||||
LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL(const std::string& URL)
|
||||
{
|
||||
LUrlParser::clParseURL Result;
|
||||
|
||||
const char* CurrentString = URL.c_str();
|
||||
|
||||
/*
|
||||
* <scheme>:<scheme-specific-part>
|
||||
* <scheme> := [a-z\+\-\.]+
|
||||
* For resiliency, programs interpreting URLs should treat upper case letters as equivalent to
|
||||
*lower case in scheme names
|
||||
*/
|
||||
|
||||
// try to read scheme
|
||||
{
|
||||
const char* LocalString = strchr(CurrentString, ':');
|
||||
|
||||
if (!LocalString)
|
||||
{
|
||||
return clParseURL(LUrlParserError_NoUrlCharacter);
|
||||
}
|
||||
|
||||
// save the scheme name
|
||||
Result.m_Scheme = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
if (!IsSchemeValid(Result.m_Scheme))
|
||||
{
|
||||
return clParseURL(LUrlParserError_InvalidSchemeName);
|
||||
}
|
||||
|
||||
// scheme should be lowercase
|
||||
std::transform(
|
||||
Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower);
|
||||
|
||||
// skip ':'
|
||||
CurrentString = LocalString + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* //<user>:<password>@<host>:<port>/<url-path>
|
||||
* any ":", "@" and "/" must be normalized
|
||||
*/
|
||||
|
||||
// skip "//"
|
||||
if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash);
|
||||
if (*CurrentString++ != '/') return clParseURL(LUrlParserError_NoDoubleSlash);
|
||||
|
||||
// check if the user name and password are specified
|
||||
bool bHasUserName = false;
|
||||
|
||||
const char* LocalString = CurrentString;
|
||||
|
||||
while (*LocalString)
|
||||
{
|
||||
if (*LocalString == '@')
|
||||
{
|
||||
// user name and password are specified
|
||||
bHasUserName = true;
|
||||
break;
|
||||
}
|
||||
else if (*LocalString == '/')
|
||||
{
|
||||
// end of <host>:<port> specification
|
||||
bHasUserName = false;
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
// user name and password
|
||||
LocalString = CurrentString;
|
||||
|
||||
if (bHasUserName)
|
||||
{
|
||||
// read user name
|
||||
while (*LocalString && *LocalString != ':' && *LocalString != '@')
|
||||
LocalString++;
|
||||
|
||||
Result.m_UserName = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
// proceed with the current pointer
|
||||
CurrentString = LocalString;
|
||||
|
||||
if (*CurrentString == ':')
|
||||
{
|
||||
// skip ':'
|
||||
CurrentString++;
|
||||
|
||||
// read password
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '@')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Password = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// skip '@'
|
||||
if (*CurrentString != '@')
|
||||
{
|
||||
return clParseURL(LUrlParserError_NoAtSign);
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
}
|
||||
|
||||
bool bHasBracket = (*CurrentString == '[');
|
||||
|
||||
// go ahead, read the host name
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString)
|
||||
{
|
||||
if (bHasBracket && *LocalString == ']')
|
||||
{
|
||||
// end of IPv6 address
|
||||
LocalString++;
|
||||
break;
|
||||
}
|
||||
else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/'))
|
||||
{
|
||||
// port number is specified
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
Result.m_Host = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// is port number specified?
|
||||
if (*CurrentString == ':')
|
||||
{
|
||||
CurrentString++;
|
||||
|
||||
// read port number
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '/')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Port = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// end of string
|
||||
if (!*CurrentString)
|
||||
{
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
// skip '/'
|
||||
if (*CurrentString != '/')
|
||||
{
|
||||
return clParseURL(LUrlParserError_NoSlash);
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
|
||||
// parse the path
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '#' && *LocalString != '?')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Path = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// check for query
|
||||
if (*CurrentString == '?')
|
||||
{
|
||||
// skip '?'
|
||||
CurrentString++;
|
||||
|
||||
// read query
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString && *LocalString != '#')
|
||||
LocalString++;
|
||||
|
||||
Result.m_Query = std::string(CurrentString, LocalString - CurrentString);
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// check for fragment
|
||||
if (*CurrentString == '#')
|
||||
{
|
||||
// skip '#'
|
||||
CurrentString++;
|
||||
|
||||
// read fragment
|
||||
LocalString = CurrentString;
|
||||
|
||||
while (*LocalString)
|
||||
LocalString++;
|
||||
|
||||
Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString);
|
||||
}
|
||||
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace LUrlParser
|
||||
{
|
||||
enum LUrlParserError
|
||||
{
|
||||
LUrlParserError_Ok = 0,
|
||||
LUrlParserError_Uninitialized = 1,
|
||||
LUrlParserError_NoUrlCharacter = 2,
|
||||
LUrlParserError_InvalidSchemeName = 3,
|
||||
LUrlParserError_NoDoubleSlash = 4,
|
||||
LUrlParserError_NoAtSign = 5,
|
||||
LUrlParserError_UnexpectedEndOfLine = 6,
|
||||
LUrlParserError_NoSlash = 7,
|
||||
};
|
||||
|
||||
class clParseURL
|
||||
{
|
||||
public:
|
||||
LUrlParserError m_ErrorCode;
|
||||
std::string m_Scheme;
|
||||
std::string m_Host;
|
||||
std::string m_Port;
|
||||
std::string m_Path;
|
||||
std::string m_Query;
|
||||
std::string m_Fragment;
|
||||
std::string m_UserName;
|
||||
std::string m_Password;
|
||||
|
||||
clParseURL()
|
||||
: m_ErrorCode(LUrlParserError_Uninitialized)
|
||||
{
|
||||
}
|
||||
|
||||
/// return 'true' if the parsing was successful
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_ErrorCode == LUrlParserError_Ok;
|
||||
}
|
||||
|
||||
/// helper to convert the port number to int, return 'true' if the port is valid (within the
|
||||
/// 0..65535 range)
|
||||
bool GetPort(int* OutPort) const;
|
||||
|
||||
/// parse the URL
|
||||
static clParseURL ParseURL(const std::string& URL);
|
||||
|
||||
private:
|
||||
explicit clParseURL(LUrlParserError ErrorCode)
|
||||
: m_ErrorCode(ErrorCode)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace LUrlParser
|
@ -1,135 +0,0 @@
|
||||
// Copyright (c) 2016 Alex Hultman and contributors
|
||||
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgement in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
class WebSocketHandshakeKeyGen {
|
||||
template <int N, typename T>
|
||||
struct static_for {
|
||||
void operator()(uint32_t *a, uint32_t *b) {
|
||||
static_for<N - 1, T>()(a, b);
|
||||
T::template f<N - 1>(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct static_for<0, T> {
|
||||
void operator()(uint32_t * /*a*/, uint32_t * /*hash*/) {}
|
||||
};
|
||||
|
||||
template <int state>
|
||||
struct Sha1Loop {
|
||||
static inline uint32_t rol(uint32_t value, size_t bits) {return (value << bits) | (value >> (32 - bits));}
|
||||
static inline uint32_t blk(uint32_t b[16], size_t i) {
|
||||
return rol(b[(i + 13) & 15] ^ b[(i + 8) & 15] ^ b[(i + 2) & 15] ^ b[i], 1);
|
||||
}
|
||||
|
||||
template <int i>
|
||||
static inline void f(uint32_t *a, uint32_t *b) {
|
||||
switch (state) {
|
||||
case 1:
|
||||
a[i % 5] += ((a[(3 + i) % 5] & (a[(2 + i) % 5] ^ a[(1 + i) % 5])) ^ a[(1 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 2:
|
||||
b[i] = blk(b, i);
|
||||
a[(1 + i) % 5] += ((a[(4 + i) % 5] & (a[(3 + i) % 5] ^ a[(2 + i) % 5])) ^ a[(2 + i) % 5]) + b[i] + 0x5a827999 + rol(a[(5 + i) % 5], 5);
|
||||
a[(4 + i) % 5] = rol(a[(4 + i) % 5], 30);
|
||||
break;
|
||||
case 3:
|
||||
b[(i + 4) % 16] = blk(b, (i + 4) % 16);
|
||||
a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 4) % 16] + 0x6ed9eba1 + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 4:
|
||||
b[(i + 8) % 16] = blk(b, (i + 8) % 16);
|
||||
a[i % 5] += (((a[(3 + i) % 5] | a[(2 + i) % 5]) & a[(1 + i) % 5]) | (a[(3 + i) % 5] & a[(2 + i) % 5])) + b[(i + 8) % 16] + 0x8f1bbcdc + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 5:
|
||||
b[(i + 12) % 16] = blk(b, (i + 12) % 16);
|
||||
a[i % 5] += (a[(3 + i) % 5] ^ a[(2 + i) % 5] ^ a[(1 + i) % 5]) + b[(i + 12) % 16] + 0xca62c1d6 + rol(a[(4 + i) % 5], 5);
|
||||
a[(3 + i) % 5] = rol(a[(3 + i) % 5], 30);
|
||||
break;
|
||||
case 6:
|
||||
b[i] += a[4 - i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static inline void sha1(uint32_t hash[5], uint32_t b[16]) {
|
||||
uint32_t a[5] = {hash[4], hash[3], hash[2], hash[1], hash[0]};
|
||||
static_for<16, Sha1Loop<1>>()(a, b);
|
||||
static_for<4, Sha1Loop<2>>()(a, b);
|
||||
static_for<20, Sha1Loop<3>>()(a, b);
|
||||
static_for<20, Sha1Loop<4>>()(a, b);
|
||||
static_for<20, Sha1Loop<5>>()(a, b);
|
||||
static_for<5, Sha1Loop<6>>()(a, hash);
|
||||
}
|
||||
|
||||
static inline void base64(unsigned char *src, char *dst) {
|
||||
const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
for (int i = 0; i < 18; i += 3) {
|
||||
*dst++ = b64[(src[i] >> 2) & 63];
|
||||
*dst++ = b64[((src[i] & 3) << 4) | ((src[i + 1] & 240) >> 4)];
|
||||
*dst++ = b64[((src[i + 1] & 15) << 2) | ((src[i + 2] & 192) >> 6)];
|
||||
*dst++ = b64[src[i + 2] & 63];
|
||||
}
|
||||
*dst++ = b64[(src[18] >> 2) & 63];
|
||||
*dst++ = b64[((src[18] & 3) << 4) | ((src[19] & 240) >> 4)];
|
||||
*dst++ = b64[((src[19] & 15) << 2)];
|
||||
*dst++ = '=';
|
||||
}
|
||||
|
||||
public:
|
||||
static inline void generate(const std::string& inputStr, char output[28]) {
|
||||
|
||||
char input[25] = {};
|
||||
strncpy(input, inputStr.c_str(), 25 - 1);
|
||||
input[25 - 1] = '\0';
|
||||
|
||||
uint32_t b_output[5] = {
|
||||
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
|
||||
};
|
||||
uint32_t b_input[16] = {
|
||||
0, 0, 0, 0, 0, 0, 0x32353845, 0x41464135, 0x2d453931, 0x342d3437, 0x44412d39,
|
||||
0x3543412d, 0x43354142, 0x30444338, 0x35423131, 0x80000000
|
||||
};
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
b_input[i] = (input[4 * i + 3] & 0xff) | (input[4 * i + 2] & 0xff) << 8 | (input[4 * i + 1] & 0xff) << 16 | (input[4 * i + 0] & 0xff) << 24;
|
||||
}
|
||||
sha1(b_output, b_input);
|
||||
uint32_t last_b[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480};
|
||||
sha1(b_output, last_b);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
uint32_t tmp = b_output[i];
|
||||
char *bytes = (char *) &b_output[i];
|
||||
bytes[3] = tmp & 0xff;
|
||||
bytes[2] = (tmp >> 8) & 0xff;
|
||||
bytes[1] = (tmp >> 16) & 0xff;
|
||||
bytes[0] = (tmp >> 24) & 0xff;
|
||||
}
|
||||
base64((unsigned char *) b_output, output);
|
||||
}
|
||||
};
|
8
makefile
8
makefile
@ -20,7 +20,7 @@ install: brew
|
||||
# Release, Debug, MinSizeRel, RelWithDebInfo are the build types
|
||||
#
|
||||
brew:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4 install)
|
||||
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)
|
||||
|
||||
# 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
|
||||
@ -116,10 +116,12 @@ test_ubsan:
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_asan:
|
||||
test_asan: build_test_asan
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
build_test_asan:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableAddressSanitizer YES)
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_tsan_openssl:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
|
@ -66,6 +66,7 @@ if (UNIX)
|
||||
IXCobraMetricsPublisherTest.cpp
|
||||
IXCobraToSentryBotTest.cpp
|
||||
IXCobraToStatsdBotTest.cpp
|
||||
IXCobraToStdoutBotTest.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -180,44 +180,40 @@ namespace
|
||||
_conn.configure(_cobraConfig);
|
||||
_conn.connect();
|
||||
|
||||
_conn.setEventCallback([this, channel](ix::CobraConnectionEventType eventType,
|
||||
const std::string& errMsg,
|
||||
const ix::WebSocketHttpHeaders& headers,
|
||||
const std::string& subscriptionId,
|
||||
CobraConnection::MsgId msgId) {
|
||||
if (eventType == ix::CobraConnection_EventType_Open)
|
||||
_conn.setEventCallback([this, channel](const CobraEventPtr& event) {
|
||||
if (event->type == ix::CobraEventType::Open)
|
||||
{
|
||||
log("Subscriber connected: " + _user);
|
||||
for (auto&& it : headers)
|
||||
for (auto&& it : event->headers)
|
||||
{
|
||||
log("Headers " + it.first + " " + it.second);
|
||||
}
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
||||
else if (event->type == ix::CobraEventType::Authenticated)
|
||||
{
|
||||
log("Subscriber authenticated: " + _user);
|
||||
subscribe(channel);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Error)
|
||||
else if (event->type == ix::CobraEventType::Error)
|
||||
{
|
||||
log(errMsg + _user);
|
||||
log(event->errMsg + _user);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Closed)
|
||||
else if (event->type == ix::CobraEventType::Closed)
|
||||
{
|
||||
log("Connection closed: " + _user);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
||||
else if (event->type == ix::CobraEventType::Subscribed)
|
||||
{
|
||||
log("Subscription ok: " + _user + " subscription_id " + subscriptionId);
|
||||
log("Subscription ok: " + _user + " subscription_id " + event->subscriptionId);
|
||||
_connectedAndSubscribed = true;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
||||
else if (event->type == ix::CobraEventType::UnSubscribed)
|
||||
{
|
||||
log("Unsubscription ok: " + _user + " subscription_id " + subscriptionId);
|
||||
log("Unsubscription ok: " + _user + " subscription_id " + event->subscriptionId);
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Published)
|
||||
else if (event->type == ix::CobraEventType::Published)
|
||||
{
|
||||
TLogger() << "Subscriber: published message acked: " << msgId;
|
||||
TLogger() << "Subscriber: published message acked: " << event->msgId;
|
||||
}
|
||||
});
|
||||
|
||||
@ -248,11 +244,7 @@ namespace
|
||||
ix::msleep(50);
|
||||
_conn.disconnect();
|
||||
|
||||
_conn.setEventCallback([](ix::CobraConnectionEventType /*eventType*/,
|
||||
const std::string& /*errMsg*/,
|
||||
const ix::WebSocketHttpHeaders& /*headers*/,
|
||||
const std::string& /*subscriptionId*/,
|
||||
CobraConnection::MsgId /*msgId*/) { ; });
|
||||
_conn.setEventCallback([](const CobraEventPtr& /*event*/) {});
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -54,24 +54,24 @@ namespace
|
||||
conn.configure(config);
|
||||
conn.connect();
|
||||
|
||||
conn.setEventCallback([&conn, &channel](ix::CobraConnectionEventType eventType,
|
||||
const std::string& errMsg,
|
||||
const ix::WebSocketHttpHeaders& headers,
|
||||
const std::string& subscriptionId,
|
||||
CobraConnection::MsgId msgId) {
|
||||
if (eventType == ix::CobraConnection_EventType_Open)
|
||||
conn.setEventCallback([&conn, &channel](const CobraEventPtr& event) {
|
||||
if (event->type == ix::CobraEventType::Open)
|
||||
{
|
||||
TLogger() << "Subscriber connected:";
|
||||
for (auto&& it : headers)
|
||||
for (auto&& it : event->headers)
|
||||
{
|
||||
log("Headers " + it.first + " " + it.second);
|
||||
}
|
||||
}
|
||||
if (eventType == ix::CobraConnection_EventType_Error)
|
||||
else if (event->type == ix::CobraEventType::Closed)
|
||||
{
|
||||
TLogger() << "Subscriber error:" << errMsg;
|
||||
TLogger() << "Subscriber closed:" << event->errMsg;
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Authenticated)
|
||||
else if (event->type == ix::CobraEventType::Error)
|
||||
{
|
||||
TLogger() << "Subscriber error:" << event->errMsg;
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Authenticated)
|
||||
{
|
||||
log("Subscriber authenticated");
|
||||
std::string filter;
|
||||
@ -92,29 +92,29 @@ namespace
|
||||
gMessageCount++;
|
||||
});
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Subscribed)
|
||||
else if (event->type == ix::CobraEventType::Subscribed)
|
||||
{
|
||||
TLogger() << "Subscriber: subscribed to channel " << subscriptionId;
|
||||
if (subscriptionId == channel)
|
||||
TLogger() << "Subscriber: subscribed to channel " << event->subscriptionId;
|
||||
if (event->subscriptionId == channel)
|
||||
{
|
||||
gSubscriberConnectedAndSubscribed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
TLogger() << "Subscriber: unexpected channel " << subscriptionId;
|
||||
TLogger() << "Subscriber: unexpected channel " << event->subscriptionId;
|
||||
}
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
|
||||
else if (event->type == ix::CobraEventType::UnSubscribed)
|
||||
{
|
||||
TLogger() << "Subscriber: ununexpected from channel " << subscriptionId;
|
||||
if (subscriptionId != channel)
|
||||
TLogger() << "Subscriber: ununexpected from channel " << event->subscriptionId;
|
||||
if (event->subscriptionId != channel)
|
||||
{
|
||||
TLogger() << "Subscriber: unexpected channel " << subscriptionId;
|
||||
TLogger() << "Subscriber: unexpected channel " << event->subscriptionId;
|
||||
}
|
||||
}
|
||||
else if (eventType == ix::CobraConnection_EventType_Published)
|
||||
else if (event->type == ix::CobraEventType::Published)
|
||||
{
|
||||
TLogger() << "Subscriber: published message acked: " << msgId;
|
||||
TLogger() << "Subscriber: published message acked: " << event->msgId;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -141,7 +141,6 @@ TEST_CASE("Cobra_to_sentry_bot", "[cobra_bots]")
|
||||
std::string filter;
|
||||
std::string position("$");
|
||||
bool verbose = true;
|
||||
bool strict = true;
|
||||
size_t maxQueueSize = 10;
|
||||
bool enableHeartbeat = false;
|
||||
|
||||
@ -161,16 +160,15 @@ TEST_CASE("Cobra_to_sentry_bot", "[cobra_bots]")
|
||||
// Only run the bot for 3 seconds
|
||||
int runtime = 3;
|
||||
|
||||
int sentCount = cobra_to_sentry_bot(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
sentryClient,
|
||||
verbose,
|
||||
strict,
|
||||
maxQueueSize,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
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
|
||||
//
|
||||
|
@ -114,18 +114,18 @@ TEST_CASE("Cobra_to_statsd_bot", "[cobra_bots]")
|
||||
std::string gauge;
|
||||
std::string timer;
|
||||
|
||||
int sentCount = ix::cobra_to_statsd_bot(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
statsdClient,
|
||||
fields,
|
||||
gauge,
|
||||
timer,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
int64_t sentCount = ix::cobra_to_statsd_bot(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
statsdClient,
|
||||
fields,
|
||||
gauge,
|
||||
timer,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
//
|
||||
// We want at least 2 messages to be sent
|
||||
//
|
||||
|
127
test/IXCobraToStdoutBotTest.cpp
Normal file
127
test/IXCobraToStdoutBotTest.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* IXCobraToStdoutTest.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXTest.h"
|
||||
#include "catch.hpp"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <ixbots/IXCobraToStdoutBot.h>
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcobra/IXCobraMetricsPublisher.h>
|
||||
#include <ixcrypto/IXUuid.h>
|
||||
#include <ixsentry/IXSentryClient.h>
|
||||
#include <ixsnake/IXRedisServer.h>
|
||||
#include <ixsnake/IXSnakeServer.h>
|
||||
#include <ixwebsocket/IXHttpServer.h>
|
||||
#include <ixwebsocket/IXUserAgent.h>
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace
|
||||
{
|
||||
void runPublisher(const ix::CobraConfig& config, const std::string& channel)
|
||||
{
|
||||
ix::CobraMetricsPublisher cobraMetricsPublisher;
|
||||
cobraMetricsPublisher.configure(config, channel);
|
||||
cobraMetricsPublisher.setSession(uuid4());
|
||||
cobraMetricsPublisher.enable(true);
|
||||
|
||||
Json::Value msg;
|
||||
msg["fps"] = 60;
|
||||
|
||||
cobraMetricsPublisher.setGenericAttributes("game", "ody");
|
||||
|
||||
// Wait a bit
|
||||
ix::msleep(500);
|
||||
|
||||
// publish some messages
|
||||
cobraMetricsPublisher.push("sms_metric_A_id", msg); // (msg #1)
|
||||
cobraMetricsPublisher.push("sms_metric_B_id", msg); // (msg #2)
|
||||
ix::msleep(500);
|
||||
|
||||
cobraMetricsPublisher.push("sms_metric_A_id", msg); // (msg #3)
|
||||
cobraMetricsPublisher.push("sms_metric_D_id", msg); // (msg #4)
|
||||
ix::msleep(500);
|
||||
|
||||
cobraMetricsPublisher.push("sms_metric_A_id", msg); // (msg #4)
|
||||
cobraMetricsPublisher.push("sms_metric_F_id", msg); // (msg #5)
|
||||
ix::msleep(500);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Cobra_to_stdout_bot", "[cobra_bots]")
|
||||
{
|
||||
SECTION("Exchange and count sent/received messages.")
|
||||
{
|
||||
int port = getFreePort();
|
||||
snake::AppConfig appConfig = makeSnakeServerConfig(port, true);
|
||||
|
||||
// Start a redis server
|
||||
ix::RedisServer redisServer(appConfig.redisPort);
|
||||
auto res = redisServer.listen();
|
||||
REQUIRE(res.first);
|
||||
redisServer.start();
|
||||
|
||||
// Start a snake server
|
||||
snake::SnakeServer snakeServer(appConfig);
|
||||
snakeServer.run();
|
||||
|
||||
// Run the bot for a small amount of time
|
||||
std::string channel = ix::generateSessionId();
|
||||
std::string appkey("FC2F10139A2BAc53BB72D9db967b024f");
|
||||
std::string role = "_sub";
|
||||
std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba";
|
||||
std::string endpoint = makeCobraEndpoint(port, true);
|
||||
|
||||
ix::CobraConfig config;
|
||||
config.endpoint = endpoint;
|
||||
config.appkey = appkey;
|
||||
config.rolename = role;
|
||||
config.rolesecret = secret;
|
||||
config.socketTLSOptions = makeClientTLSOptions();
|
||||
|
||||
std::thread publisherThread(runPublisher, config, channel);
|
||||
|
||||
std::string filter;
|
||||
std::string position("$");
|
||||
bool verbose = true;
|
||||
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.
|
||||
bool fluentd = true;
|
||||
|
||||
int64_t sentCount = ix::cobra_to_stdout_bot(config,
|
||||
channel,
|
||||
filter,
|
||||
position,
|
||||
fluentd,
|
||||
quiet,
|
||||
verbose,
|
||||
maxQueueSize,
|
||||
enableHeartbeat,
|
||||
runtime);
|
||||
//
|
||||
// We want at least 2 messages to be sent
|
||||
//
|
||||
REQUIRE(sentCount >= 2);
|
||||
|
||||
// Give us 1s for all messages to be received
|
||||
ix::msleep(1000);
|
||||
|
||||
spdlog::info("Stopping snake server...");
|
||||
snakeServer.stop();
|
||||
|
||||
spdlog::info("Stopping redis server...");
|
||||
redisServer.stop();
|
||||
|
||||
publisherThread.join();
|
||||
}
|
||||
}
|
@ -17,8 +17,11 @@
|
||||
#include <ixwebsocket/IXSelectInterruptFactory.h>
|
||||
#include <ixwebsocket/IXSetThreadName.h>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <ixwebsocket/IXSocketAppleSSL.h>
|
||||
#include <ixwebsocket/IXSocketConnect.h>
|
||||
#include <ixwebsocket/IXSocketFactory.h>
|
||||
#include <ixwebsocket/IXSocketMbedTLS.h>
|
||||
#include <ixwebsocket/IXSocketOpenSSL.h>
|
||||
#include <ixwebsocket/IXSocketServer.h>
|
||||
#include <ixwebsocket/IXUrlParser.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
@ -26,6 +29,7 @@
|
||||
#include <ixwebsocket/IXWebSocketCloseInfo.h>
|
||||
#include <ixwebsocket/IXWebSocketErrorInfo.h>
|
||||
#include <ixwebsocket/IXWebSocketHandshake.h>
|
||||
#include <ixwebsocket/IXWebSocketHandshakeKeyGen.h>
|
||||
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
|
||||
#include <ixwebsocket/IXWebSocketMessage.h>
|
||||
#include <ixwebsocket/IXWebSocketMessageType.h>
|
||||
@ -36,8 +40,6 @@
|
||||
#include <ixwebsocket/IXWebSocketSendInfo.h>
|
||||
#include <ixwebsocket/IXWebSocketServer.h>
|
||||
#include <ixwebsocket/IXWebSocketTransport.h>
|
||||
#include <ixwebsocket/LUrlParser.h>
|
||||
#include <ixwebsocket/libwshandshake.hpp>
|
||||
|
||||
using namespace ix;
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include "IXTest.h"
|
||||
#include "catch.hpp"
|
||||
#include <iostream>
|
||||
#include "msgpack11.hpp"
|
||||
#include <iostream>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <ixwebsocket/IXSocketFactory.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
@ -130,7 +130,8 @@ namespace
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Error)
|
||||
{
|
||||
ss << "websocket_broadcast_client: " << _user << " Error ! " << msg->errorInfo.reason;
|
||||
ss << "websocket_broadcast_client: " << _user << " Error ! "
|
||||
<< msg->errorInfo.reason;
|
||||
log(ss.str());
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Ping)
|
||||
@ -234,7 +235,7 @@ namespace
|
||||
server.start();
|
||||
return true;
|
||||
}
|
||||
} // namespace ix
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Websocket_broadcast_server", "[websocket_server]")
|
||||
{
|
||||
@ -247,7 +248,7 @@ TEST_CASE("Websocket_broadcast_server", "[websocket_server]")
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
std::vector<std::shared_ptr<WebSocketChat>> chatClients;
|
||||
for (int i = 0 ; i < 10; ++i)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
std::string user("user_" + std::to_string(i));
|
||||
chatClients.push_back(std::make_shared<WebSocketChat>(user, session, port));
|
||||
@ -259,7 +260,7 @@ TEST_CASE("Websocket_broadcast_server", "[websocket_server]")
|
||||
while (true)
|
||||
{
|
||||
bool allReady = true;
|
||||
for (size_t i = 0 ; i < chatClients.size(); ++i)
|
||||
for (size_t i = 0; i < chatClients.size(); ++i)
|
||||
{
|
||||
allReady &= chatClients[i]->isReady();
|
||||
}
|
||||
@ -269,7 +270,7 @@ TEST_CASE("Websocket_broadcast_server", "[websocket_server]")
|
||||
|
||||
for (int j = 0; j < 1000; j++)
|
||||
{
|
||||
for (size_t i = 0 ; i < chatClients.size(); ++i)
|
||||
for (size_t i = 0; i < chatClients.size(); ++i)
|
||||
{
|
||||
chatClients[i]->sendMessage("hello world");
|
||||
}
|
||||
@ -291,7 +292,7 @@ TEST_CASE("Websocket_broadcast_server", "[websocket_server]")
|
||||
|
||||
// Stop all clients
|
||||
size_t messageCount = chatClients.size() * 50;
|
||||
for (size_t i = 0 ; i < chatClients.size(); ++i)
|
||||
for (size_t i = 0; i < chatClients.size(); ++i)
|
||||
{
|
||||
REQUIRE(chatClients[i]->getReceivedMessagesCount() >= messageCount);
|
||||
chatClients[i]->stop();
|
||||
|
@ -14,8 +14,41 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
ix::initNetSystem();
|
||||
|
||||
ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) { spdlog::info(msg); };
|
||||
ix::IXCoreLogger::setLogFunction(logFunc);
|
||||
ix::CoreLogger::LogFunc logFunc = [](const char* msg, ix::LogLevel level) {
|
||||
switch (level)
|
||||
{
|
||||
case ix::LogLevel::Debug:
|
||||
{
|
||||
spdlog::debug(msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case ix::LogLevel::Info:
|
||||
{
|
||||
spdlog::info(msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case ix::LogLevel::Warning:
|
||||
{
|
||||
spdlog::warn(msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case ix::LogLevel::Error:
|
||||
{
|
||||
spdlog::error(msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case ix::LogLevel::Critical:
|
||||
{
|
||||
spdlog::critical(msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
ix::CoreLogger::setLogFunction(logFunc);
|
||||
|
||||
int result = Catch::Session().run(argc, argv);
|
||||
|
||||
|
6
third_party/.clang-format
vendored
6
third_party/.clang-format
vendored
@ -1,4 +1,2 @@
|
||||
{
|
||||
"DisableFormat": true,
|
||||
"SortIncludes": false
|
||||
}
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
||||
|
41
third_party/mbedtls/.github/issue_template.md
vendored
41
third_party/mbedtls/.github/issue_template.md
vendored
@ -1,41 +0,0 @@
|
||||
Note: This is just a template, so feel free to use/remove the unnecessary things
|
||||
|
||||
### Description
|
||||
- Type: Bug | Enhancement\Feature Request | Question
|
||||
- Priority: Blocker | Major | Minor
|
||||
|
||||
---------------------------------------------------------------
|
||||
## Bug
|
||||
|
||||
**OS**
|
||||
Mbed OS|linux|windows|
|
||||
|
||||
**mbed TLS build:**
|
||||
Version: x.x.x or git commit id
|
||||
OS version: x.x.x
|
||||
Configuration: please attach config.h file where possible
|
||||
Compiler and options (if you used a pre-built binary, please indicate how you obtained it):
|
||||
Additional environment information:
|
||||
|
||||
**Peer device TLS stack and version**
|
||||
OpenSSL|GnuTls|Chrome|NSS(Firefox)|SecureChannel (IIS/Internet Explorer/Edge)|Other
|
||||
Version:
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
**Actual behavior**
|
||||
|
||||
**Steps to reproduce**
|
||||
|
||||
----------------------------------------------------------------
|
||||
## Enhancement\Feature Request
|
||||
|
||||
**Justification - why does the library need this feature?**
|
||||
|
||||
**Suggested enhancement**
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
## Question
|
||||
|
||||
**Please first check for answers in the [Mbed TLS knowledge Base](https://tls.mbed.org/kb), and preferably file an issue in the [Mbed TLS support forum](https://forums.mbed.com/c/mbed-tls)**
|
@ -1,39 +0,0 @@
|
||||
Notes:
|
||||
* Pull requests cannot be accepted until:
|
||||
- The submitter has [accepted the online agreement here with a click through](https://developer.mbed.org/contributor_agreement/)
|
||||
or for companies or those that do not wish to create an mbed account, a slightly different agreement can be found [here](https://www.mbed.com/en/about-mbed/contributor-license-agreements/)
|
||||
- The PR follows the [mbed TLS coding standards](https://tls.mbed.org/kb/development/mbedtls-coding-standards)
|
||||
* This is just a template, so feel free to use/remove the unnecessary things
|
||||
## Description
|
||||
A few sentences describing the overall goals of the pull request's commits.
|
||||
|
||||
|
||||
## Status
|
||||
**READY/IN DEVELOPMENT/HOLD**
|
||||
|
||||
## Requires Backporting
|
||||
When there is a bug fix, it should be backported to all maintained and supported branches.
|
||||
Changes do not have to be backported if:
|
||||
- This PR is a new feature\enhancement
|
||||
- This PR contains changes in the API. If this is true, and there is a need for the fix to be backported, the fix should be handled differently in the legacy branch
|
||||
|
||||
Yes | NO
|
||||
Which branch?
|
||||
|
||||
## Migrations
|
||||
If there is any API change, what's the incentive and logic for it.
|
||||
|
||||
YES | NO
|
||||
|
||||
## Additional comments
|
||||
Any additional information that could be of interest
|
||||
|
||||
## Todos
|
||||
- [ ] Tests
|
||||
- [ ] Documentation
|
||||
- [ ] Changelog updated
|
||||
- [ ] Backported
|
||||
|
||||
|
||||
## Steps to test or reproduce
|
||||
Outline the steps to test or reproduce the PR here.
|
43
third_party/mbedtls/.gitignore
vendored
43
third_party/mbedtls/.gitignore
vendored
@ -1,43 +0,0 @@
|
||||
# Random seed file created by test scripts and sample programs
|
||||
seedfile
|
||||
|
||||
# CMake build artifacts:
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CTestTestfile.cmake
|
||||
cmake_install.cmake
|
||||
Testing
|
||||
# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those:
|
||||
*.dir/
|
||||
# MSVC files generated by CMake:
|
||||
/*.sln
|
||||
/*.vcxproj
|
||||
/*.filters
|
||||
|
||||
# Test coverage build artifacts:
|
||||
Coverage
|
||||
*.gcno
|
||||
*.gcda
|
||||
|
||||
# generated by scripts/memory.sh
|
||||
massif-*
|
||||
|
||||
# MSVC build artifacts:
|
||||
*.exe
|
||||
*.pdb
|
||||
*.ilk
|
||||
*.lib
|
||||
|
||||
# Python build artifacts:
|
||||
*.pyc
|
||||
|
||||
# Generated documentation:
|
||||
/apidoc
|
||||
|
||||
# Editor navigation files:
|
||||
/GPATH
|
||||
/GRTAGS
|
||||
/GSYMS
|
||||
/GTAGS
|
||||
/TAGS
|
||||
/tags
|
3
third_party/mbedtls/.globalrc
vendored
3
third_party/mbedtls/.globalrc
vendored
@ -1,3 +0,0 @@
|
||||
default:\
|
||||
:langmap=c\:.c.h.function:\
|
||||
|
52
third_party/mbedtls/.pylintrc
vendored
52
third_party/mbedtls/.pylintrc
vendored
@ -1,52 +0,0 @@
|
||||
[BASIC]
|
||||
# We're ok with short funtion argument names.
|
||||
# [invalid-name]
|
||||
argument-rgx=[a-z_][a-z0-9_]*$
|
||||
|
||||
# Allow filter and map.
|
||||
# [bad-builtin]
|
||||
bad-functions=input
|
||||
|
||||
# We prefer docstrings, but we don't require them on all functions.
|
||||
# Require them only on long functions (for some value of long).
|
||||
# [missing-docstring]
|
||||
docstring-min-length=10
|
||||
|
||||
# Allow longer methods than the default.
|
||||
# [invalid-name]
|
||||
method-rgx=[a-z_][a-z0-9_]{2,35}$
|
||||
|
||||
# Allow module names containing a dash (but no underscore or uppercase letter).
|
||||
# They are whole programs, not meant to be included by another module.
|
||||
# [invalid-name]
|
||||
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|[a-z][-0-9a-z]+)$
|
||||
|
||||
# Some functions don't need docstrings.
|
||||
# [missing-docstring]
|
||||
no-docstring-rgx=(run_)?main$
|
||||
|
||||
# We're ok with short local or global variable names.
|
||||
# [invalid-name]
|
||||
variable-rgx=[a-z_][a-z0-9_]*$
|
||||
|
||||
[DESIGN]
|
||||
# Allow more than the default 7 attributes.
|
||||
# [too-many-instance-attributes]
|
||||
max-attributes=15
|
||||
|
||||
[FORMAT]
|
||||
# Allow longer modules than the default recommended maximum.
|
||||
# [too-many-lines]
|
||||
max-module-lines=2000
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
disable=
|
||||
|
||||
[REPORTS]
|
||||
# Don't diplay statistics. Just the facts.
|
||||
reports=no
|
||||
|
||||
[VARIABLES]
|
||||
# Allow unused variables if their name starts with an underscore.
|
||||
# [unused-argument]
|
||||
dummy-variables-rgx=_.*
|
48
third_party/mbedtls/.travis.yml
vendored
48
third_party/mbedtls/.travis.yml
vendored
@ -1,48 +0,0 @@
|
||||
language: c
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
sudo: false
|
||||
cache: ccache
|
||||
|
||||
# blocklist
|
||||
branches:
|
||||
except:
|
||||
- development-psa
|
||||
- coverity_scan
|
||||
|
||||
script:
|
||||
- tests/scripts/recursion.pl library/*.c
|
||||
- tests/scripts/check-generated-files.sh
|
||||
- tests/scripts/check-doxy-blocks.pl
|
||||
- tests/scripts/check-names.sh
|
||||
- tests/scripts/check-files.py
|
||||
- tests/scripts/doxygen.sh
|
||||
- cmake -D CMAKE_BUILD_TYPE:String="Check" .
|
||||
- make
|
||||
- make test
|
||||
- programs/test/selftest
|
||||
- OSSL_NO_DTLS=1 tests/compat.sh
|
||||
- tests/ssl-opt.sh -e '\(DTLS\|SCSV\).*openssl'
|
||||
- tests/scripts/test-ref-configs.pl
|
||||
- tests/scripts/curves.pl
|
||||
- tests/scripts/key-exchanges.pl
|
||||
after_failure:
|
||||
- tests/scripts/travis-log-failure.sh
|
||||
env:
|
||||
global:
|
||||
- SEED=1
|
||||
- secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k="
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- doxygen
|
||||
- graphviz
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "ARMmbed/mbedtls"
|
||||
notification_email: simon.butcher@arm.com
|
||||
build_command_prepend:
|
||||
build_command: make
|
||||
branch_pattern: coverity_scan
|
246
third_party/mbedtls/CMakeLists.txt
vendored
246
third_party/mbedtls/CMakeLists.txt
vendored
@ -1,246 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
if(TEST_CPP)
|
||||
project("mbed TLS" C CXX)
|
||||
else()
|
||||
project("mbed TLS" C)
|
||||
endif()
|
||||
|
||||
set(MBEDTLS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
option(USE_PKCS11_HELPER_LIBRARY "Build mbed TLS with the pkcs11-helper library." OFF)
|
||||
option(ENABLE_ZLIB_SUPPORT "Build mbed TLS with zlib library." OFF)
|
||||
|
||||
option(ENABLE_PROGRAMS "Build mbed TLS programs." OFF)
|
||||
|
||||
option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF)
|
||||
|
||||
# export the submodule flag so that crypto knows it's being built as a submodule
|
||||
set( USE_CRYPTO_SUBMODULE ON )
|
||||
|
||||
string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
|
||||
string(REGEX MATCH "GNU" CMAKE_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}")
|
||||
string(REGEX MATCH "IAR" CMAKE_COMPILER_IS_IAR "${CMAKE_C_COMPILER_ID}")
|
||||
string(REGEX MATCH "MSVC" CMAKE_COMPILER_IS_MSVC "${CMAKE_C_COMPILER_ID}")
|
||||
|
||||
# the test suites currently have compile errors with MSVC
|
||||
if(CMAKE_COMPILER_IS_MSVC)
|
||||
option(ENABLE_TESTING "Build mbed TLS tests." OFF)
|
||||
else()
|
||||
option(ENABLE_TESTING "Build mbed TLS tests." OFF)
|
||||
endif()
|
||||
|
||||
# Warning string - created as a list for compatibility with CMake 2.8
|
||||
set(WARNING_BORDER "*******************************************************\n")
|
||||
set(NULL_ENTROPY_WARN_L1 "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined!\n")
|
||||
set(NULL_ENTROPY_WARN_L2 "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES\n")
|
||||
set(NULL_ENTROPY_WARN_L3 "**** AND IS *NOT* SUITABLE FOR PRODUCTION USE\n")
|
||||
|
||||
set(NULL_ENTROPY_WARNING "${WARNING_BORDER}"
|
||||
"${NULL_ENTROPY_WARN_L1}"
|
||||
"${NULL_ENTROPY_WARN_L2}"
|
||||
"${NULL_ENTROPY_WARN_L3}"
|
||||
"${WARNING_BORDER}")
|
||||
|
||||
set(CTR_DRBG_128_BIT_KEY_WARN_L1 "**** WARNING! MBEDTLS_CTR_DRBG_USE_128_BIT_KEY defined!\n")
|
||||
set(CTR_DRBG_128_BIT_KEY_WARN_L2 "**** Using 128-bit keys for CTR_DRBG limits the security of generated\n")
|
||||
set(CTR_DRBG_128_BIT_KEY_WARN_L3 "**** keys and operations that use random values generated to 128-bit security\n")
|
||||
|
||||
set(CTR_DRBG_128_BIT_KEY_WARNING "${WARNING_BORDER}"
|
||||
"${CTR_DRBG_128_BIT_KEY_WARN_L1}"
|
||||
"${CTR_DRBG_128_BIT_KEY_WARN_L2}"
|
||||
"${CTR_DRBG_128_BIT_KEY_WARN_L3}"
|
||||
"${WARNING_BORDER}")
|
||||
|
||||
find_package(PythonInterp)
|
||||
find_package(Perl)
|
||||
if(PERL_FOUND)
|
||||
|
||||
# If 128-bit keys are configured for CTR_DRBG, display an appropriate warning
|
||||
execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
|
||||
RESULT_VARIABLE result)
|
||||
if(${result} EQUAL 0)
|
||||
message(WARNING ${CTR_DRBG_128_BIT_KEY_WARNING})
|
||||
endif()
|
||||
|
||||
# If NULL Entropy is configured, display an appropriate warning
|
||||
execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY
|
||||
RESULT_VARIABLE result)
|
||||
if(${result} EQUAL 0)
|
||||
message(WARNING ${NULL_ENTROPY_WARNING})
|
||||
|
||||
if(NOT UNSAFE_BUILD)
|
||||
message(FATAL_ERROR "\
|
||||
\n\
|
||||
Warning! You have enabled MBEDTLS_TEST_NULL_ENTROPY. \
|
||||
This option is not safe for production use and negates all security \
|
||||
It is intended for development use only. \
|
||||
\n\
|
||||
To confirm you want to build with this option, re-run cmake with the \
|
||||
option: \n\
|
||||
cmake -DUNSAFE_BUILD=ON ")
|
||||
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
|
||||
CACHE STRING "Choose the type of build: None Debug Release Coverage ASan ASanDbg MemSan MemSanDbg Check CheckFull"
|
||||
FORCE)
|
||||
|
||||
# Create a symbolic link from ${base_name} in the binary directory
|
||||
# to the corresponding path in the source directory.
|
||||
function(link_to_source base_name)
|
||||
# Get OS dependent path to use in `execute_process`
|
||||
if (CMAKE_HOST_WIN32)
|
||||
#mklink is an internal command of cmd.exe it can only work with \
|
||||
string(REPLACE "/" "\\" link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
|
||||
string(REPLACE "/" "\\" target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
|
||||
else()
|
||||
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
|
||||
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS ${link})
|
||||
if (CMAKE_HOST_UNIX)
|
||||
set(command ln -s ${target} ${link})
|
||||
else()
|
||||
if (IS_DIRECTORY ${target})
|
||||
set(command cmd.exe /c mklink /j ${link} ${target})
|
||||
else()
|
||||
set(command cmd.exe /c mklink /h ${link} ${target})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND ${command}
|
||||
RESULT_VARIABLE result
|
||||
ERROR_VARIABLE output)
|
||||
|
||||
if (NOT ${result} EQUAL 0)
|
||||
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction(link_to_source)
|
||||
|
||||
string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNU)
|
||||
# some warnings we want are not available with old GCC versions
|
||||
# note: starting with CMake 2.8 we could use CMAKE_C_COMPILER_VERSION
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement -Wwrite-strings")
|
||||
if (GCC_VERSION VERSION_GREATER 4.5 OR GCC_VERSION VERSION_EQUAL 4.5)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wlogical-op")
|
||||
endif()
|
||||
if (GCC_VERSION VERSION_GREATER 4.8 OR GCC_VERSION VERSION_EQUAL 4.8)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O2")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -g3")
|
||||
set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage")
|
||||
set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -O3")
|
||||
set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
|
||||
set(CMAKE_C_FLAGS_CHECK "-Werror -Os")
|
||||
set(CMAKE_C_FLAGS_CHECKFULL "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
|
||||
endif(CMAKE_COMPILER_IS_GNU)
|
||||
|
||||
if(CMAKE_COMPILER_IS_CLANG)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O2")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -g3")
|
||||
set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage")
|
||||
set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
|
||||
set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
|
||||
set(CMAKE_C_FLAGS_MEMSAN "-Werror -fsanitize=memory -O3")
|
||||
set(CMAKE_C_FLAGS_MEMSANDBG "-Werror -fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2")
|
||||
set(CMAKE_C_FLAGS_CHECK "-Werror -Os")
|
||||
endif(CMAKE_COMPILER_IS_CLANG)
|
||||
|
||||
if(CMAKE_COMPILER_IS_IAR)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts --warnings_are_errors -Ohz")
|
||||
endif(CMAKE_COMPILER_IS_IAR)
|
||||
|
||||
if(CMAKE_COMPILER_IS_MSVC)
|
||||
# Strictest warnings, and treat as errors
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
|
||||
endif(CMAKE_COMPILER_IS_MSVC)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
||||
if(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "--coverage")
|
||||
endif(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
|
||||
endif(CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
||||
|
||||
if(LIB_INSTALL_DIR)
|
||||
else()
|
||||
set(LIB_INSTALL_DIR lib)
|
||||
endif()
|
||||
|
||||
if(ENABLE_ZLIB_SUPPORT)
|
||||
find_package(ZLIB)
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
endif(ZLIB_FOUND)
|
||||
endif(ENABLE_ZLIB_SUPPORT)
|
||||
|
||||
add_subdirectory(library)
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(crypto/library)
|
||||
add_subdirectory(crypto/include)
|
||||
|
||||
if(ENABLE_PROGRAMS)
|
||||
add_subdirectory(programs)
|
||||
endif()
|
||||
|
||||
ADD_CUSTOM_TARGET(apidoc
|
||||
COMMAND doxygen mbedtls.doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doxygen)
|
||||
|
||||
if(ENABLE_TESTING)
|
||||
enable_testing()
|
||||
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(crypto/tests)
|
||||
|
||||
# additional convenience targets for Unix only
|
||||
if(UNIX)
|
||||
|
||||
ADD_CUSTOM_TARGET(covtest
|
||||
COMMAND make test
|
||||
COMMAND programs/test/selftest
|
||||
COMMAND tests/compat.sh
|
||||
COMMAND tests/ssl-opt.sh
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(lcov
|
||||
COMMAND rm -rf Coverage
|
||||
COMMAND lcov --capture --initial --directory library/CMakeFiles/mbedtls.dir -o files.info
|
||||
COMMAND lcov --capture --directory library/CMakeFiles/mbedtls.dir -o tests.info
|
||||
COMMAND lcov --add-tracefile files.info --add-tracefile tests.info -o all.info
|
||||
COMMAND lcov --remove all.info -o final.info '*.h'
|
||||
COMMAND gendesc tests/Descriptions.txt -o descriptions
|
||||
COMMAND genhtml --title "mbed TLS" --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage final.info
|
||||
COMMAND rm -f files.info tests.info all.info final.info descriptions
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(memcheck
|
||||
COMMAND sed -i.bak s+/usr/bin/valgrind+`which valgrind`+ DartConfiguration.tcl
|
||||
COMMAND ctest -O memcheck.log -D ExperimentalMemCheck
|
||||
COMMAND tail -n1 memcheck.log | grep 'Memory checking results:' > /dev/null
|
||||
COMMAND rm -f memcheck.log
|
||||
COMMAND mv DartConfiguration.tcl.bak DartConfiguration.tcl
|
||||
)
|
||||
endif(UNIX)
|
||||
endif()
|
||||
|
||||
# Make scripts needed for testing available in an out-of-source build.
|
||||
if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
link_to_source(scripts)
|
||||
# Copy (don't link) DartConfiguration.tcl, needed for memcheck, to
|
||||
# keep things simple with the sed commands in the memcheck target.
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/DartConfiguration.tcl
|
||||
${CMAKE_CURRENT_BINARY_DIR}/DartConfiguration.tcl COPYONLY)
|
||||
endif()
|
95
third_party/mbedtls/CONTRIBUTING.md
vendored
95
third_party/mbedtls/CONTRIBUTING.md
vendored
@ -1,95 +0,0 @@
|
||||
Contributing
|
||||
============
|
||||
We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions:
|
||||
|
||||
- As with any open source project, contributions will be reviewed by the project team and community and may need some modifications to be accepted.
|
||||
- The contribution should not break API or ABI, unless there is a real justification for that. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release.
|
||||
|
||||
Contributor License Agreement (CLA)
|
||||
-----------------------------------
|
||||
- All contributions, whether large or small, require a Contributor's License Agreement (CLA) to be accepted. This is because source code can possibly fall under copyright law and we need your consent to share in the ownership of the copyright.
|
||||
- To accept the Contributor’s License Agreement (CLA), individual contributors can do this by creating an Mbed account and [accepting the online agreement here with a click through](https://developer.mbed.org/contributor_agreement/). Alternatively, for contributions from corporations, or those that do not wish to create an Mbed account, a slightly different agreement can be found [here](https://www.mbed.com/en/about-mbed/contributor-license-agreements/). This agreement should be signed and returned to Arm as described in the instructions given.
|
||||
|
||||
Coding Standards
|
||||
----------------
|
||||
- We would ask that contributions conform to [our coding standards](https://tls.mbed.org/kb/development/mbedtls-coding-standards), and that contributions are fully tested before submission, as mentioned in the [Tests](#tests) and [Continuous Integration](#continuous-integration-tests) sections.
|
||||
- The code should be written in a clean and readable style.
|
||||
- The code should be written in a portable generic way, that will benefit the whole community, and not only your own needs.
|
||||
- The code should be secure, and will be reviewed from a security point of view as well.
|
||||
|
||||
Making a Contribution
|
||||
---------------------
|
||||
1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://tls.mbed.org/discussions) around a feature idea or a bug.
|
||||
1. Fork the [Mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the ["development" branch](https://github.com/ARMmbed/mbedtls/tree/development) as a basis.
|
||||
1. Write a test which shows that the bug was fixed or that the feature works as expected.
|
||||
1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. We will include your name in the ChangeLog :)
|
||||
1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it.
|
||||
1. Mbed TLS is released under the Apache license, and as such, all the added files should include the Apache license header.
|
||||
|
||||
API/ABI Compatibility
|
||||
---------------------
|
||||
The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches.
|
||||
|
||||
To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change.
|
||||
|
||||
Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function.
|
||||
|
||||
When a build is made with the deprecation preprocessor symbols defined, a compiler warning will be generated to warn a user that the function will be removed at some point in the future, notifying users that they should change from the older deprecated function to the newer function at their own convenience.
|
||||
|
||||
Therefore, no changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. As described above, if a function needs to be changed, a new function needs to be created alongside it, with a new name, and whatever change is necessary, such as a new parameter or the addition of a return value.
|
||||
|
||||
Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library.
|
||||
|
||||
Long Term Support Branches
|
||||
--------------------------
|
||||
Mbed TLS maintains several LTS (Long Term Support) branches, which are maintained continuously for a given period. The LTS branches are provided to allow users of the library to have a maintained, stable version of the library which contains only security fixes and fixes for other defects, without encountering additional features or API extensions which may introduce issues or change the code size or RAM usage, which can be significant considerations on some platforms. To allow users to take advantage of the LTS branches, these branches maintain backwards compatibility for both the public API and ABI.
|
||||
|
||||
When backporting to these branches please observe the following rules:
|
||||
|
||||
1. Any change to the library which changes the API or ABI cannot be backported.
|
||||
|
||||
2. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted.
|
||||
|
||||
3. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be additional test cases or quality improvements such as changes to build or test scripts.
|
||||
|
||||
It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development) by contributors.
|
||||
|
||||
Currently maintained LTS branches are:
|
||||
|
||||
1. [mbedtls-2.7](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.7)
|
||||
|
||||
1. [mbedtls-2.16](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.16)
|
||||
|
||||
|
||||
Tests
|
||||
-----
|
||||
As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist.
|
||||
|
||||
Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_mpi.c`). These files are generated from a `function file` (e.g. `suites/test_suite_mpi.function`) and a `data file` (e.g. `suites/test_suite_mpi.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function.
|
||||
|
||||
[A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://tls.mbed.org/kb/development/test_suites).
|
||||
|
||||
A test script `tests/scripts/basic-build-test.sh` is available to show test coverage of the library. New code contributions should provide a similar level of code coverage to that which already exists for the library.
|
||||
|
||||
Sample applications, if needed, should be modified as well.
|
||||
|
||||
Continuous Integration Tests
|
||||
----------------------------
|
||||
Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures.
|
||||
|
||||
It is advised to enable the [githooks scripts](https://github.com/ARMmbed/mbedtls/tree/development/tests/git-scripts) prior to pushing your changes, for catching some of the issues as early as possible.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
Mbed TLS is well documented, but if you think documentation is needed, speak out!
|
||||
|
||||
1. All interfaces should be documented through Doxygen. New APIs should introduce Doxygen documentation.
|
||||
|
||||
2. Complex parts in the code should include comments.
|
||||
|
||||
3. If needed, a Readme file is advised.
|
||||
|
||||
4. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description.
|
||||
|
||||
5. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog) entry should be added for this contribution.
|
||||
|
3341
third_party/mbedtls/ChangeLog
vendored
3341
third_party/mbedtls/ChangeLog
vendored
File diff suppressed because it is too large
Load Diff
4
third_party/mbedtls/DartConfiguration.tcl
vendored
4
third_party/mbedtls/DartConfiguration.tcl
vendored
@ -1,4 +0,0 @@
|
||||
Site: localhost
|
||||
BuildName: mbed TLS-test
|
||||
CoverageCommand: /usr/bin/gcov
|
||||
MemoryCheckCommand: /usr/bin/valgrind
|
2
third_party/mbedtls/LICENSE
vendored
2
third_party/mbedtls/LICENSE
vendored
@ -1,2 +0,0 @@
|
||||
Unless specifically indicated otherwise in a file, files are licensed
|
||||
under the Apache 2.0 license, as can be found in: apache-2.0.txt
|
200
third_party/mbedtls/Makefile
vendored
200
third_party/mbedtls/Makefile
vendored
@ -1,200 +0,0 @@
|
||||
# CMAKE generated file: DO NOT EDIT!
|
||||
# Generated by "Unix Makefiles" Generator, CMake Version 3.12
|
||||
|
||||
# Default target executed when no arguments are given to make.
|
||||
default_target: all
|
||||
|
||||
.PHONY : default_target
|
||||
|
||||
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
|
||||
.NOTPARALLEL:
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets provided by cmake.
|
||||
|
||||
# Disable implicit rules so canonical targets will work.
|
||||
.SUFFIXES:
|
||||
|
||||
|
||||
# Remove some rules from gmake that .SUFFIXES does not remove.
|
||||
SUFFIXES =
|
||||
|
||||
.SUFFIXES: .hpux_make_needs_suffix_list
|
||||
|
||||
|
||||
# Suppress display of executed commands.
|
||||
$(VERBOSE).SILENT:
|
||||
|
||||
|
||||
# A target that is always out of date.
|
||||
cmake_force:
|
||||
|
||||
.PHONY : cmake_force
|
||||
|
||||
#=============================================================================
|
||||
# Set environment variables for the build.
|
||||
|
||||
# The shell in which to execute make rules.
|
||||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /Applications/CMake.app/Contents/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /Applications/CMake.app/Contents/bin/cmake -E remove -f
|
||||
|
||||
# Escaping for special characters.
|
||||
EQUALS = =
|
||||
|
||||
# The top-level source directory on which CMake was run.
|
||||
CMAKE_SOURCE_DIR = /Users/bsergeant/src/foss/ixwebsocket
|
||||
|
||||
# The top-level build directory on which CMake was run.
|
||||
CMAKE_BINARY_DIR = /Users/bsergeant/src/foss/ixwebsocket
|
||||
|
||||
#=============================================================================
|
||||
# Targets provided globally by CMake.
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
|
||||
/Applications/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
|
||||
/Applications/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local/fast
|
||||
|
||||
# Special rule for the target install/strip
|
||||
install/strip: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
|
||||
/Applications/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
.PHONY : install/strip
|
||||
|
||||
# Special rule for the target install/strip
|
||||
install/strip/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
|
||||
/Applications/CMake.app/Contents/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
.PHONY : install/strip/fast
|
||||
|
||||
# Special rule for the target install
|
||||
install: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
|
||||
/Applications/CMake.app/Contents/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install
|
||||
|
||||
# Special rule for the target install
|
||||
install/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
|
||||
/Applications/CMake.app/Contents/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install/fast
|
||||
|
||||
# Special rule for the target list_install_components
|
||||
list_install_components:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
|
||||
.PHONY : list_install_components
|
||||
|
||||
# Special rule for the target list_install_components
|
||||
list_install_components/fast: list_install_components
|
||||
|
||||
.PHONY : list_install_components/fast
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
|
||||
/Applications/CMake.app/Contents/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : rebuild_cache
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache/fast: rebuild_cache
|
||||
|
||||
.PHONY : rebuild_cache/fast
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
|
||||
/Applications/CMake.app/Contents/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : edit_cache
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache/fast: edit_cache
|
||||
|
||||
.PHONY : edit_cache/fast
|
||||
|
||||
# The main all target
|
||||
all: cmake_check_build_system
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(CMAKE_COMMAND) -E cmake_progress_start /Users/bsergeant/src/foss/ixwebsocket/CMakeFiles /Users/bsergeant/src/foss/ixwebsocket/third_party/mbedtls/CMakeFiles/progress.marks
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(MAKE) -f CMakeFiles/Makefile2 third_party/mbedtls/all
|
||||
$(CMAKE_COMMAND) -E cmake_progress_start /Users/bsergeant/src/foss/ixwebsocket/CMakeFiles 0
|
||||
.PHONY : all
|
||||
|
||||
# The main clean target
|
||||
clean:
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(MAKE) -f CMakeFiles/Makefile2 third_party/mbedtls/clean
|
||||
.PHONY : clean
|
||||
|
||||
# The main clean target
|
||||
clean/fast: clean
|
||||
|
||||
.PHONY : clean/fast
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall: all
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(MAKE) -f CMakeFiles/Makefile2 third_party/mbedtls/preinstall
|
||||
.PHONY : preinstall
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall/fast:
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(MAKE) -f CMakeFiles/Makefile2 third_party/mbedtls/preinstall
|
||||
.PHONY : preinstall/fast
|
||||
|
||||
# clear depends
|
||||
depend:
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
|
||||
.PHONY : depend
|
||||
|
||||
# Convenience name for target.
|
||||
third_party/mbedtls/CMakeFiles/apidoc.dir/rule:
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(MAKE) -f CMakeFiles/Makefile2 third_party/mbedtls/CMakeFiles/apidoc.dir/rule
|
||||
.PHONY : third_party/mbedtls/CMakeFiles/apidoc.dir/rule
|
||||
|
||||
# Convenience name for target.
|
||||
apidoc: third_party/mbedtls/CMakeFiles/apidoc.dir/rule
|
||||
|
||||
.PHONY : apidoc
|
||||
|
||||
# fast build rule for target.
|
||||
apidoc/fast:
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(MAKE) -f third_party/mbedtls/CMakeFiles/apidoc.dir/build.make third_party/mbedtls/CMakeFiles/apidoc.dir/build
|
||||
.PHONY : apidoc/fast
|
||||
|
||||
# Help Target
|
||||
help:
|
||||
@echo "The following are some of the valid targets for this Makefile:"
|
||||
@echo "... all (the default if no target is provided)"
|
||||
@echo "... clean"
|
||||
@echo "... depend"
|
||||
@echo "... install/local"
|
||||
@echo "... install/strip"
|
||||
@echo "... install"
|
||||
@echo "... list_install_components"
|
||||
@echo "... rebuild_cache"
|
||||
@echo "... edit_cache"
|
||||
@echo "... apidoc"
|
||||
.PHONY : help
|
||||
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets to cleanup operation of make.
|
||||
|
||||
# Special rule to run CMake to check the build system integrity.
|
||||
# No rule that depends on this can have commands that come from listfiles
|
||||
# because they might be regenerated.
|
||||
cmake_check_build_system:
|
||||
cd /Users/bsergeant/src/foss/ixwebsocket && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
|
||||
.PHONY : cmake_check_build_system
|
||||
|
205
third_party/mbedtls/README.md
vendored
205
third_party/mbedtls/README.md
vendored
@ -1,205 +0,0 @@
|
||||
README for Mbed TLS
|
||||
===================
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Perl script `scripts/config.pl` (use `--help` for usage instructions).
|
||||
|
||||
Compiler options can be set using conventional environment variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below).
|
||||
|
||||
Compiling
|
||||
---------
|
||||
|
||||
There are currently three active build systems used within Mbed TLS releases:
|
||||
|
||||
- GNU Make
|
||||
- CMake
|
||||
- Microsoft Visual Studio (Microsoft Visual Studio 2010 or later)
|
||||
|
||||
The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically.
|
||||
|
||||
The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. Also, when loading shared libraries using dlopen(), you'll need to load libmbedcrypto first, then libmbedx509, before you can load libmbedtls.
|
||||
|
||||
### Getting files form git: the Crypto submodule
|
||||
|
||||
The Mbed Crypto library now has its own git repository, which the Mbed TLS build systems are using as a git submodule in order to build libmbedcrypto as a subproject of Mbed TLS. When cloning the Mbed TLS repository, you need to make sure you're getting the submodule as well:
|
||||
|
||||
git clone --recursive https://github.com/ARMmbed/mbedtls.git
|
||||
|
||||
Alternatively, if you already have an existing clone of the Mbed TLS
|
||||
repository, you can initialise and update the submodule with:
|
||||
|
||||
git submodule update --init crypto
|
||||
|
||||
After these steps, your clone is now ready for building the libraries as detailed in the following sections.
|
||||
|
||||
Note that building libmbedcrypto as a subproject of Mbed TLS does not enable the PSA-specific tests and utility programs. To use these programs, build Mbed Crypto as a standalone project.
|
||||
|
||||
Please note that for now, Mbed TLS can only use versions of libmbedcrypto that were built as a subproject of Mbed TLS, not versions that were built standalone from the Mbed Crypto repository. This restriction will be removed in the future.
|
||||
|
||||
### Make
|
||||
|
||||
We require GNU Make. To build the library and the sample programs, GNU Make and a C compiler are sufficient. Some of the more advanced build targets require some Unix/Linux tools.
|
||||
|
||||
We intentionally only use a minimum of functionality in the makefiles in order to keep them as simple and independent of different toolchains as possible, to allow users to more easily move between different platforms. Users who need more features are recommended to use CMake.
|
||||
|
||||
In order to build from the source code using GNU Make, just enter at the command line:
|
||||
|
||||
make
|
||||
|
||||
In order to run the tests, enter:
|
||||
|
||||
make check
|
||||
|
||||
The tests need Python to be built and Perl to be run. If you don't have one of them installed, you can skip building the tests with:
|
||||
|
||||
make no_test
|
||||
|
||||
You'll still be able to run a much smaller set of tests with:
|
||||
|
||||
programs/test/selftest
|
||||
|
||||
In order to build for a Windows platform, you should use `WINDOWS_BUILD=1` if the target is Windows but the build environment is Unix-like (for instance when cross-compiling, or compiling from an MSYS shell), and `WINDOWS=1` if the build environment is a Windows shell (for instance using mingw32-make) (in that case some targets will not be available).
|
||||
|
||||
Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved.
|
||||
|
||||
Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line.
|
||||
|
||||
Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue.
|
||||
|
||||
In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://tls.mbed.org/kb).
|
||||
|
||||
### CMake
|
||||
|
||||
In order to build the source using CMake in a separate directory (recommended), just enter at the command line:
|
||||
|
||||
mkdir /path/to/build_dir && cd /path/to/build_dir
|
||||
cmake /path/to/mbedtls_source
|
||||
make
|
||||
|
||||
In order to run the tests, enter:
|
||||
|
||||
make test
|
||||
|
||||
The test suites need Python to be built and Perl to be executed. If you don't have one of these installed, you'll want to disable the test suites with:
|
||||
|
||||
cmake -DENABLE_TESTING=Off /path/to/mbedtls_source
|
||||
|
||||
If you disabled the test suites, but kept the programs enabled, you can still run a much smaller set of tests with:
|
||||
|
||||
programs/test/selftest
|
||||
|
||||
To configure CMake for building shared libraries, use:
|
||||
|
||||
cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On /path/to/mbedtls_source
|
||||
|
||||
There are many different build modes available within the CMake buildsystem. Most of them are available for gcc and clang, though some are compiler-specific:
|
||||
|
||||
- `Release`. This generates the default code without any unnecessary information in the binary files.
|
||||
- `Debug`. This generates debug information and disables optimization of the code.
|
||||
- `Coverage`. This generates code coverage information in addition to debug information.
|
||||
- `ASan`. This instruments the code with AddressSanitizer to check for memory errors. (This includes LeakSanitizer, with recent version of gcc and clang.) (With recent version of clang, this mode also instruments the code with UndefinedSanitizer to check for undefined behaviour.)
|
||||
- `ASanDbg`. Same as ASan but slower, with debug information and better stack traces.
|
||||
- `MemSan`. This instruments the code with MemorySanitizer to check for uninitialised memory reads. Experimental, needs recent clang on Linux/x86\_64.
|
||||
- `MemSanDbg`. Same as MemSan but slower, with debug information, better stack traces and origin tracking.
|
||||
- `Check`. This activates the compiler warnings that depend on optimization and treats all warnings as errors.
|
||||
|
||||
Switching build modes in CMake is simple. For debug mode, enter at the command line:
|
||||
|
||||
cmake -D CMAKE_BUILD_TYPE=Debug /path/to/mbedtls_source
|
||||
|
||||
To list other available CMake options, use:
|
||||
|
||||
cmake -LH
|
||||
|
||||
Note that, with CMake, you can't adjust the compiler or its flags after the
|
||||
initial invocation of cmake. This means that `CC=your_cc make` and `make
|
||||
CC=your_cc` will *not* work (similarly with `CFLAGS` and other variables).
|
||||
These variables need to be adjusted when invoking cmake for the first time,
|
||||
for example:
|
||||
|
||||
CC=your_cc cmake /path/to/mbedtls_source
|
||||
|
||||
If you already invoked cmake and want to change those settings, you need to
|
||||
remove the build directory and create it again.
|
||||
|
||||
Note that it is possible to build in-place; this will however overwrite the
|
||||
provided Makefiles (see `scripts/tmp_ignore_makefiles.sh` if you want to
|
||||
prevent `git status` from showing them as modified). In order to do so, from
|
||||
the Mbed TLS source directory, use:
|
||||
|
||||
cmake .
|
||||
make
|
||||
|
||||
If you want to change `CC` or `CFLAGS` afterwards, you will need to remove the
|
||||
CMake cache. This can be done with the following command using GNU find:
|
||||
|
||||
find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} +
|
||||
|
||||
You can now make the desired change:
|
||||
|
||||
CC=your_cc cmake .
|
||||
make
|
||||
|
||||
Regarding variables, also note that if you set CFLAGS when invoking cmake,
|
||||
your value of CFLAGS doesn't override the content provided by cmake (depending
|
||||
on the build mode as seen above), it's merely prepended to it.
|
||||
|
||||
### Microsoft Visual Studio
|
||||
|
||||
The build files for Microsoft Visual Studio are generated for Visual Studio 2010.
|
||||
|
||||
The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available.
|
||||
|
||||
Example programs
|
||||
----------------
|
||||
|
||||
We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code.
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
Mbed TLS includes an elaborate test suite in `tests/` that initially requires Python to generate the tests files (e.g. `test\_suite\_mpi.c`). These files are generated from a `function file` (e.g. `suites/test\_suite\_mpi.function`) and a `data file` (e.g. `suites/test\_suite\_mpi.data`). The `function file` contains the test functions. The `data file` contains the test cases, specified as parameters that will be passed to the test function.
|
||||
|
||||
For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, additional test scripts are available:
|
||||
|
||||
- `tests/ssl-opt.sh` runs integration tests for various TLS options (renegotiation, resumption, etc.) and tests interoperability of these options with other implementations.
|
||||
- `tests/compat.sh` tests interoperability of every ciphersuite with other implementations.
|
||||
- `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations.
|
||||
- `tests/scripts/key-exchanges.pl` test builds in configurations with a single key exchange enabled
|
||||
- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `config.h`, etc).
|
||||
|
||||
Configurations
|
||||
--------------
|
||||
|
||||
We provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt`
|
||||
|
||||
|
||||
Porting Mbed TLS
|
||||
----------------
|
||||
|
||||
Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful:
|
||||
|
||||
- [Porting Mbed TLS to a new environment or OS](https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS)
|
||||
- [What external dependencies does Mbed TLS rely on?](https://tls.mbed.org/kb/development/what-external-dependencies-does-mbedtls-rely-on)
|
||||
- [How do I configure Mbed TLS](https://tls.mbed.org/kb/compiling-and-building/how-do-i-configure-mbedtls)
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions:
|
||||
|
||||
- All contributions, whether large or small require a Contributor's License Agreement (CLA) to be accepted. This is because source code can possibly fall under copyright law and we need your consent to share in the ownership of the copyright.
|
||||
- We would ask that contributions conform to [our coding standards](https://tls.mbed.org/kb/development/mbedtls-coding-standards), and that contributions should be fully tested before submission.
|
||||
- As with any open source project, contributions will be reviewed by the project team and community and may need some modifications to be accepted.
|
||||
|
||||
To accept the Contributor’s Licence Agreement (CLA), individual contributors can do this by creating an Mbed account and [accepting the online agreement here with a click through](https://os.mbed.com/contributor_agreement/). Alternatively, for contributions from corporations, or those that do not wish to create an Mbed account, a slightly different agreement can be found [here](https://www.mbed.com/en/about-mbed/contributor-license-agreements/). This agreement should be signed and returned to Arm as described in the instructions given.
|
||||
|
||||
### Making a Contribution
|
||||
|
||||
1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://forums.mbed.com/c/mbed-tls) around a feature idea or a bug.
|
||||
2. Fork the [Mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the "development" branch as a basis.
|
||||
3. Write a test which shows that the bug was fixed or that the feature works as expected.
|
||||
4. Send a pull request and bug us until it gets merged and published. Contributions may need some modifications, so work with us to get your change accepted. We will include your name in the ChangeLog :)
|
||||
|
202
third_party/mbedtls/apache-2.0.txt
vendored
202
third_party/mbedtls/apache-2.0.txt
vendored
@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
26
third_party/mbedtls/configs/README.txt
vendored
26
third_party/mbedtls/configs/README.txt
vendored
@ -1,26 +0,0 @@
|
||||
This directory contains example configuration files.
|
||||
|
||||
The examples are generally focused on a particular usage case (eg, support for
|
||||
a restricted number of ciphersuites) and aim at minimizing resource usage for
|
||||
this target. They can be used as a basis for custom configurations.
|
||||
|
||||
These files are complete replacements for the default config.h. To use one of
|
||||
them, you can pick one of the following methods:
|
||||
|
||||
1. Replace the default file include/mbedtls/config.h with the chosen one.
|
||||
(Depending on your compiler, you may need to adjust the line with
|
||||
#include "mbedtls/check_config.h" then.)
|
||||
|
||||
2. Define MBEDTLS_CONFIG_FILE and adjust the include path accordingly.
|
||||
For example, using make:
|
||||
|
||||
CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE='<foo.h>'" make
|
||||
|
||||
Or, using cmake:
|
||||
|
||||
find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} +
|
||||
CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE='<foo.h>'" cmake .
|
||||
make
|
||||
|
||||
Note that the second method also works if you want to keep your custom
|
||||
configuration file outside the mbed TLS tree.
|
@ -1,88 +0,0 @@
|
||||
/**
|
||||
* \file config-ccm-psk-tls1_2.h
|
||||
*
|
||||
* \brief Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
|
||||
* Distinguishing features:
|
||||
* - no bignum, no PK, no X509
|
||||
* - fully modern and secure (provided the pre-shared keys have high entropy)
|
||||
* - very low record overhead with CCM-8
|
||||
* - optimized for low RAM usage
|
||||
*
|
||||
* See README.txt for usage instructions.
|
||||
*/
|
||||
#ifndef MBEDTLS_CONFIG_H
|
||||
#define MBEDTLS_CONFIG_H
|
||||
|
||||
/* System support */
|
||||
//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
|
||||
/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_CCM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_NET_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
|
||||
/* Save RAM at the expense of ROM */
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
|
||||
/* Save some RAM by adjusting to your exact needs */
|
||||
#define MBEDTLS_PSK_MAX_LEN 16 /* 128-bits keys are generally enough */
|
||||
|
||||
/*
|
||||
* You should adjust this to the exact number of sources you're using: default
|
||||
* is the "platform_entropy_poll" source, but you may want to add other ones
|
||||
* Minimum is 2 for the entropy test suite.
|
||||
*/
|
||||
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
|
||||
|
||||
/*
|
||||
* Use only CCM_8 ciphersuites, and
|
||||
* save ROM and a few bytes of RAM by specifying our own ciphersuite list
|
||||
*/
|
||||
#define MBEDTLS_SSL_CIPHERSUITES \
|
||||
MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \
|
||||
MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
|
||||
|
||||
/*
|
||||
* Save RAM at the expense of interoperability: do this only if you control
|
||||
* both ends of the connection! (See comments in "mbedtls/ssl.h".)
|
||||
* The optimal size here depends on the typical size of records.
|
||||
*/
|
||||
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
|
||||
|
||||
#include "mbedtls/check_config.h"
|
||||
|
||||
#endif /* MBEDTLS_CONFIG_H */
|
78
third_party/mbedtls/configs/config-mini-tls1_1.h
vendored
78
third_party/mbedtls/configs/config-mini-tls1_1.h
vendored
@ -1,78 +0,0 @@
|
||||
/**
|
||||
* \file config-mini-tls1_1.h
|
||||
*
|
||||
* \brief Minimal configuration for TLS 1.1 (RFC 4346)
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* Minimal configuration for TLS 1.1 (RFC 4346), implementing only the
|
||||
* required ciphersuite: MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||
*
|
||||
* See README.txt for usage instructions.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONFIG_H
|
||||
#define MBEDTLS_CONFIG_H
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_1
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_DES_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_NET_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
|
||||
/* For test certificates */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_CERTS_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
|
||||
/* For testing with compat.sh */
|
||||
#define MBEDTLS_FS_IO
|
||||
|
||||
#include "mbedtls/check_config.h"
|
||||
|
||||
#endif /* MBEDTLS_CONFIG_H */
|
92
third_party/mbedtls/configs/config-no-entropy.h
vendored
92
third_party/mbedtls/configs/config-no-entropy.h
vendored
@ -1,92 +0,0 @@
|
||||
/**
|
||||
* \file config-no-entropy.h
|
||||
*
|
||||
* \brief Minimal configuration of features that do not require an entropy source
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* Minimal configuration of features that do not require an entropy source
|
||||
* Distinguishing reatures:
|
||||
* - no entropy module
|
||||
* - no TLS protocol implementation available due to absence of an entropy
|
||||
* source
|
||||
*
|
||||
* See README.txt for usage instructions.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONFIG_H
|
||||
#define MBEDTLS_CONFIG_H
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
#define MBEDTLS_ECP_NIST_OPTIM
|
||||
#define MBEDTLS_ECDSA_DETERMINISTIC
|
||||
#define MBEDTLS_PK_RSA_ALT_SUPPORT
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_PKCS1_V21
|
||||
#define MBEDTLS_SELF_TEST
|
||||
#define MBEDTLS_VERSION_FEATURES
|
||||
#define MBEDTLS_X509_CHECK_KEY_USAGE
|
||||
#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CCM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ERROR_C
|
||||
#define MBEDTLS_GCM_C
|
||||
#define MBEDTLS_HMAC_DRBG_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_PK_WRITE_C
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_VERSION_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_CRL_PARSE_C
|
||||
//#define MBEDTLS_CMAC_C
|
||||
|
||||
/* Miscellaneous options */
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
|
||||
#include "check_config.h"
|
||||
|
||||
#endif /* MBEDTLS_CONFIG_H */
|
117
third_party/mbedtls/configs/config-suite-b.h
vendored
117
third_party/mbedtls/configs/config-suite-b.h
vendored
@ -1,117 +0,0 @@
|
||||
/**
|
||||
* \file config-suite-b.h
|
||||
*
|
||||
* \brief Minimal configuration for TLS NSA Suite B Profile (RFC 6460)
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* Minimal configuration for TLS NSA Suite B Profile (RFC 6460)
|
||||
*
|
||||
* Distinguishing features:
|
||||
* - no RSA or classic DH, fully based on ECC
|
||||
* - optimized for low RAM usage
|
||||
*
|
||||
* Possible improvements:
|
||||
* - if 128-bit security is enough, disable secp384r1 and SHA-512
|
||||
* - use embedded certs in DER format and disable PEM_PARSE_C and BASE64_C
|
||||
*
|
||||
* See README.txt for usage instructions.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONFIG_H
|
||||
#define MBEDTLS_CONFIG_H
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_GCM_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_NET_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
|
||||
/* For test certificates */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_CERTS_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
|
||||
/* Save RAM at the expense of ROM */
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
|
||||
/* Save RAM by adjusting to our exact needs */
|
||||
#define MBEDTLS_ECP_MAX_BITS 384
|
||||
#define MBEDTLS_MPI_MAX_SIZE 48 // 384 bits is 48 bytes
|
||||
|
||||
/* Save RAM at the expense of speed, see ecp.h */
|
||||
#define MBEDTLS_ECP_WINDOW_SIZE 2
|
||||
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0
|
||||
|
||||
/* Significant speed benefit at the expense of some ROM */
|
||||
#define MBEDTLS_ECP_NIST_OPTIM
|
||||
|
||||
/*
|
||||
* You should adjust this to the exact number of sources you're using: default
|
||||
* is the "mbedtls_platform_entropy_poll" source, but you may want to add other ones.
|
||||
* Minimum is 2 for the entropy test suite.
|
||||
*/
|
||||
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
|
||||
|
||||
/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
|
||||
#define MBEDTLS_SSL_CIPHERSUITES \
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
||||
|
||||
/*
|
||||
* Save RAM at the expense of interoperability: do this only if you control
|
||||
* both ends of the connection! (See coments in "mbedtls/ssl.h".)
|
||||
* The minimum size here depends on the certificate chain used as well as the
|
||||
* typical size of records.
|
||||
*/
|
||||
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
|
||||
|
||||
#include "mbedtls/check_config.h"
|
||||
|
||||
#endif /* MBEDTLS_CONFIG_H */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user