DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
edge_fetch.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file edge_fetch.h
6 * @brief CDN edge-cache tier - async origin-fetch engine (DETWS_ENABLE_EDGE_CACHE).
7 *
8 * A non-blocking origin fetch: open + send a request over a transport seam, accumulate the response
9 * across poll loops into a bounded buffer, detect completion (Content-Length / chunked / connection
10 * close), then parse it with the proven http_client codec. Pumped from the server poll loop so a miss
11 * or revalidation never stalls the worker; the transport seam is det_client on the device and a mock in
12 * host tests. Zero heap; the buffer is fixed (`DETWS_EDGE_FETCH_BUF`).
13 *
14 * @author Douglas Quigg (dstroy0)
15 * @date 2026
16 */
17
18#ifndef DETERMINISTICESPASYNCWEBSERVER_EDGE_FETCH_H
19#define DETERMINISTICESPASYNCWEBSERVER_EDGE_FETCH_H
20
21#include "ServerConfig.h"
22
23#if DETWS_ENABLE_EDGE_CACHE
24
25#include <stddef.h>
26#include <stdint.h>
27
28/** @brief The origin transport, bound to det_client on the device and a mock in host tests. */
29struct EdgeFetchTransport
30{
31 int (*open)(void *ctx, const char *host, uint16_t port, uint32_t timeout_ms); ///< cid >= 0, or < 0 on failure
32 bool (*send)(void *ctx, int cid, const void *data, size_t len);
33 size_t (*read)(void *ctx, int cid, uint8_t *buf, size_t cap); ///< 0 = nothing available right now
34 bool (*closed)(void *ctx, int cid); ///< true once the origin closed its side
35 void (*close)(void *ctx, int cid);
36 void *ctx;
37};
38
39/** @brief Fetch progress. */
40enum class EdgeFetchStatus : uint8_t
41{
42 PENDING, ///< still receiving
43 DONE, ///< a complete response is parsed (status / body_off / body_len valid)
44 OVERSIZE, ///< response exceeded the buffer - not cacheable (caller passes through / fails open)
45 FAILED, ///< connect / send / timeout / closed-before-complete
46};
47
48/** @brief One in-flight origin fetch (fixed-size, zero-heap). */
49struct EdgeFetch
50{
51 EdgeFetchStatus st;
52 int cid;
53 uint32_t start_ms;
54 uint32_t got; ///< bytes accumulated
55 int status; ///< HTTP status (valid when DONE)
56 size_t head_len;
57 size_t body_off, body_len;
58 uint8_t buf[DETWS_EDGE_FETCH_BUF];
59};
60
61/** @brief Open + send @p request; begin receiving. Sets @p st to PENDING, or FAILED on open/send error. */
62void edge_fetch_begin(EdgeFetch *f, const EdgeFetchTransport *t, const char *host, uint16_t port, const void *request,
63 size_t req_len, uint32_t now_ms);
64
65/**
66 * @brief Drain available bytes and advance. On DONE the response is parsed (chunked bodies decoded in
67 * place); honors `DETWS_EDGE_FETCH_TIMEOUT_MS`. @return the current status.
68 */
69EdgeFetchStatus edge_fetch_pump(EdgeFetch *f, const EdgeFetchTransport *t, uint32_t now_ms);
70
71/** @brief Release the transport connection (idempotent). */
72void edge_fetch_end(EdgeFetch *f, const EdgeFetchTransport *t);
73
74/**
75 * @brief Is the accumulated response complete? (headers terminated + body per Content-Length / chunked
76 * terminator / connection close). Sets @p head_len to the header-block length (0 if not yet whole).
77 * Pure - host-testable without a transport.
78 */
79bool edge_resp_complete(const uint8_t *buf, size_t len, bool conn_closed, size_t *head_len);
80
81#endif // DETWS_ENABLE_EDGE_CACHE
82
83#endif // DETERMINISTICESPASYNCWEBSERVER_EDGE_FETCH_H
User-facing configuration for DeterministicESPAsyncWebServer.
#define DETWS_EDGE_FETCH_BUF