DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
guardrails.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 guardrails.h
6 * @brief Runtime heap/stack guardrails (DETWS_ENABLE_GUARDRAILS).
7 *
8 * Samples the live health of the device - free heap, the heap low-water mark, the
9 * largest free block (a fragmentation signal), and the calling task's remaining
10 * stack - and trips a guardrail (callback) when any value crosses its configured
11 * floor. A proactive fail-safe hook on top of the passive numbers in /metrics: an
12 * app can shed load, drop to a safe state, or reboot before exhaustion bites.
13 *
14 * The threshold evaluator and the JSON serializer are pure and host-tested; the
15 * sample reads `esp_get_free_heap_size` / `heap_caps_get_largest_free_block` /
16 * `uxTaskGetStackHighWaterMark` on ESP32 (zeros on host).
17 *
18 * @author Douglas Quigg (dstroy0)
19 * @date 2026
20 */
21
22#ifndef DETERMINISTICESPASYNCWEBSERVER_GUARDRAILS_H
23#define DETERMINISTICESPASYNCWEBSERVER_GUARDRAILS_H
24
25#include "ServerConfig.h"
26#include <stddef.h>
27#include <stdint.h>
28
29#if DETWS_ENABLE_GUARDRAILS
30
31/** @brief A health snapshot. */
32struct DetwsHealth
33{
34 uint32_t free_heap; ///< current free heap (bytes).
35 uint32_t min_free_heap; ///< lowest free heap since boot (bytes).
36 uint32_t largest_free_block; ///< largest allocatable block (fragmentation, bytes).
37 uint32_t stack_free; ///< calling task's remaining stack (bytes).
38};
39
40/** @brief Guardrail breach flags: a bitmask OR'd together, so integer constants in a namespacing
41 * struct (cast-free at every | / &). */
42struct DetwsBreach
43{
44 static constexpr uint8_t DETWS_BREACH_NONE = 0;
45 static constexpr uint8_t DETWS_BREACH_HEAP = 1; ///< free heap below DETWS_GUARDRAIL_HEAP_MIN.
46 static constexpr uint8_t DETWS_BREACH_FRAG = 2; ///< largest block below DETWS_GUARDRAIL_FRAG_MIN_BLOCK.
47 static constexpr uint8_t DETWS_BREACH_STACK = 4; ///< task stack remaining below DETWS_GUARDRAIL_STACK_MIN.
48};
49
50// ---------------------------------------------------------------------------
51// Host-testable core
52// ---------------------------------------------------------------------------
53
54/** @brief Evaluate @p h against the floors; returns a DETWS_BREACH_* bitmask. */
55uint8_t detws_guardrail_eval(const DetwsHealth *h, uint32_t heap_min, uint32_t frag_min_block, uint32_t stack_min);
56
57/**
58 * @brief Serialize a health snapshot as JSON into @p out.
59 * @return characters written, or 0 if @p cap is too small (fail-closed).
60 */
61int detws_health_json(const DetwsHealth *h, char *out, size_t cap);
62
63// ---------------------------------------------------------------------------
64// Sampling + guardrail check (ESP32; zeros / no-op on host)
65// ---------------------------------------------------------------------------
66
67/** @brief Fill @p h from the live esp_* / FreeRTOS counters (zeros on host). */
68void detws_guardrails_sample(DetwsHealth *h);
69
70/** @brief Breach callback: @p breaches is a DETWS_BREACH_* bitmask, @p h the snapshot. */
71typedef void (*detws_breach_fn)(uint8_t breaches, const DetwsHealth *h);
72
73/** @brief Install the breach callback (thresholds come from DETWS_GUARDRAIL_*). */
74void detws_guardrails_begin(detws_breach_fn cb);
75
76/**
77 * @brief Sample, evaluate, and fire the callback if any guardrail is breached.
78 * @return the DETWS_BREACH_* bitmask (0 = all clear).
79 */
80uint8_t detws_guardrails_check(void);
81
82#endif // DETWS_ENABLE_GUARDRAILS
83#endif // DETERMINISTICESPASYNCWEBSERVER_GUARDRAILS_H
User-facing configuration for DeterministicESPAsyncWebServer.