Skip to content

Commit 346c947

Browse files
committed
net: lib: sntp: async query API
Add a variant of the SNTP API that does not block while waiting for a response from the SNTP server. Instead it takes advantage of `CONFIG_NET_SOCKETS_SERVICE` to read the response asynchronously when the response is received. Signed-off-by: Jordan Yates <[email protected]>
1 parent c8b5187 commit 346c947

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

include/zephyr/net/sntp.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define ZEPHYR_INCLUDE_NET_SNTP_H_
1515

1616
#include <zephyr/net/socket.h>
17+
#include <zephyr/net/socket_service.h>
1718

1819
#ifdef __cplusplus
1920
extern "C" {
@@ -99,6 +100,52 @@ int sntp_recv_response(struct sntp_ctx *ctx, uint32_t timeout, struct sntp_time
99100
*/
100101
void sntp_close(struct sntp_ctx *ctx);
101102

103+
/**
104+
* @brief Initialise SNTP context for async operation
105+
*
106+
* Asynchronous operation is powered by @kconfig{CONFIG_NET_SOCKETS_SERVICE}.
107+
*
108+
* @param service Socket service defined by @ref NET_SOCKET_SERVICE_SYNC_DEFINE
109+
* @param ctx Address of sntp context.
110+
* @param addr IP address of NTP/SNTP server.
111+
* @param addr_len IP address length of NTP/SNTP server.
112+
*
113+
* @return 0 if ok, <0 if error.
114+
*/
115+
int sntp_init_async(const struct net_socket_service_desc *service,
116+
struct sntp_ctx *ctx, struct sockaddr *addr,
117+
socklen_t addr_len);
118+
119+
/**
120+
* @brief Send the SNTP query
121+
*
122+
* @param ctx Address of sntp context.
123+
*
124+
* @return 0 if ok, <0 if error.
125+
*/
126+
int sntp_send_async(struct sntp_ctx *ctx);
127+
128+
/**
129+
* @brief Read the result of the SNTP query
130+
*
131+
* Must be called from the callback attached to the @ref net_socket_service_desc
132+
* context.
133+
*
134+
* @param event Event pointer extracted from the service work callback
135+
* @param time Timestamp including integer and fractional seconds since
136+
* 1 Jan 1970 (output).
137+
*
138+
* @return 0 if ok, <0 if error
139+
*/
140+
int sntp_read_async(struct net_socket_service_event *event, struct sntp_time *time);
141+
142+
/**
143+
* @brief Release SNTP context
144+
*
145+
* @param service Socket service defined by @ref NET_SOCKET_SERVICE_SYNC_DEFINE
146+
*/
147+
void sntp_close_async(const struct net_socket_service_desc *service);
148+
102149
/**
103150
* @brief Convenience function to query SNTP in one-shot fashion
104151
*

subsys/net/lib/sntp/sntp.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,72 @@ void sntp_close(struct sntp_ctx *ctx)
254254
(void)zsock_close(ctx->sock.fd);
255255
}
256256
}
257+
258+
#ifdef CONFIG_NET_SOCKETS_SERVICE
259+
260+
int sntp_init_async(const struct net_socket_service_desc *service, struct sntp_ctx *ctx,
261+
struct sockaddr *addr, socklen_t addr_len)
262+
{
263+
int ret;
264+
265+
/* Standard init */
266+
ret = sntp_init(ctx, addr, addr_len);
267+
if (ret < 0) {
268+
return ret;
269+
}
270+
/* Attach socket to socket service */
271+
ret = net_socket_service_register(service, ctx->sock.fds, ctx->sock.nfds, ctx);
272+
if (ret < 0) {
273+
NET_ERR("Failed to register socket %d", ret);
274+
/* Cleanup init on register failure*/
275+
sntp_close(ctx);
276+
}
277+
return ret;
278+
}
279+
280+
int sntp_send_async(struct sntp_ctx *ctx)
281+
{
282+
int ret = 0;
283+
284+
if (!ctx) {
285+
return -EFAULT;
286+
}
287+
288+
ret = sntp_query_send(ctx);
289+
if (ret < 0) {
290+
NET_ERR("Failed to send over UDP socket %d", ret);
291+
return ret;
292+
}
293+
return 0;
294+
}
295+
296+
int sntp_read_async(struct net_socket_service_event *event, struct sntp_time *time)
297+
{
298+
struct sntp_ctx *ctx = event->user_data;
299+
struct sntp_pkt buf = {0};
300+
int rcvd;
301+
302+
rcvd = zsock_recv(ctx->sock.fd, (uint8_t *)&buf, sizeof(buf), 0);
303+
if (rcvd < 0) {
304+
return -errno;
305+
}
306+
307+
if (rcvd != sizeof(struct sntp_pkt)) {
308+
return -EMSGSIZE;
309+
}
310+
311+
return parse_response((uint8_t *)&buf, sizeof(buf), &ctx->expected_orig_ts, time);
312+
}
313+
314+
void sntp_close_async(const struct net_socket_service_desc *service)
315+
{
316+
struct sntp_ctx *ctx = service->pev->user_data;
317+
/* Detach socket from socket service */
318+
net_socket_service_unregister(service);
319+
/* CLose the socket */
320+
if (ctx) {
321+
(void)zsock_close(ctx->sock.fd);
322+
}
323+
}
324+
325+
#endif /* CONFIG_NET_SOCKETS_SERVICE */

0 commit comments

Comments
 (0)