ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
ascii-chat API Documentation

Introduction

ascii-chat is a real-time terminal-based video chat application that converts video streams to ASCII art for display in terminals. It supports multiple clients, audio streaming, and end-to-end encryption.

This documentation provides comprehensive API reference and architectural guidance for developers working with ascii-chat. Whether you're integrating ascii-chat into your application, extending its functionality, or contributing to the project, this documentation will help you understand the codebase structure and implementation details.

Note
Getting Started? We recommend starting with the Build System topic to understand how to compile ascii-chat on Windows, Linux, and macOS, configure the build system, and set up your development environment.
Warning
Important: When exploring this documentation, navigate to Topics in the sidebar. Many topic pages have "README" in their title and provide comprehensive subsystem overviews. These are excellent entry points for understanding major subsystems. You can also start with Topic Categories for an organized index. See the Exploring the Documentation section below for detailed navigation guidance.

Exploring the Documentation

Understanding the Sidebar

The left sidebar is your primary navigation tool. It contains the following main sections:

  • ascii-chat API Documentation - The main landing page (you are here)
  • Topics - Comprehensive architectural documentation (the most important section for understanding the system)
  • Topic Categories - Index page that lists all topics organized by category (start here to browse topics!)
  • Data Structures - All struct and typedef definitions organized by functionality
  • Files - Browse source files organized by directory structure
  • Examples - Code examples and usage patterns
  • Search - Use the search bar at the top of the page to find anything quickly

Finding Topics in the Sidebar

Topics are directly accessible in the sidebar. To access them:

  1. Look for Topics in the left sidebar (or click here)
  2. Click to expand the topics tree.
  3. Each topic has a tree to expand with files, functions, enums and structs, custom documentation pages, etc.

Alternatively, you can start with Topic Categories in the sidebar, which provides an organized index of all topics grouped by category. This is an excellent starting point!

The Topics page includes comprehensive architectural guides with names like:

Warning
Important: These links go to the full topic page that has all the topic's functions and enums and structs etc documentation listed first, before the documentation that you wanted when you clicked the link... either scroll down to where the custom documentation starts, or expand the topic in the sidebar to see a direct link to the page you desire (in the sidebar tree, it will be down past the topic's files and structs).
Note
Pro Tip: Many topic pages have "README" in their title and/or descriptive names with capitalized titles (Pages Titled Like This). These are comprehensive overview documents that explain entire subsystems in detail.
Pro Tip: Many topic pages have the same name as their topic. For instance the Packet Queue topic has a page called "Packet Queue" that explains the code in more detail than the header file documentation does. Look for these pages.

How to Navigate the Sidebar

Looking for architectural documentation?

  • Click Topics in the sidebar to see all topic pages
  • Or start with Topic Categories for an organized index of all topics
  • Look for topic pages with "README" in the title for comprehensive subsystem overviews

Looking for a specific function or struct?

  • Use the search bar at the top of the page (fastest method)
  • Or check Data Structures to find type definitions
  • Or browse Files to see all functions in a particular source file

Looking for implementation details? Check the sidebar!

  • Check Files to browse source files by directory
  • Review Data Structures to understand type definitions
  • Read Topics for architectural context, then drill into specific files
  • Check Examples for code samples and usage patterns

Topics: Comprehensive Architectural Documentation

Topics are detailed guides that explain subsystems comprehensively. They combine:

  • Architectural overviews and design rationale
  • API documentation with usage examples
  • Integration patterns and best practices
  • Performance considerations and optimization notes

Access topics directly via Topics in the sidebar, or start with Topic Categories in the sidebar for an organized index of all topics grouped by category.

Key topics to explore:

Getting Started:

  • Build System: CMake configuration, cross-platform compilation, build types, platform-specific gotchas, static builds, and build optimizations (start here if new to the project!)
  • Platform Abstraction Layer README: Complete cross-platform abstraction guide covering threads, mutexes, sockets, terminal I/O, crash handling, and OS portability (essential for understanding Windows/Linux/macOS support!)
  • Testing Framework: Test infrastructure, test runner, Docker testing, coverage

Core Infrastructure:

Cryptography:

Data Structures:

Media Processing:

Network Layer:

Client Application:

Server Application:

For more details, explore the Topic Categories page, which provides links to all topics organized by category. Key topics include:

  • Build System: Complete build documentation, CMake configuration, cross-platform compilation, build types, and optimization
  • Platform Abstraction Layer README: Comprehensive guide to cross-platform abstractions, threading, sockets, terminal I/O, and OS portability
  • Cryptography: Encryption architecture, cryptographic operations, and security details
  • Handshake Module README: How client and server establish secure encrypted sessions using X25519 key exchange
  • Keys Module README: SSH/GPG key handling, key validation, and authentication mechanisms
  • Audio/Video Networking: Media packet APIs, compression, and streaming protocols
  • Network I/O: Packet I/O operations, socket management, and network abstractions
Note
Finding Topics: All topics are accessible via Topics in the sidebar. Many topics have "README" in their title and/or descriptive names with capitalized titles (Pages Titled Like This), indicating they are comprehensive subsystem documentation. You can also start with Topic Categories for an organized index, or use the search bar at the top of the page to find topics.

Development & Debugging:

Quick Start

New to ascii-chat? Start here:

  1. Set up your build environment: Read Build System to learn how to compile ascii-chat on your platform (Windows, Linux, or macOS) and understand the CMake configuration, build types, and platform-specific considerations
  2. Read this main page to understand the project overview
  3. Visit Topic Categories to browse detailed guides
  4. Check out Getting Started section below for code examples
  5. Explore Topics for architectural documentation and Files or Data Structures for API reference

Finding Code Elements

Looking for a specific function or structure?

  • Use the search bar at the top of the page (Ctrl+F / Cmd+F in browser)
  • Browse Data Structures to find related types grouped together
  • Check Files to see all functions in a particular source file
  • Review Topics for architectural context and usage examples

Understanding the System

Want to understand how things work together?

  1. Start with Topics: Navigate to Topics in the sidebar, or visit Topic Categories for an organized index. Topics provide comprehensive architectural documentation that explains how subsystems work together.
  2. Look for README pages: Many topics have "README" in their title (e.g., "Build System README", "Cryptography Module README"). These are the most comprehensive guides and are excellent entry points.
  3. Follow cross-references: Click on @ref links in documentation (like Build System or Cryptography) to navigate between related concepts.
  4. Review "See also" sections: Most documentation blocks include "See also" references at the bottom that link to related topics, modules, or functions.
  5. Check Integration sections: Topic pages include "Integration" sections that explain how modules interact with each other in the larger system.

Contributing to the Project

Planning to contribute code?

  • Set up your build environment: Read Build System to configure your development environment and understand build types, CMake presets, and testing setup
  • Read Topic Pages to understand the architecture before making changes
  • Review Best Practices sections for coding standards and patterns
  • Check
    Note
    @note tags that look like this and
    Warning
    @warning tags that look like this in documentation for important details
  • Follow the existing documentation style when adding new code and format with clang-format

Library Structure

The library is organized into several major modules:

Core Library

Platform Abstractions

  • Platform Abstraction Layer README - Comprehensive guide to cross-platform abstractions for threads, mutexes, sockets, terminal I/O, crash handling, and OS portability (Windows/Linux/macOS)
  • Platform Layer - API reference for platform abstractions
  • Webcam Capture - Cross-platform webcam capture functionality

Core Libraries

Network Layer

Cryptography

Media Processing

Utilities

  • Utilities - String manipulation, path handling, IP parsing, math utilities, UTF-8 support

Getting Started

Note
Before diving into the code, make sure you've read the Build System topic to understand how to compile and configure ascii-chat for your platform.

This section provides a quick overview of how to use the ascii-chat library. For detailed documentation on each component, see the Topic Categories page.

Typical Workflow

The typical workflow for using the ascii-chat library:

  1. Initialize the logging system with log_init()
  2. Initialize common subsystems with asciichat_common_init()
  3. Initialize platform-specific components (audio, video, network)
  4. Set up cryptographic context and perform handshake
  5. Start audio/video capture and network streaming
  6. Handle incoming packets and render to terminal

Client Workflow: Connect, Handshake, Send Video, Display ASCII

Complete client workflow from connection to displaying ASCII frames:

// STEP 1: Connect to server and perform crypto handshake
// From src/client/main.c and src/client/crypto.c
// Connect to server
socket_t sockfd = server_connection_connect("127.0.0.1", 27224);
if (sockfd == INVALID_SOCKET_VALUE) {
log_error("Failed to connect to server");
}
// Perform cryptographic handshake with server
// This establishes encrypted session using X25519 key exchange
asciichat_error_t handshake_result = crypto_client_perform_handshake();
if (handshake_result != ASCIICHAT_OK) {
log_error("Crypto handshake failed");
return handshake_result;
}
log_info("Encrypted session established with server");
// Send client capabilities to server (terminal size, color support, etc.)
client_capabilities_packet_t caps = {
.terminal_width = htons(80),
.terminal_height = htons(24),
.supports_color = 1,
.color_mode = COLOR_MODE_TRUECOLOR,
.render_mode = RENDER_MODE_HALF_BLOCK
};
// STEP 2: Capture webcam frame and send to server
// From src/client/capture.c
// Capture RGB frame from webcam (640x480 in this example)
rgb_pixel_t *webcam_pixels = NULL;
int width = 640, height = 480;
if (webcam_capture_frame(&webcam_pixels, &width, &height) != 0) {
log_error("Failed to capture webcam frame");
return ERROR_WEBCAM;
}
// Package frame: [width:4][height:4][rgb_data:w*h*3]
size_t frame_size = sizeof(uint32_t) * 2 + (size_t)width * (size_t)height * sizeof(rgb_pixel_t);
uint8_t *frame_data = SAFE_MALLOC(frame_size, uint8_t *);
// Write dimensions in network byte order
*(uint32_t *)frame_data = htonl(width);
*(uint32_t *)(frame_data + sizeof(uint32_t)) = htonl(height);
// Copy pixel data
memcpy(frame_data + sizeof(uint32_t) * 2, webcam_pixels,
(size_t)width * (size_t)height * sizeof(rgb_pixel_t));
// Send image frame to server (automatically encrypted after handshake)
threaded_send_packet(PACKET_TYPE_IMAGE_FRAME, frame_data, frame_size, 0);
SAFE_FREE(frame_data);
log_debug("Sent %dx%d webcam frame to server", width, height);
// STEP 3: Receive ASCII frame from server and display
// From src/client/protocol.c
// Receive packet (automatically decrypted)
bool crypto_ready = crypto_client_is_ready();
packet_recv_result_t result = receive_packet_secure(sockfd, (void *)crypto_ctx,
crypto_ready, &envelope);
if (result == PACKET_RECV_OK && envelope.type == PACKET_TYPE_ASCII_FRAME) {
// Parse ASCII frame header
header->width = ntohl(header->width);
header->height = ntohl(header->height);
header->original_size = ntohl(header->original_size);
header->checksum = ntohl(header->checksum);
// Extract ASCII art string
const char *frame_data_ptr = (const char *)envelope.data + sizeof(ascii_frame_packet_t);
char *ascii_frame = SAFE_MALLOC(header->original_size + 1, char *);
memcpy(ascii_frame, frame_data_ptr, header->original_size);
ascii_frame[header->original_size] = '\0';
// Verify integrity
uint32_t actual_crc = asciichat_crc32(ascii_frame, header->original_size);
if (actual_crc == header->checksum) {
// Display ASCII art in terminal
display_render_frame(ascii_frame, false);
log_debug("Displayed %ux%u ASCII frame", header->width, header->height);
}
SAFE_FREE(ascii_frame);
}
void buffer_pool_free(buffer_pool_t *pool, void *data, size_t size)
Free a buffer back to the pool (lock-free)
asciichat_error_t threaded_send_packet(packet_type_t type, const void *data, size_t len)
Thread-safe packet transmission.
const crypto_context_t * crypto_client_get_context(void)
Get crypto context for encryption/decryption.
bool crypto_client_is_ready(void)
Check if crypto handshake is ready.
void display_render_frame(const char *frame_data, bool is_snapshot_frame)
Render ASCII frame to display.
Definition display.c:353
unsigned int uint32_t
Definition common.h:58
#define SAFE_FREE(ptr)
Definition common.h:320
#define SAFE_MALLOC(size, cast)
Definition common.h:208
unsigned char uint8_t
Definition common.h:56
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:46
@ ERROR_NETWORK_CONNECT
Definition error_codes.h:71
@ ASCIICHAT_OK
Definition error_codes.h:48
@ ERROR_WEBCAM
Definition error_codes.h:61
#define log_error(...)
Log an ERROR message.
#define log_info(...)
Log an INFO message.
#define log_debug(...)
Log a DEBUG message.
void * allocated_buffer
Buffer that needs to be freed by caller (may be NULL if not allocated)
Definition packet.h:990
size_t allocated_size
Size of allocated buffer in bytes.
Definition packet.h:992
void * data
Packet payload data (decrypted and decompressed if applicable)
Definition packet.h:984
packet_recv_result_t receive_packet_secure(socket_t sockfd, void *crypto_ctx, bool enforce_encryption, packet_envelope_t *envelope)
Receive a packet with decryption and decompression support.
Definition packet.c:568
packet_type_t type
Packet type (from packet_types.h)
Definition packet.h:982
packet_recv_result_t
Packet reception result codes.
Definition packet.h:1003
#define COLOR_MODE_TRUECOLOR
24-bit truecolor mode
Definition options.h:162
@ PACKET_TYPE_IMAGE_FRAME
Complete RGB image with dimensions.
Definition packet.h:288
@ PACKET_TYPE_ASCII_FRAME
Complete ASCII frame with all metadata.
Definition packet.h:286
@ PACKET_TYPE_CLIENT_CAPABILITIES
Client reports terminal capabilities.
Definition packet.h:293
int socket_t
Socket handle type (POSIX: int)
Definition socket.h:50
#define INVALID_SOCKET_VALUE
Invalid socket value (POSIX: -1)
Definition socket.h:52
@ RENDER_MODE_HALF_BLOCK
Unicode half-block characters (mixed foreground/background)
Definition terminal.h:473
#define asciichat_crc32(data, len)
Main CRC32 dispatcher macro - use this in application code.
Definition crc32.h:144
ASCII frame packet structure (Packet Type 2)
Definition packet.h:740
Cryptographic context structure.
Packet envelope containing received packet data.
Definition packet.h:980

Server Workflow: Receive Video, Convert to ASCII, Broadcast

Complete server workflow showing client connection, video reception, ASCII conversion, and broadcasting:

// STEP 1: Accept client connection and perform crypto handshake
// From src/server/main.c and src/server/crypto.c
// Accept incoming client connection
socket_t client_sockfd = socket_accept(listen_sockfd, NULL, NULL);
if (client_sockfd == INVALID_SOCKET_VALUE) {
log_error("Failed to accept client connection");
return ERROR_NETWORK_ACCEPT;
}
// Assign client ID and create client info structure
uint32_t client_id = allocate_client_id();
client_info_t *client = create_client_info(client_id, client_sockfd);
// Perform server-side crypto handshake
asciichat_error_t handshake_result = crypto_server_perform_handshake(client);
if (handshake_result != ASCIICHAT_OK) {
log_error("Crypto handshake failed for client %u", client_id);
close_client_connection(client);
return handshake_result;
}
log_info("Client %u: Encrypted session established", client_id);
// STEP 2: Receive video frame from client
// From src/server/protocol.c
// Receive packet from client (automatically decrypted)
bool crypto_ready = crypto_server_client_is_ready(client);
const crypto_context_t *crypto_ctx = crypto_server_get_client_context(client);
packet_recv_result_t result = receive_packet_secure(client_sockfd, (void *)crypto_ctx,
crypto_ready, &envelope);
if (result == PACKET_RECV_OK && envelope.type == PACKET_TYPE_IMAGE_FRAME) {
// Parse image frame: [width:4][height:4][rgb_data:w*h*3]
uint32_t img_width = ntohl(*(uint32_t *)envelope.data);
uint32_t img_height = ntohl(*(uint32_t *)(envelope.data + sizeof(uint32_t)));
rgb_pixel_t *pixels = (rgb_pixel_t *)(envelope.data + sizeof(uint32_t) * 2);
log_debug("Client %u: Received %ux%u video frame", client_id, img_width, img_height);
// Store frame in client's incoming video buffer
video_frame_store(client->incoming_video_buffer, envelope.data, envelope.len);
// Mark client as sending video
atomic_store(&client->is_sending_video, true);
}
// STEP 3: Convert video to ASCII and broadcast to all clients
// From src/server/stream.c and src/server/render.c
// For each connected client, generate personalized ASCII frame
for (int i = 0; i < MAX_CLIENTS; i++) {
client_info_t *target_client = &g_client_manager.clients[i];
if (!atomic_load(&target_client->active)) {
continue;
}
// Get target client's terminal dimensions
unsigned short term_width = target_client->terminal_caps.width;
unsigned short term_height = target_client->terminal_caps.height;
// Mix video from ALL clients into composite for this target client
size_t ascii_size = 0;
target_client->client_id, term_width, term_height, &ascii_size);
if (!ascii_frame) {
continue; // No video sources available yet
}
// Package ASCII frame with header
ascii_frame_packet_t packet_header = {
.width = htonl(term_width),
.height = htonl(term_height),
.original_size = htonl(ascii_size),
.compressed_size = 0,
.checksum = htonl(asciichat_crc32(ascii_frame, ascii_size)),
.flags = 0
};
// Combine header + ASCII data into single packet
size_t total_size = sizeof(packet_header) + ascii_size;
uint8_t *packet_data = SAFE_MALLOC(total_size, uint8_t *);
memcpy(packet_data, &packet_header, sizeof(packet_header));
memcpy(packet_data + sizeof(packet_header), ascii_frame, ascii_size);
// Send to target client (automatically encrypted)
threaded_send_packet_to_client(target_client, PACKET_TYPE_ASCII_FRAME,
packet_data, total_size);
log_debug("Sent %zub ASCII frame to client %u", total_size, target_client->client_id);
SAFE_FREE(ascii_frame);
SAFE_FREE(packet_data);
}
// STEP 4: Mix and broadcast audio to all clients
// From src/server/mixer.c
// Mix audio from all clients (excluding target client's own audio)
for (int i = 0; i < MAX_CLIENTS; i++) {
client_info_t *target_client = &g_client_manager.clients[i];
if (!atomic_load(&target_client->active)) {
continue;
}
// Get mixed audio for this client (excludes their own audio)
float mixed_audio[AUDIO_SAMPLES_PER_PACKET];
int sample_count = mixer_get_mixed_audio_for_client(target_client->client_id,
mixed_audio, AUDIO_SAMPLES_PER_PACKET);
if (sample_count > 0) {
// Send audio packet to client
size_t audio_size = sample_count * sizeof(float);
queue_audio_for_client(target_client, mixed_audio, audio_size);
}
}
#define MAX_CLIENTS
Maximum possible clients (static array size) - actual runtime limit set by –max-clients (1-32)
Definition limits.h:23
uint32_t width
Terminal width in characters.
Definition packet.h:742
size_t len
Length of payload data in bytes.
Definition packet.h:986
#define AUDIO_SAMPLES_PER_PACKET
Samples per audio packet (256 samples)
Definition packet.h:233
socket_t socket_accept(socket_t sock, struct sockaddr *addr, socklen_t *addrlen)
Accept an incoming connection.
client_manager_t g_client_manager
Global client manager singleton - central coordination point.
char * create_mixed_ascii_frame_for_client(uint32_t target_client_id, unsigned short width, unsigned short height, bool wants_stretch, size_t *out_size, bool *out_grid_changed, int *out_sources_count)
Generate personalized ASCII frame for a specific client.
Definition stream.c:959
int queue_audio_for_client(client_info_t *client, const void *audio_data, size_t data_size)
Queue ASCII frame for delivery to specific client.
Definition stream.c:1172
Per-client state structure for server-side client management.
terminal_capabilities_t terminal_caps
atomic_uint client_id
video_frame_buffer_t * incoming_video_buffer
atomic_bool is_sending_video
atomic_bool active
client_info_t clients[MAX_CLIENTS]
Array of client_info_t structures (backing storage)

Important Notes

Encryption:

  • All packets are automatically encrypted after the crypto handshake
  • Use threaded_send_packet() or receive_packet_secure() for encrypted I/O
  • Crypto context is per-connection (client or server)
  • Keys are automatically zeroed on crypto_destroy()

Compression:

  • Large packets (>100KB) are automatically compressed
  • Compression is transparent - handled by packet I/O functions
  • Use av_send_*() functions for media packets with compression

Client Capabilities:

  • Sent once after crypto handshake
  • Includes terminal size, color support, palette preferences
  • Server uses this to format output appropriately

Thread Safety:

Building Documentation

To build this documentation, you'll need Doxygen configured. See Build System for information on configuring the project with CMake, including documentation generation.

To build this documentation:

cmake --build build --target docs

The documentation will be generated in build/docs/html/index.html.

To open the documentation in your browser:

cmake --build build --target docs-open

For more information on the build system, including CMake configuration, build types, and platform-specific considerations, see Build System.

License

See the LICENSE.txt file for license information.

Links