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:
- Look for Topics in the left sidebar (or click here)
- Click to expand the topics tree.
- 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:
Discovery Service (ACDS):
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:
- 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
- Read this main page to understand the project overview
- Visit Topic Categories to browse detailed guides
- Check out Getting Started section below for code examples
- 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?
- 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.
- 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.
- Follow cross-references: Click on
@ref links in documentation (like Build System or Cryptography) to navigate between related concepts.
- Review "See also" sections: Most documentation blocks include "See also" references at the bottom that link to related topics, modules, or functions.
- 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:
- Initialize the logging system with log_init()
- Initialize common subsystems with asciichat_common_init()
- Initialize platform-specific components (audio, video, network)
- Set up cryptographic context and perform handshake
- Start audio/video capture and network streaming
- Handle incoming packets and render to terminal
Client Workflow: Connect, Handshake, Send Video, Display ASCII
Complete client workflow from connection to displaying ASCII frames:
socket_t sockfd = server_connection_connect(
"127.0.0.1", 27224);
if (sockfd == INVALID_SOCKET_VALUE) {
log_error("Failed to connect to server");
return ERROR_NETWORK_CONNECT;
}
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");
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
};
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;
}
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 *);
*(uint32_t *)frame_data = htonl(width);
*(uint32_t *)(frame_data + sizeof(uint32_t)) = htonl(height);
memcpy(frame_data + sizeof(uint32_t) * 2, webcam_pixels,
(size_t)width * (size_t)height * sizeof(rgb_pixel_t));
SAFE_FREE(frame_data);
log_debug("Sent %dx%d webcam frame to server", width, height);
packet_envelope_t envelope;
crypto_ready, &envelope);
if (result == PACKET_RECV_OK && envelope.type == PACKET_TYPE_ASCII_FRAME) {
ascii_frame_packet_t *header = (ascii_frame_packet_t *)envelope.data;
header->width = ntohl(header->width);
header->height = ntohl(header->height);
header->original_size = ntohl(header->original_size);
header->checksum = ntohl(header->checksum);
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';
uint32_t actual_crc = asciichat_crc32(ascii_frame, header->original_size);
if (actual_crc == header->checksum) {
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)
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)
Render ASCII frame to display.
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.
Server Workflow: Receive Video, Convert to ASCII, Broadcast
Complete server workflow showing client connection, video reception, ASCII conversion, and broadcasting:
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;
}
uint32_t client_id = allocate_client_id();
client_info_t *client = create_client_info(client_id, client_sockfd);
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);
bool crypto_ready = crypto_server_client_is_ready(client);
const crypto_context_t *crypto_ctx = crypto_server_get_client_context(client);
packet_envelope_t envelope;
crypto_ready, &envelope);
if (result == PACKET_RECV_OK && envelope.type == PACKET_TYPE_IMAGE_FRAME) {
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);
video_frame_store(client->incoming_video_buffer, envelope.data, envelope.len);
atomic_store(&client->is_sending_video, true);
}
for (int i = 0; i < MAX_CLIENTS; i++) {
if (!atomic_load(&target_client->active)) {
continue;
}
unsigned short term_width = target_client->terminal_caps.width;
unsigned short term_height = target_client->terminal_caps.height;
size_t ascii_size = 0;
target_client->client_id, term_width, term_height, &ascii_size);
if (!ascii_frame) {
continue;
}
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
};
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);
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);
}
for (int i = 0; i < MAX_CLIENTS; i++) {
if (!atomic_load(&target_client->active)) {
continue;
}
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) {
size_t audio_size = sample_count * sizeof(float);
}
}
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.
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.
client_info_t clients[MAX_CLIENTS]
Array of client_info_t structures (backing storage)
Important Notes
Encryption:
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