diff --git a/include/haproxy/applet-t.h b/include/haproxy/applet-t.h index 6b9a710d9..ee77093ad 100644 --- a/include/haproxy/applet-t.h +++ b/include/haproxy/applet-t.h @@ -132,16 +132,6 @@ struct appctx { __attribute__((deprecated)) size_t o0, o1; __attribute__((deprecated)) int i0, i1; } cli; /* context used by the CLI */ - struct { - struct cache_entry *entry; /* Entry to be sent from cache. */ - unsigned int sent; /* The number of bytes already sent for this cache entry. */ - unsigned int offset; /* start offset of remaining data relative to beginning of the next block */ - unsigned int rem_data; /* Remaining bytes for the last data block (HTX only, 0 means process next block) */ - unsigned int send_notmodified:1; /* In case of conditional request, we might want to send a "304 Not Modified" - * response instead of the stored data. */ - unsigned int unused:31; - struct shared_block *next; /* The next block of data to be sent for this cache entry. */ - } cache; } ctx; /* context-specific variables used by any applet */ }; /* end of anon union */ }; diff --git a/src/cache.c b/src/cache.c index 057d8b67c..f62aff847 100644 --- a/src/cache.c +++ b/src/cache.c @@ -57,6 +57,17 @@ struct cache { char id[33]; /* cache name */ }; +/* the appctx context of a cache applet, stored in appctx->svcctx */ +struct cache_appctx { + struct cache_entry *entry; /* Entry to be sent from cache. */ + unsigned int sent; /* The number of bytes already sent for this cache entry. */ + unsigned int offset; /* start offset of remaining data relative to beginning of the next block */ + unsigned int rem_data; /* Remaining bytes for the last data block (HTX only, 0 means process next block) */ + unsigned int send_notmodified:1; /* In case of conditional request, we might want to send a "304 Not Modified" response instead of the stored data. */ + unsigned int unused:31; + struct shared_block *next; /* The next block of data to be sent for this cache entry. */ +}; + /* cache config for filters */ struct cache_flt_conf { union { @@ -1259,8 +1270,9 @@ out: static void http_cache_applet_release(struct appctx *appctx) { + struct cache_appctx *ctx = appctx->svcctx; struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0]; - struct cache_entry *cache_ptr = appctx->ctx.cache.entry; + struct cache_entry *cache_ptr = ctx->entry; struct cache *cache = cconf->c.cache; struct shared_block *first = block_ptr(cache_ptr); @@ -1273,6 +1285,7 @@ static void http_cache_applet_release(struct appctx *appctx) static unsigned int htx_cache_dump_blk(struct appctx *appctx, struct htx *htx, enum htx_blk_type type, uint32_t info, struct shared_block *shblk, unsigned int offset) { + struct cache_appctx *ctx = appctx->svcctx; struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0]; struct shared_context *shctx = shctx_ptr(cconf->c.cache); struct htx_blk *blk; @@ -1308,16 +1321,16 @@ static unsigned int htx_cache_dump_blk(struct appctx *appctx, struct htx *htx, e offset = 0; } } - appctx->ctx.cache.offset = offset; - appctx->ctx.cache.next = shblk; - appctx->ctx.cache.sent += total; + ctx->offset = offset; + ctx->next = shblk; + ctx->sent += total; return total; } static unsigned int htx_cache_dump_data_blk(struct appctx *appctx, struct htx *htx, uint32_t info, struct shared_block *shblk, unsigned int offset) { - + struct cache_appctx *ctx = appctx->svcctx; struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0]; struct shared_context *shctx = shctx_ptr(cconf->c.cache); unsigned int max, total, rem_data; @@ -1328,8 +1341,8 @@ static unsigned int htx_cache_dump_data_blk(struct appctx *appctx, struct htx *h return 0; rem_data = 0; - if (appctx->ctx.cache.rem_data) { - blksz = appctx->ctx.cache.rem_data; + if (ctx->rem_data) { + blksz = ctx->rem_data; total = 0; } else { @@ -1357,16 +1370,17 @@ static unsigned int htx_cache_dump_data_blk(struct appctx *appctx, struct htx *h } } - appctx->ctx.cache.offset = offset; - appctx->ctx.cache.next = shblk; - appctx->ctx.cache.sent += total; - appctx->ctx.cache.rem_data = rem_data + blksz; + ctx->offset = offset; + ctx->next = shblk; + ctx->sent += total; + ctx->rem_data = rem_data + blksz; return total; } static size_t htx_cache_dump_msg(struct appctx *appctx, struct htx *htx, unsigned int len, enum htx_blk_type mark) { + struct cache_appctx *ctx = appctx->svcctx; struct cache_flt_conf *cconf = appctx->rule->arg.act.p[0]; struct shared_context *shctx = shctx_ptr(cconf->c.cache); struct shared_block *shblk; @@ -1377,9 +1391,9 @@ static size_t htx_cache_dump_msg(struct appctx *appctx, struct htx *htx, unsigne enum htx_blk_type type; uint32_t info; - shblk = appctx->ctx.cache.next; - offset = appctx->ctx.cache.offset; - if (appctx->ctx.cache.rem_data) { + shblk = ctx->next; + offset = ctx->offset; + if (ctx->rem_data) { type = HTX_BLK_DATA; info = 0; goto add_data_blk; @@ -1409,7 +1423,7 @@ static size_t htx_cache_dump_msg(struct appctx *appctx, struct htx *htx, unsigne total += ret; len -= ret; - if (appctx->ctx.cache.rem_data || type == mark) + if (ctx->rem_data || type == mark) break; } @@ -1418,7 +1432,8 @@ static size_t htx_cache_dump_msg(struct appctx *appctx, struct htx *htx, unsigne static int htx_cache_add_age_hdr(struct appctx *appctx, struct htx *htx) { - struct cache_entry *cache_ptr = appctx->ctx.cache.entry; + struct cache_appctx *ctx = appctx->svcctx; + struct cache_entry *cache_ptr = ctx->entry; unsigned int age; char *end; @@ -1435,7 +1450,8 @@ static int htx_cache_add_age_hdr(struct appctx *appctx, struct htx *htx) static void http_cache_io_handler(struct appctx *appctx) { - struct cache_entry *cache_ptr = appctx->ctx.cache.entry; + struct cache_appctx *ctx = appctx->svcctx; + struct cache_entry *cache_ptr = ctx->entry; struct shared_block *first = block_ptr(cache_ptr); struct conn_stream *cs = appctx->owner; struct channel *req = cs_oc(cs); @@ -1461,16 +1477,16 @@ static void http_cache_io_handler(struct appctx *appctx) appctx->st0 = HTX_CACHE_END; if (appctx->st0 == HTX_CACHE_INIT) { - appctx->ctx.cache.next = block_ptr(cache_ptr); - appctx->ctx.cache.offset = sizeof(*cache_ptr); - appctx->ctx.cache.sent = 0; - appctx->ctx.cache.rem_data = 0; + ctx->next = block_ptr(cache_ptr); + ctx->offset = sizeof(*cache_ptr); + ctx->sent = 0; + ctx->rem_data = 0; appctx->st0 = HTX_CACHE_HEADER; } if (appctx->st0 == HTX_CACHE_HEADER) { /* Headers must be dump at once. Otherwise it is an error */ - len = first->len - sizeof(*cache_ptr) - appctx->ctx.cache.sent; + len = first->len - sizeof(*cache_ptr) - ctx->sent; ret = htx_cache_dump_msg(appctx, res_htx, len, HTX_BLK_EOH); if (!ret || (htx_get_tail_type(res_htx) != HTX_BLK_EOH) || !htx_cache_add_age_hdr(appctx, res_htx)) @@ -1478,23 +1494,23 @@ static void http_cache_io_handler(struct appctx *appctx) /* In case of a conditional request, we might want to send a * "304 Not Modified" response instead of the stored data. */ - if (appctx->ctx.cache.send_notmodified) { + if (ctx->send_notmodified) { if (!http_replace_res_status(res_htx, ist("304"), ist("Not Modified"))) { /* If replacing the status code fails we need to send the full response. */ - appctx->ctx.cache.send_notmodified = 0; + ctx->send_notmodified = 0; } } /* Skip response body for HEAD requests or in case of "304 Not * Modified" response. */ - if (__cs_strm(cs)->txn->meth == HTTP_METH_HEAD || appctx->ctx.cache.send_notmodified) + if (__cs_strm(cs)->txn->meth == HTTP_METH_HEAD || ctx->send_notmodified) appctx->st0 = HTX_CACHE_EOM; else appctx->st0 = HTX_CACHE_DATA; } if (appctx->st0 == HTX_CACHE_DATA) { - len = first->len - sizeof(*cache_ptr) - appctx->ctx.cache.sent; + len = first->len - sizeof(*cache_ptr) - ctx->sent; if (len) { ret = htx_cache_dump_msg(appctx, res_htx, len, HTX_BLK_UNUSED); if (ret < len) { @@ -1823,12 +1839,14 @@ enum act_return http_action_req_cache_use(struct act_rule *rule, struct proxy *p s->target = &http_cache_applet.obj_type; if ((appctx = cs_applet_create(s->csb, objt_applet(s->target)))) { + struct cache_appctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx)); + appctx->st0 = HTX_CACHE_INIT; appctx->rule = rule; - appctx->ctx.cache.entry = res; - appctx->ctx.cache.next = NULL; - appctx->ctx.cache.sent = 0; - appctx->ctx.cache.send_notmodified = + ctx->entry = res; + ctx->next = NULL; + ctx->sent = 0; + ctx->send_notmodified = should_send_notmodified_response(cache, htxbuf(&s->req.buf), res); if (px == strm_fe(s))