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

Go to the source code of this file.

Typedefs

typedef struct http_server_http3 http_server_http3_t

Functions

asciichat_error_t http_server_http3_create (const char *origin, const char *path, int64_t control_stream, int64_t encoder_stream, int64_t decoder_stream, http_server_t *http_server, const char *peer_address, http_server_http3_t **out)
asciichat_error_t http_server_http3_read (http_server_http3_t *server, int64_t stream_id, const uint8_t *data, size_t length, bool fin, uint64_t now_ns, size_t *consumed)
asciichat_error_t http_server_http3_write (http_server_http3_t *server, int64_t *stream_id, bool *fin, nghttp3_vec *vectors, size_t capacity, size_t *count)
asciichat_error_t http_server_http3_wrote (http_server_http3_t *server, int64_t stream_id, size_t length)
asciichat_error_t http_server_http3_ack (http_server_http3_t *server, int64_t stream_id, uint64_t length)
bool http_server_http3_accepted (const http_server_http3_t *server, int64_t *session_id)
void http_server_http3_destroy (http_server_http3_t **server)

Typedef Documentation

◆ http_server_http3_t

Definition at line 11 of file http3.h.

Function Documentation

◆ http_server_http3_accepted()

bool http_server_http3_accepted ( const http_server_http3_t * server,
int64_t * session_id )

Definition at line 549 of file http3.c.

549 {
550 if (!server || !server->accepted)
551 return false;
552 if (session_id)
553 *session_id = server->request;
554 return true;
555}
uint8_t session_id[SESSION_ID_SIZE]
int64_t request
Definition http3.c:23

References http_server_http3::accepted, http_server_http3::request, and session_id.

Referenced by quic_connection_datagram_payload(), and quic_connection_webtransport_ready().

◆ http_server_http3_ack()

asciichat_error_t http_server_http3_ack ( http_server_http3_t * server,
int64_t stream_id,
uint64_t length )

Definition at line 535 of file http3.c.

535 {
536 if (!server)
537 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/3 server");
538 if (stream_id == server->control) {
539 if (length > server->settings_written - server->settings_acked)
540 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/3 settings acknowledgement");
541 server->settings_acked += (size_t)length;
542 return ASCIICHAT_OK;
543 }
544 int result = nghttp3_conn_add_ack_offset(server->http, stream_id, length);
545 return result ? SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot acknowledge HTTP/3 output: %s", nghttp3_strerror(result))
546 : ASCIICHAT_OK;
547}
#define SET_ERRNO(code,...)
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:76
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
int64_t control
Definition http3.c:23
nghttp3_conn * http
Definition http3.c:22
size_t settings_written
Definition http3.c:26
size_t settings_acked
Definition http3.c:26

References ASCIICHAT_OK, http_server_http3::control, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, http_server_http3::http, SET_ERRNO, http_server_http3::settings_acked, and http_server_http3::settings_written.

◆ http_server_http3_create()

asciichat_error_t http_server_http3_create ( const char * origin,
const char * path,
int64_t control_stream,
int64_t encoder_stream,
int64_t decoder_stream,
http_server_t * http_server,
const char * peer_address,
http_server_http3_t ** out )

Definition at line 406 of file http3.c.

408 {
409 if (!out)
410 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing HTTP/3 server output");
411 *out = NULL;
412 if ((!http_server && (!origin || !path)) ||
413 (origin && strnlen(origin, sizeof(((http_server_http3_t *)0)->origin)) >= H3_MAX_ORIGIN) ||
414 (path && strnlen(path, sizeof(((http_server_http3_t *)0)->path)) >= H3_MAX_PATH) ||
415 (!http_server && (strncmp(origin, "https://", sizeof("https://") - 1) || path[0] != '/')) || control < 0 ||
416 encoder < 0 || decoder < 0 || control == encoder || control == decoder || encoder == decoder ||
417 (control & 3) != 3 || (encoder & 3) != 3 || (decoder & 3) != 3)
418 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/3 WebTransport configuration");
419 http_server_http3_t *server = SAFE_CALLOC(1, sizeof(*server), http_server_http3_t *);
420 if (!server)
421 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate HTTP/3 server");
422 if (origin)
423 memcpy(server->origin, origin, strlen(origin) + (size_t)1);
424 if (path)
425 memcpy(server->path, path, strlen(path) + (size_t)1);
426 server->control = control;
427 server->http_server = http_server;
428 safe_snprintf(server->peer_address, sizeof(server->peer_address), "%s", peer_address ? peer_address : "unknown");
429 server->request = -1;
430 make_settings(server);
431 nghttp3_callbacks callbacks = {.stream_close = close_stream,
432 .begin_headers = begin_headers,
433 .recv_header = receive_header,
434 .end_headers = end_headers,
435 .recv_data = receive_data,
436 .end_stream = end_stream,
437 .recv_settings2 = receive_settings};
438 nghttp3_settings settings;
439 nghttp3_settings_default(&settings);
440 settings.enable_connect_protocol = 1;
441 settings.h3_datagram = 1;
442 settings.qpack_max_dtable_capacity = 0;
443 settings.qpack_encoder_max_dtable_capacity = 0;
444 settings.qpack_blocked_streams = 0;
445 settings.max_field_section_size = H3_MAX_HEADER_BYTES;
446 int result = nghttp3_conn_server_new(&server->http, &callbacks, &settings, NULL, server);
447 if (!result)
448 result = nghttp3_conn_bind_control_stream(server->http, control);
449 if (!result)
450 result = nghttp3_conn_bind_qpack_streams(server->http, encoder, decoder);
451 if (result) {
453 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot initialize HTTP/3: %s", nghttp3_strerror(result));
454 }
455 nghttp3_conn_set_max_client_streams_bidi(server->http, 128);
456 *out = server;
457 return ASCIICHAT_OK;
458}
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
@ ERROR_MEMORY
Definition error_codes.h:51
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Platform-safe snprintf wrapper.
#define H3_MAX_HEADER_BYTES
Definition http3.c:7
void http_server_http3_destroy(http_server_http3_t **server)
Definition http3.c:557
#define H3_MAX_PATH
Definition http3.c:9
#define H3_MAX_ORIGIN
Definition http3.c:8
struct http_server_http3 http_server_http3_t
Definition http3.h:11
static bool size_t gotel_query_t * out
Definition queries.h:8
char origin[512U]
Definition http3.c:24
char peer_address[64]
Definition http3.c:33
http_server_t * http_server
Definition http3.c:32
char path[512U]
Definition http3.c:24

References ASCIICHAT_OK, http_server_http3::control, ERROR_INVALID_PARAM, ERROR_MEMORY, ERROR_NETWORK_PROTOCOL, H3_MAX_HEADER_BYTES, H3_MAX_ORIGIN, H3_MAX_PATH, http_server_http3::http, http_server_http3::http_server, http_server_http3_destroy(), http_server_http3::origin, out, http_server_http3::path, http_server_http3::peer_address, http_server_http3::request, SAFE_CALLOC, safe_snprintf(), and SET_ERRNO.

◆ http_server_http3_destroy()

void http_server_http3_destroy ( http_server_http3_t ** server)

Definition at line 557 of file http3.c.

557 {
558 if (!server || !*server)
559 return;
560 http_server_invalidate_http3_context((*server)->http_server, *server);
561 nghttp3_conn_del((*server)->http);
562 while ((*server)->streams) {
563 http3_stream_state_t *state = (*server)->streams;
564 (*server)->streams = state->next;
565 SAFE_FREE(state->request_body);
566 SAFE_FREE(state->response_body);
567 SAFE_FREE(state);
568 }
569 SAFE_FREE((*server)->request_body);
570 SAFE_FREE((*server)->response_body);
571 SAFE_FREE(*server);
572}
#define SAFE_FREE(ptr)
Definition common.h:377
struct http3_stream_state http3_stream_state_t
Definition http3.c:14
void http_server_invalidate_http3_context(http_server_t *server, void *context)

References http_server_invalidate_http3_context(), and SAFE_FREE.

Referenced by http_server_http3_create(), and quic_connection_destroy().

◆ http_server_http3_read()

asciichat_error_t http_server_http3_read ( http_server_http3_t * server,
int64_t stream_id,
const uint8_t * data,
size_t length,
bool fin,
uint64_t now_ns,
size_t * consumed )

Definition at line 460 of file http3.c.

461 {
462 if (!server || !consumed || (!data && length))
463 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/3 input");
464 *consumed = 0;
465 nghttp3_ssize result = nghttp3_conn_read_stream2(server->http, stream_id, data, length, fin, now_ns);
466 if (result < 0)
467 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "HTTP/3 receive failed: %s", nghttp3_strerror((int)result));
468 *consumed = (size_t)result;
469 return ASCIICHAT_OK;
470}

References ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, http_server_http3::http, and SET_ERRNO.

◆ http_server_http3_write()

asciichat_error_t http_server_http3_write ( http_server_http3_t * server,
int64_t * stream_id,
bool * fin,
nghttp3_vec * vectors,
size_t capacity,
size_t * count )

Definition at line 472 of file http3.c.

473 {
474 if (!server || !stream_id || !fin || !vectors || !capacity || !count)
475 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/3 output");
476 if (server->pending)
477 return SET_ERRNO(ERROR_INVALID_STATE, "HTTP/3 output has not been submitted");
478 *stream_id = -1;
479 *fin = false;
480 *count = 0;
481 if (server->settings_written < server->settings_length) {
482 *stream_id = server->control;
483 vectors[0].base = server->settings + server->settings_written;
484 vectors[0].len = server->settings_length - server->settings_written;
485 *count = 1;
486 server->pending = true;
487 server->pending_stream = *stream_id;
488 server->pending_bytes = vectors[0].len;
489 return ASCIICHAT_OK;
490 }
491 for (;;) {
492 int is_fin = 0;
493 nghttp3_ssize result = nghttp3_conn_writev_stream(server->http, stream_id, &is_fin, vectors, capacity);
494 if (result < 0)
495 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "HTTP/3 output failed: %s", nghttp3_strerror((int)result));
496 if (*stream_id != server->control) {
497 *fin = is_fin != 0;
498 *count = (size_t)result;
499 if (*stream_id >= 0) {
500 server->pending = true;
501 server->pending_stream = *stream_id;
502 server->pending_bytes = 0;
503 for (nghttp3_ssize i = 0; i < result; ++i) {
504 if (vectors[i].len > SIZE_MAX - server->pending_bytes)
505 return SET_ERRNO(ERROR_NETWORK_SIZE, "HTTP/3 output size overflow");
506 server->pending_bytes += vectors[i].len;
507 }
508 }
509 return ASCIICHAT_OK;
510 }
511 size_t skipped = 0;
512 for (nghttp3_ssize i = 0; i < result; ++i)
513 skipped += vectors[i].len;
514 if (is_fin || !skipped || nghttp3_conn_add_write_offset(server->http, *stream_id, skipped) ||
515 nghttp3_conn_add_ack_offset(server->http, *stream_id, skipped))
516 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot replace HTTP/3 control settings");
517 }
518}
@ ERROR_INVALID_STATE
@ ERROR_NETWORK_SIZE
Definition error_codes.h:77
size_t pending_bytes
Definition http3.c:28
uint8_t settings[96U]
Definition http3.c:25
int64_t pending_stream
Definition http3.c:27
size_t settings_length
Definition http3.c:26

References ASCIICHAT_OK, http_server_http3::control, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, ERROR_NETWORK_PROTOCOL, ERROR_NETWORK_SIZE, http_server_http3::http, http_server_http3::pending, http_server_http3::pending_bytes, http_server_http3::pending_stream, SET_ERRNO, http_server_http3::settings, http_server_http3::settings_length, and http_server_http3::settings_written.

◆ http_server_http3_wrote()

asciichat_error_t http_server_http3_wrote ( http_server_http3_t * server,
int64_t stream_id,
size_t length )

Definition at line 520 of file http3.c.

520 {
521 if (!server || !server->pending || stream_id != server->pending_stream || length > server->pending_bytes)
522 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/3 submitted output");
523 if (stream_id == server->control) {
524 server->settings_written += length;
525 server->pending = false;
526 return ASCIICHAT_OK;
527 }
528 int result = nghttp3_conn_add_write_offset(server->http, stream_id, length);
529 if (result)
530 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot advance HTTP/3 output: %s", nghttp3_strerror(result));
531 server->pending = false;
532 return ASCIICHAT_OK;
533}

References ASCIICHAT_OK, http_server_http3::control, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, http_server_http3::http, http_server_http3::pending, http_server_http3::pending_bytes, http_server_http3::pending_stream, SET_ERRNO, and http_server_http3::settings_written.