ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
webhook.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 webhook.h
6 * @brief Outbound webhooks / IFTTT (PROTOCORE_ENABLE_WEBHOOK).
7 *
8 * A webhook is an HTTP POST the device originates. The pattern itself is not standardized: no
9 * IETF RFC defines "webhook", and the IFTTT Maker interface these builders target is one
10 * service's own URI convention. What is standardized is everything that POST rides on.
11 *
12 * RFC 9110 sec 9.3.3: "The POST method requests that the target resource process the
13 * representation enclosed in the request according to the resource's own specific semantics."
14 * The resource is named by the target URI (RFC 9110 sec 7.1), here an https URI
15 * (RFC 9110 sec 4.2.2) whose path is a sequence of segments (RFC 3986 sec 3.3). The content
16 * (RFC 9110 sec 6.4) is a JSON object (RFC 8259 sec 4) carried under Content-Type
17 * application/json (RFC 9110 sec 8.3; the media type is registered in RFC 8259 sec 11) with a
18 * Content-Length taken from its octet count (RFC 9110 sec 8.6). The answer is a three-digit
19 * status code (RFC 9110 sec 15.1): 2xx says the request was received, understood, and accepted
20 * (RFC 9110 sec 15.3); 4xx and 5xx say it was not (RFC 9110 sec 15.5, sec 15.6).
21 *
22 * The two builders are pure and host-testable. Sending needs PROTOCORE_ENABLE_HTTP_CLIENT: on a
23 * build without it ::WebhookNs::post reports -1 and nothing is transmitted.
24 *
25 * The module exports one symbol, @ref Webhook. Everything in webhook.c has internal linkage.
26 *
27 * @author Douglas Quigg (dstroy0)
28 * @date 2026
29 */
30
31#ifndef PROTOCORE_WEBHOOK_H
32#define PROTOCORE_WEBHOOK_H
33
34#include "protocore_config.h" // the entry point: protocore_types.h for the widths
35
36#if PROTOCORE_ENABLE_WEBHOOK
37
39
40/** @brief RFC 9110 sec 7.1 / sec 6.4: what a POST names and what it carries. */
41typedef struct
42{
43 const char *target_uri; ///< the https URI a POST is sent to (RFC 9110 sec 4.2.2)
44 const char *content; ///< the JSON object it carries (RFC 8259 sec 4)
45} WebhookRequestArgs;
46
47/** @brief The caller region a builder writes into. */
48typedef struct
49{
50 char *out; ///< where the built octets land
51 size_t cap; ///< how much room they have, terminator included
52} WebhookBuildArgs;
53
54/** @brief The IFTTT Maker event: the two path segments its URI carries and its three values. */
55typedef struct
56{
57 const char *event; ///< the event name path segment (RFC 3986 sec 3.3)
58 const char *key; ///< the Maker key path segment
59 const char *value1; ///< first member of the object; NULL omits it
60 const char *value2; ///< second member; NULL omits it
61 const char *value3; ///< third member; NULL omits it
62} WebhookIftttArgs;
63
64/**
65 * @brief The outbound webhook module: build a target URI and a JSON object, then POST them.
66 *
67 * A caller sets the members a call takes, invokes it through ::Webhook, and reads the outcome off
68 * the same handle. No slot member: one call runs at a time and names no session.
69 *
70 * No storage member: the builders write the caller's region, and the URI and content a trigger
71 * builds live on that call's own frame, so nothing survives a call.
72 *
73 * @var WebhookNs::request the target URI a POST names and the content it carries
74 * @var WebhookNs::build the caller region a builder writes into
75 * @var WebhookNs::ifttt the Maker event, key, and up to three values
76 * @var WebhookNs::n octets a builder wrote, 0 when the whole build would not fit
77 * @var WebhookNs::i32 the status code a POST read back (RFC 9110 sec 15.1), or a negative
78 * transport error
79 * @var WebhookNs::ifttt_url build the Maker target URI from @c ifttt.event and @c ifttt.key
80 * @var WebhookNs::ifttt_payload build the value1/value2/value3 object (RFC 8259 sec 4)
81 * @var WebhookNs::post POST @c request.content as application/json to
82 * @c request.target_uri (RFC 9110 sec 9.3.3)
83 * @var WebhookNs::ifttt_trigger build the URI and the object into its own frames, then POST them
84 */
85typedef struct
86{
87 WebhookRequestArgs request; ///< what a POST names and carries
88 WebhookBuildArgs build; ///< where a builder writes
89 WebhookIftttArgs ifttt; ///< the Maker event fields
90 int n;
91 int i32;
92} WebhookVars;
93
94/** @brief The operands and the outcome. */
95extern WebhookVars WebhookV;
96
97/** @brief The entries. */
98typedef struct
99{
100 void (*const ifttt_url)(uint8_t *work);
101 void (*const ifttt_payload)(uint8_t *work);
102 void (*const post)(uint8_t *work);
103 void (*const ifttt_trigger)(uint8_t *work);
104} WebhookNs;
105
106// What the table binds, defined once in the .c and taking one parameter each: everything
107// else an entry needs is an operand in WebhookV or a region of the borrow at a fixed offset.
108void protocore_webhook_ifttt_url(uint8_t *work);
109void protocore_webhook_ifttt_payload(uint8_t *work);
110void protocore_webhook_post(uint8_t *work);
111void protocore_webhook_ifttt_trigger(uint8_t *work);
112
113// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
114// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
115// `Webhook.ifttt_url(work)` resolves to a named function and becomes a DIRECT call. An extern table
116// leaves the call indirect and the symbol live at every level, -O2 -flto included.
117static const WebhookNs Webhook __attribute__((unused)) = {
118 .ifttt_url = protocore_webhook_ifttt_url,
119 .ifttt_payload = protocore_webhook_ifttt_payload,
120 .post = protocore_webhook_post,
121 .ifttt_trigger = protocore_webhook_ifttt_trigger,
122};
123
125
126#endif // PROTOCORE_ENABLE_WEBHOOK
127
128#endif // PROTOCORE_WEBHOOK_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