diff --git a/mongoose.c b/mongoose.c index bdd25c3c..2e7696c1 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6225,9 +6225,9 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) { len = trim_len(c, len); // Trimming length if necessary res = udp_send(c, buf, len); } else { - res = (bool) mg_iobuf_add(&c->send, c->send.len, buf, len); - // res == 0 means an OOM condition (iobuf couldn't resize), yet this is so - // far recoverable, let the caller decide + res = len == 0 || mg_iobuf_add(&c->send, c->send.len, buf, len) > 0; + // returning 0 means an OOM condition (iobuf couldn't resize), yet this is + // so far recoverable, let the caller decide } return res; } @@ -9582,7 +9582,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) { iolog(c, (char *) buf, n, false); return n > 0; } else { - return (bool) mg_iobuf_add(&c->send, c->send.len, buf, len); + return len == 0 || mg_iobuf_add(&c->send, c->send.len, buf, len) > 0; // returning 0 means an OOM condition (iobuf couldn't resize), yet this is // so far recoverable, let the caller decide } diff --git a/src/net_builtin.c b/src/net_builtin.c index bbe8873c..a262b846 100644 --- a/src/net_builtin.c +++ b/src/net_builtin.c @@ -2019,9 +2019,9 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) { len = trim_len(c, len); // Trimming length if necessary res = udp_send(c, buf, len); } else { - res = (bool) mg_iobuf_add(&c->send, c->send.len, buf, len); - // res == 0 means an OOM condition (iobuf couldn't resize), yet this is so - // far recoverable, let the caller decide + res = len == 0 || mg_iobuf_add(&c->send, c->send.len, buf, len) > 0; + // returning 0 means an OOM condition (iobuf couldn't resize), yet this is + // so far recoverable, let the caller decide } return res; } diff --git a/src/sock.c b/src/sock.c index 0c664548..26d8fd8c 100644 --- a/src/sock.c +++ b/src/sock.c @@ -141,7 +141,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) { iolog(c, (char *) buf, n, false); return n > 0; } else { - return (bool) mg_iobuf_add(&c->send, c->send.len, buf, len); + return len == 0 || mg_iobuf_add(&c->send, c->send.len, buf, len) > 0; // returning 0 means an OOM condition (iobuf couldn't resize), yet this is // so far recoverable, let the caller decide } diff --git a/test/mip_tap_test.c b/test/mip_tap_test.c index a3211b16..61647b5f 100644 --- a/test/mip_tap_test.c +++ b/test/mip_tap_test.c @@ -413,6 +413,7 @@ static void test_http_server(struct mg_mgr *mgr) { mg_mprintf("./mip_curl.sh http://%M:12347", mg_print_ip4, &mgr->ifp->ip); #endif ASSERT(c != NULL); + ASSERT (mg_send(c, "NADA", 0)); // check mg_send allows len=0 pthread_create(&thread_id, NULL, poll_thread, mgr); // simpler this way, no concurrency anyway MG_DEBUG(("CURL")); diff --git a/test/unit_test.c b/test/unit_test.c index 54e3ef91..52632595 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -2977,6 +2977,14 @@ static void eZ(struct mg_connection *c, int ev, void *ev_data) { (void) ev_data; } +static void eS(struct mg_connection *c, int ev, void *ev_data) { + if (ev == MG_EV_HTTP_MSG) { + ASSERT (mg_send(c, "NADA", 0)); + mg_http_reply(c, 200, "", "abcd"); + } + (void) ev_data; +} + // Do not delete chunks as they arrive static void eh4(struct mg_connection *c, int ev, void *ev_data) { uint32_t *crc = (uint32_t *) c->fn_data; @@ -3012,6 +3020,9 @@ static void test_http_chunked_case(mg_event_handler_t s, mg_event_handler_t c, } static void test_http_chunked(void) { + // test mg_send allows calls with 0 length + test_http_chunked_case(eS, eh4, 1, "abcd"); + // Non-chunked encoding test_http_chunked_case(eY, eh4, 1, "abcd"); // Chunks not deleted test_http_chunked_case(eY, eh4, 2, "abcdabcd");