From 4bc755045e79e6221d3f2e3dba84ac6e6725f254 Mon Sep 17 00:00:00 2001 From: cpq Date: Thu, 21 May 2026 00:04:03 +0100 Subject: [PATCH] Remove MG_IO_RESET --- mongoose.c | 79 ++++++++++++++++++++++++------------------------ mongoose.h | 2 +- src/sock.c | 73 ++++++++++++++++++++++---------------------- src/tls.h | 2 +- src/tls_mbed.c | 6 ++-- test/unit_test.c | 4 +-- 6 files changed, 82 insertions(+), 84 deletions(-) diff --git a/mongoose.c b/mongoose.c index 31ea1ff9..8ea6da72 100644 --- a/mongoose.c +++ b/mongoose.c @@ -12276,8 +12276,10 @@ static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { } // Get the local 'addr' the stack will use to connect to 'to' -void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr); -void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr) { +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, + struct mg_addr *addr); +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, + struct mg_addr *addr) { union usa usa; socklen_t slen; MG_SOCKET_TYPE fd; @@ -12297,7 +12299,6 @@ void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr * closesocket(fd); } - static void iolog(struct mg_connection *c, char *buf, long n, bool r) { if (n == MG_IO_WAIT) { // Do nothing @@ -12335,7 +12336,7 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { } MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n))); if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; - if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507 + if (MG_SOCK_RESET(n)) return MG_IO_ERR; // See #1507, #3031 if (n <= 0) return MG_IO_ERR; return n; } @@ -12485,7 +12486,7 @@ static long recv_raw(struct mg_connection *c, void *buf, size_t len) { } MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n))); if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; - if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507 + if (MG_SOCK_RESET(n)) return MG_IO_ERR; // See #1507, #3031 if (n <= 0) return MG_IO_ERR; return n; } @@ -12506,42 +12507,40 @@ static bool ioalloc(struct mg_connection *c, struct mg_iobuf *io) { // NOTE(lsm): do only one iteration of reads, cause some systems // (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data static void read_conn(struct mg_connection *c) { - if (ioalloc(c, &c->recv)) { - char *buf = (char *) &c->recv.buf[c->recv.len]; - size_t len = c->recv.size - c->recv.len; - long n = -1; - if (c->is_tls) { - // Do not read to the raw TLS buffer if it already has enough. - // This is to prevent overflowing c->rtls if our reads are slow - long m; - if (c->rtls.len < 16 * 1024 + 40) { // TLS record, header, MAC, padding - if (!ioalloc(c, &c->rtls)) return; - n = recv_raw(c, (char *) &c->rtls.buf[c->rtls.len], - c->rtls.size - c->rtls.len); - if (n > 0) c->rtls.len += (size_t) n; - } - // there can still be > 16K from last iteration, always mg_tls_recv() - m = c->is_tls_hs ? (long) MG_IO_WAIT : mg_tls_recv(c, buf, len); - if (n == MG_IO_ERR || n == MG_IO_RESET) { // Windows, see #3031 - if (c->rtls.len == 0 || (m < 0 && m != MG_IO_WAIT)) { - // Close only when we have fully drained both rtls and TLS buffers - c->is_closing = 1; // or there's nothing we can do about it. - if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104 - } else { // see #2885 - // TLS buffer is capped to max record size, even though, there can - // be more than one record, give TLS a chance to process them. - } - } else if (c->is_tls_hs) { + long n = MG_IO_WAIT; + if (ioalloc(c, &c->recv) == false) return; // Oopsie poopsie, OOM + if (c->is_tls) { + size_t rtls = c->rtls.len, pending = mg_tls_pending(c); + long m = MG_IO_WAIT; + if (c->rtls.len < 16 * 1024 + 40) { // TLS record, header, MAC, padding + if (!ioalloc(c, &c->rtls)) return; + n = recv_raw(c, (char *) &c->rtls.buf[c->rtls.len], + c->rtls.size - c->rtls.len); + if (n > 0) c->rtls.len += (size_t) n; + } + // There can still be > 16K from last iteration, always mg_tls_recv() + if (c->is_tls_hs) { + if (n != MG_IO_ERR || c->rtls.len > 0 || pending > 0) { mg_tls_handshake(c); } - n = m; } else { - n = recv_raw(c, buf, len); + m = mg_tls_recv(c, &c->recv.buf[c->recv.len], c->recv.size - c->recv.len); } - MG_DEBUG(("%lu %ld %lu:%lu:%lu %ld err %d", c->id, c->fd, c->send.len, - c->recv.len, c->rtls.len, n, MG_SOCK_ERR(n))); - iolog(c, buf, n, true); + if (n == MG_IO_ERR && + (m == MG_IO_ERR || (c->rtls.len == 0 && mg_tls_pending(c) == 0) || + (c->is_tls_hs && c->rtls.len == rtls && + mg_tls_pending(c) == pending))) { + // Close only when we have fully drained both rtls and TLS buffers + c->is_closing = 1; // or there's nothing we can do about it. + if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104 + } + n = m; + } else { + n = recv_raw(c, &c->recv.buf[c->recv.len], c->recv.size - c->recv.len); } + MG_DEBUG(("%lu %ld %lu:%lu:%lu %ld err %d", c->id, c->fd, c->send.len, + c->recv.len, c->rtls.len, n, MG_SOCK_ERR(n))); + iolog(c, (char *) &c->recv.buf[c->recv.len], n, true); } static void write_conn(struct mg_connection *c) { @@ -12682,7 +12681,7 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { setsockopts(c); c->is_accepted = 1; c->is_hexdumping = lsn->is_hexdumping; - setlocaddr(fd, &c->loc); // set local addr to where the client connected to + setlocaddr(fd, &c->loc); // set local addr to where the client connected to c->pfn = lsn->pfn; c->pfn_data = lsn->pfn_data; c->fn = lsn->fn; @@ -18595,7 +18594,7 @@ static int mg_net_send(void *ctx, const unsigned char *buf, size_t len) { long n = mg_io_send((struct mg_connection *) ctx, buf, len); MG_VERBOSE(("%lu n=%ld e=%d", ((struct mg_connection *) ctx)->id, n, errno)); if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE; - if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; + // if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_SEND_FAILED; return (int) n; } @@ -18603,8 +18602,8 @@ static int mg_net_send(void *ctx, const unsigned char *buf, size_t len) { static int mg_net_recv(void *ctx, unsigned char *buf, size_t len) { long n = mg_io_recv((struct mg_connection *) ctx, buf, len); MG_VERBOSE(("%lu n=%ld", ((struct mg_connection *) ctx)->id, n)); - if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE; - if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; + if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_READ; + // if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_RECV_FAILED; return (int) n; } diff --git a/mongoose.h b/mongoose.h index 1684c72a..ce418ad0 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1904,7 +1904,7 @@ void mg_tls_ctx_free(struct mg_mgr *); #define MG_IS_DER(buf) (((uint8_t *) (buf))[0] == 0x30) // DER begins with 0x30 // Low-level IO primives used by TLS layer -enum { MG_IO_ERR = -1, MG_IO_WAIT = -2, MG_IO_RESET = -3 }; +enum { MG_IO_ERR = -1, MG_IO_WAIT = -2 }; long mg_io_send(struct mg_connection *c, const void *buf, size_t len); long mg_io_recv(struct mg_connection *c, void *buf, size_t len); #ifndef TLS_X15519_H diff --git a/src/sock.c b/src/sock.c index 228226cd..e85e08dd 100644 --- a/src/sock.c +++ b/src/sock.c @@ -94,8 +94,10 @@ static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { } // Get the local 'addr' the stack will use to connect to 'to' -void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr); -void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr) { +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, + struct mg_addr *addr); +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, + struct mg_addr *addr) { union usa usa; socklen_t slen; MG_SOCKET_TYPE fd; @@ -115,7 +117,6 @@ void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr * closesocket(fd); } - static void iolog(struct mg_connection *c, char *buf, long n, bool r) { if (n == MG_IO_WAIT) { // Do nothing @@ -153,7 +154,7 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { } MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n))); if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; - if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507 + if (MG_SOCK_RESET(n)) return MG_IO_ERR; // See #1507, #3031 if (n <= 0) return MG_IO_ERR; return n; } @@ -303,7 +304,7 @@ static long recv_raw(struct mg_connection *c, void *buf, size_t len) { } MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n))); if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; - if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507 + if (MG_SOCK_RESET(n)) return MG_IO_ERR; // See #1507, #3031 if (n <= 0) return MG_IO_ERR; return n; } @@ -324,42 +325,40 @@ static bool ioalloc(struct mg_connection *c, struct mg_iobuf *io) { // NOTE(lsm): do only one iteration of reads, cause some systems // (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data static void read_conn(struct mg_connection *c) { - if (ioalloc(c, &c->recv)) { - char *buf = (char *) &c->recv.buf[c->recv.len]; - size_t len = c->recv.size - c->recv.len; - long n = -1; - if (c->is_tls) { - // Do not read to the raw TLS buffer if it already has enough. - // This is to prevent overflowing c->rtls if our reads are slow - long m; - if (c->rtls.len < 16 * 1024 + 40) { // TLS record, header, MAC, padding - if (!ioalloc(c, &c->rtls)) return; - n = recv_raw(c, (char *) &c->rtls.buf[c->rtls.len], - c->rtls.size - c->rtls.len); - if (n > 0) c->rtls.len += (size_t) n; - } - // there can still be > 16K from last iteration, always mg_tls_recv() - m = c->is_tls_hs ? (long) MG_IO_WAIT : mg_tls_recv(c, buf, len); - if (n == MG_IO_ERR || n == MG_IO_RESET) { // Windows, see #3031 - if (c->rtls.len == 0 || (m < 0 && m != MG_IO_WAIT)) { - // Close only when we have fully drained both rtls and TLS buffers - c->is_closing = 1; // or there's nothing we can do about it. - if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104 - } else { // see #2885 - // TLS buffer is capped to max record size, even though, there can - // be more than one record, give TLS a chance to process them. - } - } else if (c->is_tls_hs) { + long n = MG_IO_WAIT; + if (ioalloc(c, &c->recv) == false) return; // Oopsie poopsie, OOM + if (c->is_tls) { + size_t rtls = c->rtls.len, pending = mg_tls_pending(c); + long m = MG_IO_WAIT; + if (c->rtls.len < 16 * 1024 + 40) { // TLS record, header, MAC, padding + if (!ioalloc(c, &c->rtls)) return; + n = recv_raw(c, (char *) &c->rtls.buf[c->rtls.len], + c->rtls.size - c->rtls.len); + if (n > 0) c->rtls.len += (size_t) n; + } + // There can still be > 16K from last iteration, always mg_tls_recv() + if (c->is_tls_hs) { + if (n != MG_IO_ERR || c->rtls.len > 0 || pending > 0) { mg_tls_handshake(c); } - n = m; } else { - n = recv_raw(c, buf, len); + m = mg_tls_recv(c, &c->recv.buf[c->recv.len], c->recv.size - c->recv.len); } - MG_DEBUG(("%lu %ld %lu:%lu:%lu %ld err %d", c->id, c->fd, c->send.len, - c->recv.len, c->rtls.len, n, MG_SOCK_ERR(n))); - iolog(c, buf, n, true); + if (n == MG_IO_ERR && + (m == MG_IO_ERR || (c->rtls.len == 0 && mg_tls_pending(c) == 0) || + (c->is_tls_hs && c->rtls.len == rtls && + mg_tls_pending(c) == pending))) { + // Close only when we have fully drained both rtls and TLS buffers + c->is_closing = 1; // or there's nothing we can do about it. + if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104 + } + n = m; + } else { + n = recv_raw(c, &c->recv.buf[c->recv.len], c->recv.size - c->recv.len); } + MG_DEBUG(("%lu %ld %lu:%lu:%lu %ld err %d", c->id, c->fd, c->send.len, + c->recv.len, c->rtls.len, n, MG_SOCK_ERR(n))); + iolog(c, (char *) &c->recv.buf[c->recv.len], n, true); } static void write_conn(struct mg_connection *c) { @@ -500,7 +499,7 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { setsockopts(c); c->is_accepted = 1; c->is_hexdumping = lsn->is_hexdumping; - setlocaddr(fd, &c->loc); // set local addr to where the client connected to + setlocaddr(fd, &c->loc); // set local addr to where the client connected to c->pfn = lsn->pfn; c->pfn_data = lsn->pfn_data; c->fn = lsn->fn; diff --git a/src/tls.h b/src/tls.h index 124605ae..e5917eab 100644 --- a/src/tls.h +++ b/src/tls.h @@ -37,6 +37,6 @@ void mg_tls_ctx_free(struct mg_mgr *); #define MG_IS_DER(buf) (((uint8_t *) (buf))[0] == 0x30) // DER begins with 0x30 // Low-level IO primives used by TLS layer -enum { MG_IO_ERR = -1, MG_IO_WAIT = -2, MG_IO_RESET = -3 }; +enum { MG_IO_ERR = -1, MG_IO_WAIT = -2 }; long mg_io_send(struct mg_connection *c, const void *buf, size_t len); long mg_io_recv(struct mg_connection *c, void *buf, size_t len); diff --git a/src/tls_mbed.c b/src/tls_mbed.c index b7a49281..1bee87a0 100644 --- a/src/tls_mbed.c +++ b/src/tls_mbed.c @@ -75,7 +75,7 @@ static int mg_net_send(void *ctx, const unsigned char *buf, size_t len) { long n = mg_io_send((struct mg_connection *) ctx, buf, len); MG_VERBOSE(("%lu n=%ld e=%d", ((struct mg_connection *) ctx)->id, n, errno)); if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE; - if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; + // if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_SEND_FAILED; return (int) n; } @@ -83,8 +83,8 @@ static int mg_net_send(void *ctx, const unsigned char *buf, size_t len) { static int mg_net_recv(void *ctx, unsigned char *buf, size_t len) { long n = mg_io_recv((struct mg_connection *) ctx, buf, len); MG_VERBOSE(("%lu n=%ld", ((struct mg_connection *) ctx)->id, n)); - if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE; - if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; + if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_READ; + // if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET; if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_RECV_FAILED; return (int) n; } diff --git a/test/unit_test.c b/test/unit_test.c index 644e7771..96f84841 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -622,7 +622,7 @@ static void test_mqtt_basic(void) { // Connect with empty client ID, no options, ergo MQTT = 3.1.1 mg_mgr_init(&mgr); c = mg_mqtt_connect(&mgr, url, NULL, mqtt_cb, &test_data); - for (i = 0; i < 300 && mbuf[0] == 0; i++) mg_mgr_poll(&mgr, 10); + for (i = 0; i < 1000 && mbuf[0] == 0; i++) mg_mgr_poll(&mgr, 10); if (mbuf[0] != 'X') MG_INFO(("[%s]", mbuf)); ASSERT(mbuf[0] == 'X'); ASSERT(test_data.flags == 0); @@ -711,7 +711,7 @@ static void test_mqtt_ver(uint8_t mqtt_version) { opts.message = mg_str("mg_will_messsage"); opts.client_id = genstring(client_id, sizeof(client_id)); c = mg_mqtt_connect(&mgr, url, &opts, mqtt_cb, &test_data); - for (i = 0; i < 500 && mbuf[0] == 0; i++) mg_mgr_poll(&mgr, 10); + for (i = 0; i < 1000 && mbuf[0] == 0; i++) mg_mgr_poll(&mgr, 10); if (mbuf[0] != 'X') MG_INFO(("[%s]", mbuf)); ASSERT(mbuf[0] == 'X'); ASSERT(test_data.flags == 0);