OddSockets C SDK
Official C SDK for OddSockets real-time messaging platform, optimized for embedded systems and IoT devices
Overview & Features
The OddSockets C SDK provides a lightweight, high-performance interface for real-time messaging specifically designed for embedded systems, IoT devices, and resource-constrained environments.
Embedded Optimized
Designed for resource-constrained devices with minimal memory footprint and deterministic behavior.
Memory Efficient
Custom allocators, static allocation options, and careful memory management for embedded use.
Thread Safe
Mutex-protected operations safe for multi-threaded embedded applications and RTOS environments.
Cross Platform
Works on Linux, embedded Linux, FreeRTOS, Arduino, and other POSIX-compatible systems.
Pattern Compliant
100% compliant with JavaScript SDK patterns while optimized for C and embedded constraints.
Real-time Ready
Deterministic memory usage and timing suitable for real-time and safety-critical applications.
Installation
CMake Build
git clone https://github.com/jyswee/oddsockets-c-sdk.git
cd oddsockets-c-sdk
mkdir build && cd build
cmake ..
make
sudo make install
Dependencies
# Ubuntu/Debian
sudo apt-get install libcurl4-openssl-dev libwebsockets-dev libssl-dev
# CentOS/RHEL
sudo yum install libcurl-devel libwebsockets-devel openssl-devel
# macOS
brew install curl libwebsockets openssl
Manual Installation
# Compile manually
gcc -std=c99 -Wall -Wextra \
-I./src \
-lcurl -lwebsockets -lssl -lcrypto -lpthread \
src/oddsockets.c \
src/manager_discovery.c \
src/websocket_client.c \
src/message_validator.c \
src/json_parser.c \
src/http_client.c \
your_app.c -o your_app
Embedded Integration
For embedded systems, copy these files to your project:
src/oddsockets.h- Main headersrc/oddsockets.c- Main implementationsrc/manager_discovery.c- Manager discoverysrc/websocket_client.c- WebSocket clientsrc/message_validator.c- Message validationsrc/json_parser.c- JSON parsingsrc/http_client.c- HTTP client
# Cross-compile for ARM
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/arm-linux-gnueabihf.cmake ..
make
Quick Start
Basic Usage
#include "oddsockets.h"
int main() {
// Initialize configuration
oddsockets_config_t config;
oddsockets_config_init(&config, "ak_live_1234567890abcdef");
// Create client
oddsockets_client_t* client = oddsockets_create(&config);
// Connect to platform
oddsockets_connect(client);
// Create and subscribe to channel
oddsockets_channel_t* channel = oddsockets_channel_create(client, "my-channel");
oddsockets_channel_subscribe(channel, on_message, NULL, NULL);
// Publish a message
oddsockets_channel_publish(channel, "Hello from C SDK!", NULL);
// Event loop
while (oddsockets_get_state(client) == ODDSOCKETS_STATE_CONNECTED) {
oddsockets_process_events(client);
usleep(10000); // 10ms
}
// Cleanup
oddsockets_channel_destroy(channel);
oddsockets_destroy(client);
return 0;
}
Message Callback
void on_message(const char* channel_name, const char* message, void* user_data) {
printf("Received on %s: %s\n", channel_name, message);
}
void on_connection_state(oddsockets_state_t state, void* user_data) {
printf("Connection state: %s\n", oddsockets_state_string(state));
}
void on_error(oddsockets_error_t error, const char* message, void* user_data) {
printf("Error %d: %s\n", error, message);
}
Configuration
Client Configuration
oddsockets_config_t config;
oddsockets_config_init(&config, "your-api-key");
// Optional configuration
strncpy(config.user_id, "user123", sizeof(config.user_id) - 1);
config.auto_connect = true;
config.reconnect_attempts = 5;
config.reconnect_delay_ms = 1000;
config.connection_timeout_ms = 10000;
config.enable_ssl = true;
config.ssl_verify_peer = true;
// Callbacks
config.connection_callback = on_connection_state;
config.error_callback = on_error;
config.log_callback = on_log;
config.log_level = ODDSOCKETS_LOG_INFO;
Channel Options
// Subscribe options
oddsockets_subscribe_options_t subscribe_options = {
.max_history = 100,
.retain_history = true,
.enable_presence = false
};
oddsockets_channel_subscribe(channel, callback, user_data, &subscribe_options);
// Publish options
oddsockets_publish_options_t publish_options = {
.ttl_seconds = 3600,
.metadata = "priority:high",
.store_in_history = true
};
oddsockets_channel_publish(channel, message, &publish_options);
Examples
Explore comprehensive examples demonstrating the OddSockets C SDK in embedded and IoT environments:
Embedded Systems Integration
FreeRTOS Integration
#include "FreeRTOS.h"
#include "task.h"
#include "oddsockets.h"
void oddsockets_task(void *pvParameters) {
oddsockets_config_t config;
oddsockets_config_init(&config, "your-api-key");
// Use FreeRTOS heap
oddsockets_set_memory_functions(pvPortMalloc, vPortFree, pvPortRealloc);
oddsockets_client_t* client = oddsockets_create(&config);
while (1) {
oddsockets_process_events(client);
vTaskDelay(pdMS_TO_TICKS(10)); // 10ms delay
}
}
void app_main() {
xTaskCreate(oddsockets_task, "oddsockets", 4096, NULL, 5, NULL);
}
Arduino/ESP32 Integration
#include
#include "oddsockets.h"
const char* ssid = "your-wifi";
const char* password = "your-password";
oddsockets_client_t* client;
void setup() {
Serial.begin(115200);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
// Initialize OddSockets
oddsockets_config_t config;
oddsockets_config_init(&config, "your-api-key");
client = oddsockets_create(&config);
oddsockets_connect(client);
}
void loop() {
oddsockets_process_events(client);
delay(10);
}
Static Memory Allocation
// Enable static allocation at compile time
#define ODDSOCKETS_ENABLE_STATIC_ALLOCATION
// Pre-allocated memory pools
static uint8_t client_memory[ODDSOCKETS_CLIENT_SIZE];
static uint8_t channel_memory[ODDSOCKETS_MAX_CHANNELS][ODDSOCKETS_CHANNEL_SIZE];
// Custom allocator for deterministic memory usage
void* embedded_malloc(size_t size) {
// Your custom allocation logic
return get_from_memory_pool(size);
}
void embedded_free(void* ptr) {
// Your custom deallocation logic
return_to_memory_pool(ptr);
}
int main() {
// Set custom memory functions
oddsockets_set_memory_functions(embedded_malloc, embedded_free, embedded_realloc);
// Rest of your application
}
Enhanced Features
Enhanced (Slack-like) events layer on top of the core pub/sub. The send side is a set of free functions taking the client handle — each returns ODDSOCKETS_SUCCESS and emits a real worker event over the live socket. The matching broadcast arrives on oddsockets_on(client, "<event>", ...) as a JSON payload string. As with all C SDK I/O, pump oddsockets_process_events() to service the event loop.
Typing & reactions
#include "oddsockets.h"
#include "enhanced_features.h"
/* Raw event listeners: enhanced broadcasts arrive here as JSON strings. */
static void on_typing(const char* event, const char* payload, void* user_data) {
printf("typing: %s\n", payload);
}
static void on_reaction(const char* event, const char* payload, void* user_data) {
printf("reaction: %s\n", payload);
}
static void on_message(const char* channel, const char* message, void* user_data) {}
oddsockets_config_t config;
oddsockets_config_init(&config, "YOUR_API_KEY");
strncpy(config.user_id, "alice", sizeof(config.user_id) - 1);
oddsockets_client_t* client = oddsockets_create(&config);
/* Join the scoped room so enhanced broadcasts are delivered. */
oddsockets_channel_t* ch = oddsockets_channel_create(client, "room-42");
oddsockets_channel_subscribe(ch, on_message, NULL, NULL);
/* Receive-path */
oddsockets_on(client, "user_typing", on_typing, NULL);
oddsockets_on(client, "reaction_added", on_reaction, NULL);
/* Send-path */
oddsockets_start_typing(client, "alice", "room-42");
oddsockets_add_reaction(client, "msg-1", "room-42", ":thumbsup:", "alice", "Alice");
/* Drive the event loop to flush sends and dispatch broadcasts. */
for (int i = 0; i < 200; i++) { oddsockets_process_events(client); usleep(5000); }
Event surface
- Typing —
oddsockets_start_typing(client, user_id, channel),oddsockets_stop_typing(client, user_id, channel)→ broadcastuser_typing,user_stopped_typing - Reactions —
oddsockets_add_reaction(client, message_id, channel, emoji, user_id, user_name),oddsockets_remove_reaction(client, message_id, channel, emoji, user_id)→ broadcastreaction_added,reaction_removed
The C enhanced surface is deliberately focused on typing and reactions. Any other worker event your channel emits is still available directly on oddsockets_on(client, "<event>", ...).
Challenges & Leaderboards
Challenges, leaderboards and achievements build on the same live socket as the enhanced surface. Each send function takes the client handle plus a single JSON payload string emitted verbatim to the worker. Query functions such as oddsockets_get_standings receive the worker's reply on a <event>_success event, while progress and achievement calls are fire-and-forget with no acknowledgement. Inbound broadcasts arrive on the client event surface — subscribe with oddsockets_on(client, "<event>", ...).
Run a challenge
#include "oddsockets.h"
#include "enhanced_features.h"
/* Ack + broadcast listeners: replies arrive here as JSON strings. */
static void on_standings(const char* event, const char* payload, void* user_data) {
printf("standings: %s\n", payload);
}
oddsockets_on(client, "challenge_standings_success", on_standings, NULL);
/* Create a challenge, report progress, query standings, then finalise. */
oddsockets_create_challenge(client, "{\"challengeId\":\"c1\",\"metric\":\"score\",\"ranked\":true}");
oddsockets_report_progress(client, "{\"challengeId\":\"c1\",\"value\":42}");
oddsockets_get_standings(client, "{\"challengeId\":\"c1\",\"limit\":10}");
oddsockets_complete_challenge(client, "{\"challengeId\":\"c1\",\"outcome\":\"completed\"}");
/* Drive the event loop to flush sends and dispatch replies. */
for (int i = 0; i < 200; i++) { oddsockets_process_events(client); usleep(5000); }
Send-path functions
oddsockets_create_challenge(client, payload_json)— create a challenge / leaderboard. Ackchallenge_create_success.oddsockets_report_progress(client, payload_json)— fire-and-forget metric progress. No ack.oddsockets_complete_challenge(client, payload_json)— finalise with anoutcome. Ackchallenge_complete_success.oddsockets_unlock_achievement(client, payload_json)— fire-and-forget; passpercentComplete(0–100). No ack.oddsockets_get_standings(client, payload_json)— request top-N + caller rank. Ackchallenge_standings_success.oddsockets_get_achievements(client, payload_json)— query achievement state. Ackachievement_state.oddsockets_send_challenge_invite(client, payload_json)— directed invite to another user. Ackchallenge_invite_success.oddsockets_reply_challenge_invite(client, payload_json)— accept / decline an invite. Ackchallenge_reply_success.oddsockets_cancel_challenge_invite(client, payload_json)— cancel a sent invite. Ackchallenge_invite_cancel_success.oddsockets_get_challenge_invites(client, payload_json)— list pending invites (passNULLor"{}"). Ackchallenge_invites.
Completion outcomes
The outcome field passed to oddsockets_complete_challenge is one of:
completed— win (rank 1)failed— losstied— drawconceded— resign / concedeexpired— timed out
Progressive achievements
oddsockets_unlock_achievement always emits the wire event achievement_unlock; the worker is authoritative and derives the outbound broadcast from percentComplete: a value < 100 broadcasts achievement_progress (status in_progress), while >= 100 or an omitted value broadcasts achievement_unlock (status unlocked). Do not emit achievement_progress yourself.
Inbound events
Subscribe to these on the client with oddsockets_on(client, "<event>", ...):
- Room broadcasts —
challenge_progress,leaderboard_rank_change,challenge_complete,achievement_unlock,achievement_progress - Directed (per-user) events —
challenge_invited,challenge_reply_received,challenge_invite_cancelled
Performance & Compatibility
OddSockets C SDK delivers exceptional performance optimized for embedded and resource-constrained environments:
Platform Support
- Linux (x86, ARM, MIPS)
- Embedded Linux
- FreeRTOS
- Arduino/ESP32
- Zephyr RTOS
- Custom RTOS
Compiler Support
- GCC 7+ (C99)
- Clang 8+
- ARM GCC
- ESP-IDF
- Cross-compilation ready
Memory Optimization Features
Custom Allocators
Pluggable memory management for specialized embedded memory systems.
Static Allocation
Compile-time memory allocation for deterministic real-time systems.
Memory Pools
Pre-allocated memory pools to avoid fragmentation in long-running systems.
Memory Tracking
Built-in memory usage tracking and leak detection for development.