C++ Guide
Overview
SST's C++17 API lives in entity/c/cpp/, within the sst-c-api submodule. It implements the same wire protocol as the C API and can communicate with Auth and C entities using the same properties configs.
sst::SST_API loads configuration and credentials and requests session keys. sst::SessionKeyList stores keys, and sst::SST_Session owns a connected socket and exchanges encrypted messages. Setup failures throw sst::SST_Exception; message send/receive operations return status codes. See the C++ API Reference for signatures and ownership rules.
Prerequisites
- A C++17 compiler, CMake 3.19 or newer, and OpenSSL 3 development headers.
- A POSIX environment, such as Linux or macOS.
- Git and network access for CMake to fetch the pinned spdlog dependency.
- The main SST repository with its C/C++ submodule initialized:
git clone --recurse-submodules https://github.com/iotauth/iotauth.git
cd iotauth
export SST_ROOT="$PWD"
For an existing checkout, run git submodule update --init entity/c from the repository root.
In the commands below, set SST_ROOT to that absolute checkout path in each terminal.
On macOS, CMake can use Homebrew's OpenSSL:
brew install openssl@3 cmake
export OPENSSL_ROOT_DIR="$(brew --prefix openssl@3)"
Build and test the library
cd "$SST_ROOT/entity/c/cpp"
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failure
This builds the static sst-cpp-api library and four unit test executables: crypto_test, socket_test, api_test, and message_test. These tests do not require Auth. Each example directory has a separate CMake project; building the library alone does not build the examples.
To include the API in another CMake project, add the cpp/ source directory and link the target:
add_subdirectory("${SST_ROOT}/entity/c/cpp" sst-cpp-build)
add_executable(my_entity main.cpp)
target_link_libraries(my_entity PRIVATE sst-cpp-api)
Here SST_ROOT is a CMake variable (for example, set it with -DSST_ROOT=/path/to/iotauth). The target exports the cpp/src/ include directory, so application code uses #include "api.hpp". The C++ project currently has no install/package-export rules.
Run the server/client example
Generate example credentials and build Auth as described in Quick Start. From the main repository:
cd "$SST_ROOT/examples"
./generateAll.sh
cd "$SST_ROOT/auth/auth-server"
mvn clean install
java -jar target/auth-server-jar-with-dependencies.jar \
-p ../properties/exampleAuth101.properties
Leave Auth running. Build the C++ examples in another terminal:
cd "$SST_ROOT/entity/c/cpp/examples/server_client_example"
cmake -S . -B build
cmake --build build
Start the server from that example directory:
./build/entity_server ../../../examples/server_client_example/c_server.config
In a third terminal, start the client from the same directory:
cd "$SST_ROOT/entity/c/cpp/examples/server_client_example"
./build/entity_client ../../../examples/server_client_example/c_client.config
The programs reuse the C example's configs and exchange encrypted messages over two successive connections. Run the C++ binaries from the example directory, as shown: credential paths in these configs are relative to the process working directory. The equivalent C binaries run from their own build/ directory, which has the same depth within entity/.
Both APIs use the C properties keys, including entityInfo.name, entityInfo.purpose, and auth.port.number. C++ also accepts legacy short field names. Python properties configs resolve credential paths relative to the config file instead; see Python configuration formats.
Client lifecycle
This small client sends one message. Supply a client config whose credential paths match the working directory, and use a running compatible server:
#include "api.hpp"
#include <iostream>
int main(int argc, char** argv) {
if (argc != 2) return 1;
try {
sst::SST_API api(argv[1]);
auto keys = api.get_session_key();
if (keys.empty()) return 1;
auto session = api.secure_connect_to_server(keys.s_key[0]);
if (session->send_secure_message("hello") < 0) return 1;
// The session destructor closes the socket.
} catch (const sst::SST_Exception& error) {
std::cerr << error.what() << '\n';
return 1;
}
}
For a receiver thread, call session->shutdown() and join the thread before destroying the session. shutdown() interrupts a blocked receive; the session destructor closes the descriptor.
More examples
Example under entity/c/cpp/ | Purpose |
|---|---|
examples/server_client_example/ | Secure sessions and session-key lookup by ID from multiple threads. |
examples/file_block_encrypt_example/ | Standalone block encryption with a locally generated key; no Auth required. |
examples/ipfs_examples/ | Encrypted IPFS uploads/downloads with plain or secure File System Managers. |
The C++ IPFS README provides the file-sharing topology, configuration paths, and run commands. cpp/src/ipfs.hpp exposes the corresponding sst::ipfs helpers.