ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
transport.c File Reference

Go to the source code of this file.

Data Structures

struct  tcp_transport_data_t
 TCP transport implementation data. More...
 

Functions

acip_transport_t * acip_tcp_transport_create (const char *name, socket_t sockfd, crypto_context_t *crypto_ctx)
 Create TCP transport from existing socket.
 
void acip_transport_destroy (acip_transport_t *transport)
 Destroy transport and free all resources.
 

Function Documentation

◆ acip_tcp_transport_create()

acip_transport_t * acip_tcp_transport_create ( const char *  name,
socket_t  sockfd,
crypto_context_t *  crypto_ctx 
)

Create TCP transport from existing socket.

Parameters
nameDebug name for tracking this transport (required, e.g., "transport_client_5")
sockfdConnected socket descriptor
crypto_ctxOptional crypto context (may be NULL)
Returns
Transport instance or NULL on error
Note
Caller retains socket ownership (transport doesn't close on destroy)

Definition at line 398 of file tcp/transport.c.

398 {
399 if (!name) {
400 SET_ERRNO(ERROR_INVALID_STATE, "Transport name is required");
401 return NULL;
402 }
403
404 if (sockfd == INVALID_SOCKET_VALUE) {
405 log_error("[TCP_CREATE_STATE] ❌ INVALID_SOCKET: sockfd=%d", sockfd);
406 SET_ERRNO(ERROR_INVALID_PARAM, "Invalid socket descriptor");
407 return NULL;
408 }
409
410 log_info("[TCP_CREATE_STATE] 🟢 CREATE_START: sockfd=%d, crypto=%s", sockfd, crypto_ctx ? "yes" : "no");
411
412 // Allocate transport structure
414 if (!transport) {
415 log_error("[TCP_CREATE_STATE] ❌ ALLOC_TRANSPORT_FAILED: size=%zu", sizeof(acip_transport_t));
416 SET_ERRNO(ERROR_MEMORY, "Failed to allocate TCP transport");
417 return NULL;
418 }
419
420 log_debug("[TCP_CREATE_STATE] 🟢 TRANSPORT_ALLOCATED: transport=%p", (void *)transport);
421
422 // Allocate TCP-specific data
424 if (!tcp_data) {
425 log_error("[TCP_CREATE_STATE] ❌ ALLOC_TCP_DATA_FAILED: size=%zu", sizeof(tcp_transport_data_t));
426 SAFE_FREE(transport);
427 SET_ERRNO(ERROR_MEMORY, "Failed to allocate TCP transport data");
428 return NULL;
429 }
430
431 log_debug("[TCP_CREATE_STATE] 🟢 TCP_DATA_ALLOCATED: tcp_data=%p", (void *)tcp_data);
432
433 // Initialize TCP data
434 tcp_data->sockfd = sockfd;
435 tcp_data->is_connected = true;
436
437 // Initialize send mutex to protect concurrent sends from multiple threads
438 int mutex_result = mutex_init(&tcp_data->send_mutex, "tcp_send");
439 if (mutex_result != 0) {
440 log_error("[TCP_CREATE_STATE] ❌ MUTEX_INIT_FAILED: result=%d", mutex_result);
441 SAFE_FREE(tcp_data);
442 SAFE_FREE(transport);
443 SET_ERRNO(ERROR_MEMORY, "Failed to initialize send mutex");
444 return NULL;
445 }
446
447 log_info("[TCP_CREATE_STATE] 🟢 TCP_DATA_INITIALIZED: sockfd=%d, is_connected=true, send_mutex=initialized", sockfd);
448
449 // Enable TCP_NODELAY to disable Nagle's algorithm
450 // This ensures small packets are sent immediately instead of being buffered
451 int nodelay = 1;
452 if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char *)&nodelay, sizeof(nodelay)) < 0) {
453 log_warn("[TCP_CREATE_STATE] ⚠️ TCP_NODELAY_FAILED: sockfd=%d, %s", sockfd, SAFE_STRERROR(errno));
454 // Continue anyway - this is not fatal
455 } else {
456 log_debug("[TCP_CREATE_STATE] 🟢 TCP_NODELAY_SET: sockfd=%d", sockfd);
457 }
458
459 // Initialize transport
460 transport->methods = &tcp_methods;
461 transport->crypto_ctx = crypto_ctx;
462 transport->impl_data = tcp_data;
463
464 // Register transport and impl_data before logging so named replacements work
465 NAMED_REGISTER_TRANSPORT(transport, name, NULL);
466 NAMED_REGISTER(tcp_data, "impl", "tcp_impl", "0x%tx", (uintptr_t)(const void *)(transport));
467
468 log_info("[TCP_CREATE_STATE] ✅ CREATE_COMPLETE: transport=%p, sockfd=%d, is_connected=true, crypto=%s",
469 (void *)transport, sockfd, crypto_ctx ? "enabled" : "disabled");
470
471 return transport;
472}
#define SAFE_FREE(ptr)
Definition common.h:376
#define SAFE_MALLOC(size, cast)
Definition common.h:264
#define SAFE_STRERROR(errnum)
Definition common.h:465
#define NAMED_REGISTER_TRANSPORT(transport, name, parent_ptr)
Register a transport with automatic format specifier.
#define NAMED_REGISTER(ptr, name, type, fmt, parent_ptr)
Register any pointer with base name, type, format spec, and location (auto-suffix)
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
@ ERROR_INVALID_STATE
@ ERROR_MEMORY
Definition error_codes.h:56
@ ERROR_INVALID_PARAM
#define log_warn(...)
Log a WARN message.
Definition log/log.h:574
#define log_error(...)
Log an ERROR message.
Definition log/log.h:587
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
#define INVALID_SOCKET_VALUE
Invalid socket value (POSIX: -1)
Definition socket.h:278
int mutex_init(mutex_t *mutex, const char *name)
Initialize a mutex with a name.
Definition threading.c:16
int errno
Transport instance structure.
Definition transport.h:214
void * impl_data
Transport-specific state.
Definition transport.h:218
const acip_transport_methods_t * methods
Method table (virtual functions)
Definition transport.h:215
crypto_context_t * crypto_ctx
Optional encryption context.
Definition transport.h:216
TCP transport implementation data.
socket_t sockfd
Socket descriptor (NOT owned - don't close)
bool is_connected
Connection state.
mutex_t send_mutex
Mutex to protect concurrent sends (multiple threads may send packets)

References errno, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, ERROR_MEMORY, INVALID_SOCKET_VALUE, tcp_transport_data_t::is_connected, log_debug, log_error, log_info, log_warn, mutex_init(), NAMED_REGISTER, NAMED_REGISTER_TRANSPORT, SAFE_FREE, SAFE_MALLOC, SAFE_STRERROR, tcp_transport_data_t::send_mutex, SET_ERRNO, and tcp_transport_data_t::sockfd.

Referenced by acds_client_connect(), acds_client_handler(), add_client(), connection_attempt_tcp(), and server_connection_establish().

◆ acip_transport_destroy()

void acip_transport_destroy ( acip_transport_t *  transport)

Destroy transport and free all resources.

Parameters
transportTransport to destroy (may be NULL)
Note
Calls close() first if still connected
Frees the transport structure itself
Safe to pass NULL

Definition at line 478 of file tcp/transport.c.

478 {
479 if (!transport) {
480 log_debug("[TRANSPORT_DESTROY] ⚠️ NULL_TRANSPORT: nothing to destroy");
481 return;
482 }
483
484 log_warn("[TRANSPORT_DESTROY] 🔴 DESTROY_START: transport=%p, impl_data=%p", (void *)transport, transport->impl_data);
485
486 // Get type before we destroy for logging
487 acip_transport_type_t type = 0;
488 if (transport->methods && transport->methods->get_type) {
489 type = transport->methods->get_type(transport);
490 log_info("[TRANSPORT_DESTROY] 📋 TRANSPORT_TYPE: type=%d (1=TCP, 2=WebSocket, 3=WebRTC, ...)", type);
491 }
492
493 // Close if still connected
494 if (transport->methods && transport->methods->close && transport->methods->is_connected &&
495 transport->methods->is_connected(transport)) {
496 log_warn("[TRANSPORT_DESTROY] 🔴 STILL_CONNECTED: calling close() first (type=%d)", type);
497 asciichat_error_t close_result = transport->methods->close(transport);
498 log_info("[TRANSPORT_DESTROY] 🔴 CLOSE_CALLED: result=%d", close_result != ASCIICHAT_OK ? -1 : 0);
499 } else {
500 log_debug("[TRANSPORT_DESTROY] ✅ ALREADY_CLOSED: skipping close (type=%d)", type);
501 }
502
503 // Call custom destroy implementation if provided
504 if (transport->methods && transport->methods->destroy_impl) {
505 log_info("[TRANSPORT_DESTROY] 🔧 CALLING_DESTROY_IMPL: type=%d", type);
506 transport->methods->destroy_impl(transport);
507 log_info("[TRANSPORT_DESTROY] ✅ DESTROY_IMPL_COMPLETE: type=%d", type);
508 } else {
509 log_debug("[TRANSPORT_DESTROY] ⏭️ NO_CUSTOM_DESTROY: type=%d (using generic cleanup)", type);
510 }
511
512 // Free implementation data
513 if (transport->impl_data) {
514 log_debug("[TRANSPORT_DESTROY] 🗑️ FREEING_IMPL_DATA: %p", transport->impl_data);
515 NAMED_UNREGISTER(transport->impl_data);
516 SAFE_FREE(transport->impl_data);
517 log_debug("[TRANSPORT_DESTROY] ✅ IMPL_DATA_FREED");
518 }
519
520 // Free transport structure
521 log_debug("[TRANSPORT_DESTROY] 🗑️ FREEING_TRANSPORT: %p", (void *)transport);
522 SAFE_FREE(transport);
523
524 log_warn("[TRANSPORT_DESTROY] ✅ DESTROY_COMPLETE: type=%d", type);
525}
#define NAMED_UNREGISTER(ptr)
Unregister a pointer.
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ASCIICHAT_OK
Definition error_codes.h:51
bool(* is_connected)(acip_transport_t *transport)
Check if transport is connected.
Definition transport.h:183
asciichat_error_t(* close)(acip_transport_t *transport)
Close this transport.
Definition transport.h:156
void(* destroy_impl)(acip_transport_t *transport)
Custom destroy implementation (optional)
Definition transport.h:205
acip_transport_type_t(* get_type)(acip_transport_t *transport)
Get transport type.
Definition transport.h:164
acip_transport_type_t
Transport type enumeration.
Definition transport.h:93

References ASCIICHAT_OK, acip_transport_methods_t::close, acip_transport_methods_t::destroy_impl, acip_transport_methods_t::get_type, acip_transport::impl_data, acip_transport_methods_t::is_connected, log_debug, log_info, log_warn, acip_transport::methods, NAMED_UNREGISTER, and SAFE_FREE.

Referenced by acds_client_connect(), acds_client_disconnect(), acds_client_handler(), connection_attempt_tcp(), connection_handle_cleanup(), discovery_session_destroy(), discovery_session_process(), remove_client(), server_connection_close(), server_connection_establish(), server_connection_set_transport(), and session_participant_destroy().