From 0aa12c1e993f420bff74c275943a1eb36e32257c Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Tue, 12 Mar 2024 08:16:20 +0000 Subject: [PATCH] Fix #2619 - use mg_tls_pending() API to check for buffered TLS data --- mongoose.c | 23 +++++++++++------------ src/sock.c | 23 +++++++++++------------ test/unit_test.c | 8 ++++++++ 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/mongoose.c b/mongoose.c index 74f1a7252e5..bb2b532ce56 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7237,8 +7237,8 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { bool mg_send(struct mg_connection *c, const void *buf, size_t len) { if (c->is_udp) { long n = mg_io_send(c, buf, len); - MG_DEBUG(("%lu %ld %d:%d %ld err %d", c->id, c->fd, (int) c->send.len, - (int) c->recv.len, n, MG_SOCK_ERR(n))); + 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 *) buf, n, false); return n > 0; } else { @@ -7392,9 +7392,8 @@ static void read_conn(struct mg_connection *c) { } else { n = recv_raw(c, buf, len); } - MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd, - (long) c->send.len, (long) c->send.size, (long) c->recv.len, - (long) c->recv.size, n, MG_SOCK_ERR(n))); + 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); } } @@ -7582,7 +7581,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { size_t max = 1; for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { c->is_readable = c->is_writable = 0; - if (c->rtls.len > 0) ms = 1, c->is_readable = 1; + if (mg_tls_pending(c) > 0) ms = 1, c->is_readable = 1; if (can_write(c)) MG_EPOLL_MOD(c, 1); if (c->is_closing) ms = 1; max++; @@ -7598,7 +7597,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { bool wr = evs[i].events & EPOLLOUT; c->is_readable = can_read(c) && rd ? 1U : 0; c->is_writable = can_write(c) && wr ? 1U : 0; - if (c->rtls.len > 0) c->is_readable = 1; + if (mg_tls_pending(c) > 0) c->is_readable = 1; } } (void) skip_iotest; @@ -7612,7 +7611,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { c->is_readable = c->is_writable = 0; if (skip_iotest(c)) { // Socket not valid, ignore - } else if (c->rtls.len > 0) { + } else if (mg_tls_pending(c) > 0) { ms = 1; // Don't wait if TLS is ready } else { fds[n].fd = FD(c); @@ -7634,7 +7633,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { if (skip_iotest(c)) { // Socket not valid, ignore - } else if (c->rtls.len > 0) { + } else if (mg_tls_pending(c) > 0) { c->is_readable = 1; } else { if (fds[n].revents & POLLERR) { @@ -7643,7 +7642,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { c->is_readable = (unsigned) (fds[n].revents & (POLLIN | POLLHUP) ? 1 : 0); c->is_writable = (unsigned) (fds[n].revents & POLLOUT ? 1 : 0); - if (c->rtls.len > 0) c->is_readable = 1; + if (mg_tls_pending(c) > 0) c->is_readable = 1; } n++; } @@ -7665,7 +7664,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { FD_SET(FD(c), &eset); if (can_read(c)) FD_SET(FD(c), &rset); if (can_write(c)) FD_SET(FD(c), &wset); - if (c->rtls.len > 0) tvp = &tv_zero; + if (mg_tls_pending(c) > 0) tvp = &tv_zero; if (FD(c) > maxfd) maxfd = FD(c); if (c->is_closing) ms = 1; } @@ -7687,7 +7686,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { } else { c->is_readable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &rset); c->is_writable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &wset); - if (c->rtls.len > 0) c->is_readable = 1; + if (mg_tls_pending(c) > 0) c->is_readable = 1; } } #endif diff --git a/src/sock.c b/src/sock.c index 3aa80f9fe84..d993dae46f5 100644 --- a/src/sock.c +++ b/src/sock.c @@ -136,8 +136,8 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { bool mg_send(struct mg_connection *c, const void *buf, size_t len) { if (c->is_udp) { long n = mg_io_send(c, buf, len); - MG_DEBUG(("%lu %ld %d:%d %ld err %d", c->id, c->fd, (int) c->send.len, - (int) c->recv.len, n, MG_SOCK_ERR(n))); + 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 *) buf, n, false); return n > 0; } else { @@ -291,9 +291,8 @@ static void read_conn(struct mg_connection *c) { } else { n = recv_raw(c, buf, len); } - MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd, - (long) c->send.len, (long) c->send.size, (long) c->recv.len, - (long) c->recv.size, n, MG_SOCK_ERR(n))); + 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); } } @@ -481,7 +480,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { size_t max = 1; for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { c->is_readable = c->is_writable = 0; - if (c->rtls.len > 0) ms = 1, c->is_readable = 1; + if (mg_tls_pending(c) > 0) ms = 1, c->is_readable = 1; if (can_write(c)) MG_EPOLL_MOD(c, 1); if (c->is_closing) ms = 1; max++; @@ -497,7 +496,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { bool wr = evs[i].events & EPOLLOUT; c->is_readable = can_read(c) && rd ? 1U : 0; c->is_writable = can_write(c) && wr ? 1U : 0; - if (c->rtls.len > 0) c->is_readable = 1; + if (mg_tls_pending(c) > 0) c->is_readable = 1; } } (void) skip_iotest; @@ -511,7 +510,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { c->is_readable = c->is_writable = 0; if (skip_iotest(c)) { // Socket not valid, ignore - } else if (c->rtls.len > 0) { + } else if (mg_tls_pending(c) > 0) { ms = 1; // Don't wait if TLS is ready } else { fds[n].fd = FD(c); @@ -533,7 +532,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) { if (skip_iotest(c)) { // Socket not valid, ignore - } else if (c->rtls.len > 0) { + } else if (mg_tls_pending(c) > 0) { c->is_readable = 1; } else { if (fds[n].revents & POLLERR) { @@ -542,7 +541,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { c->is_readable = (unsigned) (fds[n].revents & (POLLIN | POLLHUP) ? 1 : 0); c->is_writable = (unsigned) (fds[n].revents & POLLOUT ? 1 : 0); - if (c->rtls.len > 0) c->is_readable = 1; + if (mg_tls_pending(c) > 0) c->is_readable = 1; } n++; } @@ -564,7 +563,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { FD_SET(FD(c), &eset); if (can_read(c)) FD_SET(FD(c), &rset); if (can_write(c)) FD_SET(FD(c), &wset); - if (c->rtls.len > 0) tvp = &tv_zero; + if (mg_tls_pending(c) > 0) tvp = &tv_zero; if (FD(c) > maxfd) maxfd = FD(c); if (c->is_closing) ms = 1; } @@ -586,7 +585,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { } else { c->is_readable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &rset); c->is_writable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &wset); - if (c->rtls.len > 0) c->is_readable = 1; + if (mg_tls_pending(c) > 0) c->is_readable = 1; } } #endif diff --git a/test/unit_test.c b/test/unit_test.c index 5186df104f1..03de2a87c58 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1210,6 +1210,7 @@ static void test_tls(void) { const char *url = "https://127.0.0.1:12347"; char buf[FETCH_BUF_SIZE]; struct mg_tls_opts opts; + struct mg_str data = mg_unpacked("/Makefile"); memset(&opts, 0, sizeof(opts)); // opts.ca = mg_str(s_tls_ca); opts.cert = mg_str(s_tls_cert); @@ -1220,6 +1221,13 @@ static void test_tls(void) { ASSERT(fetch(&mgr, buf, url, "GET /a.txt HTTP/1.0\n\n") == 200); // MG_INFO(("%s", buf)); ASSERT(cmpbody(buf, "hello\n") == 0); + // POST a larger file, make sure we drain TLS buffers and read all, #2619 + ASSERT(data.ptr != NULL && data.len > 0); + ASSERT(fetch(&mgr, buf, url, + "POST /foo/bar HTTP/1.0\n" + "Content-Length: %lu\n\n" + "%s", + data.len, data.ptr) == 200); mg_mgr_free(&mgr); ASSERT(mgr.conns == NULL); #endif