Compare commits

..

6 Commits

27 changed files with 133 additions and 52 deletions

19
CMake/FindJsonCpp.cmake Normal file
View File

@ -0,0 +1,19 @@
# Find package structure taken from libcurl
include(FindPackageHandleStandardArgs)
find_path(JSONCPP_INCLUDE_DIRS json/json.h)
find_library(JSONCPP_LIBRARY jsoncpp)
find_package_handle_standard_args(JSONCPP
FOUND_VAR
JSONCPP_FOUND
REQUIRED_VARS
JSONCPP_LIBRARY
JSONCPP_INCLUDE_DIRS
FAIL_MESSAGE
"Could NOT find jsoncpp"
)
set(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIRS})
set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY})

View File

@ -182,6 +182,7 @@ if (USE_TLS AND USE_OPEN_SSL)
endif()
if (USE_TLS AND USE_MBED_TLS)
# FIXME I'm not too sure that this USE_VENDORED_THIRD_PARTY thing works
if (USE_VENDORED_THIRD_PARTY)
set (ENABLE_PROGRAMS OFF)
add_subdirectory(third_party/mbedtls)

View File

@ -1 +1 @@
7.4.1
7.4.5

View File

@ -1,16 +1,16 @@
## Hello world
![Alt text](https://travis-ci.org/machinezone/IXWebSocket.svg?branch=master)
![Build status badge](https://travis-ci.org/machinezone/IXWebSocket.svg?branch=master)
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.
```cpp
# Required on Windows
// Required on Windows
ix::initNetSystem();
# Our websocket object
// Our websocket object
ix::WebSocket webSocket;
std::string url("ws://localhost:8080/");
@ -34,8 +34,8 @@ webSocket.start();
webSocket.send("hello world");
```
Interested ? Go read the [docs](https://machinezone.github.io/IXWebSocket/) ! If things don't work as expected, please create an issue in github, or even better a pull request if you know how to fix your problem.
Interested? Go read the [docs](https://machinezone.github.io/IXWebSocket/)! If things don't work as expected, please create an issue on GitHub, or even better a pull request if you know how to fix your problem.
IXWebSocket is actively being developed, check out the [changelog](CHANGELOG.md) to know what's cooking. If you are looking for a real time messaging service (the chat-like 'server' your websocket code will talk to) with many features such as history, backed by Redis, look at [cobra](https://github.com/machinezone/cobra).
IXWebSocket is actively being developed, check out the [changelog](https://machinezone.github.io/IXWebSocket/CHANGELOG/) to know what's cooking. If you are looking for a real time messaging service (the chat-like 'server' your websocket code will talk to) with many features such as history, backed by Redis, look at [cobra](https://github.com/machinezone/cobra).
IXWebSocket client code is autobahn compliant beginning with the 6.0.0 version. See the current [test results](https://bsergean.github.io/IXWebSocket/autobahn/index.html). Some tests are still failing in the server code.

View File

@ -1,6 +1,22 @@
# Changelog
All notable changes to this project will be documented in this file.
## [7.4.5] - 2019-12-03
- (ws) #125 / fix build problem when jsoncpp is not installed locally
## [7.4.4] - 2019-12-03
- (ws) #125 / cmake detects an already installed jsoncpp and will try to use this one if present
## [7.4.3] - 2019-12-03
- (http client) use std::unordered_map instead of std::map for HttpParameters and HttpFormDataParameters class aliases
## [7.4.2] - 2019-12-02
- (client) internal IXDNSLookup class requires a valid cancellation request function callback to be passed in
## [7.4.1] - 2019-12-02
- (client) fix an overflow in the exponential back off code

View File

@ -33,7 +33,7 @@ vcpkg install ixwebsocket
### Conan
Support for building with conan was contributed by Olivia Zoe (thanks !). The package name to reference is `IXWebSocket/5.0.0@LunarWatcher/stable`. The package is in the process to be published to the official conan package repo, but in the meantime, it can be accessed by adding a new remote
Support for building with conan was contributed by Olivia Zoe (thanks!). The package name to reference is `IXWebSocket/5.0.0@LunarWatcher/stable`, and a list of the uploaded versions is available on [Bintray](https://bintray.com/oliviazoe0/conan-packages/IXWebSocket%3ALunarWatcher). The package is in the process to be published to the official conan package repo, but in the meantime, it can be accessed by adding a new remote
```
conan remote add remote_name_here https://api.bintray.com/conan/oliviazoe0/conan-packages

View File

@ -8,7 +8,7 @@ Bring up 3 terminals and run a server, a publisher and a subscriber in each one.
You will need to have a redis server running locally. To run the server:
```
```bash
$ cd <ixwebsocket-top-level-folder>/ixsnake/ixsnake
$ ws snake
{
@ -33,7 +33,7 @@ redis port: 6379
### Publisher
```
```bash
$ cd <ixwebsocket-top-level-folder>/ws
$ ws cobra_publish --appkey FC2F10139A2BAc53BB72D9db967b024f --endpoint ws://127.0.0.1:8008 --rolename _pub --rolesecret 1c04DB8fFe76A4EeFE3E318C72d771db test_channel cobraMetricsSample.json
[2019-11-27 09:06:12.980] [info] Publisher connected
@ -49,7 +49,7 @@ $ ws cobra_publish --appkey FC2F10139A2BAc53BB72D9db967b024f --endpoint ws://127
### Subscriber
```
```bash
$ ws cobra_subscribe --appkey FC2F10139A2BAc53BB72D9db967b024f --endpoint ws://127.0.0.1:8008 --rolename _pub --rolesecret 1c04DB8fFe76A4EeFE3E318C72d771db test_channel
#messages 0 msg/s 0
[2019-11-27 09:07:39.341] [info] Subscriber connected

View File

@ -24,7 +24,7 @@ Large frames are broken up into smaller chunks or messages to avoid filling up t
The library has an interactive tool which is handy for testing compatibility ith other libraries. We have tested our client against Python, Erlang, Node.js, and C++ websocket server libraries.
The unittest tries to be comprehensive, and has been running on multiple platoform, with different sanitizers such as thread sanitizer to catch data races or the undefined behavior sanitizer.
The unittest tries to be comprehensive, and has been running on multiple platforms, with different sanitizers such as a thread sanitizer to catch data races or the undefined behavior sanitizer.
The regression test is running after each commit on travis.

View File

@ -13,11 +13,11 @@
## Example code
```
# Required on Windows
```cpp
// Required on Windows
ix::initNetSystem();
# Our websocket object
// Our websocket object
ix::WebSocket webSocket;
std::string url("ws://localhost:8080/");
@ -40,7 +40,7 @@ webSocket.start();
webSocket.send("hello world");
```
## Why another library ?
## Why another library?
There are 2 main reasons that explain why IXWebSocket got written. First, we needed a C++ cross-platform client library, which should have few dependencies. What looked like the most solid one, [websocketpp](https://github.com/zaphoyd/websocketpp) did depend on boost and this was not an option for us. Secondly, there were other available libraries with fewer dependencies (C ones), but they required calling an explicit poll routine periodically to know if a client had received data from a server, which was not elegant.
@ -48,4 +48,4 @@ We started by solving those 2 problems, then we added server websocket code, the
## Contributing
IXWebSocket is developed on [github](https://github.com/machinezone/IXWebSocket). We'd love to hear about how you use it ; opening up an issue in github is ok for that. If things don't work as expected, please create an issue in github, or even better a pull request if you know how to fix your problem.
IXWebSocket is developed on [GitHub](https://github.com/machinezone/IXWebSocket). We'd love to hear about how you use it; opening up an issue on GitHub is ok for that. If things don't work as expected, please create an issue on GitHub, or even better a pull request if you know how to fix your problem.

View File

@ -6,7 +6,7 @@ The [*ws*](https://github.com/machinezone/IXWebSocket/tree/master/ws) folder cou
To use the network system on Windows, you need to initialize it once with *WSAStartup()* and clean it up with *WSACleanup()*. We have helpers for that which you can use, see below. This init would typically take place in your main function.
```
```cpp
#include <ixwebsocket/IXNetSystem.h>
int main()
@ -22,12 +22,12 @@ int main()
## WebSocket client API
```
```cpp
#include <ixwebsocket/IXWebSocket.h>
...
# Our websocket object
// Our websocket object
ix::WebSocket webSocket;
std::string url("ws://localhost:8080/");
@ -82,9 +82,9 @@ If the connection was closed and sending failed, the return value will be set to
### Open and Close notifications
The onMessage event will be fired when the connection is opened or closed. This is similar to the [Javascript browser API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket), which has `open` and `close` events notification that can be registered with the browser `addEventListener`.
The onMessage event will be fired when the connection is opened or closed. This is similar to the [JavaScript browser API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket), which has `open` and `close` events notification that can be registered with the browser `addEventListener`.
```
```cpp
webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Open)
@ -115,7 +115,7 @@ webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
A message will be fired when there is an error with the connection. The message type will be `ix::WebSocketMessageType::Error`. Multiple fields will be available on the event to describe the error.
```
```cpp
webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Error)
@ -140,7 +140,7 @@ webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
The url can be set and queried after a websocket object has been created. You will have to call `stop` and `start` if you want to disconnect and connect to that new url.
```
```cpp
std::string url("wss://example.com");
websocket.configure(url);
```
@ -149,7 +149,7 @@ websocket.configure(url);
Ping/pong messages are used to implement keep-alive. 2 message types exists to identify ping and pong messages. Note that when a ping message is received, a pong is instantly send back as requested by the WebSocket spec.
```
```cpp
webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Ping ||
@ -163,7 +163,7 @@ webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
A ping message can be sent to the server, with an optional data string.
```
```cpp
websocket.ping("ping data, optional (empty string is ok): limited to 125 bytes long");
```
@ -173,7 +173,7 @@ You can configure an optional heart beat / keep-alive, sent every 45 seconds
when there is no any traffic to make sure that load balancers do not kill an
idle connection.
```
```cpp
webSocket.setHeartBeatPeriod(45);
```
@ -181,7 +181,7 @@ webSocket.setHeartBeatPeriod(45);
You can set extra HTTP headers to be sent during the WebSocket handshake.
```
```cpp
WebSocketHttpHeaders headers;
headers["foo"] = "bar";
webSocket.setExtraHeaders(headers);
@ -191,14 +191,14 @@ webSocket.setExtraHeaders(headers);
You can specify subprotocols to be set during the WebSocket handshake. For more info you can refer to [this doc](https://hpbn.co/websocket/#subprotocol-negotiation).
```
```cpp
webSocket.addSubprotocol("appProtocol-v1");
webSocket.addSubprotocol("appProtocol-v2");
```
The protocol that the server did accept is available in the open info `protocol` field.
```
```cpp
std::cout << "protocol: " << msg->openInfo.protocol << std::endl;
```
@ -206,7 +206,7 @@ std::cout << "protocol: " << msg->openInfo.protocol << std::endl;
Automatic reconnection kicks in when the connection is disconnected without the user consent. This feature is on by default and can be turned off.
```
```cpp
webSocket.enableAutomaticReconnection(); // turn on
webSocket.disableAutomaticReconnection(); // turn off
bool enabled = webSocket.isAutomaticReconnectionEnabled(); // query state
@ -239,7 +239,7 @@ Wait time(ms): 10000
The waiting time is capped by default at 10s between 2 attempts, but that value can be changed and queried.
```
```cpp
webSocket.setMaxWaitBetweenReconnectionRetries(5 * 1000); // 5000ms = 5s
uint32_t m = webSocket.getMaxWaitBetweenReconnectionRetries();
```
@ -253,7 +253,7 @@ Then, secure sockets are automatically used when connecting to a `wss://*` url.
Additional TLS options can be configured by passing a `ix::SocketTLSOptions` instance to the
`setTLSOptions` on `ix::WebSocket` (or `ix::WebSocketServer` or `ix::HttpServer`)
```
```cpp
webSocket.setTLSOptions({
.certFile = "path/to/cert/file.pem",
.keyFile = "path/to/key/file.pem",
@ -279,7 +279,7 @@ For a server, specifying `caFile` implies that:
## WebSocket server API
```
```cpp
#include <ixwebsocket/IXWebSocketServer.h>
...
@ -344,7 +344,7 @@ server.wait();
## HTTP client API
```
```cpp
#include <ixwebsocket/IXHttpClient.h>
...
@ -427,7 +427,7 @@ bool ok = httpClient.performRequest(args, [](const HttpResponsePtr& response)
## HTTP server API
```
```cpp
#include <ixwebsocket/IXHttpServer.h>
ix::HttpServer server(port, hostname);
@ -445,7 +445,7 @@ server.wait();
If you want to handle how requests are processed, implement the setOnConnectionCallback callback, which takes an HttpRequestPtr as input, and returns an HttpResponsePtr. You can look at HttpServer::setDefaultConnectionCallback for a slightly more advanced callback example.
```
```cpp
setOnConnectionCallback(
[this](HttpRequestPtr request,
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr

View File

@ -245,4 +245,4 @@ Options:
## Cobra Client
[cobra](https://github.com/machinezone/cobra) is a real time messenging server. ws has sub-command to interacti with cobra.
[cobra](https://github.com/machinezone/cobra) is a real time messenging server. ws has a sub-command to interact with cobra.

View File

@ -20,11 +20,16 @@ add_library(ixcobra STATIC
${IXCOBRA_HEADERS}
)
find_package(JsonCpp)
if (NOT JSONCPP_FOUND)
set(JSONCPP_INCLUDE_DIRS ../third_party/jsoncpp)
endif()
set(IXCOBRA_INCLUDE_DIRS
.
..
../ixcore
../ixcrypto
../third_party)
${JSONCPP_INCLUDE_DIRS})
target_include_directories( ixcobra PUBLIC ${IXCOBRA_INCLUDE_DIRS} )

View File

@ -14,6 +14,7 @@
#include <cassert>
#include <cstring>
#include <iostream>
#include <sstream>
namespace ix

View File

@ -8,7 +8,7 @@
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
#include <ixwebsocket/IXWebSocketPerMessageDeflateOptions.h>
#include <jsoncpp/json/json.h>
#include <json/json.h>
#include <memory>
#include <mutex>
#include <queue>

View File

@ -9,7 +9,7 @@
#include "IXCobraMetricsThreadedPublisher.h"
#include <atomic>
#include <chrono>
#include <jsoncpp/json/json.h>
#include <json/json.h>
#include <string>
#include <unordered_map>

View File

@ -13,6 +13,7 @@
#include <cmath>
#include <cassert>
#include <iostream>
#include <sstream>
namespace ix

View File

@ -9,7 +9,7 @@
#include "IXCobraConnection.h"
#include <atomic>
#include <condition_variable>
#include <jsoncpp/json/json.h>
#include <json/json.h>
#include <map>
#include <mutex>
#include <queue>

View File

@ -16,10 +16,15 @@ add_library(ixsentry STATIC
${IXSENTRY_HEADERS}
)
find_package(JsonCpp)
if (NOT JSONCPP_FOUND)
set(JSONCPP_INCLUDE_DIRS ../third_party/jsoncpp)
endif()
set(IXSENTRY_INCLUDE_DIRS
.
..
../ixcore
../third_party)
${JSONCPP_INCLUDE_DIRS})
target_include_directories( ixsentry PUBLIC ${IXSENTRY_INCLUDE_DIRS} )

View File

@ -9,6 +9,7 @@
#include <chrono>
#include <iostream>
#include <fstream>
#include <sstream>
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
#include <ixcore/utils/IXCoreLogger.h>

View File

@ -8,7 +8,7 @@
#include <algorithm>
#include <ixwebsocket/IXHttpClient.h>
#include <jsoncpp/json/json.h>
#include <json/json.h>
#include <regex>
#include <memory>

View File

@ -29,8 +29,13 @@ namespace ix
return false;
}
CancellationRequest cancellationRequest = []() -> bool
{
return false;
};
std::string errMsg;
return _socket->connect(hostname, port, errMsg, nullptr);
return _socket->connect(hostname, port, errMsg, cancellationRequest);
}
void RedisClient::stop()

View File

@ -61,7 +61,7 @@ namespace ix
errMsg = "no error";
// Maybe a cancellation request got in before the background thread terminated ?
if (isCancellationRequested && isCancellationRequested())
if (isCancellationRequested())
{
errMsg = "cancellation requested";
return nullptr;
@ -107,7 +107,7 @@ namespace ix
std::this_thread::sleep_for(std::chrono::milliseconds(_wait));
// Were we cancelled ?
if (isCancellationRequested && isCancellationRequested())
if (isCancellationRequested())
{
errMsg = "cancellation requested";
return nullptr;
@ -115,7 +115,7 @@ namespace ix
}
// Maybe a cancellation request got in before the bg terminated ?
if (isCancellationRequested && isCancellationRequested())
if (isCancellationRequested())
{
errMsg = "cancellation requested";
return nullptr;

View File

@ -9,6 +9,7 @@
#include "IXProgressCallback.h"
#include "IXWebSocketHttpHeaders.h"
#include <tuple>
#include <unordered_map>
namespace ix
{
@ -65,8 +66,8 @@ namespace ix
};
using HttpResponsePtr = std::shared_ptr<HttpResponse>;
using HttpParameters = std::map<std::string, std::string>;
using HttpFormDataParameters = std::map<std::string, std::string>;
using HttpParameters = std::unordered_map<std::string, std::string>;
using HttpFormDataParameters = std::unordered_map<std::string, std::string>;
using Logger = std::function<void(const std::string&)>;
using OnResponseCallback = std::function<void(const HttpResponsePtr&)>;

View File

@ -9,6 +9,9 @@
*
* This is the right example to look at:
* https://www.codeproject.com/Articles/1000189/A-Working-TCP-Client-and-Server-With-SSL
*
* Similar code is available from this git repo
* https://github.com/david-maw/StreamSSL
*/
#include "IXSocketSChannel.h"

View File

@ -6,4 +6,4 @@
#pragma once
#define IX_WEBSOCKET_VERSION "7.4.1"
#define IX_WEBSOCKET_VERSION "7.4.5"

View File

@ -23,13 +23,20 @@ include_directories(
../ws
)
find_package(JsonCpp)
if (NOT JSONCPP_FOUND)
include_directories(../third_party/jsoncpp)
set(JSONCPP_SOURCES ../third_party/jsoncpp/jsoncpp.cpp)
endif()
# Shared sources
set (SOURCES
${JSONCPP_SOURCES}
test_runner.cpp
IXTest.cpp
IXGetFreePort.cpp
../third_party/msgpack11/msgpack11.cpp
../third_party/jsoncpp/jsoncpp.cpp
IXSocketTest.cpp
IXSocketConnectTest.cpp
@ -79,6 +86,11 @@ 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()
target_link_libraries(ixwebsocket_unittest ixsnake)
target_link_libraries(ixwebsocket_unittest ixcobra)
target_link_libraries(ixwebsocket_unittest ixwebsocket)

View File

@ -29,10 +29,16 @@ if (UNIX)
set( STATSD_CLIENT_SOURCES ../third_party/statsd-client-cpp/src/statsd_client.cpp)
endif()
find_package(JsonCpp)
if (NOT JSONCPP_FOUND)
include_directories(../third_party/jsoncpp)
set(JSONCPP_SOURCES ../third_party/jsoncpp/jsoncpp.cpp)
endif()
add_executable(ws
../third_party/msgpack11/msgpack11.cpp
../third_party/jsoncpp/jsoncpp.cpp
${STATSD_CLIENT_SOURCES}
${JSONCPP_SOURCES}
ws_http_client.cpp
ws_ping_pong.cpp
@ -74,4 +80,9 @@ if(NOT APPLE AND NOT USE_MBED_TLS)
target_link_libraries(ws ${OPENSSL_LIBRARIES})
endif()
if (JSONCPP_FOUND)
target_include_directories(ws PUBLIC ${JSONCPP_INCLUDE_DIRS})
target_link_libraries(ws ${JSONCPP_LIBRARIES})
endif()
install(TARGETS ws RUNTIME DESTINATION bin)