mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-26 12:14:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab650ec5c9 | ||
|
|
8f36597048 | ||
|
|
d0213ee90a | ||
|
|
1e9fabe1ca | ||
|
|
148d3f0562 | ||
|
|
c3057df3f5 | ||
|
|
0b2e474d52 | ||
|
|
95a36b1759 | ||
|
|
86ffa3a3ea | ||
|
|
69e2b2985d | ||
|
|
c431904b56 | ||
|
|
c2a10601b9 | ||
|
|
e9a8e5468d | ||
|
|
22e602debb | ||
|
|
455cec67a5 | ||
|
|
e2dfac946d | ||
|
|
c198d2e5f1 | ||
|
|
9a70abef24 | ||
|
|
53e1c469a2 | ||
|
|
139c2061a8 | ||
|
|
15b361fbac | ||
|
|
3130e59244 | ||
|
|
93286836f9 | ||
|
|
91b57aa9a8 | ||
|
|
220231e647 | ||
|
|
c438bb0bc5 | ||
|
|
95afa323c0 | ||
|
|
bc56353a79 | ||
|
|
1ffccdb7b2 | ||
|
|
e79fe4b8f0 | ||
|
|
aaf1fc3a4a | ||
|
|
8b42353039 | ||
|
|
05c687e251 | ||
|
|
492b8f6950 | ||
|
|
8ccee82059 | ||
|
|
b99a94a652 | ||
|
|
41e5d7e471 | ||
|
|
1adea37c45 | ||
|
|
98f6c8aa4f | ||
|
|
341ae53e85 | ||
|
|
291fc024cd | ||
|
|
f63d833a33 | ||
|
|
ab035901f8 | ||
|
|
20f54059ad | ||
|
|
563c31303e | ||
|
|
421e099f2b | ||
|
|
955d4a3129 | ||
|
|
b84981ad03 |
No files matched your search
@@ -1,12 +1,15 @@
|
|||||||
---
|
---
|
||||||
title: "Memory Buffers"
|
title: "mbuf.h"
|
||||||
symbol_kind: "intro"
|
symbol_kind: "intro"
|
||||||
decl_name: "mbuf.h"
|
decl_name: "mbuf.h"
|
||||||
items:
|
items:
|
||||||
- { name: mbuf_append.md }
|
- { name: mbuf_append.md }
|
||||||
|
- { name: mbuf_append_and_free.md }
|
||||||
|
- { name: mbuf_clear.md }
|
||||||
- { name: mbuf_free.md }
|
- { name: mbuf_free.md }
|
||||||
- { name: mbuf_init.md }
|
- { name: mbuf_init.md }
|
||||||
- { name: mbuf_insert.md }
|
- { name: mbuf_insert.md }
|
||||||
|
- { name: mbuf_move.md }
|
||||||
- { name: mbuf_remove.md }
|
- { name: mbuf_remove.md }
|
||||||
- { name: mbuf_resize.md }
|
- { name: mbuf_resize.md }
|
||||||
- { name: mbuf_trim.md }
|
- { name: mbuf_trim.md }
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
title: "mbuf_append_and_free()"
|
||||||
|
decl_name: "mbuf_append_and_free"
|
||||||
|
symbol_kind: "func"
|
||||||
|
signature: |
|
||||||
|
size_t mbuf_append_and_free(struct mbuf *, void *data, size_t data_size);
|
||||||
|
---
|
||||||
|
|
||||||
|
Appends data to the Mbuf and frees it (data must be heap-allocated).
|
||||||
|
|
||||||
|
Returns the number of bytes appended or 0 if out of memory.
|
||||||
|
data is freed irrespective of return value.
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: "mbuf_clear()"
|
||||||
|
decl_name: "mbuf_clear"
|
||||||
|
symbol_kind: "func"
|
||||||
|
signature: |
|
||||||
|
void mbuf_clear(struct mbuf *);
|
||||||
|
---
|
||||||
|
|
||||||
|
Removes all the data from mbuf (if any).
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: "mbuf_move()"
|
||||||
|
decl_name: "mbuf_move"
|
||||||
|
symbol_kind: "func"
|
||||||
|
signature: |
|
||||||
|
void mbuf_move(struct mbuf *from, struct mbuf *to);
|
||||||
|
---
|
||||||
|
|
||||||
|
Moves the state from one mbuf to the other.
|
||||||
|
|
||||||
@@ -30,7 +30,9 @@ The user-defined event handler will receive following extra events:
|
|||||||
- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
||||||
handshake request. `ev_data` contains parsed HTTP request.
|
handshake request. `ev_data` contains parsed HTTP request.
|
||||||
- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
||||||
handshake. `ev_data` is `NULL`.
|
handshake. `ev_data` is a `struct http_message` containing the
|
||||||
|
client's request (server mode) or server's response (client).
|
||||||
|
In client mode handler can examine `resp_code`, which should be 101.
|
||||||
- MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
- MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
||||||
`struct websocket_message *`
|
`struct websocket_message *`
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ signature: |
|
|||||||
struct mg_str data;
|
struct mg_str data;
|
||||||
int status; /* <0 on error */
|
int status; /* <0 on error */
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
/*
|
||||||
|
* User handler can indicate how much of the data was consumed
|
||||||
|
* by setting this variable. By default, it is assumed that all
|
||||||
|
* data has been consumed by the handler.
|
||||||
|
* If not all data was consumed, user's handler will be invoked again later
|
||||||
|
* with the remainder.
|
||||||
|
*/
|
||||||
|
size_t num_data_consumed;
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -16,5 +16,5 @@ that can be, and must be, called from a different (non-IO) thread.
|
|||||||
`func` callback function will be called by the IO thread for each
|
`func` callback function will be called by the IO thread for each
|
||||||
connection. When called, the event will be `MG_EV_POLL`, and a message will
|
connection. When called, the event will be `MG_EV_POLL`, and a message will
|
||||||
be passed as the `ev_data` pointer. Maximum message size is capped
|
be passed as the `ev_data` pointer. Maximum message size is capped
|
||||||
by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
|
by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes by default.
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@ title: "mg_mgr_free()"
|
|||||||
decl_name: "mg_mgr_free"
|
decl_name: "mg_mgr_free"
|
||||||
symbol_kind: "func"
|
symbol_kind: "func"
|
||||||
signature: |
|
signature: |
|
||||||
void mg_mgr_free(struct mg_mgr *);
|
void mg_mgr_free(struct mg_mgr *mgr);
|
||||||
---
|
---
|
||||||
|
|
||||||
De-initialises Mongoose manager.
|
De-initialises Mongoose manager.
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ title: "mg_mgr_poll()"
|
|||||||
decl_name: "mg_mgr_poll"
|
decl_name: "mg_mgr_poll"
|
||||||
symbol_kind: "func"
|
symbol_kind: "func"
|
||||||
signature: |
|
signature: |
|
||||||
time_t mg_mgr_poll(struct mg_mgr *, int milli);
|
int mg_mgr_poll(struct mg_mgr *mgr, int milli);
|
||||||
---
|
---
|
||||||
|
|
||||||
This function performs the actual IO and must be called in a loop
|
This function performs the actual IO and must be called in a loop
|
||||||
(an event loop). It returns the current timestamp.
|
(an event loop). It returns number of user events generated (except POLLs).
|
||||||
`milli` is the maximum number of milliseconds to sleep.
|
`milli` is the maximum number of milliseconds to sleep.
|
||||||
`mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
`mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
||||||
of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ signature: |
|
|||||||
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
||||||
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
||||||
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
||||||
|
#define MG_F_RECV_AND_CLOSE (1 << 9) /* Drain rx and close the connection. */
|
||||||
|
|
||||||
/* Flags that are settable by user */
|
/* Flags that are settable by user */
|
||||||
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ signature: |
|
|||||||
#endif
|
#endif
|
||||||
void *user_data; /* User data */
|
void *user_data; /* User data */
|
||||||
int num_ifaces;
|
int num_ifaces;
|
||||||
|
int num_calls;
|
||||||
struct mg_iface **ifaces; /* network interfaces */
|
struct mg_iface **ifaces; /* network interfaces */
|
||||||
const char *nameserver; /* DNS server to use */
|
const char *nameserver; /* DNS server to use */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ flags are meant to be set only by the user event handler to tell Mongoose how to
|
|||||||
behave. Below is a list of connection flags that are meant to be set by event
|
behave. Below is a list of connection flags that are meant to be set by event
|
||||||
handlers:
|
handlers:
|
||||||
|
|
||||||
* `MG_F_FINISHED_SENDING_DATA` tells Mongoose that all data has been appended
|
* `MG_F_SEND_AND_CLOSE` tells Mongoose that all data has been appended
|
||||||
to the `send_mbuf`. As soon as Mongoose sends it to the socket, the
|
to the `send_mbuf`. As soon as Mongoose sends it to the socket, the
|
||||||
connection will be closed.
|
connection will be closed.
|
||||||
* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf`
|
* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf`
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ bool bm222_get_data(struct bm222_ctx *ctx) {
|
|||||||
s->y = v[3];
|
s->y = v[3];
|
||||||
s->z = v[5];
|
s->z = v[5];
|
||||||
if (d > max_d) max_d = d;
|
if (d > max_d) max_d = d;
|
||||||
LOG(LL_VERBOSE_DEBUG, ("dx %d dy %d dz %d d %d", dx, dy, dz, d));
|
LOG(LL_VERBOSE_DEBUG,
|
||||||
|
("dx %d dy %d dz %d d %d", (int) dx, (int) dy, (int) dz, (int) d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (overflow ? bm222_fifo_init(ctx) : true); /* Clear the ovf flag. */
|
return (overflow ? bm222_fifo_init(ctx) : true); /* Clear the ovf flag. */
|
||||||
|
|||||||
+84
-14
@@ -1,11 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CS_COMMON_CS_DBG_H_
|
#ifndef CS_COMMON_CS_DBG_H_
|
||||||
#define CS_COMMON_CS_DBG_H_
|
#define CS_COMMON_CS_DBG_H_
|
||||||
|
|
||||||
|
#include "common/platform.h"
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -14,6 +28,10 @@
|
|||||||
#define CS_ENABLE_DEBUG 0
|
#define CS_ENABLE_DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_LOG_PREFIX_LEN
|
||||||
|
#define CS_LOG_PREFIX_LEN 24
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CS_LOG_ENABLE_TS_DIFF
|
#ifndef CS_LOG_ENABLE_TS_DIFF
|
||||||
#define CS_LOG_ENABLE_TS_DIFF 0
|
#define CS_LOG_ENABLE_TS_DIFF 0
|
||||||
#endif
|
#endif
|
||||||
@@ -22,6 +40,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log level; `LL_INFO` is the default. Use `cs_log_set_level()` to change it.
|
||||||
|
*/
|
||||||
enum cs_log_level {
|
enum cs_log_level {
|
||||||
LL_NONE = -1,
|
LL_NONE = -1,
|
||||||
LL_ERROR = 0,
|
LL_ERROR = 0,
|
||||||
@@ -34,29 +55,78 @@ enum cs_log_level {
|
|||||||
_LL_MAX = 5,
|
_LL_MAX = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set max log level to print; messages with the level above the given one will
|
||||||
|
* not be printed.
|
||||||
|
*/
|
||||||
void cs_log_set_level(enum cs_log_level level);
|
void cs_log_set_level(enum cs_log_level level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A comma-separated set of prefix=level.
|
||||||
|
* prefix is matched against the log prefix exactly as printed, including line
|
||||||
|
* number, but partial match is ok. Check stops on first matching entry.
|
||||||
|
* If nothing matches, default level is used.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* main.c:=4 - everything from main C at verbose debug level.
|
||||||
|
* mongoose.c=1,mjs.c=1,=4 - everything at verbose debug except mg_* and mjs_*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cs_log_set_file_level(const char *file_level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function which prints message prefix with the given `level`.
|
||||||
|
* If message should be printed (according to the current log level
|
||||||
|
* and filter), prints the prefix and returns 1, otherwise returns 0.
|
||||||
|
*
|
||||||
|
* Clients should typically just use `LOG()` macro.
|
||||||
|
*/
|
||||||
|
int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line);
|
||||||
|
|
||||||
|
extern enum cs_log_level cs_log_level;
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set file to write logs into. If `NULL`, logs go to `stderr`.
|
||||||
|
*/
|
||||||
void cs_log_set_file(FILE *file);
|
void cs_log_set_file(FILE *file);
|
||||||
|
|
||||||
extern enum cs_log_level cs_log_threshold;
|
/*
|
||||||
void cs_log_print_prefix(const char *func);
|
* Prints log to the current log file, appends "\n" in the end and flushes the
|
||||||
void cs_log_printf(const char *fmt, ...);
|
* stream.
|
||||||
|
*/
|
||||||
|
void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||||||
|
|
||||||
#define LOG(l, x) \
|
#if CS_ENABLE_STDIO
|
||||||
if (cs_log_threshold >= l) { \
|
|
||||||
cs_log_print_prefix(__func__); \
|
/*
|
||||||
cs_log_printf x; \
|
* Format and print message `x` with the given level `l`. Example:
|
||||||
}
|
*
|
||||||
|
* ```c
|
||||||
|
* LOG(LL_INFO, ("my info message: %d", 123));
|
||||||
|
* LOG(LL_DEBUG, ("my debug message: %d", 123));
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
#define LOG(l, x) \
|
||||||
|
do { \
|
||||||
|
if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
|
||||||
|
cs_log_printf x; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define LOG(l, x) ((void) l)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CS_NDEBUG
|
#ifndef CS_NDEBUG
|
||||||
|
|
||||||
#define DBG(x) \
|
/*
|
||||||
if (cs_log_threshold >= LL_VERBOSE_DEBUG) { \
|
* Shortcut for `LOG(LL_VERBOSE_DEBUG, (...))`
|
||||||
cs_log_print_prefix(__func__); \
|
*/
|
||||||
cs_log_printf x; \
|
#define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
|
||||||
}
|
|
||||||
|
|
||||||
#else /* NDEBUG */
|
#else /* NDEBUG */
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
#define BM222_ADDR 0x18
|
#define BM222_ADDR 0x18
|
||||||
#define TMP006_ADDR 0x41
|
#define TMP006_ADDR 0x41
|
||||||
|
|
||||||
void fs_slfs_set_new_file_size(const char *name, size_t size);
|
void fs_slfs_set_file_size(const char *name, size_t size);
|
||||||
|
|
||||||
static const char *upload_form =
|
static const char *upload_form =
|
||||||
"\
|
"\
|
||||||
@@ -70,7 +70,7 @@ static struct mg_str upload_fname(struct mg_connection *nc,
|
|||||||
if (nc->user_data != NULL) {
|
if (nc->user_data != NULL) {
|
||||||
intptr_t cl = (intptr_t) nc->user_data;
|
intptr_t cl = (intptr_t) nc->user_data;
|
||||||
if (cl >= 0) {
|
if (cl >= 0) {
|
||||||
fs_slfs_set_new_file_size(fn + 3, cl);
|
fs_slfs_set_file_size(fn + 3, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lfn.len = fname.len + 4;
|
lfn.len = fname.len + 4;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *e) {
|
|||||||
LOG(LL_INFO, ("WiFi: station disconnected"));
|
LOG(LL_INFO, ("WiFi: station disconnected"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(LL_INFO, ("WiFi: event %d", e->Event));
|
LOG(LL_INFO, ("WiFi: event %d", (int) e->Event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *e) {
|
|||||||
} else if (e->Event == SL_NETAPP_IP_LEASED_EVENT) {
|
} else if (e->Event == SL_NETAPP_IP_LEASED_EVENT) {
|
||||||
LOG(LL_INFO, ("IP leased"));
|
LOG(LL_INFO, ("IP leased"));
|
||||||
} else {
|
} else {
|
||||||
LOG(LL_INFO, ("NetApp event %d", e->Event));
|
LOG(LL_INFO, ("NetApp event %d", (int) e->Event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ static int s_done = 0;
|
|||||||
static int s_is_connected = 0;
|
static int s_is_connected = 0;
|
||||||
|
|
||||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
|
||||||
(void) nc;
|
(void) nc;
|
||||||
|
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
@@ -26,8 +25,14 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
|
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
|
||||||
printf("-- Connected\n");
|
struct http_message *hm = (struct http_message *) ev_data;
|
||||||
s_is_connected = 1;
|
if (hm->resp_code == 101) {
|
||||||
|
printf("-- Connected\n");
|
||||||
|
s_is_connected = 1;
|
||||||
|
} else {
|
||||||
|
printf("-- Connection failed! HTTP code %d\n", hm->resp_code);
|
||||||
|
/* Connection will be closed after this. */
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_POLL: {
|
case MG_EV_POLL: {
|
||||||
@@ -66,6 +71,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_WEBSOCKET_FRAME: {
|
case MG_EV_WEBSOCKET_FRAME: {
|
||||||
|
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||||
printf("%.*s\n", (int) wm->size, wm->data);
|
printf("%.*s\n", (int) wm->size, wm->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+551
-222
File diff suppressed because it is too large.
Load diff
+54
-12
@@ -23,7 +23,7 @@
|
|||||||
#ifndef CS_MONGOOSE_SRC_COMMON_H_
|
#ifndef CS_MONGOOSE_SRC_COMMON_H_
|
||||||
#define CS_MONGOOSE_SRC_COMMON_H_
|
#define CS_MONGOOSE_SRC_COMMON_H_
|
||||||
|
|
||||||
#define MG_VERSION "6.12"
|
#define MG_VERSION "6.14"
|
||||||
|
|
||||||
/* Local tweaks, applied before any of Mongoose's own headers. */
|
/* Local tweaks, applied before any of Mongoose's own headers. */
|
||||||
#ifdef MG_LOCALS
|
#ifdef MG_LOCALS
|
||||||
@@ -105,6 +105,7 @@
|
|||||||
#define MG_NET_IF_SIMPLELINK 2
|
#define MG_NET_IF_SIMPLELINK 2
|
||||||
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
||||||
#define MG_NET_IF_PIC32 4
|
#define MG_NET_IF_PIC32 4
|
||||||
|
#define MG_NET_IF_NULL 5
|
||||||
|
|
||||||
#define MG_SSL_IF_OPENSSL 1
|
#define MG_SSL_IF_OPENSSL 1
|
||||||
#define MG_SSL_IF_MBEDTLS 2
|
#define MG_SSL_IF_MBEDTLS 2
|
||||||
@@ -1530,7 +1531,7 @@ int sl_set_ssl_opts(int sock, struct mg_connection *nc);
|
|||||||
|
|
||||||
#endif /* SL_MAJOR_VERSION_NUM < 2 */
|
#endif /* SL_MAJOR_VERSION_NUM < 2 */
|
||||||
|
|
||||||
int slfs_open(const unsigned char *fname, uint32_t flags);
|
int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token);
|
||||||
|
|
||||||
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
|
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
|
||||||
|
|
||||||
@@ -1944,7 +1945,7 @@ char *inet_ntoa(struct in_addr in);
|
|||||||
#include <stm32_sdk_hal.h>
|
#include <stm32_sdk_hal.h>
|
||||||
|
|
||||||
#define to64(x) strtoll(x, NULL, 10)
|
#define to64(x) strtoll(x, NULL, 10)
|
||||||
#define INT64_FMT PRId64
|
#define INT64_FMT "lld"
|
||||||
#define SIZE_T_FMT "u"
|
#define SIZE_T_FMT "u"
|
||||||
typedef struct stat cs_stat_t;
|
typedef struct stat cs_stat_t;
|
||||||
#define DIRSEP '/'
|
#define DIRSEP '/'
|
||||||
@@ -2030,7 +2031,6 @@ typedef int sock_t;
|
|||||||
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
||||||
struct mg_mgr;
|
struct mg_mgr;
|
||||||
struct mg_connection;
|
struct mg_connection;
|
||||||
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr);
|
|
||||||
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
||||||
int interval, int count);
|
int interval, int count);
|
||||||
#endif
|
#endif
|
||||||
@@ -2239,6 +2239,8 @@ struct mg_str mg_mk_str_n(const char *s, size_t len);
|
|||||||
/* Macro for initializing mg_str. */
|
/* Macro for initializing mg_str. */
|
||||||
#define MG_MK_STR(str_literal) \
|
#define MG_MK_STR(str_literal) \
|
||||||
{ str_literal, sizeof(str_literal) - 1 }
|
{ str_literal, sizeof(str_literal) - 1 }
|
||||||
|
#define MG_MK_STR_N(str_literal, len) \
|
||||||
|
{ str_literal, len }
|
||||||
#define MG_NULL_STR \
|
#define MG_NULL_STR \
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
|
|
||||||
@@ -2278,6 +2280,11 @@ int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
|
|||||||
*/
|
*/
|
||||||
int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n);
|
int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the string (assuming it was heap allocated).
|
||||||
|
*/
|
||||||
|
void mg_strfree(struct mg_str *s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds the first occurrence of a substring `needle` in the `haystack`.
|
* Finds the first occurrence of a substring `needle` in the `haystack`.
|
||||||
*/
|
*/
|
||||||
@@ -2286,6 +2293,9 @@ const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle);
|
|||||||
/* Strip whitespace at the start and the end of s */
|
/* Strip whitespace at the start and the end of s */
|
||||||
struct mg_str mg_strstrip(struct mg_str s);
|
struct mg_str mg_strstrip(struct mg_str s);
|
||||||
|
|
||||||
|
/* Returns 1 if s starts with the given prefix. */
|
||||||
|
int mg_str_starts_with(struct mg_str s, struct mg_str prefix);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2312,8 +2322,6 @@ struct mg_str mg_strstrip(struct mg_str s);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* === Memory Buffers
|
|
||||||
*
|
|
||||||
* Mbufs are mutable/growing memory buffers, like C++ strings.
|
* Mbufs are mutable/growing memory buffers, like C++ strings.
|
||||||
* Mbuf can append data to the end of a buffer or insert data into arbitrary
|
* Mbuf can append data to the end of a buffer or insert data into arbitrary
|
||||||
* position in the middle of a buffer. The buffer grows automatically when
|
* position in the middle of a buffer. The buffer grows automatically when
|
||||||
@@ -2365,6 +2373,14 @@ void mbuf_free(struct mbuf *);
|
|||||||
*/
|
*/
|
||||||
size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
|
size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends data to the Mbuf and frees it (data must be heap-allocated).
|
||||||
|
*
|
||||||
|
* Returns the number of bytes appended or 0 if out of memory.
|
||||||
|
* data is freed irrespective of return value.
|
||||||
|
*/
|
||||||
|
size_t mbuf_append_and_free(struct mbuf *, void *data, size_t data_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inserts data at a specified offset in the Mbuf.
|
* Inserts data at a specified offset in the Mbuf.
|
||||||
*
|
*
|
||||||
@@ -2385,6 +2401,12 @@ void mbuf_remove(struct mbuf *, size_t data_size);
|
|||||||
*/
|
*/
|
||||||
void mbuf_resize(struct mbuf *, size_t new_size);
|
void mbuf_resize(struct mbuf *, size_t new_size);
|
||||||
|
|
||||||
|
/* Moves the state from one mbuf to the other. */
|
||||||
|
void mbuf_move(struct mbuf *from, struct mbuf *to);
|
||||||
|
|
||||||
|
/* Removes all the data from mbuf (if any). */
|
||||||
|
void mbuf_clear(struct mbuf *);
|
||||||
|
|
||||||
/* Shrinks an Mbuf by resizing its `size` to `len`. */
|
/* Shrinks an Mbuf by resizing its `size` to `len`. */
|
||||||
void mbuf_trim(struct mbuf *);
|
void mbuf_trim(struct mbuf *);
|
||||||
|
|
||||||
@@ -2625,6 +2647,8 @@ const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Like `mg_next_comma_list_entry()`, but takes `list` as `struct mg_str`.
|
* Like `mg_next_comma_list_entry()`, but takes `list` as `struct mg_str`.
|
||||||
|
* NB: Test return value's .p, not .len. On last itreation that yields result
|
||||||
|
* .len will be 0 but .p will not. When finished, .p will be NULL.
|
||||||
*/
|
*/
|
||||||
struct mg_str mg_next_comma_list_entry_n(struct mg_str list, struct mg_str *val,
|
struct mg_str mg_next_comma_list_entry_n(struct mg_str list, struct mg_str *val,
|
||||||
struct mg_str *eq_val);
|
struct mg_str *eq_val);
|
||||||
@@ -3718,6 +3742,12 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len,
|
|||||||
/* Deliver a POLL event to the connection. */
|
/* Deliver a POLL event to the connection. */
|
||||||
int mg_if_poll(struct mg_connection *nc, double now);
|
int mg_if_poll(struct mg_connection *nc, double now);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return minimal timer value amoung connections in the manager.
|
||||||
|
* Returns 0 if there aren't any timers.
|
||||||
|
*/
|
||||||
|
double mg_mgr_min_timer(const struct mg_mgr *mgr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
@@ -3875,6 +3905,7 @@ struct mg_mgr {
|
|||||||
#endif
|
#endif
|
||||||
void *user_data; /* User data */
|
void *user_data; /* User data */
|
||||||
int num_ifaces;
|
int num_ifaces;
|
||||||
|
int num_calls;
|
||||||
struct mg_iface **ifaces; /* network interfaces */
|
struct mg_iface **ifaces; /* network interfaces */
|
||||||
const char *nameserver; /* DNS server to use */
|
const char *nameserver; /* DNS server to use */
|
||||||
};
|
};
|
||||||
@@ -3925,6 +3956,7 @@ struct mg_connection {
|
|||||||
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
||||||
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
||||||
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
||||||
|
#define MG_F_RECV_AND_CLOSE (1 << 9) /* Drain rx and close the connection. */
|
||||||
|
|
||||||
/* Flags that are settable by user */
|
/* Flags that are settable by user */
|
||||||
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
||||||
@@ -3987,17 +4019,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data,
|
|||||||
*
|
*
|
||||||
* Closes and deallocates all active connections.
|
* Closes and deallocates all active connections.
|
||||||
*/
|
*/
|
||||||
void mg_mgr_free(struct mg_mgr *);
|
void mg_mgr_free(struct mg_mgr *mgr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function performs the actual IO and must be called in a loop
|
* This function performs the actual IO and must be called in a loop
|
||||||
* (an event loop). It returns the current timestamp.
|
* (an event loop). It returns number of user events generated (except POLLs).
|
||||||
* `milli` is the maximum number of milliseconds to sleep.
|
* `milli` is the maximum number of milliseconds to sleep.
|
||||||
* `mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
* `mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
||||||
* of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
* of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
||||||
* event handlers and returns.
|
* event handlers and returns.
|
||||||
*/
|
*/
|
||||||
time_t mg_mgr_poll(struct mg_mgr *, int milli);
|
int mg_mgr_poll(struct mg_mgr *mgr, int milli);
|
||||||
|
|
||||||
#if MG_ENABLE_BROADCAST
|
#if MG_ENABLE_BROADCAST
|
||||||
/*
|
/*
|
||||||
@@ -4010,7 +4042,7 @@ time_t mg_mgr_poll(struct mg_mgr *, int milli);
|
|||||||
* `func` callback function will be called by the IO thread for each
|
* `func` callback function will be called by the IO thread for each
|
||||||
* connection. When called, the event will be `MG_EV_POLL`, and a message will
|
* connection. When called, the event will be `MG_EV_POLL`, and a message will
|
||||||
* be passed as the `ev_data` pointer. Maximum message size is capped
|
* be passed as the `ev_data` pointer. Maximum message size is capped
|
||||||
* by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
|
* by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes by default.
|
||||||
*/
|
*/
|
||||||
void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data,
|
void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
@@ -4748,6 +4780,14 @@ struct mg_http_multipart_part {
|
|||||||
struct mg_str data;
|
struct mg_str data;
|
||||||
int status; /* <0 on error */
|
int status; /* <0 on error */
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
/*
|
||||||
|
* User handler can indicate how much of the data was consumed
|
||||||
|
* by setting this variable. By default, it is assumed that all
|
||||||
|
* data has been consumed by the handler.
|
||||||
|
* If not all data was consumed, user's handler will be invoked again later
|
||||||
|
* with the remainder.
|
||||||
|
*/
|
||||||
|
size_t num_data_consumed;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SSI call context */
|
/* SSI call context */
|
||||||
@@ -4766,7 +4806,7 @@ struct mg_ssi_call_ctx {
|
|||||||
|
|
||||||
#if MG_ENABLE_HTTP_WEBSOCKET
|
#if MG_ENABLE_HTTP_WEBSOCKET
|
||||||
#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* struct http_message * */
|
#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* struct http_message * */
|
||||||
#define MG_EV_WEBSOCKET_HANDSHAKE_DONE 112 /* NULL */
|
#define MG_EV_WEBSOCKET_HANDSHAKE_DONE 112 /* struct http_message * */
|
||||||
#define MG_EV_WEBSOCKET_FRAME 113 /* struct websocket_message * */
|
#define MG_EV_WEBSOCKET_FRAME 113 /* struct websocket_message * */
|
||||||
#define MG_EV_WEBSOCKET_CONTROL_FRAME 114 /* struct websocket_message * */
|
#define MG_EV_WEBSOCKET_CONTROL_FRAME 114 /* struct websocket_message * */
|
||||||
#endif
|
#endif
|
||||||
@@ -4805,7 +4845,9 @@ struct mg_ssi_call_ctx {
|
|||||||
* - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
* - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
||||||
* handshake request. `ev_data` contains parsed HTTP request.
|
* handshake request. `ev_data` contains parsed HTTP request.
|
||||||
* - MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
* - MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
||||||
* handshake. `ev_data` is `NULL`.
|
* handshake. `ev_data` is a `struct http_message` containing the
|
||||||
|
* client's request (server mode) or server's response (client).
|
||||||
|
* In client mode handler can examine `resp_code`, which should be 101.
|
||||||
* - MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
* - MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
||||||
* `struct websocket_message *`
|
* `struct websocket_message *`
|
||||||
*
|
*
|
||||||
|
|||||||
+53
-26
@@ -24,7 +24,7 @@
|
|||||||
#include "common/cs_time.h"
|
#include "common/cs_time.h"
|
||||||
#include "common/str_util.h"
|
#include "common/str_util.h"
|
||||||
|
|
||||||
enum cs_log_level cs_log_threshold WEAK =
|
enum cs_log_level cs_log_level WEAK =
|
||||||
#if CS_ENABLE_DEBUG
|
#if CS_ENABLE_DEBUG
|
||||||
LL_VERBOSE_DEBUG;
|
LL_VERBOSE_DEBUG;
|
||||||
#else
|
#else
|
||||||
@@ -32,10 +32,9 @@ enum cs_log_level cs_log_threshold WEAK =
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
static char *s_filter_pattern = NULL;
|
static char *s_file_level = NULL;
|
||||||
static size_t s_filter_pattern_len;
|
|
||||||
|
|
||||||
void cs_log_set_filter(const char *pattern) WEAK;
|
void cs_log_set_file_level(const char *file_level) WEAK;
|
||||||
|
|
||||||
FILE *cs_log_file WEAK = NULL;
|
FILE *cs_log_file WEAK = NULL;
|
||||||
|
|
||||||
@@ -45,34 +44,62 @@ double cs_log_ts WEAK;
|
|||||||
|
|
||||||
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
|
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
|
||||||
|
|
||||||
void cs_log_set_filter(const char *pattern) {
|
void cs_log_set_file_level(const char *file_level) {
|
||||||
free(s_filter_pattern);
|
char *fl = s_file_level;
|
||||||
if (pattern != NULL) {
|
if (file_level != NULL) {
|
||||||
s_filter_pattern = strdup(pattern);
|
s_file_level = strdup(file_level);
|
||||||
s_filter_pattern_len = strlen(pattern);
|
|
||||||
} else {
|
} else {
|
||||||
s_filter_pattern = NULL;
|
s_file_level = NULL;
|
||||||
s_filter_pattern_len = 0;
|
|
||||||
}
|
}
|
||||||
|
free(fl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cs_log_print_prefix(enum cs_log_level, const char *, const char *) WEAK;
|
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) WEAK;
|
||||||
int cs_log_print_prefix(enum cs_log_level level, const char *func,
|
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) {
|
||||||
const char *filename) {
|
char prefix[CS_LOG_PREFIX_LEN], *q;
|
||||||
char prefix[21];
|
const char *p;
|
||||||
|
size_t fl = 0, ll = 0, pl = 0;
|
||||||
|
|
||||||
if (level > cs_log_threshold) return 0;
|
if (level > cs_log_level && s_file_level == NULL) return 0;
|
||||||
if (s_filter_pattern != NULL &&
|
|
||||||
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) == 0 &&
|
p = file + strlen(file);
|
||||||
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) == 0) {
|
|
||||||
return 0;
|
while (p != file) {
|
||||||
|
const char c = *(p - 1);
|
||||||
|
if (c == '/' || c == '\\') break;
|
||||||
|
p--;
|
||||||
|
fl++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ll = (ln < 10000 ? (ln < 1000 ? (ln < 100 ? (ln < 10 ? 1 : 2) : 3) : 4) : 5);
|
||||||
|
if (fl > (sizeof(prefix) - ll - 2)) fl = (sizeof(prefix) - ll - 2);
|
||||||
|
|
||||||
|
pl = fl + 1 + ll;
|
||||||
|
memcpy(prefix, p, fl);
|
||||||
|
q = prefix + pl;
|
||||||
|
memset(q, ' ', sizeof(prefix) - pl);
|
||||||
|
do {
|
||||||
|
*(--q) = '0' + (ln % 10);
|
||||||
|
ln /= 10;
|
||||||
|
} while (ln > 0);
|
||||||
|
*(--q) = ':';
|
||||||
|
|
||||||
|
if (s_file_level != NULL) {
|
||||||
|
enum cs_log_level pll = cs_log_level;
|
||||||
|
struct mg_str fl = mg_mk_str(s_file_level), ps = MG_MK_STR_N(prefix, pl);
|
||||||
|
struct mg_str k, v;
|
||||||
|
while ((fl = mg_next_comma_list_entry_n(fl, &k, &v)).p != NULL) {
|
||||||
|
bool yes = !(!mg_str_starts_with(ps, k) || v.len == 0);
|
||||||
|
if (!yes) continue;
|
||||||
|
pll = (enum cs_log_level)(*v.p - '0');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (level > pll) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(prefix, func, 20);
|
|
||||||
prefix[20] = '\0';
|
|
||||||
if (cs_log_file == NULL) cs_log_file = stderr;
|
if (cs_log_file == NULL) cs_log_file = stderr;
|
||||||
cs_log_cur_msg_level = level;
|
cs_log_cur_msg_level = level;
|
||||||
fprintf(cs_log_file, "%-20s ", prefix);
|
fwrite(prefix, 1, sizeof(prefix), cs_log_file);
|
||||||
#if CS_LOG_ENABLE_TS_DIFF
|
#if CS_LOG_ENABLE_TS_DIFF
|
||||||
{
|
{
|
||||||
double now = cs_time();
|
double now = cs_time();
|
||||||
@@ -101,15 +128,15 @@ void cs_log_set_file(FILE *file) {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void cs_log_set_filter(const char *pattern) {
|
void cs_log_set_file_level(const char *file_level) {
|
||||||
(void) pattern;
|
(void) file_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CS_ENABLE_STDIO */
|
#endif /* CS_ENABLE_STDIO */
|
||||||
|
|
||||||
void cs_log_set_level(enum cs_log_level level) WEAK;
|
void cs_log_set_level(enum cs_log_level level) WEAK;
|
||||||
void cs_log_set_level(enum cs_log_level level) {
|
void cs_log_set_level(enum cs_log_level level) {
|
||||||
cs_log_threshold = level;
|
cs_log_level = level;
|
||||||
#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
|
#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
|
||||||
cs_log_ts = cs_time();
|
cs_log_ts = cs_time();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+22
-39
@@ -28,6 +28,10 @@
|
|||||||
#define CS_ENABLE_DEBUG 0
|
#define CS_ENABLE_DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CS_LOG_PREFIX_LEN
|
||||||
|
#define CS_LOG_PREFIX_LEN 24
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CS_LOG_ENABLE_TS_DIFF
|
#ifndef CS_LOG_ENABLE_TS_DIFF
|
||||||
#define CS_LOG_ENABLE_TS_DIFF 0
|
#define CS_LOG_ENABLE_TS_DIFF 0
|
||||||
#endif
|
#endif
|
||||||
@@ -58,51 +62,28 @@ enum cs_log_level {
|
|||||||
void cs_log_set_level(enum cs_log_level level);
|
void cs_log_set_level(enum cs_log_level level);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set log filter. NULL (a default) logs everything.
|
* A comma-separated set of prefix=level.
|
||||||
* Otherwise, function name and file name will be tested against the given
|
* prefix is matched against the log prefix exactly as printed, including line
|
||||||
* pattern, and only matching messages will be printed.
|
* number, but partial match is ok. Check stops on first matching entry.
|
||||||
|
* If nothing matches, default level is used.
|
||||||
*
|
*
|
||||||
* For the pattern syntax, refer to `mg_match_prefix()` in `str_util.h`.
|
* Examples:
|
||||||
|
* main.c:=4 - everything from main C at verbose debug level.
|
||||||
|
* mongoose.c=1,mjs.c=1,=4 - everything at verbose debug except mg_* and mjs_*
|
||||||
*
|
*
|
||||||
* Example:
|
|
||||||
* ```c
|
|
||||||
* void foo(void) {
|
|
||||||
* LOG(LL_INFO, ("hello from foo"));
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* void bar(void) {
|
|
||||||
* LOG(LL_INFO, ("hello from bar"));
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* void test(void) {
|
|
||||||
* cs_log_set_filter(NULL);
|
|
||||||
* foo();
|
|
||||||
* bar();
|
|
||||||
*
|
|
||||||
* cs_log_set_filter("f*");
|
|
||||||
* foo();
|
|
||||||
* bar(); // Will NOT print anything
|
|
||||||
*
|
|
||||||
* cs_log_set_filter("bar");
|
|
||||||
* foo(); // Will NOT print anything
|
|
||||||
* bar();
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
void cs_log_set_filter(const char *pattern);
|
void cs_log_set_file_level(const char *file_level);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function which prints message prefix with the given `level`, function
|
* Helper function which prints message prefix with the given `level`.
|
||||||
* name `func` and `filename`. If message should be printed (accordingly to the
|
* If message should be printed (according to the current log level
|
||||||
* current log level and filter), prints the prefix and returns 1, otherwise
|
* and filter), prints the prefix and returns 1, otherwise returns 0.
|
||||||
* returns 0.
|
|
||||||
*
|
*
|
||||||
* Clients should typically just use `LOG()` macro.
|
* Clients should typically just use `LOG()` macro.
|
||||||
*/
|
*/
|
||||||
int cs_log_print_prefix(enum cs_log_level level, const char *func,
|
int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line);
|
||||||
const char *filename);
|
|
||||||
|
|
||||||
extern enum cs_log_level cs_log_threshold;
|
extern enum cs_log_level cs_log_level;
|
||||||
|
|
||||||
#if CS_ENABLE_STDIO
|
#if CS_ENABLE_STDIO
|
||||||
|
|
||||||
@@ -127,9 +108,11 @@ void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
|||||||
* LOG(LL_DEBUG, ("my debug message: %d", 123));
|
* LOG(LL_DEBUG, ("my debug message: %d", 123));
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
#define LOG(l, x) \
|
#define LOG(l, x) \
|
||||||
do { \
|
do { \
|
||||||
if (cs_log_print_prefix(l, __func__, __FILE__)) cs_log_printf x; \
|
if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
|
||||||
|
cs_log_printf x; \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
#define MG_NET_IF_SIMPLELINK 2
|
#define MG_NET_IF_SIMPLELINK 2
|
||||||
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
||||||
#define MG_NET_IF_PIC32 4
|
#define MG_NET_IF_PIC32 4
|
||||||
|
#define MG_NET_IF_NULL 5
|
||||||
|
|
||||||
#define MG_SSL_IF_OPENSSL 1
|
#define MG_SSL_IF_OPENSSL 1
|
||||||
#define MG_SSL_IF_MBEDTLS 2
|
#define MG_SSL_IF_MBEDTLS 2
|
||||||
|
|||||||
@@ -27,6 +27,10 @@
|
|||||||
#include "mgos_core_dump.h"
|
#include "mgos_core_dump.h"
|
||||||
#include "mgos_hal.h"
|
#include "mgos_hal.h"
|
||||||
|
|
||||||
|
#ifndef MGOS_ENABLE_CORE_DUMP
|
||||||
|
#define MGOS_ENABLE_CORE_DUMP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
struct arm_exc_frame {
|
struct arm_exc_frame {
|
||||||
uint32_t r0;
|
uint32_t r0;
|
||||||
uint32_t r1;
|
uint32_t r1;
|
||||||
@@ -53,7 +57,7 @@ struct arm_gdb_reg_file {
|
|||||||
uint32_t fpscr;
|
uint32_t fpscr;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#if ARM_HAVE_FPU
|
#if ARM_HAVE_FPU && !defined(MGOS_BOOT_BUILD)
|
||||||
static void save_s16_s31(uint32_t *dst) {
|
static void save_s16_s31(uint32_t *dst) {
|
||||||
__asm volatile(
|
__asm volatile(
|
||||||
"\
|
"\
|
||||||
@@ -91,6 +95,7 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
struct arm_gdb_reg_file *rf) {
|
struct arm_gdb_reg_file *rf) {
|
||||||
char buf[8];
|
char buf[8];
|
||||||
const char *name;
|
const char *name;
|
||||||
|
(void) ef;
|
||||||
portDISABLE_INTERRUPTS();
|
portDISABLE_INTERRUPTS();
|
||||||
switch (isr_no) {
|
switch (isr_no) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -134,16 +139,20 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
name = "SysTick";
|
name = "SysTick";
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
|
#ifndef MGOS_BOOT_BUILD
|
||||||
sprintf(buf, "IRQ%u", isr_no - 16);
|
sprintf(buf, "IRQ%u", isr_no - 16);
|
||||||
|
#endif
|
||||||
name = buf;
|
name = buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mgos_cd_printf("\n\n--- Exception %u (%s) ---\n", isr_no, name);
|
mgos_cd_printf("\n\n--- Exception %u (%s) ---\n", isr_no, name);
|
||||||
if (rf != NULL) {
|
if (rf != NULL) {
|
||||||
mgos_cd_printf(" R0: 0x%08lx R1: 0x%08lx R2: 0x%08lx R3: 0x%08lx\n",
|
mgos_cd_printf(
|
||||||
rf->r[0], rf->r[1], rf->r[2], rf->r[3]);
|
" R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx\n", 0,
|
||||||
mgos_cd_printf(" R4: 0x%08lx R5: 0x%08lx R6: 0x%08lx R7: 0x%08lx\n",
|
rf->r[0], 1, rf->r[1], 2, rf->r[2], 3, rf->r[3]);
|
||||||
rf->r[4], rf->r[5], rf->r[6], rf->r[7]);
|
mgos_cd_printf(
|
||||||
|
" R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx R%d: 0x%08lx\n", 4,
|
||||||
|
rf->r[4], 5, rf->r[5], 6, rf->r[6], 7, rf->r[7]);
|
||||||
mgos_cd_printf(" R8: 0x%08lx R9: 0x%08lx R10: 0x%08lx R11: 0x%08lx\n",
|
mgos_cd_printf(" R8: 0x%08lx R9: 0x%08lx R10: 0x%08lx R11: 0x%08lx\n",
|
||||||
rf->r[8], rf->r[9], rf->r[10], rf->r[11]);
|
rf->r[8], rf->r[9], rf->r[10], rf->r[11]);
|
||||||
mgos_cd_printf(" R12: 0x%08lx SP: 0x%08lx LR: 0x%08lx PC: 0x%08lx\n",
|
mgos_cd_printf(" R12: 0x%08lx SP: 0x%08lx LR: 0x%08lx PC: 0x%08lx\n",
|
||||||
@@ -151,7 +160,7 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
mgos_cd_printf(" PSR: 0x%08lx\n", rf->cpsr);
|
mgos_cd_printf(" PSR: 0x%08lx\n", rf->cpsr);
|
||||||
}
|
}
|
||||||
memset(rf->d, 0, sizeof(rf->d));
|
memset(rf->d, 0, sizeof(rf->d));
|
||||||
#if ARM_HAVE_FPU
|
#if ARM_HAVE_FPU && !defined(MGOS_BOOT_BUILD)
|
||||||
rf->fpscr = ef->fpscr;
|
rf->fpscr = ef->fpscr;
|
||||||
memcpy((uint8_t *) rf->d, ef->s, sizeof(ef->s));
|
memcpy((uint8_t *) rf->d, ef->s, sizeof(ef->s));
|
||||||
print_fpu_regs((uint32_t *) rf->d, 0, ARRAY_SIZE(ef->s));
|
print_fpu_regs((uint32_t *) rf->d, 0, ARRAY_SIZE(ef->s));
|
||||||
@@ -164,10 +173,12 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
|||||||
#else
|
#else
|
||||||
rf->fpscr = 0;
|
rf->fpscr = 0;
|
||||||
#endif
|
#endif
|
||||||
|
#if MGOS_ENABLE_CORE_DUMP
|
||||||
mgos_cd_emit_header();
|
mgos_cd_emit_header();
|
||||||
mgos_cd_emit_section(MGOS_CORE_DUMP_SECTION_REGS, rf, sizeof(*rf));
|
mgos_cd_emit_section(MGOS_CORE_DUMP_SECTION_REGS, rf, sizeof(*rf));
|
||||||
mgos_cd_emit_section("SRAM", (void *) SRAM_BASE_ADDR, SRAM_SIZE);
|
mgos_cd_emit_section("SRAM", (void *) SRAM_BASE_ADDR, SRAM_SIZE);
|
||||||
mgos_cd_emit_footer();
|
mgos_cd_emit_footer();
|
||||||
|
#endif
|
||||||
#ifdef MGOS_HALT_ON_EXCEPTION
|
#ifdef MGOS_HALT_ON_EXCEPTION
|
||||||
mgos_cd_printf("Halting\n");
|
mgos_cd_printf("Halting\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2019 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.arch armv7e-m
|
||||||
|
.syntax unified
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
/* These are required to satisfy TI linker. */
|
||||||
|
.eabi_attribute Tag_ABI_align_needed, 1
|
||||||
|
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||||
|
|
||||||
|
.global mgos_nsleep100_impl
|
||||||
|
.global mgos_nsleep100_loop_count
|
||||||
|
|
||||||
|
#ifdef STM32
|
||||||
|
.section .RamFunc.mgos_nsleep100_impl
|
||||||
|
#else
|
||||||
|
.section .iram.mgos_nsleep100_impl
|
||||||
|
#endif
|
||||||
|
.type mgos_nsleep100_impl, %function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
mgos_nsleep100_impl:
|
||||||
|
ldr r3, =mgos_nsleep100_loop_count
|
||||||
|
ldr r3, [r3]
|
||||||
|
mul r0, r3
|
||||||
|
mov r1, #6
|
||||||
|
udiv r0, r0, r1
|
||||||
|
cbz r0, xxx
|
||||||
|
lxx:
|
||||||
|
subs r0, #1
|
||||||
|
bne lxx
|
||||||
|
xxx:
|
||||||
|
bx lr
|
||||||
|
.align 4
|
||||||
|
.size mgos_nsleep100_impl, . - mgos_nsleep100_impl
|
||||||
@@ -26,7 +26,11 @@
|
|||||||
.global mgos_nsleep100_impl
|
.global mgos_nsleep100_impl
|
||||||
.global mgos_nsleep100_loop_count
|
.global mgos_nsleep100_loop_count
|
||||||
|
|
||||||
|
#ifdef STM32
|
||||||
|
.section .RamFunc.mgos_nsleep100_impl
|
||||||
|
#else
|
||||||
.section .iram.mgos_nsleep100_impl
|
.section .iram.mgos_nsleep100_impl
|
||||||
|
#endif
|
||||||
.type mgos_nsleep100_impl, %function
|
.type mgos_nsleep100_impl, %function
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
@@ -34,7 +38,11 @@ mgos_nsleep100_impl:
|
|||||||
ldr r3, =mgos_nsleep100_loop_count
|
ldr r3, =mgos_nsleep100_loop_count
|
||||||
ldr r3, [r3]
|
ldr r3, [r3]
|
||||||
mul r0, r3
|
mul r0, r3
|
||||||
|
#ifdef STM32L4
|
||||||
|
mov r1, #3
|
||||||
|
#else
|
||||||
mov r1, #6
|
mov r1, #6
|
||||||
|
#endif
|
||||||
udiv r0, r0, r1
|
udiv r0, r0, r1
|
||||||
cbz r0, xxx
|
cbz r0, xxx
|
||||||
lxx:
|
lxx:
|
||||||
|
|||||||
@@ -26,7 +26,11 @@
|
|||||||
.global mgos_nsleep100_impl
|
.global mgos_nsleep100_impl
|
||||||
.global mgos_nsleep100_loop_count
|
.global mgos_nsleep100_loop_count
|
||||||
|
|
||||||
|
#ifdef STM32
|
||||||
|
.section .RamFunc.mgos_nsleep100_impl
|
||||||
|
#else
|
||||||
.section .iram.mgos_nsleep100_impl
|
.section .iram.mgos_nsleep100_impl
|
||||||
|
#endif
|
||||||
.type mgos_nsleep100_impl, %function
|
.type mgos_nsleep100_impl, %function
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ $(SDK_OBJS): CFLAGS += -include common/platform.h
|
|||||||
|
|
||||||
# cc flags,file
|
# cc flags,file
|
||||||
define cc
|
define cc
|
||||||
$(vecho) "GCC $2 -> $@"
|
$(vecho) "GCC $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c $1 -o $@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c $1 -o $@ $2
|
||||||
endef
|
endef
|
||||||
define cxx
|
define cxx
|
||||||
$(vecho) "G++ $2 -> $@"
|
$(vecho) "G++ $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CXX) -c $1 -o $@ $2
|
$(Q) $(CC_WRAPPER) $(CXX) -c $1 -o $@ $2
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|||||||
@@ -17,17 +17,17 @@ CXXFLAGS += $(TI_C_CXX_FLAGS) $(C_CXX_FLAGS)
|
|||||||
|
|
||||||
# cc flags,file
|
# cc flags,file
|
||||||
define cc
|
define cc
|
||||||
$(vecho) "TICC $2 -> $@"
|
$(vecho) "TICC $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
||||||
endef
|
endef
|
||||||
define cxx
|
define cxx
|
||||||
$(vecho) "TICXX $2 -> $@"
|
$(vecho) "TICXX $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# asm flags,file
|
# asm flags,file
|
||||||
define asm
|
define asm
|
||||||
$(vecho) "TIASM $2 -> $@"
|
$(vecho) "TIASM $2"
|
||||||
$(Q) $(CC_WRAPPER) $(CC) -c $1 --output_file=$@ $2
|
$(Q) $(CC_WRAPPER) $(CC) -c $1 --output_file=$@ $2
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include "eagle_soc.h"
|
#include "eagle_soc.h"
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
#include "../../../miniz.c"
|
#include "miniz.c"
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
#include "rom/efuse.h"
|
#include "rom/efuse.h"
|
||||||
#include "rom/miniz.h"
|
#include "rom/miniz.h"
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
/* Param: baud rate. */
|
/* Param: baud rate. */
|
||||||
uint32_t params[1] __attribute__((section(".params")));
|
uint32_t params[2] __attribute__((section(".params")));
|
||||||
|
|
||||||
#define FLASH_BLOCK_SIZE 65536
|
#define FLASH_BLOCK_SIZE 65536
|
||||||
#define FLASH_SECTOR_SIZE 4096
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
@@ -470,6 +470,27 @@ uint8_t cmd_loop(void) {
|
|||||||
resp = 0;
|
resp = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CMD_READ_REG: {
|
||||||
|
len = SLIP_recv(args, sizeof(args));
|
||||||
|
if (len == 4) {
|
||||||
|
uint32_t value = READ_PERI_REG((uint32_t *) args[0]);
|
||||||
|
SLIP_send(&value, sizeof(value));
|
||||||
|
resp = 0;
|
||||||
|
} else {
|
||||||
|
resp = 0x91;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_WRITE_REG: {
|
||||||
|
len = SLIP_recv(args, sizeof(args));
|
||||||
|
if (len == 8) {
|
||||||
|
WRITE_PERI_REG((uint32_t *) args[0], args[1]);
|
||||||
|
resp = 0;
|
||||||
|
} else {
|
||||||
|
resp = 0xa1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SLIP_send(&resp, 1);
|
SLIP_send(&resp, 1);
|
||||||
} while (cmd != CMD_BOOT_FW && cmd != CMD_REBOOT);
|
} while (cmd != CMD_BOOT_FW && cmd != CMD_REBOOT);
|
||||||
@@ -477,8 +498,7 @@ uint8_t cmd_loop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stub_main1(void) {
|
void stub_main1(void) {
|
||||||
uint32_t baud_rate = params[0];
|
uint32_t old_baud_rate = params[0], new_baud_rate = params[1];
|
||||||
uint32_t greeting = 0x4941484f; /* OHAI */
|
|
||||||
uint8_t last_cmd;
|
uint8_t last_cmd;
|
||||||
|
|
||||||
/* This points at us right now, reset for next boot. */
|
/* This points at us right now, reset for next boot. */
|
||||||
@@ -487,6 +507,7 @@ void stub_main1(void) {
|
|||||||
/* Selects SPI functions for flash pins. */
|
/* Selects SPI functions for flash pins. */
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
SelectSpiFunction();
|
SelectSpiFunction();
|
||||||
|
spi_flash_attach();
|
||||||
SET_PERI_REG_MASK(0x3FF00014, 1); /* Switch to 160 MHz */
|
SET_PERI_REG_MASK(0x3FF00014, 1); /* Switch to 160 MHz */
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), 0 /* legacy */);
|
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), 0 /* legacy */);
|
||||||
@@ -496,9 +517,10 @@ void stub_main1(void) {
|
|||||||
0 /* deviceId */, 16 * 1024 * 1024 /* chip_size */, FLASH_BLOCK_SIZE,
|
0 /* deviceId */, 16 * 1024 * 1024 /* chip_size */, FLASH_BLOCK_SIZE,
|
||||||
FLASH_SECTOR_SIZE, FLASH_PAGE_SIZE, 0xffff /* status_mask */);
|
FLASH_SECTOR_SIZE, FLASH_PAGE_SIZE, 0xffff /* status_mask */);
|
||||||
|
|
||||||
if (baud_rate > 0) {
|
uint32_t old_div = 0;
|
||||||
|
if (new_baud_rate > 0) {
|
||||||
ets_delay_us(10000);
|
ets_delay_us(10000);
|
||||||
set_baud_rate(0, baud_rate);
|
old_div = set_baud_rate(0, old_baud_rate, new_baud_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give host time to get ready too. */
|
/* Give host time to get ready too. */
|
||||||
@@ -509,7 +531,7 @@ void stub_main1(void) {
|
|||||||
WRITE_PERI_REG(UART_FIFO_REG(0), 0x55);
|
WRITE_PERI_REG(UART_FIFO_REG(0), 0x55);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
SLIP_send(&greeting, 4);
|
SLIP_send(&old_div, 4);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
last_cmd = cmd_loop();
|
last_cmd = cmd_loop();
|
||||||
@@ -525,7 +547,7 @@ void stub_main1(void) {
|
|||||||
* then jumps to 0x4000108a, then checks strapping bits again (which will
|
* then jumps to 0x4000108a, then checks strapping bits again (which will
|
||||||
* not have changed), and then proceeds to 0x400010a8.
|
* not have changed), and then proceeds to 0x400010a8.
|
||||||
*/
|
*/
|
||||||
volatile uint32_t *sp = &baud_rate;
|
volatile uint32_t *sp = &old_baud_rate;
|
||||||
while (*sp != (uint32_t) 0x40001100) sp++;
|
while (*sp != (uint32_t) 0x40001100) sp++;
|
||||||
*sp = 0x400010a8;
|
*sp = 0x400010a8;
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -91,6 +91,24 @@ enum stub_cmd {
|
|||||||
* Output: arguments.
|
* Output: arguments.
|
||||||
*/
|
*/
|
||||||
CMD_ECHO = 8,
|
CMD_ECHO = 8,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read register value.
|
||||||
|
*
|
||||||
|
* Args: register address.
|
||||||
|
* Input: None.
|
||||||
|
* Output: register value.
|
||||||
|
*/
|
||||||
|
CMD_READ_REG = 9,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write register value.
|
||||||
|
*
|
||||||
|
* Args: register address, value.
|
||||||
|
* Input: None.
|
||||||
|
* Output: None.
|
||||||
|
*/
|
||||||
|
CMD_WRITE_REG = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_STUB_FLASHER_H_ */
|
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_STUB_FLASHER_H_ */
|
||||||
@@ -42,5 +42,10 @@ SECTIONS {
|
|||||||
INCLUDE "components/esp32/ld/esp32.rom.ld"
|
INCLUDE "components/esp32/ld/esp32.rom.ld"
|
||||||
INCLUDE "components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld"
|
INCLUDE "components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld"
|
||||||
|
|
||||||
|
PROVIDE(ets_isr_mask = 0x400067fc);
|
||||||
|
PROVIDE(ets_isr_unmask = 0x40006808);
|
||||||
|
PROVIDE(MD5Init = 0x4005da7c);
|
||||||
|
PROVIDE(MD5Update = 0x4005da9c);
|
||||||
|
PROVIDE(MD5Final = 0x4005db1c);
|
||||||
PROVIDE(esp_rom_spiflash_attach = 0x40062a6c);
|
PROVIDE(esp_rom_spiflash_attach = 0x40062a6c);
|
||||||
PROVIDE(esp_rom_spiflash_config_clk = 0x40062bc8);
|
PROVIDE(esp_rom_spiflash_config_clk = 0x40062bc8);
|
||||||
@@ -19,9 +19,13 @@
|
|||||||
|
|
||||||
#include "rom_functions.h"
|
#include "rom_functions.h"
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate) {
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
uint32_t master_freq = ets_get_detected_xtal_freq() << 4;
|
uint32_t new_baud_rate) {
|
||||||
master_freq += (baud_rate / 2);
|
uint32_t uart_reg = REG_READ(UART_CLKDIV_REG(uart_no));
|
||||||
uint32_t div = master_freq / baud_rate;
|
uint32_t uart_div = uart_reg & UART_CLKDIV_M;
|
||||||
uart_div_modify(uart_no, div);
|
uint32_t fraction = (uart_reg >> UART_CLKDIV_FRAG_S) & UART_CLKDIV_FRAG_V;
|
||||||
|
uart_div = (uart_div << 4) + fraction;
|
||||||
|
uint32_t master_freq = uart_div * old_baud_rate;
|
||||||
|
uart_div_modify(uart_no, master_freq / new_baud_rate);
|
||||||
|
return uart_div;
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate);
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
|
uint32_t new_baud_rate);
|
||||||
|
|
||||||
#endif /* CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_ */
|
#endif /* CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_ */
|
||||||
@@ -44,80 +44,3 @@ void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[],
|
|||||||
const size_t *msg_lens, uint8_t *digest) {
|
const size_t *msg_lens, uint8_t *digest) {
|
||||||
(void) sha1_vector(num_msgs, msgs, msg_lens, digest);
|
(void) sha1_vector(num_msgs, msgs, msg_lens, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ENABLE_SSL
|
|
||||||
|
|
||||||
#include "mbedtls/aes.h"
|
|
||||||
#include "mbedtls/sha256.h"
|
|
||||||
|
|
||||||
#define AES_PRIV_NR_POS (4 * 15)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Crypto functions in ROM/SDK.
|
|
||||||
* They come from wpa_supplicant, you can find them here https://w1.fi/cgit/
|
|
||||||
*
|
|
||||||
* Note that ROM version of the key setup function is older, does not take the
|
|
||||||
* number of bits argument and only supports AES-128. This prototype doesn't
|
|
||||||
* suit it, but since the difference is in the last aegument, it doesn't matter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void rijndaelKeySetupDec(void *ctx, const uint8_t *key, int bits);
|
|
||||||
extern int rijndaelKeySetupEnc(void *ctx, const uint8_t *key, int bits);
|
|
||||||
void aes_encrypt(void *ctx, const uint8_t *plain, uint8_t *crypt);
|
|
||||||
void aes_decrypt(void *ctx, const uint8_t *crypt, uint8_t *plain);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AES that comes with wpa_supplicant allocates its own AES context in
|
|
||||||
* aes_{encrypt,decrypt}_init. Ideally, we'd take that pointer and store it in
|
|
||||||
* our mbedtls_aes_context, but then a lot of space would be wasted.
|
|
||||||
* We do not call _init and go directly to key setup functions and poke number
|
|
||||||
* of rounds into the right place too. This is a bit hacky, but works fine.
|
|
||||||
* There is also a difference between older function in ROM and the one coming
|
|
||||||
* with SDK which is newer: the older one actually takes two arguments, not 3.
|
|
||||||
* But it doesn't matter, extra argument doesn't hurt and this works with both.
|
|
||||||
*/
|
|
||||||
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
|
|
||||||
unsigned int keybits) {
|
|
||||||
if (keybits != 128) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
|
||||||
((uint32_t *) ctx)[AES_PRIV_NR_POS] = 10;
|
|
||||||
rijndaelKeySetupEnc(ctx, key, 128);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
|
|
||||||
unsigned int keybits) {
|
|
||||||
if (keybits != 128) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
|
||||||
((uint32_t *) ctx)[AES_PRIV_NR_POS] = 10;
|
|
||||||
rijndaelKeySetupDec(ctx, key, 128);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,
|
|
||||||
const unsigned char input[16],
|
|
||||||
unsigned char output[16]) {
|
|
||||||
aes_encrypt(ctx, input, output);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
|
|
||||||
const unsigned char input[16],
|
|
||||||
unsigned char output[16]) {
|
|
||||||
aes_decrypt(ctx, input, output);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* os_get_random uses hardware RNG, so it's cool. */
|
|
||||||
int mg_ssl_if_mbed_random(void *ctx, unsigned char *buf, size_t len) {
|
|
||||||
os_get_random(buf, len);
|
|
||||||
(void) ctx;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For CryptoAuthLib host crypto. */
|
|
||||||
int atcac_sw_sha2_256(const uint8_t *data, size_t data_size,
|
|
||||||
uint8_t digest[32]) {
|
|
||||||
mbedtls_sha256(data, data_size, digest, false /* is_224 */);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MG_ENABLE_SSL */
|
|
||||||
@@ -23,13 +23,13 @@ all: $(STUB_ELF)
|
|||||||
$(STUB_ELF): $(STUB) $(LIBS)
|
$(STUB_ELF): $(STUB) $(LIBS)
|
||||||
@echo " CC $^ -> $@"
|
@echo " CC $^ -> $@"
|
||||||
@[ -d $(BUILD_DIR) ] || mkdir $(BUILD_DIR)
|
@[ -d $(BUILD_DIR) ] || mkdir $(BUILD_DIR)
|
||||||
@docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||||
"cd /src/common/platforms/esp8266/stubs && \
|
"cd /src/common/platforms/esp8266/stubs && \
|
||||||
$(XT_CC) -std=c99 -Wall -Werror -Os -DESP8266 \
|
$(XT_CC) -std=c99 -Wall -Werror -Os -DESP8266 \
|
||||||
-mtext-section-literals -mlongcalls -nostdlib -fno-builtin \
|
-mtext-section-literals -mlongcalls -nostdlib -fno-builtin \
|
||||||
-I. -I/src/common/platforms/esp \
|
-I. -I/src/common/platforms/esp -I/src/common/platforms/esp8266 \
|
||||||
-I/opt/Espressif/ESP8266_SDK \
|
-I/opt/Espressif/ESP8266_SDK \
|
||||||
-Wl,-static -ffunction-sections -Wl,--gc-sections \
|
-Wl,-static -ffunction-sections -lgcc -Wl,--gc-sections \
|
||||||
-Tstub.ld $(CFLAGS) -o $@ $^"
|
-Tstub.ld $(CFLAGS) -o $@ $^"
|
||||||
|
|
||||||
wrap: $(STUB_JSON)
|
wrap: $(STUB_JSON)
|
||||||
|
|||||||
@@ -41,3 +41,4 @@ INCLUDE "eagle.rom.addr.v6.ld"
|
|||||||
PROVIDE(SPIFlashModeConfig = 0x40004568);
|
PROVIDE(SPIFlashModeConfig = 0x40004568);
|
||||||
PROVIDE(SPI_erase_sector = 0x400040c0);
|
PROVIDE(SPI_erase_sector = 0x400040c0);
|
||||||
PROVIDE(SPI_erase_block = 0x40004120);
|
PROVIDE(SPI_erase_block = 0x40004120);
|
||||||
|
PROVIDE(uart_div_modify = 0x400039d8);
|
||||||
@@ -18,9 +18,15 @@
|
|||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
|
|
||||||
#define UART_CLKDIV_26MHZ(B) (52000000 + B / 2) / B
|
#define UART_CLKDIV_M (UART_CLKDIV_CNT << UART_CLKDIV_S)
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate) {
|
void uart_div_modify(uint8_t uart_no, uint32_t div);
|
||||||
uint32_t div = UART_CLKDIV_26MHZ(baud_rate);
|
|
||||||
WRITE_PERI_REG(UART_CLKDIV_REG(uart_no), div & 0xfffff);
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
|
uint32_t new_baud_rate) {
|
||||||
|
uint32_t uart_reg = READ_PERI_REG(UART_CLKDIV_REG(uart_no));
|
||||||
|
uint32_t uart_div = uart_reg & UART_CLKDIV_M;
|
||||||
|
uint32_t master_freq = uart_div * old_baud_rate;
|
||||||
|
uart_div_modify(uart_no, master_freq / new_baud_rate);
|
||||||
|
return uart_div;
|
||||||
}
|
}
|
||||||
@@ -20,9 +20,11 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate);
|
#include "uart_register.h"
|
||||||
|
|
||||||
|
uint32_t set_baud_rate(uint32_t uart_no, uint32_t old_baud_rate,
|
||||||
|
uint32_t new_baud_rate);
|
||||||
|
|
||||||
#define REG_UART_BASE(i) (0x60000000 + (i) *0xf00)
|
|
||||||
#define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0)
|
#define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0)
|
||||||
#define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24)
|
#define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24)
|
||||||
#define UART_RX_TOUT_EN (BIT(31))
|
#define UART_RX_TOUT_EN (BIT(31))
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
# Analyzers output of firmware compiler with -DESP_ENABLE_MALLOC_TRACES
|
|
||||||
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
allocs = {}
|
|
||||||
|
|
||||||
for l in sys.stdin:
|
|
||||||
m = re.match(r'(ca|ma|re|fr) (\S+)\s*(\S*)\s*(\S*)', l)
|
|
||||||
if not m: continue
|
|
||||||
op = m.group(1)
|
|
||||||
if op in ('ca', 'ma'):
|
|
||||||
allocs[m.group(2)] = long(m.group(3))
|
|
||||||
else:
|
|
||||||
if m.group(2) in allocs:
|
|
||||||
del allocs[m.group(2)]
|
|
||||||
if op == 're':
|
|
||||||
allocs[m.group(3)] = long(m.group(4))
|
|
||||||
|
|
||||||
for k, v in sorted(allocs.iteritems()):
|
|
||||||
print k, v
|
|
||||||
@@ -66,7 +66,6 @@ typedef int sock_t;
|
|||||||
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
||||||
struct mg_mgr;
|
struct mg_mgr;
|
||||||
struct mg_connection;
|
struct mg_connection;
|
||||||
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr);
|
|
||||||
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
||||||
int interval, int count);
|
int interval, int count);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_SIG_CLOSE_CONN: {
|
case MG_SIG_CLOSE_CONN: {
|
||||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
|
||||||
mg_close_conn(nc);
|
mg_close_conn(nc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -167,36 +166,4 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
|
|||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) {
|
|
||||||
struct mg_connection *nc;
|
|
||||||
double now;
|
|
||||||
double min_timer = 0;
|
|
||||||
int num_timers = 0;
|
|
||||||
mg_ev_mgr_lwip_process_signals(mgr);
|
|
||||||
for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
|
|
||||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
|
||||||
if (nc->ev_timer_time > 0) {
|
|
||||||
if (num_timers == 0 || nc->ev_timer_time < min_timer) {
|
|
||||||
min_timer = nc->ev_timer_time;
|
|
||||||
}
|
|
||||||
num_timers++;
|
|
||||||
}
|
|
||||||
/* We want and can send data, request a poll immediately. */
|
|
||||||
if (nc->sock != INVALID_SOCKET && mg_lwip_if_can_send(nc, cs)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t timeout_ms = ~0;
|
|
||||||
now = mg_time();
|
|
||||||
if (num_timers > 0) {
|
|
||||||
/* If we have a timer that is past due, do a poll ASAP. */
|
|
||||||
if (min_timer < now) return 0;
|
|
||||||
double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */;
|
|
||||||
if (timer_timeout_ms < timeout_ms) {
|
|
||||||
timeout_ms = timer_timeout_ms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return timeout_ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
|
#endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
|
||||||
@@ -187,6 +187,7 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
|
|||||||
}
|
}
|
||||||
mg_lwip_recv_common(nc, p);
|
mg_lwip_recv_common(nc, p);
|
||||||
mgos_unlock();
|
mgos_unlock();
|
||||||
|
(void) err;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +200,10 @@ static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb,
|
|||||||
nc->send_mbuf.len == 0 && tpcb->unsent == NULL && tpcb->unacked == NULL) {
|
nc->send_mbuf.len == 0 && tpcb->unsent == NULL && tpcb->unacked == NULL) {
|
||||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||||
}
|
}
|
||||||
|
if (nc->send_mbuf.len > 0 || (nc->flags & MG_F_WANT_WRITE)) {
|
||||||
|
mg_lwip_mgr_schedule_poll(nc->mgr);
|
||||||
|
}
|
||||||
|
(void) num_sent;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,6 +565,10 @@ static int mg_lwip_if_can_send(struct mg_connection *nc,
|
|||||||
can_send = (cs->pcb.udp != NULL);
|
can_send = (cs->pcb.udp != NULL);
|
||||||
} else {
|
} else {
|
||||||
can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0);
|
can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0);
|
||||||
|
/* See comment above. */
|
||||||
|
#if CS_PLATFORM == CS_P_ESP8266
|
||||||
|
if (cs->pcb.tcp->unacked != NULL) can_send = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return can_send;
|
return can_send;
|
||||||
@@ -572,7 +581,7 @@ struct tcp_recved_ctx {
|
|||||||
|
|
||||||
void tcp_recved_tcpip(void *arg) {
|
void tcp_recved_tcpip(void *arg) {
|
||||||
struct tcp_recved_ctx *ctx = (struct tcp_recved_ctx *) arg;
|
struct tcp_recved_ctx *ctx = (struct tcp_recved_ctx *) arg;
|
||||||
tcp_recved(ctx->tpcb, ctx->len);
|
if (ctx->tpcb != NULL) tcp_recved(ctx->tpcb, ctx->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf,
|
static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include <stm32_sdk_hal.h>
|
#include <stm32_sdk_hal.h>
|
||||||
|
|
||||||
#define to64(x) strtoll(x, NULL, 10)
|
#define to64(x) strtoll(x, NULL, 10)
|
||||||
#define INT64_FMT PRId64
|
#define INT64_FMT "lld"
|
||||||
#define SIZE_T_FMT "u"
|
#define SIZE_T_FMT "u"
|
||||||
typedef struct stat cs_stat_t;
|
typedef struct stat cs_stat_t;
|
||||||
#define DIRSEP '/'
|
#define DIRSEP '/'
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ int sl_set_ssl_opts(int sock, struct mg_connection *nc);
|
|||||||
|
|
||||||
#endif /* SL_MAJOR_VERSION_NUM < 2 */
|
#endif /* SL_MAJOR_VERSION_NUM < 2 */
|
||||||
|
|
||||||
int slfs_open(const unsigned char *fname, uint32_t flags);
|
int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token);
|
||||||
|
|
||||||
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
|
#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,14 @@
|
|||||||
#include "common/mg_mem.h"
|
#include "common/mg_mem.h"
|
||||||
|
|
||||||
#if SL_MAJOR_VERSION_NUM < 2
|
#if SL_MAJOR_VERSION_NUM < 2
|
||||||
int slfs_open(const unsigned char *fname, uint32_t flags) {
|
int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token) {
|
||||||
_i32 fh;
|
_i32 fh;
|
||||||
_i32 r = sl_FsOpen(fname, flags, NULL /* token */, &fh);
|
_i32 r = sl_FsOpen(fname, flags, (unsigned long *) token, &fh);
|
||||||
return (r < 0 ? r : fh);
|
return (r < 0 ? r : fh);
|
||||||
}
|
}
|
||||||
#else /* SL_MAJOR_VERSION_NUM >= 2 */
|
#else /* SL_MAJOR_VERSION_NUM >= 2 */
|
||||||
int slfs_open(const unsigned char *fname, uint32_t flags) {
|
int slfs_open(const unsigned char *fname, uint32_t flags, uint32_t *token) {
|
||||||
return sl_FsOpen(fname, flags, NULL /* token */);
|
return sl_FsOpen(fname, flags, (unsigned long *) token);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -54,9 +54,11 @@ const char *drop_dir(const char *fname, bool *is_slfs);
|
|||||||
#define FS_SLFS_MAX_FILE_SIZE (64 * 1024)
|
#define FS_SLFS_MAX_FILE_SIZE (64 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sl_file_size_hint {
|
struct sl_file_open_info {
|
||||||
char *name;
|
char *name;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t *token;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sl_fd_info {
|
struct sl_fd_info {
|
||||||
@@ -66,7 +68,10 @@ struct sl_fd_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES];
|
static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES];
|
||||||
static struct sl_file_size_hint s_sl_file_size_hints[MAX_OPEN_SLFS_FILES];
|
static struct sl_file_open_info s_sl_file_open_infos[MAX_OPEN_SLFS_FILES];
|
||||||
|
|
||||||
|
static struct sl_file_open_info *fs_slfs_find_foi(const char *name,
|
||||||
|
bool create);
|
||||||
|
|
||||||
static int sl_fs_to_errno(_i32 r) {
|
static int sl_fs_to_errno(_i32 r) {
|
||||||
DBG(("SL error: %d", (int) r));
|
DBG(("SL error: %d", (int) r));
|
||||||
@@ -107,7 +112,13 @@ int fs_slfs_open(const char *pathname, int flags, mode_t mode) {
|
|||||||
_u32 am = 0;
|
_u32 am = 0;
|
||||||
fi->size = (size_t) -1;
|
fi->size = (size_t) -1;
|
||||||
int rw = (flags & 3);
|
int rw = (flags & 3);
|
||||||
size_t new_size = FS_SLFS_MAX_FILE_SIZE;
|
size_t new_size = 0;
|
||||||
|
struct sl_file_open_info *foi =
|
||||||
|
fs_slfs_find_foi(pathname, false /* create */);
|
||||||
|
if (foi != NULL) {
|
||||||
|
LOG(LL_DEBUG, ("FOI for %s: %d 0x%x %p", pathname, (int) foi->size,
|
||||||
|
(unsigned int) foi->flags, foi->token));
|
||||||
|
}
|
||||||
if (rw == O_RDONLY) {
|
if (rw == O_RDONLY) {
|
||||||
SlFsFileInfo_t sl_fi;
|
SlFsFileInfo_t sl_fi;
|
||||||
_i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi);
|
_i32 r = sl_FsGetInfo((const _u8 *) pathname, 0, &sl_fi);
|
||||||
@@ -122,24 +133,27 @@ int fs_slfs_open(const char *pathname, int flags, mode_t mode) {
|
|||||||
return set_errno(ENOTSUP);
|
return set_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
if (flags & O_CREAT) {
|
if (flags & O_CREAT) {
|
||||||
size_t i;
|
if (foi->size > 0) {
|
||||||
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
new_size = foi->size;
|
||||||
if (s_sl_file_size_hints[i].name != NULL &&
|
} else {
|
||||||
strcmp(s_sl_file_size_hints[i].name, pathname) == 0) {
|
new_size = FS_SLFS_MAX_FILE_SIZE;
|
||||||
new_size = s_sl_file_size_hints[i].size;
|
|
||||||
MG_FREE(s_sl_file_size_hints[i].name);
|
|
||||||
s_sl_file_size_hints[i].name = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
am = FS_MODE_OPEN_CREATE(new_size, 0);
|
am = FS_MODE_OPEN_CREATE(new_size, 0);
|
||||||
} else {
|
} else {
|
||||||
am = SL_FS_WRITE;
|
am = SL_FS_WRITE;
|
||||||
}
|
}
|
||||||
|
#if SL_MAJOR_VERSION_NUM >= 2
|
||||||
|
am |= SL_FS_OVERWRITE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
fi->fh = slfs_open((_u8 *) pathname, am);
|
uint32_t *token = NULL;
|
||||||
LOG(LL_DEBUG, ("sl_FsOpen(%s, 0x%x) sz %u = %d", pathname, (int) am,
|
if (foi != NULL) {
|
||||||
(unsigned int) new_size, (int) fi->fh));
|
am |= foi->flags;
|
||||||
|
token = foi->token;
|
||||||
|
}
|
||||||
|
fi->fh = slfs_open((_u8 *) pathname, am, token);
|
||||||
|
LOG(LL_DEBUG, ("sl_FsOpen(%s, 0x%x, %p) sz %u = %d", pathname, (int) am,
|
||||||
|
token, (unsigned int) new_size, (int) fi->fh));
|
||||||
int r;
|
int r;
|
||||||
if (fi->fh >= 0) {
|
if (fi->fh >= 0) {
|
||||||
fi->pos = 0;
|
fi->pos = 0;
|
||||||
@@ -243,16 +257,46 @@ int fs_slfs_rename(const char *from, const char *to) {
|
|||||||
return set_errno(ENOTSUP);
|
return set_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_slfs_set_new_file_size(const char *name, size_t size) {
|
static struct sl_file_open_info *fs_slfs_find_foi(const char *name,
|
||||||
int i;
|
bool create) {
|
||||||
|
int i = 0;
|
||||||
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
||||||
if (s_sl_file_size_hints[i].name == NULL) {
|
if (s_sl_file_open_infos[i].name != NULL &&
|
||||||
DBG(("File size hint: %s %d", name, (int) size));
|
strcmp(drop_dir(s_sl_file_open_infos[i].name, NULL), name) == 0) {
|
||||||
s_sl_file_size_hints[i].name = strdup(name);
|
|
||||||
s_sl_file_size_hints[i].size = size;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (i != MAX_OPEN_SLFS_FILES) return &s_sl_file_open_infos[i];
|
||||||
|
if (!create) return NULL;
|
||||||
|
for (i = 0; i < MAX_OPEN_SLFS_FILES; i++) {
|
||||||
|
if (s_sl_file_open_infos[i].name == NULL) break;
|
||||||
|
}
|
||||||
|
if (i == MAX_OPEN_SLFS_FILES) {
|
||||||
|
i = 0; /* Evict a random slot. */
|
||||||
|
}
|
||||||
|
if (s_sl_file_open_infos[i].name != NULL) {
|
||||||
|
free(s_sl_file_open_infos[i].name);
|
||||||
|
}
|
||||||
|
s_sl_file_open_infos[i].name = strdup(name);
|
||||||
|
return &s_sl_file_open_infos[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_slfs_set_file_size(const char *name, size_t size) {
|
||||||
|
struct sl_file_open_info *foi = fs_slfs_find_foi(name, true /* create */);
|
||||||
|
foi->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_slfs_set_file_flags(const char *name, uint32_t flags, uint32_t *token) {
|
||||||
|
struct sl_file_open_info *foi = fs_slfs_find_foi(name, true /* create */);
|
||||||
|
foi->flags = flags;
|
||||||
|
foi->token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_slfs_unset_file_flags(const char *name) {
|
||||||
|
struct sl_file_open_info *foi = fs_slfs_find_foi(name, false /* create */);
|
||||||
|
if (foi == NULL) return;
|
||||||
|
free(foi->name);
|
||||||
|
memset(foi, 0, sizeof(*foi));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS) */
|
#endif /* defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS) */
|
||||||
@@ -39,7 +39,9 @@ off_t fs_slfs_lseek(int fd, off_t offset, int whence);
|
|||||||
int fs_slfs_unlink(const char *filename);
|
int fs_slfs_unlink(const char *filename);
|
||||||
int fs_slfs_rename(const char *from, const char *to);
|
int fs_slfs_rename(const char *from, const char *to);
|
||||||
|
|
||||||
void fs_slfs_set_new_file_size(const char *name, size_t size);
|
void fs_slfs_set_file_size(const char *name, size_t size);
|
||||||
|
void fs_slfs_set_file_flags(const char *name, uint32_t flags, uint32_t *token);
|
||||||
|
void fs_slfs_unset_file_flags(const char *name);
|
||||||
|
|
||||||
#endif /* defined(MG_FS_SLFS) */
|
#endif /* defined(MG_FS_SLFS) */
|
||||||
|
|
||||||
|
|||||||
@@ -115,9 +115,9 @@ bool pem_to_der(const char *pem_file, const char *der_file) {
|
|||||||
pf = fopen(pem_file, "r");
|
pf = fopen(pem_file, "r");
|
||||||
if (pf == NULL) goto clean;
|
if (pf == NULL) goto clean;
|
||||||
remove(der_file);
|
remove(der_file);
|
||||||
fs_slfs_set_new_file_size(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN,
|
fs_slfs_set_file_size(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN, 2048);
|
||||||
2048);
|
|
||||||
df = fopen(der_file, "w");
|
df = fopen(der_file, "w");
|
||||||
|
fs_slfs_unset_file_flags(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN);
|
||||||
if (df == NULL) goto clean;
|
if (df == NULL) goto clean;
|
||||||
while (1) {
|
while (1) {
|
||||||
char pem_buf[70];
|
char pem_buf[70];
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"cesanta.com/mos/flash/common"
|
"cesanta.com/common/go/fwbundle"
|
||||||
"github.com/cesanta/errors"
|
"github.com/cesanta/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ type FlashOpts struct {
|
|||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flash(fw *common.FirmwareBundle, opts *FlashOpts) error {
|
func Flash(fw *fwbundle.FirmwareBundle, opts *FlashOpts) error {
|
||||||
data, err := fw.GetPartData("boot")
|
data, err := fw.GetPartData("boot")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Annotatef(err, "invalid manifest")
|
return errors.Annotatef(err, "invalid manifest")
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
#ifndef CS_MONGOOSE_SRC_COMMON_H_
|
#ifndef CS_MONGOOSE_SRC_COMMON_H_
|
||||||
#define CS_MONGOOSE_SRC_COMMON_H_
|
#define CS_MONGOOSE_SRC_COMMON_H_
|
||||||
|
|
||||||
#define MG_VERSION "6.12"
|
#define MG_VERSION "6.14"
|
||||||
|
|
||||||
/* Local tweaks, applied before any of Mongoose's own headers. */
|
/* Local tweaks, applied before any of Mongoose's own headers. */
|
||||||
#ifdef MG_LOCALS
|
#ifdef MG_LOCALS
|
||||||
|
|||||||
+98
-44
@@ -140,6 +140,7 @@ struct mg_http_multipart_stream {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
enum mg_http_multipart_stream_state state;
|
enum mg_http_multipart_stream_state state;
|
||||||
int processing_part;
|
int processing_part;
|
||||||
|
int data_avail;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_reverse_proxy_data {
|
struct mg_reverse_proxy_data {
|
||||||
@@ -564,6 +565,10 @@ static size_t mg_http_parse_chunk(char *buf, size_t len, char **chunk_data,
|
|||||||
n *= 16;
|
n *= 16;
|
||||||
n += (s[i] >= '0' && s[i] <= '9') ? s[i] - '0' : tolower(s[i]) - 'a' + 10;
|
n += (s[i] >= '0' && s[i] <= '9') ? s[i] - '0' : tolower(s[i]) - 'a' + 10;
|
||||||
i++;
|
i++;
|
||||||
|
if (i > 6) {
|
||||||
|
/* Chunk size is unreasonable. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip new line */
|
/* Skip new line */
|
||||||
@@ -754,9 +759,9 @@ void mg_http_handler(struct mg_connection *nc, int ev,
|
|||||||
if (io->len > 0 &&
|
if (io->len > 0 &&
|
||||||
(req_len = mg_parse_http(io->buf, io->len, hm, is_req)) > 0) {
|
(req_len = mg_parse_http(io->buf, io->len, hm, is_req)) > 0) {
|
||||||
/*
|
/*
|
||||||
* For HTTP messages without Content-Length, always send HTTP message
|
* For HTTP messages without Content-Length, always send HTTP message
|
||||||
* before MG_EV_CLOSE message.
|
* before MG_EV_CLOSE message.
|
||||||
*/
|
*/
|
||||||
int ev2 = is_req ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY;
|
int ev2 = is_req ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY;
|
||||||
hm->message.len = io->len;
|
hm->message.len = io->len;
|
||||||
hm->body.len = io->buf + io->len - hm->body.p;
|
hm->body.len = io->buf + io->len - hm->body.p;
|
||||||
@@ -764,6 +769,9 @@ void mg_http_handler(struct mg_connection *nc, int ev,
|
|||||||
mg_http_call_endpoint_handler(nc, ev2, hm);
|
mg_http_call_endpoint_handler(nc, ev2, hm);
|
||||||
}
|
}
|
||||||
pd->rcvd = 0;
|
pd->rcvd = 0;
|
||||||
|
if (pd->endpoint_handler != NULL && pd->endpoint_handler != nc->handler) {
|
||||||
|
mg_call(nc, pd->endpoint_handler, nc->user_data, ev, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MG_ENABLE_FILESYSTEM
|
#if MG_ENABLE_FILESYSTEM
|
||||||
@@ -774,17 +782,24 @@ void mg_http_handler(struct mg_connection *nc, int ev,
|
|||||||
|
|
||||||
mg_call(nc, nc->handler, nc->user_data, ev, ev_data);
|
mg_call(nc, nc->handler, nc->user_data, ev, ev_data);
|
||||||
|
|
||||||
|
#if MG_ENABLE_HTTP_STREAMING_MULTIPART
|
||||||
|
if (pd->mp_stream.boundary != NULL &&
|
||||||
|
(ev == MG_EV_RECV || ev == MG_EV_POLL)) {
|
||||||
|
if (ev == MG_EV_RECV) {
|
||||||
|
pd->rcvd += *(int *) ev_data;
|
||||||
|
mg_http_multipart_continue(nc);
|
||||||
|
} else if (pd->mp_stream.data_avail) {
|
||||||
|
/* Try re-delivering the data. */
|
||||||
|
mg_http_multipart_continue(nc);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
|
||||||
|
|
||||||
if (ev == MG_EV_RECV) {
|
if (ev == MG_EV_RECV) {
|
||||||
struct mg_str *s;
|
struct mg_str *s;
|
||||||
pd->rcvd += *(int *) ev_data;
|
pd->rcvd += *(int *) ev_data;
|
||||||
|
|
||||||
#if MG_ENABLE_HTTP_STREAMING_MULTIPART
|
|
||||||
if (pd->mp_stream.boundary != NULL) {
|
|
||||||
mg_http_multipart_continue(nc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
req_len = mg_parse_http(io->buf, io->len, hm, is_req);
|
req_len = mg_parse_http(io->buf, io->len, hm, is_req);
|
||||||
|
|
||||||
@@ -812,16 +827,23 @@ void mg_http_handler(struct mg_connection *nc, int ev,
|
|||||||
/* Do nothing, request is not yet fully buffered */
|
/* Do nothing, request is not yet fully buffered */
|
||||||
}
|
}
|
||||||
#if MG_ENABLE_HTTP_WEBSOCKET
|
#if MG_ENABLE_HTTP_WEBSOCKET
|
||||||
else if (nc->listener == NULL &&
|
else if (nc->listener == NULL && (nc->flags & MG_F_IS_WEBSOCKET)) {
|
||||||
mg_get_http_header(hm, "Sec-WebSocket-Accept")) {
|
|
||||||
/* We're websocket client, got handshake response from server. */
|
/* We're websocket client, got handshake response from server. */
|
||||||
/* TODO(lsm): check the validity of accept Sec-WebSocket-Accept */
|
DBG(("%p WebSocket upgrade code %d", nc, hm->resp_code));
|
||||||
mbuf_remove(io, req_len);
|
if (hm->resp_code == 101 &&
|
||||||
nc->proto_handler = mg_ws_handler;
|
mg_get_http_header(hm, "Sec-WebSocket-Accept")) {
|
||||||
nc->flags |= MG_F_IS_WEBSOCKET;
|
/* TODO(lsm): check the validity of accept Sec-WebSocket-Accept */
|
||||||
mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_DONE,
|
mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_DONE,
|
||||||
NULL);
|
hm);
|
||||||
mg_ws_handler(nc, MG_EV_RECV, ev_data MG_UD_ARG(user_data));
|
mbuf_remove(io, req_len);
|
||||||
|
nc->proto_handler = mg_ws_handler;
|
||||||
|
mg_ws_handler(nc, MG_EV_RECV, ev_data MG_UD_ARG(user_data));
|
||||||
|
} else {
|
||||||
|
mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_DONE,
|
||||||
|
hm);
|
||||||
|
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||||
|
mbuf_remove(io, req_len);
|
||||||
|
}
|
||||||
} else if (nc->listener != NULL &&
|
} else if (nc->listener != NULL &&
|
||||||
(vec = mg_get_http_header(hm, "Sec-WebSocket-Key")) != NULL) {
|
(vec = mg_get_http_header(hm, "Sec-WebSocket-Key")) != NULL) {
|
||||||
struct mg_http_endpoint *ep;
|
struct mg_http_endpoint *ep;
|
||||||
@@ -852,7 +874,7 @@ void mg_http_handler(struct mg_connection *nc, int ev,
|
|||||||
mg_ws_handshake(nc, vec, hm);
|
mg_ws_handshake(nc, vec, hm);
|
||||||
}
|
}
|
||||||
mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_DONE,
|
mg_call(nc, nc->handler, nc->user_data, MG_EV_WEBSOCKET_HANDSHAKE_DONE,
|
||||||
NULL);
|
hm);
|
||||||
mg_ws_handler(nc, MG_EV_RECV, ev_data MG_UD_ARG(user_data));
|
mg_ws_handler(nc, MG_EV_RECV, ev_data MG_UD_ARG(user_data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -869,6 +891,7 @@ void mg_http_handler(struct mg_connection *nc, int ev,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* We did receive all HTTP body. */
|
/* We did receive all HTTP body. */
|
||||||
|
int request_done = 1;
|
||||||
int trigger_ev = nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY;
|
int trigger_ev = nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY;
|
||||||
char addr[32];
|
char addr[32];
|
||||||
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
|
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
|
||||||
@@ -880,8 +903,28 @@ void mg_http_handler(struct mg_connection *nc, int ev,
|
|||||||
mg_http_call_endpoint_handler(nc, trigger_ev, hm);
|
mg_http_call_endpoint_handler(nc, trigger_ev, hm);
|
||||||
mbuf_remove(io, hm->message.len);
|
mbuf_remove(io, hm->message.len);
|
||||||
pd->rcvd -= hm->message.len;
|
pd->rcvd -= hm->message.len;
|
||||||
if (io->len > 0) {
|
#if MG_ENABLE_FILESYSTEM
|
||||||
goto again;
|
/* We don't have a generic mechanism of communicating that we are done
|
||||||
|
* responding to a request (should probably add one). But if we are
|
||||||
|
* serving
|
||||||
|
* a file, we are definitely not done. */
|
||||||
|
if (pd->file.fp != NULL) request_done = 0;
|
||||||
|
#endif
|
||||||
|
#if MG_ENABLE_HTTP_CGI
|
||||||
|
/* If this is a CGI request, we are not done either. */
|
||||||
|
if (pd->cgi.cgi_nc != NULL) request_done = 0;
|
||||||
|
#endif
|
||||||
|
if (request_done) {
|
||||||
|
/* This request is done but we may receive another on this connection.
|
||||||
|
*/
|
||||||
|
mg_http_conn_destructor(pd);
|
||||||
|
nc->proto_data = NULL;
|
||||||
|
if (io->len > 0) {
|
||||||
|
/* We already have data for the next one, restart parsing. */
|
||||||
|
pd = mg_http_get_proto_data(nc);
|
||||||
|
pd->rcvd = io->len;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -958,8 +1001,9 @@ exit_mp:
|
|||||||
|
|
||||||
#define CONTENT_DISPOSITION "Content-Disposition: "
|
#define CONTENT_DISPOSITION "Content-Disposition: "
|
||||||
|
|
||||||
static void mg_http_multipart_call_handler(struct mg_connection *c, int ev,
|
static size_t mg_http_multipart_call_handler(struct mg_connection *c, int ev,
|
||||||
const char *data, size_t data_len) {
|
const char *data,
|
||||||
|
size_t data_len) {
|
||||||
struct mg_http_multipart_part mp;
|
struct mg_http_multipart_part mp;
|
||||||
struct mg_http_proto_data *pd = mg_http_get_proto_data(c);
|
struct mg_http_proto_data *pd = mg_http_get_proto_data(c);
|
||||||
memset(&mp, 0, sizeof(mp));
|
memset(&mp, 0, sizeof(mp));
|
||||||
@@ -969,8 +1013,11 @@ static void mg_http_multipart_call_handler(struct mg_connection *c, int ev,
|
|||||||
mp.user_data = pd->mp_stream.user_data;
|
mp.user_data = pd->mp_stream.user_data;
|
||||||
mp.data.p = data;
|
mp.data.p = data;
|
||||||
mp.data.len = data_len;
|
mp.data.len = data_len;
|
||||||
|
mp.num_data_consumed = data_len;
|
||||||
mg_call(c, pd->endpoint_handler, c->user_data, ev, &mp);
|
mg_call(c, pd->endpoint_handler, c->user_data, ev, &mp);
|
||||||
pd->mp_stream.user_data = mp.user_data;
|
pd->mp_stream.user_data = mp.user_data;
|
||||||
|
pd->mp_stream.data_avail = (mp.num_data_consumed != data_len);
|
||||||
|
return mp.num_data_consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mg_http_multipart_finalize(struct mg_connection *c) {
|
static int mg_http_multipart_finalize(struct mg_connection *c) {
|
||||||
@@ -1108,19 +1155,25 @@ static int mg_http_multipart_continue_wait_for_chunk(struct mg_connection *c) {
|
|||||||
|
|
||||||
boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len);
|
boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len);
|
||||||
if (boundary == NULL) {
|
if (boundary == NULL) {
|
||||||
int data_size = (io->len - (pd->mp_stream.boundary_len + 6));
|
int data_len = (io->len - (pd->mp_stream.boundary_len + 6));
|
||||||
if (data_size > 0) {
|
if (data_len > 0) {
|
||||||
mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_DATA, io->buf,
|
size_t consumed = mg_http_multipart_call_handler(
|
||||||
data_size);
|
c, MG_EV_HTTP_PART_DATA, io->buf, (size_t) data_len);
|
||||||
mbuf_remove(io, data_size);
|
mbuf_remove(io, consumed);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (boundary != NULL) {
|
} else if (boundary != NULL) {
|
||||||
int data_size = (boundary - io->buf - 4);
|
size_t data_len = ((size_t)(boundary - io->buf) - 4);
|
||||||
mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_DATA, io->buf, data_size);
|
size_t consumed = mg_http_multipart_call_handler(c, MG_EV_HTTP_PART_DATA,
|
||||||
mbuf_remove(io, (boundary - io->buf));
|
io->buf, data_len);
|
||||||
pd->mp_stream.state = MPS_WAITING_FOR_BOUNDARY;
|
mbuf_remove(io, consumed);
|
||||||
return 1;
|
if (consumed == data_len) {
|
||||||
|
mbuf_remove(io, 4);
|
||||||
|
pd->mp_stream.state = MPS_WAITING_FOR_BOUNDARY;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1898,7 +1951,7 @@ int mg_check_digest_auth(struct mg_str method, struct mg_str uri,
|
|||||||
struct mg_str nc, struct mg_str nonce,
|
struct mg_str nc, struct mg_str nonce,
|
||||||
struct mg_str auth_domain, FILE *fp) {
|
struct mg_str auth_domain, FILE *fp) {
|
||||||
char buf[128], f_user[sizeof(buf)], f_ha1[sizeof(buf)], f_domain[sizeof(buf)];
|
char buf[128], f_user[sizeof(buf)], f_ha1[sizeof(buf)], f_domain[sizeof(buf)];
|
||||||
char expected_response[33];
|
char exp_resp[33];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read passwords file line by line. If should have htdigest format,
|
* Read passwords file line by line. If should have htdigest format,
|
||||||
@@ -1912,11 +1965,10 @@ int mg_check_digest_auth(struct mg_str method, struct mg_str uri,
|
|||||||
/* Username and domain matched, check the password */
|
/* Username and domain matched, check the password */
|
||||||
mg_mkmd5resp(method.p, method.len, uri.p, uri.len, f_ha1, strlen(f_ha1),
|
mg_mkmd5resp(method.p, method.len, uri.p, uri.len, f_ha1, strlen(f_ha1),
|
||||||
nonce.p, nonce.len, nc.p, nc.len, cnonce.p, cnonce.len,
|
nonce.p, nonce.len, nc.p, nc.len, cnonce.p, cnonce.len,
|
||||||
qop.p, qop.len, expected_response);
|
qop.p, qop.len, exp_resp);
|
||||||
LOG(LL_DEBUG,
|
LOG(LL_DEBUG, ("%.*s %s %.*s %s", (int) username.len, username.p,
|
||||||
("%.*s %s %.*s %s", (int) username.len, username.p, f_domain,
|
f_domain, (int) response.len, response.p, exp_resp));
|
||||||
(int) response.len, response.p, expected_response));
|
return mg_ncasecmp(response.p, exp_resp, strlen(exp_resp)) == 0;
|
||||||
return mg_ncasecmp(response.p, expected_response, response.len) == 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2511,9 +2563,11 @@ void mg_http_send_digest_auth_request(struct mg_connection *c,
|
|||||||
domain, (unsigned long) mg_time());
|
domain, (unsigned long) mg_time());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_http_send_options(struct mg_connection *nc) {
|
static void mg_http_send_options(struct mg_connection *nc,
|
||||||
|
struct mg_serve_http_opts *opts) {
|
||||||
|
mg_send_response_line(nc, 200, opts->extra_headers);
|
||||||
mg_printf(nc, "%s",
|
mg_printf(nc, "%s",
|
||||||
"HTTP/1.1 200 OK\r\nAllow: GET, POST, HEAD, CONNECT, OPTIONS"
|
"Allow: GET, POST, HEAD, CONNECT, OPTIONS"
|
||||||
#if MG_ENABLE_HTTP_WEBDAV
|
#if MG_ENABLE_HTTP_WEBDAV
|
||||||
", MKCOL, PUT, DELETE, PROPFIND, MOVE\r\nDAV: 1,2"
|
", MKCOL, PUT, DELETE, PROPFIND, MOVE\r\nDAV: 1,2"
|
||||||
#endif
|
#endif
|
||||||
@@ -2620,7 +2674,7 @@ MG_INTERNAL void mg_send_http_file(struct mg_connection *nc, char *path,
|
|||||||
#endif
|
#endif
|
||||||
#endif /* MG_ENABLE_HTTP_WEBDAV */
|
#endif /* MG_ENABLE_HTTP_WEBDAV */
|
||||||
} else if (!mg_vcmp(&hm->method, "OPTIONS")) {
|
} else if (!mg_vcmp(&hm->method, "OPTIONS")) {
|
||||||
mg_http_send_options(nc);
|
mg_http_send_options(nc, opts);
|
||||||
} else if (is_directory && index_file == NULL) {
|
} else if (is_directory && index_file == NULL) {
|
||||||
#if MG_ENABLE_DIRECTORY_LISTING
|
#if MG_ENABLE_DIRECTORY_LISTING
|
||||||
if (strcmp(opts->enable_directory_listing, "yes") == 0) {
|
if (strcmp(opts->enable_directory_listing, "yes") == 0) {
|
||||||
@@ -2737,7 +2791,7 @@ void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
|
|||||||
if (lfn.p != mp->file_name) MG_FREE((char *) lfn.p);
|
if (lfn.p != mp->file_name) MG_FREE((char *) lfn.p);
|
||||||
LOG(LL_DEBUG,
|
LOG(LL_DEBUG,
|
||||||
("%p Receiving file %s -> %s", nc, mp->file_name, fus->lfn));
|
("%p Receiving file %s -> %s", nc, mp->file_name, fus->lfn));
|
||||||
fus->fp = mg_fopen(fus->lfn, "w");
|
fus->fp = mg_fopen(fus->lfn, "wb");
|
||||||
if (fus->fp == NULL) {
|
if (fus->fp == NULL) {
|
||||||
mg_printf(nc,
|
mg_printf(nc,
|
||||||
"HTTP/1.1 500 Internal Server Error\r\n"
|
"HTTP/1.1 500 Internal Server Error\r\n"
|
||||||
|
|||||||
+12
-2
@@ -80,6 +80,14 @@ struct mg_http_multipart_part {
|
|||||||
struct mg_str data;
|
struct mg_str data;
|
||||||
int status; /* <0 on error */
|
int status; /* <0 on error */
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
/*
|
||||||
|
* User handler can indicate how much of the data was consumed
|
||||||
|
* by setting this variable. By default, it is assumed that all
|
||||||
|
* data has been consumed by the handler.
|
||||||
|
* If not all data was consumed, user's handler will be invoked again later
|
||||||
|
* with the remainder.
|
||||||
|
*/
|
||||||
|
size_t num_data_consumed;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SSI call context */
|
/* SSI call context */
|
||||||
@@ -98,7 +106,7 @@ struct mg_ssi_call_ctx {
|
|||||||
|
|
||||||
#if MG_ENABLE_HTTP_WEBSOCKET
|
#if MG_ENABLE_HTTP_WEBSOCKET
|
||||||
#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* struct http_message * */
|
#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* struct http_message * */
|
||||||
#define MG_EV_WEBSOCKET_HANDSHAKE_DONE 112 /* NULL */
|
#define MG_EV_WEBSOCKET_HANDSHAKE_DONE 112 /* struct http_message * */
|
||||||
#define MG_EV_WEBSOCKET_FRAME 113 /* struct websocket_message * */
|
#define MG_EV_WEBSOCKET_FRAME 113 /* struct websocket_message * */
|
||||||
#define MG_EV_WEBSOCKET_CONTROL_FRAME 114 /* struct websocket_message * */
|
#define MG_EV_WEBSOCKET_CONTROL_FRAME 114 /* struct websocket_message * */
|
||||||
#endif
|
#endif
|
||||||
@@ -137,7 +145,9 @@ struct mg_ssi_call_ctx {
|
|||||||
* - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
* - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
||||||
* handshake request. `ev_data` contains parsed HTTP request.
|
* handshake request. `ev_data` contains parsed HTTP request.
|
||||||
* - MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
* - MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
||||||
* handshake. `ev_data` is `NULL`.
|
* handshake. `ev_data` is a `struct http_message` containing the
|
||||||
|
* client's request (server mode) or server's response (client).
|
||||||
|
* In client mode handler can examine `resp_code`, which should be 101.
|
||||||
* - MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
* - MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
||||||
* `struct websocket_message *`
|
* `struct websocket_message *`
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -478,6 +478,8 @@ void mg_send_websocket_handshake3v(struct mg_connection *nc,
|
|||||||
}
|
}
|
||||||
mg_printf(nc, "\r\n");
|
mg_printf(nc, "\r\n");
|
||||||
|
|
||||||
|
nc->flags |= MG_F_IS_WEBSOCKET;
|
||||||
|
|
||||||
mbuf_free(&auth);
|
mbuf_free(&auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,9 @@
|
|||||||
#include "mg_http.h"
|
#include "mg_http.h"
|
||||||
#include "mg_net.h"
|
#include "mg_net.h"
|
||||||
|
|
||||||
|
#ifndef MG_CTL_MSG_MESSAGE_SIZE
|
||||||
#define MG_CTL_MSG_MESSAGE_SIZE 8192
|
#define MG_CTL_MSG_MESSAGE_SIZE 8192
|
||||||
|
#endif
|
||||||
|
|
||||||
/* internals that need to be accessible in unit tests */
|
/* internals that need to be accessible in unit tests */
|
||||||
MG_INTERNAL struct mg_connection *mg_do_connect(struct mg_connection *nc,
|
MG_INTERNAL struct mg_connection *mg_do_connect(struct mg_connection *nc,
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ SOURCES = $(COMMON)/mg_mem.h \
|
|||||||
mg_net_if_socket.h \
|
mg_net_if_socket.h \
|
||||||
mg_net_if_socks.h \
|
mg_net_if_socks.h \
|
||||||
mg_net_if.c \
|
mg_net_if.c \
|
||||||
|
mg_net_if_null.c \
|
||||||
mg_net_if_socket.c \
|
mg_net_if_socket.c \
|
||||||
mg_net_if_socks.c \
|
mg_net_if_socks.c \
|
||||||
mg_ssl_if_openssl.c \
|
mg_ssl_if_openssl.c \
|
||||||
|
|||||||
+34
-16
@@ -196,26 +196,44 @@ static void mg_mqtt_proto_data_destructor(void *proto_data) {
|
|||||||
MG_FREE(proto_data);
|
MG_FREE(proto_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct mg_str mg_mqtt_next_topic_component(struct mg_str *topic) {
|
||||||
|
struct mg_str res = *topic;
|
||||||
|
const char *c = mg_strchr(*topic, '/');
|
||||||
|
if (c != NULL) {
|
||||||
|
res.len = (c - topic->p);
|
||||||
|
topic->len -= (res.len + 1);
|
||||||
|
topic->p += (res.len + 1);
|
||||||
|
} else {
|
||||||
|
topic->len = 0;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Refernce: https://mosquitto.org/man/mqtt-7.html */
|
||||||
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic) {
|
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic) {
|
||||||
/* TODO(mkm): implement real matching */
|
struct mg_str ec, tc;
|
||||||
if (memchr(exp.p, '#', exp.len)) {
|
if (exp.len == 0) return 0;
|
||||||
/* exp `foo/#` will become `foo/` */
|
while (1) {
|
||||||
exp.len -= 1;
|
ec = mg_mqtt_next_topic_component(&exp);
|
||||||
/*
|
tc = mg_mqtt_next_topic_component(&topic);
|
||||||
* topic should be longer than the expression: e.g. topic `foo/bar` does
|
if (ec.len == 0) {
|
||||||
* match `foo/#`, but neither `foo` nor `foo/` do.
|
if (tc.len != 0) return 0;
|
||||||
*/
|
if (exp.len == 0) break;
|
||||||
if (topic.len <= exp.len) {
|
continue;
|
||||||
|
}
|
||||||
|
if (mg_vcmp(&ec, "+") == 0) {
|
||||||
|
if (tc.len == 0 && topic.len == 0) return 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mg_vcmp(&ec, "#") == 0) {
|
||||||
|
/* Must be the last component in the expression or it's invalid. */
|
||||||
|
return (exp.len == 0);
|
||||||
|
}
|
||||||
|
if (mg_strcmp(ec, tc) != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Truncate topic so that it'll pass the next length check */
|
|
||||||
topic.len = exp.len;
|
|
||||||
}
|
}
|
||||||
if (topic.len != exp.len) {
|
return (tc.len == 0 && topic.len == 0);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return strncmp(topic.p, exp.p, exp.len) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic) {
|
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic) {
|
||||||
|
|||||||
+47
-27
@@ -99,6 +99,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
|
|||||||
(nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK);
|
(nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ev != MG_EV_POLL) nc->mgr->num_calls++;
|
||||||
if (ev != MG_EV_POLL) {
|
if (ev != MG_EV_POLL) {
|
||||||
DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc,
|
DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc,
|
||||||
ev_handler == nc->handler ? "user" : "proto", nc->flags,
|
ev_handler == nc->handler ? "user" : "proto", nc->flags,
|
||||||
@@ -127,8 +128,16 @@ MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max) {
|
|||||||
static int mg_do_recv(struct mg_connection *nc);
|
static int mg_do_recv(struct mg_connection *nc);
|
||||||
|
|
||||||
int mg_if_poll(struct mg_connection *nc, double now) {
|
int mg_if_poll(struct mg_connection *nc, double now) {
|
||||||
if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) ||
|
if (nc->flags & MG_F_CLOSE_IMMEDIATELY) {
|
||||||
(nc->send_mbuf.len == 0 && (nc->flags & MG_F_SEND_AND_CLOSE))) {
|
mg_close_conn(nc);
|
||||||
|
return 0;
|
||||||
|
} else if (nc->flags & MG_F_SEND_AND_CLOSE) {
|
||||||
|
if (nc->send_mbuf.len == 0) {
|
||||||
|
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||||
|
mg_close_conn(nc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (nc->flags & MG_F_RECV_AND_CLOSE) {
|
||||||
mg_close_conn(nc);
|
mg_close_conn(nc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -171,6 +180,13 @@ void mg_destroy_conn(struct mg_connection *conn, int destroy_if) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mg_close_conn(struct mg_connection *conn) {
|
void mg_close_conn(struct mg_connection *conn) {
|
||||||
|
/* See if there's any remaining data to deliver. Skip if user completely
|
||||||
|
* throttled the connection there will be no progress anyway. */
|
||||||
|
if (conn->sock != INVALID_SOCKET && mg_do_recv(conn) == -2) {
|
||||||
|
/* Receive is throttled, wait. */
|
||||||
|
conn->flags |= MG_F_RECV_AND_CLOSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
#if MG_ENABLE_SSL
|
#if MG_ENABLE_SSL
|
||||||
if (conn->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
if (conn->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
||||||
mg_ssl_if_conn_close_notify(conn);
|
mg_ssl_if_conn_close_notify(conn);
|
||||||
@@ -261,6 +277,7 @@ void mg_mgr_free(struct mg_mgr *m) {
|
|||||||
|
|
||||||
for (conn = m->active_connections; conn != NULL; conn = tmp_conn) {
|
for (conn = m->active_connections; conn != NULL; conn = tmp_conn) {
|
||||||
tmp_conn = conn->next;
|
tmp_conn = conn->next;
|
||||||
|
conn->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||||
mg_close_conn(conn);
|
mg_close_conn(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,19 +293,14 @@ void mg_mgr_free(struct mg_mgr *m) {
|
|||||||
MG_FREE((char *) m->nameserver);
|
MG_FREE((char *) m->nameserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) {
|
int mg_mgr_poll(struct mg_mgr *m, int timeout_ms) {
|
||||||
int i;
|
int i, num_calls_before = m->num_calls;
|
||||||
time_t now = 0; /* oh GCC, seriously ? */
|
|
||||||
|
|
||||||
if (m->num_ifaces == 0) {
|
|
||||||
LOG(LL_ERROR, ("cannot poll: no interfaces"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < m->num_ifaces; i++) {
|
for (i = 0; i < m->num_ifaces; i++) {
|
||||||
now = m->ifaces[i]->vtable->poll(m->ifaces[i], timeout_ms);
|
m->ifaces[i]->vtable->poll(m->ifaces[i], timeout_ms);
|
||||||
}
|
}
|
||||||
return now;
|
|
||||||
|
return (m->num_calls - num_calls_before);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap) {
|
int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap) {
|
||||||
@@ -492,7 +504,6 @@ MG_INTERNAL void mg_ssl_handshake(struct mg_connection *nc) {
|
|||||||
enum mg_ssl_if_result res;
|
enum mg_ssl_if_result res;
|
||||||
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) return;
|
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) return;
|
||||||
res = mg_ssl_if_handshake(nc);
|
res = mg_ssl_if_handshake(nc);
|
||||||
LOG(LL_DEBUG, ("%p %d res %d", nc, server_side, res));
|
|
||||||
|
|
||||||
if (res == MG_SSL_OK) {
|
if (res == MG_SSL_OK) {
|
||||||
nc->flags |= MG_F_SSL_HANDSHAKE_DONE;
|
nc->flags |= MG_F_SSL_HANDSHAKE_DONE;
|
||||||
@@ -570,18 +581,23 @@ static int mg_do_recv(struct mg_connection *nc) {
|
|||||||
((nc->flags & MG_F_LISTENING) && !(nc->flags & MG_F_UDP))) {
|
((nc->flags & MG_F_LISTENING) && !(nc->flags & MG_F_UDP))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
len = recv_avail_size(nc, len);
|
do {
|
||||||
if (len == 0) return -2;
|
len = recv_avail_size(nc, len);
|
||||||
if (nc->recv_mbuf.size < nc->recv_mbuf.len + len) {
|
if (len == 0) {
|
||||||
mbuf_resize(&nc->recv_mbuf, nc->recv_mbuf.len + len);
|
res = -2;
|
||||||
}
|
break;
|
||||||
buf = nc->recv_mbuf.buf + nc->recv_mbuf.len;
|
}
|
||||||
len = nc->recv_mbuf.size - nc->recv_mbuf.len;
|
if (nc->recv_mbuf.size < nc->recv_mbuf.len + len) {
|
||||||
if (nc->flags & MG_F_UDP) {
|
mbuf_resize(&nc->recv_mbuf, nc->recv_mbuf.len + len);
|
||||||
res = mg_recv_udp(nc, buf, len);
|
}
|
||||||
} else {
|
buf = nc->recv_mbuf.buf + nc->recv_mbuf.len;
|
||||||
res = mg_recv_tcp(nc, buf, len);
|
len = nc->recv_mbuf.size - nc->recv_mbuf.len;
|
||||||
}
|
if (nc->flags & MG_F_UDP) {
|
||||||
|
res = mg_recv_udp(nc, buf, len);
|
||||||
|
} else {
|
||||||
|
res = mg_recv_tcp(nc, buf, len);
|
||||||
|
}
|
||||||
|
} while (res > 0 && !(nc->flags & (MG_F_CLOSE_IMMEDIATELY | MG_F_UDP)));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,10 +639,12 @@ static int mg_recv_tcp(struct mg_connection *nc, char *buf, size_t len) {
|
|||||||
mg_hexdump_connection(nc, nc->mgr->hexdump_file, buf, n, MG_EV_RECV);
|
mg_hexdump_connection(nc, nc->mgr->hexdump_file, buf, n, MG_EV_RECV);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
mbuf_trim(&nc->recv_mbuf);
|
||||||
mg_call(nc, NULL, nc->user_data, MG_EV_RECV, &n);
|
mg_call(nc, NULL, nc->user_data, MG_EV_RECV, &n);
|
||||||
} else if (n < 0) {
|
} else if (n < 0) {
|
||||||
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||||
}
|
}
|
||||||
|
mbuf_trim(&nc->recv_mbuf);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,7 +714,9 @@ static int mg_recv_udp(struct mg_connection *nc, char *buf, size_t len) {
|
|||||||
mg_hexdump_connection(nc, nc->mgr->hexdump_file, buf, n, MG_EV_RECV);
|
mg_hexdump_connection(nc, nc->mgr->hexdump_file, buf, n, MG_EV_RECV);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
mg_call(nc, NULL, nc->user_data, MG_EV_RECV, &n);
|
if (n != 0) {
|
||||||
|
mg_call(nc, NULL, nc->user_data, MG_EV_RECV, &n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -738,7 +758,7 @@ void mg_if_can_send_cb(struct mg_connection *nc) {
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
if (len > 0) {
|
||||||
if (nc->flags & MG_F_UDP) {
|
if (nc->flags & MG_F_UDP) {
|
||||||
n = nc->iface->vtable->udp_send(nc, buf, len);
|
n = nc->iface->vtable->udp_send(nc, buf, len);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+6
-4
@@ -89,6 +89,7 @@ struct mg_mgr {
|
|||||||
#endif
|
#endif
|
||||||
void *user_data; /* User data */
|
void *user_data; /* User data */
|
||||||
int num_ifaces;
|
int num_ifaces;
|
||||||
|
int num_calls;
|
||||||
struct mg_iface **ifaces; /* network interfaces */
|
struct mg_iface **ifaces; /* network interfaces */
|
||||||
const char *nameserver; /* DNS server to use */
|
const char *nameserver; /* DNS server to use */
|
||||||
};
|
};
|
||||||
@@ -139,6 +140,7 @@ struct mg_connection {
|
|||||||
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
||||||
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
||||||
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
||||||
|
#define MG_F_RECV_AND_CLOSE (1 << 9) /* Drain rx and close the connection. */
|
||||||
|
|
||||||
/* Flags that are settable by user */
|
/* Flags that are settable by user */
|
||||||
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
||||||
@@ -201,17 +203,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data,
|
|||||||
*
|
*
|
||||||
* Closes and deallocates all active connections.
|
* Closes and deallocates all active connections.
|
||||||
*/
|
*/
|
||||||
void mg_mgr_free(struct mg_mgr *);
|
void mg_mgr_free(struct mg_mgr *mgr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function performs the actual IO and must be called in a loop
|
* This function performs the actual IO and must be called in a loop
|
||||||
* (an event loop). It returns the current timestamp.
|
* (an event loop). It returns number of user events generated (except POLLs).
|
||||||
* `milli` is the maximum number of milliseconds to sleep.
|
* `milli` is the maximum number of milliseconds to sleep.
|
||||||
* `mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
* `mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
||||||
* of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
* of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
||||||
* event handlers and returns.
|
* event handlers and returns.
|
||||||
*/
|
*/
|
||||||
time_t mg_mgr_poll(struct mg_mgr *, int milli);
|
int mg_mgr_poll(struct mg_mgr *mgr, int milli);
|
||||||
|
|
||||||
#if MG_ENABLE_BROADCAST
|
#if MG_ENABLE_BROADCAST
|
||||||
/*
|
/*
|
||||||
@@ -224,7 +226,7 @@ time_t mg_mgr_poll(struct mg_mgr *, int milli);
|
|||||||
* `func` callback function will be called by the IO thread for each
|
* `func` callback function will be called by the IO thread for each
|
||||||
* connection. When called, the event will be `MG_EV_POLL`, and a message will
|
* connection. When called, the event will be `MG_EV_POLL`, and a message will
|
||||||
* be passed as the `ev_data` pointer. Maximum message size is capped
|
* be passed as the `ev_data` pointer. Maximum message size is capped
|
||||||
* by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
|
* by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes by default.
|
||||||
*/
|
*/
|
||||||
void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data,
|
void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
|||||||
@@ -39,3 +39,15 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr,
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double mg_mgr_min_timer(const struct mg_mgr *mgr) {
|
||||||
|
double min_timer = 0;
|
||||||
|
struct mg_connection *nc;
|
||||||
|
for (nc = mgr->active_connections; nc != NULL; nc = nc->next) {
|
||||||
|
if (nc->ev_timer_time <= 0) continue;
|
||||||
|
if (min_timer == 0 || nc->ev_timer_time < min_timer) {
|
||||||
|
min_timer = nc->ev_timer_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min_timer;
|
||||||
|
}
|
||||||
@@ -118,6 +118,12 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len,
|
|||||||
/* Deliver a POLL event to the connection. */
|
/* Deliver a POLL event to the connection. */
|
||||||
int mg_if_poll(struct mg_connection *nc, double now);
|
int mg_if_poll(struct mg_connection *nc, double now);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return minimal timer value amoung connections in the manager.
|
||||||
|
* Returns 0 if there aren't any timers.
|
||||||
|
*/
|
||||||
|
double mg_mgr_min_timer(const struct mg_mgr *mgr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* This software is dual-licensed: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation. For the terms of this
|
||||||
|
* license, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* You are free to use this software under the terms of the GNU General
|
||||||
|
* Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* Alternatively, you can license this software under a commercial
|
||||||
|
* license, as set out in <https://www.cesanta.com/license>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void mg_null_if_connect_tcp(struct mg_connection *c,
|
||||||
|
const union socket_address *sa) {
|
||||||
|
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||||
|
(void) sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_connect_udp(struct mg_connection *c) {
|
||||||
|
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mg_null_if_listen_tcp(struct mg_connection *c,
|
||||||
|
union socket_address *sa) {
|
||||||
|
(void) c;
|
||||||
|
(void) sa;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mg_null_if_listen_udp(struct mg_connection *c,
|
||||||
|
union socket_address *sa) {
|
||||||
|
(void) c;
|
||||||
|
(void) sa;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mg_null_if_tcp_send(struct mg_connection *c, const void *buf,
|
||||||
|
size_t len) {
|
||||||
|
(void) c;
|
||||||
|
(void) buf;
|
||||||
|
(void) len;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mg_null_if_udp_send(struct mg_connection *c, const void *buf,
|
||||||
|
size_t len) {
|
||||||
|
(void) c;
|
||||||
|
(void) buf;
|
||||||
|
(void) len;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mg_null_if_tcp_recv(struct mg_connection *c, void *buf, size_t len) {
|
||||||
|
(void) c;
|
||||||
|
(void) buf;
|
||||||
|
(void) len;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mg_null_if_udp_recv(struct mg_connection *c, void *buf, size_t len,
|
||||||
|
union socket_address *sa, size_t *sa_len) {
|
||||||
|
(void) c;
|
||||||
|
(void) buf;
|
||||||
|
(void) len;
|
||||||
|
(void) sa;
|
||||||
|
(void) sa_len;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mg_null_if_create_conn(struct mg_connection *c) {
|
||||||
|
(void) c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_destroy_conn(struct mg_connection *c) {
|
||||||
|
(void) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_sock_set(struct mg_connection *c, sock_t sock) {
|
||||||
|
(void) c;
|
||||||
|
(void) sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_init(struct mg_iface *iface) {
|
||||||
|
(void) iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_free(struct mg_iface *iface) {
|
||||||
|
(void) iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_add_conn(struct mg_connection *c) {
|
||||||
|
c->sock = INVALID_SOCKET;
|
||||||
|
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_remove_conn(struct mg_connection *c) {
|
||||||
|
(void) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t mg_null_if_poll(struct mg_iface *iface, int timeout_ms) {
|
||||||
|
struct mg_mgr *mgr = iface->mgr;
|
||||||
|
struct mg_connection *nc, *tmp;
|
||||||
|
double now = mg_time();
|
||||||
|
/* We basically just run timers and poll. */
|
||||||
|
for (nc = mgr->active_connections; nc != NULL; nc = tmp) {
|
||||||
|
tmp = nc->next;
|
||||||
|
mg_if_poll(nc, now);
|
||||||
|
}
|
||||||
|
(void) timeout_ms;
|
||||||
|
return (time_t) now;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mg_null_if_get_conn_addr(struct mg_connection *c, int remote,
|
||||||
|
union socket_address *sa) {
|
||||||
|
(void) c;
|
||||||
|
(void) remote;
|
||||||
|
(void) sa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MG_NULL_IFACE_VTABLE \
|
||||||
|
{ \
|
||||||
|
mg_null_if_init, mg_null_if_free, mg_null_if_add_conn, \
|
||||||
|
mg_null_if_remove_conn, mg_null_if_poll, mg_null_if_listen_tcp, \
|
||||||
|
mg_null_if_listen_udp, mg_null_if_connect_tcp, mg_null_if_connect_udp, \
|
||||||
|
mg_null_if_tcp_send, mg_null_if_udp_send, mg_null_if_tcp_recv, \
|
||||||
|
mg_null_if_udp_recv, mg_null_if_create_conn, mg_null_if_destroy_conn, \
|
||||||
|
mg_null_if_sock_set, mg_null_if_get_conn_addr, \
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct mg_iface_vtable mg_null_iface_vtable = MG_NULL_IFACE_VTABLE;
|
||||||
|
|
||||||
|
#if MG_NET_IF == MG_NET_IF_NULL
|
||||||
|
const struct mg_iface_vtable mg_default_iface_vtable = MG_NULL_IFACE_VTABLE;
|
||||||
|
#endif /* MG_NET_IF == MG_NET_IF_NULL */
|
||||||
+3
-1
@@ -152,7 +152,9 @@ static void mg_resolve_async_eh(struct mg_connection *nc, int ev,
|
|||||||
void *user_data = nc->user_data;
|
void *user_data = nc->user_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ev != MG_EV_POLL) DBG(("ev=%d user_data=%p", ev, user_data));
|
if (ev != MG_EV_POLL) {
|
||||||
|
DBG(("ev=%d user_data=%p", ev, user_data));
|
||||||
|
}
|
||||||
|
|
||||||
req = (struct mg_resolve_async_request *) user_data;
|
req = (struct mg_resolve_async_request *) user_data;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ static void mg_ssl_mbed_log(void *ctx, int level, const char *file, int line,
|
|||||||
}
|
}
|
||||||
/* mbedTLS passes strings with \n at the end, strip it. */
|
/* mbedTLS passes strings with \n at the end, strip it. */
|
||||||
LOG(cs_level, ("%p %.*s", ctx, (int) (strlen(str) - 1), str));
|
LOG(cs_level, ("%p %.*s", ctx, (int) (strlen(str) - 1), str));
|
||||||
|
(void) ctx;
|
||||||
|
(void) str;
|
||||||
(void) file;
|
(void) file;
|
||||||
(void) line;
|
(void) line;
|
||||||
(void) cs_level;
|
(void) cs_level;
|
||||||
@@ -221,9 +223,9 @@ static void mg_ssl_if_mbed_free_certs_and_keys(struct mg_ssl_if_ctx *ctx) {
|
|||||||
if (ctx->ca_cert != NULL) {
|
if (ctx->ca_cert != NULL) {
|
||||||
mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL);
|
mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL);
|
||||||
#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
|
#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
|
||||||
if (ctx->ca_cert->ca_chain_file != NULL) {
|
if (ctx->conf->ca_chain_file != NULL) {
|
||||||
MG_FREE((void *) ctx->ca_cert->ca_chain_file);
|
MG_FREE((void *) ctx->conf->ca_chain_file);
|
||||||
ctx->ca_cert->ca_chain_file = NULL;
|
ctx->conf->ca_chain_file = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
mbedtls_x509_crt_free(ctx->ca_cert);
|
mbedtls_x509_crt_free(ctx->ca_cert);
|
||||||
@@ -330,15 +332,13 @@ static enum mg_ssl_if_result mg_use_ca_cert(struct mg_ssl_if_ctx *ctx,
|
|||||||
mbedtls_x509_crt_init(ctx->ca_cert);
|
mbedtls_x509_crt_init(ctx->ca_cert);
|
||||||
#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
|
#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
|
||||||
ca_cert = strdup(ca_cert);
|
ca_cert = strdup(ca_cert);
|
||||||
if (mbedtls_x509_crt_set_ca_chain_file(ctx->ca_cert, ca_cert) != 0) {
|
mbedtls_ssl_conf_ca_chain_file(ctx->conf, ca_cert, NULL);
|
||||||
return MG_SSL_ERROR;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (mbedtls_x509_crt_parse_file(ctx->ca_cert, ca_cert) != 0) {
|
if (mbedtls_x509_crt_parse_file(ctx->ca_cert, ca_cert) != 0) {
|
||||||
return MG_SSL_ERROR;
|
return MG_SSL_ERROR;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
mbedtls_ssl_conf_ca_chain(ctx->conf, ctx->ca_cert, NULL);
|
mbedtls_ssl_conf_ca_chain(ctx->conf, ctx->ca_cert, NULL);
|
||||||
|
#endif
|
||||||
mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||||
return MG_SSL_OK;
|
return MG_SSL_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -9,7 +9,9 @@ SRC_DIR = ../src
|
|||||||
COMMON_DIR_PUB = ../src/common
|
COMMON_DIR_PUB = ../src/common
|
||||||
COMMON_DIR_DEV = ../../common
|
COMMON_DIR_DEV = ../../common
|
||||||
|
|
||||||
ifneq ("$(wildcard ../../fw/defs)","")
|
# Our dev repo and public mongoose repo have different layouts, so here
|
||||||
|
# we make it work on both
|
||||||
|
ifneq ("$(wildcard ../../fw)","")
|
||||||
COMMON_PARENT = ../..
|
COMMON_PARENT = ../..
|
||||||
else
|
else
|
||||||
COMMON_PARENT = $(SRC_DIR)
|
COMMON_PARENT = $(SRC_DIR)
|
||||||
@@ -19,8 +21,6 @@ TEST_SOURCES = unit_test.c test_util.c test_main.c
|
|||||||
AMALGAMATED_SOURCES = ../mongoose.c
|
AMALGAMATED_SOURCES = ../mongoose.c
|
||||||
KRYPTON_PATH = $(REPO_ROOT)/krypton
|
KRYPTON_PATH = $(REPO_ROOT)/krypton
|
||||||
|
|
||||||
# Our dev repo and public mongoose repo have different layouts, so here
|
|
||||||
# we make it work on both
|
|
||||||
VPATH = $(MONGOOSE_DIR) $(SRC_DIR) $(COMMON_DIR_PUB) $(COMMON_DIR_DEV) $(COMMON_PARENT)
|
VPATH = $(MONGOOSE_DIR) $(SRC_DIR) $(COMMON_DIR_PUB) $(COMMON_DIR_DEV) $(COMMON_PARENT)
|
||||||
|
|
||||||
# or Krypton, or mbedTLS
|
# or Krypton, or mbedTLS
|
||||||
|
|||||||
+86
-44
@@ -15,12 +15,12 @@
|
|||||||
* license, as set out in <https://www.cesanta.com/license>.
|
* license, as set out in <https://www.cesanta.com/license>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mongoose.h"
|
|
||||||
#include "src/mg_internal.h"
|
|
||||||
#include "unit_test.h"
|
#include "unit_test.h"
|
||||||
|
#include "common/cs_md5.h"
|
||||||
#include "common/test_main.h"
|
#include "common/test_main.h"
|
||||||
#include "common/test_util.h"
|
#include "common/test_util.h"
|
||||||
#include "common/cs_md5.h"
|
#include "mongoose.h"
|
||||||
|
#include "src/mg_internal.h"
|
||||||
|
|
||||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ < 199901L && !defined(WIN32)
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ < 199901L && !defined(WIN32)
|
||||||
#define __func__ ""
|
#define __func__ ""
|
||||||
@@ -2011,7 +2011,8 @@ static const char *test_http(void) {
|
|||||||
char buf[50] = "", status[100] = "", mime1[20] = "", mime2[100] = "";
|
char buf[50] = "", status[100] = "", mime1[20] = "", mime2[100] = "";
|
||||||
char opt_buf[1024] = "";
|
char opt_buf[1024] = "";
|
||||||
const char *opt_answer =
|
const char *opt_answer =
|
||||||
"HTTP/1.1 200 OK\r\nAllow: GET, POST, HEAD, CONNECT, OPTIONS, MKCOL, "
|
"HTTP/1.1 200 OK\r\nServer: Mongoose/" MG_VERSION
|
||||||
|
"\r\nAllow: GET, POST, HEAD, CONNECT, OPTIONS, MKCOL, "
|
||||||
"PUT, DELETE, PROPFIND, MOVE";
|
"PUT, DELETE, PROPFIND, MOVE";
|
||||||
char url[1000];
|
char url[1000];
|
||||||
|
|
||||||
@@ -2069,7 +2070,7 @@ static const char *test_http(void) {
|
|||||||
nc->user_data = mime2;
|
nc->user_data = mime2;
|
||||||
|
|
||||||
/* Run event loop. Use more cycles to let file download complete. */
|
/* Run event loop. Use more cycles to let file download complete. */
|
||||||
poll_until(&mgr, 5, c_str_ne, status, (void *) "");
|
poll_until(&mgr, 15, c_str_ne, status, (void *) "");
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
/* Check that test buffer has been filled by the callback properly. */
|
/* Check that test buffer has been filled by the callback properly. */
|
||||||
@@ -2539,32 +2540,6 @@ static const char *test_http_range(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cb3(struct mg_connection *nc, int ev, void *ev_data) {
|
|
||||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
|
||||||
|
|
||||||
if (ev == MG_EV_WEBSOCKET_FRAME) {
|
|
||||||
const char *reply = wm->size == 2 && !memcmp(wm->data, "hi", 2) ? "A" : "B";
|
|
||||||
mg_printf_websocket_frame(nc, WEBSOCKET_OP_TEXT, "%s", reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cb4(struct mg_connection *nc, int ev, void *ev_data) {
|
|
||||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
|
||||||
|
|
||||||
if (ev == MG_EV_WEBSOCKET_FRAME) {
|
|
||||||
memcpy(nc->user_data, wm->data, wm->size);
|
|
||||||
mg_send_websocket_frame(nc, WEBSOCKET_OP_CLOSE, NULL, 0);
|
|
||||||
} else if (ev == MG_EV_WEBSOCKET_HANDSHAKE_DONE) {
|
|
||||||
/* Send "hi" to server. server must reply "A". */
|
|
||||||
struct mg_str h[2];
|
|
||||||
h[0].p = "h";
|
|
||||||
h[0].len = 1;
|
|
||||||
h[1].p = "i";
|
|
||||||
h[1].len = 1;
|
|
||||||
mg_send_websocket_framev(nc, WEBSOCKET_OP_TEXT, h, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cb_ws_server(struct mg_connection *nc, int ev, void *ev_data) {
|
static void cb_ws_server(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||||
|
|
||||||
@@ -2779,6 +2754,38 @@ static const char *test_websocket(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cb3(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
|
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||||
|
if (ev != MG_EV_WEBSOCKET_FRAME) return;
|
||||||
|
DBG(("server data '%.*s'", (int) wm->size, wm->data));
|
||||||
|
const char *reply = wm->size == 2 && !memcmp(wm->data, "hi", 2) ? "A" : "B";
|
||||||
|
mg_printf_websocket_frame(nc, WEBSOCKET_OP_TEXT, "%s", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb4(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
|
char *buf = (char *) nc->user_data;
|
||||||
|
if (ev == MG_EV_WEBSOCKET_FRAME) {
|
||||||
|
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||||
|
DBG(("client data '%.*s'", (int) wm->size, wm->data));
|
||||||
|
memcpy(buf, wm->data, wm->size);
|
||||||
|
mg_send_websocket_frame(nc, WEBSOCKET_OP_CLOSE, NULL, 0);
|
||||||
|
} else if (ev == MG_EV_WEBSOCKET_HANDSHAKE_DONE) {
|
||||||
|
struct http_message *hm = (struct http_message *) ev_data;
|
||||||
|
DBG(("code %d", hm->resp_code));
|
||||||
|
if (hm->resp_code == 101) {
|
||||||
|
/* Send "hi" to server. server must reply "A". */
|
||||||
|
struct mg_str h[2];
|
||||||
|
h[0].p = "h";
|
||||||
|
h[0].len = 1;
|
||||||
|
h[1].p = "i";
|
||||||
|
h[1].len = 1;
|
||||||
|
mg_send_websocket_framev(nc, WEBSOCKET_OP_TEXT, h, 2);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, 20, "code %d", hm->resp_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void cbwep(struct mg_connection *c, int ev, void *ev_data) {
|
static void cbwep(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||||
char *buf = (char *) c->user_data;
|
char *buf = (char *) c->user_data;
|
||||||
@@ -2786,6 +2793,9 @@ static void cbwep(struct mg_connection *c, int ev, void *ev_data) {
|
|||||||
switch (ev) {
|
switch (ev) {
|
||||||
case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST:
|
case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST:
|
||||||
strcat(buf, "R");
|
strcat(buf, "R");
|
||||||
|
if (buf[0] != '0') {
|
||||||
|
mg_http_send_error(c, 403, "I don't like you");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
|
case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
|
||||||
strcat(buf, "D");
|
strcat(buf, "D");
|
||||||
@@ -2802,7 +2812,7 @@ static const char *test_websocket_endpoint(void) {
|
|||||||
struct mg_mgr mgr;
|
struct mg_mgr mgr;
|
||||||
struct mg_connection *nc;
|
struct mg_connection *nc;
|
||||||
const char *local_addr = "127.0.0.1:7798";
|
const char *local_addr = "127.0.0.1:7798";
|
||||||
char buf[20] = "", buf2[20] = "";
|
char buf[20] = "", buf2[20] = "0";
|
||||||
|
|
||||||
mg_mgr_init(&mgr, NULL);
|
mg_mgr_init(&mgr, NULL);
|
||||||
/* mgr.hexdump_file = "-"; */
|
/* mgr.hexdump_file = "-"; */
|
||||||
@@ -2817,10 +2827,21 @@ static const char *test_websocket_endpoint(void) {
|
|||||||
nc->user_data = buf;
|
nc->user_data = buf;
|
||||||
mg_send_websocket_handshake(nc, "/boo", NULL);
|
mg_send_websocket_handshake(nc, "/boo", NULL);
|
||||||
poll_until(&mgr, 1, c_str_ne, buf, (void *) "");
|
poll_until(&mgr, 1, c_str_ne, buf, (void *) "");
|
||||||
mg_mgr_free(&mgr);
|
|
||||||
|
|
||||||
/* Check that test buffer has been filled by the callback properly. */
|
/* Check that test buffer has been filled by the callback properly. */
|
||||||
ASSERT_STREQ(buf, "RDF|hi");
|
ASSERT_STREQ(buf, "0RDF|hi");
|
||||||
|
|
||||||
|
/* Test handshake failure */
|
||||||
|
ASSERT((nc = mg_connect(&mgr, local_addr, cb4)) != NULL);
|
||||||
|
mg_set_protocol_http_websocket(nc);
|
||||||
|
buf[0] = '\0';
|
||||||
|
buf2[0] = '1';
|
||||||
|
buf2[1] = '\0';
|
||||||
|
nc->user_data = buf;
|
||||||
|
mg_send_websocket_handshake(nc, "/boo", NULL);
|
||||||
|
poll_until(&mgr, 1, c_str_ne, buf, (void *) "");
|
||||||
|
ASSERT_STREQ(buf, "code 403");
|
||||||
|
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -3379,15 +3400,36 @@ static const char *test_mqtt_parse_mqtt_qos1(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *test_mqtt_match_topic_expression(void) {
|
static const char *test_mqtt_match_topic_expression(void) {
|
||||||
ASSERT_EQ(mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo")), 1);
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo")));
|
||||||
ASSERT_EQ(mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo/")), 0);
|
ASSERT(mg_mqtt_vmatch_topic_expression("/foo", mg_mk_str("/foo")));
|
||||||
ASSERT_EQ(mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo/bar")), 0);
|
ASSERT(mg_mqtt_vmatch_topic_expression("+/foo", mg_mk_str("/foo")));
|
||||||
|
ASSERT(!mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foobar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo/")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo//")));
|
||||||
|
ASSERT(!mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(!mg_mqtt_vmatch_topic_expression("foo", mg_mk_str("foo/+")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/bar", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/+", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("+/bar", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("+/+", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/+/bar", mg_mk_str("foo//bar")));
|
||||||
|
ASSERT(!mg_mqtt_vmatch_topic_expression("foo/+/+", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/+/#", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("+/foo/bar", mg_mk_str("/foo/bar")));
|
||||||
|
|
||||||
ASSERT_EQ(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo")), 0);
|
ASSERT(!mg_mqtt_vmatch_topic_expression("", mg_mk_str("")));
|
||||||
ASSERT_EQ(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo/")), 0);
|
ASSERT(mg_mqtt_vmatch_topic_expression("/", mg_mk_str("")));
|
||||||
ASSERT_EQ(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo/bar")), 1);
|
ASSERT(mg_mqtt_vmatch_topic_expression("/", mg_mk_str("/")));
|
||||||
ASSERT_EQ(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo/bar/baz")),
|
|
||||||
1);
|
ASSERT(mg_mqtt_vmatch_topic_expression("#", mg_mk_str("")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("#", mg_mk_str("foo")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("#", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo/")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo/bar")));
|
||||||
|
ASSERT(mg_mqtt_vmatch_topic_expression("foo/#", mg_mk_str("foo/bar/baz")));
|
||||||
|
ASSERT(!mg_mqtt_vmatch_topic_expression("#/foo", mg_mk_str("foo")));
|
||||||
|
ASSERT(!mg_mqtt_vmatch_topic_expression("#/foo", mg_mk_str("bar/foo")));
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -5665,7 +5707,7 @@ static const char *test_socks(void) {
|
|||||||
mbuf_resize(&c->recv_mbuf, 10000000);
|
mbuf_resize(&c->recv_mbuf, 10000000);
|
||||||
|
|
||||||
/* Run event loop. Use more cycles to let file download complete. */
|
/* Run event loop. Use more cycles to let file download complete. */
|
||||||
poll_until(&mgr, 10, c_str_ne, status, (void *) "");
|
poll_until(&mgr, 15, c_str_ne, status, (void *) "");
|
||||||
ASSERT_STREQ(status, "success");
|
ASSERT_STREQ(status, "success");
|
||||||
|
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
|
|||||||
Reference in new issue
Block a user