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

Go to the source code of this file.

Data Structures

struct  quic_config_t

Functions

asciichat_error_t quic_endpoint_set_http_server (quic_endpoint_t *endpoint, http_server_t *server)
asciichat_error_t quic_endpoint_open (const struct sockaddr *bind_address, socklen_t bind_length, bool listener, const quic_config_t *config, quic_endpoint_t **out)
asciichat_error_t quic_endpoint_address (quic_endpoint_t *endpoint, struct sockaddr_storage *address, socklen_t *length)
asciichat_error_t quic_connect (quic_endpoint_t *endpoint, const struct sockaddr *remote, socklen_t remote_length, const char *server_name, acip_transport_t **out)
asciichat_error_t quic_accept (quic_endpoint_t *endpoint, acip_transport_t **out)
asciichat_error_t quic_transport_peer_address (acip_transport_t *transport, struct sockaddr_storage *address, socklen_t *length)
asciichat_error_t quic_transport_begin_security (acip_transport_t *transport, crypto_context_t *crypto)
bool quic_transport_security_ready (acip_transport_t *transport)
asciichat_error_t quic_transport_wait_security (acip_transport_t *transport, uint64_t timeout_ns)
asciichat_error_t quic_transport_allow_media (acip_transport_t *transport)
asciichat_error_t quic_release (quic_endpoint_t *endpoint, acip_transport_t **transport)
asciichat_error_t quic_endpoint_stop (quic_endpoint_t *endpoint)
asciichat_error_t quic_endpoint_destroy (quic_endpoint_t **endpoint)
asciichat_error_t quic_endpoint_migrate (quic_endpoint_t *endpoint, const struct sockaddr *local_address, socklen_t length)

Function Documentation

◆ quic_accept()

asciichat_error_t quic_accept ( quic_endpoint_t * endpoint,
acip_transport_t ** out )

Nonblocking accept. Returns ERROR_NETWORK_TIMEOUT when none is available. A returned transport is owned and may still be negotiating TLS.

Definition at line 255 of file endpoint.c.

255 {
256 if (!out)
257 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC accept output");
258 *out = NULL;
259 if (!endpoint || !endpoint->listener)
260 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC listener");
261 mutex_lock(&endpoint->lane);
262 endpoint_transport_t *item = endpoint->transports;
263 bool generic_http3 = endpoint->tls->http3 && !endpoint->tls->webtransport;
264 while (item && (item->claimed || generic_http3 ||
266 item = item->next;
268 if (item) {
269 item->claimed = true;
270 *out = item->transport;
271 } else {
272 result = endpoint->terminal_error ? SET_ERRNO(endpoint->terminal_error, "QUIC endpoint failed")
273 : endpoint->stopping ? SET_ERRNO(ERROR_INVALID_STATE, "QUIC endpoint stopped")
274 : SET_ERRNO(ERROR_NETWORK_TIMEOUT, "No QUIC connection is available");
275 }
276 mutex_unlock(&endpoint->lane);
277 return result;
278}
#define SET_ERRNO(code,...)
struct endpoint_transport endpoint_transport_t
This is the handoff point for acip quic endpoint. Callers fill lane, tls, udp, worker before passing ...
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_INVALID_STATE
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
@ ERROR_NETWORK_TIMEOUT
Definition error_codes.h:75
bool quic_connection_accept_ready(const quic_connection_t *connection)
static bool size_t gotel_query_t * out
Definition queries.h:8
struct endpoint_transport * next
Definition endpoint.c:18
quic_connection_t * connection
Definition endpoint.c:19
acip_transport_t * transport
Definition endpoint.c:20
mutex_t lane
Definition endpoint.c:25
endpoint_transport_t * transports
Definition endpoint.c:29
bool listener
Definition endpoint.c:31
quic_tls_t * tls
Definition endpoint.c:26
asciichat_error_t terminal_error
Definition endpoint.c:32
bool http3
Definition tls.h:19
bool webtransport
Definition tls.h:18

References ASCIICHAT_OK, endpoint_transport::claimed, endpoint_transport::connection, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, ERROR_NETWORK_TIMEOUT, quic_tls_t::http3, quic_endpoint::lane, quic_endpoint::listener, endpoint_transport::next, out, quic_connection_accept_ready(), SET_ERRNO, quic_endpoint::stopping, quic_endpoint::terminal_error, quic_endpoint::tls, endpoint_transport::transport, quic_endpoint::transports, and quic_tls_t::webtransport.

◆ quic_connect()

asciichat_error_t quic_connect ( quic_endpoint_t * endpoint,
const struct sockaddr * remote,
socklen_t remote_length,
const char * server_name,
acip_transport_t ** out )

Start a client connection to a resolved address. server_name is used for certificate identity verification and is required even for an IP address. The returned transport is owned by the caller and is initially negotiating TLS. Check capabilities for TLS readiness before ACIP handshake. No application media is enabled until ACIP authentication and readiness.

Definition at line 229 of file endpoint.c.

230 {
231 if (!out)
232 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC transport output");
233 *out = NULL;
234 if (!endpoint || endpoint->listener || !remote || !server_name || !*server_name)
235 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC connect configuration");
236 mutex_lock(&endpoint->lane);
237 quic_connection_t *connection = NULL;
238 asciichat_error_t result = endpoint->stopping ? SET_ERRNO(ERROR_INVALID_STATE, "QUIC endpoint stopped")
239 : endpoint->terminal_error ? SET_ERRNO(endpoint->terminal_error, "QUIC endpoint failed")
240 : endpoint->count >= QUIC_ENDPOINT_MAX_TRANSPORTS
241 ? SET_ERRNO(ERROR_BUFFER_FULL, "QUIC endpoint transport limit reached")
242 : quic_udp_connect(endpoint->udp, endpoint->tls, server_name, remote, remote_length,
243 time_get_ns(), &connection);
244 if (result == ASCIICHAT_OK) {
245 result = attach(endpoint, connection, true, out);
246 if (result != ASCIICHAT_OK)
247 (void)quic_udp_remove(endpoint->udp, connection);
248 }
249 mutex_unlock(&endpoint->lane);
250 if (result == ASCIICHAT_OK)
251 wake_endpoint(endpoint);
252 return result;
253}
#define QUIC_ENDPOINT_MAX_TRANSPORTS
Definition endpoint.c:7
@ ERROR_BUFFER_FULL
struct quic_connection quic_connection_t
bool stopping
Definition endpoint.c:31
quic_udp_endpoint_t * udp
Definition endpoint.c:27
asciichat_error_t quic_udp_connect(quic_udp_endpoint_t *endpoint, quic_tls_t *client_tls, const char *server_name, const struct sockaddr *remote, socklen_t remote_length, uint64_t now_ns, quic_connection_t **out)
Definition udp.c:144
asciichat_error_t quic_udp_remove(quic_udp_endpoint_t *endpoint, quic_connection_t *connection)
Definition udp.c:356

References ASCIICHAT_OK, quic_endpoint::count, ERROR_BUFFER_FULL, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, quic_endpoint::lane, quic_endpoint::listener, out, QUIC_ENDPOINT_MAX_TRANSPORTS, quic_udp_connect(), quic_udp_remove(), SET_ERRNO, quic_endpoint::stopping, quic_endpoint::terminal_error, quic_endpoint::tls, and quic_endpoint::udp.

◆ quic_endpoint_address()

asciichat_error_t quic_endpoint_address ( quic_endpoint_t * endpoint,
struct sockaddr_storage * address,
socklen_t * length )

Definition at line 219 of file endpoint.c.

220 {
221 if (!endpoint)
222 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC endpoint");
223 mutex_lock(&endpoint->lane);
224 asciichat_error_t result = quic_udp_endpoint_address(endpoint->udp, address, length);
225 mutex_unlock(&endpoint->lane);
226 return result;
227}
asciichat_error_t quic_udp_endpoint_address(const quic_udp_endpoint_t *endpoint, struct sockaddr_storage *address, socklen_t *length)
Definition udp.c:106

References ERROR_INVALID_PARAM, quic_endpoint::lane, quic_udp_endpoint_address(), SET_ERRNO, and quic_endpoint::udp.

◆ quic_endpoint_destroy()

asciichat_error_t quic_endpoint_destroy ( quic_endpoint_t ** endpoint)

Stop must succeed and all claimed transports must be destroyed first. Lifecycle calls and destruction must not run concurrently with other calls.

Definition at line 353 of file endpoint.c.

353 {
354 if (!endpoint || !*endpoint)
355 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC endpoint destruction");
356 if (!(*endpoint)->stopped || (*endpoint)->count)
357 return SET_ERRNO(ERROR_INVALID_STATE, "Stop QUIC endpoint and release all transports first");
358 quic_udp_endpoint_destroy(&(*endpoint)->udp);
359 quic_tls_destroy(&(*endpoint)->tls);
360 mutex_destroy(&(*endpoint)->lane);
361 SAFE_FREE(*endpoint);
362 *endpoint = NULL;
363 return ASCIICHAT_OK;
364}
#define SAFE_FREE(ptr)
Definition common.h:377
void quic_tls_destroy(quic_tls_t **tls)
Definition tls.c:202
void quic_udp_endpoint_destroy(quic_udp_endpoint_t **endpoint)
Definition udp.c:372

References ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, quic_tls_destroy(), quic_udp_endpoint_destroy(), SAFE_FREE, and SET_ERRNO.

Referenced by api_server_main(), network_connection_open(), and session_quic_listeners_close().

◆ quic_endpoint_migrate()

asciichat_error_t quic_endpoint_migrate ( quic_endpoint_t * endpoint,
const struct sockaddr * local_address,
socklen_t length )

Move a single-connection client endpoint to a new concrete local address. Port zero requests a new ephemeral port. TLS, ACIP keys, and stream state survive; ngtcp2 validates the new path after the immediate switch. Migration requires handshake confirmation, a spare peer CID, and peer permission. Pause transport users first, as for endpoint lifecycle calls. This call stops and restarts the worker to avoid closing a socket under its readiness wait. A rejected migration retains the original socket and live connection. The new address must have the same family as the existing remote address.

Definition at line 366 of file endpoint.c.

367 {
368 if (!endpoint || endpoint->listener || !local_address)
369 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC client endpoint migration");
370 mutex_lock(&endpoint->lane);
371 bool available = !endpoint->stopping && !endpoint->terminal_error && endpoint->count == 1 &&
372 endpoint->transports->connection && endpoint->worker;
373 mutex_unlock(&endpoint->lane);
374 if (!available)
375 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC migration requires one live client connection");
376 asciichat_error_t result = quic_worker_stop(&endpoint->worker);
377 if (result != ASCIICHAT_OK)
378 return result;
379 mutex_lock(&endpoint->lane);
380 result = quic_udp_migrate(endpoint->udp, local_address, length, time_get_ns());
381 asciichat_error_t restart =
382 quic_worker_start_locked_failure(endpoint->udp, &endpoint->lane, connection_failed, endpoint, &endpoint->worker);
383 if (restart != ASCIICHAT_OK)
384 (void)connection_failed(NULL, restart, endpoint);
385 mutex_unlock(&endpoint->lane);
386 return restart != ASCIICHAT_OK ? restart : result;
387}
size_t count
Definition endpoint.c:30
quic_worker_t * worker
Definition endpoint.c:28
asciichat_error_t quic_udp_migrate(quic_udp_endpoint_t *endpoint, const struct sockaddr *address, socklen_t length, uint64_t now_ns)
Definition udp.c:383
asciichat_error_t quic_worker_start_locked_failure(quic_udp_endpoint_t *endpoint, mutex_t *lane, quic_worker_failure_fn failure, void *context, quic_worker_t **out)
Definition worker.c:107
asciichat_error_t quic_worker_stop(quic_worker_t **worker)
Definition worker.c:118

References ASCIICHAT_OK, endpoint_transport::connection, quic_endpoint::count, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, quic_endpoint::lane, quic_endpoint::listener, quic_udp_migrate(), quic_worker_start_locked_failure(), quic_worker_stop(), SET_ERRNO, quic_endpoint::stopping, quic_endpoint::terminal_error, quic_endpoint::transports, quic_endpoint::udp, and quic_endpoint::worker.

◆ quic_endpoint_open()

asciichat_error_t quic_endpoint_open ( const struct sockaddr * bind_address,
socklen_t bind_length,
bool listener,
const quic_config_t * config,
quic_endpoint_t ** out )

Bind a concrete IPv4 or IPv6 local address and start the endpoint worker. Configuration strings are consumed during this call. The caller retains address storage. A listener requires a matching certificate and key.

Definition at line 131 of file endpoint.c.

132 {
133 if (!out)
134 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC endpoint output");
135 *out = NULL;
136 if (!address || !config)
137 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC endpoint configuration");
138 quic_endpoint_t *endpoint = SAFE_CALLOC(1, sizeof(*endpoint), quic_endpoint_t *);
139 if (!endpoint)
140 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate QUIC endpoint");
141 if (mutex_init(&endpoint->lane, "quic_endpoint") != 0) {
142 SAFE_FREE(endpoint);
143 return SET_ERRNO(ERROR_THREAD, "Cannot initialize QUIC endpoint lane");
144 }
145 bool webtransport = config->webtransport_origin || config->webtransport_path;
146 bool http3 = webtransport || config->enable_http3 || config->http_server;
147 if (http3 && config->alpn && strcmp(config->alpn, "h3") != 0) {
148 mutex_destroy(&endpoint->lane);
149 SAFE_FREE(endpoint);
150 return SET_ERRNO(ERROR_INVALID_PARAM, "HTTP/3 requires the h3 ALPN");
151 }
152 if (webtransport &&
153 (!listener || !config->enable_datagrams || !config->webtransport_origin || !config->webtransport_path ||
154 strncmp(config->webtransport_origin, "https://", sizeof("https://") - 1) != 0 ||
155 config->webtransport_path[0] != '/' ||
156 strnlen(config->webtransport_origin, sizeof(endpoint->tls->webtransport_origin)) >=
157 sizeof(endpoint->tls->webtransport_origin) ||
158 strnlen(config->webtransport_path, sizeof(endpoint->tls->webtransport_path)) >=
159 sizeof(endpoint->tls->webtransport_path) ||
160 (config->alpn && strcmp(config->alpn, "h3") != 0))) {
161 mutex_destroy(&endpoint->lane);
162 SAFE_FREE(endpoint);
163 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid WebTransport listener configuration");
164 }
165 const char *alpn = config->alpn ? config->alpn : http3 ? "h3" : "acip/1";
166 asciichat_error_t result =
167 listener ? quic_tls_server_create(alpn, config->certificate_file, config->private_key_file, &endpoint->tls)
168 : quic_tls_client_create(alpn, config->ca_file, &endpoint->tls);
169 if (result == ASCIICHAT_OK) {
170 endpoint->tls->enable_datagrams = config->enable_datagrams;
171 endpoint->tls->webtransport = webtransport;
172 endpoint->tls->http3 = http3;
173 endpoint->tls->accept_native = webtransport && config->accept_native;
174 endpoint->tls->http_server = config->http_server;
175 if (endpoint->tls->accept_native) {
176 static const unsigned char protocols[] = {2, 'h', '3', 6, 'a', 'c', 'i', 'p', '/', '1'};
177 memcpy(endpoint->tls->alpn, protocols, sizeof(protocols));
178 endpoint->tls->alpn_length = sizeof(protocols);
179 }
180 if (webtransport) {
181 memcpy(endpoint->tls->webtransport_origin, config->webtransport_origin,
182 strlen(config->webtransport_origin) + (size_t)1);
183 memcpy(endpoint->tls->webtransport_path, config->webtransport_path,
184 strlen(config->webtransport_path) + (size_t)1);
185 }
188 endpoint->listener = listener;
189 result = quic_udp_endpoint_create(address, length, listener ? endpoint->tls : NULL,
190 listener ? accept_connection : NULL, listener ? endpoint : NULL, &endpoint->udp);
191 }
192 if (result == ASCIICHAT_OK)
193 result = quic_worker_start_locked_failure(endpoint->udp, &endpoint->lane, connection_failed, endpoint,
194 &endpoint->worker);
195 if (result != ASCIICHAT_OK) {
196 quic_udp_endpoint_destroy(&endpoint->udp);
197 quic_tls_destroy(&endpoint->tls);
198 mutex_destroy(&endpoint->lane);
199 SAFE_FREE(endpoint);
200 return result;
201 }
202 *out = endpoint;
203 return ASCIICHAT_OK;
204}
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
@ ERROR_MEMORY
Definition error_codes.h:51
@ ERROR_THREAD
struct quic_endpoint quic_endpoint_t
if(!queries||!out||index >=DATABASE_QUERY_COUNT) return false
bool prefer_visual_datagrams
Definition quic.h:22
const char * private_key_file
Definition quic.h:16
bool enable_datagrams
Definition quic.h:20
http_server_t * http_server
Definition quic.h:26
const char * alpn
Definition quic.h:14
bool prefer_audio_datagrams
Definition quic.h:23
bool accept_native
Definition quic.h:21
const char * certificate_file
Definition quic.h:15
bool enable_http3
Definition quic.h:24
const char * webtransport_path
Definition quic.h:19
const char * webtransport_origin
Definition quic.h:18
bool prefer_visual_datagrams
Definition endpoint.c:31
bool prefer_audio_datagrams
Definition endpoint.c:31
bool accept_native
Definition tls.h:20
unsigned char alpn[256]
Definition tls.h:13
char webtransport_origin[512]
Definition tls.h:22
unsigned int alpn_length
Definition tls.h:14
char webtransport_path[512]
Definition tls.h:23
http_server_t * http_server
Definition tls.h:21
bool enable_datagrams
Definition tls.h:17
asciichat_error_t quic_tls_client_create(const char *alpn, const char *ca_file, quic_tls_t **out)
Definition tls.c:90
asciichat_error_t quic_tls_server_create(const char *alpn, const char *certificate_file, const char *private_key_file, quic_tls_t **out)
Definition tls.c:67
asciichat_error_t quic_udp_endpoint_create(const struct sockaddr *address, socklen_t length, quic_tls_t *server_tls, quic_udp_accept_fn accept, void *context, quic_udp_endpoint_t **out)
Definition udp.c:67

References quic_config_t::accept_native, quic_tls_t::accept_native, quic_config_t::alpn, quic_tls_t::alpn, quic_tls_t::alpn_length, ASCIICHAT_OK, quic_config_t::ca_file, quic_config_t::certificate_file, quic_config_t::enable_datagrams, quic_tls_t::enable_datagrams, quic_config_t::enable_http3, ERROR_INVALID_PARAM, ERROR_MEMORY, ERROR_THREAD, quic_tls_t::http3, quic_config_t::http_server, quic_tls_t::http_server, quic_endpoint::lane, quic_endpoint::listener, out, quic_config_t::prefer_audio_datagrams, quic_endpoint::prefer_audio_datagrams, quic_config_t::prefer_visual_datagrams, quic_endpoint::prefer_visual_datagrams, quic_config_t::private_key_file, quic_tls_client_create(), quic_tls_destroy(), quic_tls_server_create(), quic_udp_endpoint_create(), quic_udp_endpoint_destroy(), quic_worker_start_locked_failure(), SAFE_CALLOC, SAFE_FREE, SET_ERRNO, quic_endpoint::tls, quic_endpoint::udp, quic_tls_t::webtransport, quic_config_t::webtransport_origin, quic_tls_t::webtransport_origin, quic_config_t::webtransport_path, quic_tls_t::webtransport_path, and quic_endpoint::worker.

Referenced by api_server_main(), and session_quic_listeners_open().

◆ quic_endpoint_set_http_server()

asciichat_error_t quic_endpoint_set_http_server ( quic_endpoint_t * endpoint,
http_server_t * server )

Attach the shared HTTP handler before accepting new HTTP/3 streams.

Definition at line 206 of file endpoint.c.

206 {
207 if (!endpoint || !endpoint->listener || !endpoint->tls || !endpoint->tls->http3)
208 return SET_ERRNO(ERROR_INVALID_PARAM, "Endpoint is not an HTTP/3 listener");
209 mutex_lock(&endpoint->lane);
211 if (endpoint->stopping || endpoint->count)
212 result = SET_ERRNO(ERROR_INVALID_STATE, "HTTP/3 handler must be attached before connections");
213 else
214 endpoint->tls->http_server = server;
215 mutex_unlock(&endpoint->lane);
216 return result;
217}

References ASCIICHAT_OK, quic_endpoint::count, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, quic_tls_t::http3, quic_tls_t::http_server, quic_endpoint::lane, quic_endpoint::listener, SET_ERRNO, quic_endpoint::stopping, and quic_endpoint::tls.

◆ quic_endpoint_stop()

asciichat_error_t quic_endpoint_stop ( quic_endpoint_t * endpoint)

Stop and join the worker and interrupt remaining transports. Unclaimed accepts are discarded. Claimed transports must still be destroyed.

Definition at line 308 of file endpoint.c.

308 {
309 if (!endpoint)
310 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC endpoint");
311 if (endpoint->stopped)
312 return ASCIICHAT_OK;
313 mutex_lock(&endpoint->lane);
314 endpoint->stopping = true;
315 mutex_unlock(&endpoint->lane);
316 asciichat_error_t worker_result = endpoint->worker ? quic_worker_stop(&endpoint->worker) : ASCIICHAT_OK;
317 if (endpoint->worker)
318 return worker_result;
320 for (;;) {
321 mutex_lock(&endpoint->lane);
322 endpoint_transport_t *item = endpoint->transports;
323 while (item && item->claimed)
324 item = item->next;
325 if (item)
326 item->claimed = true;
327 mutex_unlock(&endpoint->lane);
328 if (!item)
329 break;
330 acip_transport_t *transport = item->transport;
331 result = quic_release(endpoint, &transport);
332 if (result != ASCIICHAT_OK)
333 return result;
334 }
335 mutex_lock(&endpoint->lane);
336 for (endpoint_transport_t *item = endpoint->transports; item; item = item->next) {
338 if (result != ASCIICHAT_OK)
339 break;
340 if (item->connection) {
341 result = quic_udp_remove(endpoint->udp, item->connection);
342 if (result != ASCIICHAT_OK)
343 break;
344 item->connection = NULL;
345 }
346 }
347 if (result == ASCIICHAT_OK)
348 endpoint->stopped = true;
349 mutex_unlock(&endpoint->lane);
350 return result == ASCIICHAT_OK ? worker_result : result;
351}
asciichat_error_t quic_release(quic_endpoint_t *endpoint, acip_transport_t **transport)
Definition endpoint.c:280
@ ERROR_NETWORK
Definition error_codes.h:72
struct acip_transport acip_transport_t
Forward declaration of ACIP transport.
Definition host.h:506
asciichat_error_t quic_transport_fail_on_lane(acip_transport_t *transport, asciichat_error_t reason)

References ASCIICHAT_OK, endpoint_transport::claimed, endpoint_transport::connection, ERROR_INVALID_PARAM, ERROR_NETWORK, quic_endpoint::lane, endpoint_transport::next, quic_release(), quic_transport_fail_on_lane(), quic_udp_remove(), quic_worker_stop(), SET_ERRNO, quic_endpoint::stopped, quic_endpoint::stopping, endpoint_transport::transport, quic_endpoint::transports, quic_endpoint::udp, and quic_endpoint::worker.

Referenced by api_server_main(), network_connection_open(), and session_quic_listeners_close().

◆ quic_release()

asciichat_error_t quic_release ( quic_endpoint_t * endpoint,
acip_transport_t ** transport )

Stop all users, then release through the endpoint, or destroy the transport directly using acip_transport_destroy. The endpoint must outlive it.

Definition at line 280 of file endpoint.c.

280 {
281 if (!endpoint || !transport || !*transport)
282 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC transport release");
283 mutex_lock(&endpoint->lane);
284 endpoint_transport_t **link = &endpoint->transports;
285 while (*link && (*link)->transport != *transport)
286 link = &(*link)->next;
287 if (!*link || !(*link)->claimed) {
288 mutex_unlock(&endpoint->lane);
289 return SET_ERRNO(ERROR_INVALID_PARAM, "Transport does not belong to QUIC endpoint");
290 }
291 endpoint_transport_t *item = *link;
293 if (result == ASCIICHAT_OK && item->connection)
294 result = quic_udp_remove(endpoint->udp, item->connection);
295 if (result == ASCIICHAT_OK) {
296 *link = item->next;
297 --endpoint->count;
298 }
299 mutex_unlock(&endpoint->lane);
300 if (result != ASCIICHAT_OK)
301 return result;
303 SAFE_FREE(item);
304 *transport = NULL;
305 return ASCIICHAT_OK;
306}
void acip_transport_destroy(acip_transport_t *transport)
Destroy transport and free all resources.

References acip_transport_destroy(), ASCIICHAT_OK, endpoint_transport::claimed, endpoint_transport::connection, quic_endpoint::count, ERROR_INVALID_PARAM, ERROR_NETWORK, quic_endpoint::lane, endpoint_transport::next, quic_transport_fail_on_lane(), quic_udp_remove(), SAFE_FREE, SET_ERRNO, endpoint_transport::transport, quic_endpoint::transports, and quic_endpoint::udp.

Referenced by quic_endpoint_stop().

◆ quic_transport_allow_media()

asciichat_error_t quic_transport_allow_media ( acip_transport_t * transport)

Definition at line 378 of file quic/transport.c.

378 {
379 if (!transport || transport->methods != &quic_methods)
380 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC transport");
381 quic_transport_t *quic = transport->impl_data;
382 lane_lock(quic);
384 : SET_ERRNO(quic->failure, "QUIC transport is closed");
385 lane_unlock(quic);
386 return result;
387}
asciichat_error_t quic_connection_allow_media(quic_connection_t *connection)
void * impl_data
Transport-specific state.
const acip_transport_methods_t * methods
Method table (virtual functions).
quic_connection_t * connection

References quic_transport_t::connected, quic_transport_t::connection, ERROR_INVALID_PARAM, quic_transport_t::failure, acip_transport::impl_data, acip_transport::methods, quic_connection_allow_media(), and SET_ERRNO.

◆ quic_transport_begin_security()

asciichat_error_t quic_transport_begin_security ( acip_transport_t * transport,
crypto_context_t * crypto )

Start the authenticated transition after the existing ACIP handshake. crypto is borrowed and must outlive the transport. After this call the caller must not access or rekey it until the transport has been released.

Definition at line 324 of file quic/transport.c.

324 {
325 if (!transport || transport->methods != &quic_methods || !crypto)
326 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC transport security context");
327 quic_transport_t *quic = transport->impl_data;
328 lane_lock(quic);
330 : SET_ERRNO(quic->failure, "QUIC transport is closed");
331 if (result == ASCIICHAT_OK) {
332 transport->crypto_ctx = crypto;
333 result = acip_security_activate(transport);
334 if (quic->wake)
335 quic->wake(quic->wake_context);
336 }
337 lane_unlock(quic);
338 if (result == ASCIICHAT_OK && quic->lane)
339 result = acip_outbound_create(transport);
340 return result;
341}
asciichat_error_t acip_outbound_create(acip_transport_t *transport)
asciichat_error_t acip_security_activate(acip_transport_t *transport)
asciichat_error_t quic_connection_enable_security(quic_connection_t *connection, crypto_context_t *crypto)
crypto_context_t * crypto_ctx
Optional encryption context.
void(* wake)(void *)

References acip_outbound_create(), acip_security_activate(), ASCIICHAT_OK, quic_transport_t::connected, quic_transport_t::connection, acip_transport::crypto_ctx, ERROR_INVALID_PARAM, quic_transport_t::failure, acip_transport::impl_data, quic_transport_t::lane, acip_transport::methods, quic_connection_enable_security(), SET_ERRNO, quic_transport_t::wake, and quic_transport_t::wake_context.

◆ quic_transport_peer_address()

asciichat_error_t quic_transport_peer_address ( acip_transport_t * transport,
struct sockaddr_storage * address,
socklen_t * length )

Copy the current peer address. It may change after a validated migration.

Definition at line 52 of file quic/transport.c.

53 {
54 if (!transport || transport->methods != &quic_methods || !address || !length)
55 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC peer address query");
56 quic_transport_t *quic = transport->impl_data;
57 if (quic->lane)
58 mutex_lock(quic->lane);
59 asciichat_error_t result = quic->connected ? quic_connection_peer_address(quic->connection, address, length)
60 : SET_ERRNO(quic->failure, "QUIC transport is closed");
61 if (quic->lane)
62 mutex_unlock(quic->lane);
63 return result;
64}
asciichat_error_t quic_connection_peer_address(const quic_connection_t *connection, struct sockaddr_storage *address, socklen_t *length)

References quic_transport_t::connected, quic_transport_t::connection, ERROR_INVALID_PARAM, quic_transport_t::failure, acip_transport::impl_data, quic_transport_t::lane, acip_transport::methods, quic_connection_peer_address(), and SET_ERRNO.

◆ quic_transport_security_ready()

bool quic_transport_security_ready ( acip_transport_t * transport)

Definition at line 343 of file quic/transport.c.

343 {
344 if (!transport || transport->methods != &quic_methods)
345 return false;
346 quic_transport_t *quic = transport->impl_data;
347 lane_lock(quic);
348 bool ready = quic->connected && quic_connection_security_ready(quic->connection);
349 lane_unlock(quic);
350 return ready;
351}
bool quic_connection_security_ready(const quic_connection_t *connection)

References quic_transport_t::connected, quic_transport_t::connection, acip_transport::impl_data, acip_transport::methods, and quic_connection_security_ready().

◆ quic_transport_wait_security()

asciichat_error_t quic_transport_wait_security ( acip_transport_t * transport,
uint64_t timeout_ns )

Wait at most timeout_ns for the authenticated readiness exchange.

Definition at line 353 of file quic/transport.c.

353 {
354 if (!transport || transport->methods != &quic_methods)
355 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC transport");
356 quic_transport_t *quic = transport->impl_data;
357 if (!quic->lane)
358 return SET_ERRNO(ERROR_NOT_SUPPORTED, "QUIC security wait requires a serialized endpoint");
359 uint64_t start = time_get_ns();
360 lane_lock(quic);
361 while (quic->connected && !quic_connection_security_ready(quic->connection)) {
362 uint64_t elapsed = time_get_ns() - start;
363 if (elapsed >= timeout_ns) {
364 lane_unlock(quic);
365 return SET_ERRNO(ERROR_NETWORK_TIMEOUT, "QUIC security readiness timed out");
366 }
367 int rc = cond_timedwait(&quic->security_changed, quic->lane, timeout_ns - elapsed);
368 if (rc != 0 && rc != ETIMEDOUT) {
369 lane_unlock(quic);
370 return SET_ERRNO(ERROR_THREAD, "QUIC security readiness wait failed");
371 }
372 }
373 asciichat_error_t result = quic->connected ? ASCIICHAT_OK : SET_ERRNO(quic->failure, "QUIC transport is closed");
374 lane_unlock(quic);
375 return result;
376}
unsigned long long uint64_t
Definition common.h:63
@ ERROR_NOT_SUPPORTED
Definition error_codes.h:69
#define ETIMEDOUT
asciichat_error_t failure

References ASCIICHAT_OK, quic_transport_t::connected, quic_transport_t::connection, ERROR_INVALID_PARAM, ERROR_NETWORK_TIMEOUT, ERROR_NOT_SUPPORTED, ERROR_THREAD, ETIMEDOUT, quic_transport_t::failure, acip_transport::impl_data, quic_transport_t::lane, acip_transport::methods, quic_connection_security_ready(), quic_transport_t::security_changed, and SET_ERRNO.