mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-24 11:54:49 +00:00
Refactor mg_http_reply and mg_http_printf_chunk to use less allocs and mem copies
This commit is contained in:
1 parent
17e2fdd4cb
commit
bd7ee0d1e8
4 files changed
+55
-35
No files matched your search
+22
-14
@@ -265,12 +265,17 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
|
||||
|
||||
static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
|
||||
va_list ap) {
|
||||
char mem[256], *buf = mem;
|
||||
size_t len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
mg_printf(c, "%lx\r\n", (unsigned long) len);
|
||||
mg_send(c, buf, len > 0 ? (size_t) len : 0);
|
||||
size_t len = c->send.len;
|
||||
va_list tmp;
|
||||
mg_send(c, " \r\n", 10);
|
||||
va_copy(tmp, ap);
|
||||
mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &tmp);
|
||||
va_end(tmp);
|
||||
if (c->send.len >= len + 10) {
|
||||
mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10);
|
||||
c->send.buf[len + 8] = '\r';
|
||||
}
|
||||
mg_send(c, "\r\n", 2);
|
||||
if (buf != mem) free(buf);
|
||||
}
|
||||
|
||||
void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
|
||||
@@ -311,16 +316,19 @@ static const char *mg_http_status_code_str(int status_code) {
|
||||
|
||||
void mg_http_reply(struct mg_connection *c, int code, const char *headers,
|
||||
const char *fmt, ...) {
|
||||
char mem[256], *buf = mem;
|
||||
va_list ap;
|
||||
size_t len;
|
||||
mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: \r\n\r\n", code,
|
||||
mg_http_status_code_str(code), headers == NULL ? "" : headers);
|
||||
len = c->send.len;
|
||||
va_start(ap, fmt);
|
||||
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
|
||||
mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
|
||||
va_end(ap);
|
||||
mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: %d\r\n\r\n", code,
|
||||
mg_http_status_code_str(code), headers == NULL ? "" : headers, len);
|
||||
mg_send(c, buf, len > 0 ? len : 0);
|
||||
if (buf != mem) free(buf);
|
||||
if (c->send.len > 15) {
|
||||
mg_snprintf((char *) &c->send.buf[len - 14], 11, "%010lu",
|
||||
(unsigned long) (c->send.len - len));
|
||||
c->send.buf[len - 4] = '\r'; // Change ending 0 to space
|
||||
}
|
||||
}
|
||||
|
||||
static void http_cb(struct mg_connection *, int, void *, void *);
|
||||
@@ -787,13 +795,13 @@ static bool walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
||||
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);
|
||||
// MG_INFO(("len %zu off %zu cl %zu ll %zu", len, off, cl, ll));
|
||||
// MG_INFO(("len %u off %u cl %u ll %u", memo - reqlen, off, cl, ll));
|
||||
if (cl == 0) break;
|
||||
hm->chunk = mg_str_n(&buf[off + ll], cl < ll + 2 ? 0 : cl - ll - 2);
|
||||
mg_call(c, MG_EV_HTTP_CHUNK, hm);
|
||||
// Increase offset only if user has not deleted this chunk
|
||||
if (memo == c->recv.len) off += cl;
|
||||
if (cl <= 5) {
|
||||
if (ll + 2 >= cl) {
|
||||
// Zero chunk - last one. Prepare body - cut off chunk lengths
|
||||
if (memo != c->recv.len) return true; // Tell caller to cleanup
|
||||
off = bl = 0;
|
||||
@@ -805,7 +813,7 @@ static bool walkchunks(struct mg_connection *c, struct mg_http_message *hm,
|
||||
memmove(buf2 + bl, buf2 + off + ll, n);
|
||||
bl += n;
|
||||
off += cl2;
|
||||
if (cl2 <= 5) break;
|
||||
if (ll + 2 >= cl2) break;
|
||||
}
|
||||
// MG_INFO(("BL->%d del %d off %d", (int) bl, (int) del, (int) off));
|
||||
c->recv.len -= off - bl;
|
||||
|
||||
Reference in new issue
Block a user