Compare commits

...

42 Commits

Author SHA1 Message Date
0d7fb05567 (ixwebsocket) version bump 2021-03-23 21:54:54 -07:00
bf1747ef18 (ixwebsocket) version bump 2021-03-23 21:54:15 -07:00
5c9c05caff bump version 2021-03-23 21:52:49 -07:00
2573ca151b CaseInsensitiveLess::NocaseCompare::operator mingw fix attempt 2021-03-23 21:21:36 -07:00
c5b5fa82be use inet_* wrapper only on mingw 2021-03-23 21:13:18 -07:00
80dff08304 invoke ctest manually on ci for windows + gcc builder 2021-03-23 21:07:26 -07:00
24c2eae3d7 use inet_ntop and inet_pton musl implementations on all platforms 2021-03-23 20:53:19 -07:00
449c5fa138 (ixwebsocket) add getMinWaitBetweenReconnectionRetries 2021-03-23 08:29:50 -07:00
b6234ff908 compile errors due to missing changes for the introduction of setMinWaitBetweenReconnectionRetries and getMinWaitBetweenReconnectionRetries 2021-03-23 08:28:40 -07:00
d26664fccc (ixwebsocket) New option to set the min wait between reconnection attempts. Still default to 1ms. (setMinWaitBetweenReconnectionRetries). 2021-03-23 07:33:48 -07:00
def0243d6d (ws) initialize maxWaitBetweenReconnectionRetries to a non zero value ; a zero value was causing spurious reconnections attempts 2021-03-22 21:10:18 -07:00
1410797d6f document -DBUILD_DEMO=ON 2021-03-22 08:51:58 -07:00
2670187fe0 Adds demo building option. (#278) 2021-03-22 08:47:10 -07:00
95359461d7 enable test on windows + gcc 2021-03-21 10:22:44 -07:00
4d7b149649 mingw: cast fixes 2021-03-21 10:16:06 -07:00
b29a37ce76 mingw: inet_ntop and inet_pton compilation fix, use correct parameter names 2021-03-21 09:50:15 -07:00
9a4dfb40da mingw: add real implementation of inet_ntop and inet_pton taken from musl C library 2021-03-21 09:43:16 -07:00
c4c344518d disable shared-libs on windows where test does not work yet 2021-03-20 10:18:10 -07:00
d706a4a73e doc: document BUILD_SHARED_LIBS 2021-03-20 09:50:21 -07:00
88970604e3 ixwebsocketserver::broadcast server to return a boolean to know whether the server could start/listen, and use that in ws 2021-03-19 11:52:41 -07:00
7fee54464e WebSocketServer::listenAndStart: fix branch where we do not return an integer 2021-03-19 11:48:21 -07:00
1c7634d075 ws: cannot use << with an std::vector 2021-03-19 11:43:29 -07:00
99f9556aa9 ws + mingw: uses << operator to write file to disk in WebSocketReceiver::handleMessage 2021-03-19 11:39:14 -07:00
39b2a3d6df ws curl -O mingw compile fix + detect when we cannot extract a filename from the url to save file to disk with -O option 2021-03-19 11:35:25 -07:00
056b02a494 ws: WebSocketSender uses anonymous namespace load instead of its own method 2021-03-19 11:25:48 -07:00
48166a9a72 mingw: fix compile errors with linenoise and fstream 2021-03-19 11:18:55 -07:00
b36a2d1faa mingw compile fix / remove restrict in inet_* functions 2021-03-19 10:58:38 -07:00
968cc5c1c4 reference wslay as alternative C websocket library 2021-03-19 08:05:01 -07:00
0813eb1788 mention disablePerMessageDeflate in the doc 2021-03-16 09:56:08 -07:00
cadb8336f2 add reference to Teleport which is using ixwebsockets 2021-03-16 09:10:36 -07:00
7fd782f72f add WIN32_LEAN_AND_MEAN windows blip 2021-03-15 19:58:18 -07:00
85bcdaaec3 stub inet_ntop and inet_pton function that mingw does not have 2021-03-14 14:25:40 -07:00
461641f3d0 ci with unity build for windows + gcc 2021-03-14 13:23:16 -07:00
2d65c27d11 rename windows+gcc unittest ci file 2021-03-14 13:18:09 -07:00
6a7785d9d9 no set thread name on mingw 2021-03-13 19:02:20 -08:00
78a670e0c8 more mingw quirks 2021-03-13 18:55:30 -08:00
e63ac69ec6 mock poll struct and macro for mingw 2021-03-13 18:49:29 -08:00
afa15d6dcf mingw build problem fix attempt 2021-03-13 18:31:42 -08:00
432a202c07 use https://github.com/marketplace/actions/install-mingw 2021-03-13 18:21:46 -08:00
d609370a85 change compiler 2021-03-13 18:16:21 -08:00
bbe3a766f4 ci windows_gcc, disable zlib 2021-03-13 18:04:00 -08:00
09d3520b66 Create windows_gcc.yml 2021-03-13 18:00:32 -08:00
29 changed files with 382 additions and 70 deletions

View File

@ -14,7 +14,7 @@ jobs:
- run: |
mkdir build
cd build
cmake -GNinja -DCMAKE_CXX_COMPILER=cl.exe -DCMAKE_C_COMPILER=cl.exe -DUSE_WS=1 -DUSE_TEST=1 -DUSE_ZLIB=0 ..
cmake -GNinja -DCMAKE_CXX_COMPILER=cl.exe -DCMAKE_C_COMPILER=cl.exe -DUSE_WS=1 -DUSE_TEST=1 -DUSE_ZLIB=OFF -DBUILD_SHARED_LIBS=OFF ..
- run: |
cd build
ninja

View File

@ -0,0 +1,27 @@
name: windows_gcc
on:
push:
paths-ignore:
- 'docs/**'
jobs:
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- uses: seanmiddleditch/gha-setup-ninja@master
- uses: egor-tensin/setup-mingw@v2
- run: |
mkdir build
cd build
cmake -GNinja -DCMAKE_CXX_COMPILER=c++ -DCMAKE_C_COMPILER=cc -DUSE_WS=1 -DUSE_TEST=1 -DUSE_ZLIB=0 -DCMAKE_UNITY_BUILD=ON ..
- run: |
cd build
ninja
- run: |
cd build
ctest -V
# ninja test
#- run: ../build/test/ixwebsocket_unittest.exe
# working-directory: test

View File

@ -12,6 +12,8 @@ set (CMAKE_CXX_STANDARD 11)
set (CXX_STANDARD_REQUIRED ON)
set (CMAKE_CXX_EXTENSIONS OFF)
option (BUILD_DEMO OFF)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
@ -111,6 +113,7 @@ set( IXWEBSOCKET_HEADERS
ixwebsocket/IXWebSocketVersion.h
)
option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
option(USE_TLS "Enable TLS support" FALSE)
if (USE_TLS)
@ -144,7 +147,7 @@ if (USE_TLS)
endif()
endif()
add_library( ixwebsocket STATIC
add_library( ixwebsocket
${IXWEBSOCKET_SOURCES}
${IXWEBSOCKET_HEADERS}
)
@ -273,3 +276,8 @@ if (USE_WS OR USE_TEST)
add_subdirectory(test)
endif()
endif()
if (BUILD_DEMO)
add_executable(demo main.cpp)
target_link_libraries(demo ixwebsocket)
endif()

View File

@ -18,6 +18,8 @@ A bad security bug affecting users compiling with SSL enabled and OpenSSL as the
* $ mkdir -p build ; (cd build ; cmake -DUSE_TLS=1 .. ; make -j ; make install)
* $ clang++ --std=c++11 --stdlib=libc++ main.cpp -lixwebsocket -lz -framework Security -framework Foundation
* $ ./a.out
*
* Or use cmake -DBUILD_DEMO=ON option for other platforms
*/
#include <ixwebsocket/IXNetSystem.h>
@ -94,6 +96,7 @@ If your company or project is using this library, feel free to open an issue or
- [gwebsocket](https://github.com/norrbotten/gwebsocket), a websocket (lua) module for Garry's Mod
- [DisCPP](https://github.com/DisCPP/DisCPP), a simple but feature rich Discord API wrapper
- [discord.cpp](https://github.com/luccanunes/discord.cpp), a discord library for making bots
- [Teleport](http://teleportconnect.com/), Teleport is your own personal remote robot avatar
## Alternative libraries
@ -103,6 +106,7 @@ There are plenty of great websocket libraries out there, which might work for yo
* [beast](https://github.com/boostorg/beast) - C++
* [libwebsockets](https://libwebsockets.org/) - C
* [µWebSockets](https://github.com/uNetworking/uWebSockets) - C
* [wslay](https://github.com/tatsuhiro-t/wslay) - C
[uvweb](https://github.com/bsergean/uvweb) is a library written by the IXWebSocket author which is built on top of [uvw](https://github.com/skypjack/uvw), which is a C++ wrapper for [libuv](https://libuv.org/). It has more dependencies and does not support SSL at this point, but it can be used to open multiple connections within a single OS thread thanks to libuv.

View File

@ -2,6 +2,38 @@
All changes to this project will be documented in this file.
## [11.2.2] - 2021-03-23
(ixwebsocket) version bump
## [11.2.1] - 2021-03-23
(ixwebsocket) version bump
## [11.2.0] - 2021-03-23
(ixwebsocket) correct mingw support (gcc on windows)
## [11.1.4] - 2021-03-23
(ixwebsocket) add getMinWaitBetweenReconnectionRetries
## [11.1.3] - 2021-03-23
(ixwebsocket) New option to set the min wait between reconnection attempts. Still default to 1ms. (setMinWaitBetweenReconnectionRetries).
## [11.1.2] - 2021-03-22
(ws) initialize maxWaitBetweenReconnectionRetries to a non zero value ; a zero value was causing spurious reconnections attempts
## [11.1.1] - 2021-03-20
(cmake) Library can be built as a static or a dynamic library, controlled with BUILD_SHARED_LIBS. Default to static library
## [11.1.0] - 2021-03-16
(ixwebsocket) Use LEAN_AND_MEAN Windows define to help with undefined link error when building a DLL. Support websocket server disablePerMessageDeflate option correctly.
## [11.0.9] - 2021-03-07
(ixwebsocket) Expose setHandshakeTimeout method

View File

@ -17,13 +17,13 @@ There is a unittest which can be executed by typing `make test`.
Options for building:
* `-DBUILD_SHARED_LIBS=ON` will build the unittest as a shared libary instead of a static library, which is the default
* `-DUSE_ZLIB=1` will enable zlib support, required for http client + server + websocket per message deflate extension
* `-DUSE_TLS=1` will enable TLS support
* `-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
* `-DUSE_PYTHON=1` will use Python3 for cobra bots, require Python3 to be installed.
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/unittest_windows.yml) which have instructions for building dependencies.

View File

@ -256,11 +256,15 @@ Wait time(ms): 6400
Wait time(ms): 10000
```
The waiting time is capped by default at 10s between 2 attempts, but that value can be changed and queried.
The waiting time is capped by default at 10s between 2 attempts, but that value
can be changed and queried. The minimum waiting time can also be set.
```cpp
webSocket.setMaxWaitBetweenReconnectionRetries(5 * 1000); // 5000ms = 5s
uint32_t m = webSocket.getMaxWaitBetweenReconnectionRetries();
webSocket.setMinWaitBetweenReconnectionRetries(1000); // 1000ms = 1s
uint32_t m = webSocket.getMinWaitBetweenReconnectionRetries();
```
## Handshake timeout
@ -343,6 +347,10 @@ if (!res.first)
return 1;
}
// Per message deflate connection is enabled by default. It can be disabled
// which might be helpful when running on low power devices such as a Rasbery Pi
server.disablePerMessageDeflate();
// Run the server in the background. Server can be stoped by calling server.stop()
server.start();
@ -410,6 +418,10 @@ if (!res.first)
return 1;
}
// Per message deflate connection is enabled by default. It can be disabled
// which might be helpful when running on low power devices such as a Rasbery Pi
server.disablePerMessageDeflate();
// Run the server in the background. Server can be stoped by calling server.stop()
server.start();

View File

@ -24,6 +24,12 @@
#include <string.h>
#include <thread>
// mingw build quirks
#if defined(_WIN32) && defined(__GNUC__)
#define AI_NUMERICSERV NI_NUMERICSERV
#define AI_ADDRCONFIG LUP_ADDRCONFIG
#endif
namespace ix
{
const int64_t DNSLookup::kDefaultWait = 1; // ms

View File

@ -10,16 +10,22 @@
namespace ix
{
uint32_t calculateRetryWaitMilliseconds(uint32_t retry_count,
uint32_t maxWaitBetweenReconnectionRetries)
uint32_t calculateRetryWaitMilliseconds(uint32_t retryCount,
uint32_t maxWaitBetweenReconnectionRetries,
uint32_t minWaitBetweenReconnectionRetries)
{
uint32_t wait_time = (retry_count < 26) ? (std::pow(2, retry_count) * 100) : 0;
uint32_t waitTime = (retryCount < 26) ? (std::pow(2, retryCount) * 100) : 0;
if (wait_time > maxWaitBetweenReconnectionRetries || wait_time == 0)
if (waitTime < minWaitBetweenReconnectionRetries)
{
wait_time = maxWaitBetweenReconnectionRetries;
waitTime = minWaitBetweenReconnectionRetries;
}
return wait_time;
if (waitTime > maxWaitBetweenReconnectionRetries || waitTime == 0)
{
waitTime = maxWaitBetweenReconnectionRetries;
}
return waitTime;
}
} // namespace ix

View File

@ -10,6 +10,7 @@
namespace ix
{
uint32_t calculateRetryWaitMilliseconds(uint32_t retry_count,
uint32_t maxWaitBetweenReconnectionRetries);
uint32_t calculateRetryWaitMilliseconds(uint32_t retryCount,
uint32_t maxWaitBetweenReconnectionRetries,
uint32_t minWaitBetweenReconnectionRetries);
} // namespace ix

View File

@ -124,4 +124,156 @@ namespace ix
#endif
}
//
// mingw does not have inet_ntop, which were taken as is from the musl C library.
//
const char* inet_ntop(int af, const void* a0, char* s, socklen_t l)
{
#if defined(_WIN32) && defined(__GNUC__)
const unsigned char* a = (const unsigned char*) a0;
int i, j, max, best;
char buf[100];
switch (af)
{
case AF_INET:
if (snprintf(s, l, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]) < l) return s;
break;
case AF_INET6:
if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\377\377", 12))
snprintf(buf,
sizeof buf,
"%x:%x:%x:%x:%x:%x:%x:%x",
256 * a[0] + a[1],
256 * a[2] + a[3],
256 * a[4] + a[5],
256 * a[6] + a[7],
256 * a[8] + a[9],
256 * a[10] + a[11],
256 * a[12] + a[13],
256 * a[14] + a[15]);
else
snprintf(buf,
sizeof buf,
"%x:%x:%x:%x:%x:%x:%d.%d.%d.%d",
256 * a[0] + a[1],
256 * a[2] + a[3],
256 * a[4] + a[5],
256 * a[6] + a[7],
256 * a[8] + a[9],
256 * a[10] + a[11],
a[12],
a[13],
a[14],
a[15]);
/* Replace longest /(^0|:)[:0]{2,}/ with "::" */
for (i = best = 0, max = 2; buf[i]; i++)
{
if (i && buf[i] != ':') continue;
j = strspn(buf + i, ":0");
if (j > max) best = i, max = j;
}
if (max > 3)
{
buf[best] = buf[best + 1] = ':';
memmove(buf + best + 2, buf + best + max, i - best - max + 1);
}
if (strlen(buf) < l)
{
strcpy(s, buf);
return s;
}
break;
default: errno = EAFNOSUPPORT; return 0;
}
errno = ENOSPC;
return 0;
#else
return ::inet_ntop(af, a0, s, l);
#endif
}
static int hexval(unsigned c)
{
if (c - '0' < 10) return c - '0';
c |= 32;
if (c - 'a' < 6) return c - 'a' + 10;
return -1;
}
//
// mingw does not have inet_pton, which were taken as is from the musl C library.
//
int inet_pton(int af, const char* s, void* a0)
{
#if defined(_WIN32) && defined(__GNUC__)
uint16_t ip[8];
unsigned char* a = (unsigned char*) a0;
int i, j, v, d, brk = -1, need_v4 = 0;
if (af == AF_INET)
{
for (i = 0; i < 4; i++)
{
for (v = j = 0; j < 3 && isdigit(s[j]); j++)
v = 10 * v + s[j] - '0';
if (j == 0 || (j > 1 && s[0] == '0') || v > 255) return 0;
a[i] = v;
if (s[j] == 0 && i == 3) return 1;
if (s[j] != '.') return 0;
s += j + 1;
}
return 0;
}
else if (af != AF_INET6)
{
errno = EAFNOSUPPORT;
return -1;
}
if (*s == ':' && *++s != ':') return 0;
for (i = 0;; i++)
{
if (s[0] == ':' && brk < 0)
{
brk = i;
ip[i & 7] = 0;
if (!*++s) break;
if (i == 7) return 0;
continue;
}
for (v = j = 0; j < 4 && (d = hexval(s[j])) >= 0; j++)
v = 16 * v + d;
if (j == 0) return 0;
ip[i & 7] = v;
if (!s[j] && (brk >= 0 || i == 7)) break;
if (i == 7) return 0;
if (s[j] != ':')
{
if (s[j] != '.' || (i < 6 && brk < 0)) return 0;
need_v4 = 1;
i++;
break;
}
s += j + 1;
}
if (brk >= 0)
{
memmove(ip + brk + 7 - i, ip + brk, 2 * (i + 1 - brk));
for (j = 0; j < 7 - i; j++)
ip[brk + j] = 0;
}
for (j = 0; j < 8; j++)
{
*a++ = ip[j] >> 8;
*a++ = ip[j];
}
if (need_v4 && inet_pton(AF_INET, (const char*) s, a - 4) <= 0) return 0;
return 1;
#else
return ::inet_pton(af, s, a0);
#endif
}
} // namespace ix

View File

@ -7,6 +7,11 @@
#pragma once
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <WS2tcpip.h>
#include <WinSock2.h>
#include <basetsd.h>
@ -16,6 +21,22 @@
// Define our own poll on Windows, as a wrapper on top of select
typedef unsigned long int nfds_t;
// mingw does not know about poll so mock it
#if defined(__GNUC__)
struct pollfd
{
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
#define POLLIN 0x001 /* There is data to read. */
#define POLLOUT 0x004 /* Writing now will not block. */
#define POLLERR 0x008 /* Error condition. */
#define POLLHUP 0x010 /* Hung up. */
#define POLLNVAL 0x020 /* Invalid polling request. */
#endif
#else
#include <arpa/inet.h>
#include <errno.h>
@ -44,4 +65,7 @@ namespace ix
bool uninitNetSystem();
int poll(struct pollfd* fds, nfds_t nfds, int timeout);
const char* inet_ntop(int af, const void* src, char* dst, socklen_t size);
int inet_pton(int af, const char* src, void* dst);
} // namespace ix

View File

@ -37,6 +37,7 @@ namespace ix
void SetThreadName(DWORD dwThreadID, const char* threadName)
{
#ifndef __GNUC__
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
@ -51,6 +52,7 @@ namespace ix
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
#endif
}
#endif

View File

@ -104,7 +104,7 @@ namespace ix
server.sin_family = _addressFamily;
server.sin_port = htons(_port);
if (inet_pton(_addressFamily, _host.c_str(), &server.sin_addr.s_addr) <= 0)
if (ix::inet_pton(_addressFamily, _host.c_str(), &server.sin_addr.s_addr) <= 0)
{
std::stringstream ss;
ss << "SocketServer::listen() error calling inet_pton "
@ -133,7 +133,7 @@ namespace ix
server.sin6_family = _addressFamily;
server.sin6_port = htons(_port);
if (inet_pton(_addressFamily, _host.c_str(), &server.sin6_addr) <= 0)
if (ix::inet_pton(_addressFamily, _host.c_str(), &server.sin6_addr) <= 0)
{
std::stringstream ss;
ss << "SocketServer::listen() error calling inet_pton "
@ -338,7 +338,7 @@ namespace ix
if (_addressFamily == AF_INET)
{
char remoteIp4[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &client.sin_addr, remoteIp4, INET_ADDRSTRLEN) == nullptr)
if (ix::inet_ntop(AF_INET, &client.sin_addr, remoteIp4, INET_ADDRSTRLEN) == nullptr)
{
int err = Socket::getErrno();
std::stringstream ss;
@ -357,7 +357,8 @@ namespace ix
else // AF_INET6
{
char remoteIp6[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, &client.sin_addr, remoteIp6, INET6_ADDRSTRLEN) == nullptr)
if (ix::inet_ntop(AF_INET6, &client.sin_addr, remoteIp6, INET6_ADDRSTRLEN) ==
nullptr)
{
int err = Socket::getErrno();
std::stringstream ss;

View File

@ -14,7 +14,7 @@ namespace ix
bool CaseInsensitiveLess::NocaseCompare::operator()(const unsigned char& c1,
const unsigned char& c2) const
{
#ifdef _WIN32
#if defined(_WIN32) && !defined(__GNUC__)
return std::tolower(c1, std::locale()) < std::tolower(c2, std::locale());
#else
return std::tolower(c1) < std::tolower(c2);

View File

@ -22,12 +22,14 @@ namespace ix
const int WebSocket::kDefaultPingIntervalSecs(-1);
const bool WebSocket::kDefaultEnablePong(true);
const uint32_t WebSocket::kDefaultMaxWaitBetweenReconnectionRetries(10 * 1000); // 10s
const uint32_t WebSocket::kDefaultMinWaitBetweenReconnectionRetries(1); // 1 ms
WebSocket::WebSocket()
: _onMessageCallback(OnMessageCallback())
, _stop(false)
, _automaticReconnection(true)
, _maxWaitBetweenReconnectionRetries(kDefaultMaxWaitBetweenReconnectionRetries)
, _minWaitBetweenReconnectionRetries(kDefaultMinWaitBetweenReconnectionRetries)
, _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs)
, _enablePong(kDefaultEnablePong)
, _pingIntervalSecs(kDefaultPingIntervalSecs)
@ -136,12 +138,24 @@ namespace ix
_maxWaitBetweenReconnectionRetries = maxWaitBetweenReconnectionRetries;
}
void WebSocket::setMinWaitBetweenReconnectionRetries(uint32_t minWaitBetweenReconnectionRetries)
{
std::lock_guard<std::mutex> lock(_configMutex);
_minWaitBetweenReconnectionRetries = minWaitBetweenReconnectionRetries;
}
uint32_t WebSocket::getMaxWaitBetweenReconnectionRetries() const
{
std::lock_guard<std::mutex> lock(_configMutex);
return _maxWaitBetweenReconnectionRetries;
}
uint32_t WebSocket::getMinWaitBetweenReconnectionRetries() const
{
std::lock_guard<std::mutex> lock(_configMutex);
return _minWaitBetweenReconnectionRetries;
}
void WebSocket::start()
{
if (_thread.joinable()) return; // we've already been started
@ -218,7 +232,9 @@ namespace ix
return status;
}
WebSocketInitResult WebSocket::connectToSocket(std::unique_ptr<Socket> socket, int timeoutSecs)
WebSocketInitResult WebSocket::connectToSocket(std::unique_ptr<Socket> socket,
int timeoutSecs,
bool enablePerMessageDeflate)
{
{
std::lock_guard<std::mutex> lock(_configMutex);
@ -226,7 +242,8 @@ namespace ix
_perMessageDeflateOptions, _socketTLSOptions, _enablePong, _pingIntervalSecs);
}
WebSocketInitResult status = _ws.connectToSocket(std::move(socket), timeoutSecs);
WebSocketInitResult status =
_ws.connectToSocket(std::move(socket), timeoutSecs, enablePerMessageDeflate);
if (!status.success)
{
return status;
@ -308,8 +325,10 @@ namespace ix
if (_automaticReconnection)
{
duration = millis(calculateRetryWaitMilliseconds(
retries++, _maxWaitBetweenReconnectionRetries));
duration =
millis(calculateRetryWaitMilliseconds(retries++,
_maxWaitBetweenReconnectionRetries,
_minWaitBetweenReconnectionRetries));
connectErr.wait_time = duration.count();
connectErr.retries = retries;

View File

@ -101,7 +101,9 @@ namespace ix
void disableAutomaticReconnection();
bool isAutomaticReconnectionEnabled() const;
void setMaxWaitBetweenReconnectionRetries(uint32_t maxWaitBetweenReconnectionRetries);
void setMinWaitBetweenReconnectionRetries(uint32_t minWaitBetweenReconnectionRetries);
uint32_t getMaxWaitBetweenReconnectionRetries() const;
uint32_t getMinWaitBetweenReconnectionRetries() const;
const std::vector<std::string>& getSubProtocols();
private:
@ -115,7 +117,9 @@ namespace ix
static void invokeTrafficTrackerCallback(size_t size, bool incoming);
// Server
WebSocketInitResult connectToSocket(std::unique_ptr<Socket>, int timeoutSecs);
WebSocketInitResult connectToSocket(std::unique_ptr<Socket>,
int timeoutSecs,
bool enablePerMessageDeflate);
WebSocketTransport _ws;
@ -138,7 +142,9 @@ namespace ix
// Automatic reconnection
std::atomic<bool> _automaticReconnection;
static const uint32_t kDefaultMaxWaitBetweenReconnectionRetries;
static const uint32_t kDefaultMinWaitBetweenReconnectionRetries;
uint32_t _maxWaitBetweenReconnectionRetries;
uint32_t _minWaitBetweenReconnectionRetries;
// Make the sleeping in the automatic reconnection cancellable
std::mutex _sleepMutex;

View File

@ -241,7 +241,8 @@ namespace ix
return WebSocketInitResult(true, status, "", headers, path);
}
WebSocketInitResult WebSocketHandshake::serverHandshake(int timeoutSecs)
WebSocketInitResult WebSocketHandshake::serverHandshake(int timeoutSecs,
bool enablePerMessageDeflate)
{
_requestInitCancellation = false;
@ -338,7 +339,7 @@ namespace ix
WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(header);
// If the client has requested that extension,
if (webSocketPerMessageDeflateOptions.enabled())
if (webSocketPerMessageDeflateOptions.enabled() && enablePerMessageDeflate)
{
_enablePerMessageDeflate = true;

View File

@ -35,7 +35,7 @@ namespace ix
int port,
int timeoutSecs);
WebSocketInitResult serverHandshake(int timeoutSecs);
WebSocketInitResult serverHandshake(int timeoutSecs, bool enablePerMessageDeflate);
private:
std::string genRandomString(const int len);

View File

@ -129,7 +129,8 @@ namespace ix
_clients.insert(webSocket);
}
auto status = webSocket->connectToSocket(std::move(socket), _handshakeTimeoutSecs);
auto status = webSocket->connectToSocket(
std::move(socket), _handshakeTimeoutSecs, _enablePerMessageDeflate);
if (status.success)
{
// Process incoming messages and execute callbacks
@ -200,14 +201,15 @@ namespace ix
});
}
int WebSocketServer::listenAndStart()
bool WebSocketServer::listenAndStart()
{
auto res = listen();
if (!res.first)
{
return 1;
return false;
}
start();
return true;
}
} // namespace ix

View File

@ -48,7 +48,7 @@ namespace ix
std::set<std::shared_ptr<WebSocket>> getClients();
void makeBroadcastServer();
int listenAndStart();
bool listenAndStart();
const static int kDefaultHandShakeTimeoutSecs;

View File

@ -169,7 +169,8 @@ namespace ix
// Server
WebSocketInitResult WebSocketTransport::connectToSocket(std::unique_ptr<Socket> socket,
int timeoutSecs)
int timeoutSecs,
bool enablePerMessageDeflate)
{
std::lock_guard<std::mutex> lock(_socketMutex);
@ -186,7 +187,7 @@ namespace ix
_perMessageDeflateOptions,
_enablePerMessageDeflate);
auto result = webSocketHandshake.serverHandshake(timeoutSecs);
auto result = webSocketHandshake.serverHandshake(timeoutSecs, enablePerMessageDeflate);
if (result.success)
{
setReadyState(ReadyState::OPEN);

View File

@ -83,7 +83,9 @@ namespace ix
int timeoutSecs);
// Server
WebSocketInitResult connectToSocket(std::unique_ptr<Socket> socket, int timeoutSecs);
WebSocketInitResult connectToSocket(std::unique_ptr<Socket> socket,
int timeoutSecs,
bool enablePerMessageDeflate);
PollResult poll();
WebSocketSendInfo sendBinary(const std::string& message,

View File

@ -6,4 +6,4 @@
#pragma once
#define IX_WEBSOCKET_VERSION "11.0.9"
#define IX_WEBSOCKET_VERSION "11.2.2"

View File

@ -9,6 +9,8 @@
* $ mkdir -p build ; cd build ; cmake -DUSE_TLS=1 .. ; make -j ; make install
* $ clang++ --std=c++14 --stdlib=libc++ main.cpp -lixwebsocket -lz -framework Security -framework Foundation
* $ ./a.out
*
* Or use cmake -DBUILD_DEMO=ON option for other platform
*/
#include <ixwebsocket/IXNetSystem.h>

View File

@ -113,7 +113,7 @@ test_server:
test:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 ..)
(cd build ; ninja)
(cd build ; ninja test)
(cd build ; ninja -v test)
test_asan:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer")

View File

@ -139,8 +139,9 @@ namespace ix
std::streamoff size = file.tellg();
file.seekg(0, file.beg);
memblock.resize((size_t) size);
file.read((char*) &memblock.front(), static_cast<std::streamsize>(size));
memblock.reserve((size_t) size);
memblock.insert(
memblock.begin(), std::istream_iterator<char>(file), std::istream_iterator<char>());
return memblock;
}

View File

@ -1639,7 +1639,10 @@ bool enableRawMode(int fd) {
/* Init windows console handles only once */
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hOut==INVALID_HANDLE_VALUE) goto fatal;
if (hOut==INVALID_HANDLE_VALUE) {
errno = ENOTTY;
return false;
}
}
DWORD consolemodeOut;

View File

@ -55,16 +55,17 @@ namespace
std::pair<bool, std::vector<uint8_t>> load(const std::string& path)
{
std::vector<uint8_t> memblock;
std::ifstream file(path);
if (!file.is_open()) return std::make_pair(false, memblock);
file.seekg(0, file.end);
std::streamoff size = file.tellg();
file.seekg(0, file.beg);
memblock.resize((size_t) size);
file.read((char*) &memblock.front(), static_cast<std::streamsize>(size));
memblock.reserve((size_t) size);
memblock.insert(
memblock.begin(), std::istream_iterator<char>(file), std::istream_iterator<char>());
return std::make_pair(true, memblock);
}
@ -86,9 +87,9 @@ namespace
std::streamoff size = file.tellg();
file.seekg(0, file.beg);
memblock.resize(size);
file.read((char*) &memblock.front(), static_cast<std::streamsize>(size));
memblock.reserve((size_t) size);
memblock.insert(
memblock.begin(), std::istream_iterator<char>(file), std::istream_iterator<char>());
std::string bytes(memblock.begin(), memblock.end());
return bytes;
@ -905,7 +906,7 @@ namespace ix
// code which display correct results
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr, str, INET_ADDRSTRLEN);
ix::inet_ntop(AF_INET, &addr, str, INET_ADDRSTRLEN);
spdlog::info("host: {} ip: {}", hostname, str);
@ -1424,10 +1425,18 @@ namespace ix
filename = output;
}
spdlog::info("Writing to disk: {}", filename);
std::ofstream out(filename);
out.write((char*) &response->body.front(), response->body.size());
out.close();
if (filename.empty())
{
spdlog::error("Cannot save content to disk: No output file supplied, and not "
"filename could be extracted from the url {}",
url);
}
else
{
spdlog::info("Writing to disk: {}", filename);
std::ofstream out(filename);
out << response->body;
}
}
else
{
@ -1884,7 +1893,8 @@ namespace ix
spdlog::info("ws_receive: Writing to disk: {}", filenameTmp);
std::ofstream out(filenameTmp);
out.write((char*) &content.front(), content.size());
std::string contentAsString(content.begin(), content.end());
out << contentAsString;
out.close();
spdlog::info("ws_receive: Renaming {} to {}", filenameTmp, filename);
@ -2072,23 +2082,6 @@ namespace ix
_condition.wait(lock);
}
std::vector<uint8_t> load(const std::string& path)
{
std::vector<uint8_t> memblock;
std::ifstream file(path);
if (!file.is_open()) return memblock;
file.seekg(0, file.end);
std::streamoff size = file.tellg();
file.seekg(0, file.beg);
memblock.resize((size_t) size);
file.read((char*) &memblock.front(), static_cast<std::streamsize>(size));
return memblock;
}
void WebSocketSender::start()
{
_webSocket.setUrl(_url);
@ -2182,7 +2175,8 @@ namespace ix
std::vector<uint8_t> content;
{
Bench bench("ws_send: load file from disk");
content = load(filename);
auto res = load(filename);
content = res.second;
}
_id = uuid4();
@ -2493,7 +2487,7 @@ int main(int argc, char** argv)
int delayMs = -1;
int count = 1;
int msgCount = 1000 * 1000;
uint32_t maxWaitBetweenReconnectionRetries;
uint32_t maxWaitBetweenReconnectionRetries = 10 * 1000; // 10 seconds
int pingIntervalSecs = 30;
int runCount = 1;
@ -2774,8 +2768,14 @@ int main(int argc, char** argv)
ix::WebSocketServer server(port, hostname);
server.setTLSOptions(tlsOptions);
server.makeBroadcastServer();
server.listenAndStart();
server.wait();
if (!server.listenAndStart())
{
spdlog::error("Error while starting the server");
}
else
{
server.wait();
}
}
else if (app.got_subcommand("send"))
{