11#if PC_ENABLE_HTTP2 && PC_ENABLE_TLS
24#if PC_H2_POOL_IN_PSRAM && defined(ARDUINO)
26#if !defined(CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY)
28 "PC_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 PC_H2_POOL_IN_PSRAM."
30#if defined(EXT_RAM_BSS_ATTR)
31#define PC_H2_POOL_ATTR EXT_RAM_BSS_ATTR
32#elif defined(EXT_RAM_ATTR)
33#define PC_H2_POOL_ATTR EXT_RAM_ATTR
35#define PC_H2_POOL_ATTR
38#define PC_H2_POOL_ATTR
47static PC_H2_POOL_ATTR H2ServerCtx s_h2;
51void set_field(
char *dst,
size_t cap,
const char *src,
size_t n)
63void cb_write(
void *io,
const uint8_t *data,
size_t len)
65 uint8_t slot = (uint8_t)(uintptr_t)io;
69 int w = pc_tls_write(slot, data + off, len - off);
78void cb_header(
void *app, uint32_t,
const char *n,
size_t nl,
const char *v,
size_t vl)
81 if (nl == 7 && memcmp(n,
":method", 7) == 0)
85 else if (nl == 5 && memcmp(n,
":path", 5) == 0)
87 const char *q = (
const char *)memchr(v,
'?', vl);
88 size_t plen = q ? (size_t)(q - v) : vl;
89 set_field(r->
path,
sizeof r->
path, v, plen);
93 set_field(r->
query,
sizeof r->
query, q + 1, vl - plen - 1);
97 else if (nl == 10 && memcmp(n,
":authority", 10) == 0)
102 set_field(h->
key,
sizeof h->
key,
"host", 4);
103 set_field(h->
val,
sizeof h->
val, v, vl);
106 else if (nl >= 1 && n[0] ==
':')
115 set_field(h->
key,
sizeof h->
key, n, nl);
116 set_field(h->
val,
sizeof h->
val, v, vl);
118 if (nl == 14 && memcmp(n,
"content-length", 14) == 0)
121 for (
size_t i = 0; i < vl && v[i] >=
'0' && v[i] <=
'9'; i++)
123 cl = cl * 10 + (size_t)(v[i] -
'0');
130void cb_headers_end(
void *app, uint32_t sid,
bool)
132 uint8_t slot = (uint8_t)(uintptr_t)app;
137void cb_data(
void *app, uint32_t,
const uint8_t *data,
size_t len,
bool)
149void pc_h2_server_open(uint8_t slot)
152 memset(&cb, 0,
sizeof cb);
154 cb.on_header = cb_header;
155 cb.on_headers_end = cb_headers_end;
156 cb.on_data = cb_data;
157 cb.io = (
void *)(uintptr_t)slot;
158 cb.app = (
void *)(uintptr_t)slot;
159 pc_h2_conn_init(&s_h2.pool[slot], &cb);
163void pc_h2_server_data(uint8_t slot)
167 while ((n = pc_tls_read(slot, buf,
sizeof buf)) > 0)
169 if (!pc_h2_conn_recv(&s_h2.pool[slot], buf, (
size_t)n))
171 pc_h2_conn_goaway(&s_h2.pool[slot], 1 );
177bool pc_h2_server_respond(uint8_t slot,
int code,
const char *content_type,
const char *body,
size_t len)
179 bool ok = pc_h2_conn_respond(&s_h2.pool[slot],
conn_pool[slot].pc_h2_stream, code, content_type, body, len);
184void pc_h2_server_close(uint8_t slot)
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 ?).
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.
char method[PC_METHOD_BUF_SIZE]
HTTP method, null-terminated (OPTIONS, or WebDAV methods when enabled).
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 (PC_ENABLE_TLS).