OddSockets C SDK

Official C SDK for OddSockets real-time messaging platform, optimized for embedded systems and IoT devices

Embedded Ready Low Memory Thread Safe High Performance Cross Platform

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

bash
git clone https://github.com/jyswee/oddsockets-c-sdk.git
cd oddsockets-c-sdk
mkdir build && cd build
cmake ..
make
sudo make install

Dependencies

bash
# 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

bash
# 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 header
  • src/oddsockets.c - Main implementation
  • src/manager_discovery.c - Manager discovery
  • src/websocket_client.c - WebSocket client
  • src/message_validator.c - Message validation
  • src/json_parser.c - JSON parsing
  • src/http_client.c - HTTP client
bash
# Cross-compile for ARM
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/arm-linux-gnueabihf.cmake ..
make

Quick Start

Basic Usage

c
#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

c
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

c
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

c
// 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

c
#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

c
#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

c
// 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

  • Typingoddsockets_start_typing(client, user_id, channel), oddsockets_stop_typing(client, user_id, channel) → broadcast user_typing, user_stopped_typing
  • Reactionsoddsockets_add_reaction(client, message_id, channel, emoji, user_id, user_name), oddsockets_remove_reaction(client, message_id, channel, emoji, user_id) → broadcast reaction_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. Ack challenge_create_success.
  • oddsockets_report_progress(client, payload_json) — fire-and-forget metric progress. No ack.
  • oddsockets_complete_challenge(client, payload_json) — finalise with an outcome. Ack challenge_complete_success.
  • oddsockets_unlock_achievement(client, payload_json) — fire-and-forget; pass percentComplete (0–100). No ack.
  • oddsockets_get_standings(client, payload_json) — request top-N + caller rank. Ack challenge_standings_success.
  • oddsockets_get_achievements(client, payload_json) — query achievement state. Ack achievement_state.
  • oddsockets_send_challenge_invite(client, payload_json) — directed invite to another user. Ack challenge_invite_success.
  • oddsockets_reply_challenge_invite(client, payload_json) — accept / decline an invite. Ack challenge_reply_success.
  • oddsockets_cancel_challenge_invite(client, payload_json) — cancel a sent invite. Ack challenge_invite_cancel_success.
  • oddsockets_get_challenge_invites(client, payload_json) — list pending invites (pass NULL or "{}"). Ack challenge_invites.

Completion outcomes

The outcome field passed to oddsockets_complete_challenge is one of:

  • completed — win (rank 1)
  • failed — loss
  • tied — draw
  • conceded — resign / concede
  • expired — 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 broadcastschallenge_progress, leaderboard_rank_change, challenge_complete, achievement_unlock, achievement_progress
  • Directed (per-user) eventschallenge_invited, challenge_reply_received, challenge_invite_cancelled

Performance & Compatibility

OddSockets C SDK delivers exceptional performance optimized for embedded and resource-constrained environments:

<50ms
Latency
<64KB
RAM Usage
<128KB
Flash Usage
99.9%
Uptime

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.