diff --git a/examples/device-dashboard/net.c b/examples/device-dashboard/net.c index 4ad5c2ff..fae16969 100644 --- a/examples/device-dashboard/net.c +++ b/examples/device-dashboard/net.c @@ -26,12 +26,6 @@ static struct settings s_settings = {true, 1, 57, NULL}; static const char *s_json_header = "Content-Type: application/json\r\n" "Cache-Control: no-cache\r\n"; -static uint64_t s_boot_timestamp = 0; // Updated by SNTP - -// This is for newlib and TLS (mbedTLS) -uint64_t mg_now(void) { - return mg_millis() + s_boot_timestamp; -} int ui_event_next(int no, struct ui_event *e) { if (no < 0 || no >= MAX_EVENTS_NO) return 0; @@ -49,23 +43,8 @@ int ui_event_next(int no, struct ui_event *e) { return no + 1; } -// SNTP connection event handler. When we get a response from an SNTP server, -// adjust s_boot_timestamp. We'll get a valid time from that point on -static void sfn(struct mg_connection *c, int ev, void *ev_data) { - uint64_t *expiration_time = (uint64_t *) c->data; - if (ev == MG_EV_OPEN) { - *expiration_time = mg_millis() + 3000; // Store expiration time in 3s - } else if (ev == MG_EV_SNTP_TIME) { - uint64_t t = *(uint64_t *) ev_data; - s_boot_timestamp = t - mg_millis(); - c->is_closing = 1; - } else if (ev == MG_EV_POLL) { - if (mg_millis() > *expiration_time) c->is_closing = 1; - } -} - static void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time - mg_sntp_connect(param, "udp://time.google.com:123", sfn, NULL); + mg_sntp_connect(param, "udp://time.google.com:123", NULL, NULL); } // Parse HTTP requests, return authenticated user or NULL diff --git a/examples/modbus-dashboard/net.c b/examples/modbus-dashboard/net.c index a226b1f5..a734f12e 100644 --- a/examples/modbus-dashboard/net.c +++ b/examples/modbus-dashboard/net.c @@ -22,7 +22,6 @@ static struct device_settings s_settings; static const char *s_json_header = "Content-Type: application/json\r\n" "Cache-Control: no-cache\r\n"; -static uint64_t s_boot_timestamp = 0; // Updated by SNTP static void set_default_settings(struct device_settings *s) { s->magic = SETTINGS_MAGIC; @@ -33,29 +32,9 @@ static void set_default_settings(struct device_settings *s) { mg_snprintf(s->mqtt_topic_rx, sizeof(s->mqtt_topic_rx), "%s", "modbus1/rx"); } -// This is for newlib and TLS (mbedTLS) -uint64_t mg_now(void) { - return mg_millis() + s_boot_timestamp; -} - -// SNTP connection event handler. When we get a response from an SNTP server, -// adjust s_boot_timestamp. We'll get a valid time from that point on -static void sfn(struct mg_connection *c, int ev, void *ev_data) { - uint64_t *expiration_time = (uint64_t *) c->data; - if (ev == MG_EV_OPEN) { - *expiration_time = mg_millis() + 3000; // Store expiration time in 3s - } else if (ev == MG_EV_SNTP_TIME) { - uint64_t t = *(uint64_t *) ev_data; - s_boot_timestamp = t - mg_millis(); - c->is_closing = 1; - } else if (ev == MG_EV_POLL) { - if (mg_millis() > *expiration_time) c->is_closing = 1; - } -} - // SNTP timer function. Sync up time static void timer_sntp_fn(void *param) { - mg_sntp_connect(param, "udp://time.google.com:123", sfn, NULL); + mg_sntp_connect(param, "udp://time.google.com:123", NULL, NULL); } static void setfromjson(struct mg_str json, const char *jsonpath, char *buf, diff --git a/examples/mqtt-dashboard/device/net.c b/examples/mqtt-dashboard/device/net.c index 29b79d22..5964dae8 100644 --- a/examples/mqtt-dashboard/device/net.c +++ b/examples/mqtt-dashboard/device/net.c @@ -20,11 +20,6 @@ struct device_config { }; static struct device_config s_device_config; -static uint64_t s_boot_timestamp = 0; // Updated by SNTP - -uint64_t mg_now(void) { - return mg_millis() + s_boot_timestamp; -} // Device ID generation function. Create an ID that is unique // for a given device, and does not change between device restarts. @@ -277,26 +272,11 @@ static void timer_ping(void *arg) { (void) arg; } -// SNTP connection event handler. When we get a response from an SNTP server, -// adjust s_boot_timestamp. We'll get a valid time from that point on -static void sntp_ev_handler(struct mg_connection *c, int ev, void *ev_data) { - uint64_t *expiration_time = (uint64_t *) c->data; - if (ev == MG_EV_OPEN) { - *expiration_time = mg_millis() + 3000; // Store expiration time in 3s - } else if (ev == MG_EV_SNTP_TIME) { - uint64_t t = *(uint64_t *) ev_data; - s_boot_timestamp = t - mg_millis(); - c->is_closing = 1; - } else if (ev == MG_EV_POLL) { - if (mg_millis() > *expiration_time) c->is_closing = 1; - } -} - static void timer_sntp(void *param) { // SNTP timer function. Sync up time static uint64_t hourly_timer = 0; - if (s_boot_timestamp == 0 || - mg_timer_expired(&hourly_timer, 3600000, mg_millis())) { - mg_sntp_connect(param, "udp://time.google.com:123", sntp_ev_handler, NULL); + uint64_t t1 = mg_now(), t2 = mg_millis(); + if (t1 < t2 + 3600 || mg_timer_expired(&hourly_timer, 3600000, t2)) { + mg_sntp_connect(param, "udp://time.google.com:123", NULL, NULL); } } diff --git a/mongoose.c b/mongoose.c index 7a3e9263..e02c7f80 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7145,6 +7145,12 @@ void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data, #define SNTP_TIME_OFFSET 2208988800U // (1970 - 1900) in seconds #define SNTP_MAX_FRAC 4294967295.0 // 2 ** 32 - 1 +static uint64_t s_boot_timestamp = 0; // Updated by SNTP + +uint64_t mg_now(void) { + return mg_millis() + s_boot_timestamp; +} + static int64_t gettimestamp(const uint32_t *data) { uint32_t sec = mg_ntohl(data[0]), frac = mg_ntohl(data[1]); if (sec) sec -= SNTP_TIME_OFFSET; @@ -7167,9 +7173,9 @@ int64_t mg_sntp_parse(const unsigned char *buf, size_t len) { int64_t receive_time = gettimestamp((uint32_t *) &buf[32]); int64_t transmit_time = gettimestamp((uint32_t *) &buf[40]); int64_t now = (int64_t) mg_millis(); - int64_t travel_time = (now - origin_time) - (transmit_time - receive_time); - MG_INFO(("%lld %lld", transmit_time, travel_time)); - epoch_milliseconds = transmit_time + travel_time / 2; + int64_t latency = (now - origin_time) - (transmit_time - receive_time); + epoch_milliseconds = transmit_time + latency / 2; + s_boot_timestamp = (uint64_t) (epoch_milliseconds - now); } else { MG_ERROR(("unexpected version: %d", version)); } @@ -7177,17 +7183,22 @@ int64_t mg_sntp_parse(const unsigned char *buf, size_t len) { } static void sntp_cb(struct mg_connection *c, int ev, void *ev_data) { - if (ev == MG_EV_READ) { - int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); - if (milliseconds > 0) { - MG_DEBUG(("%lu got time: %lld ms from epoch", c->id, milliseconds)); - mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); - MG_VERBOSE(("%u.%u", (unsigned) (milliseconds / 1000), - (unsigned) (milliseconds % 1000))); - } - mg_iobuf_del(&c->recv, 0, c->recv.len); // Free receive buffer + uint64_t *expiration_time = (uint64_t *) c->data; + if (ev == MG_EV_OPEN) { + *expiration_time = mg_millis() + 3000; // Store expiration time in 3s } else if (ev == MG_EV_CONNECT) { mg_sntp_request(c); + } else if (ev == MG_EV_READ) { + int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); + if (milliseconds > 0) { + s_boot_timestamp = (uint64_t) milliseconds - mg_millis(); + mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); + MG_DEBUG(("%lu got time: %lld ms from epoch", c->id, milliseconds)); + } + // mg_iobuf_del(&c->recv, 0, c->recv.len); // Free receive buffer + c->is_closing = 1; + } else if (ev == MG_EV_POLL) { + if (mg_millis() > *expiration_time) c->is_closing = 1; } else if (ev == MG_EV_CLOSE) { } (void) ev_data; @@ -7212,7 +7223,10 @@ struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fnd) { struct mg_connection *c = NULL; if (url == NULL) url = "udp://time.google.com:123"; - if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) c->pfn = sntp_cb; + if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) { + c->pfn = sntp_cb; + sntp_cb(c, MG_EV_OPEN, (void *) url); + } return c; } diff --git a/reference-projects/windows-macos-linux/web-ui-dashboard/net.c b/reference-projects/windows-macos-linux/web-ui-dashboard/net.c index 6da28c45..9a80e4da 100644 --- a/reference-projects/windows-macos-linux/web-ui-dashboard/net.c +++ b/reference-projects/windows-macos-linux/web-ui-dashboard/net.c @@ -27,12 +27,6 @@ static struct settings s_settings = {true, 1, 57, NULL}; static const char *s_json_header = "Content-Type: application/json\r\n" "Cache-Control: no-cache\r\n"; -static uint64_t s_boot_timestamp = 0; // Updated by SNTP - -// This is for newlib and TLS (mbedTLS) -uint64_t mg_now(void) { - return mg_millis() + s_boot_timestamp; -} int ui_event_next(int no, struct ui_event *e) { if (no < 0 || no >= MAX_EVENTS_NO) return 0; @@ -50,23 +44,8 @@ int ui_event_next(int no, struct ui_event *e) { return no + 1; } -// SNTP connection event handler. When we get a response from an SNTP server, -// adjust s_boot_timestamp. We'll get a valid time from that point on -static void sfn(struct mg_connection *c, int ev, void *ev_data) { - uint64_t *expiration_time = (uint64_t *) c->data; - if (ev == MG_EV_OPEN) { - *expiration_time = mg_millis() + 3000; // Store expiration time in 3s - } else if (ev == MG_EV_SNTP_TIME) { - uint64_t t = *(uint64_t *) ev_data; - s_boot_timestamp = t - mg_millis(); - c->is_closing = 1; - } else if (ev == MG_EV_POLL) { - if (mg_millis() > *expiration_time) c->is_closing = 1; - } -} - static void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time - mg_sntp_connect(param, "udp://time.google.com:123", sfn, NULL); + mg_sntp_connect(param, "udp://time.google.com:123", NULL, NULL); } // Parse HTTP requests, return authenticated user or NULL diff --git a/src/sntp.c b/src/sntp.c index 2afa1327..fbbba176 100644 --- a/src/sntp.c +++ b/src/sntp.c @@ -7,6 +7,12 @@ #define SNTP_TIME_OFFSET 2208988800U // (1970 - 1900) in seconds #define SNTP_MAX_FRAC 4294967295.0 // 2 ** 32 - 1 +static uint64_t s_boot_timestamp = 0; // Updated by SNTP + +uint64_t mg_now(void) { + return mg_millis() + s_boot_timestamp; +} + static int64_t gettimestamp(const uint32_t *data) { uint32_t sec = mg_ntohl(data[0]), frac = mg_ntohl(data[1]); if (sec) sec -= SNTP_TIME_OFFSET; @@ -29,8 +35,9 @@ int64_t mg_sntp_parse(const unsigned char *buf, size_t len) { int64_t receive_time = gettimestamp((uint32_t *) &buf[32]); int64_t transmit_time = gettimestamp((uint32_t *) &buf[40]); int64_t now = (int64_t) mg_millis(); - int64_t travel_time = (now - origin_time) - (transmit_time - receive_time); - epoch_milliseconds = transmit_time + travel_time / 2; + int64_t latency = (now - origin_time) - (transmit_time - receive_time); + epoch_milliseconds = transmit_time + latency / 2; + s_boot_timestamp = (uint64_t) (epoch_milliseconds - now); } else { MG_ERROR(("unexpected version: %d", version)); } @@ -38,17 +45,22 @@ int64_t mg_sntp_parse(const unsigned char *buf, size_t len) { } static void sntp_cb(struct mg_connection *c, int ev, void *ev_data) { - if (ev == MG_EV_READ) { - int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); - if (milliseconds > 0) { - MG_DEBUG(("%lu got time: %lld ms from epoch", c->id, milliseconds)); - mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); - MG_VERBOSE(("%u.%u", (unsigned) (milliseconds / 1000), - (unsigned) (milliseconds % 1000))); - } - mg_iobuf_del(&c->recv, 0, c->recv.len); // Free receive buffer + uint64_t *expiration_time = (uint64_t *) c->data; + if (ev == MG_EV_OPEN) { + *expiration_time = mg_millis() + 3000; // Store expiration time in 3s } else if (ev == MG_EV_CONNECT) { mg_sntp_request(c); + } else if (ev == MG_EV_READ) { + int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); + if (milliseconds > 0) { + s_boot_timestamp = (uint64_t) milliseconds - mg_millis(); + mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds); + MG_DEBUG(("%lu got time: %lld ms from epoch", c->id, milliseconds)); + } + // mg_iobuf_del(&c->recv, 0, c->recv.len); // Free receive buffer + c->is_closing = 1; + } else if (ev == MG_EV_POLL) { + if (mg_millis() > *expiration_time) c->is_closing = 1; } else if (ev == MG_EV_CLOSE) { } (void) ev_data; @@ -73,6 +85,9 @@ struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url, mg_event_handler_t fn, void *fnd) { struct mg_connection *c = NULL; if (url == NULL) url = "udp://time.google.com:123"; - if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) c->pfn = sntp_cb; + if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) { + c->pfn = sntp_cb; + sntp_cb(c, MG_EV_OPEN, (void *) url); + } return c; }