mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-15 10:29:47 +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
|
||||
// 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 off = 0, bl, ll;
|
||||
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 (cl <= 5) {
|
||||
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
||||
if (memo != c->recv.len) return true; // Tell caller to cleanup
|
||||
off = bl = 0;
|
||||
while (off + reqlen < c->recv.len) {
|
||||
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
|
||||
hm->message.len = bl + reqlen;
|
||||
hm->body.len = bl;
|
||||
// If user was deleting chunks, send nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
hm.message.len = c->recv.len;
|
||||
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
|
||||
} else if (is_chunked && n > 0) {
|
||||
walkchunks(c, &hm, (size_t) n);
|
||||
} else if (is_chunked && n > 0 && 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,
|
||||
// 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
|
||||
// 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 off = 0, bl, ll;
|
||||
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 (cl <= 5) {
|
||||
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
||||
if (memo != c->recv.len) return true; // Tell caller to cleanup
|
||||
off = bl = 0;
|
||||
while (off + reqlen < c->recv.len) {
|
||||
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
|
||||
hm->message.len = bl + reqlen;
|
||||
hm->body.len = bl;
|
||||
// If user was deleting chunks, send nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
hm.message.len = c->recv.len;
|
||||
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
|
||||
} else if (is_chunked && n > 0) {
|
||||
walkchunks(c, &hm, (size_t) n);
|
||||
} else if (is_chunked && n > 0 && 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,
|
||||
// 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);
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
// 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);
|
||||
// MG_INFO(("CHUNK [%.*s]", (int) hm->chunk.len, hm->chunk.ptr));
|
||||
mg_http_delete_chunk(c, hm);
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
*crc = mg_crc32(*crc, hm->chunk.ptr, hm->chunk.len);
|
||||
c->is_closing = 1;
|
||||
*(uint32_t *) fn_data = *crc;
|
||||
// MG_INFO(("MSG [%.*s]", (int) hm->body.len, hm->body.ptr));
|
||||
if (hm->chunk.len == 0) {
|
||||
*(uint32_t *) fn_data = *crc;
|
||||
c->is_closing = 1;
|
||||
}
|
||||
}
|
||||
(void) ev_data;
|
||||
}
|
||||
@@ -1651,8 +1717,6 @@ static void test_http_chunked(void) {
|
||||
ASSERT(mgr.conns == NULL);
|
||||
}
|
||||
|
||||
#undef LONG_CHUNK
|
||||
|
||||
static void test_multipart(void) {
|
||||
struct mg_http_part part;
|
||||
size_t ofs;
|
||||
@@ -1922,6 +1986,7 @@ int main(void) {
|
||||
test_crc32();
|
||||
test_multipart();
|
||||
test_http_chunked();
|
||||
test_http_upload();
|
||||
test_http_parse();
|
||||
test_util();
|
||||
test_sntp();
|
||||
|
||||
Reference in new issue
Block a user