ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
edge_cache.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/**
5 * @file edge_cache.h
6 * @brief CDN edge-cache tier - pure engine (PROTOCORE_ENABLE_EDGE_CACHE).
7 *
8 * The caching reverse-proxy edge that network_drivers/presentation/http/httpcache is the origin-side groundwork for.
9 * This header is the pure, host-testable core: the response header-field access and HTTP-date math that httpcache
10 * lacks, RFC 9111 freshness (lifetime + age), and the deterministic cache key + SHA-256 digest + `Vary` secondary key.
11 * No sockets, no PC, no heap - the socket glue (edge_cache_proxy) and the L2 SD tier (edge_cache_sd) layer on top.
12 *
13 * @author Douglas Quigg (dstroy0)
14 * @date 2026
15 */
16
17#ifndef PROTOCORE_EDGE_CACHE_H
18#define PROTOCORE_EDGE_CACHE_H
19
20#include "protocore_config.h" // the entry point: protocore_types.h for the widths
21
22#if PROTOCORE_ENABLE_EDGE_CACHE
23
25
26// This module holds nothing between calls, so it carves no borrow and states none. An entry
27// takes one all the same, and never reads it, so every namespace in the tree is invoked the
28// same way.
29
30#define PROTOCORE_EDGE_LRU_NONE 0xFFFFu
31
32/** @brief Request-header lookup used to build the Vary secondary key; return nullptr when absent. */
33typedef const char *(*EdgeHdrLookup)(void *ctx, const char *name);
34
35typedef struct EdgeEntry
36{
37 proto_bool used;
38 char key[PROTOCORE_EDGE_KEY_MAX]; ///< canonical key (collision-safe exact compare)
39 uint8_t digest[32]; ///< sha256.hash(key) - the L2 dbm key
40 char vary_names[PROTOCORE_EDGE_VARY_MAX]; ///< the response Vary header value (field-name list), "" if none
41 char vary_vals[PROTOCORE_EDGE_VARY_MAX]; ///< serialized request Vary values at store time (secondary key)
42 int status; ///< stored response status (200)
43 char content_type[PROTOCORE_EDGE_CTYPE_MAX]; ///< Content-Type to replay
44 char etag[PROTOCORE_EDGE_ETAG_MAX]; ///< validator (quotes included), "" if none
45 char last_modified[PROTOCORE_EDGE_LASTMOD_MAX]; ///< Last-Modified (RFC 1123), "" if none
46 char content_encoding[PROTOCORE_EDGE_CENC_MAX]; ///< Content-Encoding to replay (e.g. gzip), "" if none
47 int64_t date_epoch; ///< origin Date (-1 absent)
48 int64_t expires_epoch; ///< origin Expires (-1 absent)
49 int32_t age_hdr; ///< origin Age at store (>=0)
50 long lifetime_s; ///< resolved freshness lifetime (always >=0)
51 long initial_age; ///< corrected initial age at store
52 uint32_t insert_ms; ///< monotonic store time (TTL/age base)
53 uint32_t last_used_ms; ///< recency
54 struct ///< intrusive LRU node (PROTOCORE_EDGE_LRU_NONE = end)
55 {
56 uint16_t prev;
57 uint16_t next;
58 } lru;
59 uint16_t body_len;
60 uint8_t body[PROTOCORE_EDGE_BODY_MAX];
61} EdgeEntry;
62
63/** @brief Cache observability counters. */
64typedef struct EdgeCacheStats
65{
66 uint32_t hits;
67 uint32_t misses;
68 uint32_t revalidations_304;
69 uint32_t replaces_200;
70 uint32_t stores;
71 uint32_t evictions;
72 uint32_t purges;
73 uint32_t l2_spills;
74 uint32_t l2_promotes;
75 uint32_t mesh_hits; ///< sibling pulls served (PROTOCORE_ENABLE_EDGE_MESH)
76 uint32_t mesh_misses; ///< peer queries that missed
77 uint64_t bytes_stored;
78} EdgeCacheStats;
79
80/**
81 * @brief Write-back hook fired with the LRU victim just before ::edge_store_alloc recycles its slot.
82 *
83 * Lets the L2 SD tier (edge_cache_sd) spill an evicted entry to persistent storage without the pure
84 * engine ever depending on dbm: the glue installs the callback, the engine only calls it. @p victim is
85 * still fully populated (not yet unlinked). Transient passthrough entries (empty key) are not offered.
86 */
87typedef void (*EdgeEvictFn)(void *ctx, const EdgeEntry *victim);
88
89/** @brief The L1 store: a fixed pool of entries with an intrusive MRU..LRU list. */
90typedef struct
91{
92 EdgeEntry entries[PROTOCORE_EDGE_CACHE_SLOTS];
93 uint16_t lru_head; ///< MRU end (PROTOCORE_EDGE_LRU_NONE when empty)
94 uint16_t lru_tail; ///< LRU end (PROTOCORE_EDGE_LRU_NONE when empty)
95 EdgeCacheStats stats;
96 EdgeEvictFn on_evict; ///< nullptr = no L2 write-back; else called with each evicted victim
97 void *evict_ctx; ///< opaque context passed to on_evict
98 // The bytes the key digest works out of. Live with the store, so hashing a key costs no borrow.
99 uint8_t digest_work[PROTOCORE_SHA256_BORROW];
100} EdgeCacheStore;
101
102/** @brief protocore_cache_control, as the caller already knows it. */
103struct protocore_cache_control;
104
105/** @brief What header_value takes: hdrs, len, name, out, out_cap. */
106typedef struct
107{
108 const char *hdrs;
109 size_t len;
110 const char *name;
111 char *out;
112 size_t out_cap;
113} EdgeCacheHeaderValueArgs;
114
115/** @brief What parse_http_date takes: s, len. */
116typedef struct
117{
118 const char *s;
119 size_t len;
120} EdgeCacheParseHttpDateArgs;
121
122/** @brief What freshness_lifetime takes: cc, shared, date_epoch, ... */
123typedef struct
124{
125 const struct protocore_cache_control *cc;
126 proto_bool shared;
127 int64_t date_epoch;
128 int64_t expires_epoch;
129} EdgeCacheFreshnessLifetimeArgs;
130
131/** @brief What heuristic_lifetime takes: date_epoch, ... */
132typedef struct
133{
134 int64_t date_epoch;
135 int64_t last_modified_epoch;
136} EdgeCacheHeuristicLifetimeArgs;
137
138/** @brief What initial_age takes: age_hdr, date_epoch, ... */
139typedef struct
140{
141 int32_t age_hdr;
142 int64_t date_epoch;
143 int64_t response_time_epoch;
144} EdgeCacheInitialAgeArgs;
145
146/** @brief What current_age takes: initial_age, insert_ms, now_ms. */
147typedef struct
148{
149 long initial_age;
150 uint32_t insert_ms;
151 uint32_t now_ms;
152} EdgeCacheCurrentAgeArgs;
153
154/** @brief What is_fresh_at takes: lifetime, current_age. */
155typedef struct
156{
157 long lifetime;
158 long current_age;
159} EdgeCacheIsFreshAtArgs;
160
161/** @brief What key_canon takes: method, host, path, query, ... */
162typedef struct
163{
164 const char *method;
165 const char *host;
166 const char *path;
167 const char *query;
168 proto_bool include_query;
169 char *out;
170 size_t out_cap;
171} EdgeCacheKeyCanonArgs;
172
173/** @brief What key_digest takes: digest_work, canon, len, digest. */
174typedef struct
175{
176 uint8_t *digest_work;
177 const char *canon;
178 size_t len;
179 uint8_t *digest; ///< 32 bytes.
180} EdgeCacheKeyDigestArgs;
181
182/** @brief What vary_serialize takes: vary_header, lookup, ctx, out, ... */
183typedef struct
184{
185 const char *vary_header;
186 EdgeHdrLookup lookup;
187 void *ctx;
188 char *out;
189 size_t out_cap;
190} EdgeCacheVarySerializeArgs;
191
192/** @brief What store_init takes: s. */
193typedef struct
194{
195 EdgeCacheStore *s;
196} EdgeCacheStoreInitArgs;
197
198/** @brief What store_alloc takes: s, canon, vary_key. */
199typedef struct
200{
201 EdgeCacheStore *s;
202 const char *canon;
203 const char *vary_key;
204} EdgeCacheStoreAllocArgs;
205
206/** @brief What store_lookup takes: s, canon, vary_key, now_ms. */
207typedef struct
208{
209 EdgeCacheStore *s;
210 const char *canon;
211 const char *vary_key;
212 uint32_t now_ms;
213} EdgeCacheStoreLookupArgs;
214
215/** @brief What store_find takes: s, canon, lookup, ctx, now_ms. */
216typedef struct
217{
218 EdgeCacheStore *s;
219 const char *canon;
220 EdgeHdrLookup lookup;
221 void *ctx;
222 uint32_t now_ms;
223} EdgeCacheStoreFindArgs;
224
225/** @brief What entry_set_freshness takes: e, cc, shared, date_epoch, ... */
226typedef struct
227{
228 EdgeEntry *e;
229 const struct protocore_cache_control *cc;
230 proto_bool shared;
231 int64_t date_epoch;
232 int64_t expires_epoch;
233 int64_t last_modified_epoch;
234 int32_t age_hdr;
235 int64_t response_time_epoch;
236 uint32_t now_ms;
237} EdgeCacheEntrySetFreshnessArgs;
238
239/** @brief What entry_has_validator takes: e. */
240typedef struct
241{
242 const EdgeEntry *e;
243} EdgeCacheEntryHasValidatorArgs;
244
245/** @brief What entry_fresh takes: e, now_ms. */
246typedef struct
247{
248 const EdgeEntry *e;
249 uint32_t now_ms;
250} EdgeCacheEntryFreshArgs;
251
252/** @brief What store_sweep takes: s, now_ms. */
253typedef struct
254{
255 EdgeCacheStore *s;
256 uint32_t now_ms;
257} EdgeCacheStoreSweepArgs;
258
259/** @brief What store_purge takes: s, canon. */
260typedef struct
261{
262 EdgeCacheStore *s;
263 const char *canon;
264} EdgeCacheStorePurgeArgs;
265
266/** @brief What store_purge_prefix takes: s, prefix. */
267typedef struct
268{
269 EdgeCacheStore *s;
270 const char *prefix;
271} EdgeCacheStorePurgePrefixArgs;
272
273/** @brief What store_free_entry takes: s, e. */
274typedef struct
275{
276 EdgeCacheStore *s;
277 const EdgeEntry *e;
278} EdgeCacheStoreFreeEntryArgs;
279
280/** @brief What is_storeable takes: status, method, cc, vary_header, ... */
281typedef struct
282{
283 int status;
284 const char *method;
285 const struct protocore_cache_control *cc;
286 const char *vary_header;
287 size_t body_len;
288} EdgeCacheIsStoreableArgs;
289
290/** @brief What build_conditional takes: e, out, cap. */
291typedef struct
292{
293 const EdgeEntry *e;
294 char *out;
295 size_t cap;
296} EdgeCacheBuildConditionalArgs;
297
298/** @brief What apply_304 takes: e, new_hdrs, hdr_len, ... */
299typedef struct
300{
301 EdgeEntry *e;
302 const char *new_hdrs;
303 size_t hdr_len;
304 int64_t response_time_epoch;
305 uint32_t now_ms;
306} EdgeCacheApply304Args;
307
308/**
309 * @brief CDN edge-cache tier - pure engine (PROTOCORE_ENABLE_EDGE_CACHE). The caching reverse-proxy edge that ...
310 *
311 * A caller sets the members a call takes, invokes it through ::EdgeCache with the bytes it runs
312 * out of, and reads the outcome off the same handle.
313 *
314 * EdgeCache.header_value_args.hdrs = ...;
315 * EdgeCache.header_value_args.len = ...;
316 * EdgeCache.header_value_args.name = ...;
317 * EdgeCache.header_value_args.out = ...;
318 * EdgeCache.header_value_args.out_cap = ...;
319 * EdgeCache.header_value(work);
320 * // EdgeCache.ok is what the call reports
321 *
322 * @var EdgeCacheNs::header_value_args what header_value takes: hdrs, len, name, out, out_cap
323 * @var EdgeCacheNs::parse_http_date_args what parse_http_date takes: s, len
324 * @var EdgeCacheNs::freshness_lifetime_args what freshness_lifetime takes: cc, shared, date_epoch,
325 * @var EdgeCacheNs::heuristic_lifetime_args what heuristic_lifetime takes: date_epoch,
326 * @var EdgeCacheNs::initial_age_args what initial_age takes: age_hdr, date_epoch,
327 * @var EdgeCacheNs::current_age_args what current_age takes: initial_age, insert_ms, now_ms
328 * @var EdgeCacheNs::is_fresh_at_args what is_fresh_at takes: lifetime, current_age
329 * @var EdgeCacheNs::key_canon_args what key_canon takes: method, host, path, query,
330 * @var EdgeCacheNs::key_digest_args what key_digest takes: digest_work, canon, len, digest
331 * @var EdgeCacheNs::vary_serialize_args what vary_serialize takes: vary_header, lookup, ctx, out,
332 * @var EdgeCacheNs::store_init_args what store_init takes: s
333 * @var EdgeCacheNs::store_alloc_args what store_alloc takes: s, canon, vary_key
334 * @var EdgeCacheNs::store_lookup_args what store_lookup takes: s, canon, vary_key, now_ms
335 * @var EdgeCacheNs::store_find_args what store_find takes: s, canon, lookup, ctx, now_ms
336 * @var EdgeCacheNs::entry_set_freshness_args what entry_set_freshness takes: e, cc, shared, date_epoch,
337 * @var EdgeCacheNs::entry_has_validator_args what entry_has_validator takes: e
338 * @var EdgeCacheNs::entry_fresh_args what entry_fresh takes: e, now_ms
339 * @var EdgeCacheNs::store_sweep_args what store_sweep takes: s, now_ms
340 * @var EdgeCacheNs::store_purge_args what store_purge takes: s, canon
341 * @var EdgeCacheNs::store_purge_prefix_args what store_purge_prefix takes: s, prefix
342 * @var EdgeCacheNs::store_free_entry_args what store_free_entry takes: s, e
343 * @var EdgeCacheNs::is_storeable_args what is_storeable takes: status, method, cc, vary_header,
344 * @var EdgeCacheNs::build_conditional_args what build_conditional takes: e, out, cap
345 * @var EdgeCacheNs::apply_304_args what apply_304 takes: e, new_hdrs, hdr_len,
346 * @var EdgeCacheNs::ok a call's true/false outcome
347 * @var EdgeCacheNs::epoch what a call reports
348 * @var EdgeCacheNs::secs what a call reports
349 * @var EdgeCacheNs::n the key length (excluding NUL), or 0 if it would overflow out_cap ...
350 * @var EdgeCacheNs::entry the entry, or nullptr on a miss. Freshness is the caller's decision ...
351 * @var EdgeCacheNs::count the number evicted. Revalidatable stale entries are kept (they can ...
352 * @var EdgeCacheNs::header_value copy the value of header name from a raw HTTP response head (status ...
353 * @var EdgeCacheNs::parse_http_date parse an HTTP-date to epoch seconds (UTC), or return -1 if it does ...
354 * @var EdgeCacheNs::freshness_lifetime freshness lifetime in seconds, or -1 when none is explicit (caller ...
355 * @var EdgeCacheNs::heuristic_lifetime heuristic freshness (RFC 9111 sec 4.2.2): 10% of (Date - ...
356 * @var EdgeCacheNs::initial_age corrected initial age at store time (RFC 9111 sec 4.2.3)
357 * @var EdgeCacheNs::current_age current age = initial_age + resident time, taken from the monotonic ...
358 * @var EdgeCacheNs::is_fresh_at fresh iff a lifetime is known (>= 0) and the current age has not ...
359 * @var EdgeCacheNs::key_canon build the canonical cache key `METHOD "\n" host "\n" path [ "\n" ...
360 * @var EdgeCacheNs::key_digest SHA-256 of the canonical key -> digest[32] (doubles as the L2 dbm ...
361 * @var EdgeCacheNs::vary_serialize serialize a request's values for each field-name in a response ...
362 * @var EdgeCacheNs::store_init reset a store to empty
363 * @var EdgeCacheNs::store_alloc reserve a slot for canon / vary_key, evicting the LRU entry if the ...
364 * @var EdgeCacheNs::store_lookup find the entry for canon whose stored Vary values equal vary_key; ...
365 * @var EdgeCacheNs::store_find vary-aware lookup: find the entry for canon whose stored `Vary` ...
366 * @var EdgeCacheNs::entry_set_freshness resolve and store an entry's freshness (lifetime with heuristic / ...
367 * @var EdgeCacheNs::entry_has_validator true if the entry carries a validator (ETag or Last-Modified) ...
368 * @var EdgeCacheNs::entry_fresh true if the entry is still fresh at now_ms
369 * @var EdgeCacheNs::store_sweep drop entries that are both stale AND unrevalidatable (no validator) ...
370 * @var EdgeCacheNs::store_purge purge every variant stored under the exact canonical key canon. ...
371 * @var EdgeCacheNs::store_purge_prefix purge every entry whose request path begins with prefix. count ...
372 * @var EdgeCacheNs::store_free_entry unlink e and free its slot (no stat bump). Used to release a ...
373 * @var EdgeCacheNs::is_storeable may a response be stored? GET + 200 + not no-store/private + not ...
374 * @var EdgeCacheNs::build_conditional build the conditional-request header lines for revalidating e ...
375 * @var EdgeCacheNs::apply_304 apply an origin `304 Not Modified` to a stored entry: recompute its ...
376 *
377 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
378 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
379 * a caller drives every namespace the same way.
380 */
381typedef struct
382{
383 EdgeCacheHeaderValueArgs header_value_args;
384 EdgeCacheParseHttpDateArgs parse_http_date_args;
385 EdgeCacheFreshnessLifetimeArgs freshness_lifetime_args;
386 EdgeCacheHeuristicLifetimeArgs heuristic_lifetime_args;
387 EdgeCacheInitialAgeArgs initial_age_args;
388 EdgeCacheCurrentAgeArgs current_age_args;
389 EdgeCacheIsFreshAtArgs is_fresh_at_args;
390 EdgeCacheKeyCanonArgs key_canon_args;
391 EdgeCacheKeyDigestArgs key_digest_args;
392 EdgeCacheVarySerializeArgs vary_serialize_args;
393 EdgeCacheStoreInitArgs store_init_args;
394 EdgeCacheStoreAllocArgs store_alloc_args;
395 EdgeCacheStoreLookupArgs store_lookup_args;
396 EdgeCacheStoreFindArgs store_find_args;
397 EdgeCacheEntrySetFreshnessArgs entry_set_freshness_args;
398 EdgeCacheEntryHasValidatorArgs entry_has_validator_args;
399 EdgeCacheEntryFreshArgs entry_fresh_args;
400 EdgeCacheStoreSweepArgs store_sweep_args;
401 EdgeCacheStorePurgeArgs store_purge_args;
402 EdgeCacheStorePurgePrefixArgs store_purge_prefix_args;
403 EdgeCacheStoreFreeEntryArgs store_free_entry_args;
404 EdgeCacheIsStoreableArgs is_storeable_args;
405 EdgeCacheBuildConditionalArgs build_conditional_args;
406 EdgeCacheApply304Args apply_304_args;
407 proto_bool ok;
408 int64_t epoch;
409 long secs;
410 size_t n;
411 EdgeEntry *entry;
412 uint32_t count;
413} EdgeCacheVars;
414
415/** @brief The operands and the outcome. */
416extern EdgeCacheVars EdgeCacheV;
417
418/** @brief The entries. */
419typedef struct
420{
421 void (*const header_value)(uint8_t *work);
422 void (*const parse_http_date)(uint8_t *work);
423 void (*const freshness_lifetime)(uint8_t *work);
424 void (*const heuristic_lifetime)(uint8_t *work);
425 void (*const initial_age)(uint8_t *work);
426 void (*const current_age)(uint8_t *work);
427 void (*const is_fresh_at)(uint8_t *work);
428 void (*const key_canon)(uint8_t *work);
429 void (*const key_digest)(uint8_t *work);
430 void (*const vary_serialize)(uint8_t *work);
431 void (*const store_init)(uint8_t *work);
432 void (*const store_alloc)(uint8_t *work);
433 void (*const store_lookup)(uint8_t *work);
434 void (*const store_find)(uint8_t *work);
435 void (*const entry_set_freshness)(uint8_t *work);
436 void (*const entry_has_validator)(uint8_t *work);
437 void (*const entry_fresh)(uint8_t *work);
438 void (*const store_sweep)(uint8_t *work);
439 void (*const store_purge)(uint8_t *work);
440 void (*const store_purge_prefix)(uint8_t *work);
441 void (*const store_free_entry)(uint8_t *work);
442 void (*const is_storeable)(uint8_t *work);
443 void (*const build_conditional)(uint8_t *work);
444 void (*const apply_304)(uint8_t *work);
445} EdgeCacheNs;
446
447// What the table binds, defined once in the .c and taking one parameter each: everything
448// else an entry needs is an operand in EdgeCacheV or a region of the borrow at a fixed offset.
449void protocore_edge_cache_header_value(uint8_t *work);
450void protocore_edge_cache_parse_http_date(uint8_t *work);
451void protocore_edge_cache_freshness_lifetime(uint8_t *work);
452void protocore_edge_cache_heuristic_lifetime(uint8_t *work);
453void protocore_edge_cache_initial_age(uint8_t *work);
454void protocore_edge_cache_current_age(uint8_t *work);
455void protocore_edge_cache_is_fresh_at(uint8_t *work);
456void protocore_edge_cache_key_canon(uint8_t *work);
457void protocore_edge_cache_key_digest(uint8_t *work);
458void protocore_edge_cache_vary_serialize(uint8_t *work);
459void protocore_edge_cache_store_init(uint8_t *work);
460void protocore_edge_cache_store_alloc(uint8_t *work);
461void protocore_edge_cache_store_lookup(uint8_t *work);
462void protocore_edge_cache_store_find(uint8_t *work);
463void protocore_edge_cache_entry_set_freshness(uint8_t *work);
464void protocore_edge_cache_entry_has_validator(uint8_t *work);
465void protocore_edge_cache_entry_fresh(uint8_t *work);
466void protocore_edge_cache_store_sweep(uint8_t *work);
467void protocore_edge_cache_store_purge(uint8_t *work);
468void protocore_edge_cache_store_purge_prefix(uint8_t *work);
469void protocore_edge_cache_store_free_entry(uint8_t *work);
470void protocore_edge_cache_is_storeable(uint8_t *work);
471void protocore_edge_cache_build_conditional(uint8_t *work);
472void protocore_edge_cache_apply_304(uint8_t *work);
473
474// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
475// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
476// `EdgeCache.header_value(work)` resolves to a named function and becomes a DIRECT call. An extern table
477// leaves the call indirect and the symbol live at every level, -O2 -flto included.
478static const EdgeCacheNs EdgeCache __attribute__((unused)) = {
479 .header_value = protocore_edge_cache_header_value,
480 .parse_http_date = protocore_edge_cache_parse_http_date,
481 .freshness_lifetime = protocore_edge_cache_freshness_lifetime,
482 .heuristic_lifetime = protocore_edge_cache_heuristic_lifetime,
483 .initial_age = protocore_edge_cache_initial_age,
484 .current_age = protocore_edge_cache_current_age,
485 .is_fresh_at = protocore_edge_cache_is_fresh_at,
486 .key_canon = protocore_edge_cache_key_canon,
487 .key_digest = protocore_edge_cache_key_digest,
488 .vary_serialize = protocore_edge_cache_vary_serialize,
489 .store_init = protocore_edge_cache_store_init,
490 .store_alloc = protocore_edge_cache_store_alloc,
491 .store_lookup = protocore_edge_cache_store_lookup,
492 .store_find = protocore_edge_cache_store_find,
493 .entry_set_freshness = protocore_edge_cache_entry_set_freshness,
494 .entry_has_validator = protocore_edge_cache_entry_has_validator,
495 .entry_fresh = protocore_edge_cache_entry_fresh,
496 .store_sweep = protocore_edge_cache_store_sweep,
497 .store_purge = protocore_edge_cache_store_purge,
498 .store_purge_prefix = protocore_edge_cache_store_purge_prefix,
499 .store_free_entry = protocore_edge_cache_store_free_entry,
500 .is_storeable = protocore_edge_cache_is_storeable,
501 .build_conditional = protocore_edge_cache_build_conditional,
502 .apply_304 = protocore_edge_cache_apply_304,
503};
504
506
507#endif // PROTOCORE_ENABLE_EDGE_CACHE
508
509#endif // PROTOCORE_EDGE_CACHE_H
#define PROTOCORE_EDGE_ETAG_MAX
Stored validator (ETag, quotes included).
#define PROTOCORE_EDGE_CENC_MAX
Stored Content-Encoding to replay (e.g. gzip).
#define PROTOCORE_EDGE_LASTMOD_MAX
Stored Last-Modified (RFC 1123 date).
#define PROTOCORE_EDGE_KEY_MAX
#define PROTOCORE_EDGE_VARY_MAX
#define PROTOCORE_EDGE_CTYPE_MAX
Stored Content-Type to replay.
#define PROTOCORE_SHA256_BORROW
Worst-case bytes each module borrows from the secure pool in a single call.
#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