ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
ntp_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 ntp_service.h
6 * @brief Optional SNTP wall-clock time sync (PROTOCORE_ENABLE_NTP).
7 *
8 * Starts a client, reports sync state, and formats the current time.
9 *
10 * One client, the library's own: it asks a server over the UDP listener, checks the reply echoes the
11 * request it answers, and keeps the epoch in its own state; the monotonic clock carries it between
12 * syncs and nothing in libc moves. It takes a literal address rather than a name - it has no resolver
13 * of its own - and reports UTC, so the POSIX TZ argument is accepted and ignored.
14 *
15 * @author Douglas Quigg (dstroy0)
16 * @date 2026
17 */
18
19#ifndef PROTOCORE_NTP_SERVICE_H
20#define PROTOCORE_NTP_SERVICE_H
21
22#include "protocore_config.h" // the entry point: protocore_types.h for the widths
23
25
27
28#if PROTOCORE_ENABLE_NTP
29
31
32// PROTOCORE_NTP_SERVICE_BORROW - the bytes this module runs out of - is stated in protocore_config.h, which sums
33// it into its arena. A caller takes them once and passes the pointer to every call. How they
34// are carved is this module's and is never named here.
35
36/** @brief Server this asks when the caller names none. */
37#define PROTOCORE_NTP_SERVER1 "pool.ntp.org"
38
39/** @brief Server this falls back to when the caller names none. */
40#define PROTOCORE_NTP_SERVER2 "time.nist.gov"
41
42/** @brief What begin takes: tz, server1, server2. */
43typedef struct
44{
45 const char *tz; ///< POSIX TZ string (e.g. "UTC0", "EST5EDT,M3.2.0,M11.1.0"). NULL selects UTC
46 const char *server1; ///< Primary NTP server. NULL selects PROTOCORE_NTP_SERVER1
47 const char *server2; ///< Secondary NTP server. NULL selects PROTOCORE_NTP_SERVER2
48} NtpServiceBeginArgs;
49
50/** @brief What set_test_epoch takes: epoch. */
51typedef struct
52{
53 time_t epoch;
54} NtpServiceSetTestEpochArgs;
55
56/**
57 * @brief Optional SNTP wall-clock time sync (PROTOCORE_ENABLE_NTP).
58 *
59 * A caller sets the members a call takes, invokes it through ::NtpService with the bytes it runs
60 * out of, and reads the outcome off the same handle.
61 *
62 * NtpService.begin_args.tz = ...;
63 * NtpService.begin_args.server1 = ...;
64 * NtpService.begin_args.server2 = ...;
65 * NtpService.begin(work);
66 * // NtpService.ok is what the call reports
67 *
68 * @var NtpServiceNs::begin_args what begin takes: tz, server1, server2
69 * @var NtpServiceNs::set_test_epoch_args what set_test_epoch takes: epoch
70 * @var NtpServiceNs::ok true if the client was started; false if disabled at compile time
71 * @var NtpServiceNs::value the value a call reports
72 * @var NtpServiceNs::ms the milliseconds a call reports
73 * @var NtpServiceNs::begin start the SNTP client. Returns immediately; the first sync arrives ...
74 * @var NtpServiceNs::synced true once a plausible wall-clock time has been obtained from SNTP. ...
75 * @var NtpServiceNs::epoch current Unix epoch seconds, or 0 if not yet synced (or disabled)
76 * @var NtpServiceNs::time_source NTP as a time source for the multi-source registry ...
77 * @var NtpServiceNs::set_test_epoch seed the clock without asking a server: the accessors above report ...
78 *
79 * @c work is PROTOCORE_NTP_SERVICE_BORROW bytes the CALLER took, at an address it knows. It is not held past the call,
80 * so nothing here aliases it. How those bytes are carved is this module's and is never named here.
81 */
82typedef struct
83{
84 NtpServiceBeginArgs begin_args;
85 NtpServiceSetTestEpochArgs set_test_epoch_args;
86 proto_bool ok;
87 time_t value;
88 uint32_t ms;
89} NtpServiceVars;
90
91/** @brief The operands and the outcome. */
92extern NtpServiceVars NtpServiceV;
93
94/** @brief The entries. */
95typedef struct
96{
97 void (*const begin)(uint8_t *work);
98 void (*const synced)(uint8_t *work);
99 void (*const epoch)(uint8_t *work);
100 void (*const time_source)(uint8_t *work);
101 void (*const set_test_epoch)(uint8_t *work);
102} NtpServiceNs;
103
104// What the table binds, defined once in the .c and taking one parameter each: everything
105// else an entry needs is an operand in NtpServiceV or a region of the borrow at a fixed offset.
106void protocore_ntp_service_begin(uint8_t *work);
107void protocore_ntp_service_synced(uint8_t *work);
108void protocore_ntp_service_epoch(uint8_t *work);
109void protocore_ntp_service_time_source(uint8_t *work);
110void protocore_ntp_service_set_test_epoch(uint8_t *work);
111
112// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
113// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
114// `NtpService.begin(work)` resolves to a named function and becomes a DIRECT call. An extern table
115// leaves the call indirect and the symbol live at every level, -O2 -flto included.
116static const NtpServiceNs NtpService __attribute__((unused)) = {
117 .begin = protocore_ntp_service_begin,
118 .synced = protocore_ntp_service_synced,
119 .epoch = protocore_ntp_service_epoch,
120 .time_source = protocore_ntp_service_time_source,
121 .set_test_epoch = protocore_ntp_service_set_test_epoch,
122};
123
124/**
125 * @brief The PROTOCORE_NTP_SERVICE_BORROW bytes this module's state lives in.
126 *
127 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
128 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
129 * walks, so the state lasts the life of the program.
130 *
131 * @return the span.
132 */
133uint8_t *protocore_ntp_service_span(void);
134
136
137#endif // PROTOCORE_ENABLE_NTP
138
139#endif // PROTOCORE_NTP_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
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97