ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
acds_client.h File Reference

ACIP client-side protocol library and ACDS client connection API. More...

Go to the source code of this file.

Data Structures

struct  acds_client_config_t
 acds client config is intentionally a small, concrete record. Fields such as server_port, timeout_ms, security_policy, identity_key give callers the identity and current value they need. It is normally borrowed from, or owned by, the surrounding subsystem—not independently managed. More...
struct  acds_client_t
 ACDS client connection handle. More...
struct  acds_session_create_params_t
 Session creation request parameters. More...
struct  acds_session_create_result_t
 Session creation result. More...
struct  acds_session_lookup_result_t
 Session lookup result. More...
struct  acds_session_join_params_t
 Session join parameters. More...
struct  acds_session_join_result_t
 Session join result. More...

Macros

#define ACDS_TRANSPORT_METADATA_MAX   521

Typedefs

typedef bool(* parallel_connect_should_exit_fn) (void *user_data)

Functions

asciichat_error_t acds_client_connect (acds_client_t *client, const acds_client_config_t *config)
 Connect to ACDS server.
void acds_client_disconnect (acds_client_t *client)
 Disconnect from ACDS server.
asciichat_error_t acds_session_create (acds_client_t *client, const acds_session_create_params_t *params, acds_session_create_result_t *result)
 Create a new session on the discovery server.
asciichat_error_t acds_session_lookup (acds_client_t *client, const char *session_string, acds_session_lookup_result_t *result)
 Look up session by string.
asciichat_error_t acds_session_join (acds_client_t *client, const acds_session_join_params_t *params, acds_session_join_result_t *result)
 Join an existing session.
asciichat_error_t acds_sign_session_create (const uint8_t identity_seckey[64], uint64_t timestamp, uint8_t capabilities, uint8_t max_participants, uint8_t signature_out[64])
 Sign a SESSION_CREATE message.
asciichat_error_t acds_verify_session_create (const uint8_t identity_pubkey[32], uint64_t timestamp, uint8_t capabilities, uint8_t max_participants, const uint8_t signature[64])
 Verify SESSION_CREATE signature.
asciichat_error_t acds_sign_session_join (const uint8_t identity_seckey[64], uint64_t timestamp, const char *session_string, uint8_t signature_out[64])
 Sign a SESSION_JOIN message.
asciichat_error_t acds_verify_session_join (const uint8_t identity_pubkey[32], uint64_t timestamp, const char *session_string, const uint8_t signature[64])
 Verify SESSION_JOIN signature.
bool acds_validate_timestamp (uint64_t timestamp_ms, uint32_t window_seconds)
 Check if timestamp is within acceptable window.
void acds_client_config_init_defaults (acds_client_config_t *config)
 Initialize ACDS client configuration with defaults.
asciichat_error_t acds_transport_metadata_encode (uint16_t quic_port, const char *url, void *output, size_t capacity, size_t *length)
asciichat_error_t acds_transport_metadata_decode (const void *bytes, size_t length, uint16_t *quic_port, char *url, size_t capacity)

Detailed Description

ACIP client-side protocol library and ACDS client connection API.

Definition in file acds_client.h.

Macro Definition Documentation

◆ ACDS_TRANSPORT_METADATA_MAX

#define ACDS_TRANSPORT_METADATA_MAX   521

Definition at line 405 of file acds_client.h.

Typedef Documentation

◆ parallel_connect_should_exit_fn

typedef bool(* parallel_connect_should_exit_fn) (void *user_data)

Definition at line 135 of file acds_client.h.

Function Documentation

◆ acds_client_config_init_defaults()

void acds_client_config_init_defaults ( acds_client_config_t * config)

Initialize ACDS client configuration with defaults.

Sets default values:

  • server_address: "127.0.0.1"
  • server_port: 27225
  • timeout_ms: 5000
Parameters
configConfiguration to initialize

Definition at line 78 of file acds_client_io.c.

78 {
79 if (!config) {
80 return;
81 }
82
83 memset(config, 0, sizeof(*config));
84 SAFE_STRNCPY(config->server_address, "127.0.0.1", sizeof(config->server_address));
86 config->timeout_ms = 5 * MS_PER_SEC_INT;
87}
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:423
#define ACIP_DISCOVERY_DEFAULT_PORT
Discovery server default port (use OPT_ACDS_PORT_INT_DEFAULT from options.h).
Definition acds.h:1102
#define MS_PER_SEC_INT
Definition time.h:176
char server_address[256]
ACDS server address (e.g., "discovery.ascii.chat" or "127.0.0.1").
uint32_t timeout_ms
Connection timeout in milliseconds.
uint16_t server_port
ACDS server port (default: 27225).

References ACIP_DISCOVERY_DEFAULT_PORT, MS_PER_SEC_INT, SAFE_STRNCPY, acds_client_config_t::server_address, acds_client_config_t::server_port, and acds_client_config_t::timeout_ms.

Referenced by client_crypto_init().

◆ acds_client_connect()

asciichat_error_t acds_client_connect ( acds_client_t * client,
const acds_client_config_t * config )

Connect to ACDS server.

Establishes TCP connection to the discovery server.

Parameters
clientClient handle (output)
configConnection configuration
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 93 of file acds_client_io.c.

93 {
94 if (!client || !config) {
95 return SET_ERRNO(ERROR_INVALID_PARAM, "client or config is NULL");
96 }
97
98 memset(client, 0, sizeof(*client));
99 memcpy(&client->config, config, sizeof(acds_client_config_t));
100 client->connected = false;
101
102 network_connect_config_t settings = {.timeout_ms = config->timeout_ms,
103 .should_exit_callback = config->should_exit_callback,
104 .callback_data = config->callback_data};
105 asciichat_error_t pconn_result = network_connection_open("acds", config->server_address, config->server_port,
106 &settings, &client->connection, NULL);
107 if (pconn_result == ASCIICHAT_OK) {
108 client->connected = true;
110
111 asciichat_error_t handshake_result = acds_client_handshake(client);
112 if (handshake_result != ASCIICHAT_OK) {
114 client->transport = NULL;
115 client->connected = false;
116 client->handshake_ctx = NULL;
117 return handshake_result;
118 }
119
121
122 /* Register ACDS client with named registry */
124 snprintf(acds_name, sizeof(acds_name), "acds_client:%s:%d", config->server_address, config->server_port);
125 NAMED_REGISTER(client, acds_name, "acds_client_t", "0x%tx", NULL);
126
127 log_info("Connected to ACDS server at %s:%d", config->server_address, config->server_port);
128 return ASCIICHAT_OK;
129 }
130
131 return pconn_result;
132}
#define NETWORK_ACIP_ACDS_CLIENT_IO_ACDS_NAME_BUFFER_SIZE
#define SET_ERRNO(code,...)
#define NAMED_REGISTER(ptr, name, type, fmt, parent_ptr)
Register any pointer with base name, type, format spec, and location (auto-suffix).
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define log_info(...)
Log an INFO message.
Definition log/log.h:608
void network_connection_destroy(network_connection_t **owner)
asciichat_error_t network_connection_open(const char *name, const char *address, uint16_t port, const network_connect_config_t *settings, network_connection_t **out, connection_endpoint_t *resolved)
void network_connection_ready(network_connection_t *c)
acip_transport_t * network_connection_transport(network_connection_t *c)
acds client config is intentionally a small, concrete record. Fields such as server_port,...
parallel_connect_should_exit_fn should_exit_callback
crypto_handshake_context_t * handshake_ctx
Borrowed from connection owner.
acds_client_config_t config
bool connected
Connection status.
network_connection_t * connection
acip_transport_t * transport
Transport used for the initial crypto handshake.
For network connect config, this is the live record that ties timeout_ms, callback_data,...

References ASCIICHAT_OK, acds_client_config_t::callback_data, acds_client_t::config, acds_client_t::connected, acds_client_t::connection, ERROR_INVALID_PARAM, acds_client_t::handshake_ctx, log_info, NAMED_REGISTER, NETWORK_ACIP_ACDS_CLIENT_IO_ACDS_NAME_BUFFER_SIZE, network_connection_destroy(), network_connection_open(), network_connection_ready(), network_connection_transport(), acds_client_config_t::server_address, acds_client_config_t::server_port, SET_ERRNO, acds_client_config_t::should_exit_callback, acds_client_config_t::timeout_ms, and acds_client_t::transport.

Referenced by client_crypto_init().

◆ acds_client_disconnect()

void acds_client_disconnect ( acds_client_t * client)

Disconnect from ACDS server.

Closes the connection and cleans up resources.

Parameters
clientClient handle

Definition at line 134 of file acds_client_io.c.

134 {
135 if (!client) {
136 return;
137 }
138
140 client->transport = NULL;
141 client->handshake_ctx = NULL;
142
143 client->connected = false;
144 log_debug("Disconnected from ACDS server");
145}
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595

References acds_client_t::connected, acds_client_t::connection, acds_client_t::handshake_ctx, log_debug, network_connection_destroy(), and acds_client_t::transport.

Referenced by client_crypto_init().

◆ acds_session_create()

asciichat_error_t acds_session_create ( acds_client_t * client,
const acds_session_create_params_t * params,
acds_session_create_result_t * result )

Create a new session on the discovery server.

Sends SESSION_CREATE packet and receives SESSION_CREATED response.

Parameters
clientConnected ACDS client
paramsSession creation parameters
resultSession creation result (output)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 165 of file acds_client_io.c.

166 {
167 if (!client || !client->connected || !params || !result)
168 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid discovery create parameters");
169 acds_protocol_t protocol;
170 acds_protocol_init(&protocol, client_protocol_send, client);
171 asciichat_error_t error = acds_protocol_create(&protocol, params, 0, 0);
172 if (error == ASCIICHAT_OK)
173 error = client_protocol_receive(client, &protocol);
174 if (error == ASCIICHAT_OK) {
175 memset(result, 0, sizeof(*result));
176 SAFE_STRNCPY(result->session_string, protocol.name, sizeof(result->session_string));
177 memcpy(result->session_id, protocol.created.session_id, sizeof(result->session_id));
178 result->expires_at = protocol.created.expires_at;
179 }
180 acds_protocol_destroy(&protocol);
181 return error;
182}
void acds_protocol_init(acds_protocol_t *p, acds_protocol_send_fn send, void *user_data)
void acds_protocol_destroy(acds_protocol_t *p)
asciichat_error_t acds_protocol_create(acds_protocol_t *p, const acds_session_create_params_t *params, uint8_t total_keys, uint8_t key_index)
struct acds_protocol acds_protocol_t
acip_session_created_t created
uint8_t session_id[16]
Session UUID.
char session_string[48+1]
Generated session string (null-terminated).
uint64_t expires_at
Expiration timestamp (Unix ms).

References acds_protocol_create(), acds_protocol_destroy(), acds_protocol_init(), ASCIICHAT_OK, acds_client_t::connected, acds_protocol::created, ERROR_INVALID_PARAM, acds_session_create_result_t::expires_at, acds_protocol::name, SAFE_STRNCPY, acds_session_create_result_t::session_id, acds_session_create_result_t::session_string, and SET_ERRNO.

◆ acds_session_join()

asciichat_error_t acds_session_join ( acds_client_t * client,
const acds_session_join_params_t * params,
acds_session_join_result_t * result )

Join an existing session.

Sends SESSION_JOIN packet and receives SESSION_JOINED response.

Parameters
clientConnected ACDS client
paramsJoin parameters
resultJoin result (output)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 210 of file acds_client_io.c.

211 {
212 if (!client || !client->connected || !params || !result)
213 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid discovery join parameters");
214 acds_protocol_t protocol;
215 acds_protocol_init(&protocol, client_protocol_send, client);
216 memset(result, 0, sizeof(*result));
217 asciichat_error_t error = acds_protocol_join(&protocol, params);
218 if (error == ASCIICHAT_OK)
219 error = client_protocol_receive(client, &protocol);
220 result->success = protocol.joined.success;
221 result->error_code = protocol.joined.error_code;
222 SAFE_STRNCPY(result->error_message, protocol.joined.error_message, sizeof(result->error_message));
223 if (error == ASCIICHAT_OK) {
224 memcpy(result->participant_id, protocol.joined.participant_id, sizeof(result->participant_id));
225 memcpy(result->session_id, protocol.joined.session_id, sizeof(result->session_id));
226 result->session_type = protocol.joined.session_type;
227 SAFE_STRNCPY(result->server_address, protocol.joined.server_address, sizeof(result->server_address));
228 result->server_port = protocol.joined.server_port;
229 }
230 acds_protocol_destroy(&protocol);
231 return error;
232}
asciichat_error_t acds_protocol_join(acds_protocol_t *p, const acds_session_join_params_t *params)
acip_session_joined_t joined
uint8_t error_code
Error code (if !success).
uint8_t session_type
acds_session_type_t: 0=DIRECT_TCP, 1=WEBRTC (if success)
uint8_t participant_id[16]
Participant UUID (if success).
bool success
Join succeeded.
uint16_t server_port
Server port (if success).
char error_message[128+1]
Error message (if !success, null-terminated).
uint8_t session_id[16]
Session UUID (if success).
char server_address[64+1]
Server IP/hostname (if success, null-terminated).

References acds_protocol_destroy(), acds_protocol_init(), acds_protocol_join(), ASCIICHAT_OK, acds_client_t::connected, acds_session_join_result_t::error_code, ERROR_INVALID_PARAM, acds_session_join_result_t::error_message, acds_protocol::joined, acds_session_join_result_t::participant_id, SAFE_STRNCPY, acds_session_join_result_t::server_address, acds_session_join_result_t::server_port, acds_session_join_result_t::session_id, acds_session_join_result_t::session_type, SET_ERRNO, and acds_session_join_result_t::success.

◆ acds_session_lookup()

asciichat_error_t acds_session_lookup ( acds_client_t * client,
const char * session_string,
acds_session_lookup_result_t * result )

Look up session by string.

Sends SESSION_LOOKUP packet and receives SESSION_INFO response.

Parameters
clientConnected ACDS client
session_stringSession string to look up
resultLookup result (output)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 183 of file acds_client_io.c.

183 {
184 if (!client || !client->connected || !name || !result)
185 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid discovery lookup parameters");
186 acds_protocol_t protocol;
187 acds_protocol_init(&protocol, client_protocol_send, client);
188 asciichat_error_t error = acds_protocol_lookup(&protocol, name);
189 if (error == ASCIICHAT_OK)
190 error = client_protocol_receive(client, &protocol);
191 if (error == ASCIICHAT_OK) {
192 memset(result, 0, sizeof(*result));
193 result->found = protocol.info.found;
194 if (result->found) {
195 memcpy(result->session_id, protocol.info.session_id, sizeof(result->session_id));
196 memcpy(result->host_pubkey, protocol.info.host_pubkey, sizeof(result->host_pubkey));
197 result->capabilities = protocol.info.capabilities;
198 result->max_participants = protocol.info.max_participants;
199 result->current_participants = protocol.info.current_participants;
200 result->has_password = protocol.info.has_password;
201 result->created_at = protocol.info.created_at;
202 result->expires_at = protocol.info.expires_at;
203 result->require_server_verify = protocol.info.require_server_verify;
204 result->require_client_verify = protocol.info.require_client_verify;
205 }
206 }
207 acds_protocol_destroy(&protocol);
208 return error;
209}
asciichat_error_t acds_protocol_lookup(acds_protocol_t *p, const char *name)
acip_session_info_t info
uint8_t capabilities
Session capabilities.
bool found
Session exists.
bool require_client_verify
ACDS policy: client must verify server identity.
bool has_password
Password required to join.
uint64_t expires_at
Expiration timestamp (Unix ms).
uint8_t max_participants
Maximum participants.
bool require_server_verify
ACDS policy: server must verify client identity.
uint64_t created_at
Creation timestamp (Unix ms).
uint8_t host_pubkey[32]
Host's Ed25519 public key.
uint8_t current_participants
Current participant count.
uint8_t session_id[16]
Session UUID (if found).

References acds_protocol_destroy(), acds_protocol_init(), acds_protocol_lookup(), ASCIICHAT_OK, acds_session_lookup_result_t::capabilities, acds_client_t::connected, acds_session_lookup_result_t::created_at, acds_session_lookup_result_t::current_participants, ERROR_INVALID_PARAM, acds_session_lookup_result_t::expires_at, acds_session_lookup_result_t::found, acds_session_lookup_result_t::has_password, acds_session_lookup_result_t::host_pubkey, acds_protocol::info, acds_session_lookup_result_t::max_participants, acds_session_lookup_result_t::require_client_verify, acds_session_lookup_result_t::require_server_verify, acds_session_lookup_result_t::session_id, and SET_ERRNO.

Referenced by client_crypto_init().

◆ acds_sign_session_create()

asciichat_error_t acds_sign_session_create ( const uint8_t identity_seckey[64],
uint64_t timestamp,
uint8_t capabilities,
uint8_t max_participants,
uint8_t signature_out[64] )

Sign a SESSION_CREATE message.

Computes Ed25519 signature over: type || timestamp || capabilities || max_participants

Parameters
identity_seckeyEd25519 secret key (64 bytes)
timestampUnix milliseconds timestamp
capabilitiesCapabilities bitfield
max_participantsMaximum participants (1-128)
signature_outOutput buffer for signature (64 bytes)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 45 of file acds_client.c.

47 {
48 if (!identity_seckey || !signature_out) {
49 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter");
50 }
51
52 // Build message: type (1 byte) || timestamp (8 bytes) || capabilities (1 byte) || max_participants (1 byte)
55
56 // Convert timestamp to network byte order and pack into message
57 uint64_t timestamp_net = HOST_TO_NET_U64(timestamp);
58 memcpy(&message[1], &timestamp_net, sizeof(timestamp_net));
59
60 message[9] = capabilities;
61 message[10] = max_participants;
62
63 // Sign using Ed25519
64 if (crypto_sign_detached(signature_out, NULL, message, sizeof(message), identity_seckey) != 0) {
65 return SET_ERRNO(ERROR_CRYPTO, "Ed25519 signature generation failed");
66 }
67
68 log_debug("Generated SESSION_CREATE signature (timestamp=%llu, caps=%u, max=%u)", (unsigned long long)timestamp,
69 capabilities, max_participants);
70
71 return ASCIICHAT_OK;
72}
#define ACDS_CREATE_SIGNATURE_MESSAGE_SIZE
Definition acds_client.c:4
#define HOST_TO_NET_U64(val)
Definition endian.h:213
unsigned long long uint64_t
Definition common.h:63
unsigned char uint8_t
Definition common.h:60
@ ERROR_CRYPTO
Definition error_codes.h:93
@ PACKET_TYPE_ACIP_SESSION_CREATE
Create new session (Client -> Discovery Server).
Definition packet.h:431

References ACDS_CREATE_SIGNATURE_MESSAGE_SIZE, ASCIICHAT_OK, ED25519_PRIVATE_KEY_SIZE, ED25519_SIGNATURE_SIZE, ERROR_CRYPTO, ERROR_INVALID_PARAM, HOST_TO_NET_U64, log_debug, PACKET_TYPE_ACIP_SESSION_CREATE, and SET_ERRNO.

Referenced by acds_protocol_create().

◆ acds_sign_session_join()

asciichat_error_t acds_sign_session_join ( const uint8_t identity_seckey[64],
uint64_t timestamp,
const char * session_string,
uint8_t signature_out[64] )

Sign a SESSION_JOIN message.

Computes Ed25519 signature over: type || timestamp || session_string

Parameters
identity_seckeyEd25519 secret key (64 bytes)
timestampUnix milliseconds timestamp
session_stringSession string (null-terminated)
signature_outOutput buffer for signature (64 bytes)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 102 of file acds_client.c.

103 {
104 if (!identity_seckey || !session_string || !signature_out) {
105 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter");
106 }
107
108 size_t session_len = strlen(session_string);
109 if (session_len > ACIP_MAX_SESSION_STRING_LEN) {
110 return SET_ERRNO(ERROR_INVALID_PARAM, "Session string too long (max 48 chars)");
111 }
112
113 // Build message: type (1 byte) || timestamp (8 bytes) || session_string (variable length)
116
117 // Convert timestamp to network byte order and pack into message
118 uint64_t timestamp_net = HOST_TO_NET_U64(timestamp);
119 memcpy(&message[1], &timestamp_net, sizeof(timestamp_net));
120
121 // Copy session string (copy exactly session_len bytes, no null terminator in signature)
122 memcpy(&message[9], session_string, session_len);
123
124 size_t message_len = ACDS_SIGNATURE_PREFIX_SIZE + session_len;
125
126 // Sign using Ed25519
127 if (crypto_sign_detached(signature_out, NULL, message, message_len, identity_seckey) != 0) {
128 return SET_ERRNO(ERROR_CRYPTO, "Ed25519 signature generation failed");
129 }
130
131 log_debug("Generated SESSION_JOIN signature (timestamp=%llu, session='%s')", (unsigned long long)timestamp,
132 session_string);
133
134 return ASCIICHAT_OK;
135}
#define ACDS_SIGNATURE_PREFIX_SIZE
Definition acds_client.c:3
#define ACIP_MAX_SESSION_STRING_LEN
Definition acds_sizes.h:6
@ PACKET_TYPE_ACIP_SESSION_JOIN
Join existing session (Client -> Discovery Server).
Definition packet.h:439

References ACDS_SIGNATURE_PREFIX_SIZE, ACIP_MAX_SESSION_STRING_LEN, ASCIICHAT_OK, ED25519_PRIVATE_KEY_SIZE, ED25519_SIGNATURE_SIZE, ERROR_CRYPTO, ERROR_INVALID_PARAM, HOST_TO_NET_U64, log_debug, PACKET_TYPE_ACIP_SESSION_JOIN, and SET_ERRNO.

Referenced by acds_protocol_join().

◆ acds_transport_metadata_decode()

asciichat_error_t acds_transport_metadata_decode ( const void * bytes,
size_t length,
uint16_t * quic_port,
char * url,
size_t capacity )

Definition at line 525 of file acds_client.c.

526 {
527 if (!port || !url || !capacity || (!data && length))
528 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing discovery transport input or output");
529 *port = 0;
530 url[0] = 0;
531 if (!length)
532 return ASCIICHAT_OK;
533 const uint8_t *bytes = data;
534 if (length < 10 || memcmp(bytes, "ACQT", sizeof("ACQT") - 1) || bytes[4] != 1 || bytes[5])
535 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid discovery transport extension");
536 size_t size = ((size_t)bytes[8] << 8) | bytes[9];
537 if (size >= 512 || size >= capacity || length != 10 + size ||
538 (size && (size < 9 || memcmp(bytes + 10, "https://", sizeof("https://") - 1) || memchr(bytes + 10, 0, size))))
539 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid discovery WebTransport endpoint");
540 *port = (uint16_t)((uint16_t)bytes[6] << 8 | bytes[7]);
541 memcpy(url, bytes + 10, size);
542 url[size] = 0;
543 return ASCIICHAT_OK;
544}
unsigned short uint16_t
Definition common.h:61
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:76

References ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, and SET_ERRNO.

Referenced by acds_on_host_announcement_ex().

◆ acds_transport_metadata_encode()

asciichat_error_t acds_transport_metadata_encode ( uint16_t quic_port,
const char * url,
void * output,
size_t capacity,
size_t * length )

Definition at line 504 of file acds_client.c.

505 {
506 if (!url || !output || !length)
507 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing discovery transport output");
508 *length = 0;
509 size_t size = strnlen(url, (size_t)512);
510 if (size >= 512 || capacity < 10 + size || (size && (size < 9 || strncmp(url, "https://", sizeof("https://") - 1))))
511 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid discovery transport endpoint or capacity");
512 uint8_t *bytes = output;
513 memcpy(bytes, "ACQT", sizeof("ACQT") - 1);
514 bytes[4] = 1;
515 bytes[5] = 0;
516 bytes[6] = (uint8_t)(port >> 8);
517 bytes[7] = (uint8_t)port;
518 bytes[8] = (uint8_t)(size >> 8);
519 bytes[9] = (uint8_t)size;
520 memcpy(bytes + 10, url, size);
521 *length = 10 + size;
522 return ASCIICHAT_OK;
523}

References ASCIICHAT_OK, ERROR_INVALID_PARAM, and SET_ERRNO.

◆ acds_validate_timestamp()

bool acds_validate_timestamp ( uint64_t timestamp_ms,
uint32_t window_seconds )

Check if timestamp is within acceptable window.

Validates timestamp is recent (within window_seconds of current time) and not in the future.

Parameters
timestamp_msUnix milliseconds timestamp
window_secondsAcceptable age window (e.g., 300 for 5 minutes)
Returns
true if timestamp is valid, false if too old or in the future

Definition at line 172 of file acds_client.c.

172 {
173 uint64_t now_ms = time_ns_to_ms(time_get_realtime_ns());
174 uint64_t window_ms = (uint64_t)window_seconds * 1000;
175
176 if (timestamp_ms > now_ms + 60000) {
177 int64_t skew = (int64_t)timestamp_ms - (int64_t)now_ms;
178 log_warn("Timestamp is in the future: %llu > %llu (skew: %lld ms)", (unsigned long long)timestamp_ms,
179 (unsigned long long)now_ms, (long long)skew);
180 return false;
181 }
182
183 uint64_t min_valid_timestamp = (now_ms >= window_ms) ? (now_ms - window_ms) : 0;
184 if (timestamp_ms < min_valid_timestamp) {
185 int64_t age = (int64_t)now_ms - (int64_t)timestamp_ms;
186 log_warn("Timestamp is too old: %llu < %llu (age: %lld ms, max: %u seconds)", (unsigned long long)timestamp_ms,
187 (unsigned long long)min_valid_timestamp, (long long)age, window_seconds);
188 return false;
189 }
190
191 int64_t age = (int64_t)now_ms - (int64_t)timestamp_ms;
192 log_debug("Timestamp validation passed (age: %lld ms, window: %u seconds)", (long long)age, window_seconds);
193 return true;
194}
#define log_warn(...)
Log a WARN message.
Definition log/log.h:621

References log_debug, and log_warn.

Referenced by acds_create_key_set_collect().

◆ acds_verify_session_create()

asciichat_error_t acds_verify_session_create ( const uint8_t identity_pubkey[32],
uint64_t timestamp,
uint8_t capabilities,
uint8_t max_participants,
const uint8_t signature[64] )

Verify SESSION_CREATE signature.

Verifies Ed25519 signature matches the message fields.

Parameters
identity_pubkeyEd25519 public key (32 bytes)
timestampUnix milliseconds timestamp
capabilitiesCapabilities bitfield
max_participantsMaximum participants
signatureSignature to verify (64 bytes)
Returns
ASCIICHAT_OK if valid, ERROR_CRYPTO_VERIFY_FAILED if invalid

Definition at line 74 of file acds_client.c.

76 {
77 if (!identity_pubkey || !signature) {
78 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter");
79 }
80
81 // Build message: type (1 byte) || timestamp (8 bytes) || capabilities (1 byte) || max_participants (1 byte)
84
85 // Convert timestamp to network byte order and pack into message
86 uint64_t timestamp_net = HOST_TO_NET_U64(timestamp);
87 memcpy(&message[1], &timestamp_net, sizeof(timestamp_net));
88
89 message[9] = capabilities;
90 message[10] = max_participants;
91
92 // Verify using Ed25519
93 if (crypto_sign_verify_detached(signature, message, sizeof(message), identity_pubkey) != 0) {
94 log_warn("SESSION_CREATE signature verification failed");
95 return SET_ERRNO(ERROR_CRYPTO_VERIFICATION, "Invalid SESSION_CREATE signature");
96 }
97
98 log_debug("SESSION_CREATE signature verified successfully");
99 return ASCIICHAT_OK;
100}
@ ERROR_CRYPTO_VERIFICATION
Definition error_codes.h:97

References ACDS_CREATE_SIGNATURE_MESSAGE_SIZE, ASCIICHAT_OK, ED25519_PUBLIC_KEY_SIZE, ED25519_SIGNATURE_SIZE, ERROR_CRYPTO_VERIFICATION, ERROR_INVALID_PARAM, HOST_TO_NET_U64, log_debug, log_warn, PACKET_TYPE_ACIP_SESSION_CREATE, and SET_ERRNO.

Referenced by acds_create_key_set_collect().

◆ acds_verify_session_join()

asciichat_error_t acds_verify_session_join ( const uint8_t identity_pubkey[32],
uint64_t timestamp,
const char * session_string,
const uint8_t signature[64] )

Verify SESSION_JOIN signature.

Verifies Ed25519 signature matches the message fields.

Parameters
identity_pubkeyEd25519 public key (32 bytes)
timestampUnix milliseconds timestamp
session_stringSession string (null-terminated)
signatureSignature to verify (64 bytes)
Returns
ASCIICHAT_OK if valid, ERROR_CRYPTO_VERIFY_FAILED if invalid

Definition at line 137 of file acds_client.c.

139 {
140 if (!identity_pubkey || !session_string || !signature) {
141 return SET_ERRNO(ERROR_INVALID_PARAM, "NULL parameter");
142 }
143
144 size_t session_len = strlen(session_string);
145 if (session_len > ACIP_MAX_SESSION_STRING_LEN) {
146 return SET_ERRNO(ERROR_INVALID_PARAM, "Session string too long (max 48 chars)");
147 }
148
149 // Build message: type (1 byte) || timestamp (8 bytes) || session_string (variable length)
152
153 // Convert timestamp to network byte order and pack into message
154 uint64_t timestamp_net = HOST_TO_NET_U64(timestamp);
155 memcpy(&message[1], &timestamp_net, sizeof(timestamp_net));
156
157 // Copy session string (copy exactly session_len bytes, no null terminator in signature)
158 memcpy(&message[9], session_string, session_len);
159
160 size_t message_len = ACDS_SIGNATURE_PREFIX_SIZE + session_len;
161
162 // Verify using Ed25519
163 if (crypto_sign_verify_detached(signature, message, message_len, identity_pubkey) != 0) {
164 log_warn("SESSION_JOIN signature verification failed");
165 return SET_ERRNO(ERROR_CRYPTO_VERIFICATION, "Invalid SESSION_JOIN signature");
166 }
167
168 log_debug("SESSION_JOIN signature verified successfully");
169 return ASCIICHAT_OK;
170}

References ACDS_SIGNATURE_PREFIX_SIZE, ACIP_MAX_SESSION_STRING_LEN, ASCIICHAT_OK, ED25519_PUBLIC_KEY_SIZE, ED25519_SIGNATURE_SIZE, ERROR_CRYPTO_VERIFICATION, ERROR_INVALID_PARAM, HOST_TO_NET_U64, log_debug, log_warn, PACKET_TYPE_ACIP_SESSION_JOIN, and SET_ERRNO.