From 6112391f811a2c54091dd146cf02fcbb8bf195ba Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Wed, 2 Jan 2019 14:10:01 +0100 Subject: [PATCH] BUG/MEDIUM: cache: Be sure to end the forwarding when XFER length is unknown This bug exists in the HTX code and in the legacy one. When the body length is unknown, the applet hangs. For the legacy code, it hangs because the end of the cached object is not correctly handled and the applet is never recalled. For the HTX code, only the begining of the response (the 1st buffer) is sent then the applet hangs. To work in HTX, The fast forwarding must be correctly handled. This patch must be backported to 1.9. [cf: the patch adding the function channel_add_input must be backported with this one. It does not exist in 1.8 because only responses with a C-L are cached.] --- src/cache.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/cache.c b/src/cache.c index 020650a33..d80ee904f 100644 --- a/src/cache.c +++ b/src/cache.c @@ -994,12 +994,13 @@ static void htx_cache_io_handler(struct appctx *appctx) unsigned int len = cache_ptr->hdrs_len + cache_ptr->data_len - appctx->ctx.cache.sent; ret = htx_cache_dump_data(appctx, res_htx, HTX_BLK_DATA, len); - if (!ret) { + total += ret; + res_htx->extra = (len - ret); + if (ret < len) { si_rx_room_blk(si); goto out; } - total += ret; if (cache_ptr->hdrs_len + cache_ptr->data_len == appctx->ctx.cache.sent) { if (first->len > sizeof(*cache_ptr) + appctx->ctx.cache.sent) { /* Headers and all data have been sent @@ -1026,7 +1027,7 @@ static void htx_cache_io_handler(struct appctx *appctx) unsigned int len = first->len - sizeof(*cache_ptr) - appctx->ctx.cache.sent; ret = htx_cache_dump_data(appctx, res_htx, HTX_BLK_TLR, len); - if (!ret) { + if (ret < len) { si_rx_room_blk(si); goto out; } @@ -1067,10 +1068,8 @@ static void htx_cache_io_handler(struct appctx *appctx) } } out: - if (total) { - res->total += total; - res->flags |= CF_READ_PARTIAL; - } + if (total) + channel_add_input(res, total); /* we have left the request in the buffer for the case where we * process a POST, and this automatically re-enables activity on @@ -1196,7 +1195,6 @@ static void http_cache_io_handler(struct appctx *appctx) /* buffer are aligned there, should be fine */ if (appctx->st0 == HTTP_CACHE_HEADER || appctx->st0 == HTTP_CACHE_INIT) { int len = first->len - *sent - sizeof(struct cache_entry); - if (len > 0) { int ret; @@ -1208,6 +1206,10 @@ static void http_cache_io_handler(struct appctx *appctx) if (appctx->st0 == HTTP_CACHE_INIT && *sent > cache_ptr->eoh && cache_channel_append_age_header(cache_ptr, res)) appctx->st0 = HTTP_CACHE_HEADER; + else if (ret == len) { + *sent = 0; + appctx->st0 = HTTP_CACHE_FWD; + } } else { *sent = 0;