aboutsummaryrefslogtreecommitdiff
path: root/ntp_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'ntp_client.c')
-rw-r--r--ntp_client.c155
1 files changed, 77 insertions, 78 deletions
diff --git a/ntp_client.c b/ntp_client.c
index 38275c9..06f7aac 100644
--- a/ntp_client.c
+++ b/ntp_client.c
@@ -41,10 +41,11 @@
typedef struct NTP_T_ {
ip_addr_t ntp_server_address;
- bool dns_request_sent;
struct udp_pcb *ntp_pcb;
- alarm_id_t ntp_resend_alarm;
- void (*callback)(int status);
+ alarm_id_t send_alarm;
+ int err;
+ int ok;
+ int first;
} NTP_T;
@@ -52,7 +53,7 @@ typedef struct NTP_T_ {
#define NTP_MSG_LEN 48
#define NTP_PORT 123
#define NTP_DELTA 2208988800 // seconds between 1 Jan 1900 and 1 Jan 1970
-#define NTP_RESEND_TIME (10 * 1000)
+#define NTP_RESEND_TIME (5 * 1000 * 1000)
static void set_rtc(time_t iutc)
@@ -76,29 +77,41 @@ static void set_rtc(time_t iutc)
}
-static void ntp_result(NTP_T *state, int status, time_t *result)
+static void ntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
+ const ip_addr_t *addr, u16_t port)
{
- debug_print("NTP result:\n");
- if (status == NTP_REPLY_RECEIVED && result) {
-
- debug_print("yay!\n");
-
- if ( state->ntp_resend_alarm > 0 ) {
- cancel_alarm(state->ntp_resend_alarm);
- state->ntp_resend_alarm = 0;
- }
+ NTP_T *state = (NTP_T*)arg;
+ uint8_t mode = pbuf_get_at(p, 0) & 0x7;
+ uint8_t stratum = pbuf_get_at(p, 1);
- set_rtc(*result);
+ debug_print("got UDP: %i %i\n", addr, state->ntp_server_address);
+ debug_print("port %i len %i mode %i stratum %i\n", port, p->tot_len, mode, stratum);
+ if (ip_addr_cmp(addr, &state->ntp_server_address)
+ && port == NTP_PORT
+ && p->tot_len == NTP_MSG_LEN
+ && mode == 0x4 && stratum != 0)
+ {
+ uint8_t seconds_buf[4] = {0};
+ pbuf_copy_partial(p, seconds_buf, sizeof(seconds_buf), 40);
+ uint32_t seconds_since_1900 = seconds_buf[0] << 24
+ | seconds_buf[1] << 16
+ | seconds_buf[2] << 8
+ | seconds_buf[3];
+ uint32_t seconds_since_1970 = seconds_since_1900 - NTP_DELTA;
+ time_t epoch = seconds_since_1970;
+ debug_print("second since 1970 = %i\n", epoch);
+ set_rtc(epoch);
+ state->err = 0;
+ state->ok = 1;
} else {
- debug_print("other reply.\n");
+ state->err = 1;
}
-
- state->callback(status);
- state->dns_request_sent = false;
+ pbuf_free(p);
}
+/* The real address must be in state->ntp_server_address by this point */
static void ntp_request(NTP_T *state)
{
debug_print("sending NTP UDP\n");
@@ -110,7 +123,7 @@ static void ntp_request(NTP_T *state)
udp_sendto(state->ntp_pcb, p, &state->ntp_server_address, NTP_PORT);
pbuf_free(p);
cyw43_arch_lwip_end();
- state->callback(NTP_REQUEST_SENT);
+ state->err = 0;
}
@@ -122,94 +135,80 @@ static void ntp_dns_found(const char *hostname,
if (ipaddr) {
debug_print("DNS ok (%i)\n", *ipaddr);
state->ntp_server_address = *ipaddr;
+ state->err = 0;
ntp_request(state);
} else {
debug_print("NTP failed: DNS no address\n");
- ntp_result(state, NTP_DNS_NO_ADDR, NULL);
+ state->err = 1;
}
}
-static void ntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
- const ip_addr_t *addr, u16_t port)
+
+static int64_t send_handler(alarm_id_t id, void *user_data)
{
- NTP_T *state = (NTP_T*)arg;
- uint8_t mode = pbuf_get_at(p, 0) & 0x7;
- uint8_t stratum = pbuf_get_at(p, 1);
+ int err;
+ NTP_T *state = (NTP_T*)user_data;
- debug_print("got UDP: %i %i\n", addr, state->ntp_server_address);
- debug_print("port %i len %i mode %i stratum %i\n", port, p->tot_len, mode, stratum);
-
- if (ip_addr_cmp(addr, &state->ntp_server_address)
- && port == NTP_PORT
- && p->tot_len == NTP_MSG_LEN
- && mode == 0x4 && stratum != 0)
- {
- uint8_t seconds_buf[4] = {0};
- pbuf_copy_partial(p, seconds_buf, sizeof(seconds_buf), 40);
- uint32_t seconds_since_1900 = seconds_buf[0] << 24
- | seconds_buf[1] << 16
- | seconds_buf[2] << 8
- | seconds_buf[3];
- uint32_t seconds_since_1970 = seconds_since_1900 - NTP_DELTA;
- time_t epoch = seconds_since_1970;
- debug_print("second since 1970 = %i\n", epoch);
- ntp_result(state, NTP_REPLY_RECEIVED, &epoch);
- } else {
- ntp_result(state, NTP_BAD_REPLY, NULL);
- }
- pbuf_free(p);
-}
+ if ( !state->first && !state->err ) return NTP_RESEND_TIME;
+ state->first = 0;
+ cyw43_arch_lwip_begin();
+ err = dns_gethostbyname(NTP_SERVER,
+ &state->ntp_server_address,
+ ntp_dns_found,
+ state);
+ cyw43_arch_lwip_end();
-static int64_t ntp_failed_handler(alarm_id_t id, void *user_data)
-{
- NTP_T *state = (NTP_T*)user_data;
- ntp_result(state, NTP_TIMEOUT, NULL);
- return 0;
+ if ( err == ERR_OK ) {
+ /* Immediate reply -> cached result */
+ ntp_request(state);
+ state->err = 0;
+ } else if (err != ERR_INPROGRESS) {
+ state->err = 1;
+ }
+ return NTP_RESEND_TIME;
}
-NTP_T *ntp_init(void (*reply_func)(int))
+NTP_T *ntp_init()
{
NTP_T *state = calloc(1, sizeof(NTP_T));
if (!state) return NULL;
- state->callback = reply_func;
+ state->err = 0;
+ state->ok = 0;
+ state->first = 1;
state->ntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
if (!state->ntp_pcb) {
free(state);
return NULL;
}
+
+ /* Set up UDP callback */
udp_recv(state->ntp_pcb, ntp_recv, state);
+
+ /* It's probably too early to start resolving hostnames or sending
+ * UDP packets. Call us back in a moment. */
+ state->send_alarm = add_alarm_in_us(NTP_RESEND_TIME,
+ send_handler,
+ state,
+ true);
+
return state;
}
-void ntp_send_request(NTP_T *state)
+int ntp_ok(NTP_T *state)
{
- if ( state == NULL ) return;
-
- cyw43_arch_lwip_begin();
- int err = dns_gethostbyname(NTP_SERVER,
- &state->ntp_server_address,
- ntp_dns_found,
- state);
- cyw43_arch_lwip_end();
+ if ( state == NULL ) return 0;
+ return state->ok;
+}
- state->ntp_resend_alarm = add_alarm_in_ms(NTP_RESEND_TIME,
- ntp_failed_handler,
- state,
- true);
- state->dns_request_sent = true;
- if ( err == ERR_OK ) {
- /* Immediate reply -> cached result */
- ntp_request(state);
- } else if (err != ERR_INPROGRESS) {
- /* Error sending DNS request
- * (ERR_INPROGRESS means expect a callback) */
- ntp_result(state, NTP_DNS_ERROR, NULL);
- }
+int ntp_err(NTP_T *state)
+{
+ if ( state == NULL ) return 0;
+ return state->err;
}