Compare commits

..

17 Commits

Author SHA1 Message Date
80432edbd0 add 2 new ubuntu docker files 2020-11-15 21:26:59 -08:00
23606b45c7 C++11 compatible 2020-11-15 21:09:58 -08:00
2aac0afca3 compile attempt 2 with old OpenSSL versions 2020-11-15 11:32:50 -08:00
508d8c7253 compile attempt with old OpenSSL versions 2020-11-15 11:23:44 -08:00
8f5134528b (ixwebsocket) use a C++11 compatible make_unique shim 2020-11-15 09:56:54 -08:00
738c6040f7 fix memory leak in dns unittest 2020-11-12 13:07:31 -08:00
1350e9b307 missing vector header 2020-11-11 21:47:07 -08:00
4e2a40e031 (socket) replace a std::vector with an std::array used as a tmp buffer in Socket::readBytes 2020-11-11 21:39:31 -08:00
594d2e194a linux asan / run test in verbose mode 2020-11-11 11:32:47 -08:00
977a1ed7e1 link ordering fix for Linux 2020-11-11 19:23:51 +00:00
8b3789af56 linux build fix attempt 2020-11-11 11:16:19 -08:00
f60485d9c2 use ctest for testing 2020-11-11 11:11:34 -08:00
b05b124cb3 update readme 2020-11-11 09:20:42 -08:00
723c208f22 fix version 2020-11-11 09:18:03 -08:00
21758f1183 (openssl security fix) in the client to server connection, peer verification is not done in all cases. See https://github.com/machinezone/IXWebSocket/pull/250 2020-11-11 09:16:14 -08:00
422febf15d (openssl) Always set verify peer when it is not disabled (#250) 2020-11-11 09:12:39 -08:00
51ec32405d (docker) build docker container with zlib disabled 2020-11-07 11:22:52 -08:00
42 changed files with 442 additions and 252 deletions

View File

@ -9,5 +9,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: make test_make - uses: seanmiddleditch/gha-setup-ninja@master
run: make test_make - name: make test
run: make test

View File

@ -0,0 +1,14 @@
name: linux_asan
on:
push:
paths-ignore:
- 'docs/**'
jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: seanmiddleditch/gha-setup-ninja@master
- name: make test_asan
run: make test_asan

View File

@ -9,6 +9,7 @@ jobs:
runs-on: macOS-latest runs-on: macOS-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: seanmiddleditch/gha-setup-ninja@master
- name: install mbedtls - name: install mbedtls
run: brew install mbedtls run: brew install mbedtls
- name: make test - name: make test

View File

@ -9,6 +9,7 @@ jobs:
runs-on: macOS-latest runs-on: macOS-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: seanmiddleditch/gha-setup-ninja@master
- name: install openssl - name: install openssl
run: brew install openssl@1.1 run: brew install openssl@1.1
- name: make test - name: make test

View File

@ -9,5 +9,6 @@ jobs:
runs-on: macOS-latest runs-on: macOS-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: make test_tsan - uses: seanmiddleditch/gha-setup-ninja@master
run: make test_tsan - name: make test_tsan_sectransport
run: make test_tsan_sectransport

View File

@ -8,7 +8,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
project(ixwebsocket C CXX) project(ixwebsocket C CXX)
set (CMAKE_CXX_STANDARD 14) set (CMAKE_CXX_STANDARD 11)
set (CXX_STANDARD_REQUIRED ON) set (CXX_STANDARD_REQUIRED ON)
set (CMAKE_CXX_EXTENSIONS OFF) set (CMAKE_CXX_EXTENSIONS OFF)
@ -45,6 +45,7 @@ set( IXWEBSOCKET_SOURCES
ixwebsocket/IXSocketFactory.cpp ixwebsocket/IXSocketFactory.cpp
ixwebsocket/IXSocketServer.cpp ixwebsocket/IXSocketServer.cpp
ixwebsocket/IXSocketTLSOptions.cpp ixwebsocket/IXSocketTLSOptions.cpp
ixwebsocket/IXStrCaseCompare.cpp
ixwebsocket/IXUdpSocket.cpp ixwebsocket/IXUdpSocket.cpp
ixwebsocket/IXUrlParser.cpp ixwebsocket/IXUrlParser.cpp
ixwebsocket/IXUserAgent.cpp ixwebsocket/IXUserAgent.cpp
@ -82,6 +83,7 @@ set( IXWEBSOCKET_HEADERS
ixwebsocket/IXSocketFactory.h ixwebsocket/IXSocketFactory.h
ixwebsocket/IXSocketServer.h ixwebsocket/IXSocketServer.h
ixwebsocket/IXSocketTLSOptions.h ixwebsocket/IXSocketTLSOptions.h
ixwebsocket/IXStrCaseCompare.h
ixwebsocket/IXUdpSocket.h ixwebsocket/IXUdpSocket.h
ixwebsocket/IXUrlParser.h ixwebsocket/IXUrlParser.h
ixwebsocket/IXUtf8Validator.h ixwebsocket/IXUtf8Validator.h
@ -273,6 +275,7 @@ if (USE_WS OR USE_TEST)
add_subdirectory(ws) add_subdirectory(ws)
endif() endif()
if (USE_TEST) if (USE_TEST)
enable_testing()
add_subdirectory(test) add_subdirectory(test)
endif() endif()
endif() endif()

View File

@ -4,6 +4,8 @@ IXWebSocket is a C++ library for WebSocket client and server development. It has
It is been used on big mobile video game titles sending and receiving tons of messages since 2017 (iOS and Android). It was tested on macOS, iOS, Linux, Android, Windows and FreeBSD. Note that the MinGW compiler is not supported at this point. Two important design goals are simplicity and correctness. It is been used on big mobile video game titles sending and receiving tons of messages since 2017 (iOS and Android). It was tested on macOS, iOS, Linux, Android, Windows and FreeBSD. Note that the MinGW compiler is not supported at this point. Two important design goals are simplicity and correctness.
A bad security bug affecting users compiling with SSL enabled and OpenSSL as the backend was just fixed in newly released version 11.0.0. Please upgrade ! (more details in the [https://github.com/machinezone/IXWebSocket/pull/250](PR).
```cpp ```cpp
/* /*
* main.cpp * main.cpp
@ -90,18 +92,20 @@ If your company or project is using this library, feel free to open an issue or
| OS | TLS | Sanitizer | Status | | OS | TLS | Sanitizer | Status |
|-------------------|-------------------|-------------------|-------------------| |-------------------|-------------------|-------------------|-------------------|
| Linux | OpenSSL | None | [![Build2][1]][7] | | Linux | OpenSSL | None | [![Build2][1]][0] |
| macOS | Secure Transport | Thread Sanitizer | [![Build2][2]][7] | | macOS | Secure Transport | Thread Sanitizer | [![Build2][2]][0] |
| macOS | OpenSSL | Thread Sanitizer | [![Build2][3]][7] | | macOS | OpenSSL | Thread Sanitizer | [![Build2][3]][0] |
| macOS | MbedTLS | Thread Sanitizer | [![Build2][4]][7] | | macOS | MbedTLS | Thread Sanitizer | [![Build2][4]][0] |
| Windows | Disabled | None | [![Build2][5]][7] | | Windows | Disabled | None | [![Build2][5]][0] |
| UWP | Disabled | None | [![Build2][6]][7] | | UWP | Disabled | None | [![Build2][6]][0] |
| Linux | OpenSSL | Address Sanitizer | [![Build2][7]][0] |
[0]: https://github.com/machinezone/IXWebSocket
[1]: https://github.com/machinezone/IXWebSocket/workflows/linux/badge.svg [1]: https://github.com/machinezone/IXWebSocket/workflows/linux/badge.svg
[2]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_sectransport/badge.svg [2]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_sectransport/badge.svg
[3]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_openssl/badge.svg [3]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_openssl/badge.svg
[4]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_mbedtls/badge.svg [4]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_mbedtls/badge.svg
[5]: https://github.com/machinezone/IXWebSocket/workflows/windows/badge.svg [5]: https://github.com/machinezone/IXWebSocket/workflows/windows/badge.svg
[6]: https://github.com/machinezone/IXWebSocket/workflows/uwp/badge.svg [6]: https://github.com/machinezone/IXWebSocket/workflows/uwp/badge.svg
[7]: https://github.com/machinezone/IXWebSocket [7]: https://github.com/machinezone/IXWebSocket/workflows/linux_asan/badge.svg

26
docker/Dockerfile.centos7 Normal file
View File

@ -0,0 +1,26 @@
FROM centos:7 as build
RUN yum install -y gcc-c++ make zlib-devel openssl-devel redhat-rpm-config
RUN groupadd app && useradd -g app app
RUN chown -R app:app /opt
RUN chown -R app:app /usr/local
WORKDIR /tmp
RUN curl -O https://cmake.org/files/v3.14/cmake-3.14.0-Linux-x86_64.tar.gz
RUN tar zxvf cmake-3.14.0-Linux-x86_64.tar.gz
RUN cp -rf cmake-3.14.0-Linux-x86_64/* /usr/
RUN yum install -y git
# There is a bug in CMake where we cannot build from the root top folder
# So we build from /opt
COPY --chown=app:app . /opt
WORKDIR /opt
USER app
RUN [ "make", "ws_no_python" ]
RUN [ "rm", "-rf", "build" ]
ENTRYPOINT ["ws"]
CMD ["--help"]

View File

@ -0,0 +1,27 @@
# Build time
FROM ubuntu:precise as build
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update
RUN apt-get -y install wget
RUN mkdir -p /tmp/cmake
WORKDIR /tmp/cmake
RUN wget --no-check-certificate https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz
RUN tar zxf cmake-3.14.0-Linux-x86_64.tar.gz
RUN apt-get -y install g++
RUN apt-get -y install libssl-dev
RUN apt-get -y install libz-dev
RUN apt-get -y install make
RUN apt-get -y install python
RUN apt-get -y install git
COPY . .
ARG CMAKE_BIN_PATH=/tmp/cmake/cmake-3.14.0-Linux-x86_64/bin
ENV PATH="${CMAKE_BIN_PATH}:${PATH}"
RUN ["make", "ws_no_python"]
ENTRYPOINT ["ws"]
CMD ["--help"]

View File

@ -0,0 +1,22 @@
# Build time
FROM ubuntu:trusty as build
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update
RUN apt-get -y install wget
RUN mkdir -p /tmp/cmake
WORKDIR /tmp/cmake
RUN wget --no-check-certificate https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz
RUN tar zxf cmake-3.14.0-Linux-x86_64.tar.gz
RUN apt-get -y install g++ libssl-dev libz-dev make python git
COPY . .
ARG CMAKE_BIN_PATH=/tmp/cmake/cmake-3.14.0-Linux-x86_64/bin
ENV PATH="${CMAKE_BIN_PATH}:${PATH}"
RUN ["make", "ws_no_python"]
ENTRYPOINT ["ws"]
CMD ["--help"]

View File

@ -2,6 +2,22 @@
All changes to this project will be documented in this file. All changes to this project will be documented in this file.
## [11.0.2] - 2020-11-15
(ixwebsocket) use a C++11 compatible make_unique shim
## [11.0.1] - 2020-11-11
(socket) replace a std::vector with an std::array used as a tmp buffer in Socket::readBytes
## [11.0.0] - 2020-11-11
(openssl security fix) in the client to server connection, peer verification is not done in all cases. See https://github.com/machinezone/IXWebSocket/pull/250
## [10.5.7] - 2020-11-07
(docker) build docker container with zlib disabled
## [10.5.6] - 2020-11-07 ## [10.5.6] - 2020-11-07
(cmake) DEFLATE -> Deflate in CMake to stop warnings about casing (cmake) DEFLATE -> Deflate in CMake to stop warnings about casing

View File

@ -14,6 +14,7 @@
#include <ixcrypto/IXHMac.h> #include <ixcrypto/IXHMac.h>
#include <ixwebsocket/IXSocketTLSOptions.h> #include <ixwebsocket/IXSocketTLSOptions.h>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXUniquePtr.h>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
@ -98,7 +99,7 @@ namespace ix
if (_eventCallback) if (_eventCallback)
{ {
_eventCallback( _eventCallback(
std::make_unique<CobraEvent>(eventType, errorMsg, headers, subscriptionId, msgId, connectionId)); ix::make_unique<CobraEvent>(eventType, errorMsg, headers, subscriptionId, msgId, connectionId));
} }
} }

View File

@ -10,6 +10,7 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include <ixwebsocket/IXSocket.h> #include <ixwebsocket/IXSocket.h>
namespace ix namespace ix

View File

@ -16,6 +16,7 @@
#include <string> #include <string>
#include <thread> #include <thread>
#include <utility> // pair #include <utility> // pair
#include <vector> // pair
namespace ix namespace ix
{ {

View File

@ -2,6 +2,17 @@
# Author: Benjamin Sergeant # Author: Benjamin Sergeant
# Copyright (c) 2019 Machine Zone, Inc. All rights reserved. # Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
# #
include(CheckCSourceCompiles)
check_c_source_compiles("#include <regex>
int main()
{
const std::regex dsnRegex;
std::smatch group;
std::regex_match(std::string(), group, dsnRegex);
return 0;
}"
HAVE_STD_REGEX)
set (IXSENTRY_SOURCES set (IXSENTRY_SOURCES
ixsentry/IXSentryClient.cpp ixsentry/IXSentryClient.cpp
@ -28,3 +39,7 @@ set(IXSENTRY_INCLUDE_DIRS
${JSONCPP_INCLUDE_DIRS}) ${JSONCPP_INCLUDE_DIRS})
target_include_directories( ixsentry PUBLIC ${IXSENTRY_INCLUDE_DIRS} ) target_include_directories( ixsentry PUBLIC ${IXSENTRY_INCLUDE_DIRS} )
if (HAVE_STD_REGEX)
target_compile_definitions( ixsentry PUBLIC HAVE_STD_REGEX=1 )
endif()

View File

@ -20,9 +20,12 @@ namespace ix
SentryClient::SentryClient(const std::string& dsn) SentryClient::SentryClient(const std::string& dsn)
: _dsn(dsn) : _dsn(dsn)
, _validDsn(false) , _validDsn(false)
#ifdef HAVE_STD_REGEX
, _luaFrameRegex("\t([^/]+):([0-9]+): in function ['<]([^/]+)['>]") , _luaFrameRegex("\t([^/]+):([0-9]+): in function ['<]([^/]+)['>]")
#endif
, _httpClient(std::make_shared<HttpClient>(true)) , _httpClient(std::make_shared<HttpClient>(true))
{ {
#ifdef HAVE_STD_REGEX
const std::regex dsnRegex("(http[s]?)://([^:]+):([^@]+)@([^/]+)/([0-9]+)"); const std::regex dsnRegex("(http[s]?)://([^:]+):([^@]+)@([^/]+)/([0-9]+)");
std::smatch group; std::smatch group;
@ -38,6 +41,7 @@ namespace ix
_publicKey = group.str(2); _publicKey = group.str(2);
_secretKey = group.str(3); _secretKey = group.str(3);
} }
#endif
} }
void SentryClient::setTLSOptions(const SocketTLSOptions& tlsOptions) void SentryClient::setTLSOptions(const SocketTLSOptions& tlsOptions)
@ -77,6 +81,7 @@ namespace ix
{ {
Json::Value frames; Json::Value frames;
#ifdef HAVE_STD_REGEX
// Split by lines // Split by lines
std::string line; std::string line;
std::stringstream tokenStream(stack); std::stringstream tokenStream(stack);
@ -107,6 +112,7 @@ namespace ix
} }
std::reverse(frames.begin(), frames.end()); std::reverse(frames.begin(), frames.end());
#endif
return frames; return frames;
} }

View File

@ -11,7 +11,9 @@
#include <ixwebsocket/IXSocketTLSOptions.h> #include <ixwebsocket/IXSocketTLSOptions.h>
#include <json/json.h> #include <json/json.h>
#include <memory> #include <memory>
#ifdef HAVE_STD_REGEX
#include <regex> #include <regex>
#endif
namespace ix namespace ix
{ {
@ -62,7 +64,9 @@ namespace ix
Json::FastWriter _jsonWriter; Json::FastWriter _jsonWriter;
#ifdef HAVE_STD_REGEX
std::regex _luaFrameRegex; std::regex _luaFrameRegex;
#endif
std::shared_ptr<HttpClient> _httpClient; std::shared_ptr<HttpClient> _httpClient;
}; };

View File

@ -13,6 +13,7 @@
#include <ixcore/utils/IXCoreLogger.h> #include <ixcore/utils/IXCoreLogger.h>
#include <ixcrypto/IXHMac.h> #include <ixcrypto/IXHMac.h>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXUniquePtr.h>
#include <sstream> #include <sstream>
namespace snake namespace snake
@ -196,7 +197,7 @@ namespace snake
{ {
std::string filterStr = pdu["body"]["filter"]; std::string filterStr = pdu["body"]["filter"];
} }
state->streamSql = std::make_unique<StreamSql>(filterStr); state->streamSql = ix::make_unique<StreamSql>(filterStr);
state->id = 0; state->id = 0;
state->onRedisSubscribeCallback = [&ws, state](const std::string& messageStr) { state->onRedisSubscribeCallback = [&ws, state](const std::string& messageStr) {
auto msg = nlohmann::json::parse(messageStr); auto msg = nlohmann::json::parse(messageStr);

View File

@ -68,6 +68,11 @@ namespace ix
: resolveUnCancellable(errMsg, isCancellationRequested); : resolveUnCancellable(errMsg, isCancellationRequested);
} }
void DNSLookup::release(struct addrinfo* addr)
{
freeaddrinfo(addr);
}
struct addrinfo* DNSLookup::resolveUnCancellable( struct addrinfo* DNSLookup::resolveUnCancellable(
std::string& errMsg, const CancellationRequest& isCancellationRequested) std::string& errMsg, const CancellationRequest& isCancellationRequested)
{ {

View File

@ -31,6 +31,8 @@ namespace ix
const CancellationRequest& isCancellationRequested, const CancellationRequest& isCancellationRequested,
bool cancellable = true); bool cancellable = true);
void release(struct addrinfo* addr);
private: private:
struct addrinfo* resolveCancellable(std::string& errMsg, struct addrinfo* resolveCancellable(std::string& errMsg,
const CancellationRequest& isCancellationRequested); const CancellationRequest& isCancellationRequested);

View File

@ -20,9 +20,11 @@
namespace ix namespace ix
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
std::string gzipCompress(const std::string& str) std::string gzipCompress(const std::string& str)
{ {
#ifndef IXWEBSOCKET_USE_ZLIB
return std::string();
#else
#ifdef IXWEBSOCKET_USE_DEFLATE #ifdef IXWEBSOCKET_USE_DEFLATE
int compressionLevel = 6; int compressionLevel = 6;
struct libdeflate_compressor* compressor; struct libdeflate_compressor* compressor;
@ -99,7 +101,8 @@ namespace ix
deflateEnd(&zs); deflateEnd(&zs);
return outstring; return outstring;
#endif #endif // IXWEBSOCKET_USE_DEFLATE
#endif // IXWEBSOCKET_USE_ZLIB
} }
#ifdef IXWEBSOCKET_USE_DEFLATE #ifdef IXWEBSOCKET_USE_DEFLATE
@ -112,6 +115,9 @@ namespace ix
bool gzipDecompress(const std::string& in, std::string& out) bool gzipDecompress(const std::string& in, std::string& out)
{ {
#ifndef IXWEBSOCKET_USE_ZLIB
return false;
#else
#ifdef IXWEBSOCKET_USE_DEFLATE #ifdef IXWEBSOCKET_USE_DEFLATE
struct libdeflate_decompressor* decompressor; struct libdeflate_decompressor* decompressor;
decompressor = libdeflate_alloc_decompressor(); decompressor = libdeflate_alloc_decompressor();
@ -171,7 +177,7 @@ namespace ix
inflateEnd(&inflateState); inflateEnd(&inflateState);
return true; return true;
#endif #endif // IXWEBSOCKET_USE_DEFLATE
#endif // IXWEBSOCKET_USE_ZLIB
} }
#endif
} // namespace ix } // namespace ix

View File

@ -6,6 +6,7 @@
#include "IXSelectInterruptFactory.h" #include "IXSelectInterruptFactory.h"
#include "IXUniquePtr.h"
#if defined(__linux__) || defined(__APPLE__) #if defined(__linux__) || defined(__APPLE__)
#include "IXSelectInterruptPipe.h" #include "IXSelectInterruptPipe.h"
#else #else
@ -17,9 +18,9 @@ namespace ix
SelectInterruptPtr createSelectInterrupt() SelectInterruptPtr createSelectInterrupt()
{ {
#if defined(__linux__) || defined(__APPLE__) #if defined(__linux__) || defined(__APPLE__)
return std::make_unique<SelectInterruptPipe>(); return ix::make_unique<SelectInterruptPipe>();
#else #else
return std::make_unique<SelectInterrupt>(); return ix::make_unique<SelectInterrupt>();
#endif #endif
} }
} // namespace ix } // namespace ix

View File

@ -11,6 +11,7 @@
#include "IXSelectInterruptFactory.h" #include "IXSelectInterruptFactory.h"
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include <algorithm> #include <algorithm>
#include <array>
#include <assert.h> #include <assert.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdint.h> #include <stdint.h>
@ -18,6 +19,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <vector>
#ifdef min #ifdef min
#undef min #undef min
@ -27,7 +29,6 @@ namespace ix
{ {
const int Socket::kDefaultPollNoTimeout = -1; // No poll timeout by default const int Socket::kDefaultPollNoTimeout = -1; // No poll timeout by default
const int Socket::kDefaultPollTimeout = kDefaultPollNoTimeout; const int Socket::kDefaultPollTimeout = kDefaultPollNoTimeout;
constexpr size_t Socket::kChunkSize;
Socket::Socket(int fd) Socket::Socket(int fd)
: _sockfd(fd) : _sockfd(fd)
@ -364,10 +365,7 @@ namespace ix
const OnProgressCallback& onProgressCallback, const OnProgressCallback& onProgressCallback,
const CancellationRequest& isCancellationRequested) const CancellationRequest& isCancellationRequested)
{ {
if (_readBuffer.empty()) std::array<uint8_t, 1 << 14> readBuffer;
{
_readBuffer.resize(kChunkSize);
}
std::vector<uint8_t> output; std::vector<uint8_t> output;
while (output.size() != length) while (output.size() != length)
@ -378,12 +376,12 @@ namespace ix
return std::make_pair(false, errorMsg); return std::make_pair(false, errorMsg);
} }
size_t size = std::min(kChunkSize, length - output.size()); size_t size = std::min(readBuffer.size(), length - output.size());
ssize_t ret = recv((char*) &_readBuffer[0], size); ssize_t ret = recv((char*) &readBuffer[0], size);
if (ret > 0) if (ret > 0)
{ {
output.insert(output.end(), _readBuffer.begin(), _readBuffer.begin() + ret); output.insert(output.end(), readBuffer.begin(), readBuffer.begin() + ret);
} }
else if (ret <= 0 && !Socket::isWaitNeeded()) else if (ret <= 0 && !Socket::isWaitNeeded())
{ {

View File

@ -11,7 +11,6 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <vector>
#ifdef _WIN32 #ifdef _WIN32
#include <BaseTsd.h> #include <BaseTsd.h>
@ -102,10 +101,6 @@ namespace ix
static const int kDefaultPollTimeout; static const int kDefaultPollTimeout;
static const int kDefaultPollNoTimeout; static const int kDefaultPollNoTimeout;
// Buffer for reading from our socket. That buffer is never resized.
std::vector<uint8_t> _readBuffer;
static constexpr size_t kChunkSize = 1 << 15;
SelectInterruptPtr _selectInterrupt; SelectInterruptPtr _selectInterrupt;
}; };
} // namespace ix } // namespace ix

View File

@ -10,6 +10,7 @@
#include "IXNetSystem.h" #include "IXNetSystem.h"
#include "IXSelectInterrupt.h" #include "IXSelectInterrupt.h"
#include "IXSocket.h" #include "IXSocket.h"
#include "IXUniquePtr.h"
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
@ -65,7 +66,7 @@ namespace ix
int timeoutMs = 10; int timeoutMs = 10;
bool readyToRead = false; bool readyToRead = false;
auto selectInterrupt = std::make_unique<SelectInterrupt>(); auto selectInterrupt = ix::make_unique<SelectInterrupt>();
PollResultType pollResult = Socket::poll(readyToRead, timeoutMs, fd, selectInterrupt); PollResultType pollResult = Socket::poll(readyToRead, timeoutMs, fd, selectInterrupt);
if (pollResult == PollResultType::Timeout) if (pollResult == PollResultType::Timeout)

View File

@ -6,6 +6,7 @@
#include "IXSocketFactory.h" #include "IXSocketFactory.h"
#include "IXUniquePtr.h"
#ifdef IXWEBSOCKET_USE_TLS #ifdef IXWEBSOCKET_USE_TLS
#ifdef IXWEBSOCKET_USE_MBED_TLS #ifdef IXWEBSOCKET_USE_MBED_TLS
@ -35,17 +36,17 @@ namespace ix
if (!tls) if (!tls)
{ {
socket = std::make_unique<Socket>(fd); socket = ix::make_unique<Socket>(fd);
} }
else else
{ {
#ifdef IXWEBSOCKET_USE_TLS #ifdef IXWEBSOCKET_USE_TLS
#if defined(IXWEBSOCKET_USE_MBED_TLS) #if defined(IXWEBSOCKET_USE_MBED_TLS)
socket = std::make_unique<SocketMbedTLS>(tlsOptions, fd); socket = ix::make_unique<SocketMbedTLS>(tlsOptions, fd);
#elif defined(IXWEBSOCKET_USE_OPEN_SSL) #elif defined(IXWEBSOCKET_USE_OPEN_SSL)
socket = std::make_unique<SocketOpenSSL>(tlsOptions, fd); socket = ix::make_unique<SocketOpenSSL>(tlsOptions, fd);
#elif defined(__APPLE__) #elif defined(__APPLE__)
socket = std::make_unique<SocketAppleSSL>(tlsOptions, fd); socket = ix::make_unique<SocketAppleSSL>(tlsOptions, fd);
#endif #endif
#else #else
errorMsg = "TLS support is not enabled on this platform."; errorMsg = "TLS support is not enabled on this platform.";

View File

@ -10,8 +10,10 @@
#include "IXSocketOpenSSL.h" #include "IXSocketOpenSSL.h"
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include "IXUniquePtr.h"
#include <cassert> #include <cassert>
#include <errno.h> #include <errno.h>
#include <vector>
#ifdef _WIN32 #ifdef _WIN32
#include <Shlwapi.h> #include <Shlwapi.h>
#else #else
@ -85,8 +87,7 @@ namespace ix
std::atomic<bool> SocketOpenSSL::_openSSLInitializationSuccessful(false); std::atomic<bool> SocketOpenSSL::_openSSLInitializationSuccessful(false);
std::once_flag SocketOpenSSL::_openSSLInitFlag; std::once_flag SocketOpenSSL::_openSSLInitFlag;
std::unique_ptr<std::mutex[]> SocketOpenSSL::_openSSLMutexes = std::vector<std::unique_ptr<std::mutex>> openSSLMutexes;
std::make_unique<std::mutex[]>(CRYPTO_num_locks());
SocketOpenSSL::SocketOpenSSL(const SocketTLSOptions& tlsOptions, int fd) SocketOpenSSL::SocketOpenSSL(const SocketTLSOptions& tlsOptions, int fd)
: Socket(fd) : Socket(fd)
@ -111,6 +112,11 @@ namespace ix
if (CRYPTO_get_locking_callback() == nullptr) if (CRYPTO_get_locking_callback() == nullptr)
{ {
openSSLMutexes.clear();
for (int i = 0; i < CRYPTO_num_locks(); ++i)
{
openSSLMutexes.push_back(ix::make_unique<std::mutex>());
}
CRYPTO_set_locking_callback(SocketOpenSSL::openSSLLockingCallback); CRYPTO_set_locking_callback(SocketOpenSSL::openSSLLockingCallback);
} }
#endif #endif
@ -128,11 +134,11 @@ namespace ix
{ {
if (mode & CRYPTO_LOCK) if (mode & CRYPTO_LOCK)
{ {
_openSSLMutexes[type].lock(); openSSLMutexes[type]->lock();
} }
else else
{ {
_openSSLMutexes[type].unlock(); openSSLMutexes[type]->unlock();
} }
} }
@ -503,15 +509,14 @@ namespace ix
errMsg += ERR_error_string(sslErr, nullptr); errMsg += ERR_error_string(sslErr, nullptr);
return false; return false;
} }
}
}
SSL_CTX_set_verify( SSL_CTX_set_verify(_ssl_context,
_ssl_context, SSL_VERIFY_PEER, [](int preverify, X509_STORE_CTX*) -> int { SSL_VERIFY_PEER,
return preverify; [](int preverify, X509_STORE_CTX*) -> int { return preverify; });
});
SSL_CTX_set_verify_depth(_ssl_context, 4); SSL_CTX_set_verify_depth(_ssl_context, 4);
} }
}
}
else else
{ {
SSL_CTX_set_verify(_ssl_context, SSL_VERIFY_NONE, nullptr); SSL_CTX_set_verify(_ssl_context, SSL_VERIFY_NONE, nullptr);

View File

@ -61,7 +61,6 @@ namespace ix
static std::once_flag _openSSLInitFlag; static std::once_flag _openSSLInitFlag;
static std::atomic<bool> _openSSLInitializationSuccessful; static std::atomic<bool> _openSSLInitializationSuccessful;
static std::unique_ptr<std::mutex[]> _openSSLMutexes;
}; };
} // namespace ix } // namespace ix

View File

@ -0,0 +1,37 @@
/*
* IXStrCaseCompare.cpp
* Author: Benjamin Sergeant
* Copyright (c) 2020 Machine Zone. All rights reserved.
*/
#include "IXStrCaseCompare.h"
#include <algorithm>
#include <locale>
namespace ix
{
bool CaseInsensitiveLess::NocaseCompare::operator()(const unsigned char& c1,
const unsigned char& c2) const
{
#ifdef _WIN32
return std::tolower(c1, std::locale()) < std::tolower(c2, std::locale());
#else
return std::tolower(c1) < std::tolower(c2);
#endif
}
bool CaseInsensitiveLess::cmp(const std::string& s1, const std::string& s2)
{
return std::lexicographical_compare(s1.begin(),
s1.end(), // source range
s2.begin(),
s2.end(), // dest range
NocaseCompare()); // comparison
}
bool CaseInsensitiveLess::operator()(const std::string& s1, const std::string& s2) const
{
return CaseInsensitiveLess::cmp(s1, s2);
}
} // namespace ix

View File

@ -0,0 +1,25 @@
/*
* IXStrCaseCompare.h
* Author: Benjamin Sergeant
* Copyright (c) 2020 Machine Zone. All rights reserved.
*/
#pragma once
#include <string>
namespace ix
{
struct CaseInsensitiveLess
{
// Case Insensitive compare_less binary function
struct NocaseCompare
{
bool operator()(const unsigned char& c1, const unsigned char& c2) const;
};
static bool cmp(const std::string& s1, const std::string& s2);
bool operator()(const std::string& s1, const std::string& s2) const;
};
} // namespace ix

18
ixwebsocket/IXUniquePtr.h Normal file
View File

@ -0,0 +1,18 @@
/*
* IXUniquePtr.h
* Author: Benjamin Sergeant
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
*/
#pragma once
#include <memory>
namespace ix
{
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
} // namespace ix

View File

@ -8,6 +8,7 @@
#include "IXExponentialBackoff.h" #include "IXExponentialBackoff.h"
#include "IXSetThreadName.h" #include "IXSetThreadName.h"
#include "IXUniquePtr.h"
#include "IXUtf8Validator.h" #include "IXUtf8Validator.h"
#include "IXWebSocketHandshake.h" #include "IXWebSocketHandshake.h"
#include <cassert> #include <cassert>
@ -34,7 +35,7 @@ namespace ix
_ws.setOnCloseCallback( _ws.setOnCloseCallback(
[this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) { [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) {
_onMessageCallback( _onMessageCallback(
std::make_unique<WebSocketMessage>(WebSocketMessageType::Close, ix::make_unique<WebSocketMessage>(WebSocketMessageType::Close,
"", "",
wireSize, wireSize,
WebSocketErrorInfo(), WebSocketErrorInfo(),
@ -195,7 +196,7 @@ namespace ix
return status; return status;
} }
_onMessageCallback(std::make_unique<WebSocketMessage>( _onMessageCallback(ix::make_unique<WebSocketMessage>(
WebSocketMessageType::Open, WebSocketMessageType::Open,
"", "",
0, 0,
@ -227,7 +228,7 @@ namespace ix
} }
_onMessageCallback( _onMessageCallback(
std::make_unique<WebSocketMessage>(WebSocketMessageType::Open, ix::make_unique<WebSocketMessage>(WebSocketMessageType::Open,
"", "",
0, 0,
WebSocketErrorInfo(), WebSocketErrorInfo(),
@ -312,7 +313,7 @@ namespace ix
connectErr.reason = status.errorStr; connectErr.reason = status.errorStr;
connectErr.http_status = status.http_status; connectErr.http_status = status.http_status;
_onMessageCallback(std::make_unique<WebSocketMessage>(WebSocketMessageType::Error, _onMessageCallback(ix::make_unique<WebSocketMessage>(WebSocketMessageType::Error,
"", "",
0, 0,
connectErr, connectErr,
@ -388,7 +389,7 @@ namespace ix
bool binary = messageKind == WebSocketTransport::MessageKind::MSG_BINARY; bool binary = messageKind == WebSocketTransport::MessageKind::MSG_BINARY;
_onMessageCallback(std::make_unique<WebSocketMessage>(webSocketMessageType, _onMessageCallback(ix::make_unique<WebSocketMessage>(webSocketMessageType,
msg, msg,
wireSize, wireSize,
webSocketErrorInfo, webSocketErrorInfo,

View File

@ -11,6 +11,7 @@
#include "IXUrlParser.h" #include "IXUrlParser.h"
#include "IXUserAgent.h" #include "IXUserAgent.h"
#include "IXWebSocketHandshakeKeyGen.h" #include "IXWebSocketHandshakeKeyGen.h"
#include "IXStrCaseCompare.h"
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <random> #include <random>
@ -35,9 +36,7 @@ namespace ix
bool WebSocketHandshake::insensitiveStringCompare(const std::string& a, const std::string& b) bool WebSocketHandshake::insensitiveStringCompare(const std::string& a, const std::string& b)
{ {
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return CaseInsensitiveLess::cmp(a, b);
return tolower(a) == tolower(b);
});
} }
std::string WebSocketHandshake::genRandomString(const int len) std::string WebSocketHandshake::genRandomString(const int len)

View File

@ -12,25 +12,6 @@
namespace ix namespace ix
{ {
bool CaseInsensitiveLess::NocaseCompare::operator()(const unsigned char& c1,
const unsigned char& c2) const
{
#ifdef _WIN32
return std::tolower(c1, std::locale()) < std::tolower(c2, std::locale());
#else
return std::tolower(c1) < std::tolower(c2);
#endif
}
bool CaseInsensitiveLess::operator()(const std::string& s1, const std::string& s2) const
{
return std::lexicographical_compare(s1.begin(),
s1.end(), // source range
s2.begin(),
s2.end(), // dest range
NocaseCompare()); // comparison
}
std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders( std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders(
std::unique_ptr<Socket>& socket, const CancellationRequest& isCancellationRequested) std::unique_ptr<Socket>& socket, const CancellationRequest& isCancellationRequested)
{ {

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "IXCancellationRequest.h" #include "IXCancellationRequest.h"
#include "IXStrCaseCompare.h"
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
@ -15,17 +16,6 @@ namespace ix
{ {
class Socket; class Socket;
struct CaseInsensitiveLess
{
// Case Insensitive compare_less binary function
struct NocaseCompare
{
bool operator()(const unsigned char& c1, const unsigned char& c2) const;
};
bool operator()(const std::string& s1, const std::string& s2) const;
};
using WebSocketHttpHeaders = std::map<std::string, std::string, CaseInsensitiveLess>; using WebSocketHttpHeaders = std::map<std::string, std::string, CaseInsensitiveLess>;
std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders( std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders(

View File

@ -48,14 +48,15 @@
#include "IXWebSocketPerMessageDeflate.h" #include "IXWebSocketPerMessageDeflate.h"
#include "IXUniquePtr.h"
#include "IXWebSocketPerMessageDeflateCodec.h" #include "IXWebSocketPerMessageDeflateCodec.h"
#include "IXWebSocketPerMessageDeflateOptions.h" #include "IXWebSocketPerMessageDeflateOptions.h"
namespace ix namespace ix
{ {
WebSocketPerMessageDeflate::WebSocketPerMessageDeflate() WebSocketPerMessageDeflate::WebSocketPerMessageDeflate()
: _compressor(std::make_unique<WebSocketPerMessageDeflateCompressor>()) : _compressor(ix::make_unique<WebSocketPerMessageDeflateCompressor>())
, _decompressor(std::make_unique<WebSocketPerMessageDeflateDecompressor>()) , _decompressor(ix::make_unique<WebSocketPerMessageDeflateDecompressor>())
{ {
; ;
} }

View File

@ -36,6 +36,7 @@
#include "IXSocketFactory.h" #include "IXSocketFactory.h"
#include "IXSocketTLSOptions.h" #include "IXSocketTLSOptions.h"
#include "IXUniquePtr.h"
#include "IXUrlParser.h" #include "IXUrlParser.h"
#include "IXUtf8Validator.h" #include "IXUtf8Validator.h"
#include "IXWebSocketHandshake.h" #include "IXWebSocketHandshake.h"
@ -124,7 +125,7 @@ namespace ix
std::string errorMsg; std::string errorMsg;
bool tls = protocol == "wss"; bool tls = protocol == "wss";
_socket = createSocket(tls, -1, errorMsg, _socketTLSOptions); _socket = createSocket(tls, -1, errorMsg, _socketTLSOptions);
_perMessageDeflate = std::make_unique<WebSocketPerMessageDeflate>(); _perMessageDeflate = ix::make_unique<WebSocketPerMessageDeflate>();
if (!_socket) if (!_socket)
{ {
@ -177,7 +178,7 @@ namespace ix
_blockingSend = true; _blockingSend = true;
_socket = std::move(socket); _socket = std::move(socket);
_perMessageDeflate = std::make_unique<WebSocketPerMessageDeflate>(); _perMessageDeflate = ix::make_unique<WebSocketPerMessageDeflate>();
WebSocketHandshake webSocketHandshake(_requestInitCancellation, WebSocketHandshake webSocketHandshake(_requestInitCancellation,
_socket, _socket,

View File

@ -6,4 +6,4 @@
#pragma once #pragma once
#define IX_WEBSOCKET_VERSION "10.5.6" #define IX_WEBSOCKET_VERSION "11.0.2"

View File

@ -28,7 +28,7 @@ brew:
# server side ?) and I can't work-around it easily, so we're using mbedtls on # server side ?) and I can't work-around it easily, so we're using mbedtls on
# Linux for the SSL backend, which works great. # Linux for the SSL backend, which works great.
ws_mbedtls_install: ws_mbedtls_install:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install) mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_ZLIB=OFF -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
ws: ws:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install) mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
@ -52,7 +52,7 @@ ws_no_ssl:
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4) mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4)
ws_no_python: ws_no_python:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; ninja install) mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j4 install)
uninstall: uninstall:
xargs rm -fv < build/install_manifest.txt xargs rm -fv < build/install_manifest.txt
@ -110,71 +110,30 @@ format:
test_server: test_server:
(cd test && npm i ws && node broadcast-server.js) (cd test && npm i ws && node broadcast-server.js)
# env TEST=Websocket_server make test test:
# env TEST=Websocket_chat make test mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 ..)
# env TEST=heartbeat make test (cd build ; ninja)
build_test: (cd build ; ninja test)
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. ; ninja install)
test: build_test test_asan:
(cd test ; python2.7 run.py -r) mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer")
(cd build ; ninja)
test_make: (cd build ; ctest -V .)
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4)
(cd test ; python2.7 run.py -r)
test_tsan:
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
(cd test ; python2.7 run.py -r)
test_ubsan:
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableUndefinedBehaviorSanitizer YES)
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
(cd test ; python2.7 run.py -r)
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_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableAddressSanitizer YES)
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
test_tsan_openssl:
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
(cd test ; python2.7 run.py -r)
test_ubsan_openssl:
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableUndefinedBehaviorSanitizer YES)
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
(cd test ; python2.7 run.py -r)
test_tsan_openssl_release:
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Release -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -configuration Release -target ixwebsocket_unittest -enableThreadSanitizer YES)
(cd build/test ; ln -sf Release/ixwebsocket_unittest)
(cd test ; python2.7 run.py -r)
test_tsan_mbedtls: test_tsan_mbedtls:
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_MBED_TLS=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES) mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
(cd build/test ; ln -sf Debug/ixwebsocket_unittest) (cd build ; ninja)
(cd test ; python2.7 run.py -r) (cd build ; ninja test)
build_test_openssl: test_tsan_openssl:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_OPEN_SSL=1 -DUSE_TEST=1 .. ; ninja install) mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
(cd build ; ninja)
(cd build ; ninja test)
test_openssl: build_test_openssl test_tsan_sectransport:
(cd test ; python2.7 run.py -r) mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_OPENS_SSL=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer")
(cd build ; ninja)
build_test_mbedtls: (cd build ; ninja test)
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. ; make -j 4)
test_mbedtls: build_test_mbedtls
(cd test ; python2.7 run.py -r)
test_no_ssl:
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TEST=1 .. ; make -j 4)
(cd test ; python2.7 run.py -r)
ws_test: ws ws_test: ws
(cd ws ; env DEBUG=1 PATH=../ws/build:$$PATH bash test_ws.sh) (cd ws ; env DEBUG=1 PATH=../ws/build:$$PATH bash test_ws.sh)

View File

@ -5,63 +5,41 @@
cmake_minimum_required (VERSION 3.14) cmake_minimum_required (VERSION 3.14)
project (ixwebsocket_unittest) project (ixwebsocket_unittest)
set (CMAKE_CXX_STANDARD 14) set (CMAKE_CXX_STANDARD 11)
option(USE_TLS "Add TLS support" ON) option(USE_TLS "Add TLS support" ON)
include_directories(
${PROJECT_SOURCE_DIR}/Catch2/single_include
../third_party
../third_party/msgpack11
../ws
)
add_definitions(-DSPDLOG_COMPILED_LIB=1)
find_package(JsonCpp)
if (NOT JSONCPP_FOUND)
include_directories(../third_party/jsoncpp)
set(JSONCPP_SOURCES ../third_party/jsoncpp/jsoncpp.cpp)
endif()
# Shared sources # Shared sources
set (SOURCES set (TEST_TARGET_NAMES
${JSONCPP_SOURCES} IXSocketTest
IXSocketConnectTest
test_runner.cpp
IXTest.cpp
../third_party/msgpack11/msgpack11.cpp
IXSocketTest.cpp
IXSocketConnectTest.cpp
# IXWebSocketLeakTest.cpp # commented until we have a fix for #224 # IXWebSocketLeakTest.cpp # commented until we have a fix for #224
IXWebSocketServerTest.cpp IXWebSocketServerTest
IXWebSocketTestConnectionDisconnection.cpp IXWebSocketTestConnectionDisconnection
IXUrlParserTest.cpp IXUrlParserTest
IXWebSocketServerTest.cpp IXHttpClientTest
IXHttpClientTest.cpp IXHttpServerTest
IXHttpServerTest.cpp IXUnityBuildsTest
IXUnityBuildsTest.cpp IXHttpTest
IXHttpTest.cpp IXDNSLookupTest
IXDNSLookupTest.cpp IXWebSocketSubProtocolTest
IXWebSocketSubProtocolTest.cpp IXSentryClientTest
IXSentryClientTest.cpp IXWebSocketChatTest
IXWebSocketChatTest.cpp IXWebSocketBroadcastTest
IXWebSocketBroadcastTest.cpp IXWebSocketPerMessageDeflateCompressorTest
IXWebSocketPerMessageDeflateCompressorTest.cpp IXStreamSqlTest
IXStreamSqlTest.cpp
) )
# Some unittest don't work on windows yet # Some unittest don't work on windows yet
# Windows without TLS does not have hmac yet # Windows without TLS does not have hmac yet
if (UNIX) if (UNIX)
list(APPEND SOURCES list(APPEND TEST_TARGET_NAMES
IXWebSocketCloseTest.cpp IXWebSocketCloseTest
IXCobraChatTest.cpp IXCobraChatTest
IXCobraMetricsPublisherTest.cpp IXCobraMetricsPublisherTest
IXCobraToSentryBotTest.cpp IXCobraToSentryBotTest
IXCobraToStatsdBotTest.cpp IXCobraToStatsdBotTest
IXCobraToStdoutBotTest.cpp IXCobraToStdoutBotTest
) )
endif() endif()
@ -71,19 +49,9 @@ endif()
# Disable tests for now that are failing or not reliable # Disable tests for now that are failing or not reliable
add_executable(ixwebsocket_unittest ${SOURCES}) find_package(JsonCpp)
if (NOT JSONCPP_FOUND)
if (MAC) set(JSONCPP_SOURCES ../third_party/jsoncpp/jsoncpp.cpp)
add_sanitizers(ixwebsocket_unittest)
endif()
if (APPLE AND USE_TLS)
target_link_libraries(ixwebsocket_unittest "-framework foundation" "-framework security")
endif()
if (JSONCPP_FOUND)
target_include_directories(ixwebsocket_unittest PUBLIC ${JSONCPP_INCLUDE_DIRS})
target_link_libraries(ixwebsocket_unittest ${JSONCPP_LIBRARIES})
endif() endif()
if (USE_PYTHON) if (USE_PYTHON)
@ -97,19 +65,69 @@ if (USE_PYTHON)
message("Python_LIBRARIES:${Python_LIBRARIES}") message("Python_LIBRARIES:${Python_LIBRARIES}")
endif() endif()
# library with the most dependencies come first add_library(ixwebsocket_test)
target_link_libraries(ixwebsocket_unittest ixbots) target_sources(ixwebsocket_test PRIVATE
target_link_libraries(ixwebsocket_unittest ixsnake) ${JSONCPP_SOURCES}
target_link_libraries(ixwebsocket_unittest ixcobra) test_runner.cpp
target_link_libraries(ixwebsocket_unittest ixsentry) IXTest.cpp
target_link_libraries(ixwebsocket_unittest ixredis) ../third_party/msgpack11/msgpack11.cpp
target_link_libraries(ixwebsocket_unittest ixwebsocket) )
target_link_libraries(ixwebsocket_unittest ixcrypto) target_compile_definitions(ixwebsocket_test PRIVATE ${TEST_PROGRAMS_DEFINITIONS})
target_link_libraries(ixwebsocket_unittest ixcore) target_include_directories(ixwebsocket_test PRIVATE
${PROJECT_SOURCE_DIR}/Catch2/single_include
../third_party
)
target_link_libraries(ixwebsocket_test ixsnake)
target_link_libraries(ixwebsocket_test ixcobra)
target_link_libraries(ixwebsocket_test ixwebsocket)
target_link_libraries(ixwebsocket_test ixcrypto)
target_link_libraries(ixwebsocket_test spdlog)
target_link_libraries(ixwebsocket_unittest spdlog) foreach(TEST_TARGET_NAME ${TEST_TARGET_NAMES})
if (USE_PYTHON) add_executable(${TEST_TARGET_NAME}
target_link_libraries(ixwebsocket_unittest ${Python_LIBRARIES}) ${TEST_TARGET_NAME}.cpp
endif() )
install(TARGETS ixwebsocket_unittest DESTINATION bin) target_include_directories(${TEST_TARGET_NAME} PRIVATE
${PROJECT_SOURCE_DIR}/Catch2/single_include
../third_party
../third_party/msgpack11
)
target_compile_definitions(${TEST_TARGET_NAME} PRIVATE SPDLOG_COMPILED_LIB=1)
if (NOT JSONCPP_FOUND)
target_include_directories(${TEST_TARGET_NAME} PRIVATE ../third_party/jsoncpp)
endif()
if (APPLE AND USE_TLS)
target_link_libraries(${TEST_TARGET_NAME} "-framework foundation" "-framework security")
endif()
# library with the most dependencies come first
target_link_libraries(${TEST_TARGET_NAME} ixwebsocket_test)
target_link_libraries(${TEST_TARGET_NAME} ixbots)
target_link_libraries(${TEST_TARGET_NAME} ixsnake)
target_link_libraries(${TEST_TARGET_NAME} ixcobra)
target_link_libraries(${TEST_TARGET_NAME} ixsentry)
if (JSONCPP_FOUND)
target_include_directories(${TEST_TARGET_NAME} PRIVATE ${JSONCPP_INCLUDE_DIRS})
target_link_libraries(${TEST_TARGET_NAME} ${JSONCPP_LIBRARIES})
endif()
target_link_libraries(${TEST_TARGET_NAME} ixredis)
target_link_libraries(${TEST_TARGET_NAME} ixwebsocket)
target_link_libraries(${TEST_TARGET_NAME} ixcrypto)
target_link_libraries(${TEST_TARGET_NAME} ixcore)
target_link_libraries(${TEST_TARGET_NAME} spdlog)
if (USE_PYTHON)
target_link_libraries(${TEST_TARGET_NAME} ${Python_LIBRARIES})
endif()
add_test(NAME ${TEST_TARGET_NAME}
COMMAND ${TEST_TARGET_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endforeach()

View File

@ -24,6 +24,8 @@ TEST_CASE("dns", "[net]")
res = dnsLookup->resolve(errMsg, [] { return false; }); res = dnsLookup->resolve(errMsg, [] { return false; });
std::cerr << "Error message: " << errMsg << std::endl; std::cerr << "Error message: " << errMsg << std::endl;
REQUIRE(res != nullptr); REQUIRE(res != nullptr);
dnsLookup->release(res);
} }
SECTION("Test resolving a non-existing hostname") SECTION("Test resolving a non-existing hostname")

View File

@ -14,7 +14,7 @@ endif()
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
# set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") # set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
set (CMAKE_CXX_STANDARD 14) set (CMAKE_CXX_STANDARD 11)
option(USE_TLS "Add TLS support" ON) option(USE_TLS "Add TLS support" ON)