mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-02 13:20:51 +00:00
Process chunked body before sending MG_EV_HTTP_MSG
This commit is contained in:
1 parent
2dcb10ef36
commit
e84ea91a4a
3 files changed
+40
-38
No files matched your search
+17
-6
@@ -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
@@ -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
@@ -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);
|
||||||
|
|||||||
Reference in new issue
Block a user