28#include <ascii-chat/common.h>
29#include <ascii-chat/log/logging.h>
30#include <ascii-chat/options/options.h>
31#include <ascii-chat/util/url.h>
32#include <ascii-chat/options/rcu.h>
33#include <ascii-chat/network/acip/client.h>
34#include <ascii-chat/network/tcp/client.h>
35#include <ascii-chat/network/websocket/client.h>
36#include <ascii-chat/platform/abstraction.h>
59 return "DISCONNECTED";
76 return SET_ERRNO(ERROR_INVALID_PARAM,
"Context pointer is NULL");
94 log_debug(
"Connection context initialized");
110 log_debug(
"TCP client instance destroyed");
117 log_debug(
"WebSocket client instance destroyed");
125 log_debug(
"Transport connection closed");
128 log_debug(
"Connection context cleaned up");
136 return SET_ERRNO(ERROR_INVALID_PARAM,
"Context pointer is NULL");
157 bool timeout_exceeded = elapsed_ns > ctx->
timeout_ns;
159 if (timeout_exceeded) {
160 log_warn(
"Connection timeout exceeded: elapsed %.3f seconds > %.3f seconds limit", time_ns_to_s(elapsed_ns),
164 return timeout_exceeded;
178 uint16_t server_port,
struct tcp_client *pre_created_tcp_client) {
179 log_info(
"=== connection_attempt_tcp CALLED: address='%s', port=%u, pre_created=%p ===", server_address, server_port,
180 (
void *)pre_created_tcp_client);
182 if (!ctx || !server_address) {
183 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters");
188 return SET_ERRNO(ERROR_NETWORK,
"Connection attempt aborted due to shutdown request");
192 log_debug(
"connection_attempt_tcp: server_address='%s', port=%u", server_address, server_port);
196 const char *ws_url = server_address;
199 url_parts_t url_parts = {0};
200 if (
url_parse(server_address, &url_parts) == ASCIICHAT_OK) {
201 log_debug(
"WebSocket URL parsed: host=%s, port=%d, scheme=%s", url_parts.host, url_parts.port, url_parts.scheme);
204 log_info(
"Attempting WebSocket connection to %s", ws_url);
208 if (result != ASCIICHAT_OK) {
219 bool has_auth_material =
220 (GET_OPTION(encrypt_key)[0] !=
'\0' || GET_OPTION(num_identity_keys) > 0 || GET_OPTION(password)[0] !=
'\0');
221 bool no_encrypt = GET_OPTION(no_encrypt);
224 if (!no_encrypt && !has_auth_material)
225 crypto_mode = ACIP_CRYPTO_ENCRYPT;
226 else if (!no_encrypt && has_auth_material)
227 crypto_mode = ACIP_CRYPTO_FULL;
228 else if (no_encrypt && has_auth_material)
229 crypto_mode = ACIP_CRYPTO_AUTH;
231 crypto_mode = ACIP_CRYPTO_NONE;
233 log_debug(
"WebSocket crypto mode computed: 0x%02x (encrypt=%d, auth=%d)", crypto_mode,
234 ACIP_CRYPTO_HAS_ENCRYPT(crypto_mode), ACIP_CRYPTO_HAS_AUTH(crypto_mode));
240 if (crypto_mode != ACIP_CRYPTO_NONE) {
241 log_debug(
"Initializing crypto context for WebSocket...");
243 log_error(
"Failed to initialize crypto context");
245 return SET_ERRNO(ERROR_CRYPTO,
"Crypto initialization failed");
247 log_debug(
"Crypto context initialized successfully");
256 log_error(
"Failed to create WebSocket client");
259 return SET_ERRNO(ERROR_NETWORK,
"WebSocket client creation failed");
265 log_error(
"Failed to create WebSocket ACIP transport");
269 return SET_ERRNO(ERROR_NETWORK,
"WebSocket connection failed");
272 log_info(
"WebSocket connection established to %s", ws_url);
281 log_info(
"Attempting TCP connection to %s:%u (3s timeout)", server_address, server_port);
285 if (result != ASCIICHAT_OK) {
290 tcp_client_t *tcp_client = pre_created_tcp_client;
291 bool created_tcp_client =
false;
294 created_tcp_client =
true;
296 log_error(
"Failed to create TCP client");
298 return SET_ERRNO(ERROR_NETWORK,
"TCP client creation failed");
300 log_debug(
"Created TCP client locally (not pre-created by framework)");
302 log_debug(
"Using pre-created TCP client from framework");
313 if (tcp_result != 0) {
314 log_debug(
"TCP connection failed (tcp_client_connect returned %d)", tcp_result);
315 if (created_tcp_client) {
319 return SET_ERRNO(ERROR_NETWORK,
"TCP connection failed after %u attempts", ctx->
reconnect_attempt);
324 if (sockfd == INVALID_SOCKET_VALUE) {
325 log_error(
"Failed to get socket from TCP client");
326 if (created_tcp_client) {
329 return SET_ERRNO(ERROR_NETWORK,
"Invalid socket after TCP connection");
334 if (tcp_client->server_ip[0] !=
'\0') {
336 log_debug(
"Server IP extracted from TCP client: %s", tcp_client->server_ip);
338 log_warn(
"TCP client did not populate server_ip field");
343 bool has_auth_material =
344 (GET_OPTION(encrypt_key)[0] !=
'\0' || GET_OPTION(num_identity_keys) > 0 || GET_OPTION(password)[0] !=
'\0');
345 bool no_encrypt = GET_OPTION(no_encrypt);
348 if (!no_encrypt && !has_auth_material)
349 crypto_mode = ACIP_CRYPTO_ENCRYPT;
350 else if (!no_encrypt && has_auth_material)
351 crypto_mode = ACIP_CRYPTO_FULL;
352 else if (no_encrypt && has_auth_material)
353 crypto_mode = ACIP_CRYPTO_AUTH;
355 crypto_mode = ACIP_CRYPTO_NONE;
357 log_debug(
"TCP crypto mode computed: 0x%02x (encrypt=%d, auth=%d)", crypto_mode, ACIP_CRYPTO_HAS_ENCRYPT(crypto_mode),
358 ACIP_CRYPTO_HAS_AUTH(crypto_mode));
365 if (crypto_mode != ACIP_CRYPTO_NONE) {
366 log_debug(
"Initializing crypto context...");
368 log_error(
"Failed to initialize crypto context");
369 if (created_tcp_client) {
372 return SET_ERRNO(ERROR_CRYPTO,
"Crypto initialization failed");
374 log_debug(
"Crypto context initialized successfully");
377 log_debug(
"Performing crypto handshake with server...");
379 log_error(
"Crypto handshake failed");
380 if (created_tcp_client) {
383 return SET_ERRNO(ERROR_NETWORK,
"Crypto handshake failed");
385 log_debug(
"Crypto handshake completed successfully");
394 log_error(
"Failed to create ACIP transport for TCP");
395 if (created_tcp_client) {
398 return SET_ERRNO(ERROR_NETWORK,
"Failed to create ACIP transport");
401 log_info(
"TCP connection established to %s:%u", server_address, server_port);
407 if (created_tcp_client) {
409 log_debug(
"TCP client instance stored in connection context for cleanup");
411 log_debug(
"Using framework-managed TCP client, not storing in context");
424 log_info(
"=== connection_attempt_websocket CALLED: url='%s' ===", ws_url);
426 if (!ctx || !ws_url) {
427 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid parameters");
432 return SET_ERRNO(ERROR_NETWORK,
"Connection attempt aborted due to shutdown request");
435 log_info(
"Attempting WebSocket connection to %s", ws_url);
439 if (result != ASCIICHAT_OK) {
448 if (!GET_OPTION(no_encrypt)) {
449 log_debug(
"Initializing crypto context for WebSocket...");
451 log_error(
"Failed to initialize crypto context");
452 return SET_ERRNO(ERROR_CRYPTO,
"Crypto initialization failed");
454 log_debug(
"Crypto context initialized successfully");
463 log_error(
"Failed to create WebSocket client");
465 return SET_ERRNO(ERROR_NETWORK,
"WebSocket client creation failed");
471 log_error(
"Failed to create WebSocket ACIP transport");
474 return SET_ERRNO(ERROR_NETWORK,
"WebSocket connection failed");
477 log_info(
"WebSocket connection established to %s", ws_url);
481 log_debug(
"WebSocket client instance stored in connection context");
asciichat_error_t connection_context_init(connection_attempt_context_t *ctx)
Initialize connection attempt context.
asciichat_error_t connection_attempt_websocket(connection_attempt_context_t *ctx, const char *ws_url)
Attempt WebSocket connection (ws:// or wss://)
void connection_context_cleanup(connection_attempt_context_t *ctx)
Cleanup connection attempt context.
bool connection_check_timeout(const connection_attempt_context_t *ctx)
Check if connection attempt has exceeded timeout.
asciichat_error_t connection_state_transition(connection_attempt_context_t *ctx, connection_state_t new_state)
Transition to next connection state with validation.
const char * connection_state_name(connection_state_t state)
Get human-readable state name for logging.
asciichat_error_t connection_attempt_tcp(connection_attempt_context_t *ctx, const char *server_address, uint16_t server_port, struct tcp_client *pre_created_tcp_client)
Attempt direct TCP connection.
Connection state machine for TCP client connections.
#define CONN_TIMEOUT_TCP
TCP connection timeout (3s)
connection_state_t
Simple TCP connection state machine.
@ CONN_STATE_CONNECTED
Successfully connected via TCP.
@ CONN_STATE_IDLE
Not connected, no attempt in progress.
@ CONN_STATE_DISCONNECTED
Clean disconnect (user initiated)
@ CONN_STATE_FAILED
Connection attempt failed.
@ CONN_STATE_ATTEMPTING
Attempting TCP connection.
void server_connection_set_ip(const char *ip)
Set the server IP address.
const crypto_context_t * crypto_client_get_context(void)
Get crypto context for encryption/decryption.
void client_crypto_set_mode(uint8_t mode)
Set crypto mode for handshake (encryption + authentication)
int client_crypto_init(void)
Initialize client crypto handshake.
int client_crypto_handshake(socket_t socket)
Perform crypto handshake with server.
bool crypto_client_is_ready(void)
Check if crypto handshake is ready.
tcp_client_t * tcp_client_create(void)
Create and initialize TCP client.
socket_t tcp_client_get_socket(const tcp_client_t *client)
Get current socket descriptor.
int tcp_client_connect(tcp_client_t *client, const char *address, int port, int reconnect_attempt, bool first_connection, bool has_ever_connected)
Establish TCP connection to server.
void tcp_client_destroy(tcp_client_t **client_ptr)
Destroy TCP client and free resources.
acip_transport_t * websocket_client_connect(websocket_client_t *client, const char *url, struct crypto_context_t *crypto_ctx)
Establish WebSocket connection to server.
websocket_client_t * websocket_client_create(void)
Create and initialize WebSocket client.
void websocket_client_destroy(websocket_client_t **client_ptr)
Destroy WebSocket client and free resources.
Server cryptographic operations and per-client handshake management.
ascii-chat Server Mode Entry Point Header
Server packet processing and protocol implementation.
Context for TCP connection attempts.
connection_state_t current_state
Current connection state.
connection_state_t previous_state
Previous state (for debugging)
uint32_t reconnect_attempt
Reconnection attempt number (1st, 2nd, etc.)
struct tcp_client * tcp_client_instance
TCP client instance - owned by context.
acip_transport_t * active_transport
Currently active transport.
uint64_t timeout_ns
Timeout for connection attempt.
struct websocket_client * ws_client_instance
WebSocket client instance - owned by context.
uint32_t total_transitions
Total state transitions (for metrics)
uint64_t attempt_start_time_ns
When current attempt began.
acip_transport_t * acip_tcp_transport_create(socket_t sockfd, crypto_context_t *crypto_ctx)
void acip_transport_destroy(acip_transport_t *transport)
void url_parts_destroy(url_parts_t *parts)
bool url_is_websocket(const char *url)
asciichat_error_t url_parse(const char *url, url_parts_t *parts_out)
uint64_t time_get_realtime_ns(void)