cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
https.c File Reference

OpenSSL-backed HTTPS accept, receive, send, and server-loop helpers. More...

#include <cwist/net/http/https.h>
#include <cwist/net/http/writer_fast.h>
#include <cwist/core/sstring/sstring.h>
#include <cwist/sys/err/cwist_err.h>
#include <cwist/core/mem/alloc.h>
#include <cwist/core/mem/gc.h>
#include <cwist/sys/app/shutdown.h>
#include "tls_chain.h"
#include "async_internal.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <stdint.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <time.h>
Include dependency graph for https.c:

Go to the source code of this file.

Macros

#define _POSIX_C_SOURCE   200809L
 
#define CWIST_TLS_COALESCE_MAX   (16 * 1024)
 
#define HTTPS_TASK_QUEUE_INITIAL   1024
 
#define HTTPS_TASK_QUEUE_MAX   2097152
 
#define CWIST_ALPN_HTTP11   ((const unsigned char *)"\x08http/1.1")
 
#define CWIST_ALPN_H2_HTTP11   ((const unsigned char *)"\x02h2\x08http/1.1")
 
#define CWIST_ALPN_H3_H2_HTTP11   ((const unsigned char *)"\x02h3\x02h2\x08http/1.1")
 
#define CWIST_ALPN_HTTP11_LEN   9
 
#define CWIST_ALPN_H2_HTTP11_LEN   12
 
#define CWIST_ALPN_H3_H2_HTTP11_LEN   15
 

Typedefs

typedef struct cwist_tls_ticket_key cwist_tls_ticket_key
 

Functions

bool cwist_tls_apply_pqc_layer (cwist_app *app, SSL_CTX *ctx)
 Apply PQC hybrid key exchange settings to an SSL context.
 
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; on pool shutdown closes and frees the socket instead of queueing.
 
int https_hs_shepherd_start (void)
 
void https_hs_shepherd_stop (void)
 
int https_pool_init (void)
 Create the worker threads, mutex, and condition variables of the global HTTPS thread pool. No-op if already initialized.
 
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.
 
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). Blocks while the queue is full; on pool shutdown closes the connection instead of queueing.
 
void https_pool_destroy (void)
 Shut down the global HTTPS thread pool: signal workers to exit, join them, close any connections still queued, and destroy the pool's mutex and condition variables. No-op if never initialized.
 
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.
 
bool cwist_https_conn_idle (cwist_https_connection *conn)
 True when conn has no buffered TLS bytes and nothing readable.
 
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 overrides the default (CWIST_HTTP_TIMEOUT_MS, the same 30 s the blocking header read waited).
 
long cwist_https_pending_handshakes (void)
 Number of TLS handshakes currently parked in the shepherd.
 
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 when the ClientHello is already pending, otherwise parks the connection with the handshake shepherd thread and returns immediately. Established sessions are submitted to the HTTPS worker pool. Safe to call from reactor callbacks.
 
cwist_error_t cwist_https_init_context (cwist_https_context **ctx, const char *cert_path, const char *key_path)
 
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)
 
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.
 
void cwist_https_destroy_context (cwist_https_context *ctx)
 Free an HTTPS context and release its OpenSSL resources.
 
long cwist_https_tls_handshakes_total (void)
 Total TLS handshakes that completed (full + resumed).
 
long cwist_https_tls_handshakes_resumed_total (void)
 TLS handshakes completed via session resumption/ticket.
 
long cwist_https_tls_handshakes_tls12_total (void)
 Handshakes that negotiated TLS 1.2.
 
long cwist_https_tls_handshakes_tls13_total (void)
 Handshakes that negotiated TLS 1.3.
 
long cwist_https_tls_ciphers_aes128_gcm_total (void)
 Handshakes negotiated with TLS_AES_128_GCM_SHA256.
 
long cwist_https_tls_ciphers_aes256_gcm_total (void)
 Handshakes negotiated with TLS_AES_256_GCM_SHA384.
 
long cwist_https_tls_ciphers_chacha20_total (void)
 Handshakes negotiated with TLS_CHACHA20_POLY1305_SHA256.
 
long cwist_https_tls_ciphers_other_total (void)
 Handshakes negotiated with any other cipher.
 
long cwist_https_tls_connections_active (void)
 Currently established TLS connections (wrap minus teardown).
 
cwist_error_t cwist_https_accept (cwist_https_context *ctx, int client_fd, cwist_https_connection **conn)
 
bool cwist_https_connection_uses_http2 (const cwist_https_connection *conn)
 Gracefully close an HTTPS connection and free its buffers.
 
cwist_https_protocol cwist_https_connection_protocol (const cwist_https_connection *conn)
 
void cwist_https_close_connection (cwist_https_connection *conn)
 
cwist_http_request * cwist_https_receive_request (cwist_https_connection *conn)
 Read from the TLS stream until a full HTTP request has been assembled.
 
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_send_response_head (cwist_https_connection *conn, cwist_http_response *res)
 
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.
 

Detailed Description

OpenSSL-backed HTTPS accept, receive, send, and server-loop helpers.

Definition in file https.c.

Macro Definition Documentation

◆ _POSIX_C_SOURCE

#define _POSIX_C_SOURCE   200809L

Definition at line 1 of file https.c.

◆ CWIST_ALPN_H2_HTTP11

#define CWIST_ALPN_H2_HTTP11   ((const unsigned char *)"\x02h2\x08http/1.1")

Definition at line 1153 of file https.c.

◆ CWIST_ALPN_H2_HTTP11_LEN

#define CWIST_ALPN_H2_HTTP11_LEN   12

Definition at line 1156 of file https.c.

◆ CWIST_ALPN_H3_H2_HTTP11

#define CWIST_ALPN_H3_H2_HTTP11   ((const unsigned char *)"\x02h3\x02h2\x08http/1.1")

Definition at line 1154 of file https.c.

◆ CWIST_ALPN_H3_H2_HTTP11_LEN

#define CWIST_ALPN_H3_H2_HTTP11_LEN   15

Definition at line 1157 of file https.c.

◆ CWIST_ALPN_HTTP11

#define CWIST_ALPN_HTTP11   ((const unsigned char *)"\x08http/1.1")

Definition at line 1152 of file https.c.

◆ CWIST_ALPN_HTTP11_LEN

#define CWIST_ALPN_HTTP11_LEN   9

Definition at line 1155 of file https.c.

◆ CWIST_TLS_COALESCE_MAX

#define CWIST_TLS_COALESCE_MAX   (16 * 1024)

Definition at line 42 of file https.c.

◆ HTTPS_TASK_QUEUE_INITIAL

#define HTTPS_TASK_QUEUE_INITIAL   1024

Definition at line 90 of file https.c.

◆ HTTPS_TASK_QUEUE_MAX

#define HTTPS_TASK_QUEUE_MAX   2097152

Definition at line 91 of file https.c.

Typedef Documentation

◆ cwist_tls_ticket_key

typedef struct cwist_tls_ticket_key cwist_tls_ticket_key

Function Documentation

◆ cwist_https_accept()

cwist_error_t cwist_https_accept ( cwist_https_context *  ctx,
int  client_fd,
cwist_https_connection **  conn 
)

Perform SSL handshake on an accepted socket. Returns a new cwist_https_connection wrapper.

Definition at line 1756 of file https.c.

References cap, CWIST_ERR_INT16, CWIST_HTTP_TIMEOUT_MS, CWIST_HTTPS_HANDSHAKE_TIMEOUT_MS, make_error(), SSL_accept, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, SSL_free, SSL_get_error, and SSL_set_fd.

◆ cwist_https_close_connection()

void cwist_https_close_connection ( cwist_https_connection *  conn)

Close and free the HTTPS connection.

Definition at line 1875 of file https.c.

References cwist_conn_registry_untrack(), and cwist_full_gc_enabled().

Referenced by https_pool_destroy(), and https_pool_submit_conn().

◆ cwist_https_conn_idle()

bool cwist_https_conn_idle ( cwist_https_connection *  conn)

True when conn has no buffered TLS bytes and nothing readable.

Definition at line 683 of file https.c.

References cwist_https_connection::buf_len, cap, cwist_https_connection::fd, cwist_https_connection::ssl, and SSL_pending.

Referenced by cwist_http2_serve_connection_ex().

◆ cwist_https_connection_protocol()

cwist_https_protocol cwist_https_connection_protocol ( const cwist_https_connection *  conn)

Returns the protocol selected by ALPN, or HTTP/1.1 when no higher protocol matched.

Definition at line 1821 of file https.c.

References CWIST_HTTPS_PROTOCOL_NONE, and cwist_https_connection::negotiated_protocol.

◆ cwist_https_connection_uses_http2()

bool cwist_https_connection_uses_http2 ( const cwist_https_connection *  conn)

Gracefully close an HTTPS connection and free its buffers.

Parameters
connHTTPS connection wrapper to close.

Definition at line 1817 of file https.c.

References CWIST_HTTPS_PROTOCOL_HTTP2, and cwist_https_connection::negotiated_protocol.

◆ cwist_https_destroy_context()

void cwist_https_destroy_context ( cwist_https_context *  ctx)

Free an HTTPS context and release its OpenSSL resources.

Parameters
ctxContext to destroy.

Definition at line 1558 of file https.c.

References cap, cwist_https_context::ctx, cwist_https_context::ctx_lock, cwist_free(), OPENSSL_cleanse, SSL_CTX_free, and cwist_https_context::ticket_key.

Referenced by cwist_app_destroy().

◆ cwist_https_dispatch()

void cwist_https_dispatch ( int  client_fd,
cwist_https_context *  ctx,
void(*)(cwist_https_connection *, void *)  handler,
void *  user_ctx 
)

Accept a TLS connection without parking a worker on the handshake. Completes the handshake inline when the ClientHello is already pending, otherwise parks the connection with the handshake shepherd thread and returns immediately. Established sessions are submitted to the HTTPS worker pool. Safe to call from reactor callbacks.

Definition at line 1141 of file https.c.

References cap, and https_pool_submit().

Referenced by cwist_https_server_loop().

◆ cwist_https_idle_timeout_ms()

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 overrides the default (CWIST_HTTP_TIMEOUT_MS, the same 30 s the blocking header read waited).

Definition at line 710 of file https.c.

References cap, and CWIST_HTTP_TIMEOUT_MS.

◆ cwist_https_init_context()

cwist_error_t cwist_https_init_context ( cwist_https_context **  ctx,
const char *  cert_path,
const char *  key_path 
)

Initialize the OpenSSL library and create an SSL context. Loads certificate and private key.

Definition at line 1369 of file https.c.

References cap, and cwist_https_init_context_with_options().

◆ cwist_https_init_context_with_options()

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 
)

Initialize an HTTPS context with explicit transport options. The HTTP/2 option only applies the standard TLS/ALPN profile today. Application request handling remains HTTP/1.1 unless a frame engine is added.

Definition at line 1451 of file https.c.

References cap, cwist_alloc(), CWIST_ERR_INT16, cwist_https_options::enable_http2, cwist_https_options::enable_http3, make_error(), SSL_CTX_free, and SSL_CTX_set_alpn_select_cb.

Referenced by cwist_https_init_context().

◆ cwist_https_park()

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.

— API Functions —

A pool thread that has nothing to read on conn calls this instead of blocking in poll(): the connection is watched by one epoll thread and resubmitted to the pool when bytes arrive, so an idle keep-alive connection costs memory but no thread. Returns true when the connection was parked; the caller must then return without touching conn again (another pool thread may already be serving it). Returns false when parking is unavailable (full GC, CWIST_HTTPS_PARK=0, shutdown); the caller keeps serving the connection the blocking way.

Parameters
idle_msIdle budget before the class-specific expiry action.

Definition at line 672 of file https.c.

References cap.

Referenced by cwist_http2_serve_connection_ex().

◆ cwist_https_pending_handshakes()

long cwist_https_pending_handshakes ( void  )

Number of TLS handshakes currently parked in the shepherd.

Definition at line 1136 of file https.c.

◆ cwist_https_receive_request()

◆ cwist_https_reload_context()

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.

Hot-reload the certificate chain and key of a live HTTPS context.

Parameters
ctxLive HTTPS context whose SSL_CTX is replaced.
cert_pathPath to the new PEM certificate chain.
key_pathPath to the new PEM private key.
appApplication context for the PQC layer (may be NULL).
Returns
Tagged CWIST error describing success or failure. On failure the previous certificate keeps serving.

The new SSL_CTX is fully built and validated before the swap. Connections established (or handshaking) on the old SSL_CTX keep it alive through BoringSSL's reference counting and finish on the old certificate; new handshakes use the new one. The shared session-ticket key is carried over unchanged, so tickets issued before the reload still resume afterwards (see docs/decisions/0002-tls-hot-reload.md).

Definition at line 1508 of file https.c.

References cap, cwist_https_context::ctx, cwist_https_context::ctx_lock, CWIST_ERR_INT16, cwist_https_options::enable_http2, cwist_https_context::http2_enabled, cwist_https_context::http3_enabled, make_error(), SSL_CTX_free, SSL_CTX_set_alpn_select_cb, SSL_CTX_set_ex_data, SSL_CTX_set_tlsext_ticket_key_cb, and cwist_https_context::ticket_key.

Referenced by cwist_app_reload_tls().

◆ cwist_https_send_response()

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.

Zero-copy counterpart of the plaintext send path: the header block is serialized into a stack buffer and written first, then the body is streamed straight from its origin (pointer body, sstring, or file stream) instead of materializing one contiguous heap blob.

Parameters
connActive HTTPS connection wrapper.
resResponse object to serialize.
Returns
Tagged CWIST error describing success or failure.

Definition at line 2102 of file https.c.

References cwist_http_response::body, cap, cwist_alloc(), CWIST_ERR_INT16, cwist_free(), cwist_http_header_add(), cwist_http_header_get(), CWIST_HTTP_MAX_HEADER_SIZE, cwist_http_serialize_headers(), CWIST_TLS_COALESCE_MAX, cwist_sstring::data, cwist_https_connection::fd, cwist_http_response::file_stream_fd, cwist_http_response::file_stream_len, cwist_http_response::file_stream_offset, cwist_http_response::headers, cwist_https_connection::http3_enabled, cwist_http_response::is_ptr_body, make_error(), cwist_http_response::ptr_body, cwist_http_response::ptr_body_len, cwist_sstring::size, cwist_https_connection::ssl, and cwist_http_response::use_file_stream.

◆ cwist_https_send_response_head()

◆ cwist_https_server_loop()

cwist_error_t cwist_https_server_loop ( int  server_fd,
cwist_https_context *  ctx,
void(*)(cwist_https_connection *, void *)  handler,
void *  user_ctx 
)

Accept HTTPS clients in a loop and dispatch each one to the supplied handler.

Parameters
server_fdBound listening socket descriptor.
ctxHTTPS context shared by all accepted connections.
handlerCallback invoked for each successful TLS client wrapper.
user_ctxOpaque pointer forwarded to the handler.
Returns
Tagged CWIST error describing success or failure.

Definition at line 2295 of file https.c.

References cap, CWIST_ERR_INT16, cwist_https_dispatch(), g_cwist_running, https_pool_destroy(), https_pool_init(), and make_error().

◆ cwist_https_tls_ciphers_aes128_gcm_total()

long cwist_https_tls_ciphers_aes128_gcm_total ( void  )

Handshakes negotiated with TLS_AES_128_GCM_SHA256.

Definition at line 1613 of file https.c.

References cap.

◆ cwist_https_tls_ciphers_aes256_gcm_total()

long cwist_https_tls_ciphers_aes256_gcm_total ( void  )

Handshakes negotiated with TLS_AES_256_GCM_SHA384.

Definition at line 1617 of file https.c.

References cap.

◆ cwist_https_tls_ciphers_chacha20_total()

long cwist_https_tls_ciphers_chacha20_total ( void  )

Handshakes negotiated with TLS_CHACHA20_POLY1305_SHA256.

Definition at line 1621 of file https.c.

References cap.

◆ cwist_https_tls_ciphers_other_total()

long cwist_https_tls_ciphers_other_total ( void  )

Handshakes negotiated with any other cipher.

Definition at line 1625 of file https.c.

References cap.

◆ cwist_https_tls_connections_active()

long cwist_https_tls_connections_active ( void  )

Currently established TLS connections (wrap minus teardown).

Definition at line 1629 of file https.c.

References cap.

◆ cwist_https_tls_handshakes_resumed_total()

long cwist_https_tls_handshakes_resumed_total ( void  )

TLS handshakes completed via session resumption/ticket.

Definition at line 1601 of file https.c.

References cap.

◆ cwist_https_tls_handshakes_tls12_total()

long cwist_https_tls_handshakes_tls12_total ( void  )

Handshakes that negotiated TLS 1.2.

Definition at line 1605 of file https.c.

References cap.

◆ cwist_https_tls_handshakes_tls13_total()

long cwist_https_tls_handshakes_tls13_total ( void  )

Handshakes that negotiated TLS 1.3.

Definition at line 1609 of file https.c.

References cap.

◆ cwist_https_tls_handshakes_total()

long cwist_https_tls_handshakes_total ( void  )

Total TLS handshakes that completed (full + resumed).

Definition at line 1597 of file https.c.

References cap.

◆ cwist_tls_apply_pqc_layer()

bool cwist_tls_apply_pqc_layer ( cwist_app *  app,
SSL_CTX *  ctx 
)

Apply PQC hybrid key exchange settings to an SSL context.

Parameters
appApplication context containing PQC configuration.
ctxOpenSSL/BoringSSL SSL_CTX to mutate.
Returns
true when PQC was applied or not needed; false on failure.

Definition at line 19 of file pqc_layer.c.

References cap, CWIST_LOG_ERROR, CWIST_LOG_INFO, CWIST_LOG_WARN, cwist_app::pqc_layer_enabled, SSL_CTX_set1_groups_list, SSL_CTX_set_min_proto_version, SSL_CTX_set_options, SSL_OP_NO_TLSv1, SSL_OP_NO_TLSv1_1, SSL_OP_NO_TLSv1_2, TLS1_3_VERSION, and cwist_app::tls_groups.

◆ https_hs_shepherd_start()

int https_hs_shepherd_start ( void  )

Definition at line 1131 of file https.c.

◆ https_hs_shepherd_stop()

void https_hs_shepherd_stop ( void  )

Definition at line 1134 of file https.c.

Referenced by https_pool_destroy().

◆ https_pool_destroy()

void https_pool_destroy ( void  )

Shut down the global HTTPS thread pool: signal workers to exit, join them, close any connections still queued, and destroy the pool's mutex and condition variables. No-op if never initialized.

Definition at line 370 of file https.c.

References cap, cwist_free(), cwist_https_close_connection(), get_optimal_thread_count(), https_hs_shepherd_stop(), and SSL_free.

Referenced by cwist_async_server_loop(), and cwist_https_server_loop().

◆ https_pool_init()

int https_pool_init ( void  )

Create the worker threads, mutex, and condition variables of the global HTTPS thread pool. No-op if already initialized.

Returns
0 on success (or if already initialized), -1 if a worker thread could not be created.

Definition at line 268 of file https.c.

References cap, and get_optimal_thread_count().

Referenced by cwist_async_server_loop(), and cwist_https_server_loop().

◆ https_pool_submit()

void https_pool_submit ( int  client_fd,
cwist_https_context *  ctx,
void(*)(cwist_https_connection *, void *)  handler,
void *  user_ctx 
)

Queue a freshly accepted client socket whose TLS handshake still needs to run in a pool worker.

Parameters
client_fdAccepted TCP socket descriptor.
ctxHTTPS context for the handshake.
handlerCallback invoked once the connection is established.
user_ctxOpaque pointer forwarded to the handler.

Definition at line 292 of file https.c.

References cap, and https_pool_submit_ready().

Referenced by cwist_https_dispatch().

◆ https_pool_submit_conn()

void https_pool_submit_conn ( cwist_https_connection *  conn,
cwist_https_context *  ctx,
void(*)(cwist_https_connection *, void *)  handler,
void *  user_ctx 
)

Submit an established connection back to the worker pool (e.g. keep-alive re-arm after async defer). Blocks while the queue is full; on pool shutdown closes the connection instead of queueing.

Parameters
connEstablished connection wrapper (ownership transfers to the pool).
ctxHTTPS context.
handlerCallback invoked for the connection.
user_ctxOpaque pointer forwarded to the handler.

Definition at line 341 of file https.c.

References cap, cwist_https_close_connection(), and cwist_https_connection::fd.

◆ https_pool_submit_ready()

void https_pool_submit_ready ( int  client_fd,
SSL *  pres_ssl,
cwist_https_context *  ctx,
void(*)(cwist_https_connection *, void *)  handler,
void *  user_ctx 
)

Submit a connection whose TLS handshake already completed (pres_ssl). Blocks while the queue is full; on pool shutdown closes and frees the socket instead of queueing.

Parameters
client_fdAccepted TCP socket descriptor.
pres_sslEstablished SSL session, or NULL if the worker must run the handshake itself.
ctxHTTPS context.
handlerCallback invoked for the connection.
user_ctxOpaque pointer forwarded to the handler.

Definition at line 308 of file https.c.

References cap, and SSL_free.

Referenced by https_pool_submit().