1#define _POSIX_C_SOURCE 200809L
28#include <sys/socket.h>
30#include <netinet/tcp.h>
42#define CWIST_TLS_COALESCE_MAX (16 * 1024)
48static uint64_t cwist_https_now_ms(
void) {
58static int cwist_ssl_wait(
int fd,
int ssl_error,
int timeout_ms) {
59 struct pollfd pfd = {.fd = fd, .events = 0};
69 if (
ret <= 0)
return -1;
74struct https_thread_payload {
90#define HTTPS_TASK_QUEUE_INITIAL 1024
91#define HTTPS_TASK_QUEUE_MAX 2097152
105 https_pool_task_t *queue;
115} https_thread_pool_t;
117static https_thread_pool_t g_https_pool;
118static bool g_https_pool_initialized =
false;
121static void *https_thread_handler(
void *arg);
128static void https_park_stop(
void);
129static void https_park_reopen(
void);
135static __thread bool t_https_parked =
false;
136static void https_close_conn_cb(
void *handle);
144static inline https_pool_task_t *resize_queue(https_pool_task_t *queue,
size_t new_len) {
145 https_pool_task_t *
old = g_https_pool.queue;
146 size_t count = g_https_pool.count;
150 size_t first = g_https_pool.queue_len - g_https_pool.head;
155 g_https_pool.queue = queue;
156 g_https_pool.queue_len =
new_len;
157 g_https_pool.head = 0;
158 g_https_pool.tail =
count;
174static bool https_pool_reserve_locked(
void) {
175 while (g_https_pool.count >= g_https_pool.queue_len) {
176 if (g_https_pool.resizing || g_https_pool.shutdown)
return false;
181 g_https_pool.resizing =
true;
187 if (!queue || g_https_pool.shutdown) {
190 g_https_pool.resizing =
false;
197 https_pool_task_t *
old = resize_queue(queue,
new_len);
204 g_https_pool.resizing =
false;
219static void *https_pool_worker(
void *arg) {
223 while (g_https_pool.count == 0 && !g_https_pool.shutdown) {
226 if (g_https_pool.shutdown) {
230 https_pool_task_t
task = g_https_pool.queue[g_https_pool.head];
231 g_https_pool.head = (g_https_pool.head + 1) % g_https_pool.queue_len;
232 g_https_pool.count--;
241 struct https_thread_payload *payload =
cwist_alloc(
sizeof(*payload));
243 payload->client_fd =
task.client_fd;
244 payload->ctx =
task.ctx;
245 payload->handler =
task.handler;
246 payload->user_ctx =
task.user_ctx;
247 payload->pres_ssl =
task.pres_ssl;
248 payload->conn =
task.conn;
249 https_thread_handler(payload);
269 if (g_https_pool_initialized)
return 0;
271 memset(&g_https_pool, 0,
sizeof(g_https_pool));
280 g_https_pool_initialized =
true;
311 while (!g_https_pool.shutdown && !https_pool_reserve_locked()) {
314 if (g_https_pool.shutdown) {
320 g_https_pool.queue[g_https_pool.tail].client_fd = client_fd;
321 g_https_pool.queue[g_https_pool.tail].ctx = ctx;
322 g_https_pool.queue[g_https_pool.tail].handler = handler;
323 g_https_pool.queue[g_https_pool.tail].user_ctx = user_ctx;
324 g_https_pool.queue[g_https_pool.tail].pres_ssl = pres_ssl;
325 g_https_pool.queue[g_https_pool.tail].conn =
NULL;
326 g_https_pool.tail = (g_https_pool.tail + 1) % g_https_pool.queue_len;
327 g_https_pool.count++;
345 while (!g_https_pool.shutdown && !https_pool_reserve_locked()) {
348 if (g_https_pool.shutdown) {
353 g_https_pool.queue[g_https_pool.tail].client_fd = conn->
fd;
354 g_https_pool.queue[g_https_pool.tail].ctx = ctx;
355 g_https_pool.queue[g_https_pool.tail].handler = handler;
356 g_https_pool.queue[g_https_pool.tail].user_ctx = user_ctx;
357 g_https_pool.queue[g_https_pool.tail].pres_ssl =
NULL;
358 g_https_pool.queue[g_https_pool.tail].conn = conn;
359 g_https_pool.tail = (g_https_pool.tail + 1) % g_https_pool.queue_len;
360 g_https_pool.count++;
371 if (!g_https_pool_initialized)
return;
375 g_https_pool.shutdown = 1;
381 while (g_https_pool.resizing)
pthread_cond_wait(&g_https_pool.cond_not_full, &g_https_pool.mutex);
386 while (g_https_pool.count > 0) {
387 https_pool_task_t
task = g_https_pool.queue[g_https_pool.head];
388 g_https_pool.head = (g_https_pool.head + 1) % g_https_pool.queue_len;
389 g_https_pool.count--;
401 g_https_pool.queue =
NULL;
402 g_https_pool.queue_len = 0;
404 g_https_pool_initialized =
false;
458 if (
p->prev)
p->prev->next =
p->next;
460 if (
p->next)
p->next->prev =
p->prev;
491 bool running =
g_park.running;
497 for (
int i = 0;
i <
n;
i++) {
500 bool mine =
p->linked;
526 https_park_teardown(
p->conn);
555 if (
g_park.epoll_fd < 0)
return false;
579 static int enabled = -1;
581 const char *
env =
getenv(
"CWIST_HTTPS_PARK");
594 https_connection_teardown(conn);
610 if (!
p)
return false;
615 p->deadline_ms = cwist_https_now_ms() +
idle_ms;
624 if (
p->prev)
p->prev->next =
p;
638 t_https_parked =
true;
644static void https_park_reopen(
void) {
650static void https_park_stop(
void) {
654 if (running)
g_park.closed =
true;
656 if (!running)
return;
662 https_park_teardown(
p->conn);
679static void https_park_stop(
void) {}
680static void https_park_reopen(
void) {}
684 if (!conn || !conn->
ssl || conn->
buf_len > 0)
return false;
703static void cwist_tcp_quickack(
int fd) {
704#if defined(__linux__) && defined(TCP_QUICKACK)
714 const char *
env =
getenv(
"CWIST_HTTPS_IDLE_TIMEOUT_MS");
736 if (!ctx)
return NULL;
791 _Atomic
bool running;
801#define CWIST_HTTPS_HS_MAX_SHARDS 16
822 if (!
p->linked)
return;
824 p->prev->next =
p->next;
828 p->next->prev =
p->prev;
857 while (
sh->running) {
864 for (
int i = 0;
i <
n;
i++) {
877 bool found =
p->linked;
880 if (!found)
continue;
883 cwist_tcp_quickack(
p->fd);
939 if (
sh->wakeup_wr >= 0) {
941 if (
write(
sh->wakeup_wr, &b, 1) < 0) {
958 if (
sh->epoll_fd >= 0)
close(
sh->epoll_fd);
959 if (
sh->wakeup_rd >= 0)
close(
sh->wakeup_rd);
960 if (
sh->wakeup_wr >= 0)
close(
sh->wakeup_wr);
962 sh->wakeup_rd =
sh->wakeup_wr = -1;
979 const char *
env =
getenv(
"CWIST_HTTPS_HS_SHARDS");
988 for (
long i = 0;
i <
want;
i++) {
992 sh->wakeup_rd =
sh->wakeup_wr = -1;
997 if (
sh->epoll_fd < 0)
break;
1004 sh->wakeup_rd =
pfd[0];
1005 sh->wakeup_wr =
pfd[1];
1012 sh->running =
false;
1017 sh->wakeup_rd =
sh->wakeup_wr = -1;
1058 if (!ctx || client_fd < 0) {
1059 if (client_fd >= 0)
close(client_fd);
1071 SSL *ssl = cwist_https_ssl_new(ctx);
1087 p->handler = handler;
1088 p->user_ctx = user_ctx;
1125 if (
write(
sh->wakeup_wr, &b, 1) < 0) {
1143 if (!ctx || client_fd < 0) {
1144 if (client_fd >= 0)
close(client_fd);
1152#define CWIST_ALPN_HTTP11 ((const unsigned char *)"\x08http/1.1")
1153#define CWIST_ALPN_H2_HTTP11 ((const unsigned char *)"\x02h2\x08http/1.1")
1154#define CWIST_ALPN_H3_H2_HTTP11 ((const unsigned char *)"\x02h3\x02h2\x08http/1.1")
1155#define CWIST_ALPN_HTTP11_LEN 9
1156#define CWIST_ALPN_H2_HTTP11_LEN 12
1157#define CWIST_ALPN_H3_H2_HTTP11_LEN 15
1191static void cwist_https_apply_base_tls_defaults(
SSL_CTX *ssl_ctx) {
1193#ifdef SSL_OP_NO_RENEGOTIATION
1212 "ECDHE-RSA-AES128-GCM-SHA256:"
1213 "ECDHE-ECDSA-AES256-GCM-SHA384:"
1214 "ECDHE-RSA-AES256-GCM-SHA384:"
1215 "ECDHE-ECDSA-CHACHA20-POLY1305:"
1216 "ECDHE-RSA-CHACHA20-POLY1305") != 1) {
1217 return make_ssl_error(
"Unable to apply HTTP/2-compatible TLS 1.2 cipher profile");
1219#ifdef SSL_CTX_set_ciphersuites
1221 "TLS_AES_256_GCM_SHA384:"
1222 "TLS_CHACHA20_POLY1305_SHA256") != 1) {
1223 return make_ssl_error(
"Unable to apply HTTP/2-compatible TLS 1.3 cipher suites");
1227 err.error.err_i16 = 0;
1231static int cwist_https_alpn_select_cb(
SSL *ssl,
const unsigned char **out,
unsigned char *
outlen,
1232 const unsigned char *
in,
unsigned int inlen,
void *arg) {
1310 unsigned char name[16];
1311 unsigned char aes_key[32];
1312 unsigned char hmac_key[32];
1315static int g_ticket_key_ex_data_idx = -1;
1318static void cwist_tls_ticket_key_ex_data_init(
void) {
1326 if (ssl_ctx && g_ticket_key_ex_data_idx >= 0) {
1353static void cwist_tls_setup_shared_ticket_key(
SSL_CTX *ssl_ctx,
void **
out_key) {
1355 pthread_once(&g_ticket_key_ex_data_once, cwist_tls_ticket_key_ex_data_init);
1356 if (g_ticket_key_ex_data_idx < 0)
return;
1370 const char *key_path) {
1388 const char *key_path,
1393 bool enable_http2 = options && (options->
enable_http2 || enable_http3);
1402 return make_ssl_error(
"Unable to create SSL context");
1407 return make_ssl_error(
"Unable to enforce TLS minimum version");
1409 cwist_https_apply_base_tls_defaults(ssl_ctx);
1413 return make_ssl_error(
"PQC layer configuration failed");
1417 err = cwist_https_apply_http2_tls_profile(ssl_ctx);
1418 if (!cwist_error_is_ok(&
err)) {
1427 return make_ssl_error(
"Unable to load certificate");
1432 return make_ssl_error(
"Unable to complete certificate chain");
1437 return make_ssl_error(
"Unable to load private key");
1443 return make_ssl_error(
"Private key does not match certificate");
1447 err.error.err_i16 = 0;
1452 const char *cert_path,
const char *key_path,
1457 bool enable_http2 = options && (options->
enable_http2 || enable_http3);
1459 if (!ctx || !cert_path || !key_path) {
1460 err.error.err_i16 = -1;
1465 err = cwist_https_build_ssl_ctx(&ssl_ctx, cert_path, key_path, options, app);
1466 if (!cwist_error_is_ok(&
err)) {
1473 err.error.err_i16 = -1;
1476 (*ctx)->ctx = ssl_ctx;
1477 (*ctx)->http2_enabled = enable_http2;
1478 (*ctx)->http3_enabled = enable_http3;
1479 (*ctx)->ticket_key =
NULL;
1484 cwist_tls_setup_shared_ticket_key(ssl_ctx, &(*ctx)->ticket_key);
1488 err.error.err_i16 = 0;
1511 if (!ctx || !cert_path || !key_path) {
1512 err.error.err_i16 = -1;
1519 err = cwist_https_build_ssl_ctx(&
new_ctx, cert_path, key_path, &options, app);
1520 if (!cwist_error_is_ok(&
err)) {
1529 pthread_once(&g_ticket_key_ex_data_once, cwist_tls_ticket_key_ex_data_init);
1530 if (ctx->
ticket_key && g_ticket_key_ex_data_idx >= 0) {
1550 err.error.err_i16 = 0;
1587static _Atomic
long g_tls_handshakes_total;
1588static _Atomic
long g_tls_handshakes_resumed;
1589static _Atomic
long g_tls_handshakes_tls12;
1590static _Atomic
long g_tls_handshakes_tls13;
1591static _Atomic
long g_tls_ciphers_aes128_gcm;
1592static _Atomic
long g_tls_ciphers_aes256_gcm;
1593static _Atomic
long g_tls_ciphers_chacha20;
1594static _Atomic
long g_tls_ciphers_other;
1595static _Atomic
long g_tls_connections_active;
1637static void https_tls_record_handshake(
SSL *ssl) {
1654 if (
strcmp(cipher,
"TLS_AES_128_GCM_SHA256") == 0)
1656 else if (
strcmp(cipher,
"TLS_AES_256_GCM_SHA384") == 0)
1658 else if (
strcmp(cipher,
"TLS_CHACHA20_POLY1305_SHA256") == 0)
1674 err.error.err_i16 = -1;
1678 memset(*conn, 0,
sizeof(**conn));
1679 (*conn)->fd = client_fd;
1682 if (!(*conn)->read_buf) {
1685 err.error.err_i16 = -1;
1689 (*conn)->read_buf[0] =
'\0';
1690 (*conn)->negotiated_http2 =
false;
1693 (*conn)->deferred =
false;
1724 (*conn)->negotiated_http2 =
true;
1733 cwist_tcp_quickack(client_fd);
1737 https_tls_record_handshake(ssl);
1740 err.error.err_i16 = 0;
1752static void https_close_conn_cb(
void *handle) {
1760 if (!ctx || client_fd < 0) {
1761 err.error.err_i16 = -1;
1765 SSL *ssl = cwist_https_ssl_new(ctx);
1767 return make_ssl_error(
"Failed to create SSL structure");
1771 cwist_tcp_quickack(client_fd);
1781 cwist_tcp_quickack(client_fd);
1806 if (!cwist_error_is_ok(&
wrap_err)) {
1851 if (conn->
fd >= 0) {
1879 https_connection_teardown(conn);
1888 if (!conn || !conn->
ssl)
return NULL;
1968 if (!req)
return NULL;
2072 size_t left = len - off;
2105 if (!conn || !conn->
ssl || !res) {
2106 err.error.err_i16 = -1;
2124 snprintf(alt_svc,
sizeof(alt_svc),
"h3=\":%d\"; ma=86400", port);
2136 size_t body_len = 0;
2151 int rc = cwist_ssl_write_all(conn,
combined, header_len + body_len);
2154 return make_ssl_error(
"SSL coalesced write failed");
2161 if (cwist_ssl_write_all(conn,
header_buf, header_len) != 0) {
2162 return make_ssl_error(
"SSL header write failed");
2165 if (cwist_ssl_write_all(conn,
body_ptr, body_len) != 0) {
2166 return make_ssl_error(
"SSL body write failed");
2181 return make_ssl_error(
"file stream read failed");
2184 if (cwist_ssl_write_all(conn,
fbuf, (
size_t)
n) != 0) {
2185 return make_ssl_error(
"SSL file stream write failed");
2193 err.error.err_i16 = 0;
2201 if (!conn || !conn->
ssl || !res) {
2202 err.error.err_i16 = -1;
2218 snprintf(alt_svc,
sizeof(alt_svc),
"h3=\":%d\"; ma=86400", port);
2224 if (cwist_ssl_write_all(conn,
header_buf, header_len) != 0) {
2225 return make_ssl_error(
"SSL header write failed");
2228 err.error.err_i16 = 0;
2237static void *https_thread_handler(
void *arg) {
2238 struct https_thread_payload *payload = (
struct https_thread_payload *)arg;
2242 if (payload->conn) {
2243 conn = payload->conn;
2245 hs_err.error.err_i16 = 0;
2246 }
else if (payload->pres_ssl) {
2248 hs_err = https_wrap_established(payload->ctx, payload->client_fd, payload->pres_ssl, &conn);
2249 if (!cwist_error_is_ok(&
hs_err)) {
2256 if (cwist_error_is_ok(&
hs_err)) {
2260 t_https_parked =
false;
2262 payload->handler(conn, payload->user_ctx);
2267 if (t_https_parked) {
2268 t_https_parked =
false;
2269 }
else if (!deferred) {
2276 if (payload->conn) {
2279 close(payload->client_fd);
2299 if (
server_fd < 0 || !ctx || !handler) {
2300 err.error.err_i16 = -1;
2305 err.error.err_i16 = -1;
2314 if (client_fd < 0) {
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
void * cwist_malloc(size_t size)
Allocate zeroed memory via the CWIST owner context.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
bool cwist_async_https_take_deferred(void)
Private wiring between the deferred-response path (async.c) and the C1M connection engine (http....
Safe string type with helper methods.
cwist_error_t cwist_sstring_adopt_len(cwist_sstring *str, char *buf, size_t len)
Adopt a heap buffer, taking ownership without copying.
mbedTLS TLS backend: OPENSSL_cleanse / CRYPTO_memcmp.
@ CWIST_ERR_INT16
used when checking common errcodes in Unix/Linux
cwist_error_t make_error(cwist_errtype_t type)
Creates an error object initialized with the specified type.
mbedTLS TLS backend: error queue subset.
#define ERR_error_string_n
mbedTLS TLS backend: EVP subset (HMAC digest tags, AES-256-CBC).
#define EVP_DecryptInit_ex
struct cwist_mtls_cipher_ctx EVP_CIPHER_CTX
#define EVP_EncryptInit_ex
Epoch-based garbage collection wrapper.
bool cwist_conn_registry_untrack(void *handle)
Remove a handle from the registry before closing it yourself through the normal explicit path.
bool cwist_gc_scope_disown(void *ptr)
Remove ptr from the current thread's pending-sweep list without freeing it, because ownership is bein...
bool cwist_full_gc_enabled(void)
Check whether full-GC mode is currently enabled.
bool cwist_conn_registry_adopt(void *handle)
Make the calling thread the owner of a tracked handle.
void cwist_conn_registry_track(void *handle, cwist_conn_close_fn close_fn)
Register a connection handle for the full-GC exit sweep, owned by the calling thread (full-GC mode on...
mbedTLS TLS backend: HMAC subset (HMAC-SHA256, one-shot + streaming).
struct cwist_mtls_hmac_ctx HMAC_CTX
#define CWIST_HTTP_READ_BUFFER_SIZE
#define CWIST_HTTP_MAX_BODY_SIZE
#define CWIST_HTTP_MAX_HEADER_SIZE
size_t cwist_http_serialize_headers(cwist_http_response *res, char *buf, size_t buf_size)
Serialize only the status line and headers into a caller buffer.
char * cwist_http_header_get(cwist_http_header_node *head, const char *key)
Find a header value by key.
void cwist_http_request_destroy(cwist_http_request *req)
Destroy an HTTP request object.
cwist_http_request * cwist_http_parse_request(const char *raw_request)
Parse a raw HTTP request string.
#define CWIST_HTTP_TIMEOUT_MS
cwist_error_t cwist_http_header_add(cwist_http_header_node **head, const char *key, const char *value)
Add a header to the list.
#define CWIST_ALPN_HTTP11_LEN
#define CWIST_ALPN_H2_HTTP11
long cwist_https_tls_ciphers_aes128_gcm_total(void)
Handshakes negotiated with TLS_AES_128_GCM_SHA256.
struct cwist_tls_ticket_key cwist_tls_ticket_key
cwist_http_request * cwist_https_receive_request(cwist_https_connection *conn)
Read from the TLS stream until a full HTTP request has been assembled.
bool cwist_tls_apply_pqc_layer(cwist_app *app, SSL_CTX *ctx)
Apply PQC hybrid key exchange settings to an SSL context.
cwist_error_t cwist_https_accept(cwist_https_context *ctx, int client_fd, cwist_https_connection **conn)
#define CWIST_ALPN_H2_HTTP11_LEN
void https_pool_submit_conn(cwist_https_connection *conn, cwist_https_context *ctx, void(*handler)(cwist_https_connection *, void *), void *user_ctx)
Submit an established connection back to the worker pool (e.g. keep-alive re-arm after async defer)....
#define HTTPS_TASK_QUEUE_MAX
cwist_error_t cwist_https_send_response(cwist_https_connection *conn, cwist_http_response *res)
Serialize an HTTP response and send it over an active TLS connection.
cwist_error_t cwist_https_init_context(cwist_https_context **ctx, const char *cert_path, const char *key_path)
void https_pool_submit_ready(int client_fd, SSL *pres_ssl, cwist_https_context *ctx, void(*handler)(cwist_https_connection *, void *), void *user_ctx)
Submit a connection whose TLS handshake already completed (pres_ssl). Blocks while the queue is full;...
void cwist_https_close_connection(cwist_https_connection *conn)
void https_pool_destroy(void)
Shut down the global HTTPS thread pool: signal workers to exit, join them, close any connections stil...
#define CWIST_TLS_COALESCE_MAX
cwist_https_protocol cwist_https_connection_protocol(const cwist_https_connection *conn)
cwist_error_t cwist_https_reload_context(cwist_https_context *ctx, const char *cert_path, const char *key_path, cwist_app *app)
Swap in a new certificate chain and key without dropping connections.
int https_pool_init(void)
Create the worker threads, mutex, and condition variables of the global HTTPS thread pool....
int https_hs_shepherd_start(void)
long cwist_https_tls_handshakes_total(void)
Total TLS handshakes that completed (full + resumed).
long cwist_https_tls_ciphers_other_total(void)
Handshakes negotiated with any other cipher.
uint64_t cwist_https_idle_timeout_ms(void)
Idle keep-alive budget for parked HTTP/1.1 TLS connections, in ms. CWIST_HTTPS_IDLE_TIMEOUT_MS overri...
cwist_error_t cwist_https_send_response_head(cwist_https_connection *conn, cwist_http_response *res)
long cwist_https_tls_handshakes_tls12_total(void)
Handshakes that negotiated TLS 1.2.
long cwist_https_tls_ciphers_chacha20_total(void)
Handshakes negotiated with TLS_CHACHA20_POLY1305_SHA256.
cwist_error_t cwist_https_init_context_with_options(cwist_https_context **ctx, const char *cert_path, const char *key_path, const cwist_https_options *options, cwist_app *app)
bool cwist_https_conn_idle(cwist_https_connection *conn)
True when conn has no buffered TLS bytes and nothing readable.
long cwist_https_pending_handshakes(void)
Number of TLS handshakes currently parked in the shepherd.
long cwist_https_tls_handshakes_resumed_total(void)
TLS handshakes completed via session resumption/ticket.
cwist_error_t cwist_https_server_loop(int server_fd, cwist_https_context *ctx, void(*handler)(cwist_https_connection *, void *), void *user_ctx)
Accept HTTPS clients in a loop and dispatch each one to the supplied handler.
bool cwist_https_connection_uses_http2(const cwist_https_connection *conn)
Gracefully close an HTTPS connection and free its buffers.
#define CWIST_ALPN_HTTP11
long cwist_https_tls_handshakes_tls13_total(void)
Handshakes that negotiated TLS 1.3.
void cwist_https_destroy_context(cwist_https_context *ctx)
Free an HTTPS context and release its OpenSSL resources.
bool cwist_https_park(cwist_https_connection *conn, uint64_t idle_ms, cwist_https_park_class cls)
Hand an idle connection back to the HTTPS pool's park set.
long cwist_https_tls_connections_active(void)
Currently established TLS connections (wrap minus teardown).
void cwist_https_dispatch(int client_fd, cwist_https_context *ctx, void(*handler)(cwist_https_connection *, void *), void *user_ctx)
Accept a TLS connection without parking a worker on the handshake. Completes the handshake inline whe...
#define HTTPS_TASK_QUEUE_INITIAL
void https_hs_shepherd_stop(void)
void https_pool_submit(int client_fd, cwist_https_context *ctx, void(*handler)(cwist_https_connection *, void *), void *user_ctx)
Queue a freshly accepted client socket whose TLS handshake still needs to run in a pool worker.
long cwist_https_tls_ciphers_aes256_gcm_total(void)
Handshakes negotiated with TLS_AES_256_GCM_SHA384.
#define CWIST_HTTPS_HANDSHAKE_TIMEOUT_MS
#define CWIST_HTTP_HEADERS_TIMEOUT_MS
#define CWIST_HTTP_BODY_IDLE_TIMEOUT_MS
long get_optimal_thread_count(void)
Compute the HTTP worker/event-loop thread count.
HTTPS/TLS wrapper interface.
@ CWIST_HTTPS_PROTOCOL_HTTP2
@ CWIST_HTTPS_PROTOCOL_HTTP11
@ CWIST_HTTPS_PROTOCOL_NONE
mbedTLS TLS backend: RAND_bytes over mbedTLS CTR-DRBG.
Unified Graceful Shutdown support for CWIST.
atomic_int g_cwist_running
Global running flag. Checked by all server event loops.
mbedTLS TLS backend: OpenSSL-shaped seam over the CWIST TLS subset.
#define SSL_CTX_check_private_key
#define SSL_OP_CIPHER_SERVER_PREFERENCE
#define SSL_CTX_get_ex_new_index
struct cwist_mtls_ssl SSL
#define SSL_select_next_proto
#define SSL_get0_alpn_selected
#define SSL_MODE_AUTO_RETRY
#define SSL_CTX_set_tlsext_ticket_key_cb
#define OpenSSL_add_ssl_algorithms()
#define SSL_TLSEXT_ERR_OK
#define SSL_session_reused
#define SSL_TLSEXT_ERR_NOACK
#define SSL_CTX_set_options
#define SSL_CTX_set_session_cache_mode
#define TLS_server_method
#define SSL_get_cipher_name
#define OPENSSL_NPN_NEGOTIATED
#define SSL_OP_NO_COMPRESSION
#define SSL_ERROR_WANT_READ
#define SSL_CTX_sess_set_cache_size
#define SSL_CTX_get_ex_data
#define SSL_CTX_use_PrivateKey_file
#define SSL_load_error_strings()
#define SSL_CTX_set_timeout
#define SSL_CTX_set_ex_data
#define SSL_CTX_set_cipher_list
#define SSL_OP_NO_RENEGOTIATION
#define SSL_CTX_use_certificate_chain_file
struct cwist_mtls_method SSL_METHOD
#define SSL_CTX_set_alpn_select_cb
#define SSL_SESS_CACHE_SERVER
#define SSL_CTX_set_session_id_context
#define SSL_CTX_set_ciphersuites
struct cwist_mtls_ctx SSL_CTX
#define SSL_CTX_set_min_proto_version
#define SSL_ERROR_WANT_WRITE
Main Application Context.
Integrated error structure used throughout the system.
void * https_conn
HTTPS connection wrapper when on TLS path (internal).
HTTP Response Object. Supports standard string body or Zero-Copy pointer body.
int file_stream_fd
Open descriptor for sendfile.
bool use_file_stream
Fast File Streaming.
const void * ptr_body
Pointer to external data (e.g., mmap region)
off_t file_stream_offset
Current offset for sendfile loop.
cwist_http_header_node * headers
bool is_ptr_body
Zero-Copy Pointer Body.
size_t ptr_body_len
Length of external data.
size_t file_stream_len
Total bytes to stream.
void(* proto_state_free)(void *state)
struct cwist_https_context * pool_ctx
cwist_https_protocol negotiated_protocol
void(* pool_handler)(struct cwist_https_connection *, void *)
void * ticket_key
Shared session-ticket key material (forked workers inherit it)
pthread_rwlock_t ctx_lock
char * data
Access directly only when raw handling is necessary.
Unified error code and type definitions for the CWIST system layer.
int cwist_tls_autoload_intermediates(SSL_CTX *ssl_ctx)
Autoload missing intermediate CA certificates into an SSL_CTX chain.
unsigned long cwist_tls_sess_cache_size(void)
Zero-latency speculative fast-path writer and P2C worker scheduler.
uint32_t cwist_sched_p2c_select_worker(const _Atomic uint32_t *worker_loads, uint32_t num_workers)
Select worker using Power of Two Random Choices (P2C).