Skip to content

Commit

Permalink
Merge pull request #8 from chandleg/stage
Browse files Browse the repository at this point in the history
Stage
  • Loading branch information
samiam567 authored Apr 17, 2024
2 parents 93fcc73 + 5114ab4 commit ba1fe0f
Show file tree
Hide file tree
Showing 16 changed files with 792 additions and 178 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/cpp-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jobs:

steps:
- uses: actions/checkout@v3
- name: Install Boost
run: sudo apt-get install libboost-all-dev
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y build-essential cmake
- name: Configure CMake
Expand Down
15 changes: 13 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@
"span": "cpp",
"stop_token": "cpp",
"cfenv": "cpp",
"typeindex": "cpp"
}
"typeindex": "cpp",
"forward_list": "cpp",
"unordered_set": "cpp",
"csetjmp": "cpp",
"barrier": "cpp",
"slist": "cpp",
"latch": "cpp",
"ranges": "cpp",
"shared_mutex": "cpp",
"syncstream": "cpp",
"valarray": "cpp"
},
"cmake.configureOnOpen": true
}
92 changes: 92 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# API Manual

## Installation

The library requires the Boost Beast and Jsoncpp libraries to handle WebSocket communications and JSON data manipulation respectively. Install these dependencies using CMake if they are not already present on your system.

### Required Libraries
- **Boost Beast** (version >= 1.76.0): Used for WebSocket implementation. Available at [boost.org](https://www.boost.org/).
- **Jsoncpp**: Used for JSON parsing and serialization. Known for its performance and ease of use in C++ environments.

## Examples
Two simple examples are provided demonstrating the Library in a simple raw C and a C++ classed implementation. Compile the examples using:
```bash
- mkdir build && cd build
- cmake ..
- make
- ./example_client_simple or ./example_client_classed
```

## Classes
### Connection
The `Connection` class manages WebSocket connections using Boost Beast. It handles asynchronous read, write, and connection management activities necessary for real-time communication.

#### Constructor
- `Connection(net::io_context& ioc)`: Initializes a new connection with a given I/O context. This context is used to handle all I/O operations for the WebSocket.

#### Methods
- `std::thread launch_socket(const char *host, const char *port)`: Starts the WebSocket connection on a separate thread.
- `void stop()`: Stops the WebSocket connection and cleans up resources.
- `void subscribe(std::string channel, socketCallback callback)`: Subscribes to a specific channel with a callback to handle incoming messages.
- `void unsubscribe(std::string channel)`: Unsubscribes from a specific channel.
- `void publish(std::string channel, std::string data)`: Publishes data to a specific channel.
- `void message_processing()`: Handles the internal message processing in its thread.

#### Callbacks
- `socketCallback`: A function type that handles incoming messages. Takes an event as `std::string` and data as `Json::Value`.

#### Members
- `websocket::stream<beast::tcp_stream> ws_`: WebSocket stream for the connection.
- `beast::flat_buffer buffer_`: Buffer used for reading WebSocket messages.

### SocketClusterClient

The `SocketClusterClient` class manages multiple WebSocket connections and provides methods to create and retrieve these connections.

#### Constructor
- `SocketClusterClient()`: Initializes a new client capable of handling WebSocket connections.

#### Methods
- `std::shared_ptr<Connection> createConnection(const char *url, const char *port)`: Creates and returns a new connection to the specified URL and port.
- `std::list<std::shared_ptr<Connection>>& getConnections()`: Returns a list of all active connections.

#### Members
- `std::list<std::shared_ptr<Connection>> m_connections`: List storing all managed connections.


## Errors & Exceptions
- `1000 - Normal Closure` : Connection closed successfully.
- `1001 - Going Away` : Server or client is shutting down.
- `1002 - Protocol Error` : Protocol violation detected.
- `1003 - Unsupported Data` : The endpoint received data of a type it cannot accept.
- `1006 - Abnormal Closure` : Connection closed abnormally without a status code.


## Example Usage of SocketClusterClient Library

This example demonstrates how to use the `SocketClusterClient` and `Connection` classes to connect to a WebSocket server, subscribe to a channel, and handle incoming messages.

```cpp
#include <iostream>
#include "SocketClusterClient.h"

// Define a callback function to handle messages received on the WebSocket
void handleMessage(std::string event, Json::Value data) {
std::cout << "Event: " << event << "\nMessage received: " << data.toStyledString() << std::endl;
}

int main() {
// Create a client instance
SocketClusterClient client;

// Create a new WebSocket connection to the desired host and port
auto connection = client.createConnection("ws://example.com", "80");

// Subscribe to a channel with the defined callback
connection->subscribe("exampleChannel", handleMessage);

// Publish to a channel
connection->publish("exampleChannel", "Hello World!");

return 0;
}
105 changes: 22 additions & 83 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
cmake_minimum_required(VERSION 3.10) # Example minimum version
set(CMAKE_CXX_STANDARD 17)

# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -coverage")
# set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -coverage")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -O0")
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0")

project(SocketClusterClientCPP)

include(FetchContent)
Expand All @@ -18,55 +13,34 @@ FetchContent_Declare(JsonCpp
FetchContent_MakeAvailable(JsonCpp)
# === ===

# Fetch WebSocket++
FetchContent_Declare(
websocketpp
GIT_REPOSITORY https://github.com/zaphoyd/websocketpp.git
GIT_TAG master # It's better to use a specific commit or tag for reproducibility
)

# Make WebSocket++ available for #include
FetchContent_GetProperties(websocketpp)
if(NOT websocketpp_POPULATED)
FetchContent_Populate(websocketpp)
include_directories(${websocketpp_SOURCE_DIR})
endif()

# Fetch Asio (standalone version, without Boost)
# set(BOOST_INCLUDE_LIBRARIES thread filesystem system program_options)
set(BOOST_ENABLE_CMAKE ON)
include(FetchContent)
FetchContent_Declare(
asio
GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git
GIT_TAG asio-1-18-1 # Use a specific tag or commit to ensure reproducibility
Boost
GIT_REPOSITORY https://github.com/boostorg/boost.git
GIT_TAG boost-1.74.0
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(Boost)

# Make Asio available for #include
FetchContent_GetProperties(asio)
if(NOT asio_POPULATED)
FetchContent_Populate(asio)
include_directories(${asio_SOURCE_DIR}/asio/include)
add_definitions(-DASIO_STANDALONE)
endif()
find_package(Boost 1.74.0 REQUIRED)

# Build Library
# Find source files
file(GLOB_RECURSE LIBRARY_SOURCES src/*.cpp)

# Create the library
add_library(SocketClusterClientCPP SHARED ${LIBRARY_SOURCES})

# Link against json-c
target_link_libraries(SocketClusterClientCPP PRIVATE jsoncpp_static)
target_link_libraries(SocketClusterClientCPP PUBLIC jsoncpp_lib)

# Update include directories to find json-c headers
target_include_directories(SocketClusterClientCPP PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${JsonCpp_SOURCE_DIR}/_deps/jsoncpp-src/include>
$<BUILD_INTERFACE:${websocketpp_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${asio_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${jsoncpp_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${websocketpp_SOURCE_DIR}/include>
)

target_include_directories(SocketClusterClientCPP PUBLIC "${Boost_INCLUDE_DIRS}")

# Install targets and headers
install(TARGETS SocketClusterClientCPP
ARCHIVE DESTINATION lib
Expand All @@ -76,16 +50,22 @@ install(TARGETS SocketClusterClientCPP
install(DIRECTORY src/
DESTINATION include)

add_executable(simple_example test/examples/client_classed.cpp)
target_link_libraries(simple_example PUBLIC SocketClusterClientCPP)


# Coverage
option(BUILD_TESTING "Builds only the test executable." ON)
option(CODE_COVERAGE "Collect coverage from test library" ON)
option(BUILD_TESTING "Builds only the test executable." OFF)
option(CODE_COVERAGE "Collect coverage from test library" OFF)

if(BUILD_TESTING)
enable_testing()
add_subdirectory(test)
add_test(NAME project_tests COMMAND ./bin/tests)

if(CODE_COVERAGE AND CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -O0")
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0")
# Set the coverage report output directory
set(COVERAGE_DIR ${CMAKE_BINARY_DIR}/coverage)

Expand Down Expand Up @@ -120,52 +100,11 @@ if(BUILD_TESTING)


endif()


# if(CODE_COVERAGE)
# set(CODE_COVERAGE_VERBOSE TRUE)
# include(CodeCoverage.cmake)
# # append_coverage_compiler_flags()
# append_coverage_compiler_flags_to_target(SocketClusterClientCPP)
# # set(COVERAGE_EXCLUDES "src/*")
# setup_target_for_coverage_lcov(
# NAME coverage
# EXECUTABLE ./bin/tests
# # BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src/"
# # EXCLUDE "*.cpp"
# )

# # setup_target_for_coverage_lcov(
# # NAME coverage
# # EXECUTABLE ./bin/tests
# # EXCLUDE "${PROJECT_SOURCE_DIR}/_deps/*"
# # "${PROJECT_BINARY_DIR}/*"
# # "${PROJECT_SOURCE_DIR}/test/*"
# # )
# endif()
endif()





# # === websocket++ ===
# FetchContent_Declare(websocketpp
# GIT_REPOSITORY https://github.com/zaphoyd/websocketpp.git
# GIT_TAG 0.8.2
# )
# FetchContent_GetProperties(websocketpp)
# if(NOT websocketpp_POPULATED)
# FetchContent_Populate(websocketpp)
# add_subdirectory(${websocketpp_SOURCE_DIR} ${websocketpp_BINARY_DIR} EXCLUDE_FROM_ALL)
# endif()
# add_library(Websockets INTERFACE)
# # === ===

# # === boost++ ===
# FetchContent_Declare(
# Boost
# GIT_REPOSITORY https://github.com/boostorg/boost.git
# GIT_TAG boost-1.80.0 # Replace with your desired version
# )
# FetchContent_MakeAvailable(Boost)

31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
# socketcluster-client-cpp
# Socket Cluster C++ Client

This repository hosts a [SocketCluster](https://socketcluster.io/) C++ Client designed to facilitate communication between C++ applications and SocketCluster servers. This client supports real-time, scalable, bi-directional communication, making it ideal for applications requiring high performance and efficient data exchange.
S
This client is developed using the [Boost Beast](https://github.com/boostorg/beast) and [jsoncpp](https://github.com/open-source-parsers/jsoncpp) libraries in C++.

## Features

- **Real-Time Communication**: Enables real-time connectivity with SocketCluster servers.
- **Bi-Directional Communication**: Supports both sending and receiving messages efficiently.
- **Scalability**: Designed to handle high-load scenarios, making it suitable for large-scale deployments.
- **WebSocket Support**: Utilizes WebSockets for low-latency communication.


## Getting Starting
A detailed list of the libraries API can be found [here](API.md).

## Security / SSL
#### Tokens
To address the threat of unauthenticated connections, we will utilize SocketCluster's built-in JWT-based authentication mechanism. Each JWT is uniquely signed using a server-specific authKey, ensuring secure and verified connections right from the initial handshake. Follow the guide [here](https://socketcluster.io/docs/authentication/) to enable JWTs with SocketCluster.
#### WSS
To allow development and production runs a flag can be set to enable SSL assuming the SocketCluster server has been configured to accept SSL connections. To best achieve this a flag can be set in the client to put the data transfer into the secure mode.
```cpp
#define SOCKETCLUSTER_SLL 1
```
## Performance
The maximum output and input rates have not been tested yet. This document will be updated with statistics after tests have been run. **Both example programs have been profiled and show no memory leaks.**
The SocketCluster server has been thoroughly tested in an [academic paper](https://arxiv.org/pdf/1409.3367.pdf). This client library aims to match the results listed.
Loading

0 comments on commit ba1fe0f

Please sign in to comment.