Skip to content

Commit 5114ab4

Browse files
authored
Merge pull request #7 from chandleg/dev
Stage Commit
2 parents a3218ce + cfc6ba4 commit 5114ab4

21 files changed

+1874
-93
lines changed

.github/workflows/cpp-ci.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: SocketCluster CI
2+
3+
on:
4+
push:
5+
branches: [ stage, prod ]
6+
pull_request:
7+
branches: [ stage, prod ]
8+
9+
jobs:
10+
build:
11+
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v3
16+
- name: Install Boost
17+
run: sudo apt-get install libboost-all-dev
18+
- name: Install dependencies
19+
run: sudo apt-get update && sudo apt-get install -y build-essential cmake
20+
- name: Configure CMake
21+
run: cmake -S . -B build
22+
- name: Build
23+
run: cmake --build build
24+
- name: Run tests
25+
run: ./build/bin/tests

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@
3030
*.exe
3131
*.out
3232
*.app
33+
34+
build/
35+
.vscode/

.vscode/settings.json

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
{
2+
"files.associations": {
3+
"__bit_reference": "cpp",
4+
"__config": "cpp",
5+
"__debug": "cpp",
6+
"__errc": "cpp",
7+
"__hash_table": "cpp",
8+
"__locale": "cpp",
9+
"__mutex_base": "cpp",
10+
"__node_handle": "cpp",
11+
"__split_buffer": "cpp",
12+
"__threading_support": "cpp",
13+
"__tree": "cpp",
14+
"__verbose_abort": "cpp",
15+
"array": "cpp",
16+
"atomic": "cpp",
17+
"bitset": "cpp",
18+
"cctype": "cpp",
19+
"charconv": "cpp",
20+
"clocale": "cpp",
21+
"cmath": "cpp",
22+
"complex": "cpp",
23+
"condition_variable": "cpp",
24+
"cstdarg": "cpp",
25+
"cstddef": "cpp",
26+
"cstdint": "cpp",
27+
"cstdio": "cpp",
28+
"cstdlib": "cpp",
29+
"cstring": "cpp",
30+
"ctime": "cpp",
31+
"cwchar": "cpp",
32+
"cwctype": "cpp",
33+
"deque": "cpp",
34+
"exception": "cpp",
35+
"fstream": "cpp",
36+
"future": "cpp",
37+
"initializer_list": "cpp",
38+
"iomanip": "cpp",
39+
"ios": "cpp",
40+
"iosfwd": "cpp",
41+
"iostream": "cpp",
42+
"istream": "cpp",
43+
"limits": "cpp",
44+
"list": "cpp",
45+
"locale": "cpp",
46+
"map": "cpp",
47+
"mutex": "cpp",
48+
"new": "cpp",
49+
"optional": "cpp",
50+
"ostream": "cpp",
51+
"queue": "cpp",
52+
"ratio": "cpp",
53+
"regex": "cpp",
54+
"set": "cpp",
55+
"sstream": "cpp",
56+
"stack": "cpp",
57+
"stdexcept": "cpp",
58+
"streambuf": "cpp",
59+
"string": "cpp",
60+
"string_view": "cpp",
61+
"system_error": "cpp",
62+
"thread": "cpp",
63+
"tuple": "cpp",
64+
"typeinfo": "cpp",
65+
"unordered_map": "cpp",
66+
"variant": "cpp",
67+
"vector": "cpp",
68+
"algorithm": "cpp",
69+
"any": "cpp",
70+
"cinttypes": "cpp",
71+
"codecvt": "cpp",
72+
"csignal": "cpp",
73+
"coroutine": "cpp",
74+
"source_location": "cpp",
75+
"strstream": "cpp",
76+
"*.ipp": "cpp",
77+
"functional": "cpp",
78+
"bit": "cpp",
79+
"*.tcc": "cpp",
80+
"chrono": "cpp",
81+
"compare": "cpp",
82+
"concepts": "cpp",
83+
"iterator": "cpp",
84+
"memory": "cpp",
85+
"memory_resource": "cpp",
86+
"numeric": "cpp",
87+
"random": "cpp",
88+
"type_traits": "cpp",
89+
"utility": "cpp",
90+
"format": "cpp",
91+
"numbers": "cpp",
92+
"semaphore": "cpp",
93+
"span": "cpp",
94+
"stop_token": "cpp",
95+
"cfenv": "cpp",
96+
"typeindex": "cpp",
97+
"forward_list": "cpp",
98+
"unordered_set": "cpp",
99+
"csetjmp": "cpp",
100+
"barrier": "cpp",
101+
"slist": "cpp",
102+
"latch": "cpp",
103+
"ranges": "cpp",
104+
"shared_mutex": "cpp",
105+
"syncstream": "cpp",
106+
"valarray": "cpp"
107+
},
108+
"cmake.configureOnOpen": true
109+
}

API.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# API Manual
2+
3+
## Installation
4+
5+
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.
6+
7+
### Required Libraries
8+
- **Boost Beast** (version >= 1.76.0): Used for WebSocket implementation. Available at [boost.org](https://www.boost.org/).
9+
- **Jsoncpp**: Used for JSON parsing and serialization. Known for its performance and ease of use in C++ environments.
10+
11+
## Examples
12+
Two simple examples are provided demonstrating the Library in a simple raw C and a C++ classed implementation. Compile the examples using:
13+
```bash
14+
- mkdir build && cd build
15+
- cmake ..
16+
- make
17+
- ./example_client_simple or ./example_client_classed
18+
```
19+
20+
## Classes
21+
### Connection
22+
The `Connection` class manages WebSocket connections using Boost Beast. It handles asynchronous read, write, and connection management activities necessary for real-time communication.
23+
24+
#### Constructor
25+
- `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.
26+
27+
#### Methods
28+
- `std::thread launch_socket(const char *host, const char *port)`: Starts the WebSocket connection on a separate thread.
29+
- `void stop()`: Stops the WebSocket connection and cleans up resources.
30+
- `void subscribe(std::string channel, socketCallback callback)`: Subscribes to a specific channel with a callback to handle incoming messages.
31+
- `void unsubscribe(std::string channel)`: Unsubscribes from a specific channel.
32+
- `void publish(std::string channel, std::string data)`: Publishes data to a specific channel.
33+
- `void message_processing()`: Handles the internal message processing in its thread.
34+
35+
#### Callbacks
36+
- `socketCallback`: A function type that handles incoming messages. Takes an event as `std::string` and data as `Json::Value`.
37+
38+
#### Members
39+
- `websocket::stream<beast::tcp_stream> ws_`: WebSocket stream for the connection.
40+
- `beast::flat_buffer buffer_`: Buffer used for reading WebSocket messages.
41+
42+
### SocketClusterClient
43+
44+
The `SocketClusterClient` class manages multiple WebSocket connections and provides methods to create and retrieve these connections.
45+
46+
#### Constructor
47+
- `SocketClusterClient()`: Initializes a new client capable of handling WebSocket connections.
48+
49+
#### Methods
50+
- `std::shared_ptr<Connection> createConnection(const char *url, const char *port)`: Creates and returns a new connection to the specified URL and port.
51+
- `std::list<std::shared_ptr<Connection>>& getConnections()`: Returns a list of all active connections.
52+
53+
#### Members
54+
- `std::list<std::shared_ptr<Connection>> m_connections`: List storing all managed connections.
55+
56+
57+
## Errors & Exceptions
58+
- `1000 - Normal Closure` : Connection closed successfully.
59+
- `1001 - Going Away` : Server or client is shutting down.
60+
- `1002 - Protocol Error` : Protocol violation detected.
61+
- `1003 - Unsupported Data` : The endpoint received data of a type it cannot accept.
62+
- `1006 - Abnormal Closure` : Connection closed abnormally without a status code.
63+
64+
65+
## Example Usage of SocketClusterClient Library
66+
67+
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.
68+
69+
```cpp
70+
#include <iostream>
71+
#include "SocketClusterClient.h"
72+
73+
// Define a callback function to handle messages received on the WebSocket
74+
void handleMessage(std::string event, Json::Value data) {
75+
std::cout << "Event: " << event << "\nMessage received: " << data.toStyledString() << std::endl;
76+
}
77+
78+
int main() {
79+
// Create a client instance
80+
SocketClusterClient client;
81+
82+
// Create a new WebSocket connection to the desired host and port
83+
auto connection = client.createConnection("ws://example.com", "80");
84+
85+
// Subscribe to a channel with the defined callback
86+
connection->subscribe("exampleChannel", handleMessage);
87+
88+
// Publish to a channel
89+
connection->publish("exampleChannel", "Hello World!");
90+
91+
return 0;
92+
}

CMakeLists.txt

Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,110 @@
1+
cmake_minimum_required(VERSION 3.10) # Example minimum version
2+
set(CMAKE_CXX_STANDARD 17)
13

2-
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
4+
project(SocketClusterClientCPP)
35

4-
project(socketcluster_client)
6+
include(FetchContent)
57

8+
# === JsonCPP ===
9+
FetchContent_Declare(JsonCpp
10+
GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp.git
11+
GIT_TAG 1.9.5 # Or your desired version
12+
)
13+
FetchContent_MakeAvailable(JsonCpp)
14+
# === ===
615

7-
# random bullshit
8-
# Default to C99
9-
if(NOT CMAKE_C_STANDARD)
10-
set(CMAKE_C_STANDARD 99)
11-
endif()
16+
# set(BOOST_INCLUDE_LIBRARIES thread filesystem system program_options)
17+
set(BOOST_ENABLE_CMAKE ON)
18+
include(FetchContent)
19+
FetchContent_Declare(
20+
Boost
21+
GIT_REPOSITORY https://github.com/boostorg/boost.git
22+
GIT_TAG boost-1.74.0
23+
GIT_SHALLOW TRUE
24+
)
25+
FetchContent_MakeAvailable(Boost)
26+
27+
find_package(Boost 1.74.0 REQUIRED)
28+
29+
# Find source files
30+
file(GLOB_RECURSE LIBRARY_SOURCES src/*.cpp)
31+
add_library(SocketClusterClientCPP SHARED ${LIBRARY_SOURCES})
32+
target_link_libraries(SocketClusterClientCPP PUBLIC jsoncpp_lib)
33+
34+
# Update include directories to find json-c headers
35+
target_include_directories(SocketClusterClientCPP PUBLIC
36+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
37+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
38+
$<BUILD_INTERFACE:${jsoncpp_SOURCE_DIR}/include>
39+
$<BUILD_INTERFACE:${websocketpp_SOURCE_DIR}/include>
40+
)
41+
42+
target_include_directories(SocketClusterClientCPP PUBLIC "${Boost_INCLUDE_DIRS}")
43+
44+
# Install targets and headers
45+
install(TARGETS SocketClusterClientCPP
46+
ARCHIVE DESTINATION lib
47+
LIBRARY DESTINATION lib
48+
RUNTIME DESTINATION bin)
49+
50+
install(DIRECTORY src/
51+
DESTINATION include)
52+
53+
add_executable(simple_example test/examples/client_classed.cpp)
54+
target_link_libraries(simple_example PUBLIC SocketClusterClientCPP)
1255

13-
# Default to C++14
14-
if(NOT CMAKE_CXX_STANDARD)
15-
set(CMAKE_CXX_STANDARD 14)
16-
endif()
1756

18-
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
19-
add_compile_options(-Wall -Wextra -Wpedantic)
57+
# Coverage
58+
option(BUILD_TESTING "Builds only the test executable." OFF)
59+
option(CODE_COVERAGE "Collect coverage from test library" OFF)
60+
61+
if(BUILD_TESTING)
62+
enable_testing()
63+
add_subdirectory(test)
64+
add_test(NAME project_tests COMMAND ./bin/tests)
65+
66+
if(CODE_COVERAGE AND CMAKE_BUILD_TYPE MATCHES Debug)
67+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -O0")
68+
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0")
69+
# Set the coverage report output directory
70+
set(COVERAGE_DIR ${CMAKE_BINARY_DIR}/coverage)
71+
72+
# Clean the coverage directory
73+
add_custom_target(coverage_clean
74+
COMMAND ${CMAKE_COMMAND} -E rm -rf ${COVERAGE_DIR}
75+
)
76+
77+
# Add a target to run the tests and collect coverage information
78+
add_custom_target(coverage
79+
COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_DIR}
80+
COMMAND ${CMAKE_COMMAND} -E env LCOV_OPTS="--rc lcov_branch_coverage=1 geninfo_unexecuted_blocks=1" $<TARGET_FILE:tests>
81+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
82+
DEPENDS tests coverage_clean
83+
COMMENT "Running tests and collecting coverage data..."
84+
)
85+
86+
# Add a target to generate the coverage report
87+
# Add a target to generate the coverage report
88+
# Add a target to generate the coverage report
89+
add_custom_target(coverage_report
90+
COMMAND lcov --capture --directory . --output-file ${COVERAGE_DIR}/coverage.info --ignore-errors source,unused
91+
# Remove coverage data for external libraries, including Catch2
92+
COMMAND lcov --remove ${COVERAGE_DIR}/coverage.info "/usr/*" "${CMAKE_BINARY_DIR}/_deps/*" --output-file ${COVERAGE_DIR}/filtered.info --ignore-errors source,unused
93+
# Optional: Add more --remove lines as needed to exclude other directories or files
94+
COMMAND lcov --list ${COVERAGE_DIR}/filtered.info
95+
COMMAND genhtml -o ${COVERAGE_DIR}/html ${COVERAGE_DIR}/filtered.info
96+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
97+
DEPENDS coverage
98+
COMMENT "Generating coverage report..."
99+
)
100+
101+
102+
endif()
20103
endif()
21-
# end random bs
22104

23-
# find dependencies
24-
find_package(jsonc REQUIRED)
25-
find_package(boostbeast REQUIRED)
26105

27-
set(SOURCES)
28-
set(dependencies
29-
jsonc
30-
boostbeast
31-
)
32106

33-
add_executable(main src/main.cpp dependencies)
34107

35108

36-
install(
37-
TARGETS maininstall(DIRECTORY
38-
config
39-
DESTINATION share/${PROJECT_NAME}
40-
)
41-
)
109+
110+

0 commit comments

Comments
 (0)