ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
provisioning_service.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_PROVISIONING_H
5#define PROTOCORE_PROVISIONING_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file provisioning_service.h
13 * @brief First-boot WiFi provisioning via a captive portal (PROTOCORE_ENABLE_PROVISIONING).
14 *
15 * When no WiFi credentials are stored, the device starts a softAP and a
16 * catch-all DNS responder (via the transport-layer UDP service - no add-on library) so any
17 * connected client is funneled to a credentials form. Submitted SSID/passphrase
18 * are persisted to NVS and the device reboots into station mode. Uses only
19 * `Physical.wifi_ap_init`, the library UDP transport, and the platform's key/value store; compiled
20 * to stubs when disabled or when the platform carries no such store.
21 *
22 * The form-field parser (Prov.form_field) is the pure half of this module and is the
23 * only non-trivial logic, so it is unit-tested off-target.
24 *
25 * @c work is PROTOCORE_PROVISIONING_BORROW bytes the CALLER took, at an address it knows. It is not held past the call,
26 * so nothing here aliases it. How those bytes are carved is this module's and is never named here.
27 *
28 * @author Douglas Quigg (dstroy0)
29 * @date 2026
30 */
31
32/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
33typedef struct
34{
35 proto_bool (*form_field)(uint8_t *, const char *, const char *, char *, size_t);
36 proto_bool (*load)(uint8_t *, char *, size_t, char *, size_t);
37 void (*begin)(uint8_t *, const char *);
38 void (*clear)(uint8_t *);
39} ProvNs;
40PROTOCORE_NS_LAYOUT(ProvNs, form_field, load, begin, clear);
41
42/**
43 * @brief Extract and URL-decode a field from an x-www-form-urlencoded body. .
44 * @param work PROTOCORE_PROV_BORROW bytes the caller took. Not held past the call.
45 * @param body Form body (e.g. "ssid=My+AP&psk=p%40ss")
46 * @param key Field name (e.g. "ssid")
47 * @param out Destination buffer
48 * @param cap Capacity of out (>= 1)
49 * @return PROTO_TRUE on success.
50 */
51proto_bool protocore_prov_form_field(uint8_t *work, const char *body, const char *key, char *out, size_t cap);
52/**
53 * @brief Load stored WiFi credentials from NVS.
54 * @param work PROTOCORE_PROV_BORROW bytes the caller took. Not held past the call.
55 * @param ssid Destination for the stored SSID (always null-terminated)
56 * @param ssid_cap Capacity of ssid
57 * @param psk Destination for the stored passphrase (always null-terminated)
58 * @param psk_cap Capacity of psk
59 * @return PROTO_TRUE on success.
60 */
61proto_bool protocore_prov_load(uint8_t *work, char *ssid, size_t ssid_cap, char *psk, size_t psk_cap);
62/**
63 * @brief Start the captive portal: softAP ap_ssid + catch-all DNS + form .
64 * @param work PROTOCORE_PROV_BORROW bytes the caller took. Not held past the call.
65 * @param ap_ssid Ap ssid
66 */
67void protocore_prov_begin(uint8_t *work, const char *ap_ssid);
68/**
69 * @brief Erase stored credentials (forces re-provisioning on next boot).
70 * @param work PROTOCORE_PROV_BORROW bytes the caller took. Not held past the call.
71 */
72void protocore_prov_clear(uint8_t *work);
73
74/**
75 * @brief The PROTOCORE_PROVISIONING_BORROW bytes this module's state lives in.
76 *
77 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
78 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
79 * walks, so the state lasts the life of the program.
80 *
81 * @return the span.
82 */
84
85/** @brief Module namespace. */
90
92
93#endif // PROTOCORE_PROVISIONING_H
#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.
void protocore_prov_clear(uint8_t *work)
Erase stored credentials (forces re-provisioning on next boot).
void protocore_prov_begin(uint8_t *work, const char *ap_ssid)
Start the captive portal: softAP ap_ssid + catch-all DNS + form .
proto_bool protocore_prov_form_field(uint8_t *work, const char *body, const char *key, char *out, size_t cap)
Extract and URL-decode a field from an x-www-form-urlencoded body. .
uint8_t * protocore_provisioning_service_span(void)
The PROTOCORE_PROVISIONING_BORROW bytes this module's state lives in.
proto_bool protocore_prov_load(uint8_t *work, char *ssid, size_t ssid_cap, char *psk, size_t psk_cap)
Load stored WiFi credentials from NVS.
PROTOCORE_NS ProvNs Prov PROTOCORE_UNUSED
Module namespace.
Dispatch table. Addressed by offset, so the layout is asserted below.
proto_bool(* form_field)(uint8_t *, const char *, const char *, char *, size_t)
#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