ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
ota_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/**
5 * @file ota_service.h
6 * @brief Optional authenticated OTA firmware update (PROTOCORE_ENABLE_OTA).
7 *
8 * Registers a POST endpoint that streams a firmware image straight into the
9 * platform update API via the parser's streaming-body hook
10 * (http_parser_set_stream_hooks), so the image never has to fit in RAM. On a
11 * successful flash the device responds and reboots into the new firmware.
12 * Compiled to a no-op stub when PROTOCORE_ENABLE_OTA is 0 or the platform has no updater.
13 *
14 * @author Douglas Quigg (dstroy0)
15 * @date 2026
16 */
17
18#ifndef PROTOCORE_OTA_SERVICE_H
19#define PROTOCORE_OTA_SERVICE_H
20
21#include "protocore_config.h" // the entry point: the enable gate below, and the widths
22
23#if PROTOCORE_ENABLE_OTA && PROTOCORE_HAS_VENDOR_OTA
24
26
27/**
28 * @brief Register an authenticated streaming OTA endpoint.
29 *
30 * Call after begin(). A `POST @p path` carrying a raw firmware image and valid
31 * HTTP Basic credentials is streamed into `Update`; on success the device
32 * replies `200` and reboots. Unauthorized or failed uploads get `401` / `400`.
33 *
34 * @param server The running server (the route + stream hooks are installed on it).
35 * @param path URL to accept the upload on (e.g. "/update"). Persistent string.
36 * @param user Required HTTP Basic username.
37 * @param pass Required HTTP Basic password.
38 *
39 * @code
40 * curl -u admin:s3cret --data-binary @firmware.bin http://<ip>/update
41 * @endcode
42 */
43/** @brief What installing the upload route takes. */
44typedef struct
45{
46 const char *path; ///< URL to accept the upload on (e.g. "/update"); a persistent string
47 const char *user; ///< required HTTP Basic username
48 const char *pass; ///< required HTTP Basic password
49} OtaServiceArgs;
50
51/**
52 * @brief The firmware upload route.
53 *
54 * @var OtaServiceNs::args what installing the route takes
55 * @var OtaServiceNs::begin install the route and the streaming-body hooks
56 */
57typedef struct
58{
59 OtaServiceArgs args;
60} OtaServiceVars;
61
62/** @brief The operands and the outcome. */
63extern OtaServiceVars OtaServiceV;
64
65/** @brief The entries. */
66typedef struct
67{
68 void (*const begin)(uint8_t *work);
69} OtaServiceNs;
70
71// What the table binds, defined once in the .c and taking one parameter each: everything
72// else an entry needs is an operand in OtaServiceV or a region of the borrow at a fixed offset.
73void protocore_ota_service_begin(uint8_t *work);
74
75// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
76// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
77// `OtaService.begin(work)` resolves to a named function and becomes a DIRECT call. An extern table
78// leaves the call indirect and the symbol live at every level, -O2 -flto included.
79static const OtaServiceNs OtaService __attribute__((unused)) = {
80 .begin = protocore_ota_service_begin,
81};
82
84
85#endif // PROTOCORE_ENABLE_OTA && PROTOCORE_HAS_VENDOR_OTA
86
87#endif // PROTOCORE_OTA_SERVICE_H
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
#define PROTOCORE_END_DECLS
Definition types.h:97