From b84981ad034e5231c783cfcadf3b8c3ce83ac9b6 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Fri, 17 Aug 2018 22:59:51 +0300 Subject: [PATCH 01/21] STM32 OTA support for L475-IOT01 and DISCO-F746 A smattering of other related changes CL: STM32 OTA support for L475-IOT01 and DISCO-F746 PUBLISHED_FROM=e7142337086d09ba21437455b22d00db47ab33f1 --- src/common/platforms/arm/arm_exc.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/common/platforms/arm/arm_exc.c b/src/common/platforms/arm/arm_exc.c index 7f83b3cc4b..69aba18741 100644 --- a/src/common/platforms/arm/arm_exc.c +++ b/src/common/platforms/arm/arm_exc.c @@ -27,6 +27,10 @@ #include "mgos_core_dump.h" #include "mgos_hal.h" +#ifndef MGOS_ENABLE_CORE_DUMP +#define MGOS_ENABLE_CORE_DUMP 1 +#endif + struct arm_exc_frame { uint32_t r0; uint32_t r1; @@ -53,7 +57,7 @@ struct arm_gdb_reg_file { uint32_t fpscr; } __attribute__((packed)); -#if ARM_HAVE_FPU +#if ARM_HAVE_FPU && !defined(MGOS_BOOT_BUILD) static void save_s16_s31(uint32_t *dst) { __asm volatile( "\ @@ -134,16 +138,20 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, name = "SysTick"; break; default: { +#ifndef MGOS_BOOT_BUILD sprintf(buf, "IRQ%u", isr_no - 16); +#endif name = buf; } } mgos_cd_printf("\n\n--- Exception %u (%s) ---\n", isr_no, name); if (rf != NULL) { - mgos_cd_printf(" R0: 0x%08lx R1: 0x%08lx R2: 0x%08lx R3: 0x%08lx\n", - rf->r[0], rf->r[1], rf->r[2], rf->r[3]); - mgos_cd_printf(" R4: 0x%08lx R5: 0x%08lx R6: 0x%08lx R7: 0x%08lx\n", - 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", 0, + rf->r[0], 1, rf->r[1], 2, rf->r[2], 3, rf->r[3]); + 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", 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", @@ -151,7 +159,7 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, mgos_cd_printf(" PSR: 0x%08lx\n", rf->cpsr); } memset(rf->d, 0, sizeof(rf->d)); -#if ARM_HAVE_FPU +#if ARM_HAVE_FPU && !defined(MGOS_BOOT_BUILD) rf->fpscr = ef->fpscr; memcpy((uint8_t *) rf->d, ef->s, sizeof(ef->s)); print_fpu_regs((uint32_t *) rf->d, 0, ARRAY_SIZE(ef->s)); @@ -164,10 +172,12 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, #else rf->fpscr = 0; #endif +#if MGOS_ENABLE_CORE_DUMP mgos_cd_emit_header(); 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_footer(); +#endif #ifdef MGOS_HALT_ON_EXCEPTION mgos_cd_printf("Halting\n"); while (1) { From 955d4a31298179ea0af156ad961280d1844b6544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=B1=D0=B1=D0=B8?= Date: Tue, 21 Aug 2018 14:44:19 +0100 Subject: [PATCH 02/21] Fix file upload on windows CL: Fix https://github.com/cesanta/mongoose/issues/962 - file upload on windows PUBLISHED_FROM=85688eee147a1df468cca92f4ac61526ce9c02bf --- mongoose.c | 2 +- src/mg_http.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mongoose.c b/mongoose.c index d11756499c..d09345c5ea 100644 --- a/mongoose.c +++ b/mongoose.c @@ -8328,7 +8328,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); LOG(LL_DEBUG, ("%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) { mg_printf(nc, "HTTP/1.1 500 Internal Server Error\r\n" diff --git a/src/mg_http.c b/src/mg_http.c index 257bde4ceb..dcf4c22da5 100644 --- a/src/mg_http.c +++ b/src/mg_http.c @@ -2737,7 +2737,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); LOG(LL_DEBUG, ("%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) { mg_printf(nc, "HTTP/1.1 500 Internal Server Error\r\n" From 421e099f2b8ae66741a07607091206f542340eb5 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Mon, 9 Jul 2018 13:16:58 +0300 Subject: [PATCH 03/21] Refactor mg polling * Change return type of mg_mgr_poll to return number of events * Add mg_mgr_min_timer * Refactor main poll loop to remove LwIP-specific stuff CL: Refactor mg polling PUBLISHED_FROM=dc94618b32fa3c84a2f053bd04d134297780ec82 --- docs/c-api/mg_net.h/mg_mgr_free.md | 2 +- docs/c-api/mg_net.h/mg_mgr_poll.md | 4 +- docs/c-api/mg_net.h/struct_mg_mgr.md | 1 + mongoose.c | 60 +++++++--------------- mongoose.h | 14 +++-- src/common/platforms/lwip/mg_lwip.h | 1 - src/common/platforms/lwip/mg_lwip_ev_mgr.c | 32 ------------ src/mg_net.c | 16 +++--- src/mg_net.h | 7 +-- src/mg_net_if.c | 12 +++++ src/mg_net_if.h | 6 +++ 11 files changed, 60 insertions(+), 95 deletions(-) diff --git a/docs/c-api/mg_net.h/mg_mgr_free.md b/docs/c-api/mg_net.h/mg_mgr_free.md index d2df34e4c2..60ad75bdc5 100644 --- a/docs/c-api/mg_net.h/mg_mgr_free.md +++ b/docs/c-api/mg_net.h/mg_mgr_free.md @@ -3,7 +3,7 @@ title: "mg_mgr_free()" decl_name: "mg_mgr_free" symbol_kind: "func" signature: | - void mg_mgr_free(struct mg_mgr *); + void mg_mgr_free(struct mg_mgr *mgr); --- De-initialises Mongoose manager. diff --git a/docs/c-api/mg_net.h/mg_mgr_poll.md b/docs/c-api/mg_net.h/mg_mgr_poll.md index b70c31b6db..ef48a19082 100644 --- a/docs/c-api/mg_net.h/mg_mgr_poll.md +++ b/docs/c-api/mg_net.h/mg_mgr_poll.md @@ -3,11 +3,11 @@ title: "mg_mgr_poll()" decl_name: "mg_mgr_poll" symbol_kind: "func" 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 -(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. `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 diff --git a/docs/c-api/mg_net.h/struct_mg_mgr.md b/docs/c-api/mg_net.h/struct_mg_mgr.md index d33727c38d..44efa5fdf2 100644 --- a/docs/c-api/mg_net.h/struct_mg_mgr.md +++ b/docs/c-api/mg_net.h/struct_mg_mgr.md @@ -13,6 +13,7 @@ signature: | #endif void *user_data; /* User data */ int num_ifaces; + int num_calls; struct mg_iface **ifaces; /* network interfaces */ const char *nameserver; /* DNS server to use */ }; diff --git a/mongoose.c b/mongoose.c index d09345c5ea..7b0170c2b5 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2408,6 +2408,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); } } + if (ev != MG_EV_POLL) nc->mgr->num_calls++; if (ev != MG_EV_POLL) { DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc, ev_handler == nc->handler ? "user" : "proto", nc->flags, @@ -2585,19 +2586,14 @@ void mg_mgr_free(struct mg_mgr *m) { MG_FREE((char *) m->nameserver); } -time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { - int i; - time_t now = 0; /* oh GCC, seriously ? */ - - if (m->num_ifaces == 0) { - LOG(LL_ERROR, ("cannot poll: no interfaces")); - return 0; - } +int mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { + int i, num_calls_before = m->num_calls; 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) { @@ -3585,6 +3581,18 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr, } 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; +} #ifdef MG_MODULE_LINES #line 1 "mongoose/src/mg_net_if_socket.c" #endif @@ -15716,38 +15724,6 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { 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 */ #ifdef MG_MODULE_LINES #line 1 "common/platforms/wince/wince_libc.c" diff --git a/mongoose.h b/mongoose.h index 2667c75905..7c179d692f 100644 --- a/mongoose.h +++ b/mongoose.h @@ -2030,7 +2030,6 @@ typedef int sock_t; #if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL struct mg_mgr; 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, int interval, int count); #endif @@ -3718,6 +3717,12 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, /* Deliver a POLL event to the connection. */ 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 } #endif /* __cplusplus */ @@ -3875,6 +3880,7 @@ struct mg_mgr { #endif void *user_data; /* User data */ int num_ifaces; + int num_calls; struct mg_iface **ifaces; /* network interfaces */ const char *nameserver; /* DNS server to use */ }; @@ -3987,17 +3993,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data, * * 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 - * (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. * `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 * 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 /* diff --git a/src/common/platforms/lwip/mg_lwip.h b/src/common/platforms/lwip/mg_lwip.h index c0d4081e88..c15e2ee2db 100644 --- a/src/common/platforms/lwip/mg_lwip.h +++ b/src/common/platforms/lwip/mg_lwip.h @@ -66,7 +66,6 @@ typedef int sock_t; #if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL struct mg_mgr; 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, int interval, int count); #endif diff --git a/src/common/platforms/lwip/mg_lwip_ev_mgr.c b/src/common/platforms/lwip/mg_lwip_ev_mgr.c index 39937fc919..b495464e91 100644 --- a/src/common/platforms/lwip/mg_lwip_ev_mgr.c +++ b/src/common/platforms/lwip/mg_lwip_ev_mgr.c @@ -167,36 +167,4 @@ time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) { 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 */ diff --git a/src/mg_net.c b/src/mg_net.c index 5c96140914..3862fa892f 100644 --- a/src/mg_net.c +++ b/src/mg_net.c @@ -99,6 +99,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc, (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); } } + if (ev != MG_EV_POLL) nc->mgr->num_calls++; if (ev != MG_EV_POLL) { DBG(("%p after %s flags=0x%lx rmbl=%d smbl=%d", nc, ev_handler == nc->handler ? "user" : "proto", nc->flags, @@ -276,19 +277,14 @@ void mg_mgr_free(struct mg_mgr *m) { MG_FREE((char *) m->nameserver); } -time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { - int i; - time_t now = 0; /* oh GCC, seriously ? */ - - if (m->num_ifaces == 0) { - LOG(LL_ERROR, ("cannot poll: no interfaces")); - return 0; - } +int mg_mgr_poll(struct mg_mgr *m, int timeout_ms) { + int i, num_calls_before = m->num_calls; 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) { diff --git a/src/mg_net.h b/src/mg_net.h index 90b42b47af..d854e770a2 100644 --- a/src/mg_net.h +++ b/src/mg_net.h @@ -89,6 +89,7 @@ struct mg_mgr { #endif void *user_data; /* User data */ int num_ifaces; + int num_calls; struct mg_iface **ifaces; /* network interfaces */ const char *nameserver; /* DNS server to use */ }; @@ -201,17 +202,17 @@ void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data, * * 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 - * (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. * `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 * 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 /* diff --git a/src/mg_net_if.c b/src/mg_net_if.c index 2a93dcfd4a..c91feb9960 100644 --- a/src/mg_net_if.c +++ b/src/mg_net_if.c @@ -39,3 +39,15 @@ struct mg_iface *mg_find_iface(struct mg_mgr *mgr, } 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; +} diff --git a/src/mg_net_if.h b/src/mg_net_if.h index cba58fb95f..1239d54a0a 100644 --- a/src/mg_net_if.h +++ b/src/mg_net_if.h @@ -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. */ 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 } #endif /* __cplusplus */ From 563c31303e9a62bd732ec7079f0a37799640cf6a Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Thu, 6 Sep 2018 09:52:07 +0300 Subject: [PATCH 04/21] Add net_if_null, a no-op net interface Can be used for cases where device has no networking but mongoose is still needed for its event loop. CL: mg: Add net_if_null, a no-op net interface PUBLISHED_FROM=e79b4a8667508bbde1437dda9dad77ce3a3aa630 --- mongoose.c | 144 ++++++++++++++++++++++++++++++++++++++++++ mongoose.h | 1 + src/common/platform.h | 1 + src/mg_modules.mk | 1 + src/mg_net_if_null.c | 141 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 288 insertions(+) create mode 100644 src/mg_net_if_null.c diff --git a/mongoose.c b/mongoose.c index 7b0170c2b5..8a8f3827ce 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3594,6 +3594,150 @@ double mg_mgr_min_timer(const struct mg_mgr *mgr) { return min_timer; } #ifdef MG_MODULE_LINES +#line 1 "mongoose/src/mg_net_if_null.c" +#endif +/* + * 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 . + * + * 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 . + */ + +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 */ +#ifdef MG_MODULE_LINES #line 1 "mongoose/src/mg_net_if_socket.c" #endif /* diff --git a/mongoose.h b/mongoose.h index 7c179d692f..422af564b5 100644 --- a/mongoose.h +++ b/mongoose.h @@ -105,6 +105,7 @@ #define MG_NET_IF_SIMPLELINK 2 #define MG_NET_IF_LWIP_LOW_LEVEL 3 #define MG_NET_IF_PIC32 4 +#define MG_NET_IF_NULL 5 #define MG_SSL_IF_OPENSSL 1 #define MG_SSL_IF_MBEDTLS 2 diff --git a/src/common/platform.h b/src/common/platform.h index 1b803c9e6a..af0b4f501b 100644 --- a/src/common/platform.h +++ b/src/common/platform.h @@ -69,6 +69,7 @@ #define MG_NET_IF_SIMPLELINK 2 #define MG_NET_IF_LWIP_LOW_LEVEL 3 #define MG_NET_IF_PIC32 4 +#define MG_NET_IF_NULL 5 #define MG_SSL_IF_OPENSSL 1 #define MG_SSL_IF_MBEDTLS 2 diff --git a/src/mg_modules.mk b/src/mg_modules.mk index 4bc7602609..b53c53b1bf 100644 --- a/src/mg_modules.mk +++ b/src/mg_modules.mk @@ -64,6 +64,7 @@ SOURCES = $(COMMON)/mg_mem.h \ mg_net_if_socket.h \ mg_net_if_socks.h \ mg_net_if.c \ + mg_net_if_null.c \ mg_net_if_socket.c \ mg_net_if_socks.c \ mg_ssl_if_openssl.c \ diff --git a/src/mg_net_if_null.c b/src/mg_net_if_null.c new file mode 100644 index 0000000000..2142b1e6ea --- /dev/null +++ b/src/mg_net_if_null.c @@ -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 . + * + * 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 . + */ + +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 */ From 20f54059ad97c9d27b927955056985bfb2d83d7c Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Thu, 6 Sep 2018 14:09:08 +0300 Subject: [PATCH 05/21] STM32: Make LWIP optional CL: STM32: Make LWIP optional PUBLISHED_FROM=eebffe7800a74d7b69aafd95e476b2e90328be98 --- mongoose.h | 2 +- src/common/platforms/platform_stm32.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mongoose.h b/mongoose.h index 422af564b5..a36482308c 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1945,7 +1945,7 @@ char *inet_ntoa(struct in_addr in); #include #define to64(x) strtoll(x, NULL, 10) -#define INT64_FMT PRId64 +#define INT64_FMT "lld" #define SIZE_T_FMT "u" typedef struct stat cs_stat_t; #define DIRSEP '/' diff --git a/src/common/platforms/platform_stm32.h b/src/common/platforms/platform_stm32.h index 6b937569e4..d5b8919238 100644 --- a/src/common/platforms/platform_stm32.h +++ b/src/common/platforms/platform_stm32.h @@ -34,7 +34,7 @@ #include #define to64(x) strtoll(x, NULL, 10) -#define INT64_FMT PRId64 +#define INT64_FMT "lld" #define SIZE_T_FMT "u" typedef struct stat cs_stat_t; #define DIRSEP '/' From ab035901f83d313d4a3b57501b140632b1f53c15 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Mon, 10 Sep 2018 22:07:41 +0300 Subject: [PATCH 06/21] ISM43XXX networking support (TCP, UDP client) Listeners still TODO CL: ISM43XXX networking support (TCP, UDP client) PUBLISHED_FROM=b58ba88b9e6bd7b55ccb607d0b69cea98cb52fa5 --- mongoose.c | 4 ++-- src/mg_net.c | 2 +- src/mg_net_if_null.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mongoose.c b/mongoose.c index 8a8f3827ce..ceb2b7d728 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3043,7 +3043,7 @@ void mg_if_can_send_cb(struct mg_connection *nc) { } } else #endif - { + if (len > 0) { if (nc->flags & MG_F_UDP) { n = nc->iface->vtable->udp_send(nc, buf, len); } else { @@ -3673,7 +3673,7 @@ int mg_null_if_udp_recv(struct mg_connection *c, void *buf, size_t len, static int mg_null_if_create_conn(struct mg_connection *c) { (void) c; - return -1; + return 1; } static void mg_null_if_destroy_conn(struct mg_connection *c) { diff --git a/src/mg_net.c b/src/mg_net.c index 3862fa892f..2aed7df05c 100644 --- a/src/mg_net.c +++ b/src/mg_net.c @@ -734,7 +734,7 @@ void mg_if_can_send_cb(struct mg_connection *nc) { } } else #endif - { + if (len > 0) { if (nc->flags & MG_F_UDP) { n = nc->iface->vtable->udp_send(nc, buf, len); } else { diff --git a/src/mg_net_if_null.c b/src/mg_net_if_null.c index 2142b1e6ea..cf8bbaa103 100644 --- a/src/mg_net_if_null.c +++ b/src/mg_net_if_null.c @@ -75,7 +75,7 @@ int mg_null_if_udp_recv(struct mg_connection *c, void *buf, size_t len, static int mg_null_if_create_conn(struct mg_connection *c) { (void) c; - return -1; + return 1; } static void mg_null_if_destroy_conn(struct mg_connection *c) { From f63d833a33c77d54831a34b9aa5ea36187b13539 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Tue, 11 Sep 2018 11:32:19 +0300 Subject: [PATCH 07/21] Update STM32 build image * Update CubeL4 to 1.13.0 * Rebuild OurTLS with `-DMBEDTLS_X509_CA_CHAIN_ON_DISK` * Add `-Wextra` and fix build issues CL: Update STM32 build image PUBLISHED_FROM=a7eacff7580bab6c6e40bdaf6164df575a717c55 --- mongoose.c | 6 +++++- src/common/platforms/arm/arm_exc.c | 1 + src/mg_resolv.c | 4 +++- src/mg_ssl_if_mbedtls.c | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mongoose.c b/mongoose.c index ceb2b7d728..a08c800c1e 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4999,6 +4999,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. */ LOG(cs_level, ("%p %.*s", ctx, (int) (strlen(str) - 1), str)); + (void) ctx; + (void) str; (void) file; (void) line; (void) cs_level; @@ -11964,7 +11966,9 @@ static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *user_data = nc->user_data; #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; diff --git a/src/common/platforms/arm/arm_exc.c b/src/common/platforms/arm/arm_exc.c index 69aba18741..606ae5ebbe 100644 --- a/src/common/platforms/arm/arm_exc.c +++ b/src/common/platforms/arm/arm_exc.c @@ -95,6 +95,7 @@ void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef, struct arm_gdb_reg_file *rf) { char buf[8]; const char *name; + (void) ef; portDISABLE_INTERRUPTS(); switch (isr_no) { case 0: diff --git a/src/mg_resolv.c b/src/mg_resolv.c index b8b73a994a..a67c773870 100644 --- a/src/mg_resolv.c +++ b/src/mg_resolv.c @@ -152,7 +152,9 @@ static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *user_data = nc->user_data; #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; diff --git a/src/mg_ssl_if_mbedtls.c b/src/mg_ssl_if_mbedtls.c index 021addcf48..9656e5575c 100644 --- a/src/mg_ssl_if_mbedtls.c +++ b/src/mg_ssl_if_mbedtls.c @@ -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. */ LOG(cs_level, ("%p %.*s", ctx, (int) (strlen(str) - 1), str)); + (void) ctx; + (void) str; (void) file; (void) line; (void) cs_level; From 291fc024cd9a22a3efe0fef556657c812083b718 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Thu, 13 Sep 2018 16:38:38 +0100 Subject: [PATCH 08/21] Docs nits CL: Docs nits PUBLISHED_FROM=1a2fc8080d94673acf300c6f07aba3a1e6272295 --- docs/c-api/mbuf.h/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/c-api/mbuf.h/intro.md b/docs/c-api/mbuf.h/intro.md index 475c65104b..056369a243 100644 --- a/docs/c-api/mbuf.h/intro.md +++ b/docs/c-api/mbuf.h/intro.md @@ -1,5 +1,5 @@ --- -title: "Memory Buffers" +title: "mbuf.h" symbol_kind: "intro" decl_name: "mbuf.h" items: From 341ae53e85cac7d2c9e6573afdfdfc73a3416781 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Sat, 15 Sep 2018 00:13:45 +0300 Subject: [PATCH 09/21] Update mongoose.h (amalgamation) PUBLISHED_FROM=1fbe72f99bda5745c4b9b9def0601bdc5bf70e65 --- mongoose.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/mongoose.h b/mongoose.h index a36482308c..af543d689c 100644 --- a/mongoose.h +++ b/mongoose.h @@ -2312,8 +2312,6 @@ struct mg_str mg_strstrip(struct mg_str s); */ /* - * === Memory Buffers - * * Mbufs are mutable/growing memory buffers, like C++ strings. * 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 From 98f6c8aa4f09aec90a82e776a2df9d79638e0bfd Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Mon, 17 Sep 2018 18:29:59 +0300 Subject: [PATCH 10/21] Trim recv_mbuf when we know the size of the data CL: none PUBLISHED_FROM=e354b67ab6f8246af50c601f5f70d36c029601ea --- mongoose.c | 2 ++ src/mg_net.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mongoose.c b/mongoose.c index a08c800c1e..87703df36a 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2928,10 +2928,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); } #endif + mbuf_trim(&nc->recv_mbuf); mg_call(nc, NULL, nc->user_data, MG_EV_RECV, &n); } else if (n < 0) { nc->flags |= MG_F_CLOSE_IMMEDIATELY; } + mbuf_trim(&nc->recv_mbuf); return n; } diff --git a/src/mg_net.c b/src/mg_net.c index 2aed7df05c..1bf5716b9b 100644 --- a/src/mg_net.c +++ b/src/mg_net.c @@ -619,10 +619,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); } #endif + mbuf_trim(&nc->recv_mbuf); mg_call(nc, NULL, nc->user_data, MG_EV_RECV, &n); } else if (n < 0) { nc->flags |= MG_F_CLOSE_IMMEDIATELY; } + mbuf_trim(&nc->recv_mbuf); return n; } From 1adea37c459e075ceb4843e704a9ab589752d2d6 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Thu, 20 Sep 2018 15:46:29 +0100 Subject: [PATCH 11/21] Integrate https://github.com/cesanta/mongoose/pull/667, fix documentation CL: Integrate https://github.com/cesanta/mongoose/pull/667, fix documentation PUBLISHED_FROM=80a939fc3276b89c29716e7373f674dba86769ee --- docs/overview/conn-flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/overview/conn-flags.md b/docs/overview/conn-flags.md index aeb642ab98..b2ed2a74fc 100644 --- a/docs/overview/conn-flags.md +++ b/docs/overview/conn-flags.md @@ -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 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 connection will be closed. * `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf` From 41e5d7e4711767b32be0529d474328f0bff6617c Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Thu, 20 Sep 2018 21:23:09 +0300 Subject: [PATCH 12/21] Use mbedTLS from mongoose-os-libs/mbedtls mbedTLS is just another lib now CL: Use mbedTLS from mongoose-os-libs/mbedtls PUBLISHED_FROM=bae4739d22e871bd268b8a3233dbb69634770243 --- src/common/platforms/esp8266/esp_crypto.c | 77 ----------------------- 1 file changed, 77 deletions(-) diff --git a/src/common/platforms/esp8266/esp_crypto.c b/src/common/platforms/esp8266/esp_crypto.c index 6469cae0f0..ab8e97e2a6 100644 --- a/src/common/platforms/esp8266/esp_crypto.c +++ b/src/common/platforms/esp8266/esp_crypto.c @@ -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) { (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 */ From b99a94a652ff6abf18310a308306e7a8578a7597 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Tue, 25 Sep 2018 14:07:32 +0300 Subject: [PATCH 13/21] Fix build w/o logging PUBLISHED_FROM=694346bd6562c55e5ab00886df47f7cbfb0a3720 --- mongoose.c | 2 ++ src/common/platforms/lwip/mg_lwip_net_if.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mongoose.c b/mongoose.c index 87703df36a..3f593e79f3 100644 --- a/mongoose.c +++ b/mongoose.c @@ -15182,6 +15182,7 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, } mg_lwip_recv_common(nc, p); mgos_unlock(); + (void) err; return ERR_OK; } @@ -15194,6 +15195,7 @@ 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) { mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); } + (void) num_sent; return ERR_OK; } diff --git a/src/common/platforms/lwip/mg_lwip_net_if.c b/src/common/platforms/lwip/mg_lwip_net_if.c index c6cbf492b3..c9bb809b39 100644 --- a/src/common/platforms/lwip/mg_lwip_net_if.c +++ b/src/common/platforms/lwip/mg_lwip_net_if.c @@ -187,6 +187,7 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, } mg_lwip_recv_common(nc, p); mgos_unlock(); + (void) err; return ERR_OK; } @@ -199,6 +200,7 @@ 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) { mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); } + (void) num_sent; return ERR_OK; } From 8ccee820597cbc0030a5656a1443a505da8adee5 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Tue, 25 Sep 2018 18:09:46 +0300 Subject: [PATCH 14/21] Add mgos_gpio_blink() CL: Add mgos_gpio_blink() PUBLISHED_FROM=a5d2e2f44413d1ab363abeeaf0fb497bd8f63d6d --- src/common/platforms/cc3200/ti.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/platforms/cc3200/ti.mk b/src/common/platforms/cc3200/ti.mk index b50407f8e4..cbfc2f1761 100644 --- a/src/common/platforms/cc3200/ti.mk +++ b/src/common/platforms/cc3200/ti.mk @@ -17,17 +17,17 @@ CXXFLAGS += $(TI_C_CXX_FLAGS) $(C_CXX_FLAGS) # cc flags,file define cc - $(vecho) "TICC $2 -> $@" + $(vecho) "TICC $2" $(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2 endef define cxx - $(vecho) "TICXX $2 -> $@" + $(vecho) "TICXX $2" $(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2 endef # asm flags,file define asm - $(vecho) "TIASM $2 -> $@" + $(vecho) "TIASM $2" $(Q) $(CC_WRAPPER) $(CC) -c $1 --output_file=$@ $2 endef From 492b8f6950279361f7db4de60ca6a59ce2d5a2ba Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Tue, 25 Sep 2018 23:02:09 +0300 Subject: [PATCH 15/21] CC3200: Fix boot loader regression Go back to Ubuntu 16.04 and older gcc-arm (4.9.3). Boot loader just won't run when compiled with newer GCC (7.x). It's likely that it can be fixed with compile switches but I couldn't figure it out quickly, so going to just downgrade for now to get it back to workign state. CL: CC3200: Fix boot loader regression PUBLISHED_FROM=b70b03bd17e03c7dae02328b32b855f3ca3ad6a9 --- src/common/platforms/cc3200/gcc.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/platforms/cc3200/gcc.mk b/src/common/platforms/cc3200/gcc.mk index ec98b75f1d..4f39e78965 100644 --- a/src/common/platforms/cc3200/gcc.mk +++ b/src/common/platforms/cc3200/gcc.mk @@ -29,11 +29,11 @@ $(SDK_OBJS): CFLAGS += -include common/platform.h # cc flags,file define cc - $(vecho) "GCC $2 -> $@" + $(vecho) "GCC $2" $(Q) $(CC_WRAPPER) $(CC) -c $1 -o $@ $2 endef define cxx - $(vecho) "G++ $2 -> $@" + $(vecho) "G++ $2" $(Q) $(CC_WRAPPER) $(CXX) -c $1 -o $@ $2 endef From 05c687e251ec5e5e83f7f028b6ca2a151a15cb15 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Thu, 27 Sep 2018 02:20:01 +0300 Subject: [PATCH 16/21] Fix handling of keepalive HTTP requests/responses Clean the HTTP connection state when ia request/response has been fully buffered and handler invoked. Fixes https://github.com/cesanta/mongoose/issues/971 CL: mg: Fix handling of keepalive HTTP requests/responses PUBLISHED_FROM=70c854aa306aacb9161f6ee48841f38dc0312e6b --- mongoose.c | 25 +++++++++++++++++++++++-- src/mg_http.c | 25 +++++++++++++++++++++++-- test/unit_test.c | 2 +- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/mongoose.c b/mongoose.c index 3f593e79f3..589ec7fa3e 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6616,6 +6616,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, } } else { /* We did receive all HTTP body. */ + int request_done = 1; int trigger_ev = nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY; char addr[32]; mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), @@ -6627,8 +6628,28 @@ void mg_http_handler(struct mg_connection *nc, int ev, mg_http_call_endpoint_handler(nc, trigger_ev, hm); mbuf_remove(io, hm->message.len); pd->rcvd -= hm->message.len; - if (io->len > 0) { - goto again; +#if MG_ENABLE_FILESYSTEM + /* 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; + } } } } diff --git a/src/mg_http.c b/src/mg_http.c index dcf4c22da5..af94b7311e 100644 --- a/src/mg_http.c +++ b/src/mg_http.c @@ -869,6 +869,7 @@ void mg_http_handler(struct mg_connection *nc, int ev, } } else { /* We did receive all HTTP body. */ + int request_done = 1; int trigger_ev = nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY; char addr[32]; mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), @@ -880,8 +881,28 @@ void mg_http_handler(struct mg_connection *nc, int ev, mg_http_call_endpoint_handler(nc, trigger_ev, hm); mbuf_remove(io, hm->message.len); pd->rcvd -= hm->message.len; - if (io->len > 0) { - goto again; +#if MG_ENABLE_FILESYSTEM + /* 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; + } } } } diff --git a/test/unit_test.c b/test/unit_test.c index 2cf5aa1ea7..cde8df8afc 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -2069,7 +2069,7 @@ static const char *test_http(void) { nc->user_data = mime2; /* 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); /* Check that test buffer has been filled by the callback properly. */ From 8b423530393a232b5a4ca5c4d1adbbfe19560816 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Thu, 27 Sep 2018 15:40:51 +0300 Subject: [PATCH 17/21] Check HTTP chunk size, ensure it's reasonable CL: mg: Check HTTP chunk size, ensure it's reasonable PUBLISHED_FROM=d9f6babd314c092b42ce9e7fe31d6b30a38366a2 --- mongoose.c | 4 ++++ src/mg_http.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/mongoose.c b/mongoose.c index 589ec7fa3e..34f0e65713 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6311,6 +6311,10 @@ static size_t mg_http_parse_chunk(char *buf, size_t len, char **chunk_data, n *= 16; n += (s[i] >= '0' && s[i] <= '9') ? s[i] - '0' : tolower(s[i]) - 'a' + 10; i++; + if (i > 6) { + /* Chunk size is unreasonable. */ + return 0; + } } /* Skip new line */ diff --git a/src/mg_http.c b/src/mg_http.c index af94b7311e..f8161a4b47 100644 --- a/src/mg_http.c +++ b/src/mg_http.c @@ -564,6 +564,10 @@ static size_t mg_http_parse_chunk(char *buf, size_t len, char **chunk_data, n *= 16; n += (s[i] >= '0' && s[i] <= '9') ? s[i] - '0' : tolower(s[i]) - 'a' + 10; i++; + if (i > 6) { + /* Chunk size is unreasonable. */ + return 0; + } } /* Skip new line */ From aaf1fc3a4ad19dad34a71756f40d9b995409576f Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Fri, 28 Sep 2018 13:47:58 +0300 Subject: [PATCH 18/21] Schedule a poll when LwIP reports TCP data sent PUBLISHED_FROM=0cf3029d9a9b851882325e2298b878bc83fc2d33 --- mongoose.c | 7 +++++++ src/common/platforms/lwip/mg_lwip_net_if.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/mongoose.c b/mongoose.c index 34f0e65713..ed2db8d677 100644 --- a/mongoose.c +++ b/mongoose.c @@ -15220,6 +15220,9 @@ 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) { 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; } @@ -15582,6 +15585,10 @@ static int mg_lwip_if_can_send(struct mg_connection *nc, can_send = (cs->pcb.udp != NULL); } else { 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; diff --git a/src/common/platforms/lwip/mg_lwip_net_if.c b/src/common/platforms/lwip/mg_lwip_net_if.c index c9bb809b39..d077702915 100644 --- a/src/common/platforms/lwip/mg_lwip_net_if.c +++ b/src/common/platforms/lwip/mg_lwip_net_if.c @@ -200,6 +200,9 @@ 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) { 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; } @@ -562,6 +565,10 @@ static int mg_lwip_if_can_send(struct mg_connection *nc, can_send = (cs->pcb.udp != NULL); } else { 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; From e79fe4b8f0d2f9acd3a6b664328d0852af46173b Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Tue, 2 Oct 2018 17:53:35 +0300 Subject: [PATCH 19/21] Update mbedTLS to 2.13.1 CL: Update mbedTLS to 2.13.1 PUBLISHED_FROM=bd1216f727605a901f062a044c0c0ca762f4a6d1 --- mongoose.c | 12 +++++------- src/mg_ssl_if_mbedtls.c | 12 +++++------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/mongoose.c b/mongoose.c index ed2db8d677..1949e628cc 100644 --- a/mongoose.c +++ b/mongoose.c @@ -5192,9 +5192,9 @@ static void mg_ssl_if_mbed_free_certs_and_keys(struct mg_ssl_if_ctx *ctx) { if (ctx->ca_cert != NULL) { mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL); #ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK - if (ctx->ca_cert->ca_chain_file != NULL) { - MG_FREE((void *) ctx->ca_cert->ca_chain_file); - ctx->ca_cert->ca_chain_file = NULL; + if (ctx->conf->ca_chain_file != NULL) { + MG_FREE((void *) ctx->conf->ca_chain_file); + ctx->conf->ca_chain_file = NULL; } #endif mbedtls_x509_crt_free(ctx->ca_cert); @@ -5301,15 +5301,13 @@ static enum mg_ssl_if_result mg_use_ca_cert(struct mg_ssl_if_ctx *ctx, mbedtls_x509_crt_init(ctx->ca_cert); #ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK ca_cert = strdup(ca_cert); - if (mbedtls_x509_crt_set_ca_chain_file(ctx->ca_cert, ca_cert) != 0) { - return MG_SSL_ERROR; - } + mbedtls_ssl_conf_ca_chain_file(ctx->conf, ca_cert, NULL); #else if (mbedtls_x509_crt_parse_file(ctx->ca_cert, ca_cert) != 0) { return MG_SSL_ERROR; } -#endif mbedtls_ssl_conf_ca_chain(ctx->conf, ctx->ca_cert, NULL); +#endif mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED); return MG_SSL_OK; } diff --git a/src/mg_ssl_if_mbedtls.c b/src/mg_ssl_if_mbedtls.c index 9656e5575c..7640778fff 100644 --- a/src/mg_ssl_if_mbedtls.c +++ b/src/mg_ssl_if_mbedtls.c @@ -223,9 +223,9 @@ static void mg_ssl_if_mbed_free_certs_and_keys(struct mg_ssl_if_ctx *ctx) { if (ctx->ca_cert != NULL) { mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL); #ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK - if (ctx->ca_cert->ca_chain_file != NULL) { - MG_FREE((void *) ctx->ca_cert->ca_chain_file); - ctx->ca_cert->ca_chain_file = NULL; + if (ctx->conf->ca_chain_file != NULL) { + MG_FREE((void *) ctx->conf->ca_chain_file); + ctx->conf->ca_chain_file = NULL; } #endif mbedtls_x509_crt_free(ctx->ca_cert); @@ -332,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); #ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK ca_cert = strdup(ca_cert); - if (mbedtls_x509_crt_set_ca_chain_file(ctx->ca_cert, ca_cert) != 0) { - return MG_SSL_ERROR; - } + mbedtls_ssl_conf_ca_chain_file(ctx->conf, ca_cert, NULL); #else if (mbedtls_x509_crt_parse_file(ctx->ca_cert, ca_cert) != 0) { return MG_SSL_ERROR; } -#endif mbedtls_ssl_conf_ca_chain(ctx->conf, ctx->ca_cert, NULL); +#endif mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED); return MG_SSL_OK; } From 1ffccdb7b296e1db329fe3b33df3364bfac87b18 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Thu, 4 Oct 2018 15:09:02 +0300 Subject: [PATCH 20/21] Remove a spammy log line PUBLISHED_FROM=b3ec2b3b43a464700a6e6d75b7336f823549cce3 --- mongoose.c | 1 - src/mg_net.c | 1 - 2 files changed, 2 deletions(-) diff --git a/mongoose.c b/mongoose.c index 1949e628cc..3174523a23 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2797,7 +2797,6 @@ MG_INTERNAL void mg_ssl_handshake(struct mg_connection *nc) { enum mg_ssl_if_result res; if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) return; res = mg_ssl_if_handshake(nc); - LOG(LL_DEBUG, ("%p %d res %d", nc, server_side, res)); if (res == MG_SSL_OK) { nc->flags |= MG_F_SSL_HANDSHAKE_DONE; diff --git a/src/mg_net.c b/src/mg_net.c index 1bf5716b9b..97afe9ab56 100644 --- a/src/mg_net.c +++ b/src/mg_net.c @@ -488,7 +488,6 @@ MG_INTERNAL void mg_ssl_handshake(struct mg_connection *nc) { enum mg_ssl_if_result res; if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) return; res = mg_ssl_if_handshake(nc); - LOG(LL_DEBUG, ("%p %d res %d", nc, server_side, res)); if (res == MG_SSL_OK) { nc->flags |= MG_F_SSL_HANDSHAKE_DONE; From bc56353a7965fc1a131222308737a3c653edc9d5 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov Date: Mon, 8 Oct 2018 12:54:15 +0100 Subject: [PATCH 21/21] Mongoose 6.13 CL: none PUBLISHED_FROM=32418b7da17a68193e88405547152f58a4dd877f --- mongoose.h | 2 +- src/mg_common.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mongoose.h b/mongoose.h index af543d689c..8fe13cd60d 100644 --- a/mongoose.h +++ b/mongoose.h @@ -23,7 +23,7 @@ #ifndef CS_MONGOOSE_SRC_COMMON_H_ #define CS_MONGOOSE_SRC_COMMON_H_ -#define MG_VERSION "6.12" +#define MG_VERSION "6.13" /* Local tweaks, applied before any of Mongoose's own headers. */ #ifdef MG_LOCALS diff --git a/src/mg_common.h b/src/mg_common.h index adb99e8f1e..69900255aa 100644 --- a/src/mg_common.h +++ b/src/mg_common.h @@ -20,7 +20,7 @@ #ifndef CS_MONGOOSE_SRC_COMMON_H_ #define CS_MONGOOSE_SRC_COMMON_H_ -#define MG_VERSION "6.12" +#define MG_VERSION "6.13" /* Local tweaks, applied before any of Mongoose's own headers. */ #ifdef MG_LOCALS