Fix #1285 - __builtin___snprintf_chk warning. Tighten test flags and refactor the code to squash all warnings

This commit is contained in:
cpq committed 2021-05-28 18:30:42 +01:00
1 parent db27fae40e
commit 736b8ad7b7
30 files changed
+708 -691

No files matched your search

+6 -1
View File
@@ -37,4 +37,9 @@ jobs:
run: make mingw run: make mingw
- name: mingw++ - name: mingw++
run: make mingw++ run: make mingw++
arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: arm
run: make arm
+8 -1
View File
@@ -1,13 +1,17 @@
SRCS = $(wildcard src/*.c) SRCS = $(wildcard src/*.c)
HDRS = $(wildcard src/*.h) HDRS = $(wildcard src/*.h)
DEFS ?= -DMG_MAX_HTTP_HEADERS=5 -DMG_ENABLE_LINES -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1 DEFS ?= -DMG_MAX_HTTP_HEADERS=5 -DMG_ENABLE_LINES -DMG_ENABLE_DIRECTORY_LISTING=1 -DMG_ENABLE_SSI=1
CFLAGS ?= -W -Wall -Werror -Isrc -I. -O0 -g $(DEFS) $(TFLAGS) $(EXTRA) WARN ?= -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion
OPTS ?= -O3 -g3
INCS ?= -Isrc -I.
CFLAGS ?= $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) $(EXTRA)
SSL ?= MBEDTLS SSL ?= MBEDTLS
CDIR ?= $(realpath $(CURDIR)) CDIR ?= $(realpath $(CURDIR))
VC98 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc98 VC98 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc98
VC2017 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc2017 VC2017 = docker run --rm -e WINEDEBUG=-all -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/vc2017
MINGW = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/mingw MINGW = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/mingw
GCC = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) mdashnet/cc2 GCC = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) mdashnet/cc2
ARM = docker run -v $(CDIR):$(CDIR) -w $(CDIR) mdashnet/armgcc
VCFLAGS = /nologo /W3 /O2 /I. $(DEFS) $(TFLAGS) VCFLAGS = /nologo /W3 /O2 /I. $(DEFS) $(TFLAGS)
CLANG ?= clang # /usr/local/opt/llvm\@9/bin/clang CLANG ?= clang # /usr/local/opt/llvm\@9/bin/clang
IPV6 ?= 1 IPV6 ?= 1
@@ -95,6 +99,9 @@ linux: Makefile mongoose.c mongoose.h test/unit_test.c
linux++: CC = g++ -Wno-missing-field-initializers linux++: CC = g++ -Wno-missing-field-initializers
linux++: linux linux++: linux
arm: Makefile mongoose.c mongoose.h test/unit_test.c
$(ARM) arm-none-eabi-gcc mongoose.c -c -Itest -DMG_ARCH=MG_ARCH_CUSTOM $(OPTS) $(WARN) $(INCS) -DMG_MAX_HTTP_HEADERS=5 -DMG_ENABLE_LINES -DMG_ENABLE_DIRECTORY_LISTING=0 -DMG_ENABLE_SSI=1
mongoose.c: $(SRCS) Makefile mongoose.c: $(SRCS) Makefile
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/private.h src/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@ (cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/private.h src/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
+4 -6
View File
@@ -1015,19 +1015,18 @@ Subscribe to topic `topic`.
### mg\_mqtt\_next\_sub() ### mg\_mqtt\_next\_sub()
```c ```c
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, uint8_t *qos, size_t pos);
uint8_t *qos, int pos);
``` ```
Traverse list of subscribed topics. Traverse list of subscribed topics.
Used to implement MQTT server when `MQTT_CMD_SUBSCRIBE` is received. Used to implement MQTT server when `MQTT_CMD_SUBSCRIBE` is received.
Return next position. Initial position `pos` should be 4. Example: Return next position, or 0 when done. Initial position `pos` should be 4. Example:
```c ```c
if (ev == MG_EV_MQTT_CMD) { if (ev == MG_EV_MQTT_CMD) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data; struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if (mm->cmd == MQTT_CMD_SUBSCRIBE) { if (mm->cmd == MQTT_CMD_SUBSCRIBE) {
int pos = 4; size_t pos = 4;
uint8_t qos; uint8_t qos;
struct mg_str topic; struct mg_str topic;
while ((pos = mg_mqtt_next_sub(mm, &topic, &qos, pos)) > 0) { while ((pos = mg_mqtt_next_sub(mm, &topic, &qos, pos)) > 0) {
@@ -1040,8 +1039,7 @@ if (ev == MG_EV_MQTT_CMD) {
### mg\_mqtt\_next\_unsub() ### mg\_mqtt\_next\_unsub()
```c ```c
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t pos);
int pos);
``` ```
Same as `mg_mqtt_next_sub()`, but for unsubscribed topics. The difference Same as `mg_mqtt_next_sub()`, but for unsubscribed topics. The difference
+296 -305
View File
File diff suppressed because it is too large. Load diff
+24 -22
View File
@@ -286,6 +286,7 @@ typedef enum { false = 0, true = 1 } bool;
#define strdup(x) _strdup(x) #define strdup(x) _strdup(x)
#endif #endif
typedef unsigned suseconds_t;
typedef int socklen_t; typedef int socklen_t;
#define MG_DIRSEP '\\' #define MG_DIRSEP '\\'
#ifndef PATH_MAX #ifndef PATH_MAX
@@ -425,7 +426,7 @@ enum { LL_NONE, LL_ERROR, LL_INFO, LL_DEBUG, LL_VERBOSE_DEBUG };
bool mg_log_prefix(int ll, const char *file, int line, const char *fname); bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2); void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
void mg_log_set(const char *spec); void mg_log_set(const char *spec);
void mg_log_set_callback(void (*fn)(const void *, int, void *), void *param); void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
#else #else
#define LOG(level, args) (void) 0 #define LOG(level, args) (void) 0
#define mg_log_set(x) (void) (x) #define mg_log_set(x) (void) (x)
@@ -433,8 +434,8 @@ void mg_log_set_callback(void (*fn)(const void *, int, void *), void *param);
struct mg_timer { struct mg_timer {
int period_ms; // Timer period in milliseconds unsigned long period_ms; // Timer period in milliseconds
int flags; // Possible flags values below unsigned flags; // Possible flags values below
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once #define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
void (*fn)(void *); // Function to call void (*fn)(void *); // Function to call
@@ -445,7 +446,8 @@ struct mg_timer {
extern struct mg_timer *g_timers; // Global list of timers extern struct mg_timer *g_timers; // Global list of timers
void mg_timer_init(struct mg_timer *, int ms, int, void (*fn)(void *), void *); void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
void (*fn)(void *), void *);
void mg_timer_free(struct mg_timer *); void mg_timer_free(struct mg_timer *);
void mg_timer_poll(unsigned long uptime_ms); void mg_timer_poll(unsigned long uptime_ms);
@@ -471,15 +473,15 @@ int64_t mg_file_size(const char *path);
bool mg_file_write(const char *path, const void *buf, size_t len); bool mg_file_write(const char *path, const void *buf, size_t len);
bool mg_file_printf(const char *path, const char *fmt, ...); bool mg_file_printf(const char *path, const char *fmt, ...);
void mg_random(void *buf, size_t len) WEAK; void mg_random(void *buf, size_t len) WEAK;
bool mg_globmatch(const char *pattern, int plen, const char *s, int n); bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v); bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v);
uint16_t mg_ntohs(uint16_t net); uint16_t mg_ntohs(uint16_t net);
uint32_t mg_ntohl(uint32_t net); uint32_t mg_ntohl(uint32_t net);
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len); uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
char *mg_hexdump(const void *buf, size_t len); char *mg_hexdump(const void *buf, size_t len);
char *mg_hex(const void *buf, int len, char *dst); char *mg_hex(const void *buf, size_t len, char *dst);
void mg_unhex(const char *buf, int len, unsigned char *to); void mg_unhex(const char *buf, size_t len, unsigned char *to);
unsigned long mg_unhexn(const char *s, int len); unsigned long mg_unhexn(const char *s, size_t len);
int mg_asprintf(char **buf, size_t size, const char *fmt, ...); 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); int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
int64_t mg_to64(struct mg_str str); int64_t mg_to64(struct mg_str str);
@@ -604,7 +606,7 @@ enum {
MG_EV_CONNECT, // Connection established NULL MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL MG_EV_ACCEPT, // Connection accepted NULL
MG_EV_READ, // Data received from socket struct mg_str * MG_EV_READ, // Data received from socket struct mg_str *
MG_EV_WRITE, // Data written to socket int *num_bytes_written MG_EV_WRITE, // Data written to socket long *bytes_written
MG_EV_CLOSE, // Connection closed NULL MG_EV_CLOSE, // Connection closed NULL
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message * MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message * MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
@@ -686,7 +688,7 @@ struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data); mg_event_handler_t fn, void *fn_data);
struct mg_connection *mg_connect(struct mg_mgr *, const char *url, struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data); mg_event_handler_t fn, void *fn_data);
int mg_send(struct mg_connection *, const void *, size_t); bool mg_send(struct mg_connection *, const void *, size_t);
int mg_printf(struct mg_connection *, const char *fmt, ...); int mg_printf(struct mg_connection *, const char *fmt, ...);
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap); int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
char *mg_straddr(struct mg_connection *, char *, size_t); char *mg_straddr(struct mg_connection *, char *, size_t);
@@ -747,10 +749,10 @@ void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
const char *body_fmt, ...); const char *body_fmt, ...);
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
void mg_http_event_handler(struct mg_connection *c, int ev); void mg_http_event_handler(struct mg_connection *c, int ev);
int mg_http_get_var(const struct mg_str *, const char *name, char *, int); int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
int mg_url_encode(const char *s, size_t n, char *buf, size_t len); size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int); void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
bool mg_http_match_uri(const struct mg_http_message *, const char *glob); bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
int mg_http_upload(struct mg_connection *, struct mg_http_message *hm, int mg_http_upload(struct mg_connection *, struct mg_http_message *hm,
const char *dir); const char *dir);
@@ -772,11 +774,11 @@ struct mg_tls_opts {
struct mg_str srvname; // If not empty, enables server name verification struct mg_str srvname; // If not empty, enables server name verification
}; };
int mg_tls_init(struct mg_connection *, struct mg_tls_opts *); void mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
int mg_tls_free(struct mg_connection *); void mg_tls_free(struct mg_connection *);
int mg_tls_send(struct mg_connection *, const void *buf, size_t len, int *fail); long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
int mg_tls_recv(struct mg_connection *, void *buf, size_t len, int *fail); long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
int mg_tls_handshake(struct mg_connection *); void mg_tls_handshake(struct mg_connection *);
#define WEBSOCKET_OP_CONTINUE 0 #define WEBSOCKET_OP_CONTINUE 0
@@ -865,10 +867,10 @@ void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic);
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m); int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags, void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
uint32_t len); uint32_t len);
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos); uint8_t *qos, size_t pos);
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
int pos); size_t pos);
void mg_mqtt_ping(struct mg_connection *); void mg_mqtt_ping(struct mg_connection *);
void mg_mqtt_pong(struct mg_connection *); void mg_mqtt_pong(struct mg_connection *);
void mg_mqtt_disconnect(struct mg_connection *); void mg_mqtt_disconnect(struct mg_connection *);
+1
View File
@@ -42,6 +42,7 @@ typedef enum { false = 0, true = 1 } bool;
#define strdup(x) _strdup(x) #define strdup(x) _strdup(x)
#endif #endif
typedef unsigned suseconds_t;
typedef int socklen_t; typedef int socklen_t;
#define MG_DIRSEP '\\' #define MG_DIRSEP '\\'
#ifndef PATH_MAX #ifndef PATH_MAX
+9 -9
View File
@@ -33,14 +33,14 @@ static int mg_b64rev(int c) {
int mg_base64_update(unsigned char ch, char *to, int n) { int mg_base64_update(unsigned char ch, char *to, int n) {
unsigned char rem = (n & 3) % 3; unsigned char rem = (n & 3) % 3;
if (rem == 0) { if (rem == 0) {
to[n] = mg_b64idx(ch >> 2); to[n] = (char) mg_b64idx(ch >> 2);
to[++n] = (ch & 3) << 4; to[++n] = (char) ((ch & 3) << 4);
} else if (rem == 1) { } else if (rem == 1) {
to[n] = mg_b64idx(to[n] | (ch >> 4)); to[n] = (char) mg_b64idx(to[n] | (ch >> 4));
to[++n] = (ch & 15) << 2; to[++n] = (char) ((ch & 15) << 2);
} else { } else {
to[n] = mg_b64idx(to[n] | (ch >> 6)); to[n] = (char) mg_b64idx(to[n] | (ch >> 6));
to[++n] = mg_b64idx(ch & 63); to[++n] = (char) mg_b64idx(ch & 63);
n++; n++;
} }
return n; return n;
@@ -71,10 +71,10 @@ int mg_base64_decode(const char *src, int n, char *dst) {
int a = mg_b64rev(src[0]), b = mg_b64rev(src[1]), c = mg_b64rev(src[2]), int a = mg_b64rev(src[0]), b = mg_b64rev(src[1]), c = mg_b64rev(src[2]),
d = mg_b64rev(src[3]); d = mg_b64rev(src[3]);
if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0; if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) return 0;
dst[len++] = (a << 2) | (b >> 4); dst[len++] = (char) ((a << 2) | (b >> 4));
if (src[2] != '=') { if (src[2] != '=') {
dst[len++] = (b << 4) | (c >> 2); dst[len++] = (char) ((b << 4) | (c >> 2));
if (src[3] != '=') dst[len++] = (c << 6) | d; if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
} }
src += 4; src += 4;
} }
+5 -5
View File
@@ -81,15 +81,15 @@ size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
return 0; return 0;
s += rr->nlen + 4; s += rr->nlen + 4;
if (s > e) return 0; if (s > e) return 0;
rr->atype = ((uint16_t) s[-4] << 8) | s[-3]; rr->atype = (uint16_t)(((uint16_t) s[-4] << 8) | s[-3]);
rr->aclass = ((uint16_t) s[-2] << 8) | s[-1]; rr->aclass = (uint16_t)(((uint16_t) s[-2] << 8) | s[-1]);
if (is_question) return rr->nlen + 4; if (is_question) return rr->nlen + 4;
s += 6; s += 6;
if (s > e) return 0; if (s > e) return 0;
rr->alen = ((uint16_t) s[-2] << 8) | s[-1]; rr->alen = (uint16_t)(((uint16_t) s[-2] << 8) | s[-1]);
if (s + rr->alen > e) return 0; if (s + rr->alen > e) return 0;
return rr->nlen + rr->alen + 10; return (size_t)(rr->nlen + rr->alen + 10);
} }
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) { bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
@@ -247,7 +247,7 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
d->txnid = s_reqs ? s_reqs->txnid + 1 : 1; d->txnid = s_reqs ? s_reqs->txnid + 1 : 1;
d->next = s_reqs; d->next = s_reqs;
s_reqs = d; s_reqs = d;
d->expire = mg_millis() + ms; d->expire = mg_millis() + (unsigned long) ms;
d->c = c; d->c = c;
c->is_resolving = 1; c->is_resolving = 1;
LOG(LL_VERBOSE_DEBUG, LOG(LL_VERBOSE_DEBUG,
+1 -1
View File
@@ -13,7 +13,7 @@ enum {
MG_EV_CONNECT, // Connection established NULL MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL MG_EV_ACCEPT, // Connection accepted NULL
MG_EV_READ, // Data received from socket struct mg_str * MG_EV_READ, // Data received from socket struct mg_str *
MG_EV_WRITE, // Data written to socket int *num_bytes_written MG_EV_WRITE, // Data written to socket long *bytes_written
MG_EV_CLOSE, // Connection closed NULL MG_EV_CLOSE, // Connection closed NULL
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message * MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message * MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
+51 -42
View File
@@ -67,16 +67,20 @@ void mg_http_bauth(struct mg_connection *c, const char *user,
size_t need = c->send.len + 36 + (u.len + p.len) * 2; size_t need = c->send.len + 36 + (u.len + p.len) * 2;
if (c->send.size < need) mg_iobuf_resize(&c->send, need); if (c->send.size < need) mg_iobuf_resize(&c->send, need);
if (c->send.size >= need) { if (c->send.size >= need) {
size_t i, n = 0; int i, n = 0;
char *buf = (char *) &c->send.buf[c->send.len + 21]; char *buf = (char *) &c->send.buf[c->send.len + 21];
memcpy(&buf[-21], "Authorization: Basic ", 21); // DON'T use mg_send! memcpy(&buf[-21], "Authorization: Basic ", 21); // DON'T use mg_send!
for (i = 0; i < u.len; i++) n = mg_base64_update(u.ptr[i], buf, n); for (i = 0; i < (int) u.len; i++) {
n = mg_base64_update(((unsigned char *) u.ptr)[i], buf, n);
}
if (p.len > 0) { if (p.len > 0) {
n = mg_base64_update(':', buf, n); n = mg_base64_update(':', buf, n);
for (i = 0; i < p.len; i++) n = mg_base64_update(p.ptr[i], buf, n); for (i = 0; i < (int) p.len; i++) {
n = mg_base64_update(((unsigned char *) p.ptr)[i], buf, n);
}
} }
n = mg_base64_final(buf, n); n = mg_base64_final(buf, n);
c->send.len += 21 + n + 2; c->send.len += 21 + (size_t) n + 2;
memcpy(&c->send.buf[c->send.len - 2], "\r\n", 2); memcpy(&c->send.buf[c->send.len - 2], "\r\n", 2);
} else { } else {
LOG(LL_ERROR, ("%lu %s cannot resize iobuf %d->%d ", c->id, c->label, LOG(LL_ERROR, ("%lu %s cannot resize iobuf %d->%d ", c->id, c->label,
@@ -85,7 +89,7 @@ void mg_http_bauth(struct mg_connection *c, const char *user,
} }
int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst, int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
int dst_len) { size_t dst_len) {
const char *p, *e, *s; const char *p, *e, *s;
size_t name_len; size_t name_len;
int len; int len;
@@ -154,7 +158,7 @@ static const char *skip(const char *s, const char *e, const char *d,
struct mg_str *v) { struct mg_str *v) {
v->ptr = s; v->ptr = s;
while (s < e && *s != '\n' && strchr(d, *s) == NULL) s++; while (s < e && *s != '\n' && strchr(d, *s) == NULL) s++;
v->len = s - v->ptr; v->len = (size_t)(s - v->ptr);
while (s < e && strchr(d, *s) != NULL) s++; while (s < e && strchr(d, *s) != NULL) s++;
return s; return s;
} }
@@ -196,7 +200,7 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
hm->message.ptr = hm->head.ptr = s; hm->message.ptr = hm->head.ptr = s;
hm->body.ptr = end; hm->body.ptr = end;
hm->head.len = req_len; hm->head.len = (size_t) req_len;
hm->chunk.ptr = end; hm->chunk.ptr = end;
hm->message.len = hm->body.len = (size_t) ~0; // Set body length to infinite hm->message.len = hm->body.len = (size_t) ~0; // Set body length to infinite
@@ -211,15 +215,15 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
// If URI contains '?' character, setup query string // If URI contains '?' character, setup query string
if ((qs = (const char *) memchr(hm->uri.ptr, '?', hm->uri.len)) != NULL) { if ((qs = (const char *) memchr(hm->uri.ptr, '?', hm->uri.len)) != NULL) {
hm->query.ptr = qs + 1; hm->query.ptr = qs + 1;
hm->query.len = &hm->uri.ptr[hm->uri.len] - (qs + 1); hm->query.len = (size_t)(&hm->uri.ptr[hm->uri.len] - (qs + 1));
hm->uri.len = qs - hm->uri.ptr; hm->uri.len = (size_t)(qs - hm->uri.ptr);
} }
mg_http_parse_headers(s, end, hm->headers, mg_http_parse_headers(s, end, hm->headers,
sizeof(hm->headers) / sizeof(hm->headers[0])); sizeof(hm->headers) / sizeof(hm->headers[0]));
if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) { if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
hm->body.len = (size_t) mg_to64(*cl); hm->body.len = (size_t) mg_to64(*cl);
hm->message.len = req_len + hm->body.len; hm->message.len = (size_t) req_len + hm->body.len;
} }
// mg_http_parse() is used to parse both HTTP requests and HTTP // mg_http_parse() is used to parse both HTTP requests and HTTP
@@ -239,14 +243,14 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
mg_vcasecmp(&hm->method, "PUT") != 0 && mg_vcasecmp(&hm->method, "PUT") != 0 &&
mg_vcasecmp(&hm->method, "POST") != 0) { mg_vcasecmp(&hm->method, "POST") != 0) {
hm->body.len = 0; hm->body.len = 0;
hm->message.len = req_len; hm->message.len = (size_t) req_len;
} }
// The 204 (No content) responses also have 0 body length // The 204 (No content) responses also have 0 body length
if (hm->body.len == (size_t) ~0 && is_response && if (hm->body.len == (size_t) ~0 && is_response &&
mg_vcasecmp(&hm->uri, "204") == 0) { mg_vcasecmp(&hm->uri, "204") == 0) {
hm->body.len = 0; hm->body.len = 0;
hm->message.len = req_len; hm->message.len = (size_t) req_len;
} }
return req_len; return req_len;
@@ -257,7 +261,7 @@ static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
char mem[256], *buf = mem; char mem[256], *buf = mem;
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap); int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
mg_printf(c, "%X\r\n", len); mg_printf(c, "%X\r\n", len);
mg_send(c, buf, len); mg_send(c, buf, len > 0 ? (size_t) len : 0);
mg_send(c, "\r\n", 2); mg_send(c, "\r\n", 2);
if (buf != mem) free(buf); if (buf != mem) free(buf);
} }
@@ -356,7 +360,7 @@ void mg_http_reply(struct mg_connection *c, int code, const char *headers,
va_end(ap); va_end(ap);
mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: %d\r\n\r\n", code, mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: %d\r\n\r\n", code,
mg_http_status_code_str(code), headers == NULL ? "" : headers, len); mg_http_status_code_str(code), headers == NULL ? "" : headers, len);
mg_send(c, buf, len); mg_send(c, buf, len > 0 ? (size_t) len : 0);
if (buf != mem) free(buf); if (buf != mem) free(buf);
} }
@@ -395,7 +399,7 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
fwrite(hm->body.ptr, 1, hm->body.len, fp); fwrite(hm->body.ptr, 1, hm->body.len, fp);
fclose(fp); fclose(fp);
mg_http_reply(c, 200, "", ""); mg_http_reply(c, 200, "", "");
return hm->body.len; return (int) hm->body.len;
} }
} }
} }
@@ -480,9 +484,9 @@ static const char *guess_content_type(const char *filename) {
} }
static int getrange(struct mg_str *s, int64_t *a, int64_t *b) { static int getrange(struct mg_str *s, int64_t *a, int64_t *b) {
int i, numparsed = 0; size_t i, numparsed = 0;
LOG(LL_INFO, ("%.*s", (int) s->len, s->ptr)); LOG(LL_INFO, ("%.*s", (int) s->len, s->ptr));
for (i = 0; i + 6 < (int) s->len; i++) { for (i = 0; i + 6 < s->len; i++) {
if (memcmp(&s->ptr[i], "bytes=", 6) == 0) { if (memcmp(&s->ptr[i], "bytes=", 6) == 0) {
struct mg_str p = mg_str_n(s->ptr + i + 6, s->len - i - 6); struct mg_str p = mg_str_n(s->ptr + i + 6, s->len - i - 6);
if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++; if (p.len > 0 && p.ptr[0] >= '0' && p.ptr[0] <= '9') numparsed++;
@@ -496,7 +500,7 @@ static int getrange(struct mg_str *s, int64_t *a, int64_t *b) {
break; break;
} }
} }
return numparsed; return (int) numparsed;
} }
void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm, void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
@@ -516,7 +520,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n"); mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
} else { } else {
int n, status = 200; int n, status = 200;
char range[70] = ""; char range[100] = "";
int64_t r1 = 0, r2 = 0, cl = st.st_size; int64_t r1 = 0, r2 = 0, cl = st.st_size;
// Handle Range header // Handle Range header
@@ -539,7 +543,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
r1, r1 + cl - 1, (int64_t) st.st_size); r1, r1 + cl - 1, (int64_t) st.st_size);
#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \ #if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \
_XOPEN_SOURCE >= 600 _XOPEN_SOURCE >= 600
fseeko(fp, r1, SEEK_SET); fseeko(fp, (off_t) r1, SEEK_SET);
#else #else
fseek(fp, (long) r1, SEEK_SET); fseek(fp, (long) r1, SEEK_SET);
#endif #endif
@@ -716,7 +720,7 @@ static void printdirentry(struct mg_connection *c, const char *name,
} }
} }
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime_r(&stp->st_mtime, &t)); strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime_r(&stp->st_mtime, &t));
n = mg_url_encode(name, strlen(name), path, sizeof(path)); n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
mg_printf(c, mg_printf(c,
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>" " <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
"<td>%s</td><td>%s</td></tr>\n", "<td>%s</td><td>%s</td></tr>\n",
@@ -795,7 +799,9 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
"</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>" "</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
"</table><address>Mongoose v.%s</address></body></html>\n", "</table><address>Mongoose v.%s</address></body></html>\n",
MG_VERSION); MG_VERSION);
n = snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) (c->send.len - off)); n = (size_t) snprintf(tmp, sizeof(tmp), "%lu",
(unsigned long) (c->send.len - off));
if (n > sizeof(tmp)) n = 0;
memcpy(c->send.buf + off - 10, tmp, n); // Set content length memcpy(c->send.buf + off - 10, tmp, n); // Set content length
} else { } else {
mg_http_reply(c, 400, "", "Cannot open dir"); mg_http_reply(c, 400, "", "Cannot open dir");
@@ -848,7 +854,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
if (is_index && fp == NULL) { if (is_index && fp == NULL) {
char *p = t2 + strlen(t2); char *p = t2 + strlen(t2);
while (p > t2 && p[-1] != '/') p--; while (p > t2 && p[-1] != '/') p--;
strncpy(p, "index.shtml", &t2[sizeof(t2)] - p - 2); strncpy(p, "index.shtml", (size_t)(&t2[sizeof(t2)] - p - 2));
t2[sizeof(t2) - 1] = '\0'; t2[sizeof(t2) - 1] = '\0';
fp = mg_fopen(t2, "r"); fp = mg_fopen(t2, "r");
} }
@@ -881,7 +887,7 @@ static bool mg_is_url_safe(int c) {
(c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~'; (c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~';
} }
int mg_url_encode(const char *s, size_t sl, char *buf, size_t len) { size_t mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
size_t i, n = 0; size_t i, n = 0;
for (i = 0; i < sl; i++) { for (i = 0; i < sl; i++) {
int c = *(unsigned char *) &s[i]; int c = *(unsigned char *) &s[i];
@@ -897,14 +903,14 @@ int mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
return n; return n;
} }
void mg_http_creds(struct mg_http_message *hm, char *user, int userlen, void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
char *pass, int passlen) { char *pass, size_t passlen) {
struct mg_str *v = mg_http_get_header(hm, "Authorization"); struct mg_str *v = mg_http_get_header(hm, "Authorization");
user[0] = pass[0] = '\0'; user[0] = pass[0] = '\0';
if (v != NULL && v->len > 6 && memcmp(v->ptr, "Basic ", 6) == 0) { if (v != NULL && v->len > 6 && memcmp(v->ptr, "Basic ", 6) == 0) {
char buf[256]; char buf[256];
int n = mg_base64_decode(v->ptr + 6, (int) v->len - 6, buf); int n = mg_base64_decode(v->ptr + 6, (int) v->len - 6, buf);
const char *p = (const char *) memchr(buf, ':', n); const char *p = (const char *) memchr(buf, ':', n > 0 ? (size_t) n : 0);
if (p != NULL) { if (p != NULL) {
snprintf(user, userlen, "%.*s", (int) (p - buf), buf); snprintf(user, userlen, "%.*s", (int) (p - buf), buf);
snprintf(pass, passlen, "%.*s", n - (int) (p - buf) - 1, p + 1); snprintf(pass, passlen, "%.*s", n - (int) (p - buf) - 1, p + 1);
@@ -934,7 +940,7 @@ struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v) {
while (p < x && (q ? p == b || *p != '"' : *p != ';' && *p != ' ')) p++; while (p < x && (q ? p == b || *p != '"' : *p != ';' && *p != ' ')) p++;
// LOG(LL_INFO, ("[%.*s] [%.*s] [%.*s]", (int) s.len, s.ptr, (int) v.len, // LOG(LL_INFO, ("[%.*s] [%.*s] [%.*s]", (int) s.len, s.ptr, (int) v.len,
// v.ptr, (int) (p - b), b)); // v.ptr, (int) (p - b), b));
return stripquotes(mg_str_n(b, p - b + q)); return stripquotes(mg_str_n(b, (size_t)(p - b + q)));
} }
} }
return mg_str_n(NULL, 0); return mg_str_n(NULL, 0);
@@ -958,7 +964,7 @@ static size_t get_chunk_length(const char *buf, size_t len, size_t *ll) {
// Walk through all chunks in the chunked body. For each chunk, fire // Walk through all chunks in the chunked body. For each chunk, fire
// an MG_EV_HTTP_CHUNK event. // an MG_EV_HTTP_CHUNK event.
static void walkchunks(struct mg_connection *c, struct mg_http_message *hm, static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
int reqlen) { size_t reqlen) {
size_t off = 0, bl, ll; size_t off = 0, bl, ll;
while (off + reqlen < c->recv.len) { while (off + reqlen < c->recv.len) {
char *buf = (char *) &c->recv.buf[reqlen]; char *buf = (char *) &c->recv.buf[reqlen];
@@ -974,14 +980,14 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
// Zero chunk - last one. Prepare body - cut off chunk lengths // Zero chunk - last one. Prepare body - cut off chunk lengths
off = bl = 0; off = bl = 0;
while (off + reqlen < c->recv.len) { while (off + reqlen < c->recv.len) {
char *buf = (char *) &c->recv.buf[reqlen]; char *buf2 = (char *) &c->recv.buf[reqlen];
size_t memo = c->recv.len; size_t memo2 = c->recv.len;
size_t cl = get_chunk_length(&buf[off], memo - reqlen - off, &ll); size_t cl2 = get_chunk_length(&buf2[off], memo2 - reqlen - off, &ll);
size_t n = cl < ll + 2 ? 0 : cl - ll - 2; size_t n = cl < ll + 2 ? 0 : cl2 - ll - 2;
memmove(buf + bl, buf + off + ll, n); memmove(buf2 + bl, buf2 + off + ll, n);
bl += n; bl += n;
off += cl; off += cl2;
if (cl <= 5) break; if (cl2 <= 5) break;
} }
// LOG(LL_INFO, ("BL->%d del %d off %d", (int) bl, (int) del, (int) off)); // LOG(LL_INFO, ("BL->%d del %d off %d", (int) bl, (int) del, (int) off));
c->recv.len -= off - bl; c->recv.len -= off - bl;
@@ -1009,8 +1015,10 @@ void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm) {
} }
{ {
const char *end = &ch.ptr[ch.len]; const char *end = &ch.ptr[ch.len];
size_t n = end - (char *) c->recv.buf; size_t n = (size_t)(end - (char *) c->recv.buf);
if (c->recv.len > n) memmove((char *) ch.ptr, end, c->recv.len - n); if (c->recv.len > n) {
memmove((char *) ch.ptr, end, (size_t)(c->recv.len - n));
}
// LOG(LL_INFO, ("DELETING CHUNK: %zu %zu %zu\n%.*s", c->recv.len, n, // LOG(LL_INFO, ("DELETING CHUNK: %zu %zu %zu\n%.*s", c->recv.len, n,
// ch.len, (int) ch.len, ch.ptr)); // ch.len, (int) ch.len, ch.ptr));
} }
@@ -1025,9 +1033,9 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
bool is_chunked = n > 0 && mg_is_chunked(&hm); bool is_chunked = n > 0 && mg_is_chunked(&hm);
if (ev == MG_EV_CLOSE) { if (ev == MG_EV_CLOSE) {
hm.message.len = c->recv.len; hm.message.len = c->recv.len;
hm.body.len = hm.message.len - (hm.body.ptr - hm.message.ptr); hm.body.len = hm.message.len - (size_t)(hm.body.ptr - hm.message.ptr);
} else if (is_chunked) { } else if (is_chunked && n > 0) {
walkchunks(c, &hm, n); walkchunks(c, &hm, (size_t) n);
} }
// LOG(LL_INFO, // LOG(LL_INFO,
//("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len, c->recv.buf)); //("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len, c->recv.buf));
@@ -1039,7 +1047,8 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
mg_iobuf_delete(&c->recv, hm.message.len); mg_iobuf_delete(&c->recv, hm.message.len);
} else { } else {
if (n > 0 && !is_chunked) { if (n > 0 && !is_chunked) {
hm.chunk = mg_str_n((char *) &c->recv.buf[n], c->recv.len - n); hm.chunk =
mg_str_n((char *) &c->recv.buf[n], c->recv.len - (size_t) n);
mg_call(c, MG_EV_HTTP_CHUNK, &hm); mg_call(c, MG_EV_HTTP_CHUNK, &hm);
} }
break; break;
+3 -3
View File
@@ -52,10 +52,10 @@ void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
const char *body_fmt, ...); const char *body_fmt, ...);
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
void mg_http_event_handler(struct mg_connection *c, int ev); void mg_http_event_handler(struct mg_connection *c, int ev);
int mg_http_get_var(const struct mg_str *, const char *name, char *, int); int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
int mg_url_encode(const char *s, size_t n, char *buf, size_t len); size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int); void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
bool mg_http_match_uri(const struct mg_http_message *, const char *glob); bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
int mg_http_upload(struct mg_connection *, struct mg_http_message *hm, int mg_http_upload(struct mg_connection *, struct mg_http_message *hm,
const char *dir); const char *dir);
+8 -6
View File
@@ -4,13 +4,13 @@
#if MG_ENABLE_MGOS #if MG_ENABLE_MGOS
#else #else
#if MG_ENABLE_LOG #if MG_ENABLE_LOG
static void mg_log_stdout(const void *buf, int len, void *userdata) { static void mg_log_stdout(const void *buf, size_t len, void *userdata) {
(void) userdata; (void) userdata;
fwrite(buf, 1, len, stdout); fwrite(buf, 1, len, stdout);
} }
static const char *s_spec = "2"; static const char *s_spec = "2";
static void (*s_fn)(const void *, int, void *) = mg_log_stdout; static void (*s_fn)(const void *, size_t, void *) = mg_log_stdout;
static void *s_fn_param = NULL; static void *s_fn_param = NULL;
void mg_log_set(const char *spec) { void mg_log_set(const char *spec) {
@@ -23,10 +23,12 @@ bool mg_log_prefix(int level, const char *file, int line, const char *fname) {
int max = LL_INFO; int max = LL_INFO;
struct mg_str k, v, s = mg_str(s_spec); struct mg_str k, v, s = mg_str(s_spec);
const char *p = strrchr(file, '/'); const char *p = strrchr(file, '/');
if (s_fn == NULL) return false;
if (p == NULL) p = strrchr(file, '\\'); if (p == NULL) p = strrchr(file, '\\');
p = p == NULL ? file : p + 1; p = p == NULL ? file : p + 1;
if (s_fn == NULL) return false;
while (mg_next_comma_entry(&s, &k, &v)) { while (mg_next_comma_entry(&s, &k, &v)) {
if (v.len == 0) max = atoi(k.ptr); if (v.len == 0) max = atoi(k.ptr);
if (v.len > 0 && strncmp(p, k.ptr, k.len) == 0) max = atoi(v.ptr); if (v.len > 0 && strncmp(p, k.ptr, k.len) == 0) max = atoi(v.ptr);
@@ -57,14 +59,14 @@ void mg_log(const char *fmt, ...) {
va_start(ap, fmt); va_start(ap, fmt);
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap); len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
va_end(ap); va_end(ap);
s_fn(buf, len, s_fn_param); s_fn(buf, len > 0 ? (size_t) len : 0, s_fn_param);
s_fn("\n", 1, s_fn_param); s_fn("\n", 1, s_fn_param);
if (buf != mem) free(buf); if (buf != mem) free(buf);
} }
void mg_log_set_callback(void (*fn)(const void *, int, void *), void *param) { void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *fnd) {
s_fn = fn; s_fn = fn;
s_fn_param = param; s_fn_param = fnd;
} }
#endif #endif
#endif #endif
+1 -1
View File
@@ -12,7 +12,7 @@ enum { LL_NONE, LL_ERROR, LL_INFO, LL_DEBUG, LL_VERBOSE_DEBUG };
bool mg_log_prefix(int ll, const char *file, int line, const char *fname); bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2); void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
void mg_log_set(const char *spec); void mg_log_set(const char *spec);
void mg_log_set_callback(void (*fn)(const void *, int, void *), void *param); void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
#else #else
#define LOG(level, args) (void) 0 #define LOG(level, args) (void) 0
#define mg_log_set(x) (void) (x) #define mg_log_set(x) (void) (x)
+21 -20
View File
@@ -20,14 +20,14 @@ enum { MQTT_OK, MQTT_INCOMPLETE, MQTT_MALFORMED };
void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags, void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
uint32_t len) { uint32_t len) {
uint8_t buf[1 + sizeof(len)], *vlen = &buf[1]; uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
buf[0] = (cmd << 4) | flags; buf[0] = (uint8_t)((cmd << 4) | flags);
do { do {
*vlen = len % 0x80; *vlen = len % 0x80;
len /= 0x80; len /= 0x80;
if (len > 0) *vlen |= 0x80; if (len > 0) *vlen |= 0x80;
vlen++; vlen++;
} while (len > 0 && vlen < &buf[sizeof(buf)]); } while (len > 0 && vlen < &buf[sizeof(buf)]);
mg_send(c, buf, vlen - buf); mg_send(c, buf, (size_t)(vlen - buf));
} }
static void mg_send_u16(struct mg_connection *c, uint16_t value) { static void mg_send_u16(struct mg_connection *c, uint16_t value) {
@@ -37,7 +37,7 @@ static void mg_send_u16(struct mg_connection *c, uint16_t value) {
static void mqtt_login(struct mg_connection *c, const char *url, static void mqtt_login(struct mg_connection *c, const char *url,
struct mg_mqtt_opts *opts) { struct mg_mqtt_opts *opts) {
uint32_t total_len = 7 + 1 + 2 + 2; uint32_t total_len = 7 + 1 + 2 + 2;
uint16_t flags = (opts->qos & 3) << 3; uint16_t flags = (uint16_t)(((uint16_t) opts->qos & 3) << 3);
struct mg_str user = mg_url_user(url); struct mg_str user = mg_url_user(url);
struct mg_str pass = mg_url_pass(url); struct mg_str pass = mg_url_pass(url);
@@ -126,14 +126,14 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
p = (uint8_t *) buf + 1; p = (uint8_t *) buf + 1;
while ((size_t)(p - buf) < len) { while ((size_t)(p - buf) < len) {
lc = *((uint8_t *) p++); lc = *((uint8_t *) p++);
n += (lc & 0x7f) << 7 * len_len; n += (uint32_t)((lc & 0x7f) << 7 * len_len);
len_len++; len_len++;
if (!(lc & 0x80)) break; if (!(lc & 0x80)) break;
if (len_len >= 4) return MQTT_MALFORMED; if (len_len >= 4) return MQTT_MALFORMED;
} }
end = p + n; end = p + n;
if (lc & 0x80 || end > buf + len) return MQTT_INCOMPLETE; if (lc & 0x80 || end > buf + len) return MQTT_INCOMPLETE;
m->dgram.len = end - buf; m->dgram.len = (size_t)(end - buf);
switch (m->cmd) { switch (m->cmd) {
case MQTT_CMD_CONNACK: case MQTT_CMD_CONNACK:
@@ -146,28 +146,28 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
case MQTT_CMD_PUBCOMP: case MQTT_CMD_PUBCOMP:
case MQTT_CMD_SUBACK: case MQTT_CMD_SUBACK:
if (p + 2 > end) return MQTT_MALFORMED; if (p + 2 > end) return MQTT_MALFORMED;
m->id = (p[0] << 8) | p[1]; m->id = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
break; break;
case MQTT_CMD_SUBSCRIBE: { case MQTT_CMD_SUBSCRIBE: {
if (p + 2 > end) return MQTT_MALFORMED; if (p + 2 > end) return MQTT_MALFORMED;
m->id = (p[0] << 8) | p[1]; m->id = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
p += 2; p += 2;
break; break;
} }
case MQTT_CMD_PUBLISH: { case MQTT_CMD_PUBLISH: {
if (p + 2 > end) return MQTT_MALFORMED; if (p + 2 > end) return MQTT_MALFORMED;
m->topic.len = (p[0] << 8) | p[1]; m->topic.len = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
m->topic.ptr = (char *) p + 2; m->topic.ptr = (char *) p + 2;
p += 2 + m->topic.len; p += 2 + m->topic.len;
if (p > end) return MQTT_MALFORMED; if (p > end) return MQTT_MALFORMED;
if (m->qos > 0) { if (m->qos > 0) {
if (p + 2 > end) return MQTT_MALFORMED; if (p + 2 > end) return MQTT_MALFORMED;
m->id = (p[0] << 8) | p[1]; m->id = (uint16_t)((((uint16_t) p[0]) << 8) | p[1]);
p += 2; p += 2;
} }
if (p > end) return MQTT_MALFORMED; if (p > end) return MQTT_MALFORMED;
m->data.ptr = (char *) p; m->data.ptr = (char *) p;
m->data.len = end - p; m->data.len = (size_t)(end - p);
break; break;
} }
default: default:
@@ -176,28 +176,29 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
return MQTT_OK; return MQTT_OK;
} }
static int mg_mqtt_next_topic(struct mg_mqtt_message *msg, struct mg_str *topic, static size_t mg_mqtt_next_topic(struct mg_mqtt_message *msg,
uint8_t *qos, int pos) { struct mg_str *topic, uint8_t *qos,
size_t pos) {
unsigned char *buf = (unsigned char *) msg->dgram.ptr + pos; unsigned char *buf = (unsigned char *) msg->dgram.ptr + pos;
int new_pos; size_t new_pos;
if ((size_t) pos >= msg->dgram.len) return -1; if (pos >= msg->dgram.len) return 0;
topic->len = buf[0] << 8 | buf[1]; topic->len = (size_t)(((unsigned) buf[0]) << 8 | buf[1]);
topic->ptr = (char *) buf + 2; topic->ptr = (char *) buf + 2;
new_pos = pos + 2 + topic->len + (qos == NULL ? 0 : 1); new_pos = pos + 2 + topic->len + (qos == NULL ? 0 : 1);
if ((size_t) new_pos > msg->dgram.len) return -1; if ((size_t) new_pos > msg->dgram.len) return 0;
if (qos != NULL) *qos = buf[2 + topic->len]; if (qos != NULL) *qos = buf[2 + topic->len];
return new_pos; return new_pos;
} }
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos) { uint8_t *qos, size_t pos) {
uint8_t tmp; uint8_t tmp;
return mg_mqtt_next_topic(msg, topic, qos == NULL ? &tmp : qos, pos); return mg_mqtt_next_topic(msg, topic, qos == NULL ? &tmp : qos, pos);
} }
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
int pos) { size_t pos) {
return mg_mqtt_next_topic(msg, topic, NULL, pos); return mg_mqtt_next_topic(msg, topic, NULL, pos);
} }
+4 -4
View File
@@ -53,10 +53,10 @@ void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic);
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m); int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags, void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
uint32_t len); uint32_t len);
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos); uint8_t *qos, size_t pos);
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
int pos); size_t pos);
void mg_mqtt_ping(struct mg_connection *); void mg_mqtt_ping(struct mg_connection *);
void mg_mqtt_pong(struct mg_connection *); void mg_mqtt_pong(struct mg_connection *);
void mg_mqtt_disconnect(struct mg_connection *); void mg_mqtt_disconnect(struct mg_connection *);
+2 -2
View File
@@ -5,7 +5,7 @@
int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) { int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
char mem[256], *buf = mem; char mem[256], *buf = mem;
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap); int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
len = mg_send(c, buf, len); len = mg_send(c, buf, len > 0 ? (size_t) len : 0);
if (buf != mem) free(buf); if (buf != mem) free(buf);
return len; return len;
} }
@@ -56,7 +56,7 @@ static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
if (str.ptr[i] >= '0' && str.ptr[i] <= '9') { if (str.ptr[i] >= '0' && str.ptr[i] <= '9') {
int octet = data[num_dots] * 10 + (str.ptr[i] - '0'); int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
if (octet > 255) return false; if (octet > 255) return false;
data[num_dots] = octet; data[num_dots] = (uint8_t) octet;
} else if (str.ptr[i] == '.') { } else if (str.ptr[i] == '.') {
if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false; if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
num_dots++; num_dots++;
+1 -1
View File
@@ -67,7 +67,7 @@ struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data); mg_event_handler_t fn, void *fn_data);
struct mg_connection *mg_connect(struct mg_mgr *, const char *url, struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data); mg_event_handler_t fn, void *fn_data);
int mg_send(struct mg_connection *, const void *, size_t); bool mg_send(struct mg_connection *, const void *, size_t);
int mg_printf(struct mg_connection *, const char *fmt, ...); int mg_printf(struct mg_connection *, const char *fmt, ...);
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap); int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
char *mg_straddr(struct mg_connection *, char *, size_t); char *mg_straddr(struct mg_connection *, char *, size_t);
+3 -3
View File
@@ -22,8 +22,8 @@ int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
} else { } else {
uint32_t *data = (uint32_t *) &buf[40]; uint32_t *data = (uint32_t *) &buf[40];
tv->tv_sec = mg_ntohl(data[0]) - SNTP_TIME_OFFSET; tv->tv_sec = mg_ntohl(data[0]) - SNTP_TIME_OFFSET;
tv->tv_usec = mg_ntohl(data[1]); tv->tv_usec = (suseconds_t) mg_ntohl(data[1]);
s_sntmp_next = tv->tv_sec + SNTP_INTERVAL_SEC; s_sntmp_next = (unsigned long) (tv->tv_sec + SNTP_INTERVAL_SEC);
res = 0; res = 0;
} }
return res; return res;
@@ -39,7 +39,7 @@ static void sntp_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
} }
c->recv.len = 0; // Clear receive buffer c->recv.len = 0; // Clear receive buffer
} else if (ev == MG_EV_RESOLVE) { } else if (ev == MG_EV_RESOLVE) {
mg_sntp_send(c, time(NULL)); mg_sntp_send(c, (unsigned long) time(NULL));
} else if (ev == MG_EV_CLOSE) { } else if (ev == MG_EV_CLOSE) {
// mg_fn_del(c, sntp_cb); // mg_fn_del(c, sntp_cb);
} }
+103 -115
View File
@@ -73,19 +73,19 @@ static union usa tousa(struct mg_addr *a) {
return usa; return usa;
} }
static int mg_sock_failed(void) { static bool mg_sock_would_block(void) {
int err = MG_SOCK_ERRNO; int err = MG_SOCK_ERRNO;
return err != EINPROGRESS && err != EWOULDBLOCK return err == EINPROGRESS || err == EWOULDBLOCK
#ifndef WINCE #ifndef WINCE
&& err != EAGAIN && err != EINTR || err == EAGAIN || err == EINTR
#endif #endif
#if defined(_WIN32) && MG_ENABLE_WINSOCK #if defined(_WIN32) && MG_ENABLE_WINSOCK
&& err != WSAEINTR && err != WSAEWOULDBLOCK || err == WSAEINTR || err == WSAEWOULDBLOCK
#endif #endif
; ;
} }
static struct mg_connection *alloc_conn(struct mg_mgr *mgr, int is_client, static struct mg_connection *alloc_conn(struct mg_mgr *mgr, bool is_client,
SOCKET fd) { SOCKET fd) {
struct mg_connection *c = (struct mg_connection *) calloc(1, sizeof(*c)); struct mg_connection *c = (struct mg_connection *) calloc(1, sizeof(*c));
if (c != NULL) { if (c != NULL) {
@@ -97,37 +97,8 @@ static struct mg_connection *alloc_conn(struct mg_mgr *mgr, int is_client,
return c; return c;
} }
static int mg_sock_recv(struct mg_connection *c, void *buf, int len, static long mg_sock_send(struct mg_connection *c, const void *buf, size_t len) {
int *fail) { long n = 0;
int n = 0;
if (c->is_udp) {
union usa usa;
socklen_t slen = sizeof(usa.sin);
#if MG_ENABLE_IPV6
if (c->peer.is_ip6) slen = sizeof(usa.sin6);
#endif
n = recvfrom(FD(c), (char *) buf, len, 0, &usa.sa, &slen);
if (n > 0) {
if (c->peer.is_ip6) {
#if MG_ENABLE_IPV6
memcpy(c->peer.ip6, &usa.sin6.sin6_addr, sizeof(c->peer.ip6));
c->peer.port = usa.sin6.sin6_port;
#endif
} else {
c->peer.ip = *(uint32_t *) &usa.sin.sin_addr;
c->peer.port = usa.sin.sin_port;
}
}
} else {
n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING);
}
*fail = (n == 0) || (n < 0 && mg_sock_failed());
return n;
}
static int mg_sock_send(struct mg_connection *c, const void *buf, int len,
int *fail) {
int n = 0;
if (c->is_udp) { if (c->is_udp) {
union usa usa = tousa(&c->peer); union usa usa = tousa(&c->peer);
socklen_t slen = sizeof(usa.sin); socklen_t slen = sizeof(usa.sin);
@@ -138,47 +109,12 @@ static int mg_sock_send(struct mg_connection *c, const void *buf, int len,
} else { } else {
n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING); n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING);
} }
*fail = (n == 0) || (n < 0 && mg_sock_failed()); return n == 0 ? -1 : n < 0 && mg_sock_would_block() ? 0 : n;
return n;
} }
static int ll_read(struct mg_connection *c, void *buf, int len, int *fail) { bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
int n = c->is_tls ? mg_tls_recv(c, buf, len, fail) return c->is_udp ? mg_sock_send(c, buf, len) > 0
: mg_sock_recv(c, buf, len, fail); : mg_iobuf_append(&c->send, buf, len, MG_IO_SIZE);
LOG(*fail ? LL_DEBUG : LL_VERBOSE_DEBUG,
("%lu %c%c%c %d/%d %d %d", c->id, c->is_tls ? 'T' : 't',
c->is_udp ? 'U' : 'u', c->is_connecting ? 'C' : 'c', n, len,
MG_SOCK_ERRNO, *fail));
if (n > 0 && c->is_hexdumping) {
char *s = mg_hexdump(buf, n);
LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "<-", n, s));
free(s);
}
return n;
}
static int ll_write(struct mg_connection *c, const void *buf, int len,
int *fail) {
int n = c->is_tls ? mg_tls_send(c, buf, len, fail)
: mg_sock_send(c, buf, len, fail);
LOG(*fail ? LL_ERROR : LL_VERBOSE_DEBUG,
("%lu %c%c%c %d/%d %d", c->id, c->is_tls ? 'T' : 't',
c->is_udp ? 'U' : 'u', c->is_connecting ? 'C' : 'c', n, len,
MG_SOCK_ERRNO));
if (n > 0 && c->is_hexdumping) {
char *s = mg_hexdump(buf, len);
LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "->", len, s));
free(s);
}
return n;
}
int mg_send(struct mg_connection *c, const void *buf, size_t len) {
int fail, n = c->is_udp
? ll_write(c, buf, len, &fail)
: (int) mg_iobuf_append(&c->send, buf, len, MG_IO_SIZE);
if (len > 0 && n == 0) fail = 1;
return n;
} }
static void mg_set_non_blocking_mode(SOCKET fd) { static void mg_set_non_blocking_mode(SOCKET fd) {
@@ -246,40 +182,95 @@ SOCKET mg_open_listener(const char *url) {
return fd; return fd;
} }
static void read_conn(struct mg_connection *c, static long mg_sock_recv(struct mg_connection *c, void *buf, size_t len) {
int (*fn)(struct mg_connection *, void *, int, int *)) { long n = 0;
unsigned char *buf; if (c->is_udp) {
int rc, len, fail; union usa usa;
socklen_t slen = sizeof(usa.sin);
// NOTE(lsm): do only one iteration of reads, cause some systems #if MG_ENABLE_IPV6
// (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data if (c->peer.is_ip6) slen = sizeof(usa.sin6);
if (c->recv.size - c->recv.len < MG_IO_SIZE && #endif
c->recv.size < MG_MAX_RECV_BUF_SIZE && n = recvfrom(FD(c), (char *) buf, len, 0, &usa.sa, &slen);
!mg_iobuf_resize(&c->recv, c->recv.size + MG_IO_SIZE)) { if (n > 0) {
c->is_closing = 1; if (c->peer.is_ip6) {
} #if MG_ENABLE_IPV6
buf = c->recv.buf + c->recv.len; memcpy(c->peer.ip6, &usa.sin6.sin6_addr, sizeof(c->peer.ip6));
len = (int) (c->recv.size - c->recv.len); c->peer.port = usa.sin6.sin6_port;
rc = fn(c, buf, len, &fail); #endif
if (rc > 0) { } else {
struct mg_str evd = mg_str_n((char *) buf, rc); c->peer.ip = *(uint32_t *) &usa.sin.sin_addr;
c->recv.len += rc; c->peer.port = usa.sin.sin_port;
mg_call(c, MG_EV_READ, &evd); }
}
} else { } else {
if (fail) c->is_closing = 1; n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING);
}
return n == 0 ? -1 : n < 0 && mg_sock_would_block() ? 0 : n;
}
// NOTE(lsm): do only one iteration of reads, cause some systems
// (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data
static void read_conn(struct mg_connection *c) {
if (c->recv.len >= MG_MAX_RECV_BUF_SIZE) {
mg_error(c, "max_recv_buf_size reached");
} else if (c->recv.size - c->recv.len < MG_IO_SIZE &&
!mg_iobuf_resize(&c->recv, c->recv.size + MG_IO_SIZE)) {
mg_error(c, "oom");
} else {
char *buf = (char *) &c->recv.buf[c->recv.len];
size_t len = c->recv.size - c->recv.len;
long n = c->is_tls ? mg_tls_recv(c, buf, len) : mg_sock_recv(c, buf, len);
LOG(n > 0 ? LL_VERBOSE_DEBUG : LL_DEBUG,
("%-3lu %d%d%d%d%d%d%d%d%d%d%d%d%d%d %7ld %ld/%ld err %d", c->id,
c->is_listening, c->is_client, c->is_accepted, c->is_resolving,
c->is_connecting, c->is_tls, c->is_tls_hs, c->is_udp, c->is_websocket,
c->is_hexdumping, c->is_draining, c->is_closing, c->is_readable,
c->is_writable, (long) c->recv.len, n, (long) len, MG_SOCK_ERRNO));
if (n == 0) {
// Do nothing
} else if (n < 0) {
c->is_closing = 1; // Error, or normal termination
} else if (n > 0) {
struct mg_str evd = mg_str_n(buf, (size_t) n);
if (c->is_hexdumping) {
char *s = mg_hexdump(buf, (size_t) n);
LOG(LL_INFO, ("\n-- %lu %s %s %ld\n%s", c->id, c->label, "<-", n, s));
free(s);
}
c->recv.len += (size_t) n;
mg_call(c, MG_EV_READ, &evd);
}
} }
} }
static int write_conn(struct mg_connection *c) { static void write_conn(struct mg_connection *c) {
int fail, rc = ll_write(c, c->send.buf, c->send.len, &fail); char *buf = (char *) c->send.buf;
if (rc > 0) { size_t len = c->send.len;
mg_iobuf_delete(&c->send, rc); long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_sock_send(c, buf, len);
LOG(n > 0 ? LL_VERBOSE_DEBUG : LL_DEBUG,
("%-3lu %d%d%d%d%d%d%d%d%d%d%d%d%d%d %7ld %ld err %d", c->id,
c->is_listening, c->is_client, c->is_accepted, c->is_resolving,
c->is_connecting, c->is_tls, c->is_tls_hs, c->is_udp, c->is_websocket,
c->is_hexdumping, c->is_draining, c->is_closing, c->is_readable,
c->is_writable, (long) c->send.len, n, MG_SOCK_ERRNO));
if (n == 0) {
// Do nothing
} else if (n < 0) {
c->is_closing = 1; // Error, or normal termination
} else if (n > 0) {
// Hexdump before deleting
if (c->is_hexdumping) {
char *s = mg_hexdump(buf, (size_t) n);
LOG(LL_INFO, ("\n-- %lu %s %s %ld\n%s", c->id, c->label, "<-", n, s));
free(s);
}
mg_iobuf_delete(&c->send, (size_t) n);
if (c->send.len == 0) mg_iobuf_resize(&c->send, 0); if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
mg_call(c, MG_EV_WRITE, &rc); mg_call(c, MG_EV_WRITE, &n);
} else if (fail) { // if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
c->is_closing = 1;
} }
return rc;
} }
static void close_conn(struct mg_connection *c) { static void close_conn(struct mg_connection *c) {
@@ -334,7 +325,7 @@ static void setsockopts(struct mg_connection *c) {
void mg_connect_resolved(struct mg_connection *c) { void mg_connect_resolved(struct mg_connection *c) {
char buf[40]; char buf[40];
int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM; int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM;
int af = AF_INET; int rc, af = AF_INET;
#if MG_ENABLE_IPV6 #if MG_ENABLE_IPV6
if (c->peer.is_ip6) af = AF_INET6; if (c->peer.is_ip6) af = AF_INET6;
#endif #endif
@@ -349,19 +340,16 @@ void mg_connect_resolved(struct mg_connection *c) {
mg_call(c, MG_EV_RESOLVE, NULL); mg_call(c, MG_EV_RESOLVE, NULL);
if (type == SOCK_STREAM) { if (type == SOCK_STREAM) {
union usa usa = tousa(&c->peer); union usa usa = tousa(&c->peer);
socklen_t slen = socklen_t slen = sizeof(usa.sin);
#if MG_ENABLE_IPV6 #if MG_ENABLE_IPV6
c->peer.is_ip6 ? sizeof(usa.sin6) : if (c->peer.is_ip6) slen = sizeof(usa.sin6);
#endif #endif
sizeof(usa.sin); if ((rc = connect(FD(c), &usa.sa, slen)) == 0 || mg_sock_would_block()) {
int rc = connect(FD(c), &usa.sa, slen);
int fail = rc < 0 && mg_sock_failed() ? MG_SOCK_ERRNO : 0;
if (fail) {
mg_error(c, "connect: %d", MG_SOCK_ERRNO);
} else {
setsockopts(c); setsockopts(c);
if (rc != 0) c->is_connecting = 1;
} else {
mg_error(c, "connect: %d", MG_SOCK_ERRNO);
} }
if (rc < 0) c->is_connecting = 1;
} }
} }
@@ -469,7 +457,7 @@ bool mg_socketpair(int *s1, int *s2) {
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url, struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data) { mg_event_handler_t fn, void *fn_data) {
struct mg_connection *c = NULL; struct mg_connection *c = NULL;
int is_udp = strncmp(url, "udp:", 4) == 0; bool is_udp = strncmp(url, "udp:", 4) == 0;
SOCKET fd = mg_open_listener(url); SOCKET fd = mg_open_listener(url);
if (fd == INVALID_SOCKET) { if (fd == INVALID_SOCKET) {
} else if ((c = alloc_conn(mgr, 0, fd)) == NULL) { } else if ((c = alloc_conn(mgr, 0, fd)) == NULL) {
@@ -583,7 +571,7 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
} else if (c->is_tls_hs) { } else if (c->is_tls_hs) {
if ((c->is_readable || c->is_writable)) mg_tls_handshake(c); if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
} else { } else {
if (c->is_readable) read_conn(c, ll_read); if (c->is_readable) read_conn(c);
if (c->is_writable) write_conn(c); if (c->is_writable) write_conn(c);
} }
+4 -4
View File
@@ -16,7 +16,7 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
size_t len = 0, align = MG_IO_SIZE; size_t len = 0, align = MG_IO_SIZE;
while ((ch = fgetc(fp)) != EOF) { while ((ch = fgetc(fp)) != EOF) {
if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') { if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') {
buf[len++] = ch & 0xff; buf[len++] = (char) (ch & 0xff);
if (sscanf(buf, "<!--#include file=\"%[^\"]", arg)) { if (sscanf(buf, "<!--#include file=\"%[^\"]", arg)) {
char tmp[MG_PATH_MAX + BUFSIZ + 10], char tmp[MG_PATH_MAX + BUFSIZ + 10],
*p = (char *) path + strlen(path), *data; *p = (char *) path + strlen(path), *data;
@@ -50,7 +50,7 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
intag = 1; intag = 1;
if (len > 0) mg_iobuf_append(&b, buf, len, align); if (len > 0) mg_iobuf_append(&b, buf, len, align);
len = 0; len = 0;
buf[len++] = ch & 0xff; buf[len++] = (char) (ch & 0xff);
} else if (intag) { } else if (intag) {
if (len == 5 && strncmp(buf, "<!--#", 5) != 0) { if (len == 5 && strncmp(buf, "<!--#", 5) != 0) {
intag = 0; intag = 0;
@@ -58,9 +58,9 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
LOG(LL_ERROR, ("%s: SSI tag is too large", path)); LOG(LL_ERROR, ("%s: SSI tag is too large", path));
len = 0; len = 0;
} }
buf[len++] = ch & 0xff; buf[len++] = (char) (ch & 0xff);
} else { } else {
buf[len++] = ch & 0xff; buf[len++] = (char) (ch & 0xff);
if (len >= sizeof(buf)) { if (len >= sizeof(buf)) {
mg_iobuf_append(&b, buf, len, align); mg_iobuf_append(&b, buf, len, align);
len = 0; len = 0;
+2 -2
View File
@@ -6,8 +6,8 @@
struct mg_timer *g_timers; struct mg_timer *g_timers;
void mg_timer_init(struct mg_timer *t, int ms, int flags, void (*fn)(void *), void mg_timer_init(struct mg_timer *t, unsigned long ms, unsigned flags,
void *arg) { void (*fn)(void *), void *arg) {
struct mg_timer tmp = {ms, flags, fn, arg, 0UL, g_timers}; struct mg_timer tmp = {ms, flags, fn, arg, 0UL, g_timers};
*t = tmp; *t = tmp;
g_timers = t; g_timers = t;
+4 -3
View File
@@ -1,8 +1,8 @@
#pragma once #pragma once
struct mg_timer { struct mg_timer {
int period_ms; // Timer period in milliseconds unsigned long period_ms; // Timer period in milliseconds
int flags; // Possible flags values below unsigned flags; // Possible flags values below
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once #define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
void (*fn)(void *); // Function to call void (*fn)(void *); // Function to call
@@ -13,6 +13,7 @@ struct mg_timer {
extern struct mg_timer *g_timers; // Global list of timers extern struct mg_timer *g_timers; // Global list of timers
void mg_timer_init(struct mg_timer *, int ms, int, void (*fn)(void *), void *); void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
void (*fn)(void *), void *);
void mg_timer_free(struct mg_timer *); void mg_timer_free(struct mg_timer *);
void mg_timer_poll(unsigned long uptime_ms); void mg_timer_poll(unsigned long uptime_ms);
+33 -49
View File
@@ -29,7 +29,7 @@ struct mg_tls {
mbedtls_pk_context pk; // Private key context mbedtls_pk_context pk; // Private key context
}; };
int mg_tls_handshake(struct mg_connection *c) { void mg_tls_handshake(struct mg_connection *c) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
int rc; int rc;
mbedtls_ssl_set_bio(&tls->ssl, &c->fd, mbedtls_net_send, mbedtls_net_recv, 0); mbedtls_ssl_set_bio(&tls->ssl, &c->fd, mbedtls_net_send, mbedtls_net_recv, 0);
@@ -44,7 +44,6 @@ int mg_tls_handshake(struct mg_connection *c) {
} else { } else {
mg_error(c, "TLS handshake: -%#x", -rc); // Error mg_error(c, "TLS handshake: -%#x", -rc); // Error
} }
return rc == 0;
} }
static int mbed_rng(void *ctx, unsigned char *buf, size_t len) { static int mbed_rng(void *ctx, unsigned char *buf, size_t len) {
@@ -54,14 +53,14 @@ static int mbed_rng(void *ctx, unsigned char *buf, size_t len) {
} }
static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) { static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
n = strlen(s2) - 1; n = (int) strlen(s2) - 1;
LOG(LL_VERBOSE_DEBUG, ("%p %.*s", ((struct mg_connection *) c)->fd, n, s2)); LOG(LL_VERBOSE_DEBUG, ("%p %.*s", ((struct mg_connection *) c)->fd, n, s2));
(void) s; (void) s;
(void) c; (void) c;
(void) lev; (void) lev;
} }
int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) { void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls)); struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
int rc = 0; int rc = 0;
const char *ca = opts->ca == NULL ? "-" const char *ca = opts->ca == NULL ? "-"
@@ -164,31 +163,27 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) { if (c->is_client && c->is_resolving == 0 && c->is_connecting == 0) {
mg_tls_handshake(c); mg_tls_handshake(c);
} }
return 1; return;
fail: fail:
c->is_closing = 1; c->is_closing = 1;
free(tls); free(tls);
return 0;
} }
int mg_tls_recv(struct mg_connection *c, void *buf, size_t len, int *fail) { long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
int n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len); long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
*fail = (n == 0) || (n < 0 && n != MBEDTLS_ERR_SSL_WANT_READ); return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_READ ? 0 : n;
return n;
} }
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len, long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
int *fail) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
int n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len); long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
*fail = (n == 0) || (n < 0 && n != MBEDTLS_ERR_SSL_WANT_WRITE); return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_WRITE ? 0 : n;
return n;
} }
int mg_tls_free(struct mg_connection *c) { void mg_tls_free(struct mg_connection *c) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
if (tls == NULL) return 0; if (tls == NULL) return;
free(tls->cafile); free(tls->cafile);
mbedtls_ssl_free(&tls->ssl); mbedtls_ssl_free(&tls->ssl);
mbedtls_pk_free(&tls->pk); mbedtls_pk_free(&tls->pk);
@@ -197,7 +192,6 @@ int mg_tls_free(struct mg_connection *c) {
mbedtls_ssl_config_free(&tls->conf); mbedtls_ssl_config_free(&tls->conf);
free(tls); free(tls);
c->tls = NULL; c->tls = NULL;
return 1;
} }
#elif MG_ENABLE_OPENSSL ///////////////////////////////////////// OPENSSL #elif MG_ENABLE_OPENSSL ///////////////////////////////////////// OPENSSL
@@ -225,7 +219,7 @@ static int mg_tls_err(struct mg_tls *tls, int res) {
return err; return err;
} }
int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) { void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls)); struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
const char *id = "mongoose"; const char *id = "mongoose";
static unsigned char s_initialised = 0; static unsigned char s_initialised = 0;
@@ -250,7 +244,8 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
mg_error(c, "SSL_new"); mg_error(c, "SSL_new");
goto fail; goto fail;
} }
SSL_set_session_id_context(tls->ssl, (const uint8_t *) id, strlen(id)); SSL_set_session_id_context(tls->ssl, (const uint8_t *) id,
(unsigned) strlen(id));
// Disable deprecated protocols // Disable deprecated protocols
SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2); SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2);
SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3); SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3);
@@ -307,76 +302,65 @@ int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
} }
c->is_hexdumping = 1; c->is_hexdumping = 1;
LOG(LL_DEBUG, ("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client")); LOG(LL_DEBUG, ("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client"));
return 1; return;
fail: fail:
c->is_closing = 1; c->is_closing = 1;
free(tls); free(tls);
return 0;
} }
int mg_tls_handshake(struct mg_connection *c) { void mg_tls_handshake(struct mg_connection *c) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
int rc; int rc;
SSL_set_fd(tls->ssl, (long) c->fd); SSL_set_fd(tls->ssl, (int) (long) c->fd);
rc = c->is_client ? SSL_connect(tls->ssl) : SSL_accept(tls->ssl); rc = c->is_client ? SSL_connect(tls->ssl) : SSL_accept(tls->ssl);
if (rc == 1) { if (rc == 1) {
LOG(LL_DEBUG, ("%lu success", c->id)); LOG(LL_DEBUG, ("%lu success", c->id));
c->is_tls_hs = 0; c->is_tls_hs = 0;
return 1;
} else { } else {
int code; int code;
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
code = mg_tls_err(tls, rc); code = mg_tls_err(tls, rc);
if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code); if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);
return 0;
} }
} }
int mg_tls_free(struct mg_connection *c) { void mg_tls_free(struct mg_connection *c) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
if (tls == NULL) return 0; if (tls == NULL) return;
SSL_free(tls->ssl); SSL_free(tls->ssl);
SSL_CTX_free(tls->ctx); SSL_CTX_free(tls->ctx);
free(tls); free(tls);
c->tls = NULL; c->tls = NULL;
return 1;
} }
int mg_tls_recv(struct mg_connection *c, void *buf, size_t len, int *fail) { long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
int n = SSL_read(tls->ssl, buf, len); int n = SSL_read(tls->ssl, buf, (int) len);
*fail = (n == 0) || (n < 0 && mg_tls_err(tls, n) != 0); return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
return n;
} }
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len, long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
int *fail) {
struct mg_tls *tls = (struct mg_tls *) c->tls; struct mg_tls *tls = (struct mg_tls *) c->tls;
int n = SSL_write(tls->ssl, buf, len); int n = SSL_write(tls->ssl, buf, (int) len);
*fail = (n == 0) || (n < 0 && mg_tls_err(tls, n) != 0); return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
return n;
} }
#else ////////////////////////////////////////// NO TLS #else ////////////////////////////////////////// NO TLS
int mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) { void mg_tls_init(struct mg_connection *c, struct mg_tls_opts *opts) {
(void) opts; (void) opts;
mg_error(c, "TLS is not enabled"); mg_error(c, "TLS is not enabled");
return 0;
} }
int mg_tls_handshake(struct mg_connection *c) { void mg_tls_handshake(struct mg_connection *c) {
return c != NULL; (void) c;
} }
int mg_tls_free(struct mg_connection *c) { void mg_tls_free(struct mg_connection *c) {
return c != NULL; (void) c;
} }
int mg_tls_recv(struct mg_connection *c, void *buf, size_t len, int *fail) { long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
*fail = 1;
return c == NULL || buf == NULL || len == 0 ? 0 : -1; return c == NULL || buf == NULL || len == 0 ? 0 : -1;
} }
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len, long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
int *fail) {
*fail = 1;
return c == NULL || buf == NULL || len == 0 ? 0 : -1; return c == NULL || buf == NULL || len == 0 ? 0 : -1;
} }
+5 -5
View File
@@ -9,8 +9,8 @@ struct mg_tls_opts {
struct mg_str srvname; // If not empty, enables server name verification struct mg_str srvname; // If not empty, enables server name verification
}; };
int mg_tls_init(struct mg_connection *, struct mg_tls_opts *); void mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
int mg_tls_free(struct mg_connection *); void mg_tls_free(struct mg_connection *);
int mg_tls_send(struct mg_connection *, const void *buf, size_t len, int *fail); long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
int mg_tls_recv(struct mg_connection *, void *buf, size_t len, int *fail); long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
int mg_tls_handshake(struct mg_connection *); void mg_tls_handshake(struct mg_connection *);
+9 -8
View File
@@ -2,7 +2,7 @@
#include "url.h" #include "url.h"
struct url { struct url {
int key, user, pass, host, port, uri, end; size_t key, user, pass, host, port, uri, end;
}; };
int mg_url_is_ssl(const char *url) { int mg_url_is_ssl(const char *url) {
@@ -12,7 +12,7 @@ int mg_url_is_ssl(const char *url) {
} }
static struct url urlparse(const char *url) { static struct url urlparse(const char *url) {
int i; size_t i;
struct url u; struct url u;
memset(&u, 0, sizeof(u)); memset(&u, 0, sizeof(u));
for (i = 0; url[i] != '\0'; i++) { for (i = 0; url[i] != '\0'; i++) {
@@ -41,8 +41,9 @@ static struct url urlparse(const char *url) {
struct mg_str mg_url_host(const char *url) { struct mg_str mg_url_host(const char *url) {
struct url u = urlparse(url); struct url u = urlparse(url);
int n = size_t n = u.port ? u.port - u.host - 1
u.port ? u.port - u.host - 1 : u.uri ? u.uri - u.host : u.end - u.host; : u.uri ? u.uri - u.host
: u.end - u.host;
struct mg_str s = mg_str_n(url + u.host, n); struct mg_str s = mg_str_n(url + u.host, n);
if (s.len > 2 && s.ptr[0] == '[' && s.ptr[s.len - 1] == ']') { if (s.len > 2 && s.ptr[0] == '[' && s.ptr[s.len - 1] == ']') {
s.len -= 2; s.len -= 2;
@@ -63,7 +64,7 @@ unsigned short mg_url_port(const char *url) {
if (memcmp(url, "wss:", 4) == 0 || memcmp(url, "https:", 6) == 0) port = 443; if (memcmp(url, "wss:", 4) == 0 || memcmp(url, "https:", 6) == 0) port = 443;
if (memcmp(url, "mqtt:", 5) == 0) port = 1883; if (memcmp(url, "mqtt:", 5) == 0) port = 1883;
if (memcmp(url, "mqtts:", 6) == 0) port = 8883; if (memcmp(url, "mqtts:", 6) == 0) port = 8883;
if (u.port) port = atoi(url + u.port); if (u.port) port = (uint16_t) atoi(url + u.port);
return port; return port;
} }
@@ -71,7 +72,7 @@ struct mg_str mg_url_user(const char *url) {
struct url u = urlparse(url); struct url u = urlparse(url);
struct mg_str s = mg_str(""); struct mg_str s = mg_str("");
if (u.user && (u.pass || u.host)) { if (u.user && (u.pass || u.host)) {
int n = u.pass ? u.pass - u.user - 1 : u.host - u.user - 1; size_t n = u.pass ? u.pass - u.user - 1 : u.host - u.user - 1;
s = mg_str_n(url + u.user, n); s = mg_str_n(url + u.user, n);
} }
return s; return s;
@@ -79,9 +80,9 @@ struct mg_str mg_url_user(const char *url) {
struct mg_str mg_url_pass(const char *url) { struct mg_str mg_url_pass(const char *url) {
struct url u = urlparse(url); struct url u = urlparse(url);
struct mg_str s = mg_str(""); struct mg_str s = mg_str_n("", 0UL);
if (u.pass && u.host) { if (u.pass && u.host) {
int n = u.host - u.pass - 1; size_t n = u.host - u.pass - 1;
s = mg_str_n(url + u.pass, n); s = mg_str_n(url + u.pass, n);
} }
return s; return s;
+43 -37
View File
@@ -76,12 +76,12 @@ bool mg_file_write(const char *path, const void *buf, size_t len) {
bool mg_file_printf(const char *path, const char *fmt, ...) { bool mg_file_printf(const char *path, const char *fmt, ...) {
char tmp[256], *buf = tmp; char tmp[256], *buf = tmp;
bool result; bool result;
size_t len; int len;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
len = mg_vasprintf(&buf, sizeof(tmp), fmt, ap); len = mg_vasprintf(&buf, sizeof(tmp), fmt, ap);
va_end(ap); va_end(ap);
result = mg_file_write(path, buf, len); result = mg_file_write(path, buf, len > 0 ? (size_t) len : 0);
if (buf != tmp) free(buf); if (buf != tmp) free(buf);
return result; return result;
} }
@@ -99,12 +99,14 @@ void mg_random(void *buf, size_t len) {
if (!done) { if (!done) {
// Fallback to a pseudo random gen // Fallback to a pseudo random gen
size_t i; size_t i;
for (i = 0; i < len; i++) ((unsigned char *) buf)[i] = rand() % 0xff; for (i = 0; i < len; i++) {
((unsigned char *) buf)[i] = (unsigned char) (rand() % 0xff);
}
} }
} }
bool mg_globmatch(const char *s1, int n1, const char *s2, int n2) { bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) {
int i = 0, j = 0, ni = 0, nj = 0; size_t i = 0, j = 0, ni = 0, nj = 0;
while (i < n1 || j < n2) { while (i < n1 || j < n2) {
if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) { if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) {
i++, j++; i++, j++;
@@ -119,21 +121,22 @@ bool mg_globmatch(const char *s1, int n1, const char *s2, int n2) {
return true; return true;
} }
static int mg_nextcommaentry(const char *s, int slen, int ofs, int *koff, static size_t mg_nce(const char *s, size_t n, size_t ofs, size_t *koff,
int *klen, int *voff, int *vlen) { size_t *klen, size_t *voff, size_t *vlen) {
int kvlen, kl; size_t kvlen, kl;
for (kvlen = 0; ofs + kvlen < slen && s[ofs + kvlen] != ',';) kvlen++; for (kvlen = 0; ofs + kvlen < n && s[ofs + kvlen] != ',';) kvlen++;
for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++; for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++;
if (koff != NULL) *koff = ofs; if (koff != NULL) *koff = ofs;
if (klen != NULL) *klen = kl; if (klen != NULL) *klen = kl;
if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0; if (voff != NULL) *voff = kl < kvlen ? ofs + kl + 1 : 0;
if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0; if (vlen != NULL) *vlen = kl < kvlen ? kvlen - kl - 1 : 0;
return ofs >= slen ? slen : ofs + kvlen + 1; ofs += kvlen + 1;
return ofs > n ? n : ofs;
} }
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v) { bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v) {
int koff, klen, voff, vlen; size_t koff = 0, klen = 0, voff = 0, vlen = 0;
int off = mg_nextcommaentry(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen); size_t off = mg_nce(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen);
if (k != NULL) *k = mg_str_n(s->ptr + koff, klen); if (k != NULL) *k = mg_str_n(s->ptr + koff, klen);
if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen); if (v != NULL) *v = mg_str_n(s->ptr + voff, vlen);
*s = mg_str_n(s->ptr + off, s->len - off); *s = mg_str_n(s->ptr + off, s->len - off);
@@ -143,14 +146,14 @@ bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v) {
uint32_t mg_ntohl(uint32_t net) { uint32_t mg_ntohl(uint32_t net) {
uint8_t data[4] = {0, 0, 0, 0}; uint8_t data[4] = {0, 0, 0, 0};
memcpy(&data, &net, sizeof(data)); memcpy(&data, &net, sizeof(data));
return ((uint32_t) data[3] << 0) | ((uint32_t) data[2] << 8) | return (((uint32_t) data[3]) << 0) | (((uint32_t) data[2]) << 8) |
((uint32_t) data[1] << 16) | ((uint32_t) data[0] << 24); (((uint32_t) data[1]) << 16) | (((uint32_t) data[0]) << 24);
} }
uint16_t mg_ntohs(uint16_t net) { uint16_t mg_ntohs(uint16_t net) {
uint8_t data[2] = {0, 0}; uint8_t data[2] = {0, 0};
memcpy(&data, &net, sizeof(data)); memcpy(&data, &net, sizeof(data));
return ((uint16_t) data[1] << 0) | ((uint32_t) data[0] << 8); return (uint16_t)((uint16_t) data[1] | (((uint16_t) data[0]) << 8));
} }
char *mg_hexdump(const void *buf, size_t len) { char *mg_hexdump(const void *buf, size_t len) {
@@ -161,27 +164,29 @@ char *mg_hexdump(const void *buf, size_t len) {
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
idx = i % 16; idx = i % 16;
if (idx == 0) { if (idx == 0) {
if (i > 0 && dlen > n) n += snprintf(dst + n, dlen - n, " %s\n", ascii); if (i > 0 && dlen > n)
if (dlen > n) n += snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs)); n += (size_t) snprintf(dst + n, dlen - n, " %s\n", ascii);
if (dlen > n)
n += (size_t) snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs));
} }
if (dlen < n) break; if (dlen < n) break;
n += snprintf(dst + n, dlen - n, " %02x", p[i]); n += (size_t) snprintf(dst + n, dlen - n, " %02x", p[i]);
ascii[idx] = p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]; ascii[idx] = (char) (p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]);
ascii[idx + 1] = '\0'; ascii[idx + 1] = '\0';
} }
while (i++ % 16) { while (i++ % 16) {
if (n < dlen) n += snprintf(dst + n, dlen - n, "%s", " "); if (n < dlen) n += (size_t) snprintf(dst + n, dlen - n, "%s", " ");
} }
if (n < dlen) n += snprintf(dst + n, dlen - n, " %s\n", ascii); if (n < dlen) n += (size_t) snprintf(dst + n, dlen - n, " %s\n", ascii);
if (n > dlen - 1) n = dlen - 1; if (n > dlen - 1) n = dlen - 1;
dst[n] = '\0'; dst[n] = '\0';
return dst; return dst;
} }
char *mg_hex(const void *buf, int len, char *to) { char *mg_hex(const void *buf, size_t len, char *to) {
const unsigned char *p = (const unsigned char *) buf; const unsigned char *p = (const unsigned char *) buf;
static const char *hex = "0123456789abcdef"; static const char *hex = "0123456789abcdef";
int i = 0; size_t i = 0;
for (; len--; p++) { for (; len--; p++) {
to[i++] = hex[p[0] >> 4]; to[i++] = hex[p[0] >> 4];
to[i++] = hex[p[0] & 0x0f]; to[i++] = hex[p[0] & 0x0f];
@@ -190,20 +195,20 @@ char *mg_hex(const void *buf, int len, char *to) {
return to; return to;
} }
unsigned long mg_unhexn(const char *s, int len) { static unsigned char mg_unhex_nimble(unsigned char c) {
return (c >= '0' && c <= '9') ? (unsigned char) (c - '0')
: (c >= 'A' && c <= 'F') ? (unsigned char) (c - '7')
: (unsigned char) (c - 'W');
}
unsigned long mg_unhexn(const char *s, size_t len) {
unsigned long i = 0, v = 0; unsigned long i = 0, v = 0;
for (i = 0; i < (unsigned long) len; i++) { for (i = 0; i < len; i++) v <<= 4, v |= mg_unhex_nimble(((uint8_t *) s)[i]);
int c = s[i];
if (i > 0) v <<= 4;
v |= (c >= '0' && c <= '9') ? c - '0'
: (c >= 'A' && c <= 'F') ? c - '7'
: c - 'W';
}
return v; return v;
} }
void mg_unhex(const char *buf, int len, unsigned char *to) { void mg_unhex(const char *buf, size_t len, unsigned char *to) {
int i; size_t i;
for (i = 0; i < len; i += 2) { for (i = 0; i < len; i += 2) {
to[i >> 1] = (unsigned char) mg_unhexn(&buf[i], 2); to[i >> 1] = (unsigned char) mg_unhexn(&buf[i], 2);
} }
@@ -241,11 +246,11 @@ int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap) {
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} else if (len >= (int) size) { } else if (len >= (int) size) {
/// Standard-compliant code path. Allocate a buffer that is large enough /// Standard-compliant code path. Allocate a buffer that is large enough
if ((*buf = (char *) calloc(1, len + 1)) == NULL) { if ((*buf = (char *) calloc(1, (size_t) len + 1)) == NULL) {
len = -1; // LCOV_EXCL_LINE len = -1; // LCOV_EXCL_LINE
} else { // LCOV_EXCL_LINE } else { // LCOV_EXCL_LINE
va_copy(ap_copy, ap); va_copy(ap_copy, ap);
len = vsnprintf(*buf, len + 1, fmt, ap_copy); len = vsnprintf(*buf, (size_t) len + 1, fmt, ap_copy);
va_end(ap_copy); va_end(ap_copy);
} }
} }
@@ -321,7 +326,7 @@ void mg_usleep(unsigned long usecs) {
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP #elif MG_ARCH == MG_ARCH_FREERTOS_TCP
vTaskDelay(pdMS_TO_TICKS(usecs / 1000)); vTaskDelay(pdMS_TO_TICKS(usecs / 1000));
#else #else
usleep(usecs); usleep((useconds_t) usecs);
#endif #endif
} }
@@ -337,6 +342,7 @@ unsigned long mg_millis(void) {
#else #else
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
return (unsigned long) ((uint64_t) ts.tv_sec * 1000 + ts.tv_nsec / 1000000); return (unsigned long) ((uint64_t) ts.tv_sec * 1000 +
(uint64_t) ts.tv_nsec / 1000000);
#endif #endif
} }
+4 -4
View File
@@ -21,15 +21,15 @@ int64_t mg_file_size(const char *path);
bool mg_file_write(const char *path, const void *buf, size_t len); bool mg_file_write(const char *path, const void *buf, size_t len);
bool mg_file_printf(const char *path, const char *fmt, ...); bool mg_file_printf(const char *path, const char *fmt, ...);
void mg_random(void *buf, size_t len) WEAK; void mg_random(void *buf, size_t len) WEAK;
bool mg_globmatch(const char *pattern, int plen, const char *s, int n); bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v); bool mg_next_comma_entry(struct mg_str *s, struct mg_str *k, struct mg_str *v);
uint16_t mg_ntohs(uint16_t net); uint16_t mg_ntohs(uint16_t net);
uint32_t mg_ntohl(uint32_t net); uint32_t mg_ntohl(uint32_t net);
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len); uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
char *mg_hexdump(const void *buf, size_t len); char *mg_hexdump(const void *buf, size_t len);
char *mg_hex(const void *buf, int len, char *dst); char *mg_hex(const void *buf, size_t len, char *dst);
void mg_unhex(const char *buf, int len, unsigned char *to); void mg_unhex(const char *buf, size_t len, unsigned char *to);
unsigned long mg_unhexn(const char *s, int len); unsigned long mg_unhexn(const char *s, size_t len);
int mg_asprintf(char **buf, size_t size, const char *fmt, ...); 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); int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
int64_t mg_to64(struct mg_str str); int64_t mg_to64(struct mg_str str);
+3 -3
View File
@@ -54,7 +54,7 @@ static size_t ws_process(uint8_t *buf, size_t len, struct ws_msg *msg) {
} else if (len >= 10 + mask_len) { } else if (len >= 10 + mask_len) {
msg->header_len = 10 + mask_len; msg->header_len = 10 + mask_len;
msg->data_len = msg->data_len =
(int) (((uint64_t) mg_ntohl(*(uint32_t *) &buf[2])) << 32) + (size_t)(((uint64_t) mg_ntohl(*(uint32_t *) &buf[2])) << 32) +
mg_ntohl(*(uint32_t *) &buf[6]); mg_ntohl(*(uint32_t *) &buf[6]);
} }
} }
@@ -124,7 +124,7 @@ static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
c->is_websocket = 1; c->is_websocket = 1;
mg_call(c, MG_EV_WS_OPEN, &hm); mg_call(c, MG_EV_WS_OPEN, &hm);
} }
mg_iobuf_delete(&c->recv, n); mg_iobuf_delete(&c->recv, (size_t) n);
} else { } else {
return; // A request is not yet received return; // A request is not yet received
} }
@@ -188,7 +188,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
"Sec-WebSocket-Key: %s\r\n" "Sec-WebSocket-Key: %s\r\n"
"\r\n", "\r\n",
mg_url_uri(url), (int) host.len, host.ptr, n1, buf1, key); mg_url_uri(url), (int) host.len, host.ptr, n1, buf1, key);
mg_send(c, buf2, n2); mg_send(c, buf2, n2 > 0 ? (size_t) n2 : 0);
if (buf1 != mem1) free(buf1); if (buf1 != mem1) free(buf1);
if (buf2 != mem2) free(buf2); if (buf2 != mem2) free(buf2);
c->pfn = mg_ws_cb; c->pfn = mg_ws_cb;
+22
View File
@@ -0,0 +1,22 @@
// Required by the test ARM build
#pragma once
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
int clock_gettime(clockid_t clock_id, struct timespec *tp);
#define MG_DIRSEP '/'
#define MG_INT64_FMT "%lld"
#define MG_PATH_MAX 100
#define MG_ENABLE_SOCKET 0
+28 -29
View File
@@ -249,11 +249,11 @@ static void test_sntp(void) {
"\xc9\xd6\xa2\xdb\xde\xea\x30\x91\x86\xb7\x10\xdb\xde" "\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" "\xed\x98\x00\x00\x00\xde\xdb\xde\xed\x99\x0a\xe2\xc7"
"\x96\xdb\xde\xed\x99\x0a\xe4\x6b\xda"; "\x96\xdb\xde\xed\x99\x0a\xe4\x6b\xda";
struct timeval tv = {0, 0}; struct timeval tv2 = {0, 0};
struct tm *tm; struct tm *tm;
time_t t; time_t t;
ASSERT(mg_sntp_parse(sntp_good, sizeof(sntp_good), &tv) == 0); ASSERT(mg_sntp_parse(sntp_good, sizeof(sntp_good), &tv2) == 0);
t = tv.tv_sec; t = tv2.tv_sec;
tm = gmtime(&t); tm = gmtime(&t);
ASSERT(tm->tm_year == 116); ASSERT(tm->tm_year == 116);
ASSERT(tm->tm_mon == 10); ASSERT(tm->tm_mon == 10);
@@ -261,7 +261,7 @@ static void test_sntp(void) {
ASSERT(tm->tm_hour == 16); ASSERT(tm->tm_hour == 16);
ASSERT(tm->tm_min == 15); ASSERT(tm->tm_min == 15);
ASSERT(tm->tm_sec == 21); ASSERT(tm->tm_sec == 21);
ASSERT(mg_sntp_parse(bad_good, sizeof(bad_good), &tv) == -1); ASSERT(mg_sntp_parse(bad_good, sizeof(bad_good), &tv2) == -1);
} }
ASSERT(mg_sntp_parse(NULL, 0, &tv) == -1); ASSERT(mg_sntp_parse(NULL, 0, &tv) == -1);
@@ -329,8 +329,8 @@ static void test_mqtt(void) {
} }
static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_tls_opts *opts = (struct mg_tls_opts *) fn_data; struct mg_tls_opts *topts = (struct mg_tls_opts *) fn_data;
if (ev == MG_EV_ACCEPT && opts != NULL) mg_tls_init(c, opts); if (ev == MG_EV_ACCEPT && topts != NULL) mg_tls_init(c, topts);
if (ev == MG_EV_HTTP_MSG) { if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct mg_http_message *hm = (struct mg_http_message *) ev_data;
LOG(LL_INFO, LOG(LL_INFO,
@@ -345,8 +345,8 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
} else if (mg_http_match_uri(hm, "/bar")) { } else if (mg_http_match_uri(hm, "/bar")) {
mg_http_reply(c, 404, "", "not found"); mg_http_reply(c, 404, "", "not found");
} else if (mg_http_match_uri(hm, "/badroot")) { } else if (mg_http_match_uri(hm, "/badroot")) {
struct mg_http_serve_opts opts = {"/BAAADDD!", NULL, NULL}; struct mg_http_serve_opts sopts = {"/BAAADDD!", NULL, NULL};
mg_http_serve_dir(c, hm, &opts); mg_http_serve_dir(c, hm, &sopts);
} else if (mg_http_match_uri(hm, "/creds")) { } else if (mg_http_match_uri(hm, "/creds")) {
char user[100], pass[100]; char user[100], pass[100];
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass)); mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
@@ -354,11 +354,11 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
} else if (mg_http_match_uri(hm, "/upload")) { } else if (mg_http_match_uri(hm, "/upload")) {
mg_http_upload(c, hm, "."); mg_http_upload(c, hm, ".");
} else if (mg_http_match_uri(hm, "/test/")) { } else if (mg_http_match_uri(hm, "/test/")) {
struct mg_http_serve_opts opts = {".", NULL, "A: B\r\nC: D\r\n"}; struct mg_http_serve_opts sopts = {".", NULL, "A: B\r\nC: D\r\n"};
mg_http_serve_dir(c, hm, &opts); mg_http_serve_dir(c, hm, &sopts);
} else { } else {
struct mg_http_serve_opts opts = {"./test/data", "#.shtml", "C: D\r\n"}; struct mg_http_serve_opts sopts = {"./test/data", "#.shtml", "C: D\r\n"};
mg_http_serve_dir(c, hm, &opts); mg_http_serve_dir(c, hm, &sopts);
} }
} else if (ev == MG_EV_WS_MSG) { } else if (ev == MG_EV_WS_MSG) {
struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; struct mg_ws_message *wm = (struct mg_ws_message *) ev_data;
@@ -851,20 +851,20 @@ static void test_http_parse(void) {
{ {
struct mg_http_message hm; struct mg_http_message hm;
const char *req = "GET /foo?bar=baz HTTP/1.0\n\n "; const char *s = "GET /foo?bar=baz HTTP/1.0\n\n ";
ASSERT(mg_http_parse(req, strlen(req), &hm) == (int) strlen(req) - 1); ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s) - 1);
ASSERT(mg_strcmp(hm.uri, mg_str("/foo")) == 0); ASSERT(mg_strcmp(hm.uri, mg_str("/foo")) == 0);
ASSERT(mg_strcmp(hm.query, mg_str("bar=baz")) == 0); ASSERT(mg_strcmp(hm.query, mg_str("bar=baz")) == 0);
} }
{ {
struct mg_http_message hm; struct mg_http_message hm;
const char *req = "a b c\n\n"; const char *s = "a b c\n\n";
ASSERT(mg_http_parse(req, strlen(req), &hm) == (int) strlen(req)); ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s));
req = "a b\nc\n\n"; s = "a b\nc\n\n";
ASSERT(mg_http_parse(req, strlen(req), &hm) < 0); ASSERT(mg_http_parse(s, strlen(s), &hm) < 0);
req = "a\nb\nc\n\n"; s = "a\nb\nc\n\n";
ASSERT(mg_http_parse(req, strlen(req), &hm) < 0); ASSERT(mg_http_parse(s, strlen(s), &hm) < 0);
} }
} }
@@ -1142,8 +1142,7 @@ static void test_util(void) {
ASSERT(mg_url_decode("&&&a=%", 6, buf, sizeof(buf), 0) < 0); ASSERT(mg_url_decode("&&&a=%", 6, buf, sizeof(buf), 0) < 0);
{ {
char buf[100]; size_t n;
int n;
ASSERT((n = mg_url_encode("", 0, buf, sizeof(buf))) == 0); ASSERT((n = mg_url_encode("", 0, buf, sizeof(buf))) == 0);
ASSERT((n = mg_url_encode("a", 1, buf, 0)) == 0); ASSERT((n = mg_url_encode("a", 1, buf, 0)) == 0);
ASSERT((n = mg_url_encode("a", 1, buf, sizeof(buf))) == 1); ASSERT((n = mg_url_encode("a", 1, buf, sizeof(buf))) == 1);
@@ -1157,7 +1156,7 @@ static void test_util(void) {
} }
{ {
char buf[100], *s = buf; s = buf;
mg_asprintf(&s, sizeof(buf), "%s", "%3d", 123); mg_asprintf(&s, sizeof(buf), "%s", "%3d", 123);
ASSERT(s == buf); ASSERT(s == buf);
ASSERT(strcmp(buf, "%3d") == 0); ASSERT(strcmp(buf, "%3d") == 0);
@@ -1213,37 +1212,37 @@ static void eh3(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
// Streaming client event handler. Make sure we've got all chunks // Streaming client event handler. Make sure we've got all chunks
static void eh4(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { static void eh4(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
uint32_t *crc = (uint32_t *) c->label;
if (ev == MG_EV_CONNECT) { if (ev == MG_EV_CONNECT) {
mg_printf(c, "GET / HTTP/1.0\n\n"); mg_printf(c, "GET / HTTP/1.0\n\n");
} else if (ev == MG_EV_HTTP_CHUNK) { } else if (ev == MG_EV_HTTP_CHUNK) {
uint32_t *crc = (uint32_t *) c->label;
struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct mg_http_message *hm = (struct mg_http_message *) ev_data;
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len); *crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
} else if (ev == MG_EV_HTTP_MSG) { } else if (ev == MG_EV_HTTP_MSG) {
uint32_t *crc = (uint32_t *) c->label;
struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct mg_http_message *hm = (struct mg_http_message *) ev_data;
*crc = mg_crc32(*crc, hm->body.ptr, hm->body.len);
// LOG(LL_INFO, ("MSG [%.*s]", (int) hm->body.len, hm->body.ptr)); // LOG(LL_INFO, ("MSG [%.*s]", (int) hm->body.len, hm->body.ptr));
c->is_closing = 1; c->is_closing = 1;
*(int *) fn_data = mg_crc32(*crc, hm->body.ptr, hm->body.len); *(uint32_t *) fn_data = *crc;
} }
(void) ev_data; (void) ev_data;
} }
// Streaming client event handler. Delete chunks as they arrive // Streaming client event handler. Delete chunks as they arrive
static void eh5(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { static void eh5(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
uint32_t *crc = (uint32_t *) c->label;
if (ev == MG_EV_CONNECT) { if (ev == MG_EV_CONNECT) {
mg_printf(c, "GET / HTTP/1.0\n\n"); mg_printf(c, "GET / HTTP/1.0\n\n");
} else if (ev == MG_EV_HTTP_CHUNK) { } else if (ev == MG_EV_HTTP_CHUNK) {
uint32_t *crc = (uint32_t *) c->label;
struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct mg_http_message *hm = (struct mg_http_message *) ev_data;
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len); *crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
// LOG(LL_INFO, ("CHUNK [%.*s]", (int) hm->chunk.len, hm->chunk.ptr)); // LOG(LL_INFO, ("CHUNK [%.*s]", (int) hm->chunk.len, hm->chunk.ptr));
mg_http_delete_chunk(c, hm); mg_http_delete_chunk(c, hm);
} else if (ev == MG_EV_HTTP_MSG) { } else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct mg_http_message *hm = (struct mg_http_message *) ev_data;
uint32_t *crc = (uint32_t *) c->label; *crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
c->is_closing = 1; c->is_closing = 1;
*(int *) fn_data = mg_crc32(*crc, hm->body.ptr, hm->body.len); *(uint32_t *) fn_data = *crc;
// LOG(LL_INFO, ("MSG [%.*s]", (int) hm->body.len, hm->body.ptr)); // LOG(LL_INFO, ("MSG [%.*s]", (int) hm->body.len, hm->body.ptr));
} }
(void) ev_data; (void) ev_data;