mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-26 22:41:03 +08:00
Use int64_t for timers and mg_millis()
This commit is contained in:
parent
fb0a9bc7e3
commit
ae6767b1d2
@ -133,7 +133,7 @@ to an event handler:
|
||||
```c
|
||||
enum {
|
||||
MG_EV_ERROR, // Error char *error_message
|
||||
MG_EV_POLL, // mg_mgr_poll iteration unsigned long *millis
|
||||
MG_EV_POLL, // mg_mgr_poll iteration int64_t *milliseconds
|
||||
MG_EV_RESOLVE, // Host name is resolved NULL
|
||||
MG_EV_CONNECT, // Connection established NULL
|
||||
MG_EV_ACCEPT, // Connection accepted NULL
|
||||
@ -148,7 +148,7 @@ enum {
|
||||
MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
|
||||
MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
|
||||
MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
|
||||
MG_EV_SNTP_TIME, // SNTP time received struct timeval *
|
||||
MG_EV_SNTP_TIME, // SNTP time received int64_t *milliseconds
|
||||
MG_EV_USER, // Starting ID for user events
|
||||
};
|
||||
```
|
||||
@ -1903,16 +1903,15 @@ mg_tls_init(c, &opts);
|
||||
|
||||
```c
|
||||
struct mg_timer {
|
||||
int period_ms; // Timer period in milliseconds
|
||||
int flags; // Possible flags values below
|
||||
void (*fn)(void *); // Function to call
|
||||
void *arg; // Function argument
|
||||
unsigned long expire; // Expiration timestamp in milliseconds
|
||||
struct mg_timer *next; // Linkage in g_timers list
|
||||
};
|
||||
|
||||
int64_t period_ms; // Timer period in milliseconds
|
||||
int64_t expire; // Expiration timestamp in milliseconds
|
||||
unsigned flags; // Possible flags values below
|
||||
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||
void (*fn)(void *); // Function to call
|
||||
void *arg; // Function argument
|
||||
struct mg_timer *next; // Linkage in g_timers list
|
||||
};
|
||||
```
|
||||
|
||||
Timer structure. Describes a software timer. Timer granularity is the same
|
||||
@ -1921,7 +1920,7 @@ as the `mg_mgr_poll()` timeout argument in the main event loop.
|
||||
### mg\_timer\_init()
|
||||
|
||||
```c
|
||||
void mg_timer_init(struct mg_timer *t, unsigned long ms, unsigned flags,
|
||||
void mg_timer_init(struct mg_timer *t, int64_t period_ms, unsigned flags,
|
||||
void (*fn)(void *), void *fn_data);
|
||||
```
|
||||
|
||||
@ -1969,7 +1968,7 @@ mg_timer_free(&timer);
|
||||
### mg\_timer\_poll()
|
||||
|
||||
```c
|
||||
void mg_timer_poll(unsigned long uptime_ms);
|
||||
void mg_timer_poll(int64_t uptime_ms);
|
||||
```
|
||||
|
||||
Traverse list of timers and call them if current timestamp `uptime_ms` is
|
||||
@ -1986,7 +1985,7 @@ Return value: None
|
||||
Usage example:
|
||||
|
||||
```c
|
||||
unsigned long now = mg_millis();
|
||||
int64_t now = mg_millis();
|
||||
mg_timer_poll(now);
|
||||
```
|
||||
|
||||
@ -1995,7 +1994,7 @@ mg_timer_poll(now);
|
||||
### mg\_millis()
|
||||
|
||||
```c
|
||||
unsigned long mg_millis(void);
|
||||
int64_t mg_millis(void);
|
||||
```
|
||||
|
||||
Return current uptime in milliseconds.
|
||||
@ -2007,7 +2006,7 @@ Return value: Current uptime
|
||||
Usage example:
|
||||
|
||||
```c
|
||||
unsigned long uptime = mg_millis();
|
||||
int64_t uptime = mg_millis();
|
||||
```
|
||||
|
||||
## String
|
||||
|
54
mongoose.c
54
mongoose.c
@ -117,7 +117,7 @@ int mg_base64_decode(const char *src, int n, char *dst) {
|
||||
struct dns_data {
|
||||
struct dns_data *next;
|
||||
struct mg_connection *c;
|
||||
unsigned long expire;
|
||||
int64_t expire;
|
||||
uint16_t txnid;
|
||||
};
|
||||
|
||||
@ -242,7 +242,7 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
void *fn_data) {
|
||||
struct dns_data *d, *tmp;
|
||||
if (ev == MG_EV_POLL) {
|
||||
unsigned long now = *(unsigned long *) ev_data;
|
||||
int64_t now = *(int64_t *) ev_data;
|
||||
for (d = s_reqs; d != NULL; d = tmp) {
|
||||
tmp = d->next;
|
||||
// LOG(LL_DEBUG, ("%lu %lu dns poll", d->expire, now));
|
||||
@ -356,7 +356,7 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
|
||||
d->txnid = s_reqs ? (uint16_t) (s_reqs->txnid + 1) : 1;
|
||||
d->next = s_reqs;
|
||||
s_reqs = d;
|
||||
d->expire = mg_millis() + (unsigned long) ms;
|
||||
d->expire = mg_millis() + (int64_t) ms;
|
||||
d->c = c;
|
||||
c->is_resolving = 1;
|
||||
LOG(LL_VERBOSE_DEBUG,
|
||||
@ -2785,13 +2785,14 @@ void mg_hmac_sha1(const unsigned char *key, size_t keylen,
|
||||
|
||||
|
||||
|
||||
#define SNTP_INTERVAL_SEC (3600)
|
||||
#define SNTP_INTERVAL_SEC 3600
|
||||
#define SNTP_TIME_OFFSET 2208988800UL
|
||||
|
||||
static unsigned long s_sntmp_next;
|
||||
|
||||
int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
|
||||
int mode = len > 0 ? buf[0] & 7 : 0, res = -1;
|
||||
int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
|
||||
int64_t res = -1;
|
||||
int mode = len > 0 ? buf[0] & 7 : 0;
|
||||
if (len < 48) {
|
||||
LOG(LL_ERROR, ("%s", "corrupt packet"));
|
||||
} else if ((buf[0] & 0x38) >> 3 != 4) {
|
||||
@ -2802,21 +2803,22 @@ int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
|
||||
LOG(LL_ERROR, ("%s", "server sent a kiss of death"));
|
||||
} else {
|
||||
uint32_t *data = (uint32_t *) &buf[40];
|
||||
tv->tv_sec = (time_t) (mg_ntohl(data[0]) - SNTP_TIME_OFFSET);
|
||||
tv->tv_usec = (suseconds_t) mg_ntohl(data[1]);
|
||||
s_sntmp_next = (unsigned long) (tv->tv_sec + SNTP_INTERVAL_SEC);
|
||||
res = 0;
|
||||
unsigned long seconds = mg_ntohl(data[0]) - SNTP_TIME_OFFSET;
|
||||
unsigned long useconds = mg_ntohl(data[1]);
|
||||
// LOG(LL_DEBUG, ("%lu %lu %lu", time(0), seconds, useconds));
|
||||
res = ((int64_t) seconds) * 1000 + (int64_t) ((useconds / 1000) % 1000);
|
||||
s_sntmp_next = seconds + SNTP_INTERVAL_SEC;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
if (ev == MG_EV_READ) {
|
||||
struct timeval tv = {0, 0};
|
||||
if (mg_sntp_parse(c->recv.buf, c->recv.len, &tv) == 0) {
|
||||
mg_call(c, MG_EV_SNTP_TIME, &tv);
|
||||
LOG(LL_DEBUG, ("%u.%u, next at %lu", (unsigned) tv.tv_sec,
|
||||
(unsigned) tv.tv_usec, s_sntmp_next));
|
||||
int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len);
|
||||
if (milliseconds > 0) {
|
||||
mg_call(c, MG_EV_SNTP_TIME, &milliseconds);
|
||||
LOG(LL_DEBUG, ("%u.%u, next at %lu", (unsigned) (milliseconds / 1000),
|
||||
(unsigned) (milliseconds % 1000), s_sntmp_next));
|
||||
}
|
||||
c->recv.len = 0; // Clear receive buffer
|
||||
} else if (ev == MG_EV_CONNECT) {
|
||||
@ -3424,7 +3426,7 @@ static void connect_conn(struct mg_connection *c) {
|
||||
|
||||
void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
||||
struct mg_connection *c, *tmp;
|
||||
unsigned long now;
|
||||
int64_t now;
|
||||
|
||||
mg_iotest(mgr, ms);
|
||||
now = mg_millis();
|
||||
@ -3657,7 +3659,7 @@ struct mg_str mg_strstrip(struct mg_str s) {
|
||||
|
||||
struct mg_timer *g_timers;
|
||||
|
||||
void mg_timer_init(struct mg_timer *t, unsigned long ms, unsigned flags,
|
||||
void mg_timer_init(struct mg_timer *t, int64_t ms, unsigned flags,
|
||||
void (*fn)(void *), void *arg) {
|
||||
struct mg_timer tmp = {ms, 0UL, flags, fn, arg, g_timers};
|
||||
*t = tmp;
|
||||
@ -3671,11 +3673,11 @@ void mg_timer_free(struct mg_timer *t) {
|
||||
if (*head) *head = t->next;
|
||||
}
|
||||
|
||||
void mg_timer_poll(unsigned long now_ms) {
|
||||
void mg_timer_poll(int64_t now_ms) {
|
||||
// If time goes back (wrapped around), reset timers
|
||||
struct mg_timer *t, *tmp;
|
||||
static unsigned long oldnow; // Timestamp in a previous invocation
|
||||
if (oldnow > now_ms) { // If it is wrapped, reset timers
|
||||
static int64_t oldnow; // Timestamp in a previous invocation
|
||||
if (oldnow > now_ms) { // If it is wrapped, reset timers
|
||||
for (t = g_timers; t != NULL; t = t->next) t->expire = 0;
|
||||
}
|
||||
oldnow = now_ms;
|
||||
@ -3687,9 +3689,8 @@ void mg_timer_poll(unsigned long now_ms) {
|
||||
t->fn(t->arg);
|
||||
// Try to tick timers with the given period as accurate as possible,
|
||||
// even if this polling function is called with some random period.
|
||||
t->expire = now_ms - t->expire > (unsigned long) t->period_ms
|
||||
? now_ms + t->period_ms
|
||||
: t->expire + t->period_ms;
|
||||
t->expire = now_ms - t->expire > t->period_ms ? now_ms + t->period_ms
|
||||
: t->expire + t->period_ms;
|
||||
if (!(t->flags & MG_TIMER_REPEAT)) mg_timer_free(t);
|
||||
}
|
||||
}
|
||||
@ -4457,7 +4458,7 @@ int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip) {
|
||||
return allowed == '+';
|
||||
}
|
||||
|
||||
unsigned long mg_millis(void) {
|
||||
int64_t mg_millis(void) {
|
||||
#if MG_ARCH == MG_ARCH_WIN32
|
||||
return GetTickCount();
|
||||
#elif MG_ARCH == MG_ARCH_ESP32
|
||||
@ -4474,7 +4475,7 @@ unsigned long mg_millis(void) {
|
||||
mach_timebase_info(&timebase);
|
||||
double ticks_to_nanos = (double) timebase.numer / timebase.denom;
|
||||
uint64_t uptime_nanos = (uint64_t) (ticks_to_nanos * ticks);
|
||||
return (unsigned long) (uptime_nanos / 1000000);
|
||||
return (int64_t) (uptime_nanos / 1000000);
|
||||
#else
|
||||
struct timespec ts;
|
||||
#ifdef _POSIX_MONOTONIC_CLOCK
|
||||
@ -4486,8 +4487,7 @@ unsigned long mg_millis(void) {
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#endif
|
||||
return (unsigned long) ((uint64_t) ts.tv_sec * 1000 +
|
||||
(uint64_t) ts.tv_nsec / 1000000);
|
||||
return ((int64_t) ts.tv_sec * 1000 + (int64_t) ts.tv_nsec / 1000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
32
mongoose.h
32
mongoose.h
@ -427,13 +427,15 @@ typedef int socklen_t;
|
||||
|
||||
// https://lgtm.com/rules/2154840805/ -gmtime, localtime, ctime and asctime
|
||||
static __inline struct tm *gmtime_r(time_t *t, struct tm *tm) {
|
||||
(void) tm;
|
||||
return gmtime(t);
|
||||
struct tm *x = gmtime(t);
|
||||
*tm = *x;
|
||||
return tm;
|
||||
}
|
||||
|
||||
static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
|
||||
(void) tm;
|
||||
return localtime(t);
|
||||
struct tm *x = localtime(t);
|
||||
*tm = *x;
|
||||
return tm;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -581,9 +583,11 @@ void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
struct mg_timer {
|
||||
unsigned long period_ms; // Timer period in milliseconds
|
||||
unsigned long expire; // Expiration timestamp in milliseconds
|
||||
int64_t period_ms; // Timer period in milliseconds
|
||||
int64_t expire; // Expiration timestamp in milliseconds
|
||||
unsigned flags; // Possible flags values below
|
||||
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||
@ -594,10 +598,10 @@ struct mg_timer {
|
||||
|
||||
extern struct mg_timer *g_timers; // Global list of timers
|
||||
|
||||
void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
|
||||
void (*fn)(void *), void *);
|
||||
void mg_timer_init(struct mg_timer *, int64_t, unsigned, void (*)(void *),
|
||||
void *);
|
||||
void mg_timer_free(struct mg_timer *);
|
||||
void mg_timer_poll(unsigned long current_time_ms);
|
||||
void mg_timer_poll(int64_t current_time_ms);
|
||||
|
||||
|
||||
|
||||
@ -619,9 +623,9 @@ void mg_unhex(const char *buf, size_t len, unsigned char *to);
|
||||
unsigned long mg_unhexn(const char *s, size_t len);
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
int64_t mg_to64(struct mg_str str);
|
||||
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||||
unsigned long mg_millis(void);
|
||||
int64_t mg_to64(struct mg_str str);
|
||||
int64_t mg_millis(void);
|
||||
|
||||
#define mg_htons(x) mg_ntohs(x)
|
||||
#define mg_htonl(x) mg_ntohl(x)
|
||||
@ -763,7 +767,7 @@ void mg_error(struct mg_connection *c, const char *fmt, ...);
|
||||
enum {
|
||||
MG_EV_ERROR, // Error char *error_message
|
||||
MG_EV_OPEN, // Connection created NULL
|
||||
MG_EV_POLL, // mg_mgr_poll iteration unsigned long *millis
|
||||
MG_EV_POLL, // mg_mgr_poll iteration int64_t *milliseconds
|
||||
MG_EV_RESOLVE, // Host name is resolved NULL
|
||||
MG_EV_CONNECT, // Connection established NULL
|
||||
MG_EV_ACCEPT, // Connection accepted NULL
|
||||
@ -778,7 +782,7 @@ enum {
|
||||
MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
|
||||
MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
|
||||
MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
|
||||
MG_EV_SNTP_TIME, // SNTP time received struct timeval *
|
||||
MG_EV_SNTP_TIME, // SNTP time received int64_t *milliseconds
|
||||
MG_EV_USER, // Starting ID for user events
|
||||
};
|
||||
|
||||
@ -1020,7 +1024,7 @@ size_t mg_ws_wrap(struct mg_connection *, size_t len, int op);
|
||||
struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data);
|
||||
void mg_sntp_send(struct mg_connection *c, unsigned long utc);
|
||||
int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv);
|
||||
int64_t mg_sntp_parse(const unsigned char *buf, size_t len);
|
||||
|
||||
|
||||
|
||||
|
@ -89,13 +89,15 @@ typedef int socklen_t;
|
||||
|
||||
// https://lgtm.com/rules/2154840805/ -gmtime, localtime, ctime and asctime
|
||||
static __inline struct tm *gmtime_r(time_t *t, struct tm *tm) {
|
||||
(void) tm;
|
||||
return gmtime(t);
|
||||
struct tm *x = gmtime(t);
|
||||
*tm = *x;
|
||||
return tm;
|
||||
}
|
||||
|
||||
static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
|
||||
(void) tm;
|
||||
return localtime(t);
|
||||
struct tm *x = localtime(t);
|
||||
*tm = *x;
|
||||
return tm;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
struct dns_data {
|
||||
struct dns_data *next;
|
||||
struct mg_connection *c;
|
||||
unsigned long expire;
|
||||
int64_t expire;
|
||||
uint16_t txnid;
|
||||
};
|
||||
|
||||
@ -132,7 +132,7 @@ static void dns_cb(struct mg_connection *c, int ev, void *ev_data,
|
||||
void *fn_data) {
|
||||
struct dns_data *d, *tmp;
|
||||
if (ev == MG_EV_POLL) {
|
||||
unsigned long now = *(unsigned long *) ev_data;
|
||||
int64_t now = *(int64_t *) ev_data;
|
||||
for (d = s_reqs; d != NULL; d = tmp) {
|
||||
tmp = d->next;
|
||||
// LOG(LL_DEBUG, ("%lu %lu dns poll", d->expire, now));
|
||||
@ -246,7 +246,7 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
|
||||
d->txnid = s_reqs ? (uint16_t) (s_reqs->txnid + 1) : 1;
|
||||
d->next = s_reqs;
|
||||
s_reqs = d;
|
||||
d->expire = mg_millis() + (unsigned long) ms;
|
||||
d->expire = mg_millis() + (int64_t) ms;
|
||||
d->c = c;
|
||||
c->is_resolving = 1;
|
||||
LOG(LL_VERBOSE_DEBUG,
|
||||
|
@ -9,7 +9,7 @@ void mg_error(struct mg_connection *c, const char *fmt, ...);
|
||||
enum {
|
||||
MG_EV_ERROR, // Error char *error_message
|
||||
MG_EV_OPEN, // Connection created NULL
|
||||
MG_EV_POLL, // mg_mgr_poll iteration unsigned long *millis
|
||||
MG_EV_POLL, // mg_mgr_poll iteration int64_t *milliseconds
|
||||
MG_EV_RESOLVE, // Host name is resolved NULL
|
||||
MG_EV_CONNECT, // Connection established NULL
|
||||
MG_EV_ACCEPT, // Connection accepted NULL
|
||||
@ -24,6 +24,6 @@ enum {
|
||||
MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
|
||||
MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
|
||||
MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
|
||||
MG_EV_SNTP_TIME, // SNTP time received struct timeval *
|
||||
MG_EV_SNTP_TIME, // SNTP time received int64_t *milliseconds
|
||||
MG_EV_USER, // Starting ID for user events
|
||||
};
|
||||
|
26
src/sntp.c
26
src/sntp.c
@ -4,13 +4,14 @@
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
#define SNTP_INTERVAL_SEC (3600)
|
||||
#define SNTP_INTERVAL_SEC 3600
|
||||
#define SNTP_TIME_OFFSET 2208988800UL
|
||||
|
||||
static unsigned long s_sntmp_next;
|
||||
|
||||
int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
|
||||
int mode = len > 0 ? buf[0] & 7 : 0, res = -1;
|
||||
int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
|
||||
int64_t res = -1;
|
||||
int mode = len > 0 ? buf[0] & 7 : 0;
|
||||
if (len < 48) {
|
||||
LOG(LL_ERROR, ("%s", "corrupt packet"));
|
||||
} else if ((buf[0] & 0x38) >> 3 != 4) {
|
||||
@ -21,21 +22,22 @@ int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
|
||||
LOG(LL_ERROR, ("%s", "server sent a kiss of death"));
|
||||
} else {
|
||||
uint32_t *data = (uint32_t *) &buf[40];
|
||||
tv->tv_sec = (time_t) (mg_ntohl(data[0]) - SNTP_TIME_OFFSET);
|
||||
tv->tv_usec = (suseconds_t) mg_ntohl(data[1]);
|
||||
s_sntmp_next = (unsigned long) (tv->tv_sec + SNTP_INTERVAL_SEC);
|
||||
res = 0;
|
||||
unsigned long seconds = mg_ntohl(data[0]) - SNTP_TIME_OFFSET;
|
||||
unsigned long useconds = mg_ntohl(data[1]);
|
||||
// LOG(LL_DEBUG, ("%lu %lu %lu", time(0), seconds, useconds));
|
||||
res = ((int64_t) seconds) * 1000 + (int64_t) ((useconds / 1000) % 1000);
|
||||
s_sntmp_next = seconds + SNTP_INTERVAL_SEC;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
if (ev == MG_EV_READ) {
|
||||
struct timeval tv = {0, 0};
|
||||
if (mg_sntp_parse(c->recv.buf, c->recv.len, &tv) == 0) {
|
||||
mg_call(c, MG_EV_SNTP_TIME, &tv);
|
||||
LOG(LL_DEBUG, ("%u.%u, next at %lu", (unsigned) tv.tv_sec,
|
||||
(unsigned) tv.tv_usec, s_sntmp_next));
|
||||
int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len);
|
||||
if (milliseconds > 0) {
|
||||
mg_call(c, MG_EV_SNTP_TIME, &milliseconds);
|
||||
LOG(LL_DEBUG, ("%u.%u, next at %lu", (unsigned) (milliseconds / 1000),
|
||||
(unsigned) (milliseconds % 1000), s_sntmp_next));
|
||||
}
|
||||
c->recv.len = 0; // Clear receive buffer
|
||||
} else if (ev == MG_EV_CONNECT) {
|
||||
|
@ -5,4 +5,4 @@
|
||||
struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
|
||||
mg_event_handler_t fn, void *fn_data);
|
||||
void mg_sntp_send(struct mg_connection *c, unsigned long utc);
|
||||
int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv);
|
||||
int64_t mg_sntp_parse(const unsigned char *buf, size_t len);
|
||||
|
@ -572,7 +572,7 @@ static void connect_conn(struct mg_connection *c) {
|
||||
|
||||
void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
|
||||
struct mg_connection *c, *tmp;
|
||||
unsigned long now;
|
||||
int64_t now;
|
||||
|
||||
mg_iotest(mgr, ms);
|
||||
now = mg_millis();
|
||||
|
13
src/timer.c
13
src/timer.c
@ -6,7 +6,7 @@
|
||||
|
||||
struct mg_timer *g_timers;
|
||||
|
||||
void mg_timer_init(struct mg_timer *t, unsigned long ms, unsigned flags,
|
||||
void mg_timer_init(struct mg_timer *t, int64_t ms, unsigned flags,
|
||||
void (*fn)(void *), void *arg) {
|
||||
struct mg_timer tmp = {ms, 0UL, flags, fn, arg, g_timers};
|
||||
*t = tmp;
|
||||
@ -20,11 +20,11 @@ void mg_timer_free(struct mg_timer *t) {
|
||||
if (*head) *head = t->next;
|
||||
}
|
||||
|
||||
void mg_timer_poll(unsigned long now_ms) {
|
||||
void mg_timer_poll(int64_t now_ms) {
|
||||
// If time goes back (wrapped around), reset timers
|
||||
struct mg_timer *t, *tmp;
|
||||
static unsigned long oldnow; // Timestamp in a previous invocation
|
||||
if (oldnow > now_ms) { // If it is wrapped, reset timers
|
||||
static int64_t oldnow; // Timestamp in a previous invocation
|
||||
if (oldnow > now_ms) { // If it is wrapped, reset timers
|
||||
for (t = g_timers; t != NULL; t = t->next) t->expire = 0;
|
||||
}
|
||||
oldnow = now_ms;
|
||||
@ -36,9 +36,8 @@ void mg_timer_poll(unsigned long now_ms) {
|
||||
t->fn(t->arg);
|
||||
// Try to tick timers with the given period as accurate as possible,
|
||||
// even if this polling function is called with some random period.
|
||||
t->expire = now_ms - t->expire > (unsigned long) t->period_ms
|
||||
? now_ms + t->period_ms
|
||||
: t->expire + t->period_ms;
|
||||
t->expire = now_ms - t->expire > t->period_ms ? now_ms + t->period_ms
|
||||
: t->expire + t->period_ms;
|
||||
if (!(t->flags & MG_TIMER_REPEAT)) mg_timer_free(t);
|
||||
}
|
||||
}
|
||||
|
12
src/timer.h
12
src/timer.h
@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
struct mg_timer {
|
||||
unsigned long period_ms; // Timer period in milliseconds
|
||||
unsigned long expire; // Expiration timestamp in milliseconds
|
||||
int64_t period_ms; // Timer period in milliseconds
|
||||
int64_t expire; // Expiration timestamp in milliseconds
|
||||
unsigned flags; // Possible flags values below
|
||||
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||||
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||||
@ -13,7 +15,7 @@ struct mg_timer {
|
||||
|
||||
extern struct mg_timer *g_timers; // Global list of timers
|
||||
|
||||
void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
|
||||
void (*fn)(void *), void *);
|
||||
void mg_timer_init(struct mg_timer *, int64_t, unsigned, void (*)(void *),
|
||||
void *);
|
||||
void mg_timer_free(struct mg_timer *);
|
||||
void mg_timer_poll(unsigned long current_time_ms);
|
||||
void mg_timer_poll(int64_t current_time_ms);
|
||||
|
@ -299,7 +299,7 @@ int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip) {
|
||||
return allowed == '+';
|
||||
}
|
||||
|
||||
unsigned long mg_millis(void) {
|
||||
int64_t mg_millis(void) {
|
||||
#if MG_ARCH == MG_ARCH_WIN32
|
||||
return GetTickCount();
|
||||
#elif MG_ARCH == MG_ARCH_ESP32
|
||||
@ -316,7 +316,7 @@ unsigned long mg_millis(void) {
|
||||
mach_timebase_info(&timebase);
|
||||
double ticks_to_nanos = (double) timebase.numer / timebase.denom;
|
||||
uint64_t uptime_nanos = (uint64_t) (ticks_to_nanos * ticks);
|
||||
return (unsigned long) (uptime_nanos / 1000000);
|
||||
return (int64_t) (uptime_nanos / 1000000);
|
||||
#else
|
||||
struct timespec ts;
|
||||
#ifdef _POSIX_MONOTONIC_CLOCK
|
||||
@ -328,7 +328,6 @@ unsigned long mg_millis(void) {
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#endif
|
||||
return (unsigned long) ((uint64_t) ts.tv_sec * 1000 +
|
||||
(uint64_t) ts.tv_nsec / 1000000);
|
||||
return ((int64_t) ts.tv_sec * 1000 + (int64_t) ts.tv_nsec / 1000000);
|
||||
#endif
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ void mg_unhex(const char *buf, size_t len, unsigned char *to);
|
||||
unsigned long mg_unhexn(const char *s, size_t len);
|
||||
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||||
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
int64_t mg_to64(struct mg_str str);
|
||||
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||||
unsigned long mg_millis(void);
|
||||
int64_t mg_to64(struct mg_str str);
|
||||
int64_t mg_millis(void);
|
||||
|
||||
#define mg_htons(x) mg_ntohs(x)
|
||||
#define mg_htonl(x) mg_ntohl(x)
|
||||
|
@ -27,9 +27,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
mg_mqtt_parse(data, size, &mm);
|
||||
mg_mqtt_parse(NULL, 0, &mm);
|
||||
|
||||
struct timeval tv;
|
||||
mg_sntp_parse(data, size, &tv);
|
||||
mg_sntp_parse(NULL, 0, &tv);
|
||||
mg_sntp_parse(data, size);
|
||||
mg_sntp_parse(NULL, 0);
|
||||
|
||||
char buf[size * 4 / 3 + 5]; // At least 4 chars and nul termination
|
||||
mg_base64_decode((char *) data, (int) size, buf);
|
||||
|
@ -243,24 +243,24 @@ static void test_iobuf(void) {
|
||||
|
||||
static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
if (ev == MG_EV_SNTP_TIME) {
|
||||
*(struct timeval *) fnd = *(struct timeval *) evd;
|
||||
*(int64_t *) fnd = *(int64_t *) evd;
|
||||
}
|
||||
(void) c;
|
||||
}
|
||||
|
||||
static void test_sntp(void) {
|
||||
struct timeval tv = {0, 0};
|
||||
int64_t ms = 0;
|
||||
struct mg_mgr mgr;
|
||||
struct mg_connection *c = NULL;
|
||||
int i;
|
||||
|
||||
mg_mgr_init(&mgr);
|
||||
c = mg_sntp_connect(&mgr, NULL, sntp_cb, &tv);
|
||||
c = mg_sntp_connect(&mgr, NULL, sntp_cb, &ms);
|
||||
ASSERT(c != NULL);
|
||||
ASSERT(c->is_udp == 1);
|
||||
mg_sntp_send(c, (unsigned long) time(NULL));
|
||||
for (i = 0; i < 300 && tv.tv_sec == 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
ASSERT(tv.tv_sec > 0);
|
||||
for (i = 0; i < 300 && ms == 0; i++) mg_mgr_poll(&mgr, 10);
|
||||
ASSERT(ms > 0);
|
||||
mg_mgr_free(&mgr);
|
||||
|
||||
{
|
||||
@ -274,22 +274,21 @@ static void test_sntp(void) {
|
||||
"\xc9\xd6\xa2\xdb\xde\xea\x30\x91\x86\xb7\x10\xdb\xde"
|
||||
"\xed\x98\x00\x00\x00\xde\xdb\xde\xed\x99\x0a\xe2\xc7"
|
||||
"\x96\xdb\xde\xed\x99\x0a\xe4\x6b\xda";
|
||||
struct timeval tv2 = {0, 0};
|
||||
struct tm *tm;
|
||||
struct tm tm;
|
||||
time_t t;
|
||||
ASSERT(mg_sntp_parse(sntp_good, sizeof(sntp_good), &tv2) == 0);
|
||||
t = tv2.tv_sec;
|
||||
tm = gmtime(&t);
|
||||
ASSERT(tm->tm_year == 116);
|
||||
ASSERT(tm->tm_mon == 10);
|
||||
ASSERT(tm->tm_mday == 22);
|
||||
ASSERT(tm->tm_hour == 16);
|
||||
ASSERT(tm->tm_min == 15);
|
||||
ASSERT(tm->tm_sec == 21);
|
||||
ASSERT(mg_sntp_parse(bad_good, sizeof(bad_good), &tv2) == -1);
|
||||
ASSERT((ms = mg_sntp_parse(sntp_good, sizeof(sntp_good))) > 0);
|
||||
t = (time_t) (ms / 1000);
|
||||
gmtime_r(&t, &tm);
|
||||
ASSERT(tm.tm_year == 116);
|
||||
ASSERT(tm.tm_mon == 10);
|
||||
ASSERT(tm.tm_mday == 22);
|
||||
ASSERT(tm.tm_hour == 16);
|
||||
ASSERT(tm.tm_min == 15);
|
||||
ASSERT(tm.tm_sec == 21);
|
||||
ASSERT(mg_sntp_parse(bad_good, sizeof(bad_good)) < 0);
|
||||
}
|
||||
|
||||
ASSERT(mg_sntp_parse(NULL, 0, &tv) == -1);
|
||||
ASSERT(mg_sntp_parse(NULL, 0) == -1);
|
||||
}
|
||||
|
||||
static void mqtt_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user