Compare commits
16 Commits
v11.4.5
...
feature/su
Author | SHA1 | Date | |
---|---|---|---|
a2cbfcebec | |||
|
9884c325dd | ||
|
c27f5a94bd | ||
|
2d47af89cf | ||
|
c106e6cb24 | ||
|
1d210c0139 | ||
|
dc8807ec9d | ||
|
03e5a6970f | ||
|
38d6da7755 | ||
|
9ef61bf224 | ||
|
93e673da9f | ||
|
92beef8348 | ||
|
755d98d918 | ||
|
98b4828e93 | ||
|
39e085bebc | ||
|
70602c4e6b |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ ws/.srl
|
|||||||
ixhttpd
|
ixhttpd
|
||||||
makefile
|
makefile
|
||||||
a.out
|
a.out
|
||||||
|
.idea/
|
||||||
|
cmake-build-debug/
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.4.1...3.17.2)
|
cmake_minimum_required(VERSION 3.4.1...3.17.2)
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
|
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 (CMAKE_CXX_STANDARD 11)
|
||||||
set (CXX_STANDARD_REQUIRED ON)
|
set (CXX_STANDARD_REQUIRED ON)
|
||||||
@@ -168,8 +168,7 @@ if(BUILD_SHARED_LIBS)
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Set library version
|
# Set library version
|
||||||
set_target_properties(ixwebsocket PROPERTIES VERSION ${CMAKE_PROJECT_VERSION})
|
set_target_properties(ixwebsocket PROPERTIES VERSION ${PROJECT_VERSION})
|
||||||
|
|
||||||
else()
|
else()
|
||||||
# Static library
|
# Static library
|
||||||
add_library( ixwebsocket
|
add_library( ixwebsocket
|
||||||
|
@@ -110,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
|
- [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.
|
- [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
|
- [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
|
## Alternative libraries
|
||||||
|
|
||||||
|
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
All changes to this project will be documented in this file.
|
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.4] - 2023-06-05
|
||||||
|
|
||||||
## [11.4.3] - 2022-05-13
|
## [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
|
## HTTP client API
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
@@ -35,6 +35,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#ifndef AI_NUMERICSERV
|
||||||
|
#define AI_NUMERICSERV 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
const int64_t DNSLookup::kDefaultWait = 1; // ms
|
const int64_t DNSLookup::kDefaultWait = 1; // ms
|
||||||
|
@@ -34,8 +34,12 @@ namespace ix
|
|||||||
|
|
||||||
SelectInterruptPipe::~SelectInterruptPipe()
|
SelectInterruptPipe::~SelectInterruptPipe()
|
||||||
{
|
{
|
||||||
::close(_fildes[kPipeReadIndex]);
|
if (-1 != _fildes[kPipeReadIndex]) {
|
||||||
::close(_fildes[kPipeWriteIndex]);
|
::close(_fildes[kPipeReadIndex]);
|
||||||
|
}
|
||||||
|
if (-1 != _fildes[kPipeWriteIndex]) {
|
||||||
|
::close(_fildes[kPipeWriteIndex]);
|
||||||
|
}
|
||||||
_fildes[kPipeReadIndex] = -1;
|
_fildes[kPipeReadIndex] = -1;
|
||||||
_fildes[kPipeWriteIndex] = -1;
|
_fildes[kPipeWriteIndex] = -1;
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,10 @@
|
|||||||
#include <pthread_np.h>
|
#include <pthread_np.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Windows
|
// Windows
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -58,7 +62,7 @@ namespace ix
|
|||||||
|
|
||||||
void setThreadName(const std::string& name)
|
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
|
// Apple reserves 16 bytes for its thread names
|
||||||
// Notice that the Apple version of pthread_setname_np
|
// Notice that the Apple version of pthread_setname_np
|
||||||
|
@@ -13,6 +13,10 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <basetsd.h>
|
#include <basetsd.h>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@@ -47,6 +47,13 @@ namespace ix
|
|||||||
mbedtls_x509_crt_init(&_cacert);
|
mbedtls_x509_crt_init(&_cacert);
|
||||||
mbedtls_x509_crt_init(&_cert);
|
mbedtls_x509_crt_init(&_cert);
|
||||||
mbedtls_pk_init(&_pkey);
|
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)
|
bool SocketMbedTLS::loadSystemCertificates(std::string& errorMsg)
|
||||||
@@ -352,6 +359,11 @@ namespace ix
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
errno = ECONNRESET;
|
||||||
|
}
|
||||||
|
|
||||||
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE)
|
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||||
{
|
{
|
||||||
errno = EWOULDBLOCK;
|
errno = EWOULDBLOCK;
|
||||||
|
@@ -180,7 +180,7 @@ namespace
|
|||||||
bHasUserName = true;
|
bHasUserName = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (*LocalString == '/')
|
else if (*LocalString == '/' || *LocalString == '?')
|
||||||
{
|
{
|
||||||
// end of <host>:<port> specification
|
// end of <host>:<port> specification
|
||||||
bHasUserName = false;
|
bHasUserName = false;
|
||||||
@@ -242,7 +242,7 @@ namespace
|
|||||||
LocalString++;
|
LocalString++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/'))
|
else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/' || *LocalString == '?'))
|
||||||
{
|
{
|
||||||
// port number is specified
|
// port number is specified
|
||||||
break;
|
break;
|
||||||
@@ -280,12 +280,14 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// skip '/'
|
// skip '/'
|
||||||
if (*CurrentString != '/')
|
if (*CurrentString != '/' && *CurrentString != '?')
|
||||||
{
|
{
|
||||||
return clParseURL(LUrlParserError_NoSlash);
|
return clParseURL(LUrlParserError_NoSlash);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentString++;
|
if (*CurrentString != '?') {
|
||||||
|
CurrentString++;
|
||||||
|
}
|
||||||
|
|
||||||
// parse the path
|
// parse the path
|
||||||
LocalString = CurrentString;
|
LocalString = CurrentString;
|
||||||
|
@@ -209,7 +209,7 @@ namespace ix
|
|||||||
|
|
||||||
WebSocketHttpHeaders headers(_extraHeaders);
|
WebSocketHttpHeaders headers(_extraHeaders);
|
||||||
std::string subProtocolsHeader;
|
std::string subProtocolsHeader;
|
||||||
auto subProtocols = getSubProtocols();
|
const auto &subProtocols = getSubProtocols();
|
||||||
if (!subProtocols.empty())
|
if (!subProtocols.empty())
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -219,7 +219,7 @@ namespace ix
|
|||||||
// 'json,msgpack'
|
// 'json,msgpack'
|
||||||
//
|
//
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto subProtocol : subProtocols)
|
for (const auto & subProtocol : subProtocols)
|
||||||
{
|
{
|
||||||
if (i++ != 0)
|
if (i++ != 0)
|
||||||
{
|
{
|
||||||
@@ -265,7 +265,8 @@ namespace ix
|
|||||||
}
|
}
|
||||||
|
|
||||||
WebSocketInitResult status =
|
WebSocketInitResult status =
|
||||||
_ws.connectToSocket(std::move(socket), timeoutSecs, enablePerMessageDeflate, request);
|
_ws.connectToSocket(
|
||||||
|
std::move(socket), timeoutSecs, enablePerMessageDeflate, getSubProtocols(), request);
|
||||||
if (!status.success)
|
if (!status.success)
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
|
@@ -246,8 +246,30 @@ namespace ix
|
|||||||
return WebSocketInitResult(true, status, "", headers, path);
|
return WebSocketInitResult(true, status, "", headers, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocketHandshake::getSelectedSubProtocol(const std::vector<std::string>& subProtocols,
|
||||||
|
std::string& selectedSubProtocol,
|
||||||
|
const std::string& headerSubProtocol)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << headerSubProtocol;
|
||||||
|
std::string protocol;
|
||||||
|
while (std::getline(ss, protocol, ','))
|
||||||
|
{
|
||||||
|
bool subProtocolFound = false;
|
||||||
|
for (const auto& supportedSubProtocol : subProtocols)
|
||||||
|
{
|
||||||
|
if (protocol != supportedSubProtocol) continue;
|
||||||
|
selectedSubProtocol = protocol;
|
||||||
|
subProtocolFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (subProtocolFound) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WebSocketInitResult WebSocketHandshake::serverHandshake(int timeoutSecs,
|
WebSocketInitResult WebSocketHandshake::serverHandshake(int timeoutSecs,
|
||||||
bool enablePerMessageDeflate,
|
bool enablePerMessageDeflate,
|
||||||
|
const std::vector<std::string>& subProtocols,
|
||||||
HttpRequestPtr request)
|
HttpRequestPtr request)
|
||||||
{
|
{
|
||||||
_requestInitCancellation = false;
|
_requestInitCancellation = false;
|
||||||
@@ -362,6 +384,17 @@ namespace ix
|
|||||||
ss << "Connection: Upgrade\r\n";
|
ss << "Connection: Upgrade\r\n";
|
||||||
ss << "Server: " << userAgent() << "\r\n";
|
ss << "Server: " << userAgent() << "\r\n";
|
||||||
|
|
||||||
|
if(!subProtocols.empty())
|
||||||
|
{
|
||||||
|
std::string headerSubProtocol = headers["sec-websocket-protocol"];
|
||||||
|
std::string selectedSubProtocol;
|
||||||
|
getSelectedSubProtocol(subProtocols, selectedSubProtocol, headerSubProtocol);
|
||||||
|
if(!selectedSubProtocol.empty())
|
||||||
|
{
|
||||||
|
ss << "Sec-WebSocket-Protocol: " << selectedSubProtocol << "\r\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the client headers. Does it support deflate ?
|
// Parse the client headers. Does it support deflate ?
|
||||||
std::string header = headers["sec-websocket-extensions"];
|
std::string header = headers["sec-websocket-extensions"];
|
||||||
WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(header);
|
WebSocketPerMessageDeflateOptions webSocketPerMessageDeflateOptions(header);
|
||||||
|
@@ -39,6 +39,7 @@ namespace ix
|
|||||||
|
|
||||||
WebSocketInitResult serverHandshake(int timeoutSecs,
|
WebSocketInitResult serverHandshake(int timeoutSecs,
|
||||||
bool enablePerMessageDeflate,
|
bool enablePerMessageDeflate,
|
||||||
|
const std::vector<std::string>& subProtocols,
|
||||||
HttpRequestPtr request = nullptr);
|
HttpRequestPtr request = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -49,6 +50,10 @@ namespace ix
|
|||||||
|
|
||||||
bool insensitiveStringCompare(const std::string& a, const std::string& b);
|
bool insensitiveStringCompare(const std::string& a, const std::string& b);
|
||||||
|
|
||||||
|
static void getSelectedSubProtocol(const std::vector<std::string>& subProtocols,
|
||||||
|
std::string& selectedSubProtocol,
|
||||||
|
const std::string& headerSubProtocol);
|
||||||
|
|
||||||
std::atomic<bool>& _requestInitCancellation;
|
std::atomic<bool>& _requestInitCancellation;
|
||||||
std::unique_ptr<Socket>& _socket;
|
std::unique_ptr<Socket>& _socket;
|
||||||
WebSocketPerMessageDeflatePtr& _perMessageDeflate;
|
WebSocketPerMessageDeflatePtr& _perMessageDeflate;
|
||||||
|
@@ -19,17 +19,20 @@ namespace ix
|
|||||||
{
|
{
|
||||||
const int WebSocketServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds
|
const int WebSocketServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds
|
||||||
const bool WebSocketServer::kDefaultEnablePong(true);
|
const bool WebSocketServer::kDefaultEnablePong(true);
|
||||||
|
const int WebSocketServer::kPingIntervalSeconds(-1); // disable heartbeat
|
||||||
|
|
||||||
WebSocketServer::WebSocketServer(int port,
|
WebSocketServer::WebSocketServer(int port,
|
||||||
const std::string& host,
|
const std::string& host,
|
||||||
int backlog,
|
int backlog,
|
||||||
size_t maxConnections,
|
size_t maxConnections,
|
||||||
int handshakeTimeoutSecs,
|
int handshakeTimeoutSecs,
|
||||||
int addressFamily)
|
int addressFamily,
|
||||||
|
int pingIntervalSeconds)
|
||||||
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
: SocketServer(port, host, backlog, maxConnections, addressFamily)
|
||||||
, _handshakeTimeoutSecs(handshakeTimeoutSecs)
|
, _handshakeTimeoutSecs(handshakeTimeoutSecs)
|
||||||
, _enablePong(kDefaultEnablePong)
|
, _enablePong(kDefaultEnablePong)
|
||||||
, _enablePerMessageDeflate(true)
|
, _enablePerMessageDeflate(true)
|
||||||
|
, _pingIntervalSeconds(pingIntervalSeconds)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +79,16 @@ namespace ix
|
|||||||
_onClientMessageCallback = callback;
|
_onClientMessageCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::addSubProtocol(const std::string& subProtocol)
|
||||||
|
{
|
||||||
|
_subProtocols.push_back(subProtocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string>& WebSocketServer::getSubProtocols()
|
||||||
|
{
|
||||||
|
return _subProtocols;
|
||||||
|
}
|
||||||
|
|
||||||
void WebSocketServer::handleConnection(std::unique_ptr<Socket> socket,
|
void WebSocketServer::handleConnection(std::unique_ptr<Socket> socket,
|
||||||
std::shared_ptr<ConnectionState> connectionState)
|
std::shared_ptr<ConnectionState> connectionState)
|
||||||
{
|
{
|
||||||
@@ -93,6 +106,12 @@ namespace ix
|
|||||||
auto webSocket = std::make_shared<WebSocket>();
|
auto webSocket = std::make_shared<WebSocket>();
|
||||||
|
|
||||||
webSocket->setAutoThreadName(false);
|
webSocket->setAutoThreadName(false);
|
||||||
|
webSocket->setPingInterval(_pingIntervalSeconds);
|
||||||
|
if(!_subProtocols.empty())
|
||||||
|
{
|
||||||
|
for(const auto& subProtocol : _subProtocols)
|
||||||
|
webSocket->addSubProtocol(subProtocol);
|
||||||
|
}
|
||||||
|
|
||||||
if (_onConnectionCallback)
|
if (_onConnectionCallback)
|
||||||
{
|
{
|
||||||
|
@@ -33,7 +33,8 @@ namespace ix
|
|||||||
int backlog = SocketServer::kDefaultTcpBacklog,
|
int backlog = SocketServer::kDefaultTcpBacklog,
|
||||||
size_t maxConnections = SocketServer::kDefaultMaxConnections,
|
size_t maxConnections = SocketServer::kDefaultMaxConnections,
|
||||||
int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs,
|
int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs,
|
||||||
int addressFamily = SocketServer::kDefaultAddressFamily);
|
int addressFamily = SocketServer::kDefaultAddressFamily,
|
||||||
|
int pingIntervalSeconds = WebSocketServer::kPingIntervalSeconds);
|
||||||
virtual ~WebSocketServer();
|
virtual ~WebSocketServer();
|
||||||
virtual void stop() final;
|
virtual void stop() final;
|
||||||
|
|
||||||
@@ -44,6 +45,9 @@ namespace ix
|
|||||||
void setOnConnectionCallback(const OnConnectionCallback& callback);
|
void setOnConnectionCallback(const OnConnectionCallback& callback);
|
||||||
void setOnClientMessageCallback(const OnClientMessageCallback& callback);
|
void setOnClientMessageCallback(const OnClientMessageCallback& callback);
|
||||||
|
|
||||||
|
void addSubProtocol(const std::string& subProtocol);
|
||||||
|
const std::vector<std::string>& getSubProtocols();
|
||||||
|
|
||||||
// Get all the connected clients
|
// Get all the connected clients
|
||||||
std::set<std::shared_ptr<WebSocket>> getClients();
|
std::set<std::shared_ptr<WebSocket>> getClients();
|
||||||
|
|
||||||
@@ -61,6 +65,8 @@ namespace ix
|
|||||||
int _handshakeTimeoutSecs;
|
int _handshakeTimeoutSecs;
|
||||||
bool _enablePong;
|
bool _enablePong;
|
||||||
bool _enablePerMessageDeflate;
|
bool _enablePerMessageDeflate;
|
||||||
|
int _pingIntervalSeconds;
|
||||||
|
std::vector<std::string> _subProtocols;
|
||||||
|
|
||||||
OnConnectionCallback _onConnectionCallback;
|
OnConnectionCallback _onConnectionCallback;
|
||||||
OnClientMessageCallback _onClientMessageCallback;
|
OnClientMessageCallback _onClientMessageCallback;
|
||||||
@@ -69,6 +75,7 @@ namespace ix
|
|||||||
std::set<std::shared_ptr<WebSocket>> _clients;
|
std::set<std::shared_ptr<WebSocket>> _clients;
|
||||||
|
|
||||||
const static bool kDefaultEnablePong;
|
const static bool kDefaultEnablePong;
|
||||||
|
const static int kPingIntervalSeconds;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
virtual void handleConnection(std::unique_ptr<Socket> socket,
|
virtual void handleConnection(std::unique_ptr<Socket> socket,
|
||||||
|
@@ -172,6 +172,7 @@ namespace ix
|
|||||||
WebSocketInitResult WebSocketTransport::connectToSocket(std::unique_ptr<Socket> socket,
|
WebSocketInitResult WebSocketTransport::connectToSocket(std::unique_ptr<Socket> socket,
|
||||||
int timeoutSecs,
|
int timeoutSecs,
|
||||||
bool enablePerMessageDeflate,
|
bool enablePerMessageDeflate,
|
||||||
|
const std::vector<std::string>& subProtocols,
|
||||||
HttpRequestPtr request)
|
HttpRequestPtr request)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_socketMutex);
|
std::lock_guard<std::mutex> lock(_socketMutex);
|
||||||
@@ -190,7 +191,7 @@ namespace ix
|
|||||||
_enablePerMessageDeflate);
|
_enablePerMessageDeflate);
|
||||||
|
|
||||||
auto result =
|
auto result =
|
||||||
webSocketHandshake.serverHandshake(timeoutSecs, enablePerMessageDeflate, request);
|
webSocketHandshake.serverHandshake(timeoutSecs, enablePerMessageDeflate, subProtocols, request);
|
||||||
if (result.success)
|
if (result.success)
|
||||||
{
|
{
|
||||||
setReadyState(ReadyState::OPEN);
|
setReadyState(ReadyState::OPEN);
|
||||||
|
@@ -88,6 +88,7 @@ namespace ix
|
|||||||
WebSocketInitResult connectToSocket(std::unique_ptr<Socket> socket,
|
WebSocketInitResult connectToSocket(std::unique_ptr<Socket> socket,
|
||||||
int timeoutSecs,
|
int timeoutSecs,
|
||||||
bool enablePerMessageDeflate,
|
bool enablePerMessageDeflate,
|
||||||
|
const std::vector<std::string>& subProtocols,
|
||||||
HttpRequestPtr request = nullptr);
|
HttpRequestPtr request = nullptr);
|
||||||
|
|
||||||
PollResult poll();
|
PollResult poll();
|
||||||
|
@@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#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:
|
brew:
|
||||||
ifeq ($(shell uname),Darwin)
|
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
|
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
|
endif
|
||||||
|
|
||||||
# Docker default target. We've had problems with OpenSSL and TLS 1.3 (on the
|
# 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)
|
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:
|
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:
|
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:
|
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)
|
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)
|
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:
|
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:
|
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:
|
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:
|
uninstall:
|
||||||
xargs rm -fv < build/install_manifest.txt
|
xargs rm -fv < build/install_manifest.txt
|
||||||
|
@@ -84,6 +84,40 @@ namespace ix
|
|||||||
REQUIRE(port == 443); // default port for wss
|
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")
|
SECTION("real test")
|
||||||
{
|
{
|
||||||
std::string url =
|
std::string url =
|
||||||
|
Reference in New Issue
Block a user