1 /*
2  * Copyright (c) 2019 Linaro Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <errno.h>
7 
8 #include <zephyr/net/sntp.h>
9 #include <zephyr/net/socketutils.h>
10 
sntp_simple(const char * server,uint32_t timeout,struct sntp_time * time)11 int sntp_simple(const char *server, uint32_t timeout, struct sntp_time *time)
12 {
13 	int res;
14 	static struct zsock_addrinfo hints;
15 	struct zsock_addrinfo *addr;
16 	struct sntp_ctx sntp_ctx;
17 	uint64_t deadline;
18 	uint32_t iter_timeout;
19 
20 	hints.ai_family = AF_UNSPEC;
21 	hints.ai_socktype = SOCK_DGRAM;
22 	hints.ai_protocol = 0;
23 	/* 123 is the standard SNTP port per RFC4330 */
24 	res = net_getaddrinfo_addr_str(server, "123", &hints, &addr);
25 
26 	if (res < 0) {
27 		/* Just in case, as namespace for getaddrinfo errors is
28 		 * different from errno errors.
29 		 */
30 		errno = EDOM;
31 		return res;
32 	}
33 
34 	res = sntp_init(&sntp_ctx, addr->ai_addr, addr->ai_addrlen);
35 	if (res < 0) {
36 		goto freeaddr;
37 	}
38 
39 	if (timeout == SYS_FOREVER_MS) {
40 		deadline = (uint64_t)timeout;
41 	} else {
42 		deadline = k_uptime_get() + (uint64_t)timeout;
43 	}
44 
45 	/* Timeout for current iteration */
46 	iter_timeout = 100;
47 
48 	while (k_uptime_get() < deadline) {
49 		res = sntp_query(&sntp_ctx, iter_timeout, time);
50 
51 		if (res != -ETIMEDOUT) {
52 			break;
53 		}
54 
55 		/* Exponential backoff with limit */
56 		if (iter_timeout < 1000) {
57 			iter_timeout *= 2;
58 		}
59 	}
60 
61 	sntp_close(&sntp_ctx);
62 
63 freeaddr:
64 	zsock_freeaddrinfo(addr);
65 
66 	return res;
67 }
68