Compare commits

...

16 Commits

Author SHA1 Message Date
2149ac7ed6 (Windows) move EINVAL (re)definition from IXSocket.h to IXNetSystem.h (fix #289) 2021-05-18 11:18:40 -07:00
0f21a20fe3 Move errno windows definitions to IXNetSystem.h 2021-05-17 19:04:02 -07:00
54db6ec8bb add notes about ssl configuration in demo program 2021-05-09 13:45:01 -07:00
0e0a748037 Remove warnings (#284) 2021-04-19 09:25:06 -07:00
3b19b0eeca http client: DEL is not a verb, but DELETE is, fix #281 2021-04-04 23:27:28 -07:00
dbfe3104e8 Fixed example code for the new API of IXWebSocketServer (#279) 2021-03-26 23:55:34 -07:00
68fd8c20d6 change CI mkdocs invocation 2021-03-25 11:12:59 -07:00
d932af8568 (cmake) install IXUniquePtr.h 2021-03-25 10:55:59 -07:00
3add6d4c2e (ssl + windows) missing include for CertOpenStore function 2021-03-24 08:03:56 -07:00
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
21 changed files with 238 additions and 170 deletions

View File

@ -21,5 +21,7 @@ jobs:
pip install pygments pip install pygments
- name: Build doc - name: Build doc
run: | run: |
git clean -dfx .
git fetch
git pull git pull
mkdocs gh-deploy mkdocs gh-deploy

View File

@ -20,7 +20,8 @@ jobs:
ninja ninja
- run: | - run: |
cd build cd build
ninja test ctest -V
# ninja test
#- run: ../build/test/ixwebsocket_unittest.exe #- run: ../build/test/ixwebsocket_unittest.exe
# working-directory: test # working-directory: test

View File

@ -88,6 +88,7 @@ set( IXWEBSOCKET_HEADERS
ixwebsocket/IXSocketTLSOptions.h ixwebsocket/IXSocketTLSOptions.h
ixwebsocket/IXStrCaseCompare.h ixwebsocket/IXStrCaseCompare.h
ixwebsocket/IXUdpSocket.h ixwebsocket/IXUdpSocket.h
ixwebsocket/IXUniquePtr.h
ixwebsocket/IXUrlParser.h ixwebsocket/IXUrlParser.h
ixwebsocket/IXUuid.h ixwebsocket/IXUuid.h
ixwebsocket/IXUtf8Validator.h ixwebsocket/IXUtf8Validator.h

View File

@ -24,6 +24,7 @@ A bad security bug affecting users compiling with SSL enabled and OpenSSL as the
#include <ixwebsocket/IXNetSystem.h> #include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXUserAgent.h>
#include <iostream> #include <iostream>
int main() int main()
@ -34,6 +35,8 @@ int main()
// Our websocket object // Our websocket object
ix::WebSocket webSocket; ix::WebSocket webSocket;
// Connect to a server with encryption
// See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration
std::string url("wss://echo.websocket.org"); std::string url("wss://echo.websocket.org");
webSocket.setUrl(url); webSocket.setUrl(url);
@ -53,6 +56,12 @@ int main()
std::cout << "Connection established" << std::endl; std::cout << "Connection established" << std::endl;
std::cout << "> " << std::flush; std::cout << "> " << std::flush;
} }
else if (msg->type == ix::WebSocketMessageType::Error)
{
// Maybe SSL is not configured properly
std::cout << "Connection error: " << msg->errorInfo.reason << std::endl;
std::cout << "> " << std::flush;
}
} }
); );

View File

@ -2,6 +2,34 @@
All changes to this project will be documented in this file. All changes to this project will be documented in this file.
## [11.2.6] - 2021-05-18
(Windows) move EINVAL (re)definition from IXSocket.h to IXNetSystem.h (fix #289)
## [11.2.5] - 2021-04-04
(http client) DEL is not an HTTP method name, but DELETE is
## [11.2.4] - 2021-03-25
(cmake) install IXUniquePtr.h
## [11.2.3] - 2021-03-24
(ssl + windows) missing include for CertOpenStore function
## [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 ## [11.1.4] - 2021-03-23
(ixwebsocket) add getMinWaitBetweenReconnectionRetries (ixwebsocket) add getMinWaitBetweenReconnectionRetries

View File

@ -374,13 +374,10 @@ The webSocket reference is guaranteed to be always valid ; by design the callbac
// Bound host name, max connections and listen backlog can also be passed in as parameters. // Bound host name, max connections and listen backlog can also be passed in as parameters.
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionState, server.setOnClientMessageCallback([](std::shared_ptr<ix::ConnectionState> connectionState, ix::WebSocket & webSocket, const ix::WebSocketMessagePtr & msg) {
WebSocket& webSocket,
const WebSocketMessagePtr& msg)
{
// The ConnectionState object contains information about the connection, // The ConnectionState object contains information about the connection,
// at this point only the client ip address and the port. // at this point only the client ip address and the port.
std::cout << "Remote ip: " << connectionState->getRemoteIp(); std::cout << "Remote ip: " << connectionState->getRemoteIp() << std::endl;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -398,7 +395,7 @@ server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionSta
std::cout << "Headers:" << std::endl; std::cout << "Headers:" << std::endl;
for (auto it : msg->openInfo.headers) for (auto it : msg->openInfo.headers)
{ {
std::cout << it.first << ": " << it.second << std::endl; std::cout << "\t" << it.first << ": " << it.second << std::endl;
} }
} }
else if (msg->type == ix::WebSocketMessageType::Message) else if (msg->type == ix::WebSocketMessageType::Message)
@ -407,9 +404,11 @@ server.setOnClientMessageCallback(std::shared_ptr<ConnectionState> connectionSta
// All connected clients are available in an std::set. See the broadcast cpp example. // All connected clients are available in an std::set. See the broadcast cpp example.
// Second parameter tells whether we are sending the message in binary or text mode. // Second parameter tells whether we are sending the message in binary or text mode.
// Here we send it in the same mode as it was received. // Here we send it in the same mode as it was received.
std::cout << "Received: " << msg->str << std::endl;
webSocket.send(msg->str, msg->binary); webSocket.send(msg->str, msg->binary);
} }
); });
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)

View File

@ -137,7 +137,7 @@ namespace ix
{ {
contentLength = std::stoi(headers["Content-Length"]); contentLength = std::stoi(headers["Content-Length"]);
} }
catch (std::exception) catch(const std::exception&)
{ {
return std::make_tuple( return std::make_tuple(
false, "Error parsing HTTP Header 'Content-Length'", httpRequest); false, "Error parsing HTTP Header 'Content-Length'", httpRequest);

View File

@ -20,10 +20,11 @@
namespace ix namespace ix
{ {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
const std::string HttpClient::kPost = "POST"; const std::string HttpClient::kPost = "POST";
const std::string HttpClient::kGet = "GET"; const std::string HttpClient::kGet = "GET";
const std::string HttpClient::kHead = "HEAD"; const std::string HttpClient::kHead = "HEAD";
const std::string HttpClient::kDel = "DEL"; const std::string HttpClient::kDelete = "DELETE";
const std::string HttpClient::kPut = "PUT"; const std::string HttpClient::kPut = "PUT";
const std::string HttpClient::kPatch = "PATCH"; const std::string HttpClient::kPatch = "PATCH";
@ -557,9 +558,9 @@ namespace ix
return request(url, kHead, std::string(), args); return request(url, kHead, std::string(), args);
} }
HttpResponsePtr HttpClient::del(const std::string& url, HttpRequestArgsPtr args) HttpResponsePtr HttpClient::Delete(const std::string& url, HttpRequestArgsPtr args)
{ {
return request(url, kDel, std::string(), args); return request(url, kDelete, std::string(), args);
} }
HttpResponsePtr HttpClient::request(const std::string& url, HttpResponsePtr HttpClient::request(const std::string& url,

View File

@ -30,7 +30,7 @@ namespace ix
HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args); HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args);
HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args); HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args);
HttpResponsePtr del(const std::string& url, HttpRequestArgsPtr args); HttpResponsePtr Delete(const std::string& url, HttpRequestArgsPtr args);
HttpResponsePtr post(const std::string& url, HttpResponsePtr post(const std::string& url,
const HttpParameters& httpParameters, const HttpParameters& httpParameters,
@ -94,7 +94,7 @@ namespace ix
const static std::string kPost; const static std::string kPost;
const static std::string kGet; const static std::string kGet;
const static std::string kHead; const static std::string kHead;
const static std::string kDel; const static std::string kDelete;
const static std::string kPut; const static std::string kPut;
const static std::string kPatch; const static std::string kPatch;

View File

@ -124,14 +124,12 @@ namespace ix
#endif #endif
} }
} // namespace ix
// //
// mingw does not have inet_ntop and inet_pton, which were taken as is from the musl C library. // mingw does not have inet_ntop, which were taken as is from the musl C library.
// //
#if defined(_WIN32) && defined(__GNUC__)
const char* inet_ntop(int af, const void* a0, char* s, socklen_t l) 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; const unsigned char* a = (const unsigned char*) a0;
int i, j, max, best; int i, j, max, best;
char buf[100]; char buf[100];
@ -190,8 +188,12 @@ const char* inet_ntop(int af, const void* a0, char* s, socklen_t l)
} }
errno = ENOSPC; errno = ENOSPC;
return 0; return 0;
#else
return ::inet_ntop(af, a0, s, l);
#endif
} }
#if defined(_WIN32) && defined(__GNUC__)
static int hexval(unsigned c) static int hexval(unsigned c)
{ {
if (c - '0' < 10) return c - '0'; if (c - '0' < 10) return c - '0';
@ -199,9 +201,14 @@ static int hexval(unsigned c)
if (c - 'a' < 6) return c - 'a' + 10; if (c - 'a' < 6) return c - 'a' + 10;
return -1; return -1;
} }
#endif
//
// 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) int inet_pton(int af, const char* s, void* a0)
{ {
#if defined(_WIN32) && defined(__GNUC__)
uint16_t ip[8]; uint16_t ip[8];
unsigned char* a = (unsigned char*) a0; unsigned char* a = (unsigned char*) a0;
int i, j, v, d, brk = -1, need_v4 = 0; int i, j, v, d, brk = -1, need_v4 = 0;
@ -266,5 +273,9 @@ int inet_pton(int af, const char* s, void* a0)
} }
if (need_v4 && inet_pton(AF_INET, (const char*) s, a - 4) <= 0) return 0; if (need_v4 && inet_pton(AF_INET, (const char*) s, a - 4) <= 0) return 0;
return 1; return 1;
#else
return ::inet_pton(af, s, a0);
#endif
} }
#endif // defined(_WIN32) && defined(__GNUC__)
} // namespace ix

View File

@ -18,6 +18,19 @@
#include <io.h> #include <io.h>
#include <ws2def.h> #include <ws2def.h>
#undef EWOULDBLOCK
#undef EAGAIN
#undef EINPROGRESS
#undef EBADF
#undef EINVAL
// map to WSA error codes
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EAGAIN WSATRY_AGAIN
#define EINPROGRESS WSAEINPROGRESS
#define EBADF WSAEBADF
#define EINVAL WSAEINVAL
// Define our own poll on Windows, as a wrapper on top of select // Define our own poll on Windows, as a wrapper on top of select
typedef unsigned long int nfds_t; typedef unsigned long int nfds_t;
@ -53,12 +66,6 @@ struct pollfd
#include <unistd.h> #include <unistd.h>
#endif #endif
// mingw does not have those
#if defined(_WIN32) && defined(__GNUC__)
const char* inet_ntop(int af, const void* src, char* dst, socklen_t size);
int inet_pton(int af, const char* src, void* dst);
#endif
namespace ix namespace ix
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -71,4 +78,7 @@ namespace ix
bool uninitNetSystem(); bool uninitNetSystem();
int poll(struct pollfd* fds, nfds_t nfds, int timeout); 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 } // namespace ix

View File

@ -15,20 +15,6 @@
#ifdef _WIN32 #ifdef _WIN32
#include <BaseTsd.h> #include <BaseTsd.h>
typedef SSIZE_T ssize_t; typedef SSIZE_T ssize_t;
#undef EWOULDBLOCK
#undef EAGAIN
#undef EINPROGRESS
#undef EBADF
#undef EINVAL
// map to WSA error codes
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EAGAIN WSATRY_AGAIN
#define EINPROGRESS WSAEINPROGRESS
#define EBADF WSAEBADF
#define EINVAL WSAEINVAL
#endif #endif
#include "IXCancellationRequest.h" #include "IXCancellationRequest.h"

View File

@ -16,6 +16,11 @@
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include <string.h> #include <string.h>
#ifdef _WIN32
// For manipulating the certificate store
#include <wincrypt.h>
#endif
namespace ix namespace ix
{ {
SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions, int fd) SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions, int fd)

View File

@ -24,6 +24,11 @@
#endif #endif
#define socketerrno errno #define socketerrno errno
#ifdef _WIN32
// For manipulating the certificate store
#include <wincrypt.h>
#endif
#ifdef _WIN32 #ifdef _WIN32
namespace namespace
{ {

View File

@ -104,7 +104,7 @@ namespace ix
server.sin_family = _addressFamily; server.sin_family = _addressFamily;
server.sin_port = htons(_port); 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; std::stringstream ss;
ss << "SocketServer::listen() error calling inet_pton " ss << "SocketServer::listen() error calling inet_pton "
@ -133,7 +133,7 @@ namespace ix
server.sin6_family = _addressFamily; server.sin6_family = _addressFamily;
server.sin6_port = htons(_port); 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; std::stringstream ss;
ss << "SocketServer::listen() error calling inet_pton " ss << "SocketServer::listen() error calling inet_pton "
@ -338,7 +338,7 @@ namespace ix
if (_addressFamily == AF_INET) if (_addressFamily == AF_INET)
{ {
char remoteIp4[INET_ADDRSTRLEN]; 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(); int err = Socket::getErrno();
std::stringstream ss; std::stringstream ss;
@ -357,7 +357,8 @@ namespace ix
else // AF_INET6 else // AF_INET6
{ {
char remoteIp6[INET6_ADDRSTRLEN]; 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(); int err = Socket::getErrno();
std::stringstream ss; std::stringstream ss;

View File

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

View File

@ -191,7 +191,6 @@ namespace ix
// Make sure the OS send buffer is flushed before moving on // Make sure the OS send buffer is flushed before moving on
do do
{ {
size_t bufferedAmount = client->bufferedAmount();
std::chrono::duration<double, std::milli> duration(500); std::chrono::duration<double, std::milli> duration(500);
std::this_thread::sleep_for(duration); std::this_thread::sleep_for(duration);
} while (client->bufferedAmount() != 0); } while (client->bufferedAmount() != 0);

View File

@ -6,4 +6,4 @@
#pragma once #pragma once
#define IX_WEBSOCKET_VERSION "11.1.4" #define IX_WEBSOCKET_VERSION "11.2.6"

View File

@ -15,6 +15,7 @@
#include <ixwebsocket/IXNetSystem.h> #include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXUserAgent.h>
#include <iostream> #include <iostream>
int main() int main()
@ -25,9 +26,12 @@ int main()
// Our websocket object // Our websocket object
ix::WebSocket webSocket; ix::WebSocket webSocket;
// Connect to a server with encryption
// See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration
std::string url("wss://echo.websocket.org"); std::string url("wss://echo.websocket.org");
webSocket.setUrl(url); webSocket.setUrl(url);
std::cout << ix::userAgent() << std::endl;
std::cout << "Connecting to " << url << "..." << std::endl; std::cout << "Connecting to " << url << "..." << std::endl;
// Setup a callback to be fired (in a background thread, watch out for race conditions !) // Setup a callback to be fired (in a background thread, watch out for race conditions !)
@ -44,6 +48,12 @@ int main()
std::cout << "Connection established" << std::endl; std::cout << "Connection established" << std::endl;
std::cout << "> " << std::flush; std::cout << "> " << std::flush;
} }
else if (msg->type == ix::WebSocketMessageType::Error)
{
// Maybe SSL is not configured properly
std::cout << "Connection error: " << msg->errorInfo.reason << std::endl;
std::cout << "> " << std::flush;
}
} }
); );

View File

@ -113,7 +113,7 @@ test_server:
test: test:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 ..) 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)
(cd build ; ninja test) (cd build ; ninja -v test)
test_asan: 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") 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

@ -906,7 +906,7 @@ namespace ix
// code which display correct results // code which display correct results
char str[INET_ADDRSTRLEN]; 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); spdlog::info("host: {} ip: {}", hostname, str);