Compare commits
17 Commits
bsergean-p
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
9884c325dd | ||
|
c27f5a94bd | ||
|
2d47af89cf | ||
|
c106e6cb24 | ||
|
1d210c0139 | ||
|
dc8807ec9d | ||
|
03e5a6970f | ||
|
38d6da7755 | ||
|
9ef61bf224 | ||
|
93e673da9f | ||
|
92beef8348 | ||
|
755d98d918 | ||
|
98b4828e93 | ||
|
39e085bebc | ||
|
70602c4e6b | ||
|
c5a02f1066 | ||
|
e03c0be8a4 |
2
.github/workflows/unittest_windows_gcc.yml
vendored
2
.github/workflows/unittest_windows_gcc.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: seanmiddleditch/gha-setup-ninja@master
|
||||
- uses: egor-tensin/setup-mingw@v2.2.0
|
||||
- uses: bsergean/setup-mingw@d79ce405bac9edef3a1726ef00554a56f0bafe66
|
||||
- run: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,3 +8,5 @@ ws/.srl
|
||||
ixhttpd
|
||||
makefile
|
||||
a.out
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
|
@ -6,7 +6,7 @@
|
||||
cmake_minimum_required(VERSION 3.4.1...3.17.2)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
|
||||
|
||||
project(ixwebsocket LANGUAGES C CXX VERSION 11.4.4)
|
||||
project(ixwebsocket LANGUAGES C CXX VERSION 11.4.6)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
set (CXX_STANDARD_REQUIRED ON)
|
||||
@ -168,8 +168,7 @@ if(BUILD_SHARED_LIBS)
|
||||
)
|
||||
|
||||
# Set library version
|
||||
set_target_properties(ixwebsocket PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
|
||||
|
||||
set_target_properties(ixwebsocket PROPERTIES VERSION ${PROJECT_VERSION})
|
||||
else()
|
||||
# Static library
|
||||
add_library( ixwebsocket
|
||||
|
@ -1,5 +1,7 @@
|
||||
## Hello world
|
||||
|
||||
(note from the main developer, sadly I don't have too much time to devote to this library anymore, maybe it's time to pass the maintenance to someone else more motivated ?)
|
||||
|
||||
IXWebSocket is a C++ library for WebSocket client and server development. It has minimal dependencies (no boost), is very simple to use and support everything you'll likely need for websocket dev (SSL, deflate compression, compiles on most platforms, etc...). HTTP client and server code is also available, but it hasn't received as much testing.
|
||||
|
||||
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. Two important design goals are simplicity and correctness.
|
||||
@ -108,6 +110,7 @@ If your company or project is using this library, feel free to open an issue or
|
||||
- [Abaddon](https://github.com/uowuo/abaddon), An alternative Discord client made with C++/gtkmm
|
||||
- [NovaCoin](https://github.com/novacoin-project/novacoin), a hybrid scrypt PoW + PoS based cryptocurrency.
|
||||
- [Candy](https://github.com/lanthora/candy), A WebSocket and TUN based VPN for Linux
|
||||
- [ITGmania](https://github.com/itgmania/itgmania), a cross platform Dance Dance Revolution-like emulator.
|
||||
|
||||
## Alternative libraries
|
||||
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
All changes to this project will be documented in this file.
|
||||
|
||||
## [11.4.5] - 2024-06-05
|
||||
|
||||
New changes are documented in the Release page in the GitHub repository.
|
||||
|
||||
## [11.4.4] - 2023-06-05
|
||||
|
||||
## [11.4.3] - 2022-05-13
|
||||
|
@ -445,6 +445,17 @@ server.wait();
|
||||
|
||||
```
|
||||
|
||||
### Heartbeat
|
||||
|
||||
You can configure an optional heartbeat / keep-alive for the WebSocket server. The heartbeat interval can be adjusted or disabled when constructing the `WebSocketServer`. Setting the interval to `-1` disables the heartbeat feature; this is the default setting. The parameter you set will be applied to every `WebSocket` object that the server creates.
|
||||
|
||||
To enable a 45 second heartbeat on a `WebSocketServer`:
|
||||
|
||||
```cpp
|
||||
int pingIntervalSeconds = 45;
|
||||
ix::WebSocketServer server(port, host, backlog, maxConnections, handshakeTimeoutSecs, addressFamily, pingIntervalSeconds);
|
||||
```
|
||||
|
||||
## HTTP client API
|
||||
|
||||
```cpp
|
||||
|
@ -35,6 +35,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef AI_NUMERICSERV
|
||||
#define AI_NUMERICSERV 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace ix
|
||||
{
|
||||
const int64_t DNSLookup::kDefaultWait = 1; // ms
|
||||
|
@ -34,8 +34,12 @@ namespace ix
|
||||
|
||||
SelectInterruptPipe::~SelectInterruptPipe()
|
||||
{
|
||||
::close(_fildes[kPipeReadIndex]);
|
||||
::close(_fildes[kPipeWriteIndex]);
|
||||
if (-1 != _fildes[kPipeReadIndex]) {
|
||||
::close(_fildes[kPipeReadIndex]);
|
||||
}
|
||||
if (-1 != _fildes[kPipeWriteIndex]) {
|
||||
::close(_fildes[kPipeWriteIndex]);
|
||||
}
|
||||
_fildes[kPipeReadIndex] = -1;
|
||||
_fildes[kPipeWriteIndex] = -1;
|
||||
}
|
||||
|
@ -15,6 +15,10 @@
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
// Windows
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
@ -58,7 +62,7 @@ namespace ix
|
||||
|
||||
void setThreadName(const std::string& name)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
|
||||
//
|
||||
// Apple reserves 16 bytes for its thread names
|
||||
// Notice that the Apple version of pthread_setname_np
|
||||
|
@ -13,6 +13,10 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <basetsd.h>
|
||||
#ifdef _MSC_VER
|
||||
|
@ -47,6 +47,13 @@ namespace ix
|
||||
mbedtls_x509_crt_init(&_cacert);
|
||||
mbedtls_x509_crt_init(&_cert);
|
||||
mbedtls_pk_init(&_pkey);
|
||||
// Initialize the PSA Crypto API if required by the version of Mbed TLS (3.6.0).
|
||||
// This allows the X.509/TLS libraries to use PSA for crypto operations.
|
||||
// See: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/use-psa-crypto.md
|
||||
if (MBEDTLS_VERSION_MAJOR >= 3 && MBEDTLS_VERSION_MINOR >= 6 && MBEDTLS_VERSION_PATCH >= 0)
|
||||
{
|
||||
psa_crypto_init();
|
||||
}
|
||||
}
|
||||
|
||||
bool SocketMbedTLS::loadSystemCertificates(std::string& errorMsg)
|
||||
@ -352,6 +359,11 @@ namespace ix
|
||||
return res;
|
||||
}
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
errno = ECONNRESET;
|
||||
}
|
||||
|
||||
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
{
|
||||
errno = EWOULDBLOCK;
|
||||
|
@ -180,7 +180,7 @@ namespace
|
||||
bHasUserName = true;
|
||||
break;
|
||||
}
|
||||
else if (*LocalString == '/')
|
||||
else if (*LocalString == '/' || *LocalString == '?')
|
||||
{
|
||||
// end of <host>:<port> specification
|
||||
bHasUserName = false;
|
||||
@ -242,7 +242,7 @@ namespace
|
||||
LocalString++;
|
||||
break;
|
||||
}
|
||||
else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/'))
|
||||
else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/' || *LocalString == '?'))
|
||||
{
|
||||
// port number is specified
|
||||
break;
|
||||
@ -280,12 +280,14 @@ namespace
|
||||
}
|
||||
|
||||
// skip '/'
|
||||
if (*CurrentString != '/')
|
||||
if (*CurrentString != '/' && *CurrentString != '?')
|
||||
{
|
||||
return clParseURL(LUrlParserError_NoSlash);
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
if (*CurrentString != '?') {
|
||||
CurrentString++;
|
||||
}
|
||||
|
||||
// parse the path
|
||||
LocalString = CurrentString;
|
||||
|
@ -209,7 +209,7 @@ namespace ix
|
||||
|
||||
WebSocketHttpHeaders headers(_extraHeaders);
|
||||
std::string subProtocolsHeader;
|
||||
auto subProtocols = getSubProtocols();
|
||||
const auto &subProtocols = getSubProtocols();
|
||||
if (!subProtocols.empty())
|
||||
{
|
||||
//
|
||||
@ -219,7 +219,7 @@ namespace ix
|
||||
// 'json,msgpack'
|
||||
//
|
||||
int i = 0;
|
||||
for (auto subProtocol : subProtocols)
|
||||
for (const auto & subProtocol : subProtocols)
|
||||
{
|
||||
if (i++ != 0)
|
||||
{
|
||||
|
@ -19,17 +19,20 @@ namespace ix
|
||||
{
|
||||
const int WebSocketServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds
|
||||
const bool WebSocketServer::kDefaultEnablePong(true);
|
||||
const int WebSocketServer::kPingIntervalSeconds(-1); // disable heartbeat
|
||||
|
||||
WebSocketServer::WebSocketServer(int port,
|
||||
const std::string& host,
|
||||
int backlog,
|
||||
size_t maxConnections,
|
||||
int handshakeTimeoutSecs,
|
||||
int addressFamily)
|
||||
int addressFamily,
|
||||
int pingIntervalSeconds)
|
||||
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
||||
, _handshakeTimeoutSecs(handshakeTimeoutSecs)
|
||||
, _enablePong(kDefaultEnablePong)
|
||||
, _enablePerMessageDeflate(true)
|
||||
, _pingIntervalSeconds(pingIntervalSeconds)
|
||||
{
|
||||
}
|
||||
|
||||
@ -93,6 +96,7 @@ namespace ix
|
||||
auto webSocket = std::make_shared<WebSocket>();
|
||||
|
||||
webSocket->setAutoThreadName(false);
|
||||
webSocket->setPingInterval(_pingIntervalSeconds);
|
||||
|
||||
if (_onConnectionCallback)
|
||||
{
|
||||
|
@ -33,7 +33,8 @@ namespace ix
|
||||
int backlog = SocketServer::kDefaultTcpBacklog,
|
||||
size_t maxConnections = SocketServer::kDefaultMaxConnections,
|
||||
int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs,
|
||||
int addressFamily = SocketServer::kDefaultAddressFamily);
|
||||
int addressFamily = SocketServer::kDefaultAddressFamily,
|
||||
int pingIntervalSeconds = WebSocketServer::kPingIntervalSeconds);
|
||||
virtual ~WebSocketServer();
|
||||
virtual void stop() final;
|
||||
|
||||
@ -61,6 +62,7 @@ namespace ix
|
||||
int _handshakeTimeoutSecs;
|
||||
bool _enablePong;
|
||||
bool _enablePerMessageDeflate;
|
||||
int _pingIntervalSeconds;
|
||||
|
||||
OnConnectionCallback _onConnectionCallback;
|
||||
OnClientMessageCallback _onClientMessageCallback;
|
||||
@ -69,6 +71,7 @@ namespace ix
|
||||
std::set<std::shared_ptr<WebSocket>> _clients;
|
||||
|
||||
const static bool kDefaultEnablePong;
|
||||
const static int kPingIntervalSeconds;
|
||||
|
||||
// Methods
|
||||
virtual void handleConnection(std::unique_ptr<Socket> socket,
|
||||
|
@ -6,4 +6,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IX_WEBSOCKET_VERSION "11.4.4"
|
||||
#define IX_WEBSOCKET_VERSION "11.4.6"
|
||||
|
14
makefile.dev
14
makefile.dev
@ -27,9 +27,9 @@ install: brew
|
||||
#
|
||||
brew:
|
||||
ifeq ($(shell uname),Darwin)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_PREFIX=/opt/homebrew -DCMAKE_UNITY_BUILD=OFF -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_PREFIX=/opt/homebrew -DCMAKE_UNITY_BUILD=OFF -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja)
|
||||
else
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=OFF -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=OFF -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja)
|
||||
endif
|
||||
|
||||
# Docker default target. We've had problems with OpenSSL and TLS 1.3 (on the
|
||||
@ -39,10 +39,10 @@ ws_mbedtls_install:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_ZLIB=OFF -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
|
||||
|
||||
ws:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja)
|
||||
|
||||
ws_unity:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. && ninja)
|
||||
|
||||
ws_install:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. -DUSE_TEST=0 && ninja install)
|
||||
@ -54,13 +54,13 @@ ws_openssl_install:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; ninja install)
|
||||
|
||||
ws_mbedtls:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja)
|
||||
|
||||
ws_no_ssl:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; ninja)
|
||||
|
||||
ws_no_python:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j4 install)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; ninja install)
|
||||
|
||||
uninstall:
|
||||
xargs rm -fv < build/install_manifest.txt
|
||||
|
@ -84,6 +84,40 @@ namespace ix
|
||||
REQUIRE(port == 443); // default port for wss
|
||||
}
|
||||
|
||||
SECTION("wss://google.com/?arg=value")
|
||||
{
|
||||
std::string url = "wss://google.com/?arg=value&arg2=value2";
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool res;
|
||||
|
||||
res = UrlParser::parse(url, protocol, host, path, query, port);
|
||||
|
||||
REQUIRE(res);
|
||||
REQUIRE(protocol == "wss");
|
||||
REQUIRE(host == "google.com");
|
||||
REQUIRE(path == "/?arg=value&arg2=value2");
|
||||
REQUIRE(query == "arg=value&arg2=value2");
|
||||
REQUIRE(port == 443); // default port for wss
|
||||
}
|
||||
|
||||
SECTION("wss://google.com?arg=value")
|
||||
{
|
||||
std::string url = "wss://google.com?arg=value&arg2=value2";
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool res;
|
||||
|
||||
res = UrlParser::parse(url, protocol, host, path, query, port);
|
||||
|
||||
REQUIRE(res);
|
||||
REQUIRE(protocol == "wss");
|
||||
REQUIRE(host == "google.com");
|
||||
REQUIRE(path == "/?arg=value&arg2=value2");
|
||||
REQUIRE(query == "arg=value&arg2=value2");
|
||||
REQUIRE(port == 443); // default port for wss
|
||||
}
|
||||
|
||||
SECTION("real test")
|
||||
{
|
||||
std::string url =
|
||||
|
Loading…
Reference in New Issue
Block a user