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

Go to the source code of this file.

Data Structures

struct  outbound_packet
struct  outbound_stream_t
struct  acip_outbound

Macros

#define OUTBOUND_MAX_PACKETS   512
#define OUTBOUND_MAX_STREAMS   64
#define WIRE_OVERHEAD   (sizeof(packet_header_t) + 32 + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE)

Typedefs

typedef struct outbound_packet outbound_packet_t

Functions

asciichat_error_t acip_outbound_create (acip_transport_t *transport)
void acip_outbound_stop (acip_transport_t *transport)
void acip_outbound_destroy (acip_transport_t *transport)
asciichat_error_t acip_outbound_submitv (acip_transport_t *transport, const socket_buffer_t *buffers, size_t count, acip_admission_t *admission)
asciichat_error_t acip_outbound_submitv_ex (acip_transport_t *transport, const socket_buffer_t *buffers, size_t count, const acip_send_options_t *options, acip_admission_t *admission)
asciichat_error_t acip_outbound_snapshot (acip_transport_t *transport, acip_outbound_stats_t *stats)
bool acip_outbound_needs_keyframe (acip_transport_t *transport, uint16_t type, uint32_t id)

Macro Definition Documentation

◆ OUTBOUND_MAX_PACKETS

#define OUTBOUND_MAX_PACKETS   512

Definition at line 14 of file backpressure.c.

◆ OUTBOUND_MAX_STREAMS

#define OUTBOUND_MAX_STREAMS   64

Definition at line 15 of file backpressure.c.

◆ WIRE_OVERHEAD

#define WIRE_OVERHEAD   (sizeof(packet_header_t) + 32 + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE)

Definition at line 16 of file backpressure.c.

Typedef Documentation

◆ outbound_packet_t

Function Documentation

◆ acip_outbound_create()

asciichat_error_t acip_outbound_create ( acip_transport_t * transport)

Definition at line 439 of file backpressure.c.

439 {
440 ASCII_OTEL_SCOPE(ACIP_OUTBOUND_CREATE);
441 if (!transport || !transport->methods || (!transport->methods->send && !transport->methods->sendv_ex))
442 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing outbound backend");
443 if (transport->outbound)
444 return ASCIICHAT_OK;
446 if (mutex_init(&out->mutex, "connection_outgoing_packet_queue") != ASCIICHAT_OK) {
447 SAFE_FREE(out);
448 return GET_ERRNO();
449 }
450 if (cond_init(&out->changed, "outgoing_packet_ready_or_done") != ASCIICHAT_OK) {
451 mutex_destroy(&out->mutex);
452 SAFE_FREE(out);
453 return GET_ERRNO();
454 }
455 out->transport = transport;
456 asciichat_error_t result = platform_thread_create(&out->worker, "outbound", outbound_worker, out);
457 if (result != ASCIICHAT_OK) {
458 cond_destroy(&out->changed);
459 mutex_destroy(&out->mutex);
460 SAFE_FREE(out);
461 return result;
462 }
463 transport->outbound = out;
464 return ASCIICHAT_OK;
465}
#define SET_ERRNO(code,...)
#define GET_ERRNO()
struct acip_outbound acip_outbound_t
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
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 ASCII_OTEL_SCOPE(id)
Definition otel.h:72
static bool size_t gotel_query_t * out
Definition queries.h:8
asciichat_error_t(* send)(acip_transport_t *transport, const void *data, size_t len)
Send data through this transport.
asciichat_error_t(* sendv_ex)(acip_transport_t *transport, const socket_buffer_t *buffers, size_t count, const acip_send_options_t *options)
struct acip_outbound * outbound
Per-connection plaintext admission and scheduling.
const acip_transport_methods_t * methods
Method table (virtual functions).

References ASCII_OTEL_SCOPE, ASCIICHAT_OK, ERROR_INVALID_PARAM, GET_ERRNO, acip_transport::methods, out, acip_transport::outbound, SAFE_CALLOC, SAFE_FREE, acip_transport_methods_t::send, acip_transport_methods_t::sendv_ex, and SET_ERRNO.

Referenced by acip_async_tcp_client_create(), acip_async_tcp_transport_create(), acip_tcp_transport_create(), acip_websocket_client_transport_create(), acip_websocket_server_transport_create(), and quic_transport_begin_security().

◆ acip_outbound_destroy()

void acip_outbound_destroy ( acip_transport_t * transport)

Stop admission, interrupt writes, join the worker, and release every queued owner.

Definition at line 478 of file backpressure.c.

478 {
479 ASCII_OTEL_SCOPE(ACIP_OUTBOUND_DESTROY);
480 acip_outbound_t *out = transport->outbound;
481 if (!out)
482 return;
483 mutex_lock(&out->mutex);
484 out->stopping = true;
485 cond_broadcast(&out->changed);
486 mutex_unlock(&out->mutex);
487 /* Wake a blocked send while every backend resource is still alive. The
488 * failed-send worker also closes its backend, so wait for that worker before
489 * closing here: two concurrent closes can join the same service thread. */
490 if (transport->methods->interrupt)
491 transport->methods->interrupt(transport);
492 else
493 transport->methods->close(transport);
494 thread_join(&out->worker, NULL);
495 if (transport->methods->interrupt)
496 transport->methods->close(transport);
497 mutex_lock(&out->mutex);
498 outbound_record_failure_and_fail_pending(out, ERROR_NETWORK, NULL, NULL);
499 while (out->recycled) {
500 outbound_packet_t *p = out->recycled;
501 out->recycled = p->next;
502 packet_free(out, p);
503 }
504 mutex_unlock(&out->mutex);
505 cond_destroy(&out->changed);
506 mutex_destroy(&out->mutex);
507 SAFE_FREE(transport->outbound);
508}
struct outbound_packet outbound_packet_t
@ ERROR_NETWORK
Definition error_codes.h:72
void(* interrupt)(acip_transport_t *transport)
asciichat_error_t(* close)(acip_transport_t *transport)
Close this transport.
struct outbound_packet * next

References ASCII_OTEL_SCOPE, acip_transport_methods_t::close, ERROR_NETWORK, acip_transport_methods_t::interrupt, acip_transport::methods, outbound_packet::next, out, acip_transport::outbound, and SAFE_FREE.

Referenced by acip_transport_destroy().

◆ acip_outbound_needs_keyframe()

bool acip_outbound_needs_keyframe ( acip_transport_t * transport,
uint16_t type,
uint32_t id )

Definition at line 709 of file backpressure.c.

709 {
710 if (!transport || !transport->outbound)
711 return false;
712 acip_outbound_t *out = transport->outbound;
713 if (transport->methods->consume_keyframe_request &&
714 transport->methods->consume_keyframe_request(transport, type, id)) {
715 outbound_packet_t stream = {.type = type, .stream = id, .video = true, .encoded = true};
716 mutex_lock(&out->mutex);
717 discard_stream(out, &stream);
718 mutex_unlock(&out->mutex);
719 return true;
720 }
721 mutex_lock(&out->mutex);
722 size_t count = (size_t)atomic_load_u64(&out->stream_count);
723 for (size_t i = 0; i < count; ++i)
724 if (out->streams[i].type == type && out->streams[i].stream == id) {
725 bool needs_keyframe = atomic_load_bool(&out->streams[i].needs_keyframe);
726 mutex_unlock(&out->mutex);
727 return needs_keyframe;
728 }
729 mutex_unlock(&out->mutex);
730 return true;
731}
bool(* consume_keyframe_request)(acip_transport_t *transport, uint16_t type, uint32_t stream_id)

References acip_transport_methods_t::consume_keyframe_request, acip_transport::methods, out, and acip_transport::outbound.

Referenced by acip_send_image_frame_h265(), and threaded_send_image_frame_encoded().

◆ acip_outbound_snapshot()

asciichat_error_t acip_outbound_snapshot ( acip_transport_t * transport,
acip_outbound_stats_t * stats )

Definition at line 687 of file backpressure.c.

687 {
688 if (!transport || !transport->outbound || !stats)
689 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing outbound statistics");
690 acip_outbound_t *out = transport->outbound;
691 mutex_lock(&out->mutex);
692 stats->accepted = atomic_load_u64(&out->accepted);
693 stats->submitted = atomic_load_u64(&out->submitted);
694 stats->dropped = atomic_load_u64(&out->dropped);
695 stats->congestion = atomic_load_u64(&out->congestion);
696 stats->recovery_frames = atomic_load_u64(&out->recovery_frames);
697 stats->peak_bytes = (size_t)atomic_load_u64(&out->peak_bytes);
698 stats->application_bytes = out->bytes + out->active_bytes;
699 stats->backend_bytes = backend_bytes(out);
700 stats->backend_reserved_bytes = transport->methods->reserved_bytes;
701 uint64_t now = time_get_ns();
702 for (outbound_packet_t *p = out->head; p; p = p->next)
703 if (p->video && now - p->created > stats->oldest_frame_age_ns)
704 stats->oldest_frame_age_ns = now - p->created;
705 mutex_unlock(&out->mutex);
706 return ASCIICHAT_OK;
707}
unsigned long long uint64_t
Definition common.h:63
size_t reserved_bytes
Bound for backend-owned pending data not exposed by queued_bytes.

References acip_outbound_stats_t::accepted, acip_outbound_stats_t::application_bytes, ASCIICHAT_OK, acip_outbound_stats_t::backend_bytes, acip_outbound_stats_t::backend_reserved_bytes, acip_outbound_stats_t::congestion, outbound_packet::created, acip_outbound_stats_t::dropped, ERROR_INVALID_PARAM, acip_transport::methods, outbound_packet::next, acip_outbound_stats_t::oldest_frame_age_ns, out, acip_transport::outbound, acip_outbound_stats_t::peak_bytes, acip_outbound_stats_t::recovery_frames, acip_transport_methods_t::reserved_bytes, SET_ERRNO, acip_outbound_stats_t::submitted, and outbound_packet::video.

◆ acip_outbound_stop()

void acip_outbound_stop ( acip_transport_t * transport)

Stop admission and wake queued producers without joining the worker or releasing backend resources.

Definition at line 467 of file backpressure.c.

467 {
468 acip_outbound_t *out = transport ? transport->outbound : NULL;
469 if (!out)
470 return;
471 mutex_lock(&out->mutex);
472 out->stopping = true;
473 out->stopped_by_caller = true;
474 outbound_record_failure_and_fail_pending(out, ERROR_NETWORK, NULL, NULL);
475 mutex_unlock(&out->mutex);
476}

References ERROR_NETWORK, out, and acip_transport::outbound.

◆ acip_outbound_submitv()

asciichat_error_t acip_outbound_submitv ( acip_transport_t * transport,
const socket_buffer_t * buffers,
size_t count,
acip_admission_t * admission )

Copy plaintext before returning ACCEPTED; congestion never changes encryption state. Handshake/control submissions except ping/pong wait for backend submission so crypto/setup barriers hold. Success describes local admission/submission, never receiver delivery. A terminal backend failure retains its status and errno context for waiting and subsequent producers. Congestion remains a nonfatal admission outcome.

Definition at line 675 of file backpressure.c.

676 {
677 return outbound_submitv(transport, buffers, count, NULL, admission);
678}

◆ acip_outbound_submitv_ex()

asciichat_error_t acip_outbound_submitv_ex ( acip_transport_t * transport,
const socket_buffer_t * buffers,
size_t count,
const acip_send_options_t * options,
acip_admission_t * admission )

Definition at line 680 of file backpressure.c.

681 {
682 if (!options)
683 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing outbound send options");
684 return outbound_submitv(transport, buffers, count, options, admission);
685}

References ERROR_INVALID_PARAM, and SET_ERRNO.

Referenced by acip_transport_sendv_ex().