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

Go to the source code of this file.

Data Structures

struct  send_chunk
struct  send_stream_t
struct  receive_stream_t
struct  http3_receive_stream_t
struct  datagram_send
struct  quic_connection
 This is the handoff point for receive stream. Callers fill id, received_offset, reader, active before passing it on; consumers read the values during the operation and return ownership only where the member contract explicitly says they do. More...
struct  receive_context_t

Macros

#define QUIC_CONNECTION_ID_LENGTH   16
#define QUIC_INITIAL_STREAM_WINDOW   (5U * 1024U * 1024U)
#define QUIC_INITIAL_CONNECTION_WINDOW   (16U * 1024U * 1024U)
#define QUIC_IDLE_TIMEOUT_NS   (30ULL * 1000000000ULL)
#define QUIC_FLOW_COUNT   3
#define QUIC_DATAGRAM_FRAME_LIMIT   1400U
#define QUIC_DATAGRAM_OVERHEAD   128U
#define QUIC_HTTP3_PEER_UNI_STREAMS   6U

Typedefs

typedef struct send_chunk send_chunk_t
typedef struct datagram_send datagram_send_t

Functions

asciichat_error_t quic_connection_client_create (quic_tls_t *tls, const char *server_name, const ngtcp2_path *path, uint64_t now_ns, quic_connection_t **out)
asciichat_error_t quic_connection_server_create (quic_tls_t *tls, const ngtcp2_path *path, const void *initial, size_t initial_length, uint64_t now_ns, quic_connection_t **out)
asciichat_error_t quic_connection_server_create_validated (quic_tls_t *tls, const ngtcp2_path *path, const void *initial, size_t initial_length, const ngtcp2_cid *original_dcid, uint64_t now_ns, quic_connection_t **out)
asciichat_error_t quic_connection_matches_cid (const quic_connection_t *connection, const uint8_t *cid, size_t length, bool *matches)
asciichat_error_t quic_connection_set_receiver (quic_connection_t *connection, quic_stream_emit_fn emit, void *context)
asciichat_error_t quic_connection_clear_receiver (quic_connection_t *connection, void *context)
void quic_connection_set_keyframe_notifier (quic_connection_t *connection, void(*notify)(uint16_t, uint32_t, void *), void *context)
void quic_connection_set_security_notifier (quic_connection_t *connection, void(*notify)(void *), void *context)
asciichat_error_t quic_connection_allow_media (quic_connection_t *connection)
asciichat_error_t quic_connection_enable_security (quic_connection_t *connection, crypto_context_t *crypto)
bool quic_connection_security_ready (const quic_connection_t *connection)
size_t quic_connection_datagram_payload (const quic_connection_t *connection)
asciichat_error_t quic_connection_validate_datagram (const quic_connection_t *connection, acip_traffic_class_t flow, uint64_t deadline_ns)
asciichat_error_t quic_connection_submit_datagram (quic_connection_t *connection, acip_traffic_class_t flow, const void *packet, size_t length, uint64_t deadline_ns)
asciichat_error_t quic_connection_submit (quic_connection_t *connection, acip_traffic_class_t traffic_class, const void *packet, size_t length)
size_t quic_connection_pending_bytes (const quic_connection_t *connection)
asciichat_error_t quic_connection_finish_stream (quic_connection_t *connection, acip_traffic_class_t traffic_class)
bool quic_connection_received_fin (const quic_connection_t *connection, acip_traffic_class_t traffic_class)
asciichat_error_t quic_connection_receive (quic_connection_t *connection, const ngtcp2_path *path, const void *packet, size_t length, uint64_t now_ns)
bool quic_connection_pending_packet_class (const quic_connection_t *connection, acip_traffic_class_t *traffic_class)
asciichat_error_t quic_connection_write_close (quic_connection_t *connection, ngtcp2_path_storage *path, void *packet, size_t capacity, size_t *length, uint64_t now_ns)
asciichat_error_t quic_connection_write (quic_connection_t *connection, ngtcp2_path_storage *path, void *packet, size_t capacity, size_t *length, uint64_t now_ns)
asciichat_error_t quic_connection_packet_sent (quic_connection_t *connection, uint64_t now_ns)
uint64_t quic_connection_expiry (const quic_connection_t *connection)
asciichat_error_t quic_connection_handle_expiry (quic_connection_t *connection, uint64_t now_ns)
bool quic_connection_accept_ready (const quic_connection_t *connection)
bool quic_connection_webtransport_ready (const quic_connection_t *connection)
bool quic_connection_tls_ready (const quic_connection_t *connection)
asciichat_error_t quic_connection_peer_address (const quic_connection_t *connection, struct sockaddr_storage *address, socklen_t *length)
void quic_connection_destroy (quic_connection_t **connection)
asciichat_error_t quic_connection_migrate (quic_connection_t *connection, const struct sockaddr *local, socklen_t length, uint64_t now_ns)

Macro Definition Documentation

◆ QUIC_CONNECTION_ID_LENGTH

#define QUIC_CONNECTION_ID_LENGTH   16

Definition at line 16 of file lib/network/quic/connection.c.

◆ QUIC_DATAGRAM_FRAME_LIMIT

#define QUIC_DATAGRAM_FRAME_LIMIT   1400U

Definition at line 21 of file lib/network/quic/connection.c.

Referenced by quic_connection_datagram_payload().

◆ QUIC_DATAGRAM_OVERHEAD

#define QUIC_DATAGRAM_OVERHEAD   128U

Definition at line 22 of file lib/network/quic/connection.c.

Referenced by quic_connection_datagram_payload().

◆ QUIC_FLOW_COUNT

◆ QUIC_HTTP3_PEER_UNI_STREAMS

#define QUIC_HTTP3_PEER_UNI_STREAMS   6U

Definition at line 23 of file lib/network/quic/connection.c.

◆ QUIC_IDLE_TIMEOUT_NS

#define QUIC_IDLE_TIMEOUT_NS   (30ULL * 1000000000ULL)

Definition at line 19 of file lib/network/quic/connection.c.

◆ QUIC_INITIAL_CONNECTION_WINDOW

#define QUIC_INITIAL_CONNECTION_WINDOW   (16U * 1024U * 1024U)

Definition at line 18 of file lib/network/quic/connection.c.

◆ QUIC_INITIAL_STREAM_WINDOW

#define QUIC_INITIAL_STREAM_WINDOW   (5U * 1024U * 1024U)

Definition at line 17 of file lib/network/quic/connection.c.

Typedef Documentation

◆ datagram_send_t

◆ send_chunk_t

typedef struct send_chunk send_chunk_t

Function Documentation

◆ quic_connection_accept_ready()

bool quic_connection_accept_ready ( const quic_connection_t * connection)

Shared listeners wait for TLS ALPN and, for h3, an accepted CONNECT.

Definition at line 1484 of file lib/network/quic/connection.c.

1484 {
1485 return connection && connection->tls_ready && !connection->failed &&
1486 (!connection->webtransport || !connection->tls->webtransport ||
1488}
bool quic_connection_webtransport_ready(const quic_connection_t *connection)
bool webtransport
Definition tls.h:18

References quic_connection::failed, quic_connection_webtransport_ready(), quic_connection::tls, quic_connection::tls_ready, quic_connection::webtransport, and quic_tls_t::webtransport.

Referenced by quic_accept().

◆ quic_connection_allow_media()

asciichat_error_t quic_connection_allow_media ( quic_connection_t * connection)

Permit outbound media after the authenticated readiness exchange. The owner must separately coordinate later application control barriers.

Definition at line 974 of file lib/network/quic/connection.c.

974 {
975 if (!connection || !connection->conn || connection->failed || !connection->tls_ready || !connection->security ||
976 !connection->peer_security_ready)
977 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC and authenticated ACIP encryption are not ready for media");
978 connection->media_allowed = true;
979 return ASCIICHAT_OK;
980}
#define SET_ERRNO(code,...)
@ ERROR_INVALID_STATE
@ ASCIICHAT_OK
Definition error_codes.h:46
crypto_context_t * security

References ASCIICHAT_OK, quic_connection::conn, ERROR_INVALID_STATE, quic_connection::failed, quic_connection::media_allowed, quic_connection::peer_security_ready, quic_connection::security, SET_ERRNO, and quic_connection::tls_ready.

Referenced by quic_transport_allow_media().

◆ quic_connection_clear_receiver()

asciichat_error_t quic_connection_clear_receiver ( quic_connection_t * connection,
void * context )

Detach the current receiver on the connection lane before freeing its context.

Definition at line 947 of file lib/network/quic/connection.c.

947 {
948 if (!connection || !connection->emit || connection->emit_context != context)
949 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC receive callback context");
950 connection->emit = NULL;
951 connection->emit_context = NULL;
952 connection->security_notify = NULL;
953 connection->security_notify_context = NULL;
954 connection->keyframe_notify = NULL;
955 connection->keyframe_notify_context = NULL;
956 return ASCIICHAT_OK;
957}
@ ERROR_INVALID_PARAM
void(* keyframe_notify)(uint16_t, uint32_t, void *)

References ASCIICHAT_OK, quic_connection::emit, quic_connection::emit_context, ERROR_INVALID_PARAM, quic_connection::keyframe_notify, quic_connection::keyframe_notify_context, quic_connection::security_notify, quic_connection::security_notify_context, and SET_ERRNO.

◆ quic_connection_client_create()

asciichat_error_t quic_connection_client_create ( quic_tls_t * tls,
const char * server_name,
const ngtcp2_path * path,
uint64_t now_ns,
quic_connection_t ** out )

Definition at line 808 of file lib/network/quic/connection.c.

809 {
810 return quic_connection_create(tls, server_name, path, NULL, NULL, now_ns, out);
811}
static bool size_t gotel_query_t * out
Definition queries.h:8

References out.

Referenced by quic_udp_connect().

◆ quic_connection_datagram_payload()

size_t quic_connection_datagram_payload ( const quic_connection_t * connection)

Definition at line 1011 of file lib/network/quic/connection.c.

1011 {
1012 if (!connection || !connection->conn || connection->failed || !connection->tls_ready ||
1013 !connection->datagrams_enabled)
1014 return 0;
1015 const ngtcp2_transport_params *remote = ngtcp2_conn_get_remote_transport_params2(connection->conn);
1016 if (!remote || remote->max_datagram_frame_size <= QUIC_DATAGRAM_HEADER_SIZE + 9)
1017 return 0;
1018 size_t path = ngtcp2_conn_get_path_max_tx_udp_payload_size2(connection->conn);
1020 return 0;
1021 size_t frame = path - QUIC_DATAGRAM_OVERHEAD;
1022 if (frame > QUIC_DATAGRAM_FRAME_LIMIT)
1024 if (frame > remote->max_datagram_frame_size - 9)
1025 frame = (size_t)(remote->max_datagram_frame_size - 9);
1026 if (connection->webtransport) {
1027 int64_t session_id = -1;
1028 uint8_t prefix[8];
1029 if (!connection->http3 || !http_server_http3_accepted(connection->http3, &session_id))
1030 return 0;
1031 size_t size = write_quic_varint(prefix, (uint64_t)session_id / 4);
1032 if (frame <= size)
1033 return 0;
1034 frame -= size;
1035 }
1036 return frame > QUIC_DATAGRAM_HEADER_SIZE ? frame - QUIC_DATAGRAM_HEADER_SIZE : 0;
1037}
#define QUIC_DATAGRAM_HEADER_SIZE
Definition datagram.h:11
unsigned long long uint64_t
Definition common.h:63
unsigned char uint8_t
Definition common.h:60
bool http_server_http3_accepted(const http_server_http3_t *server, int64_t *session_id)
Definition http3.c:549
#define QUIC_DATAGRAM_OVERHEAD
#define QUIC_DATAGRAM_FRAME_LIMIT
uint8_t session_id[SESSION_ID_SIZE]
http_server_http3_t * http3

References quic_connection::conn, quic_connection::datagrams_enabled, quic_connection::failed, quic_connection::http3, http_server_http3_accepted(), QUIC_DATAGRAM_FRAME_LIMIT, QUIC_DATAGRAM_HEADER_SIZE, QUIC_DATAGRAM_OVERHEAD, session_id, quic_connection::tls_ready, and quic_connection::webtransport.

Referenced by quic_connection_submit_datagram(), and quic_connection_validate_datagram().

◆ quic_connection_destroy()

void quic_connection_destroy ( quic_connection_t ** connection)

Definition at line 1512 of file lib/network/quic/connection.c.

1512 {
1513 if (!connection || !*connection)
1514 return;
1515 ngtcp2_conn_del((*connection)->conn);
1516 (*connection)->conn = NULL;
1517 http_server_http3_destroy(&(*connection)->http3);
1518 buffer_release((*connection)->early_security_packet);
1519 quic_datagram_reset(&(*connection)->datagram_reader);
1520 for (size_t i = 0; i < QUIC_FLOW_COUNT; ++i) {
1521 while ((*connection)->datagram_head[i])
1522 pop_datagram(*connection, (acip_traffic_class_t)i);
1523 send_chunk_t *chunk = (*connection)->sends[i].head;
1524 while (chunk) {
1525 send_chunk_t *next = chunk->next;
1526 free_chunk(*connection, chunk);
1527 chunk = next;
1528 }
1529 quic_stream_reset(&(*connection)->receives[i].reader);
1530 }
1531 quic_tls_session_destroy(&(*connection)->ssl);
1532 ngtcp2_crypto_ossl_ctx_del((*connection)->crypto);
1533 (*connection)->security = NULL;
1534 SAFE_FREE(*connection);
1535}
#define buffer_release(data)
Definition buffer.h:91
void quic_datagram_reset(quic_datagram_reader_t *reader)
Definition datagram.c:96
#define SAFE_FREE(ptr)
Definition common.h:377
void http_server_http3_destroy(http_server_http3_t **server)
Definition http3.c:557
#define QUIC_FLOW_COUNT
struct send_chunk send_chunk_t
void quic_stream_reset(quic_stream_reader_t *reader)
struct send_chunk * next
void quic_tls_session_destroy(SSL **ssl)
Definition tls.c:194
acip_traffic_class_t
Definition traffic.h:5

References buffer_release, http_server_http3_destroy(), send_chunk::next, quic_datagram_reset(), QUIC_FLOW_COUNT, quic_stream_reset(), quic_tls_session_destroy(), and SAFE_FREE.

Referenced by quic_udp_remove().

◆ quic_connection_enable_security()

asciichat_error_t quic_connection_enable_security ( quic_connection_t * connection,
crypto_context_t * crypto )

Enable authenticated ACIP framing after the local ACIP handshake. This queues a readiness marker and handles the peer's marker and acknowledgement. The crypto context is borrowed until connection destruction. The endpoint must serialize every operation on it, including rekeying, with this engine.

Definition at line 982 of file lib/network/quic/connection.c.

982 {
983 if (!connection || !connection->conn || connection->failed || !connection->tls_ready || !connection->emit)
984 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC is not ready for the ACIP security transition");
985 crypto->server_role = connection->tls->server;
986 crypto->server_role_known = true;
987 crypto_session_t *session = NULL;
988 asciichat_error_t result = crypto_session_lock(crypto, &session);
989 if (result == ASCIICHAT_OK) {
990 crypto_session_unlock(session);
991 connection->security = crypto;
992 }
993 if (result != ASCIICHAT_OK)
994 return result;
995 result = queue_security_barrier(connection, quic_ready_payload, sizeof(quic_ready_payload));
996 if (result == ASCIICHAT_OK && connection->early_security_packet)
997 result = open_security_packet(connection, ACIP_TRAFFIC_CONTROL, connection->early_security_packet,
998 connection->early_security_length);
1000 connection->early_security_packet = NULL;
1001 connection->early_security_length = 0;
1002 if (result != ASCIICHAT_OK)
1003 connection->failed = true;
1004 return result;
1005}
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
struct crypto_session crypto_session_t
For crypto session, this is the live record that ties owner, mutex, records, rotation together....
void crypto_session_unlock(crypto_session_t *session)
asciichat_error_t crypto_session_lock(crypto_context_t *crypto, crypto_session_t **output)
bool server
Definition tls.h:15
@ ACIP_TRAFFIC_CONTROL
Definition traffic.h:6

References ACIP_TRAFFIC_CONTROL, ASCIICHAT_OK, buffer_release, quic_connection::conn, crypto_session_lock(), crypto_session_unlock(), quic_connection::early_security_length, quic_connection::early_security_packet, quic_connection::emit, ERROR_INVALID_STATE, quic_connection::failed, quic_connection::security, quic_tls_t::server, crypto_context_t::server_role, crypto_context_t::server_role_known, SET_ERRNO, quic_connection::tls, and quic_connection::tls_ready.

Referenced by quic_transport_begin_security().

◆ quic_connection_expiry()

uint64_t quic_connection_expiry ( const quic_connection_t * connection)

Definition at line 1453 of file lib/network/quic/connection.c.

1453 {
1454 if (!connection || !connection->conn || connection->failed)
1455 return UINT64_MAX;
1456 uint64_t expiry = ngtcp2_conn_get_expiry(connection->conn);
1457 for (size_t i = 0; i < QUIC_FLOW_COUNT; ++i)
1458 for (const datagram_send_t *item = connection->datagram_head[i]; item; item = item->next)
1459 if (item->deadline_ns && item->deadline_ns < expiry)
1460 expiry = item->deadline_ns;
1461 for (size_t i = 0; i < QUIC_DATAGRAM_SLOTS; ++i) {
1462 const quic_datagram_slot_t *slot = &connection->datagram_reader.slots[i];
1463 if (slot->data && slot->started_ns <= UINT64_MAX - QUIC_DATAGRAM_EXPIRY_NS &&
1464 slot->started_ns + QUIC_DATAGRAM_EXPIRY_NS < expiry)
1465 expiry = slot->started_ns + QUIC_DATAGRAM_EXPIRY_NS;
1466 }
1467 return expiry;
1468}
#define QUIC_DATAGRAM_EXPIRY_NS
Definition datagram.h:15
#define QUIC_DATAGRAM_SLOTS
Definition datagram.h:13
struct datagram_send datagram_send_t
struct datagram_send * next
quic_datagram_reader_t datagram_reader
datagram_send_t * datagram_head[3]
quic_datagram_slot_t slots[8U]
Definition datagram.h:35
uint64_t started_ns
Definition datagram.h:21

References quic_connection::conn, quic_datagram_slot_t::data, quic_connection::datagram_head, quic_connection::datagram_reader, datagram_send::deadline_ns, quic_connection::failed, datagram_send::next, QUIC_DATAGRAM_EXPIRY_NS, QUIC_DATAGRAM_SLOTS, QUIC_FLOW_COUNT, quic_datagram_reader_t::slots, and quic_datagram_slot_t::started_ns.

Referenced by quic_udp_pump(), and quic_udp_wait_parameters().

◆ quic_connection_finish_stream()

asciichat_error_t quic_connection_finish_stream ( quic_connection_t * connection,
acip_traffic_class_t traffic_class )

Definition at line 1233 of file lib/network/quic/connection.c.

1233 {
1234 if (!connection || !connection->conn || connection->failed || (unsigned)traffic_class >= QUIC_FLOW_COUNT)
1235 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC traffic stream");
1236 send_stream_t *stream = &connection->sends[traffic_class];
1237 if (!stream->initialized || stream->fin_requested)
1238 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC traffic stream is not open or is already closing");
1239 stream->fin_requested = true;
1240 return ASCIICHAT_OK;
1241}

References ASCIICHAT_OK, quic_connection::conn, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, quic_connection::failed, send_stream_t::fin_requested, send_stream_t::initialized, QUIC_FLOW_COUNT, quic_connection::sends, and SET_ERRNO.

◆ quic_connection_handle_expiry()

asciichat_error_t quic_connection_handle_expiry ( quic_connection_t * connection,
uint64_t now_ns )

Definition at line 1470 of file lib/network/quic/connection.c.

1470 {
1471 if (!connection || !connection->conn || connection->failed)
1472 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC timeout state");
1473 asciichat_error_t result = update_time(connection, now_ns);
1474 if (result != ASCIICHAT_OK)
1475 return result;
1476 int rc = ngtcp2_conn_get_expiry(connection->conn) <= now_ns ? ngtcp2_conn_handle_expiry(connection->conn, now_ns) : 0;
1477 if (rc != 0) {
1478 connection->failed = true;
1479 return SET_ERRNO(ERROR_NETWORK_TIMEOUT, "QUIC timer failed: %s", ngtcp2_strerror(rc));
1480 }
1481 return update_readiness(connection);
1482}
@ ERROR_NETWORK_TIMEOUT
Definition error_codes.h:75

References ASCIICHAT_OK, quic_connection::conn, ERROR_INVALID_PARAM, ERROR_NETWORK_TIMEOUT, quic_connection::failed, and SET_ERRNO.

Referenced by quic_udp_pump().

◆ quic_connection_matches_cid()

asciichat_error_t quic_connection_matches_cid ( const quic_connection_t * connection,
const uint8_t * cid,
size_t length,
bool * matches )

Definition at line 908 of file lib/network/quic/connection.c.

909 {
910 if (!connection || !connection->conn || !cid || !matches)
911 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC connection ID lookup");
912 *matches = false;
913 if (!length || length > NGTCP2_MAX_CIDLEN)
914 return ASCIICHAT_OK;
915 if (connection->has_initial_dcid && length == connection->initial_dcid.datalen &&
916 memcmp(cid, connection->initial_dcid.data, length) == 0) {
917 *matches = true;
918 return ASCIICHAT_OK;
919 }
920 size_t count = ngtcp2_conn_get_scid2(connection->conn, NULL);
921 if (!count)
922 return ASCIICHAT_OK;
923 if (count > SIZE_MAX / sizeof(ngtcp2_cid))
924 return SET_ERRNO(ERROR_MEMORY, "QUIC connection ID count overflow");
925 ngtcp2_cid *ids = SAFE_CALLOC(count, sizeof(*ids), ngtcp2_cid *);
926 if (!ids)
927 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate QUIC connection ID list");
928 size_t actual = ngtcp2_conn_get_scid2(connection->conn, ids);
929 for (size_t i = 0; i < actual; ++i) {
930 if (ids[i].datalen == length && memcmp(ids[i].data, cid, length) == 0) {
931 *matches = true;
932 break;
933 }
934 }
935 SAFE_FREE(ids);
936 return ASCIICHAT_OK;
937}
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
@ ERROR_MEMORY
Definition error_codes.h:51

References ASCIICHAT_OK, quic_connection::conn, ERROR_INVALID_PARAM, ERROR_MEMORY, quic_connection::has_initial_dcid, quic_connection::initial_dcid, SAFE_CALLOC, SAFE_FREE, and SET_ERRNO.

◆ quic_connection_migrate()

asciichat_error_t quic_connection_migrate ( quic_connection_t * connection,
const struct sockaddr * local,
socklen_t length,
uint64_t now_ns )

Definition at line 1537 of file lib/network/quic/connection.c.

1538 {
1539 if (!connection || !connection->conn || connection->failed || connection->tls->server || !local ||
1540 (size_t)length > sizeof(ngtcp2_sockaddr_union))
1541 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC client migration");
1542 const ngtcp2_path *current = ngtcp2_conn_get_path2(connection->conn);
1543 ngtcp2_path path = *current;
1544 path.local.addr = (struct sockaddr *)local;
1545 path.local.addrlen = length;
1546 if (!valid_address(&path.local) || local->sa_family != current->remote.addr->sa_family)
1547 return SET_ERRNO(ERROR_INVALID_PARAM, "QUIC migration requires a concrete address in the peer address family");
1548 asciichat_error_t result = update_time(connection, now_ns);
1549 if (result != ASCIICHAT_OK)
1550 return result;
1551 int rc = ngtcp2_conn_initiate_immediate_migration(connection->conn, &path, now_ns);
1552 if (rc == NGTCP2_ERR_INVALID_STATE)
1553 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC handshake is unconfirmed or peer disabled active migration");
1554 if (rc == NGTCP2_ERR_CONN_ID_BLOCKED)
1555 return SET_ERRNO(ERROR_BUFFER_FULL, "QUIC migration requires an unused peer connection ID");
1556 if (rc != 0)
1557 return SET_ERRNO(ERROR_NETWORK, "Cannot initiate QUIC migration: %s", ngtcp2_strerror(rc));
1558 return ASCIICHAT_OK;
1559}
@ ERROR_NETWORK
Definition error_codes.h:72
@ ERROR_BUFFER_FULL

References ASCIICHAT_OK, quic_connection::conn, ERROR_BUFFER_FULL, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, ERROR_NETWORK, quic_connection::failed, quic_tls_t::server, SET_ERRNO, and quic_connection::tls.

Referenced by quic_udp_migrate().

◆ quic_connection_packet_sent()

asciichat_error_t quic_connection_packet_sent ( quic_connection_t * connection,
uint64_t now_ns )

Definition at line 1442 of file lib/network/quic/connection.c.

1442 {
1443 if (!connection || !connection->conn || connection->failed || !connection->packet_pending)
1444 return SET_ERRNO(ERROR_INVALID_STATE, "No QUIC packet awaiting transmission");
1445 asciichat_error_t result = update_time(connection, now_ns);
1446 if (result != ASCIICHAT_OK)
1447 return result;
1448 ngtcp2_conn_update_pkt_tx_time(connection->conn, now_ns);
1449 connection->packet_pending = false;
1450 return ASCIICHAT_OK;
1451}

References ASCIICHAT_OK, quic_connection::conn, ERROR_INVALID_STATE, quic_connection::failed, quic_connection::packet_pending, and SET_ERRNO.

Referenced by quic_udp_pump().

◆ quic_connection_peer_address()

asciichat_error_t quic_connection_peer_address ( const quic_connection_t * connection,
struct sockaddr_storage * address,
socklen_t * length )

Definition at line 1499 of file lib/network/quic/connection.c.

1500 {
1501 if (!connection || !connection->conn || connection->failed || !address || !length)
1502 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC peer address query");
1503 const ngtcp2_path *path = ngtcp2_conn_get_path2(connection->conn);
1504 if (!path || !valid_address(&path->remote))
1505 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC peer address is unavailable");
1506 memset(address, 0, sizeof(*address));
1507 memcpy(address, path->remote.addr, (size_t)path->remote.addrlen);
1508 *length = path->remote.addrlen;
1509 return ASCIICHAT_OK;
1510}

References ASCIICHAT_OK, quic_connection::conn, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, quic_connection::failed, and SET_ERRNO.

Referenced by quic_transport_peer_address().

◆ quic_connection_pending_bytes()

size_t quic_connection_pending_bytes ( const quic_connection_t * connection)

Definition at line 1229 of file lib/network/quic/connection.c.

1229 {
1230 return connection ? connection->pending_bytes : 0;
1231}

References quic_connection::pending_bytes.

◆ quic_connection_pending_packet_class()

bool quic_connection_pending_packet_class ( const quic_connection_t * connection,
acip_traffic_class_t * traffic_class )

Reports the class of newly submitted stream or datagram data in the pending packet. Retransmissions from other streams may also be present in that packet.

Definition at line 1387 of file lib/network/quic/connection.c.

1387 {
1388 if (!connection || !connection->packet_pending || !connection->packet_has_stream_data || !traffic_class)
1389 return false;
1390 *traffic_class = connection->packet_traffic_class;
1391 return true;
1392}
acip_traffic_class_t packet_traffic_class

References quic_connection::packet_has_stream_data, quic_connection::packet_pending, and quic_connection::packet_traffic_class.

◆ quic_connection_receive()

asciichat_error_t quic_connection_receive ( quic_connection_t * connection,
const ngtcp2_path * path,
const void * packet,
size_t length,
uint64_t now_ns )

Definition at line 1252 of file lib/network/quic/connection.c.

1253 {
1254 if (!connection || !connection->conn || connection->failed || !valid_path(path) || !packet || !length)
1255 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC packet input");
1256 asciichat_error_t result = update_time(connection, now_ns);
1257 if (result != ASCIICHAT_OK)
1258 return result;
1259 ngtcp2_pkt_info info = {0};
1260 connection->callback_error = ASCIICHAT_OK;
1261 int rc = ngtcp2_conn_read_pkt(connection->conn, path, &info, packet, length, now_ns);
1262 if (rc != 0) {
1263 connection->failed = true;
1264 asciichat_error_t code = connection->callback_error != ASCIICHAT_OK ? connection->callback_error
1265 : rc == NGTCP2_ERR_CRYPTO ? ERROR_CRYPTO
1266 : rc == NGTCP2_ERR_DRAINING ? ERROR_NETWORK
1268 return SET_ERRNO(code, "QUIC receive failed: %s", ngtcp2_strerror(rc));
1269 }
1270 return update_readiness(connection);
1271}
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:76
@ ERROR_CRYPTO
Definition error_codes.h:93
asciichat_error_t callback_error

References ASCIICHAT_OK, quic_connection::callback_error, quic_connection::conn, ERROR_CRYPTO, ERROR_INVALID_PARAM, ERROR_NETWORK, ERROR_NETWORK_PROTOCOL, quic_connection::failed, and SET_ERRNO.

◆ quic_connection_received_fin()

bool quic_connection_received_fin ( const quic_connection_t * connection,
acip_traffic_class_t traffic_class )

Definition at line 1243 of file lib/network/quic/connection.c.

1243 {
1244 if (!connection || (unsigned)traffic_class >= QUIC_FLOW_COUNT)
1245 return false;
1246 for (size_t i = 0; i < QUIC_FLOW_COUNT; ++i)
1247 if (connection->receives[i].registered && connection->receives[i].reader.traffic_class == traffic_class)
1248 return connection->receives[i].reader.finished;
1249 return false;
1250}
receive_stream_t receives[3]
acip_traffic_class_t traffic_class
quic_stream_reader_t reader

References quic_stream_reader_t::finished, QUIC_FLOW_COUNT, receive_stream_t::reader, quic_connection::receives, receive_stream_t::registered, and quic_stream_reader_t::traffic_class.

◆ quic_connection_security_ready()

bool quic_connection_security_ready ( const quic_connection_t * connection)

True after the peer's authenticated READY and acknowledgement are received.

Definition at line 1007 of file lib/network/quic/connection.c.

1007 {
1008 return connection && connection->security && connection->peer_security_ready && !connection->failed;
1009}

References quic_connection::failed, quic_connection::peer_security_ready, and quic_connection::security.

Referenced by quic_transport_security_ready(), and quic_transport_wait_security().

◆ quic_connection_server_create()

asciichat_error_t quic_connection_server_create ( quic_tls_t * tls,
const ngtcp2_path * path,
const void * initial,
size_t initial_length,
uint64_t now_ns,
quic_connection_t ** out )

Creates a server connection for an acceptable QUIC v1 Initial packet. The caller must subsequently pass that same packet to receive().

Definition at line 813 of file lib/network/quic/connection.c.

814 {
815 if (!out)
816 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC connection output");
817 *out = NULL;
818 if (!initial || !initial_length)
819 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC Initial packet");
820 ngtcp2_pkt_hd header;
821 int rc = ngtcp2_accept(&header, initial, initial_length);
822 if (rc != 0 || header.version != NGTCP2_PROTO_VER_V1)
823 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid or unsupported QUIC Initial packet");
824 return quic_connection_create(tls, NULL, path, &header, NULL, now_ns, out);
825}

References ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, out, and SET_ERRNO.

◆ quic_connection_server_create_validated()

asciichat_error_t quic_connection_server_create_validated ( quic_tls_t * tls,
const ngtcp2_path * path,
const void * initial,
size_t initial_length,
const ngtcp2_cid * original_dcid,
uint64_t now_ns,
quic_connection_t ** out )

Definition at line 827 of file lib/network/quic/connection.c.

829 {
830 if (!out)
831 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC connection output");
832 *out = NULL;
833 if (!initial || !initial_length || !original_dcid || !original_dcid->datalen ||
834 original_dcid->datalen > NGTCP2_MAX_CIDLEN)
835 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing validated QUIC Initial parameters");
836 ngtcp2_pkt_hd header;
837 int rc = ngtcp2_accept(&header, initial, initial_length);
838 if (rc != 0 || header.version != NGTCP2_PROTO_VER_V1 || !header.tokenlen)
839 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid validated QUIC Initial packet");
840 return quic_connection_create(tls, NULL, path, &header, original_dcid, now_ns, out);
841}

References ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, out, and SET_ERRNO.

◆ quic_connection_set_keyframe_notifier()

void quic_connection_set_keyframe_notifier ( quic_connection_t * connection,
void(* notify )(uint16_t, uint32_t, void *),
void * context )

Definition at line 959 of file lib/network/quic/connection.c.

960 {
961 if (connection) {
962 connection->keyframe_notify = notify;
963 connection->keyframe_notify_context = notify ? context : NULL;
964 }
965}

References quic_connection::keyframe_notify, and quic_connection::keyframe_notify_context.

◆ quic_connection_set_receiver()

asciichat_error_t quic_connection_set_receiver ( quic_connection_t * connection,
quic_stream_emit_fn emit,
void * context )

Install a serialized receive callback. It borrows complete wire packets; the callback must copy what it retains and must not reenter the connection.

Definition at line 939 of file lib/network/quic/connection.c.

939 {
940 if (!connection || !connection->conn || connection->failed || !emit || connection->emit)
941 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC receive callback");
942 connection->emit = emit;
943 connection->emit_context = context;
944 return ASCIICHAT_OK;
945}

References ASCIICHAT_OK, quic_connection::conn, quic_connection::emit, quic_connection::emit_context, ERROR_INVALID_PARAM, quic_connection::failed, and SET_ERRNO.

◆ quic_connection_set_security_notifier()

void quic_connection_set_security_notifier ( quic_connection_t * connection,
void(* notify )(void *),
void * context )

The notifier runs on the serialized lane when the readiness exchange completes.

Definition at line 967 of file lib/network/quic/connection.c.

967 {
968 if (connection) {
969 connection->security_notify = notify;
970 connection->security_notify_context = notify ? context : NULL;
971 }
972}

References quic_connection::security_notify, and quic_connection::security_notify_context.

◆ quic_connection_submit()

asciichat_error_t quic_connection_submit ( quic_connection_t * connection,
acip_traffic_class_t traffic_class,
const void * packet,
size_t length )

Copy one complete ACIP wire packet to its reliable stream. Admission is bounded; ERROR_BUFFER_FULL leaves the queue unchanged. The connection owns submitted bytes until ngtcp2 acknowledges them or the connection is freed.

Definition at line 1187 of file lib/network/quic/connection.c.

1188 {
1189 if (connection && !connection->security && packet && length >= sizeof(packet_header_t)) {
1190 packet_header_t header;
1191 memcpy(&header, packet, sizeof(header));
1192 packet_type_t type = NET_TO_HOST_U16(header.type);
1193 if (traffic_class == ACIP_TRAFFIC_CONTROL && !initial_handshake_packet(type))
1194 return SET_ERRNO(ERROR_CRYPTO, "Non-handshake ACIP packet sent before authentication");
1195 }
1196 if (!connection || !connection->security)
1197 return queue_wire_packet(connection, traffic_class, packet, length);
1198 if (packet && length >= sizeof(packet_header_t)) {
1199 packet_header_t header;
1200 memcpy(&header, packet, sizeof(header));
1201 if (NET_TO_HOST_U16(header.type) == PACKET_TYPE_ENCRYPTED)
1202 return queue_wire_packet_internal(connection, traffic_class, packet, length, true);
1203 }
1204 if (!connection->peer_security_ready)
1205 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC peer has not acknowledged ACIP security readiness");
1206 if (packet && length >= sizeof(packet_header_t)) {
1207 packet_header_t header;
1208 memcpy(&header, packet, sizeof(header));
1209 if (NET_TO_HOST_U16(header.type) == PACKET_TYPE_QUIC_READY ||
1212 return SET_ERRNO(ERROR_INVALID_PARAM, "QUIC readiness marker is reserved");
1213 }
1214 if (!connection->conn || connection->failed || !connection->tls_ready || (unsigned)traffic_class >= QUIC_FLOW_COUNT ||
1215 (traffic_class != ACIP_TRAFFIC_CONTROL && !connection->media_allowed))
1216 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC connection is not ready for this traffic");
1217 if (connection->sends[traffic_class].fin_requested)
1218 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC traffic stream is closing");
1219 uint8_t *wire = NULL;
1220 size_t wire_length = 0;
1221 asciichat_error_t result = acip_security_seal(connection->security, traffic_class, ACIP_DELIVERY_RELIABLE, packet,
1222 length, &wire, &wire_length);
1223 if (result == ASCIICHAT_OK)
1224 result = queue_wire_packet(connection, traffic_class, wire, wire_length);
1225 buffer_release(wire);
1226 return result;
1227}
#define NET_TO_HOST_U16(val)
Definition endian.h:111
packet_type_t
Network protocol packet type enumeration.
Definition packet.h:301
@ PACKET_TYPE_QUIC_READY
Internal authenticated readiness barrier for ACIP over QUIC.
Definition packet.h:342
@ PACKET_TYPE_ENCRYPTED
Encrypted packet (after handshake completion).
Definition packet.h:355
@ PACKET_TYPE_QUIC_KEYFRAME_REQUEST
Internal authenticated request for a QUIC encoded-video keyframe.
Definition packet.h:344
asciichat_error_t acip_security_seal(crypto_context_t *crypto, acip_traffic_class_t flow, acip_delivery_t delivery, const void *packet, size_t length, uint8_t **output, size_t *written)
bool acip_security_rekey_packet(uint16_t type)
Fixed prefix shared by every ACIP packet on the wire.
Definition packet.h:628
@ ACIP_DELIVERY_RELIABLE
Definition traffic.h:12

References ACIP_DELIVERY_RELIABLE, acip_security_rekey_packet(), acip_security_seal(), ACIP_TRAFFIC_CONTROL, ASCIICHAT_OK, buffer_release, quic_connection::conn, ERROR_CRYPTO, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, quic_connection::failed, send_stream_t::fin_requested, quic_connection::media_allowed, NET_TO_HOST_U16, PACKET_TYPE_ENCRYPTED, PACKET_TYPE_QUIC_KEYFRAME_REQUEST, PACKET_TYPE_QUIC_READY, quic_connection::peer_security_ready, QUIC_FLOW_COUNT, quic_connection::security, quic_connection::sends, SET_ERRNO, and quic_connection::tls_ready.

◆ quic_connection_submit_datagram()

asciichat_error_t quic_connection_submit_datagram ( quic_connection_t * connection,
acip_traffic_class_t flow,
const void * packet,
size_t length,
uint64_t deadline_ns )

Definition at line 1052 of file lib/network/quic/connection.c.

1053 {
1054 asciichat_error_t validation = quic_connection_validate_datagram(connection, flow, deadline_ns);
1055 if (validation != ASCIICHAT_OK)
1056 return validation;
1057 if (flow == ACIP_TRAFFIC_VISUAL && packet && length >= sizeof(packet_header_t)) {
1058 packet_header_t header;
1059 memcpy(&header, packet, sizeof(header));
1060 uint16_t type = NET_TO_HOST_U16(header.type);
1061 if ((type == PACKET_TYPE_IMAGE_FRAME_H264 || type == PACKET_TYPE_IMAGE_FRAME_H265) && header.client_id != 0)
1062 return SET_ERRNO(ERROR_NOT_SUPPORTED, "QUIC encoded datagrams require stream ID zero");
1063 }
1064 size_t unit = quic_connection_datagram_payload(connection);
1065 if (connection->datagram_id[flow] == UINT64_MAX)
1066 return SET_ERRNO(ERROR_NETWORK_SIZE, "QUIC datagram ID exhausted");
1069 size_t limit = ACIP_OUTBOUND_BUDGET - reserve;
1070 if (connection->pending_bytes > limit || length > limit - connection->pending_bytes)
1071 return SET_ERRNO(ERROR_BUFFER_FULL, "QUIC datagram queue is full");
1072 uint8_t *wire = NULL;
1073 size_t wire_length = 0;
1074 asciichat_error_t result =
1075 acip_security_seal(connection->security, flow, ACIP_DELIVERY_DATAGRAM, packet, length, &wire, &wire_length);
1076 if (result != ASCIICHAT_OK)
1077 return result;
1078 size_t count = (wire_length + unit - 1) / unit;
1079 size_t cost = buffer_capacity(wire) + sizeof(datagram_send_t);
1080 if (count > QUIC_DATAGRAM_MAX_FRAGMENTS || cost > limit - connection->pending_bytes) {
1081 buffer_release(wire);
1083 "QUIC datagram exceeds fragmentation or queue limit");
1084 }
1085 datagram_send_t *item = SAFE_CALLOC(1, sizeof(*item), datagram_send_t *);
1086 if (!item) {
1087 buffer_release(wire);
1088 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate QUIC datagram queue entry");
1089 }
1090 item->data = wire;
1091 item->length = wire_length;
1092 item->cost = cost;
1093 item->id = ++connection->datagram_id[flow];
1094 item->deadline_ns = deadline_ns;
1095 item->unit = (uint16_t)unit;
1096 item->count = (uint16_t)count;
1097 if (connection->datagram_tail[flow])
1098 connection->datagram_tail[flow]->next = item;
1099 else
1100 connection->datagram_head[flow] = item;
1101 connection->datagram_tail[flow] = item;
1102 connection->pending_bytes += cost;
1103 return ASCIICHAT_OK;
1104}
#define ACIP_OUTBOUND_BUDGET
#define ACIP_OUTBOUND_AUDIO_RESERVE
#define ACIP_OUTBOUND_CONTROL_RESERVE
size_t buffer_capacity(const void *data)
Definition buffer.c:280
#define QUIC_DATAGRAM_MAX_FRAGMENTS
Definition datagram.h:12
unsigned short uint16_t
Definition common.h:61
@ ERROR_NETWORK_SIZE
Definition error_codes.h:77
@ ERROR_NOT_SUPPORTED
Definition error_codes.h:69
@ PACKET_TYPE_IMAGE_FRAME_H265
H.265-encoded frame from client (HEVC/H.265 codec).
Definition packet.h:387
@ PACKET_TYPE_IMAGE_FRAME_H264
Definition packet.h:389
asciichat_error_t quic_connection_validate_datagram(const quic_connection_t *connection, acip_traffic_class_t flow, uint64_t deadline_ns)
size_t quic_connection_datagram_payload(const quic_connection_t *connection)
datagram_send_t * datagram_tail[3]
@ ACIP_TRAFFIC_VISUAL
Definition traffic.h:8
@ ACIP_DELIVERY_DATAGRAM
Definition traffic.h:13

References ACIP_DELIVERY_DATAGRAM, ACIP_OUTBOUND_AUDIO_RESERVE, ACIP_OUTBOUND_BUDGET, ACIP_OUTBOUND_CONTROL_RESERVE, acip_security_seal(), ACIP_TRAFFIC_VISUAL, ASCIICHAT_OK, buffer_capacity(), buffer_release, datagram_send::cost, datagram_send::count, datagram_send::data, quic_connection::datagram_head, quic_connection::datagram_id, quic_connection::datagram_tail, datagram_send::deadline_ns, ERROR_BUFFER_FULL, ERROR_MEMORY, ERROR_NETWORK_SIZE, ERROR_NOT_SUPPORTED, datagram_send::id, datagram_send::length, NET_TO_HOST_U16, datagram_send::next, PACKET_TYPE_IMAGE_FRAME_H264, PACKET_TYPE_IMAGE_FRAME_H265, quic_connection::pending_bytes, quic_connection_datagram_payload(), quic_connection_validate_datagram(), QUIC_DATAGRAM_MAX_FRAGMENTS, SAFE_CALLOC, quic_connection::security, SET_ERRNO, and datagram_send::unit.

◆ quic_connection_tls_ready()

bool quic_connection_tls_ready ( const quic_connection_t * connection)

Definition at line 1495 of file lib/network/quic/connection.c.

1495 {
1496 return connection && !connection->failed && connection->tls_ready;
1497}

References quic_connection::failed, and quic_connection::tls_ready.

◆ quic_connection_validate_datagram()

asciichat_error_t quic_connection_validate_datagram ( const quic_connection_t * connection,
acip_traffic_class_t flow,
uint64_t deadline_ns )

Definition at line 1039 of file lib/network/quic/connection.c.

1040 {
1041 if (!connection || (flow != ACIP_TRAFFIC_AUDIO && flow != ACIP_TRAFFIC_VISUAL))
1042 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC datagram flow");
1043 if (!quic_connection_datagram_payload(connection))
1044 return SET_ERRNO(ERROR_NOT_SUPPORTED, "QUIC datagrams were not negotiated");
1045 if (!connection->security || !connection->peer_security_ready || !connection->media_allowed)
1046 return SET_ERRNO(ERROR_INVALID_STATE, "QUIC media security is not ready");
1047 if (deadline_ns && deadline_ns <= connection->last_time_ns)
1048 return SET_ERRNO(ERROR_NETWORK_TIMEOUT, "QUIC datagram deadline expired");
1049 return ASCIICHAT_OK;
1050}
@ ACIP_TRAFFIC_AUDIO
Definition traffic.h:7

References ACIP_TRAFFIC_AUDIO, ACIP_TRAFFIC_VISUAL, ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, ERROR_NETWORK_TIMEOUT, ERROR_NOT_SUPPORTED, quic_connection::media_allowed, quic_connection::peer_security_ready, quic_connection_datagram_payload(), quic_connection::security, and SET_ERRNO.

Referenced by quic_connection_submit_datagram().

◆ quic_connection_webtransport_ready()

bool quic_connection_webtransport_ready ( const quic_connection_t * connection)

Definition at line 1490 of file lib/network/quic/connection.c.

1490 {
1491 return connection && connection->webtransport && connection->http3 &&
1492 http_server_http3_accepted(connection->http3, NULL) && !connection->failed;
1493}

References quic_connection::failed, quic_connection::http3, http_server_http3_accepted(), and quic_connection::webtransport.

Referenced by quic_connection_accept_ready().

◆ quic_connection_write()

asciichat_error_t quic_connection_write ( quic_connection_t * connection,
ngtcp2_path_storage * path,
void * packet,
size_t capacity,
size_t * length,
uint64_t now_ns )

Writes a single UDP payload, or sets length to zero if no packet is ready. The returned path identifies the local and remote addresses for that packet. The endpoint must retain an unsent payload across socket backpressure and call packet_sent after successful transmission, before writing another.

Definition at line 1417 of file lib/network/quic/connection.c.

1418 {
1419 if (!length)
1420 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing QUIC packet length output");
1421 *length = 0;
1422 if (!connection || !connection->conn || connection->failed || !path || !packet || capacity < 1200)
1423 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC packet output");
1424 if (connection->packet_pending)
1425 return SET_ERRNO(ERROR_INVALID_STATE, "Previous QUIC packet has not been transmitted");
1426 asciichat_error_t result = update_time(connection, now_ns);
1427 if (result != ASCIICHAT_OK)
1428 return result;
1429 ngtcp2_path_storage_zero(path);
1430 ngtcp2_pkt_info info = {0};
1431 ngtcp2_ssize written = write_pending(connection, &path->path, &info, packet, capacity, now_ns);
1432 if (written < 0) {
1433 connection->failed = true;
1434 return SET_ERRNO(written == NGTCP2_ERR_CRYPTO ? ERROR_CRYPTO : ERROR_NETWORK, "QUIC write failed: %s",
1435 ngtcp2_strerror((int)written));
1436 }
1437 *length = (size_t)written;
1438 connection->packet_pending = written > 0;
1439 return update_readiness(connection);
1440}

References ASCIICHAT_OK, quic_connection::conn, ERROR_CRYPTO, ERROR_INVALID_PARAM, ERROR_INVALID_STATE, ERROR_NETWORK, quic_connection::failed, quic_connection::packet_pending, and SET_ERRNO.

Referenced by quic_udp_pump().

◆ quic_connection_write_close()

asciichat_error_t quic_connection_write_close ( quic_connection_t * connection,
ngtcp2_path_storage * path,
void * packet,
size_t capacity,
size_t * length,
uint64_t now_ns )

Definition at line 1394 of file lib/network/quic/connection.c.

1395 {
1396 if (!connection || !connection->conn || !path || !packet || capacity < 1200 || !length)
1397 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid QUIC close packet output");
1398 *length = 0;
1399 if (connection->failed || ngtcp2_conn_in_closing_period2(connection->conn) ||
1400 ngtcp2_conn_in_draining_period2(connection->conn))
1401 return ASCIICHAT_OK;
1402 asciichat_error_t result = update_time(connection, now_ns);
1403 if (result != ASCIICHAT_OK)
1404 return result;
1405 ngtcp2_path_storage_zero(path);
1406 ngtcp2_pkt_info info = {0};
1407 ngtcp2_ccerr close_error;
1408 ngtcp2_ccerr_default(&close_error);
1409 ngtcp2_ssize written =
1410 ngtcp2_conn_write_connection_close(connection->conn, &path->path, &info, packet, capacity, &close_error, now_ns);
1411 if (written < 0)
1412 return SET_ERRNO(ERROR_NETWORK, "Cannot write QUIC close packet: %s", ngtcp2_strerror((int)written));
1413 *length = (size_t)written;
1414 return ASCIICHAT_OK;
1415}

References ASCIICHAT_OK, quic_connection::conn, ERROR_INVALID_PARAM, ERROR_NETWORK, quic_connection::failed, and SET_ERRNO.

Referenced by quic_udp_close_peer().