From: Christopher Faulet Date: Mon, 12 Aug 2019 20:42:21 +0000 (+0200) Subject: MINOR: h1-htx: Use the same function to copy message payload in all cases X-Git-Tag: v2.1-dev2~68 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc3124cf44ad78897c2df6532ad4ee4d348bdec7;p=thirdparty%2Fhaproxy.git MINOR: h1-htx: Use the same function to copy message payload in all cases This function will try to do a zero-copy transfer. Otherwise, it adds a data block. The same is used for messages with a content-length, chunked messages and messages with unknown body length. --- diff --git a/src/h1_htx.c b/src/h1_htx.c index e2675cd553..86b4a76173 100644 --- a/src/h1_htx.c +++ b/src/h1_htx.c @@ -390,6 +390,44 @@ int h1_parse_msg_hdrs(struct h1m *h1m, union h1_sl *h1sl, struct htx *dsthtx, } +/* Copy data from into an DATA block in . If possible, a + * zero-copy is performed. It returns the number of bytes copied. + */ +static int h1_copy_msg_data(struct htx *dsthtx, struct buffer *srcbuf, size_t ofs, + size_t count, struct buffer *htxbuf) +{ + /* very often with large files we'll face the following + * situation : + * - htx is empty and points to + * - ret == srcbuf->data + * - srcbuf->head == sizeof(struct htx) + * => we can swap the buffers and place an htx header into + * the target buffer instead + */ + if (unlikely(htx_is_empty(dsthtx) && count == b_data(srcbuf) && + !ofs && b_head_ofs(srcbuf) == sizeof(struct htx))) { + void *raw_area = srcbuf->area; + void *htx_area = htxbuf->area; + struct htx_blk *blk; + + srcbuf->area = htx_area; + htxbuf->area = raw_area; + dsthtx = (struct htx *)htxbuf->area; + dsthtx->size = htxbuf->size - sizeof(*dsthtx); + htx_reset(dsthtx); + b_set_data(htxbuf, b_size(htxbuf)); + + blk = htx_add_blk(dsthtx, HTX_BLK_DATA, count); + blk->info += count; + /* nothing else to do, the old buffer now contains an + * empty pre-initialized HTX header + */ + return count; + } + + return htx_add_data(dsthtx, ist2(b_peek(srcbuf, ofs), count)); +} + /* Parse HTTP/1 body. It returns the number of bytes parsed if > 0, or 0 if it * couldn't proceed. Parsing errors are reported by setting the htx flags * HTX_FL_PARSING_ERROR and filling h1m->err_pos and h1m->err_state fields. This @@ -410,37 +448,9 @@ int h1_parse_msg_data(struct h1m *h1m, struct htx *dsthtx, if (ret > b_contig_data(srcbuf, ofs)) ret = b_contig_data(srcbuf, ofs); if (ret) { - /* very often with large files we'll face the following - * situation : - * - htx is empty and points to - * - ret == buf->data - * - buf->head == sizeof(struct htx) - * => we can swap the buffers and place an htx header into - * the target buffer instead - */ int32_t try = ret; - if (unlikely(htx_is_empty(dsthtx) && ret == b_data(srcbuf) && - !ofs && b_head_ofs(srcbuf) == sizeof(struct htx))) { - void *raw_area = srcbuf->area; - void *htx_area = htxbuf->area; - struct htx_blk *blk; - - srcbuf->area = htx_area; - htxbuf->area = raw_area; - dsthtx = (struct htx *)htxbuf->area; - dsthtx->size = htxbuf->size - sizeof(*dsthtx); - htx_reset(dsthtx); - b_set_data(htxbuf, b_size(htxbuf)); - - blk = htx_add_blk(dsthtx, HTX_BLK_DATA, ret); - blk->info += ret; - /* nothing else to do, the old buffer now contains an - * empty pre-initialized HTX header - */ - } - else - ret = htx_add_data(dsthtx, ist2(b_peek(srcbuf, ofs), try)); + ret = h1_copy_msg_data(dsthtx, srcbuf, ofs, try, htxbuf); h1m->curr_len -= ret; max -= sizeof(struct htx_blk) + ret; ofs += ret; @@ -489,7 +499,7 @@ int h1_parse_msg_data(struct h1m *h1m, struct htx *dsthtx, if (ret) { int32_t try = ret; - ret = htx_add_data(dsthtx, ist2(b_peek(srcbuf, ofs), try)); + ret = h1_copy_msg_data(dsthtx, srcbuf, ofs, try, htxbuf); h1m->curr_len -= ret; max -= sizeof(struct htx_blk) + ret; ofs += ret; @@ -518,7 +528,7 @@ int h1_parse_msg_data(struct h1m *h1m, struct htx *dsthtx, if (ret > b_contig_data(srcbuf, ofs)) ret = b_contig_data(srcbuf, ofs); if (ret) - total = htx_add_data(dsthtx, ist2(b_peek(srcbuf, ofs), ret)); + total += h1_copy_msg_data(dsthtx, srcbuf, ofs, ret, htxbuf); } end: