|
ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
|
⚙️ Code shared throughout the library More...
Files | |
| file | common.c |
| 🔧 Core utilities: memory management, safe macros, and cross-platform helpers | |
| file | common.h |
| ⚙️ Common definitions, error codes, macros, and types shared throughout the application | |
| file | fps.c |
| ⏱️ FPS tracking utility implementation | |
| file | fps.h |
| ⏱️ FPS tracking utility for monitoring frame throughput across all threads | |
Data Structures | |
| struct | fps_t |
| FPS tracking state. More... | |
Macros | |
| #define | ASCII_CHAT_APP_NAME "ascii-chat" |
| Application name for key comments ("ascii-chat") | |
| #define | PLATFORM_MAX_PATH_LENGTH 4096 |
| #define | FATAL(code, ...) asciichat_fatal_with_context(code, __FILE__, __LINE__, __func__, ##__VA_ARGS__) |
| Exit with error code and custom message, with stack trace in debug builds. | |
| #define | ALLOC_MALLOC(size) malloc(size) |
| Return the minimum of two values. | |
| #define | ALLOC_CALLOC(count, size) calloc((count), (size)) |
| #define | ALLOC_REALLOC(ptr, size) realloc((ptr), (size)) |
| #define | ALLOC_FREE(ptr) free(ptr) |
| #define | ASCIICHAT_CHECK_AND_LOG(expr, ok_value, msg, ...) |
| Check result and log error if operation failed. | |
Typedefs | |
| typedef unsigned char | uint8_t |
| typedef unsigned short | uint16_t |
| typedef unsigned int | uint32_t |
| typedef unsigned long long | uint64_t |
Functions | |
| void | asciichat_fatal_with_context (asciichat_error_t code, const char *file, int line, const char *function, const char *format,...) |
| Exit with error code and context (used by FATAL macro) | |
| asciichat_error_t | asciichat_shared_init (const char *default_log_filename, bool is_client) |
| Initialize common subsystems shared by client and server. | |
| void | fps_init (fps_t *tracker, int expected_fps, const char *name) |
| Initialize FPS tracker. | |
| void | fps_init_with_interval (fps_t *tracker, int expected_fps, const char *name, uint64_t report_interval_us) |
| Initialize FPS tracker with custom report interval. | |
| void | fps_frame (fps_t *tracker, const struct timespec *current_time, const char *context) |
| Track a frame and detect lag conditions. | |
Memory Debugging Macros | |
| #define | SAFE_MALLOC(size, cast) |
| #define | SAFE_CALLOC(count, size, cast) |
| #define | SAFE_REALLOC(ptr, size, cast) |
| #define | TRACK_ALIGNED_ALLOC(ptr, size, file, line) ((void)0) |
| #define | SAFE_MALLOC_ALIGNED(size, alignment, cast) |
| #define | SAFE_MALLOC_SIMD(size, cast) SAFE_MALLOC_ALIGNED(size, 16, cast) |
| #define | SAFE_CALLOC_SIMD(count, size, cast) |
| #define | SAFE_FREE(ptr) |
| #define | SAFE_FCLOSE(fp) |
| #define | UNTRACKED_MALLOC(size, cast) |
| #define | UNTRACKED_FREE(ptr) |
| #define | SAFE_STRNCPY(dst, src, size) platform_strlcpy((dst), (src), (size)) |
| #define | SAFE_STRDUP(dst, src) |
| #define | SAFE_GETENV(name) platform_getenv(name) |
| #define | SAFE_SSCANF(str, format, ...) sscanf(str, format, __VA_ARGS__) |
| #define | SAFE_STRERROR(errnum) platform_strerror(errnum) |
| #define | SAFE_MEMCPY(dest, dest_size, src, count) platform_memcpy((dest), (dest_size), (src), (count)) |
| #define | SAFE_MEMSET(dest, dest_size, ch, count) platform_memset((dest), (dest_size), (ch), (count)) |
| #define | SAFE_MEMMOVE(dest, dest_size, src, count) platform_memmove((dest), (dest_size), (src), (count)) |
| #define | SAFE_STRCPY(dest, dest_size, src) platform_strcpy((dest), (dest_size), (src)) |
| #define | read_u16_unaligned bytes_read_u16_unaligned |
| #define | read_u32_unaligned bytes_read_u32_unaligned |
| #define | write_u16_unaligned bytes_write_u16_unaligned |
| #define | write_u32_unaligned bytes_write_u32_unaligned |
| #define | safe_size_mul bytes_safe_size_mul |
| #define | SAFE_SNPRINTF(buffer, buffer_size, ...) (size_t)safe_snprintf((buffer), (buffer_size), __VA_ARGS__) |
| #define | SAFE_BUFFER_SIZE(buffer_size, offset) ((offset) < 0 || (size_t)(offset) >= (buffer_size) ? 0 : (buffer_size) - (size_t)(offset)) |
| Safe buffer size calculation for snprintf. | |
| #define | THREAD_CREATE_OR_RETURN(thread, func, arg) |
| Create a thread or log error and return. | |
| #define | MUTEX_INIT_OR_RETURN(m) |
| Initialize a mutex or log error and return. | |
⚙️ Code shared throughout the library
This header provides core functionality used throughout ascii-chat:
Provides a reusable FPS tracking mechanism for monitoring real-time frame delivery rates across all client threads (data reception, webcam capture, audio capture, keepalive). Tracks frame intervals, detects lag conditions, and generates periodic FPS reports every 7-15 seconds.
The common module (lib/common.h, lib/common.c) provides fundamental infrastructure:
All application code should use these common definitions to ensure consistency, proper error handling, and debuggability.
ascii-chat uses a comprehensive error system (lib/asciichat_errno.h) that provides:
Each error includes rich contextual information:
SET_ERRNO: Set error with custom message
SET_ERRNO_SYS: Set error with system errno
HAS_ERRNO: Check if error occurred
PRINT_ERRNO_CONTEXT: Debug print error details
CLEAR_ERRNO: Clear error state
GET_ERRNO: Get current error code
Custom memory allocation macros with automatic leak detection in debug builds:
SAFE_MALLOC: Allocate memory with leak tracking
SAFE_CALLOC: Allocate zeroed memory
SAFE_REALLOC: Reallocate memory
SAFE_FREE: Free memory and set to NULL
When CMAKE_BUILD_TYPE=Debug and DEBUG_MEMORY is defined:
Leak Detection:
Allocation Logging:
Double-Free Detection:
Memory Reports:
Multi-level logging with rate limiting for high-frequency code:
Control via environment:
Output format:
For high-frequency code paths (e.g., video/audio processing at 60+ FPS):
Implementation:
Example (video processing loop at 60 FPS):
Usage:
Fixed-width integers (platform-independent):
Boolean (C99 style):
NULL pointer:
| #define ALLOC_CALLOC | ( | count, | |
| size | |||
| ) | calloc((count), (size)) |
| #define ALLOC_MALLOC | ( | size | ) | malloc(size) |
| #define ALLOC_REALLOC | ( | ptr, | |
| size | |||
| ) | realloc((ptr), (size)) |
| #define ASCII_CHAT_APP_NAME "ascii-chat" |
| #define ASCIICHAT_CHECK_AND_LOG | ( | expr, | |
| ok_value, | |||
| msg, | |||
| ... | |||
| ) |
#include <common.h>
Check result and log error if operation failed.
Consolidates the pattern:
Usage:
Definition at line 529 of file common.h.
| #define FATAL | ( | code, | |
| ... | |||
| ) | asciichat_fatal_with_context(code, __FILE__, __LINE__, __func__, ##__VA_ARGS__) |
#include <common.h>
Exit with error code and custom message, with stack trace in debug builds.
| code | Error code (asciichat_error_t) |
| ... | Custom message format string and arguments (printf-style) |
| #define MUTEX_INIT_OR_RETURN | ( | m | ) |
#include <common.h>
Initialize a mutex or log error and return.
| m | Pointer to mutex_t variable |
Handles common pattern: init mutex, log error if failed, then return -1. Example usage:
MUTEX_INIT_OR_RETURN(mutex); // Mutex initialized successfully, continue
Definition at line 462 of file common.h.
| #define read_u16_unaligned bytes_read_u16_unaligned |
| #define read_u32_unaligned bytes_read_u32_unaligned |
| #define SAFE_BUFFER_SIZE | ( | buffer_size, | |
| offset | |||
| ) | ((offset) < 0 || (size_t)(offset) >= (buffer_size) ? 0 : (buffer_size) - (size_t)(offset)) |
#include <common.h>
Safe buffer size calculation for snprintf.
Casts offset to size_t to avoid sign conversion warnings when subtracting from buffer_size. Returns 0 if offset is negative or >= buffer_size (prevents underflow).
Definition at line 421 of file common.h.
| #define SAFE_CALLOC | ( | count, | |
| size, | |||
| cast | |||
| ) |
#include <common.h>
Definition at line 218 of file common.h.
| #define SAFE_CALLOC_SIMD | ( | count, | |
| size, | |||
| cast | |||
| ) |
#include <common.h>
Definition at line 311 of file common.h.
| #define SAFE_FCLOSE | ( | fp | ) |
| #define SAFE_FREE | ( | ptr | ) |
| #define SAFE_GETENV | ( | name | ) | platform_getenv(name) |
| #define SAFE_MALLOC | ( | size, | |
| cast | |||
| ) |
#include <common.h>
| #define SAFE_MALLOC_ALIGNED | ( | size, | |
| alignment, | |||
| cast | |||
| ) |
#include <common.h>
Definition at line 293 of file common.h.
| #define SAFE_MALLOC_SIMD | ( | size, | |
| cast | |||
| ) | SAFE_MALLOC_ALIGNED(size, 16, cast) |
| #define SAFE_MEMCPY | ( | dest, | |
| dest_size, | |||
| src, | |||
| count | |||
| ) | platform_memcpy((dest), (dest_size), (src), (count)) |
| #define SAFE_MEMMOVE | ( | dest, | |
| dest_size, | |||
| src, | |||
| count | |||
| ) | platform_memmove((dest), (dest_size), (src), (count)) |
| #define SAFE_MEMSET | ( | dest, | |
| dest_size, | |||
| ch, | |||
| count | |||
| ) | platform_memset((dest), (dest_size), (ch), (count)) |
| #define SAFE_REALLOC | ( | ptr, | |
| size, | |||
| cast | |||
| ) |
#include <common.h>
Definition at line 228 of file common.h.
| #define safe_size_mul bytes_safe_size_mul |
| #define SAFE_SNPRINTF | ( | buffer, | |
| buffer_size, | |||
| ... | |||
| ) | (size_t)safe_snprintf((buffer), (buffer_size), __VA_ARGS__) |
| #define SAFE_SSCANF | ( | str, | |
| format, | |||
| ... | |||
| ) | sscanf(str, format, __VA_ARGS__) |
| #define SAFE_STRCPY | ( | dest, | |
| dest_size, | |||
| src | |||
| ) | platform_strcpy((dest), (dest_size), (src)) |
| #define SAFE_STRDUP | ( | dst, | |
| src | |||
| ) |
#include <common.h>
Definition at line 362 of file common.h.
| #define SAFE_STRERROR | ( | errnum | ) | platform_strerror(errnum) |
| #define SAFE_STRNCPY | ( | dst, | |
| src, | |||
| size | |||
| ) | platform_strlcpy((dst), (src), (size)) |
| #define THREAD_CREATE_OR_RETURN | ( | thread, | |
| func, | |||
| arg | |||
| ) |
#include <common.h>
Create a thread or log error and return.
| thread | Pointer to thread_t variable |
| func | Thread function (should match void* (*)(void*) signature) |
| arg | Thread argument |
Handles common pattern: create thread, log error if failed, then return -1. Example usage:
THREAD_CREATE_OR_RETURN(thread, thread_func, arg); // Thread created successfully, continue
Definition at line 442 of file common.h.
| #define TRACK_ALIGNED_ALLOC | ( | ptr, | |
| size, | |||
| file, | |||
| line | |||
| ) | ((void)0) |
| #define UNTRACKED_FREE | ( | ptr | ) |
| #define UNTRACKED_MALLOC | ( | size, | |
| cast | |||
| ) |
| #define write_u16_unaligned bytes_write_u16_unaligned |
| #define write_u32_unaligned bytes_write_u32_unaligned |
| void asciichat_fatal_with_context | ( | asciichat_error_t | code, |
| const char * | file, | ||
| int | line, | ||
| const char * | function, | ||
| const char * | format, | ||
| ... | |||
| ) |
#include <common.h>
Exit with error code and context (used by FATAL macro)
| code | Error code (asciichat_error_t) |
| file | Source file name (can be NULL) |
| line | Line number (0 if not provided) |
| function | Function name (can be NULL) |
| format | Format string (printf-style) |
| ... | Format arguments |
Low-level function used by FATAL() macro. Sets error context and exits the program with the specified error code. In debug builds, prints stack trace before exiting.
Definition at line 275 of file asciichat_errno.c.
References asciichat_errno_context, asciichat_print_error_context(), asciichat_error_context_t::code, extract_project_relative_path(), format_message(), HAS_ERRNO, LOG_COLOR_ERROR, LOG_COLOR_FATAL, log_labeled(), log_plain, platform_backtrace(), platform_backtrace_symbols(), platform_backtrace_symbols_free(), platform_print_backtrace_symbols(), safe_fprintf(), and SAFE_FREE.
| asciichat_error_t asciichat_shared_init | ( | const char * | default_log_filename, |
| bool | is_client | ||
| ) |
#include <common.h>
Initialize common subsystems shared by client and server.
This function performs initialization that is common to both client and server modes:
Note: Memory debugging setup is handled separately by each mode due to different requirements (client has snapshot mode, server doesn't).
| default_log_filename | Default log filename (e.g., "client.log" or "server.log") |
| is_client | true for client mode (routes all logs to stderr), false for server mode |
Definition at line 64 of file common.c.
References apply_palette_config(), asciichat_errno_cleanup(), ASCIICHAT_OK, buffer_pool_cleanup_global(), buffer_pool_init_global(), ERROR_CONFIG, ERROR_PLATFORM_INIT, FATAL, GET_OPTION, known_hosts_cleanup(), log_file, options_state::log_file, log_init(), log_set_terminal_output(), log_truncate_if_large(), options_get(), options_state_shutdown(), options_state::palette_custom, options_state::palette_custom_set, platform_cleanup(), platform_init(), and UNUSED.
| void fps_frame | ( | fps_t * | tracker, |
| const struct timespec * | current_time, | ||
| const char * | context | ||
| ) |
#include <fps.h>
Track a frame and detect lag conditions.
Call this function when a frame is processed. Automatically detects when frames arrive late and generates periodic FPS reports every report_interval_us.
| tracker | FPS tracker state |
| current_time | Timestamp of this frame (CLOCK_MONOTONIC) |
| context | Optional context string for lag logging (e.g., "ASCII frame received") |
Definition at line 57 of file fps.c.
References fps_t::expected_fps, fps_t::frame_count, fps_t::last_fps_report, fps_t::last_frame_time, fps_t::report_interval_us, and fps_t::tracker_name.
Referenced by __attribute__(), client_audio_render_thread(), and client_video_render_thread().
| void fps_init | ( | fps_t * | tracker, |
| int | expected_fps, | ||
| const char * | name | ||
| ) |
#include <fps.h>
Initialize FPS tracker.
Sets up the tracker with expected FPS and default reporting interval (10 seconds). Should be called once before using the tracker.
| tracker | Pointer to uninitialized fps_t (should be zero-initialized) |
| expected_fps | Expected frame rate in FPS (e.g., 60, 30, 20) |
| name | Display name for logging (e.g., "CLIENT", "WEBCAM", "AUDIO", "KEEPALIVE") |
Definition at line 36 of file fps.c.
References fps_init_with_interval().
Referenced by client_audio_render_thread(), and client_video_render_thread().
| void fps_init_with_interval | ( | fps_t * | tracker, |
| int | expected_fps, | ||
| const char * | name, | ||
| uint64_t | report_interval_us | ||
| ) |
#include <fps.h>
Initialize FPS tracker with custom report interval.
Sets up the tracker with expected FPS and custom reporting interval. Useful for different threads that may need different reporting frequencies.
| tracker | Pointer to uninitialized fps_t (should be zero-initialized) |
| expected_fps | Expected frame rate in FPS |
| name | Display name for logging |
| report_interval_us | Custom report interval in microseconds |
Definition at line 40 of file fps.c.
References fps_t::expected_fps, fps_t::frame_count, fps_t::last_fps_report, fps_t::last_frame_time, fps_t::report_interval_us, and fps_t::tracker_name.
Referenced by __attribute__(), and fps_init().