From: Christopher Faulet Date: Fri, 21 May 2021 08:56:24 +0000 (+0200) Subject: MEDIUM: h1-htx: Split function to parse a chunk and the loop on the buffer X-Git-Tag: v2.5-dev1~239 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d4c924c34c3f6affed4538c489657eec32decb7;p=thirdparty%2Fhaproxy.git MEDIUM: h1-htx: Split function to parse a chunk and the loop on the buffer A generic function is now used to only parse the current chunk (h1_parse_chunk) and the main one (h1_parse_msg_chunks) is used to loop on the buffer and relies on the first one. This change is mandatory to be able to use an optimized function to parse contiguous small chunks. --- diff --git a/src/h1_htx.c b/src/h1_htx.c index a0cc54800c..7ac2708a70 100644 --- a/src/h1_htx.c +++ b/src/h1_htx.c @@ -451,30 +451,33 @@ static size_t h1_copy_msg_data(struct htx **dsthtx, struct buffer *srcbuf, size_ return ret; } -/* Parses medium/large HTTP chunks. This version try to performed zero-copy if - * possible. +/* Generic function to parse the current HTTP chunk. It may be used to parsed + * any kind of chunks, including incomplete HTTP chunks or splitted chunks + * because the buffer wraps. This version tries to performed zero-copy on large + * chunks if possible. */ -static size_t h1_parse_msg_chunks(struct h1m *h1m, struct htx **dsthtx, - struct buffer *srcbuf, size_t ofs, size_t max, - struct buffer *htxbuf) +static size_t h1_parse_chunk(struct h1m *h1m, struct htx **dsthtx, + struct buffer *srcbuf, size_t ofs, size_t *max, + struct buffer *htxbuf) { uint64_t chksz; - size_t sz, used, total = 0; + size_t sz, used, lmax, total = 0; int ret = 0; + lmax = *max; switch (h1m->state) { case H1_MSG_DATA: new_chunk: used = htx_used_space(*dsthtx); - if (b_data(srcbuf) == ofs || !max) + if (b_data(srcbuf) == ofs || !lmax) break; sz = b_data(srcbuf) - ofs; if (unlikely(sz > h1m->curr_len)) sz = h1m->curr_len; - sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, max, htxbuf); - max -= htx_used_space(*dsthtx) - used; + sz = h1_copy_msg_data(dsthtx, srcbuf, ofs, sz, lmax, htxbuf); + lmax -= htx_used_space(*dsthtx) - used; ofs += sz; total += sz; h1m->curr_len -= sz; @@ -490,8 +493,10 @@ static size_t h1_parse_msg_chunks(struct h1m *h1m, struct htx **dsthtx, break; ofs += ret; total += ret; + + /* Don't parse next chunk to try to handle contiguous chunks if possible */ h1m->state = H1_MSG_CHUNK_SIZE; - /* fall through */ + break; case H1_MSG_CHUNK_SIZE: ret = h1_parse_chunk_size(srcbuf, ofs, b_data(srcbuf), &chksz); @@ -525,6 +530,36 @@ static size_t h1_parse_msg_chunks(struct h1m *h1m, struct htx **dsthtx, /* Don't forget to update htx->extra */ (*dsthtx)->extra = h1m->curr_len; + *max = lmax; + return total; +} + +/* Parse HTTP chunks */ +static size_t h1_parse_msg_chunks(struct h1m *h1m, struct htx **dsthtx, + struct buffer *srcbuf, size_t ofs, size_t max, + struct buffer *htxbuf) +{ + size_t ret, total = 0; + + while (ofs < b_data(srcbuf)) { + ret = 0; + + if (h1m->state < H1_MSG_TRAILERS) { + ret = h1_parse_chunk(h1m, dsthtx, srcbuf, ofs, &max, htxbuf); + total += ret; + ofs += ret; + } + + /* nothing more was parsed, we can exit, handling parsing error + * if necessary. + */ + if (!ret) { + if ((*dsthtx)->flags & HTX_FL_PARSING_ERROR) + total = 0; + break; + } + } + return total; }