ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
edge_fetch.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_EDGE_FETCH_H
5#define PROTOCORE_EDGE_FETCH_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file edge_fetch.h
13 * @brief CDN edge-cache tier - async origin-fetch engine (PROTOCORE_ENABLE_EDGE_CACHE).
14 *
15 * A non-blocking origin fetch: open + send a request over a transport seam, accumulate the response
16 * across poll loops into a bounded buffer, detect completion (Content-Length / chunked / connection
17 * close), then parse it with the proven http_client codec. Pumped from the server poll loop so a miss
18 * or revalidation never stalls the worker; the transport seam is protocore_client on the device and a mock in
19 * host tests. Zero heap; the buffer is fixed (`PROTOCORE_EDGE_FETCH_BUF`).
20 *
21 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
22 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
23 * a caller drives every namespace the same way.
24 *
25 * @author Douglas Quigg (dstroy0)
26 * @date 2026
27 */
28
29// PROTOCORE_EDGE_FETCHER_BORROW - the bytes this module runs out of - is stated in protocore_config.h, which sums
30// it into its arena. Its size and its offset are each a static_assert, so a feature
31// combination that does not fit fails to compile rather than overrunning at run time.
32
33/** @brief The origin transport, bound to protocore_client on the device and a mock in host tests. */
34typedef struct EdgeFetchTransport
35{
36 int (*open)(void *ctx, const char *host, uint16_t port, uint32_t timeout_ms); ///< cid >= 0, or < 0 on failure
37 proto_bool (*connected)(void *ctx, int cid); ///< step the open along; true once it is up
38 proto_bool (*send)(void *ctx, int cid, const void *data, size_t len);
39 size_t (*read)(void *ctx, int cid, uint8_t *buf, size_t cap); ///< 0 = nothing available right now
40 proto_bool (*closed)(void *ctx, int cid); ///< true once the origin closed its side
41 void (*close)(void *ctx, int cid);
42 void *ctx;
44
45/** @brief Fetch progress. */
47{
48 EDGE_FETCH_STATUS_PENDING, ///< still receiving
49 EDGE_FETCH_STATUS_DONE, ///< a complete response is parsed (status / body_off / body_len valid)
50 EDGE_FETCH_STATUS_OVERSIZE, ///< response exceeded the buffer - not cacheable (caller passes through / fails open)
51 EDGE_FETCH_STATUS_FAILED, ///< connect / send / timeout / closed-before-complete
53
54/** @brief One in-flight origin fetch (fixed-size, zero-heap). */
55typedef struct
56{
58 int cid;
59 uint32_t start_ms;
60 uint32_t got; ///< bytes accumulated
61 uint32_t req_len; ///< request bytes parked at the head of buf until the connection is up
62 proto_bool sent; ///< the request reached the transport, so buf now takes the response
63 int status; ///< HTTP status (valid when DONE)
64 size_t head_len;
65 size_t body_off;
66 size_t body_len;
68} EdgeFetch;
69
70/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
71typedef struct
72{
73 void (*begin)(uint8_t *, EdgeFetch *, const EdgeFetchTransport *, const char *, uint16_t, const void *, size_t,
74 uint32_t);
75 EdgeFetchStatus (*pump)(uint8_t *, EdgeFetch *, const EdgeFetchTransport *, uint32_t);
76 void (*end)(uint8_t *, EdgeFetch *, const EdgeFetchTransport *);
77 proto_bool (*edge_resp_complete)(uint8_t *, const uint8_t *, size_t, proto_bool, size_t *);
79PROTOCORE_NS_LAYOUT(EdgeFetchNs, begin, pump, end, edge_resp_complete);
80
81/**
82 * @brief Open the origin connection and park request; begin the fetch. Sets .
83 * @param work PROTOCORE_EDGE_FETCHER_BORROW bytes the caller took. Not held past the call.
84 * @param f F
85 * @param t T
86 * @param host Host
87 * @param port Port
88 * @param request Request
89 * @param req_len Req len
90 * @param now_ms Now ms
91 */
92void protocore_edge_fetcher_begin(uint8_t *work, EdgeFetch *f, const EdgeFetchTransport *t, const char *host,
93 uint16_t port, const void *request, size_t req_len, uint32_t now_ms);
94/**
95 * @brief Drain available bytes and advance. On DONE the response is parsed .
96 * @param work PROTOCORE_EDGE_FETCHER_BORROW bytes the caller took. Not held past the call.
97 * @param f F
98 * @param t T
99 * @param now_ms Now ms
100 * @return The EdgeFetchStatus.
101 */
102EdgeFetchStatus protocore_edge_fetcher_pump(uint8_t *work, EdgeFetch *f, const EdgeFetchTransport *t, uint32_t now_ms);
103/**
104 * @brief Release the transport connection (idempotent).
105 * @param work PROTOCORE_EDGE_FETCHER_BORROW bytes the caller took. Not held past the call.
106 * @param f F
107 * @param t T
108 */
110/**
111 * @brief Is the accumulated response complete? (headers terminated + body .
112 * @param work PROTOCORE_EDGE_FETCHER_BORROW bytes the caller took. Not held past the call.
113 * @param buf Buf
114 * @param len Len
115 * @param conn_closed Conn closed
116 * @param head_len Head len
117 * @return PROTO_TRUE on success.
118 */
119proto_bool protocore_edge_fetcher_edge_resp_complete(uint8_t *work, const uint8_t *buf, size_t len,
120 proto_bool conn_closed, size_t *head_len);
121
122/** @brief Module namespace. */
128
130
131#endif // PROTOCORE_EDGE_FETCH_H
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
#define PROTOCORE_EDGE_FETCH_BUF
PROTOCORE_NS EdgeFetchNs EdgeFetcher PROTOCORE_UNUSED
Module namespace.
Definition edge_fetch.h:123
void protocore_edge_fetcher_end(uint8_t *work, EdgeFetch *f, const EdgeFetchTransport *t)
Release the transport connection (idempotent).
proto_bool protocore_edge_fetcher_edge_resp_complete(uint8_t *work, const uint8_t *buf, size_t len, proto_bool conn_closed, size_t *head_len)
Is the accumulated response complete? (headers terminated + body .
void protocore_edge_fetcher_begin(uint8_t *work, EdgeFetch *f, const EdgeFetchTransport *t, const char *host, uint16_t port, const void *request, size_t req_len, uint32_t now_ms)
Open the origin connection and park request; begin the fetch. Sets .
EdgeFetchStatus protocore_edge_fetcher_pump(uint8_t *work, EdgeFetch *f, const EdgeFetchTransport *t, uint32_t now_ms)
Drain available bytes and advance. On DONE the response is parsed .
enum PROTO_ENUM_PACKED EdgeFetchStatus
Fetch progress.
@ EDGE_FETCH_STATUS_DONE
a complete response is parsed (status / body_off / body_len valid)
Definition edge_fetch.h:49
@ EDGE_FETCH_STATUS_PENDING
still receiving
Definition edge_fetch.h:48
@ EDGE_FETCH_STATUS_FAILED
connect / send / timeout / closed-before-complete
Definition edge_fetch.h:51
@ EDGE_FETCH_STATUS_OVERSIZE
response exceeded the buffer - not cacheable (caller passes through / fails open)
Definition edge_fetch.h:50
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition edge_fetch.h:72
void(* begin)(uint8_t *, EdgeFetch *, const EdgeFetchTransport *, const char *, uint16_t, const void *, size_t, uint32_t)
Definition edge_fetch.h:73
The origin transport, bound to protocore_client on the device and a mock in host tests.
Definition edge_fetch.h:35
proto_bool(* connected)(void *ctx, int cid)
step the open along; true once it is up
Definition edge_fetch.h:37
proto_bool(* send)(void *ctx, int cid, const void *data, size_t len)
Definition edge_fetch.h:38
proto_bool(* closed)(void *ctx, int cid)
true once the origin closed its side
Definition edge_fetch.h:40
size_t(* read)(void *ctx, int cid, uint8_t *buf, size_t cap)
0 = nothing available right now
Definition edge_fetch.h:39
int(* open)(void *ctx, const char *host, uint16_t port, uint32_t timeout_ms)
cid >= 0, or < 0 on failure
Definition edge_fetch.h:36
void(* close)(void *ctx, int cid)
Definition edge_fetch.h:41
One in-flight origin fetch (fixed-size, zero-heap).
Definition edge_fetch.h:56
proto_bool sent
the request reached the transport, so buf now takes the response
Definition edge_fetch.h:62
size_t head_len
Definition edge_fetch.h:64
uint32_t got
bytes accumulated
Definition edge_fetch.h:60
size_t body_off
Definition edge_fetch.h:65
size_t body_len
Definition edge_fetch.h:66
uint32_t req_len
request bytes parked at the head of buf until the connection is up
Definition edge_fetch.h:61
uint32_t start_ms
Definition edge_fetch.h:59
EdgeFetchStatus st
Definition edge_fetch.h:57
int status
HTTP status (valid when DONE)
Definition edge_fetch.h:63
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97