mirror of
https://github.com/cesanta/mongoose.git
synced 2025-01-14 01:38:01 +08:00
Fix #1285 - __builtin___snprintf_chk warning. Tighten test flags and refactor the code to squash all warnings
This commit is contained in:
parent
db27fae40e
commit
736b8ad7b7
7
.github/workflows/test.yml
vendored
7
.github/workflows/test.yml
vendored
@ -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
|
||||
|
9
Makefile
9
Makefile
@ -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))> $@
|
||||
|
||||
|
@ -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
|
||||
|
601
mongoose.c
601
mongoose.c
File diff suppressed because it is too large
Load Diff
46
mongoose.h
46
mongoose.h
@ -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 *);
|
||||
|
@ -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
|
||||
|
18
src/base64.c
18
src/base64.c
@ -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;
|
||||
}
|
||||
|
10
src/dns.c
10
src/dns.c
@ -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,
|
||||
|
@ -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 *
|
||||
|
93
src/http.c
93
src/http.c
@ -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;
|
||||
|
@ -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);
|
||||
|
14
src/log.c
14
src/log.c
@ -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
|
||||
|
@ -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)
|
||||
|
41
src/mqtt.c
41
src/mqtt.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
218
src/sock.c
218
src/sock.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
82
src/tls.c
82
src/tls.c
@ -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;
|
||||
}
|
||||
|
||||
|
10
src/tls.h
10
src/tls.h
@ -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 *);
|
||||
|
17
src/url.c
17
src/url.c
@ -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;
|
||||
|
80
src/util.c
80
src/util.c
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
6
src/ws.c
6
src/ws.c
@ -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
22
test/mongoose_custom.h
Normal 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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user