17#define _POSIX_C_SOURCE 200809L
34#ifndef CWIST_BAREMETAL
35#include <sys/socket.h>
71static void cwist_async_reactor_complete(
void *ctx);
72static void cwist_async_deliver(cwist_async *
a);
73static bool cwist_async_publish_locked(cwist_async *
a);
91 default:
return "Status";
95static __thread bool t_https_deferred =
false;
98 bool deferred = t_https_deferred;
99 t_https_deferred =
false;
133 if (!req->
h2_queue) t_https_deferred =
true;
142 a->post.cb = cwist_async_reactor_complete;
146 cwist_http_async_disown_request(req);
147 cwist_http_async_disown_response(res);
174 cwist_http_async_disown_request(
a->req);
175 cwist_http_async_disown_response(
a->res);
176 a->keep_alive =
a->keep_alive &&
a->req->keep_alive &&
a->res->keep_alive;
177 bool finish =
a->finish_on_ack;
182 if (finish) cwist_async_deliver(
a);
190static bool cwist_async_claim(cwist_async *
a) {
196static void cwist_async_reactor_complete(
void *ctx);
200static void cwist_async_complete(cwist_async *
a) {
224 bool ok = cwist_error_is_ok(&
err);
226 if (
keep && ok &&
a->app &&
a->app->ssl_ctx &&
a->app->https_request_handler) {
227 conn->deferred =
false;
232 }
else if (
a->orphaned) {
237 }
else if (
a->reactor) {
247 bool ok =
err.error.err_i16 == 0;
249 if (
keep && ok &&
a->app) {
265static void cwist_async_reactor_complete(
void *ctx) {
266 cwist_async_complete((cwist_async *)ctx);
273static bool cwist_async_publish_locked(cwist_async *
a) {
276 cwist_http_async_disown_response(
a->final_res);
281 a->finish_on_ack =
true;
290static void cwist_async_deliver(cwist_async *
a) {
298 cwist_async_complete(
a);
306static void cwist_async_timeout_sched_init(
void) {
310static void cwist_async_timeout_job(
void *arg) {
312 if (!cwist_async_claim(
a)) {
322 bool deliver = cwist_async_publish_locked(
a);
324 if (
deliver) cwist_async_deliver(
a);
329 if (!
a ||
ms == 0)
return;
330 pthread_once(&g_timeout_once, cwist_async_timeout_sched_init);
331 if (!g_timeout_sched)
return;
341 const void *body,
size_t len) {
342 if (!
a || !cwist_async_claim(
a))
return false;
347 if (body && len > 0) {
353 bool deliver = cwist_async_publish_locked(
a);
355 if (
deliver) cwist_async_deliver(
a);
360 if (!
a || !res || !cwist_async_claim(
a))
return false;
363 a->final_res_owned = res !=
a->res;
364 bool deliver = cwist_async_publish_locked(
a);
366 if (
deliver) cwist_async_deliver(
a);
371 if (!
a || !cwist_async_claim(
a))
return false;
375 const char *
reason = cwist_async_reason(status);
379 a->keep_alive =
false;
380 bool deliver = cwist_async_publish_locked(
a);
382 if (
deliver) cwist_async_deliver(
a);
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
void cwist_async_dispatch_ack(cwist_async *a)
Internal: on the dispatch thread, after all middleware has unwound. Call exactly once; do not touch t...
bool cwist_async_respond_with(cwist_async *a, cwist_http_response *res)
Complete the exchange with a caller-built response. On success the framework takes ownership of res (...
cwist_async * cwist_async_retain(cwist_async *a)
Retain a live handle for a producer that may outlive completion. Must be called while the caller alre...
bool cwist_async_https_take_deferred(void)
bool cwist_async_respond(cwist_async *a, cwist_http_status_t status, const char *content_type, const void *body, size_t len)
Complete the exchange with a simple body response. Thread-safe and one-shot: the first of respond/res...
void cwist_async_set_timeout(cwist_async *a, uint64_t ms)
Answer with a 504 Gateway Timeout if the exchange is still pending after ms milliseconds....
bool cwist_async_abort(cwist_async *a, cwist_http_status_t status)
Complete the exchange with an error status and close the connection.
void cwist_async_wait_dispatched(cwist_async *a)
Wait until dispatch has acknowledged the handoff of a.
cwist_async * cwist_async_defer(cwist_http_request *req, cwist_http_response *res)
Defer the response for the current request.
void cwist_async_release(cwist_async *a)
Release a reference acquired with cwist_async_retain(). Does not complete or abort the exchange....
Deferred-response (async handler) API for CWIST.
struct cwist_async cwist_async
Private wiring between the deferred-response path (async.c) and the C1M connection engine (http....
void cwist_async_record_pending(struct cwist_async *a, const cwist_http_response *res)
uint64_t cwist_http_reactor_generation(void)
Return the current reactor generation counter.
void cwist_http_async_close_orphan(int client_fd, cwist_http_async_conn_t *conn)
Close an async connection whose owning worker pool is gone.
void cwist_async_forget_handle(const struct cwist_async *a)
bool cwist_http_reactor_post_live(cwist_reactor_t *reactor, uint64_t gen, cwist_reactor_post_t *node)
Post a reactor node only while the captured generation is current.
cwist_error_t cwist_sstring_assign_len(cwist_sstring *str, const char *data, size_t len)
Assign raw bytes with length.
cwist_error_t cwist_sstring_assign(cwist_sstring *str, const char *data)
Assign a C string.
Epoch-based garbage collection wrapper.
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.
HTTP/2 Protocol Definitions for CWIST.
cwist_h2_async_queue * cwist_h2_async_queue_acquire(cwist_h2_async_queue *q)
Take an additional reference on the queue (for an in-flight cwist_async handle).
int cwist_h2_async_queue_enqueue(cwist_h2_async_queue *q, uint32_t stream_id, cwist_http_request *req, cwist_http_response *send, cwist_http_response *res, bool send_owned)
void cwist_h2_async_queue_release(cwist_h2_async_queue *q)
Drop a reference on the queue. On the last reference: closes the wake descriptors,...
struct cwist_h2_async_queue cwist_h2_async_queue
cwist_error_t cwist_http_send_response(int client_fd, cwist_http_response *res)
Send a response over a socket.
cwist_error_t cwist_http_send_response_head(int client_fd, cwist_http_response *res)
Send only the status line and headers (HEAD replies).
@ CWIST_HTTP_UNAUTHORIZED
@ CWIST_HTTP_INTERNAL_ERROR
@ CWIST_HTTP_NOT_IMPLEMENTED
void cwist_http_request_destroy(cwist_http_request *req)
Destroy an HTTP request object.
cwist_error_t cwist_http_header_add(cwist_http_header_node **head, const char *key, const char *value)
Add a header to the list.
void cwist_http_response_destroy(cwist_http_response *res)
Destroy an HTTP response object.
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.
void cwist_https_close_connection(cwist_https_connection *conn)
bool cwist_http_pool_rearm_current(int client_fd, void(*handler)(int, void *), void *ctx)
Requeue the current connection's next handler turn on the pool.
void cwist_http_async_send_response(int client_fd, cwist_http_response *res, cwist_reactor_t *reactor, cwist_http_async_conn_t *conn, bool keep_alive, bool head_only)
Send a response on the async path, parking the unsent remainder on EAGAIN instead of blocking the rea...
@ CWIST_HTTP_NOT_MODIFIED
@ CWIST_HTTP_PARTIAL_CONTENT
@ CWIST_HTTP_GATEWAY_TIMEOUT
@ CWIST_HTTP_RANGE_NOT_SATISFIABLE
@ CWIST_HTTP_SERVICE_UNAVAILABLE
HTTPS/TLS wrapper interface.
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)....
cwist_error_t cwist_https_send_response_head(cwist_https_connection *conn, cwist_http_response *res)
struct cwist_reactor cwist_reactor_t
Background job scheduler / delayed task queue for CWIST.
struct cwist_scheduler cwist_scheduler_t
Opaque background job scheduler handle.
bool cwist_scheduler_schedule(cwist_scheduler_t *s, cwist_job_func func, void *arg, uint64_t delay_ms)
Schedule a job to run after a relative delay.
cwist_scheduler_t * cwist_scheduler_create(size_t worker_count, size_t queue_capacity)
Create a scheduler with a pool of background workers.
Unified Graceful Shutdown support for CWIST.
atomic_int g_cwist_running
Global running flag. Checked by all server event loops.
Main Application Context.
Integrated error structure used throughout the system.
cwist_reactor_t * reactor
void * async_conn
C1M connection shell when on the reactor path (internal).
void * h2_queue
HTTP/2 async queue when on H2 path (internal).
struct cwist_app * app
Owning app context (if any).
uint32_t stream_id
HTTP/2 or HTTP/3 stream ID (0 for HTTP/1.1).
void * https_conn
HTTPS connection wrapper when on TLS path (internal).
HTTP Response Object. Supports standard string body or Zero-Copy pointer body.
cwist_sstring * status_text
e.g., "OK"
cwist_http_status_t status_code
cwist_http_header_node * headers
void * async
Owning cwist_async while deferred (read-only).
bool deferred
Deferred-response handoff (internal; see net/http/async.h)
Core Application Structure and Lifecycle Management.
void cwist_app_http_handler(int client_fd, void *ctx)