Process chunked body before sending MG_EV_HTTP_MSG

This commit is contained in:
cpq committed 2021-03-09 08:21:29 +00:00
1 parent 2dcb10ef36
commit e84ea91a4a
3 files changed
+40 -38

No files matched your search

+17 -6
View File
@@ -1,5 +1,5 @@
// Copyright (c) 2004-2013 Sergey Lyubka // Copyright (c) 2004-2013 Sergey Lyubka
// Copyright (c) 2013-2020 Cesanta Software Limited // Copyright (c) 2013-2021 Cesanta Software Limited
// All rights reserved // All rights reserved
// //
// This software is dual-licensed: you can redistribute it and/or modify // This software is dual-licensed: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// Alternatively, you can license this software under a commercial // Alternatively, you can license this software under a commercial
// license, as set out in <https://www.cesanta.com/license>. // license, as set out in <https://www.cesanta.com/license>.
#include "mongoose.h" #include "mongoose.h"
#ifdef MG_ENABLE_LINES #ifdef MG_ENABLE_LINES
@@ -1189,7 +1188,7 @@ static size_t get_chunk_length(const char *buf, size_t len, size_t *ll) {
// 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 void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
int reqlen) { int reqlen) {
size_t off = 0, ll; size_t off = 0, bl, ll;
while (off < c->recv.len - reqlen) { while (off < c->recv.len - reqlen) {
char *buf = (char *) &c->recv.buf[reqlen]; char *buf = (char *) &c->recv.buf[reqlen];
size_t memo = c->recv.len; size_t memo = c->recv.len;
@@ -1201,10 +1200,22 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
// Increase offset only if user has not deleted this chunk // Increase offset only if user has not deleted this chunk
if (memo == c->recv.len) off += cl; if (memo == c->recv.len) off += cl;
if (cl <= 5) { if (cl <= 5) {
// Zero chunk - last one. Set message length to indicate we've received // Zero chunk - last one. Prepare body - cut off chunk lengths
off = bl = 0;
while (off < c->recv.len - reqlen) {
char *buf = (char *) &c->recv.buf[reqlen];
size_t memo = c->recv.len;
size_t cl = get_chunk_length(&buf[off], memo - reqlen - off, &ll);
size_t n = cl < ll + 2 ? 0 : cl - ll - 2;
if (cl <= 5) break;
memmove(buf + bl, buf + off + ll, n);
bl += n;
off += cl;
}
// Set message length to indicate we've received
// everything, to fire MG_EV_HTTP_MSG // everything, to fire MG_EV_HTTP_MSG
hm->message.len = off + reqlen; hm->message.len = bl + reqlen;
hm->body.len = off; hm->body.len = bl;
break; break;
} }
} }
+16 -4
View File
@@ -769,7 +769,7 @@ static size_t get_chunk_length(const char *buf, size_t len, size_t *ll) {
// 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 void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
int reqlen) { int reqlen) {
size_t off = 0, ll; size_t off = 0, bl, ll;
while (off < c->recv.len - reqlen) { while (off < c->recv.len - reqlen) {
char *buf = (char *) &c->recv.buf[reqlen]; char *buf = (char *) &c->recv.buf[reqlen];
size_t memo = c->recv.len; size_t memo = c->recv.len;
@@ -781,10 +781,22 @@ static void walkchunks(struct mg_connection *c, struct mg_http_message *hm,
// Increase offset only if user has not deleted this chunk // Increase offset only if user has not deleted this chunk
if (memo == c->recv.len) off += cl; if (memo == c->recv.len) off += cl;
if (cl <= 5) { if (cl <= 5) {
// Zero chunk - last one. Set message length to indicate we've received // Zero chunk - last one. Prepare body - cut off chunk lengths
off = bl = 0;
while (off < c->recv.len - reqlen) {
char *buf = (char *) &c->recv.buf[reqlen];
size_t memo = c->recv.len;
size_t cl = get_chunk_length(&buf[off], memo - reqlen - off, &ll);
size_t n = cl < ll + 2 ? 0 : cl - ll - 2;
if (cl <= 5) break;
memmove(buf + bl, buf + off + ll, n);
bl += n;
off += cl;
}
// Set message length to indicate we've received
// everything, to fire MG_EV_HTTP_MSG // everything, to fire MG_EV_HTTP_MSG
hm->message.len = off + reqlen; hm->message.len = bl + reqlen;
hm->body.len = off; hm->body.len = bl;
break; break;
} }
} }
+7 -28
View File
@@ -1231,7 +1231,7 @@ static void eh5(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
static void test_http_chunked(void) { static void test_http_chunked(void) {
struct mg_mgr mgr; struct mg_mgr mgr;
const char *url = "http://127.0.0.1:12344"; const char *data, *url = "http://127.0.0.1:12344";
uint32_t i, done = 0; uint32_t i, done = 0;
mg_mgr_init(&mgr); mg_mgr_init(&mgr);
mg_http_listen(&mgr, url, eh2, NULL); mg_http_listen(&mgr, url, eh2, NULL);
@@ -1239,41 +1239,20 @@ static void test_http_chunked(void) {
mg_http_connect(&mgr, url, eh3, &done); mg_http_connect(&mgr, url, eh3, &done);
for (i = 0; i < 50 && done == 0; i++) mg_mgr_poll(&mgr, 1); for (i = 0; i < 50 && done == 0; i++) mg_mgr_poll(&mgr, 1);
ASSERT(i < 50); ASSERT(i < 50);
{ data = "chunk 0chunk 1chunk 2";
const char *data = ASSERT(done == mg_crc32(0, data, strlen(data)));
"7\r\nchunk 0\r\n"
"7\r\nchunk 1\r\n"
"7\r\nchunk 2\r\n"
"0\r\n\r\n";
ASSERT(done == mg_crc32(0, data, strlen(data)));
}
done = 0; done = 0;
mg_http_connect(&mgr, url, eh4, &done); mg_http_connect(&mgr, url, eh4, &done);
for (i = 0; i < 50 && done == 0; i++) mg_mgr_poll(&mgr, 1); for (i = 0; i < 50 && done == 0; i++) mg_mgr_poll(&mgr, 1);
{ data = "chunk 0chunk 0chunk 1chunk 2chunk 0chunk 1chunk 2";
const char *data = ASSERT(done == mg_crc32(0, data, strlen(data)));
"chunk 0"
"chunk 0"
"chunk 1"
"chunk 2"
"7\r\nchunk 0\r\n"
"7\r\nchunk 1\r\n"
"7\r\nchunk 2\r\n"
"0\r\n\r\n";
ASSERT(done == mg_crc32(0, data, strlen(data)));
}
done = 0; done = 0;
mg_http_connect(&mgr, url, eh5, &done); mg_http_connect(&mgr, url, eh5, &done);
for (i = 0; i < 50 && done == 0; i++) mg_mgr_poll(&mgr, 1); for (i = 0; i < 50 && done == 0; i++) mg_mgr_poll(&mgr, 1);
{ data = "chunk 0chunk 1chunk 2";
const char *data = ASSERT(done == mg_crc32(0, data, strlen(data)));
"chunk 0"
"chunk 1"
"chunk 2";
ASSERT(done == mg_crc32(0, data, strlen(data)));
}
mg_mgr_free(&mgr); mg_mgr_free(&mgr);
ASSERT(mgr.conns == NULL); ASSERT(mgr.conns == NULL);