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

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

View File

@ -37,4 +37,9 @@ jobs:
run: make mingw
- name: mingw++
run: make mingw++
arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: arm
run: make arm

View File

@ -1,13 +1,17 @@
SRCS = $(wildcard src/*.c)
HDRS = $(wildcard src/*.h)
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
CDIR ?= $(realpath $(CURDIR))
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
MINGW = docker run --rm -v $(CDIR):$(CDIR) -w $(CDIR) docker.io/mdashnet/mingw
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)
CLANG ?= clang # /usr/local/opt/llvm\@9/bin/clang
IPV6 ?= 1
@ -95,6 +99,9 @@ linux: Makefile mongoose.c mongoose.h test/unit_test.c
linux++: CC = g++ -Wno-missing-field-initializers
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
(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))> $@

View File

@ -1015,19 +1015,18 @@ Subscribe to topic `topic`.
### mg\_mqtt\_next\_sub()
```c
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos);
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic, uint8_t *qos, size_t pos);
```
Traverse list of subscribed topics.
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
if (ev == MG_EV_MQTT_CMD) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if (mm->cmd == MQTT_CMD_SUBSCRIBE) {
int pos = 4;
size_t pos = 4;
uint8_t qos;
struct mg_str topic;
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()
```c
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
int pos);
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic, size_t pos);
```
Same as `mg_mqtt_next_sub()`, but for unsubscribed topics. The difference

File diff suppressed because it is too large Load Diff

View File

@ -286,6 +286,7 @@ typedef enum { false = 0, true = 1 } bool;
#define strdup(x) _strdup(x)
#endif
typedef unsigned suseconds_t;
typedef int socklen_t;
#define MG_DIRSEP '\\'
#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);
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
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
#define LOG(level, args) (void) 0
#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 {
int period_ms; // Timer period in milliseconds
int flags; // Possible flags values below
unsigned long period_ms; // Timer period in milliseconds
unsigned flags; // Possible flags values below
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
void (*fn)(void *); // Function to call
@ -445,7 +446,8 @@ struct mg_timer {
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_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_printf(const char *path, const char *fmt, ...);
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);
uint16_t mg_ntohs(uint16_t net);
uint32_t mg_ntohl(uint32_t net);
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
char *mg_hexdump(const void *buf, size_t len);
char *mg_hex(const void *buf, int len, char *dst);
void mg_unhex(const char *buf, int len, unsigned char *to);
unsigned long mg_unhexn(const char *s, int len);
char *mg_hex(const void *buf, size_t len, char *dst);
void mg_unhex(const char *buf, size_t len, unsigned char *to);
unsigned long mg_unhexn(const char *s, size_t len);
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
int64_t mg_to64(struct mg_str str);
@ -604,7 +606,7 @@ enum {
MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL
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_HTTP_MSG, // HTTP request/response 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);
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
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_vprintf(struct mg_connection *, const char *fmt, va_list ap);
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, ...);
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);
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_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);
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 *, size_t, char *, size_t);
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,
const char *dir);
@ -772,11 +774,11 @@ struct mg_tls_opts {
struct mg_str srvname; // If not empty, enables server name verification
};
int mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
int mg_tls_free(struct mg_connection *);
int mg_tls_send(struct mg_connection *, const void *buf, size_t len, int *fail);
int mg_tls_recv(struct mg_connection *, void *buf, size_t len, int *fail);
int mg_tls_handshake(struct mg_connection *);
void mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
void mg_tls_free(struct mg_connection *);
long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
void mg_tls_handshake(struct mg_connection *);
#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);
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
uint32_t len);
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos);
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
int pos);
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, size_t pos);
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
size_t pos);
void mg_mqtt_ping(struct mg_connection *);
void mg_mqtt_pong(struct mg_connection *);
void mg_mqtt_disconnect(struct mg_connection *);

View File

@ -42,6 +42,7 @@ typedef enum { false = 0, true = 1 } bool;
#define strdup(x) _strdup(x)
#endif
typedef unsigned suseconds_t;
typedef int socklen_t;
#define MG_DIRSEP '\\'
#ifndef PATH_MAX

View File

@ -33,14 +33,14 @@ static int mg_b64rev(int c) {
int mg_base64_update(unsigned char ch, char *to, int n) {
unsigned char rem = (n & 3) % 3;
if (rem == 0) {
to[n] = mg_b64idx(ch >> 2);
to[++n] = (ch & 3) << 4;
to[n] = (char) mg_b64idx(ch >> 2);
to[++n] = (char) ((ch & 3) << 4);
} else if (rem == 1) {
to[n] = mg_b64idx(to[n] | (ch >> 4));
to[++n] = (ch & 15) << 2;
to[n] = (char) mg_b64idx(to[n] | (ch >> 4));
to[++n] = (char) ((ch & 15) << 2);
} else {
to[n] = mg_b64idx(to[n] | (ch >> 6));
to[++n] = mg_b64idx(ch & 63);
to[n] = (char) mg_b64idx(to[n] | (ch >> 6));
to[++n] = (char) mg_b64idx(ch & 63);
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]),
d = mg_b64rev(src[3]);
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] != '=') {
dst[len++] = (b << 4) | (c >> 2);
if (src[3] != '=') dst[len++] = (c << 6) | d;
dst[len++] = (char) ((b << 4) | (c >> 2));
if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
}
src += 4;
}

View File

@ -81,15 +81,15 @@ size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
return 0;
s += rr->nlen + 4;
if (s > e) return 0;
rr->atype = ((uint16_t) s[-4] << 8) | s[-3];
rr->aclass = ((uint16_t) s[-2] << 8) | s[-1];
rr->atype = (uint16_t)(((uint16_t) s[-4] << 8) | s[-3]);
rr->aclass = (uint16_t)(((uint16_t) s[-2] << 8) | s[-1]);
if (is_question) return rr->nlen + 4;
s += 6;
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;
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) {
@ -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->next = s_reqs;
s_reqs = d;
d->expire = mg_millis() + ms;
d->expire = mg_millis() + (unsigned long) ms;
d->c = c;
c->is_resolving = 1;
LOG(LL_VERBOSE_DEBUG,

View File

@ -13,7 +13,7 @@ enum {
MG_EV_CONNECT, // Connection established NULL
MG_EV_ACCEPT, // Connection accepted NULL
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_HTTP_MSG, // HTTP request/response struct mg_http_message *
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *

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;
if (c->send.size < need) mg_iobuf_resize(&c->send, 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];
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) {
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);
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);
} else {
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 dst_len) {
size_t dst_len) {
const char *p, *e, *s;
size_t name_len;
int len;
@ -154,7 +158,7 @@ static const char *skip(const char *s, const char *e, const char *d,
struct mg_str *v) {
v->ptr = 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++;
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->body.ptr = end;
hm->head.len = req_len;
hm->head.len = (size_t) req_len;
hm->chunk.ptr = end;
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 ((qs = (const char *) memchr(hm->uri.ptr, '?', hm->uri.len)) != NULL) {
hm->query.ptr = qs + 1;
hm->query.len = &hm->uri.ptr[hm->uri.len] - (qs + 1);
hm->uri.len = qs - hm->uri.ptr;
hm->query.len = (size_t)(&hm->uri.ptr[hm->uri.len] - (qs + 1));
hm->uri.len = (size_t)(qs - hm->uri.ptr);
}
mg_http_parse_headers(s, end, hm->headers,
sizeof(hm->headers) / sizeof(hm->headers[0]));
if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
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
@ -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, "POST") != 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
if (hm->body.len == (size_t) ~0 && is_response &&
mg_vcasecmp(&hm->uri, "204") == 0) {
hm->body.len = 0;
hm->message.len = req_len;
hm->message.len = (size_t) 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;
int len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
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);
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);
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_send(c, buf, len);
mg_send(c, buf, len > 0 ? (size_t) len : 0);
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);
fclose(fp);
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) {
int i, numparsed = 0;
size_t i, numparsed = 0;
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) {
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++;
@ -496,7 +500,7 @@ static int getrange(struct mg_str *s, int64_t *a, int64_t *b) {
break;
}
}
return numparsed;
return (int) numparsed;
}
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");
} else {
int n, status = 200;
char range[70] = "";
char range[100] = "";
int64_t r1 = 0, r2 = 0, cl = st.st_size;
// 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);
#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \
_XOPEN_SOURCE >= 600
fseeko(fp, r1, SEEK_SET);
fseeko(fp, (off_t) r1, SEEK_SET);
#else
fseek(fp, (long) r1, SEEK_SET);
#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));
n = mg_url_encode(name, strlen(name), path, sizeof(path));
n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
mg_printf(c,
" <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
"<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>"
"</table><address>Mongoose v.%s</address></body></html>\n",
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
} else {
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) {
char *p = t2 + strlen(t2);
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';
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 == '~';
}
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;
for (i = 0; i < sl; 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;
}
void mg_http_creds(struct mg_http_message *hm, char *user, int userlen,
char *pass, int passlen) {
void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
char *pass, size_t passlen) {
struct mg_str *v = mg_http_get_header(hm, "Authorization");
user[0] = pass[0] = '\0';
if (v != NULL && v->len > 6 && memcmp(v->ptr, "Basic ", 6) == 0) {
char buf[256];
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) {
snprintf(user, userlen, "%.*s", (int) (p - buf), buf);
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++;
// LOG(LL_INFO, ("[%.*s] [%.*s] [%.*s]", (int) s.len, s.ptr, (int) v.len,
// 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);
@ -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
// an MG_EV_HTTP_CHUNK event.
static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
int reqlen) {
size_t reqlen) {
size_t off = 0, bl, ll;
while (off + reqlen < c->recv.len) {
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
off = bl = 0;
while (off + reqlen < c->recv.len) {
char *buf = (char *) &c->recv.buf[reqlen];
size_t memo = c->recv.len;
size_t cl = get_chunk_length(&buf[off], memo - reqlen - off, &ll);
size_t n = cl < ll + 2 ? 0 : cl - ll - 2;
memmove(buf + bl, buf + off + ll, n);
char *buf2 = (char *) &c->recv.buf[reqlen];
size_t memo2 = c->recv.len;
size_t cl2 = get_chunk_length(&buf2[off], memo2 - reqlen - off, &ll);
size_t n = cl < ll + 2 ? 0 : cl2 - ll - 2;
memmove(buf2 + bl, buf2 + off + ll, n);
bl += n;
off += cl;
if (cl <= 5) break;
off += cl2;
if (cl2 <= 5) break;
}
// LOG(LL_INFO, ("BL->%d del %d off %d", (int) bl, (int) del, (int) off));
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];
size_t n = end - (char *) c->recv.buf;
if (c->recv.len > n) memmove((char *) ch.ptr, end, c->recv.len - n);
size_t n = (size_t)(end - (char *) c->recv.buf);
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,
// 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);
if (ev == MG_EV_CLOSE) {
hm.message.len = c->recv.len;
hm.body.len = hm.message.len - (hm.body.ptr - hm.message.ptr);
} else if (is_chunked) {
walkchunks(c, &hm, n);
hm.body.len = hm.message.len - (size_t)(hm.body.ptr - hm.message.ptr);
} else if (is_chunked && n > 0) {
walkchunks(c, &hm, (size_t) n);
}
// LOG(LL_INFO,
//("---->%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);
} else {
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);
}
break;

View File

@ -52,10 +52,10 @@ void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
const char *body_fmt, ...);
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);
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_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);
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 *, size_t, char *, size_t);
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,
const char *dir);

View File

@ -4,13 +4,13 @@
#if MG_ENABLE_MGOS
#else
#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;
fwrite(buf, 1, len, stdout);
}
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;
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;
struct mg_str k, v, s = mg_str(s_spec);
const char *p = strrchr(file, '/');
if (s_fn == NULL) return false;
if (p == NULL) p = strrchr(file, '\\');
p = p == NULL ? file : p + 1;
if (s_fn == NULL) return false;
while (mg_next_comma_entry(&s, &k, &v)) {
if (v.len == 0) max = atoi(k.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);
len = mg_vasprintf(&buf, sizeof(mem), fmt, 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);
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_param = param;
s_fn_param = fnd;
}
#endif
#endif

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);
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
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
#define LOG(level, args) (void) 0
#define mg_log_set(x) (void) (x)

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,
uint32_t len) {
uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
buf[0] = (cmd << 4) | flags;
buf[0] = (uint8_t)((cmd << 4) | flags);
do {
*vlen = len % 0x80;
len /= 0x80;
if (len > 0) *vlen |= 0x80;
vlen++;
} 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) {
@ -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,
struct mg_mqtt_opts *opts) {
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 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;
while ((size_t)(p - buf) < len) {
lc = *((uint8_t *) p++);
n += (lc & 0x7f) << 7 * len_len;
n += (uint32_t)((lc & 0x7f) << 7 * len_len);
len_len++;
if (!(lc & 0x80)) break;
if (len_len >= 4) return MQTT_MALFORMED;
}
end = p + n;
if (lc & 0x80 || end > buf + len) return MQTT_INCOMPLETE;
m->dgram.len = end - buf;
m->dgram.len = (size_t)(end - buf);
switch (m->cmd) {
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_SUBACK:
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;
case MQTT_CMD_SUBSCRIBE: {
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;
break;
}
case MQTT_CMD_PUBLISH: {
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;
p += 2 + m->topic.len;
if (p > end) return MQTT_MALFORMED;
if (m->qos > 0) {
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;
}
if (p > end) return MQTT_MALFORMED;
m->data.ptr = (char *) p;
m->data.len = end - p;
m->data.len = (size_t)(end - p);
break;
}
default:
@ -176,28 +176,29 @@ int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m) {
return MQTT_OK;
}
static int mg_mqtt_next_topic(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos) {
static size_t mg_mqtt_next_topic(struct mg_mqtt_message *msg,
struct mg_str *topic, uint8_t *qos,
size_t pos) {
unsigned char *buf = (unsigned char *) msg->dgram.ptr + pos;
int new_pos;
if ((size_t) pos >= msg->dgram.len) return -1;
size_t new_pos;
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;
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];
return new_pos;
}
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos) {
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, size_t pos) {
uint8_t tmp;
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,
int pos) {
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
size_t pos) {
return mg_mqtt_next_topic(msg, topic, NULL, pos);
}

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);
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
uint32_t len);
int mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, int pos);
int mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
int pos);
size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
uint8_t *qos, size_t pos);
size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
size_t pos);
void mg_mqtt_ping(struct mg_connection *);
void mg_mqtt_pong(struct mg_connection *);
void mg_mqtt_disconnect(struct mg_connection *);

View File

@ -5,7 +5,7 @@
int mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) {
char mem[256], *buf = mem;
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);
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') {
int octet = data[num_dots] * 10 + (str.ptr[i] - '0');
if (octet > 255) return false;
data[num_dots] = octet;
data[num_dots] = (uint8_t) octet;
} else if (str.ptr[i] == '.') {
if (num_dots >= 3 || i == 0 || str.ptr[i - 1] == '.') return false;
num_dots++;

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);
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
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_vprintf(struct mg_connection *, const char *fmt, va_list ap);
char *mg_straddr(struct mg_connection *, char *, size_t);

View File

@ -22,8 +22,8 @@ int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv) {
} else {
uint32_t *data = (uint32_t *) &buf[40];
tv->tv_sec = mg_ntohl(data[0]) - SNTP_TIME_OFFSET;
tv->tv_usec = mg_ntohl(data[1]);
s_sntmp_next = tv->tv_sec + SNTP_INTERVAL_SEC;
tv->tv_usec = (suseconds_t) mg_ntohl(data[1]);
s_sntmp_next = (unsigned long) (tv->tv_sec + SNTP_INTERVAL_SEC);
res = 0;
}
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
} 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) {
// mg_fn_del(c, sntp_cb);
}

View File

@ -73,19 +73,19 @@ static union usa tousa(struct mg_addr *a) {
return usa;
}
static int mg_sock_failed(void) {
static bool mg_sock_would_block(void) {
int err = MG_SOCK_ERRNO;
return err != EINPROGRESS && err != EWOULDBLOCK
return err == EINPROGRESS || err == EWOULDBLOCK
#ifndef WINCE
&& err != EAGAIN && err != EINTR
|| err == EAGAIN || err == EINTR
#endif
#if defined(_WIN32) && MG_ENABLE_WINSOCK
&& err != WSAEINTR && err != WSAEWOULDBLOCK
|| err == WSAEINTR || err == WSAEWOULDBLOCK
#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) {
struct mg_connection *c = (struct mg_connection *) calloc(1, sizeof(*c));
if (c != NULL) {
@ -97,37 +97,8 @@ static struct mg_connection *alloc_conn(struct mg_mgr *mgr, int is_client,
return c;
}
static int mg_sock_recv(struct mg_connection *c, void *buf, int len,
int *fail) {
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;
static long mg_sock_send(struct mg_connection *c, const void *buf, size_t len) {
long n = 0;
if (c->is_udp) {
union usa usa = tousa(&c->peer);
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 {
n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING);
}
*fail = (n == 0) || (n < 0 && mg_sock_failed());
return n;
return n == 0 ? -1 : n < 0 && mg_sock_would_block() ? 0 : n;
}
static int ll_read(struct mg_connection *c, void *buf, int len, int *fail) {
int n = c->is_tls ? mg_tls_recv(c, buf, len, fail)
: mg_sock_recv(c, buf, len, fail);
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;
bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
return c->is_udp ? mg_sock_send(c, buf, len) > 0
: mg_iobuf_append(&c->send, buf, len, MG_IO_SIZE);
}
static void mg_set_non_blocking_mode(SOCKET fd) {
@ -246,40 +182,95 @@ SOCKET mg_open_listener(const char *url) {
return fd;
}
static void read_conn(struct mg_connection *c,
int (*fn)(struct mg_connection *, void *, int, int *)) {
unsigned char *buf;
int rc, len, fail;
// NOTE(lsm): do only one iteration of reads, cause some systems
// (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data
if (c->recv.size - c->recv.len < MG_IO_SIZE &&
c->recv.size < MG_MAX_RECV_BUF_SIZE &&
!mg_iobuf_resize(&c->recv, c->recv.size + MG_IO_SIZE)) {
c->is_closing = 1;
}
buf = c->recv.buf + c->recv.len;
len = (int) (c->recv.size - c->recv.len);
rc = fn(c, buf, len, &fail);
if (rc > 0) {
struct mg_str evd = mg_str_n((char *) buf, rc);
c->recv.len += rc;
mg_call(c, MG_EV_READ, &evd);
static long mg_sock_recv(struct mg_connection *c, void *buf, size_t len) {
long 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 {
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) {
int fail, rc = ll_write(c, c->send.buf, c->send.len, &fail);
if (rc > 0) {
mg_iobuf_delete(&c->send, rc);
static void write_conn(struct mg_connection *c) {
char *buf = (char *) c->send.buf;
size_t len = c->send.len;
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);
mg_call(c, MG_EV_WRITE, &rc);
} else if (fail) {
c->is_closing = 1;
mg_call(c, MG_EV_WRITE, &n);
// if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
}
return rc;
}
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) {
char buf[40];
int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM;
int af = AF_INET;
int rc, af = AF_INET;
#if MG_ENABLE_IPV6
if (c->peer.is_ip6) af = AF_INET6;
#endif
@ -349,19 +340,16 @@ void mg_connect_resolved(struct mg_connection *c) {
mg_call(c, MG_EV_RESOLVE, NULL);
if (type == SOCK_STREAM) {
union usa usa = tousa(&c->peer);
socklen_t slen =
socklen_t slen = sizeof(usa.sin);
#if MG_ENABLE_IPV6
c->peer.is_ip6 ? sizeof(usa.sin6) :
if (c->peer.is_ip6) slen = sizeof(usa.sin6);
#endif
sizeof(usa.sin);
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 {
if ((rc = connect(FD(c), &usa.sa, slen)) == 0 || mg_sock_would_block()) {
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,
mg_event_handler_t fn, void *fn_data) {
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);
if (fd == INVALID_SOCKET) {
} 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) {
if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
} else {
if (c->is_readable) read_conn(c, ll_read);
if (c->is_readable) read_conn(c);
if (c->is_writable) write_conn(c);
}

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;
while ((ch = fgetc(fp)) != EOF) {
if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') {
buf[len++] = ch & 0xff;
buf[len++] = (char) (ch & 0xff);
if (sscanf(buf, "<!--#include file=\"%[^\"]", arg)) {
char tmp[MG_PATH_MAX + BUFSIZ + 10],
*p = (char *) path + strlen(path), *data;
@ -50,7 +50,7 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
intag = 1;
if (len > 0) mg_iobuf_append(&b, buf, len, align);
len = 0;
buf[len++] = ch & 0xff;
buf[len++] = (char) (ch & 0xff);
} else if (intag) {
if (len == 5 && strncmp(buf, "<!--#", 5) != 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));
len = 0;
}
buf[len++] = ch & 0xff;
buf[len++] = (char) (ch & 0xff);
} else {
buf[len++] = ch & 0xff;
buf[len++] = (char) (ch & 0xff);
if (len >= sizeof(buf)) {
mg_iobuf_append(&b, buf, len, align);
len = 0;

View File

@ -6,8 +6,8 @@
struct mg_timer *g_timers;
void mg_timer_init(struct mg_timer *t, int ms, int flags, void (*fn)(void *),
void *arg) {
void mg_timer_init(struct mg_timer *t, unsigned long ms, unsigned flags,
void (*fn)(void *), void *arg) {
struct mg_timer tmp = {ms, flags, fn, arg, 0UL, g_timers};
*t = tmp;
g_timers = t;

View File

@ -1,8 +1,8 @@
#pragma once
struct mg_timer {
int period_ms; // Timer period in milliseconds
int flags; // Possible flags values below
unsigned long period_ms; // Timer period in milliseconds
unsigned flags; // Possible flags values below
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
void (*fn)(void *); // Function to call
@ -13,6 +13,7 @@ struct mg_timer {
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_poll(unsigned long uptime_ms);

View File

@ -29,7 +29,7 @@ struct mg_tls {
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;
int rc;
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 {
mg_error(c, "TLS handshake: -%#x", -rc); // Error
}
return rc == 0;
}
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) {
n = strlen(s2) - 1;
n = (int) strlen(s2) - 1;
LOG(LL_VERBOSE_DEBUG, ("%p %.*s", ((struct mg_connection *) c)->fd, n, s2));
(void) s;
(void) c;
(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));
int rc = 0;
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) {
mg_tls_handshake(c);
}
return 1;
return;
fail:
c->is_closing = 1;
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;
int n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
*fail = (n == 0) || (n < 0 && n != MBEDTLS_ERR_SSL_WANT_READ);
return n;
long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_READ ? 0 : n;
}
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len,
int *fail) {
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
struct mg_tls *tls = (struct mg_tls *) c->tls;
int n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
*fail = (n == 0) || (n < 0 && n != MBEDTLS_ERR_SSL_WANT_WRITE);
return n;
long n = mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf, len);
return n == 0 ? -1 : n == MBEDTLS_ERR_SSL_WANT_WRITE ? 0 : 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;
if (tls == NULL) return 0;
if (tls == NULL) return;
free(tls->cafile);
mbedtls_ssl_free(&tls->ssl);
mbedtls_pk_free(&tls->pk);
@ -197,7 +192,6 @@ int mg_tls_free(struct mg_connection *c) {
mbedtls_ssl_config_free(&tls->conf);
free(tls);
c->tls = NULL;
return 1;
}
#elif MG_ENABLE_OPENSSL ///////////////////////////////////////// OPENSSL
@ -225,7 +219,7 @@ static int mg_tls_err(struct mg_tls *tls, int res) {
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));
const char *id = "mongoose";
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");
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
SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2);
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;
LOG(LL_DEBUG, ("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client"));
return 1;
return;
fail:
c->is_closing = 1;
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;
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);
if (rc == 1) {
LOG(LL_DEBUG, ("%lu success", c->id));
c->is_tls_hs = 0;
return 1;
} else {
int code;
ERR_print_errors_fp(stderr);
code = mg_tls_err(tls, rc);
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;
if (tls == NULL) return 0;
if (tls == NULL) return;
SSL_free(tls->ssl);
SSL_CTX_free(tls->ctx);
free(tls);
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;
int n = SSL_read(tls->ssl, buf, len);
*fail = (n == 0) || (n < 0 && mg_tls_err(tls, n) != 0);
return n;
int n = SSL_read(tls->ssl, buf, (int) len);
return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
}
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len,
int *fail) {
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
struct mg_tls *tls = (struct mg_tls *) c->tls;
int n = SSL_write(tls->ssl, buf, len);
*fail = (n == 0) || (n < 0 && mg_tls_err(tls, n) != 0);
return n;
int n = SSL_write(tls->ssl, buf, (int) len);
return n == 0 ? -1 : n < 0 && mg_tls_err(tls, n) == 0 ? 0 : n;
}
#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;
mg_error(c, "TLS is not enabled");
return 0;
}
int mg_tls_handshake(struct mg_connection *c) {
return c != NULL;
void mg_tls_handshake(struct mg_connection *c) {
(void) c;
}
int mg_tls_free(struct mg_connection *c) {
return c != NULL;
void mg_tls_free(struct mg_connection *c) {
(void) c;
}
int mg_tls_recv(struct mg_connection *c, void *buf, size_t len, int *fail) {
*fail = 1;
long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
return c == NULL || buf == NULL || len == 0 ? 0 : -1;
}
int mg_tls_send(struct mg_connection *c, const void *buf, size_t len,
int *fail) {
*fail = 1;
long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
return c == NULL || buf == NULL || len == 0 ? 0 : -1;
}

View File

@ -9,8 +9,8 @@ struct mg_tls_opts {
struct mg_str srvname; // If not empty, enables server name verification
};
int mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
int mg_tls_free(struct mg_connection *);
int mg_tls_send(struct mg_connection *, const void *buf, size_t len, int *fail);
int mg_tls_recv(struct mg_connection *, void *buf, size_t len, int *fail);
int mg_tls_handshake(struct mg_connection *);
void mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
void mg_tls_free(struct mg_connection *);
long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
void mg_tls_handshake(struct mg_connection *);

View File

@ -2,7 +2,7 @@
#include "url.h"
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) {
@ -12,7 +12,7 @@ int mg_url_is_ssl(const char *url) {
}
static struct url urlparse(const char *url) {
int i;
size_t i;
struct url u;
memset(&u, 0, sizeof(u));
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 url u = urlparse(url);
int n =
u.port ? u.port - u.host - 1 : u.uri ? u.uri - u.host : u.end - u.host;
size_t n = u.port ? u.port - u.host - 1
: u.uri ? u.uri - u.host
: u.end - u.host;
struct mg_str s = mg_str_n(url + u.host, n);
if (s.len > 2 && s.ptr[0] == '[' && s.ptr[s.len - 1] == ']') {
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, "mqtt:", 5) == 0) port = 1883;
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;
}
@ -71,7 +72,7 @@ struct mg_str mg_url_user(const char *url) {
struct url u = urlparse(url);
struct mg_str s = mg_str("");
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);
}
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 url u = urlparse(url);
struct mg_str s = mg_str("");
struct mg_str s = mg_str_n("", 0UL);
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);
}
return s;

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, ...) {
char tmp[256], *buf = tmp;
bool result;
size_t len;
int len;
va_list ap;
va_start(ap, fmt);
len = mg_vasprintf(&buf, sizeof(tmp), fmt, 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);
return result;
}
@ -99,12 +99,14 @@ void mg_random(void *buf, size_t len) {
if (!done) {
// Fallback to a pseudo random gen
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) {
int i = 0, j = 0, ni = 0, nj = 0;
bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) {
size_t i = 0, j = 0, ni = 0, nj = 0;
while (i < n1 || j < n2) {
if (i < n1 && j < n2 && (s1[i] == '?' || s2[j] == s1[i])) {
i++, j++;
@ -119,21 +121,22 @@ bool mg_globmatch(const char *s1, int n1, const char *s2, int n2) {
return true;
}
static int mg_nextcommaentry(const char *s, int slen, int ofs, int *koff,
int *klen, int *voff, int *vlen) {
int kvlen, kl;
for (kvlen = 0; ofs + kvlen < slen && s[ofs + kvlen] != ',';) kvlen++;
static size_t mg_nce(const char *s, size_t n, size_t ofs, size_t *koff,
size_t *klen, size_t *voff, size_t *vlen) {
size_t kvlen, kl;
for (kvlen = 0; ofs + kvlen < n && s[ofs + kvlen] != ',';) kvlen++;
for (kl = 0; kl < kvlen && s[ofs + kl] != '=';) kl++;
if (koff != NULL) *koff = ofs;
if (klen != NULL) *klen = kl;
if (voff != NULL) *voff = kl < kvlen ? ofs + 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) {
int koff, klen, voff, vlen;
int off = mg_nextcommaentry(s->ptr, s->len, 0, &koff, &klen, &voff, &vlen);
size_t koff = 0, klen = 0, voff = 0, vlen = 0;
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 (v != NULL) *v = mg_str_n(s->ptr + voff, vlen);
*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) {
uint8_t data[4] = {0, 0, 0, 0};
memcpy(&data, &net, sizeof(data));
return ((uint32_t) data[3] << 0) | ((uint32_t) data[2] << 8) |
((uint32_t) data[1] << 16) | ((uint32_t) data[0] << 24);
return (((uint32_t) data[3]) << 0) | (((uint32_t) data[2]) << 8) |
(((uint32_t) data[1]) << 16) | (((uint32_t) data[0]) << 24);
}
uint16_t mg_ntohs(uint16_t net) {
uint8_t data[2] = {0, 0};
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) {
@ -161,27 +164,29 @@ char *mg_hexdump(const void *buf, size_t len) {
for (i = 0; i < len; i++) {
idx = i % 16;
if (idx == 0) {
if (i > 0 && dlen > n) n += snprintf(dst + n, dlen - n, " %s\n", ascii);
if (dlen > n) n += snprintf(dst + n, dlen - n, "%04x ", (int) (i + ofs));
if (i > 0 && dlen > n)
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;
n += snprintf(dst + n, dlen - n, " %02x", p[i]);
ascii[idx] = p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i];
n += (size_t) snprintf(dst + n, dlen - n, " %02x", p[i]);
ascii[idx] = (char) (p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i]);
ascii[idx + 1] = '\0';
}
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;
dst[n] = '\0';
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;
static const char *hex = "0123456789abcdef";
int i = 0;
size_t i = 0;
for (; len--; p++) {
to[i++] = hex[p[0] >> 4];
to[i++] = hex[p[0] & 0x0f];
@ -190,20 +195,20 @@ char *mg_hex(const void *buf, int len, char *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;
for (i = 0; i < (unsigned long) len; 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';
}
for (i = 0; i < len; i++) v <<= 4, v |= mg_unhex_nimble(((uint8_t *) s)[i]);
return v;
}
void mg_unhex(const char *buf, int len, unsigned char *to) {
int i;
void mg_unhex(const char *buf, size_t len, unsigned char *to) {
size_t i;
for (i = 0; i < len; 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
} else if (len >= (int) size) {
/// 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
} else { // LCOV_EXCL_LINE
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);
}
}
@ -321,7 +326,7 @@ void mg_usleep(unsigned long usecs) {
#elif MG_ARCH == MG_ARCH_FREERTOS_TCP
vTaskDelay(pdMS_TO_TICKS(usecs / 1000));
#else
usleep(usecs);
usleep((useconds_t) usecs);
#endif
}
@ -337,6 +342,7 @@ unsigned long mg_millis(void) {
#else
struct timespec 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
}

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_printf(const char *path, const char *fmt, ...);
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);
uint16_t mg_ntohs(uint16_t net);
uint32_t mg_ntohl(uint32_t net);
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
char *mg_hexdump(const void *buf, size_t len);
char *mg_hex(const void *buf, int len, char *dst);
void mg_unhex(const char *buf, int len, unsigned char *to);
unsigned long mg_unhexn(const char *s, int len);
char *mg_hex(const void *buf, size_t len, char *dst);
void mg_unhex(const char *buf, size_t len, unsigned char *to);
unsigned long mg_unhexn(const char *s, size_t len);
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
int64_t mg_to64(struct mg_str str);

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) {
msg->header_len = 10 + mask_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]);
}
}
@ -124,7 +124,7 @@ static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data,
c->is_websocket = 1;
mg_call(c, MG_EV_WS_OPEN, &hm);
}
mg_iobuf_delete(&c->recv, n);
mg_iobuf_delete(&c->recv, (size_t) n);
} else {
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"
"\r\n",
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 (buf2 != mem2) free(buf2);
c->pfn = mg_ws_cb;

22
test/mongoose_custom.h Normal file
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

View File

@ -249,11 +249,11 @@ static void test_sntp(void) {
"\xc9\xd6\xa2\xdb\xde\xea\x30\x91\x86\xb7\x10\xdb\xde"
"\xed\x98\x00\x00\x00\xde\xdb\xde\xed\x99\x0a\xe2\xc7"
"\x96\xdb\xde\xed\x99\x0a\xe4\x6b\xda";
struct timeval tv = {0, 0};
struct timeval tv2 = {0, 0};
struct tm *tm;
time_t t;
ASSERT(mg_sntp_parse(sntp_good, sizeof(sntp_good), &tv) == 0);
t = tv.tv_sec;
ASSERT(mg_sntp_parse(sntp_good, sizeof(sntp_good), &tv2) == 0);
t = tv2.tv_sec;
tm = gmtime(&t);
ASSERT(tm->tm_year == 116);
ASSERT(tm->tm_mon == 10);
@ -261,7 +261,7 @@ static void test_sntp(void) {
ASSERT(tm->tm_hour == 16);
ASSERT(tm->tm_min == 15);
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);
@ -329,8 +329,8 @@ static void test_mqtt(void) {
}
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;
if (ev == MG_EV_ACCEPT && opts != NULL) mg_tls_init(c, opts);
struct mg_tls_opts *topts = (struct mg_tls_opts *) fn_data;
if (ev == MG_EV_ACCEPT && topts != NULL) mg_tls_init(c, topts);
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
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")) {
mg_http_reply(c, 404, "", "not found");
} else if (mg_http_match_uri(hm, "/badroot")) {
struct mg_http_serve_opts opts = {"/BAAADDD!", NULL, NULL};
mg_http_serve_dir(c, hm, &opts);
struct mg_http_serve_opts sopts = {"/BAAADDD!", NULL, NULL};
mg_http_serve_dir(c, hm, &sopts);
} else if (mg_http_match_uri(hm, "/creds")) {
char user[100], pass[100];
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")) {
mg_http_upload(c, hm, ".");
} else if (mg_http_match_uri(hm, "/test/")) {
struct mg_http_serve_opts opts = {".", NULL, "A: B\r\nC: D\r\n"};
mg_http_serve_dir(c, hm, &opts);
struct mg_http_serve_opts sopts = {".", NULL, "A: B\r\nC: D\r\n"};
mg_http_serve_dir(c, hm, &sopts);
} else {
struct mg_http_serve_opts opts = {"./test/data", "#.shtml", "C: D\r\n"};
mg_http_serve_dir(c, hm, &opts);
struct mg_http_serve_opts sopts = {"./test/data", "#.shtml", "C: D\r\n"};
mg_http_serve_dir(c, hm, &sopts);
}
} else if (ev == MG_EV_WS_MSG) {
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;
const char *req = "GET /foo?bar=baz HTTP/1.0\n\n ";
ASSERT(mg_http_parse(req, strlen(req), &hm) == (int) strlen(req) - 1);
const char *s = "GET /foo?bar=baz HTTP/1.0\n\n ";
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.query, mg_str("bar=baz")) == 0);
}
{
struct mg_http_message hm;
const char *req = "a b c\n\n";
ASSERT(mg_http_parse(req, strlen(req), &hm) == (int) strlen(req));
req = "a b\nc\n\n";
ASSERT(mg_http_parse(req, strlen(req), &hm) < 0);
req = "a\nb\nc\n\n";
ASSERT(mg_http_parse(req, strlen(req), &hm) < 0);
const char *s = "a b c\n\n";
ASSERT(mg_http_parse(s, strlen(s), &hm) == (int) strlen(s));
s = "a b\nc\n\n";
ASSERT(mg_http_parse(s, strlen(s), &hm) < 0);
s = "a\nb\nc\n\n";
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);
{
char buf[100];
int n;
size_t n;
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, 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);
ASSERT(s == buf);
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
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) {
mg_printf(c, "GET / HTTP/1.0\n\n");
} 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;
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
} 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;
*crc = mg_crc32(*crc, hm->body.ptr, hm->body.len);
// LOG(LL_INFO, ("MSG [%.*s]", (int) hm->body.len, hm->body.ptr));
c->is_closing = 1;
*(int *) fn_data = mg_crc32(*crc, hm->body.ptr, hm->body.len);
*(uint32_t *) fn_data = *crc;
}
(void) ev_data;
}
// Streaming client event handler. Delete chunks as they arrive
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) {
mg_printf(c, "GET / HTTP/1.0\n\n");
} 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;
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
// LOG(LL_INFO, ("CHUNK [%.*s]", (int) hm->chunk.len, hm->chunk.ptr));
mg_http_delete_chunk(c, hm);
} else if (ev == MG_EV_HTTP_MSG) {
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;
*(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));
}
(void) ev_data;