|
@@ -1377,13 +1377,17 @@ static void set_close_on_exec(int fd) {
|
|
int mg_start_thread(mg_thread_func_t func, void *param) {
|
|
int mg_start_thread(mg_thread_func_t func, void *param) {
|
|
pthread_t thread_id;
|
|
pthread_t thread_id;
|
|
pthread_attr_t attr;
|
|
pthread_attr_t attr;
|
|
|
|
+ int result;
|
|
|
|
|
|
(void) pthread_attr_init(&attr);
|
|
(void) pthread_attr_init(&attr);
|
|
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
// TODO(lsm): figure out why mongoose dies on Linux if next line is enabled
|
|
// TODO(lsm): figure out why mongoose dies on Linux if next line is enabled
|
|
// (void) pthread_attr_setstacksize(&attr, sizeof(struct mg_connection) * 5);
|
|
// (void) pthread_attr_setstacksize(&attr, sizeof(struct mg_connection) * 5);
|
|
|
|
|
|
- return pthread_create(&thread_id, &attr, func, param);
|
|
|
|
|
|
+ result = pthread_create(&thread_id, &attr, func, param);
|
|
|
|
+ pthread_attr_destroy(&attr);
|
|
|
|
+
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef NO_CGI
|
|
#ifndef NO_CGI
|
|
@@ -2630,13 +2634,22 @@ struct dir_scan_data {
|
|
int arr_size;
|
|
int arr_size;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+// Behaves like realloc(), but frees original pointer on failure
|
|
|
|
+static void *realloc2(void *ptr, size_t size) {
|
|
|
|
+ void *new_ptr = realloc(ptr, size);
|
|
|
|
+ if (new_ptr == NULL) {
|
|
|
|
+ free(ptr);
|
|
|
|
+ }
|
|
|
|
+ return new_ptr;
|
|
|
|
+}
|
|
|
|
+
|
|
static void dir_scan_callback(struct de *de, void *data) {
|
|
static void dir_scan_callback(struct de *de, void *data) {
|
|
struct dir_scan_data *dsd = (struct dir_scan_data *) data;
|
|
struct dir_scan_data *dsd = (struct dir_scan_data *) data;
|
|
|
|
|
|
if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
|
|
if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
|
|
dsd->arr_size *= 2;
|
|
dsd->arr_size *= 2;
|
|
- dsd->entries = (struct de *) realloc(dsd->entries, dsd->arr_size *
|
|
|
|
- sizeof(dsd->entries[0]));
|
|
|
|
|
|
+ dsd->entries = (struct de *) realloc2(dsd->entries, dsd->arr_size *
|
|
|
|
+ sizeof(dsd->entries[0]));
|
|
}
|
|
}
|
|
if (dsd->entries == NULL) {
|
|
if (dsd->entries == NULL) {
|
|
// TODO(lsm): propagate an error to the caller
|
|
// TODO(lsm): propagate an error to the caller
|
|
@@ -3790,12 +3803,12 @@ static void send_websocket_handshake(struct mg_connection *conn) {
|
|
|
|
|
|
static void read_websocket(struct mg_connection *conn) {
|
|
static void read_websocket(struct mg_connection *conn) {
|
|
unsigned char *buf = (unsigned char *) conn->buf + conn->request_len;
|
|
unsigned char *buf = (unsigned char *) conn->buf + conn->request_len;
|
|
- int n;
|
|
|
|
|
|
+ int n, stop = 0;
|
|
size_t i, len, mask_len, data_len, header_len, body_len;
|
|
size_t i, len, mask_len, data_len, header_len, body_len;
|
|
char mem[4 * 1024], *data;
|
|
char mem[4 * 1024], *data;
|
|
|
|
|
|
assert(conn->content_len == 0);
|
|
assert(conn->content_len == 0);
|
|
- for (;;) {
|
|
|
|
|
|
+ while (!stop) {
|
|
header_len = 0;
|
|
header_len = 0;
|
|
if ((body_len = conn->data_len - conn->request_len) >= 2) {
|
|
if ((body_len = conn->data_len - conn->request_len) >= 2) {
|
|
len = buf[1] & 127;
|
|
len = buf[1] & 127;
|
|
@@ -3849,7 +3862,7 @@ static void read_websocket(struct mg_connection *conn) {
|
|
if ((conn->ctx->callbacks.websocket_data != NULL &&
|
|
if ((conn->ctx->callbacks.websocket_data != NULL &&
|
|
!conn->ctx->callbacks.websocket_data(conn, buf[0], data, data_len)) ||
|
|
!conn->ctx->callbacks.websocket_data(conn, buf[0], data, data_len)) ||
|
|
(buf[0] & 0xf) == 8) { // Opcode == 8, connection close
|
|
(buf[0] & 0xf) == 8) { // Opcode == 8, connection close
|
|
- break;
|
|
|
|
|
|
+ stop = 1;
|
|
}
|
|
}
|
|
|
|
|
|
if (data != mem) {
|
|
if (data != mem) {
|
|
@@ -3868,7 +3881,8 @@ static void read_websocket(struct mg_connection *conn) {
|
|
}
|
|
}
|
|
|
|
|
|
static void handle_websocket_request(struct mg_connection *conn) {
|
|
static void handle_websocket_request(struct mg_connection *conn) {
|
|
- if (strcmp(mg_get_header(conn, "Sec-WebSocket-Version"), "13") != 0) {
|
|
|
|
|
|
+ const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
|
|
|
|
+ if (version == NULL || strcmp(version, "13") != 0) {
|
|
send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required");
|
|
send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required");
|
|
} else if (conn->ctx->callbacks.websocket_connect != NULL &&
|
|
} else if (conn->ctx->callbacks.websocket_connect != NULL &&
|
|
conn->ctx->callbacks.websocket_connect(conn) != 0) {
|
|
conn->ctx->callbacks.websocket_connect(conn) != 0) {
|
|
@@ -4552,12 +4566,13 @@ static int set_ports_option(struct mg_context *ctx) {
|
|
success = 0;
|
|
success = 0;
|
|
} else {
|
|
} else {
|
|
set_close_on_exec(so.sock);
|
|
set_close_on_exec(so.sock);
|
|
- // TODO: handle realloc failure
|
|
|
|
- ctx->listening_sockets = realloc(ctx->listening_sockets,
|
|
|
|
- (ctx->num_listening_sockets + 1) *
|
|
|
|
- sizeof(ctx->listening_sockets[0]));
|
|
|
|
- ctx->listening_sockets[ctx->num_listening_sockets] = so;
|
|
|
|
- ctx->num_listening_sockets++;
|
|
|
|
|
|
+ ctx->listening_sockets = realloc2(ctx->listening_sockets,
|
|
|
|
+ (ctx->num_listening_sockets + 1) *
|
|
|
|
+ sizeof(ctx->listening_sockets[0]));
|
|
|
|
+ if (ctx->listening_sockets != NULL) {
|
|
|
|
+ ctx->listening_sockets[ctx->num_listening_sockets] = so;
|
|
|
|
+ ctx->num_listening_sockets++;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5208,7 +5223,7 @@ static void *master_thread(void *thread_func_param) {
|
|
#endif
|
|
#endif
|
|
|
|
|
|
pfd = calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
|
|
pfd = calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
|
|
- while (ctx->stop_flag == 0) {
|
|
|
|
|
|
+ while (pfd != NULL && ctx->stop_flag == 0) {
|
|
for (i = 0; i < ctx->num_listening_sockets; i++) {
|
|
for (i = 0; i < ctx->num_listening_sockets; i++) {
|
|
pfd[i].fd = ctx->listening_sockets[i].sock;
|
|
pfd[i].fd = ctx->listening_sockets[i].sock;
|
|
pfd[i].events = POLLIN;
|
|
pfd[i].events = POLLIN;
|