11#if DETWS_ENABLE_HTTP2 && DETWS_ENABLE_TLS
24#if DETWS_H2_POOL_IN_PSRAM && defined(ARDUINO)
26#if !defined(CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY)
28 "DETWS_H2_POOL_IN_PSRAM needs a framework built with CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y. The stock arduino-esp32 core ships it OFF, so EXT_RAM_BSS_ATTR silently no-ops and the pool would overflow internal DRAM. Rebuild the core (tools/psram/README.md) or unset DETWS_H2_POOL_IN_PSRAM."
30#if defined(EXT_RAM_BSS_ATTR)
31#define DETWS_H2_POOL_ATTR EXT_RAM_BSS_ATTR
32#elif defined(EXT_RAM_ATTR)
33#define DETWS_H2_POOL_ATTR EXT_RAM_ATTR
35#define DETWS_H2_POOL_ATTR
38#define DETWS_H2_POOL_ATTR
47static DETWS_H2_POOL_ATTR H2ServerCtx s_h2;
51void set_field(
char *dst,
size_t cap,
const char *src,
size_t n)
61void cb_write(
void *io,
const uint8_t *data,
size_t len)
63 uint8_t slot = (uint8_t)(uintptr_t)io;
67 int w = det_tls_write(slot, data + off, len - off);
74void cb_header(
void *app, uint32_t,
const char *n,
size_t nl,
const char *v,
size_t vl)
77 if (nl == 7 && memcmp(n,
":method", 7) == 0)
81 else if (nl == 5 && memcmp(n,
":path", 5) == 0)
83 const char *q = (
const char *)memchr(v,
'?', vl);
84 size_t plen = q ? (size_t)(q - v) : vl;
85 set_field(r->
path,
sizeof r->
path, v, plen);
89 set_field(r->
query,
sizeof r->
query, q + 1, vl - plen - 1);
93 else if (nl == 10 && memcmp(n,
":authority", 10) == 0)
98 set_field(h->
key,
sizeof h->
key,
"host", 4);
99 set_field(h->
val,
sizeof h->
val, v, vl);
102 else if (nl >= 1 && n[0] ==
':')
111 set_field(h->
key,
sizeof h->
key, n, nl);
112 set_field(h->
val,
sizeof h->
val, v, vl);
114 if (nl == 14 && memcmp(n,
"content-length", 14) == 0)
117 for (
size_t i = 0; i < vl && v[i] >=
'0' && v[i] <=
'9'; i++)
118 cl = cl * 10 + (
size_t)(v[i] -
'0');
124void cb_headers_end(
void *app, uint32_t sid,
bool)
126 uint8_t slot = (uint8_t)(uintptr_t)app;
131void cb_data(
void *app, uint32_t,
const uint8_t *data,
size_t len,
bool)
141void h2_server_open(uint8_t slot)
144 memset(&cb, 0,
sizeof cb);
146 cb.on_header = cb_header;
147 cb.on_headers_end = cb_headers_end;
148 cb.on_data = cb_data;
149 cb.io = (
void *)(uintptr_t)slot;
150 cb.app = (
void *)(uintptr_t)slot;
151 h2_conn_init(&s_h2.pool[slot], &cb);
155void h2_server_data(uint8_t slot)
159 while ((n = det_tls_read(slot, buf,
sizeof buf)) > 0)
161 if (!h2_conn_recv(&s_h2.pool[slot], buf, (
size_t)n))
163 h2_conn_goaway(&s_h2.pool[slot], 1 );
169bool h2_server_respond(uint8_t slot,
int code,
const char *content_type,
const char *body,
size_t len)
171 bool ok = h2_conn_respond(&s_h2.pool[slot],
conn_pool[slot].h2_stream, code, content_type, body, len);
176void h2_server_close(uint8_t slot)
#define BODY_BUF_SIZE
Maximum request body bytes stored in HttpReq::body.
#define MAX_HEADERS
Maximum HTTP headers stored per request.
#define MAX_CONNS
Maximum simultaneous TCP connections (fixed static pool; ~3.95 KB of internal RAM per slot).
HTTP/2 connection + stream engine (RFC 9113) over the HPACK + frame layers.
Bridge between the HTTP/2 engine (h2_conn) and the server's request pipeline.
void http_parser_reset(HttpReq *req)
Reset a parser context to the initial (ParseState::PARSE_METHOD) state.
HttpReq http_pool[CONN_POOL_SLOTS]
Pool of parser contexts, one per connection-pool slot (incl. reserved dispatch slots).
Standalone HTTP/1.1 request parser - no transport dependency.
@ PARSE_COMPLETE
Full request parsed; ready for dispatch.
Fully-parsed HTTP/1.1 request.
Header headers[MAX_HEADERS]
Captured header fields.
char query[MAX_QUERY_LEN]
Raw query string (after ?).
char method[DETWS_METHOD_BUF_SIZE]
HTTP method, null-terminated (OPTIONS, or WebDAV methods when enabled).
uint8_t body[BODY_BUF_SIZE+1]
Stored body bytes, always null-terminated.
uint8_t header_count
Valid entries in headers[].
ParseState parse_state
Current parser state.
size_t path_idx
Write cursor into path[].
size_t content_length
Value of Content-Length header (0 if absent).
size_t body_len
Bytes stored in body[] (≤ BODY_BUF_SIZE).
char path[MAX_PATH_LEN]
URL path, null-terminated; no query string.
size_t body_bytes_read
Body bytes received (may exceed BODY_BUF_SIZE).
size_t query_idx
Write cursor into query[].
TcpConn conn_pool[CONN_POOL_SLOTS]
Static pool of connection contexts. Defined in tcp.cpp. Sized CONN_POOL_SLOTS: MAX_CONNS TCP slots pl...
Layer 4 (Transport) - TCP connection pool, ring buffers, and lwIP integration.
Deterministic TLS engine: mbedTLS over a static memory pool (DETWS_ENABLE_TLS).