mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-11 16:40:17 +00:00
Fix #1545 - do not send MG_EV_HTTP_MSG if chunks were deleted
This commit is contained in:
1 parent
a4a70270ee
commit
44cf02e5ba
3 files changed
+91
-14
No files matched your search
+9
-3
@@ -1768,7 +1768,7 @@ static size_t get_chunk_length(const char *buf, size_t len, size_t *ll) {
|
|||||||
|
|
||||||
// Walk through all chunks in the chunked body. For each chunk, fire
|
// Walk through all chunks in the chunked body. For each chunk, fire
|
||||||
// an MG_EV_HTTP_CHUNK event.
|
// an MG_EV_HTTP_CHUNK event.
|
||||||
static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
static bool walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
||||||
size_t reqlen) {
|
size_t reqlen) {
|
||||||
size_t off = 0, bl, ll;
|
size_t off = 0, bl, ll;
|
||||||
while (off + reqlen < c->recv.len) {
|
while (off + reqlen < c->recv.len) {
|
||||||
@@ -1783,6 +1783,7 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
if (memo == c->recv.len) off += cl;
|
if (memo == c->recv.len) off += cl;
|
||||||
if (cl <= 5) {
|
if (cl <= 5) {
|
||||||
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
||||||
|
if (memo != c->recv.len) return true; // Tell caller to cleanup
|
||||||
off = bl = 0;
|
off = bl = 0;
|
||||||
while (off + reqlen < c->recv.len) {
|
while (off + reqlen < c->recv.len) {
|
||||||
char *buf2 = (char *) &c->recv.buf[reqlen];
|
char *buf2 = (char *) &c->recv.buf[reqlen];
|
||||||
@@ -1800,9 +1801,11 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
// everything, to fire MG_EV_HTTP_MSG
|
// everything, to fire MG_EV_HTTP_MSG
|
||||||
hm->message.len = bl + reqlen;
|
hm->message.len = bl + reqlen;
|
||||||
hm->body.len = bl;
|
hm->body.len = bl;
|
||||||
|
// If user was deleting chunks, send nothing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_is_chunked(struct mg_http_message *hm) {
|
static bool mg_is_chunked(struct mg_http_message *hm) {
|
||||||
@@ -1866,8 +1869,11 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
|||||||
if (ev == MG_EV_CLOSE) {
|
if (ev == MG_EV_CLOSE) {
|
||||||
hm.message.len = c->recv.len;
|
hm.message.len = c->recv.len;
|
||||||
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
|
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
|
||||||
} else if (is_chunked && n > 0) {
|
} else if (is_chunked && n > 0 && walkchunks(c, &hm, (size_t) n)) {
|
||||||
walkchunks(c, &hm, (size_t) n);
|
// walkchunks told us to cleanup the request
|
||||||
|
if (n > (int) c->recv.len) n = (int) c->recv.len;
|
||||||
|
mg_iobuf_del(&c->recv, 0, (size_t) n);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// MG_INFO(("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len,
|
// MG_INFO(("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len,
|
||||||
// c->recv.buf));
|
// c->recv.buf));
|
||||||
|
|||||||
+9
-3
@@ -774,7 +774,7 @@ static size_t get_chunk_length(const char *buf, size_t len, size_t *ll) {
|
|||||||
|
|
||||||
// Walk through all chunks in the chunked body. For each chunk, fire
|
// Walk through all chunks in the chunked body. For each chunk, fire
|
||||||
// an MG_EV_HTTP_CHUNK event.
|
// an MG_EV_HTTP_CHUNK event.
|
||||||
static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
static bool walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
||||||
size_t reqlen) {
|
size_t reqlen) {
|
||||||
size_t off = 0, bl, ll;
|
size_t off = 0, bl, ll;
|
||||||
while (off + reqlen < c->recv.len) {
|
while (off + reqlen < c->recv.len) {
|
||||||
@@ -789,6 +789,7 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
if (memo == c->recv.len) off += cl;
|
if (memo == c->recv.len) off += cl;
|
||||||
if (cl <= 5) {
|
if (cl <= 5) {
|
||||||
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
||||||
|
if (memo != c->recv.len) return true; // Tell caller to cleanup
|
||||||
off = bl = 0;
|
off = bl = 0;
|
||||||
while (off + reqlen < c->recv.len) {
|
while (off + reqlen < c->recv.len) {
|
||||||
char *buf2 = (char *) &c->recv.buf[reqlen];
|
char *buf2 = (char *) &c->recv.buf[reqlen];
|
||||||
@@ -806,9 +807,11 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
// everything, to fire MG_EV_HTTP_MSG
|
// everything, to fire MG_EV_HTTP_MSG
|
||||||
hm->message.len = bl + reqlen;
|
hm->message.len = bl + reqlen;
|
||||||
hm->body.len = bl;
|
hm->body.len = bl;
|
||||||
|
// If user was deleting chunks, send nothing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_is_chunked(struct mg_http_message *hm) {
|
static bool mg_is_chunked(struct mg_http_message *hm) {
|
||||||
@@ -872,8 +875,11 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
|
|||||||
if (ev == MG_EV_CLOSE) {
|
if (ev == MG_EV_CLOSE) {
|
||||||
hm.message.len = c->recv.len;
|
hm.message.len = c->recv.len;
|
||||||
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
|
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
|
||||||
} else if (is_chunked && n > 0) {
|
} else if (is_chunked && n > 0 && walkchunks(c, &hm, (size_t) n)) {
|
||||||
walkchunks(c, &hm, (size_t) n);
|
// walkchunks told us to cleanup the request
|
||||||
|
if (n > (int) c->recv.len) n = (int) c->recv.len;
|
||||||
|
mg_iobuf_del(&c->recv, 0, (size_t) n);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// MG_INFO(("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len,
|
// MG_INFO(("---->%d %d\n%.*s", n, is_chunked, (int) c->recv.len,
|
||||||
// c->recv.buf));
|
// c->recv.buf));
|
||||||
|
|||||||
+73
-8
@@ -1550,6 +1550,74 @@ static void test_crc32(void) {
|
|||||||
ASSERT(mg_crc32(mg_crc32(0, "ab", 2), "c", 1) == 891568578);
|
ASSERT(mg_crc32(mg_crc32(0, "ab", 2), "c", 1) == 891568578);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void us(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
int delete = *(int *) fn_data;
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
if (ev == MG_EV_HTTP_CHUNK && mg_http_match_uri(hm, "/upload")) {
|
||||||
|
MG_DEBUG(("Got chunk len %lu", (unsigned long) hm->chunk.len));
|
||||||
|
MG_DEBUG(("Query string: [%.*s]", (int) hm->query.len, hm->query.ptr));
|
||||||
|
// MG_DEBUG(("Chunk data:\n%.*s", (int) hm->chunk.len, hm->chunk.ptr));
|
||||||
|
if (delete) {
|
||||||
|
mg_http_delete_chunk(c, hm);
|
||||||
|
if (hm->chunk.len == 0) {
|
||||||
|
MG_DEBUG(("Last chunk received, sending response"));
|
||||||
|
mg_http_reply(c, 200, "", "ok (chunked)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG && mg_http_match_uri(hm, "/upload")) {
|
||||||
|
MG_DEBUG(("Got all %lu bytes!", (unsigned long) hm->body.len));
|
||||||
|
MG_DEBUG(("Query string: [%.*s]", (int) hm->query.len, hm->query.ptr));
|
||||||
|
// MG_DEBUG(("Body:\n%.*s", (int) hm->body.len, hm->body.ptr));
|
||||||
|
mg_http_reply(c, 200, "", "ok (%d %.*s)\n", (int) hm->body.len,
|
||||||
|
(int) hm->body.len, hm->body.ptr);
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
mg_http_reply(c, 200, "", "ok\n");
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uc(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
const char **s = (const char **) fn_data;
|
||||||
|
if (ev == MG_EV_OPEN) {
|
||||||
|
c->is_hexdumping = 1;
|
||||||
|
} else if (ev == MG_EV_CONNECT) {
|
||||||
|
mg_printf(c,
|
||||||
|
"POST /upload HTTP/1.0\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n\r\n");
|
||||||
|
mg_http_printf_chunk(c, "%s", "foo\n");
|
||||||
|
mg_http_printf_chunk(c, "%s", "bar\n");
|
||||||
|
mg_http_printf_chunk(c, "");
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
ASSERT(mg_strcmp(hm->body, mg_str(*s)) == 0);
|
||||||
|
*s = NULL;
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_http_upload(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
const char *url = "http://127.0.0.1:12352";
|
||||||
|
int i, delete = 1;
|
||||||
|
const char *s1 = "ok (chunked)\n";
|
||||||
|
const char *s2 = "ok (8 foo\nbar\n)\n";
|
||||||
|
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_http_listen(&mgr, url, us, &delete);
|
||||||
|
|
||||||
|
mg_http_connect(&mgr, url, uc, &s1);
|
||||||
|
for (i = 0; i < 20; i++) mg_mgr_poll(&mgr, 5);
|
||||||
|
ASSERT(s1 == NULL);
|
||||||
|
|
||||||
|
delete = 0;
|
||||||
|
mg_http_connect(&mgr, url, uc, &s2);
|
||||||
|
for (i = 0; i < 20; i++) mg_mgr_poll(&mgr, 5);
|
||||||
|
ASSERT(s2 == NULL);
|
||||||
|
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
ASSERT(mgr.conns == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#define LONG_CHUNK "chunk with length taking up more than two hex digits"
|
#define LONG_CHUNK "chunk with length taking up more than two hex digits"
|
||||||
|
|
||||||
// Streaming server event handler.
|
// Streaming server event handler.
|
||||||
@@ -1612,12 +1680,10 @@ static void eh5(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
|
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
|
||||||
// MG_INFO(("CHUNK [%.*s]", (int) hm->chunk.len, hm->chunk.ptr));
|
// MG_INFO(("CHUNK [%.*s]", (int) hm->chunk.len, hm->chunk.ptr));
|
||||||
mg_http_delete_chunk(c, hm);
|
mg_http_delete_chunk(c, hm);
|
||||||
} else if (ev == MG_EV_HTTP_MSG) {
|
if (hm->chunk.len == 0) {
|
||||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
*(uint32_t *) fn_data = *crc;
|
||||||
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
|
c->is_closing = 1;
|
||||||
c->is_closing = 1;
|
}
|
||||||
*(uint32_t *) fn_data = *crc;
|
|
||||||
// MG_INFO(("MSG [%.*s]", (int) hm->body.len, hm->body.ptr));
|
|
||||||
}
|
}
|
||||||
(void) ev_data;
|
(void) ev_data;
|
||||||
}
|
}
|
||||||
@@ -1651,8 +1717,6 @@ static void test_http_chunked(void) {
|
|||||||
ASSERT(mgr.conns == NULL);
|
ASSERT(mgr.conns == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef LONG_CHUNK
|
|
||||||
|
|
||||||
static void test_multipart(void) {
|
static void test_multipart(void) {
|
||||||
struct mg_http_part part;
|
struct mg_http_part part;
|
||||||
size_t ofs;
|
size_t ofs;
|
||||||
@@ -1922,6 +1986,7 @@ int main(void) {
|
|||||||
test_crc32();
|
test_crc32();
|
||||||
test_multipart();
|
test_multipart();
|
||||||
test_http_chunked();
|
test_http_chunked();
|
||||||
|
test_http_upload();
|
||||||
test_http_parse();
|
test_http_parse();
|
||||||
test_util();
|
test_util();
|
||||||
test_sntp();
|
test_sntp();
|
||||||
|
|||||||
Reference in new issue
Block a user