From: Olivier Houchard Date: Wed, 5 Apr 2023 14:25:57 +0000 (+0200) Subject: MINOR: compression: Prepare compression code for request compression X-Git-Tag: v2.8-dev7~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dfc11da5615c82c0b06a5e1d5223c87260629ab5;p=thirdparty%2Fhaproxy.git MINOR: compression: Prepare compression code for request compression Make provision for storing the compression algorithm and the compression context twice, one for requests, and the other for responses. Only the response ones are used for now. --- diff --git a/include/haproxy/compression-t.h b/include/haproxy/compression-t.h index cdbf0d14e3..6851103316 100644 --- a/include/haproxy/compression-t.h +++ b/include/haproxy/compression-t.h @@ -34,6 +34,11 @@ #include +/* Direction index */ + +#define COMP_DIR_REQ 0 +#define COMP_DIR_RES 1 + /* Compression flags */ #define COMP_FL_OFFLOAD 0x00000001 /* Compression offload */ diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c index 5070096928..ad2b77c0b8 100644 --- a/src/flt_http_comp.c +++ b/src/flt_http_comp.c @@ -32,8 +32,12 @@ const char *http_comp_flt_id = "compression filter"; struct flt_ops comp_ops; struct comp_state { - struct comp_ctx *comp_ctx; /* compression context */ - struct comp_algo *comp_algo; /* compression algorithm if not NULL */ + /* + * For both comp_ctx and comp_algo, COMP_DIR_REQ is the index + * for requests, and COMP_DIR_RES for responses + */ + struct comp_ctx *comp_ctx[2]; /* compression context */ + struct comp_algo *comp_algo[2]; /* compression algorithm if not NULL */ unsigned int flags; /* COMP_STATE_* */ }; @@ -49,14 +53,14 @@ static int select_compression_request_header(struct comp_state *st, static int select_compression_response_header(struct comp_state *st, struct stream *s, struct http_msg *msg); -static int set_compression_response_header(struct comp_state *st, - struct stream *s, - struct http_msg *msg); +static int set_compression_header(struct comp_state *st, + struct stream *s, + struct http_msg *msg); static int htx_compression_buffer_init(struct htx *htx, struct buffer *out); static int htx_compression_buffer_add_data(struct comp_state *st, const char *data, size_t len, - struct buffer *out); -static int htx_compression_buffer_end(struct comp_state *st, struct buffer *out, int end); + struct buffer *out, int dir); +static int htx_compression_buffer_end(struct comp_state *st, struct buffer *out, int end, int dir); /***********************************************************************/ static int @@ -94,8 +98,10 @@ comp_strm_init(struct stream *s, struct filter *filter) if (st == NULL) return -1; - st->comp_algo = NULL; - st->comp_ctx = NULL; + st->comp_algo[COMP_DIR_REQ] = NULL; + st->comp_algo[COMP_DIR_RES] = NULL; + st->comp_ctx[COMP_DIR_REQ] = NULL; + st->comp_ctx[COMP_DIR_RES] = NULL; st->flags = 0; filter->ctx = st; @@ -116,8 +122,10 @@ comp_strm_deinit(struct stream *s, struct filter *filter) return; /* release any possible compression context */ - if (st->comp_algo) - st->comp_algo->end(&st->comp_ctx); + if (st->comp_algo[COMP_DIR_REQ]) + st->comp_algo[COMP_DIR_REQ]->end(&st->comp_ctx[COMP_DIR_REQ]); + if (st->comp_algo[COMP_DIR_RES]) + st->comp_algo[COMP_DIR_RES]->end(&st->comp_ctx[COMP_DIR_RES]); pool_free(pool_head_comp_state, st); filter->ctx = NULL; } @@ -135,8 +143,8 @@ comp_http_headers(struct stream *s, struct filter *filter, struct http_msg *msg) else { /* Response headers have already been checked in * comp_http_post_analyze callback. */ - if (st->comp_algo) { - if (!set_compression_response_header(st, s, msg)) + if (st->comp_algo[COMP_DIR_RES]) { + if (!set_compression_header(st, s, msg)) goto end; register_data_filter(s, msg->chn, filter); st->flags |= COMP_STATE_PROCESSING; @@ -176,6 +184,12 @@ comp_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg, struct htx_ret htxret = htx_find_offset(htx, offset); struct htx_blk *blk, *next; int ret, consumed = 0, to_forward = 0, last = 0; + int dir; + + if (msg->chn->flags & CF_ISRESP) + dir = COMP_DIR_RES; + else + dir = COMP_DIR_REQ; blk = htxret.blk; offset = htxret.ret; @@ -207,8 +221,8 @@ comp_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg, v.len = len; } - ret = htx_compression_buffer_add_data(st, v.ptr, v.len, &trash); - if (ret < 0 || htx_compression_buffer_end(st, &trash, last) < 0) + ret = htx_compression_buffer_add_data(st, v.ptr, v.len, &trash, dir); + if (ret < 0 || htx_compression_buffer_end(st, &trash, last, dir) < 0) goto error; BUG_ON(v.len != ret); @@ -228,7 +242,7 @@ comp_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg, case HTX_BLK_TLR: case HTX_BLK_EOT: - if (htx_compression_buffer_end(st, &trash, 1) < 0) + if (htx_compression_buffer_end(st, &trash, 1, dir) < 0) goto error; if (b_data(&trash)) { struct htx_blk *last = htx_add_last_data(htx, ist2(b_head(&trash), b_data(&trash))); @@ -261,7 +275,7 @@ comp_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg, if (to_forward != consumed) flt_update_offsets(filter, msg->chn, to_forward - consumed); - if (st->comp_ctx && st->comp_ctx->cur_lvl > 0) { + if (st->comp_ctx[dir] && st->comp_ctx[dir]->cur_lvl > 0) { update_freq_ctr(&global.comp_bps_in, consumed); _HA_ATOMIC_ADD(&strm_fe(s)->fe_counters.comp_in, consumed); _HA_ATOMIC_ADD(&s->be->be_counters.comp_in, consumed); @@ -285,7 +299,7 @@ comp_http_end(struct stream *s, struct filter *filter, { struct comp_state *st = filter->ctx; - if (!(msg->chn->flags & CF_ISRESP) || !st || !st->comp_algo) + if (!(msg->chn->flags & CF_ISRESP) || !st || !st->comp_algo[COMP_DIR_RES]) goto end; if (strm_fe(s)->mode == PR_MODE_HTTP) @@ -298,16 +312,25 @@ comp_http_end(struct stream *s, struct filter *filter, /***********************************************************************/ static int -set_compression_response_header(struct comp_state *st, struct stream *s, struct http_msg *msg) +set_compression_header(struct comp_state *st, struct stream *s, struct http_msg *msg) { struct htx *htx = htxbuf(&msg->chn->buf); struct htx_sl *sl; struct http_hdr_ctx ctx; + struct comp_algo *comp_algo; + int comp_index; + + if (msg->chn->flags & CF_ISRESP) + comp_index = COMP_DIR_RES; + else + comp_index = COMP_DIR_REQ; sl = http_get_stline(htx); if (!sl) goto error; + comp_algo = st->comp_algo[comp_index]; + /* add "Transfer-Encoding: chunked" header */ if (!(msg->flags & HTTP_MSGF_TE_CHNK)) { if (!http_add_header(htx, ist("Transfer-Encoding"), ist("chunked"))) @@ -348,8 +371,8 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct * Accept-Encoding header, and SHOULD NOT be used in the Content-Encoding * header. */ - if (st->comp_algo->cfg_name_len != 8 || memcmp(st->comp_algo->cfg_name, "identity", 8) != 0) { - struct ist v = ist2(st->comp_algo->ua_name, st->comp_algo->ua_name_len); + if (comp_algo->cfg_name_len != 8 || memcmp(comp_algo->cfg_name, "identity", 8) != 0) { + struct ist v = ist2(comp_algo->ua_name, comp_algo->ua_name_len); if (!http_add_header(htx, ist("Content-Encoding"), v)) goto error; @@ -358,8 +381,8 @@ set_compression_response_header(struct comp_state *st, struct stream *s, struct return 1; error: - st->comp_algo->end(&st->comp_ctx); - st->comp_algo = NULL; + st->comp_algo[comp_index]->end(&st->comp_ctx[comp_index]); + st->comp_algo[comp_index] = NULL; return 0; } @@ -387,7 +410,7 @@ select_compression_request_header(struct comp_state *st, struct stream *s, struc *(ctx.value.ptr + 30) < '6' || (*(ctx.value.ptr + 30) == '6' && (ctx.value.len < 54 || memcmp(ctx.value.ptr + 51, "SV1", 3) != 0)))) { - st->comp_algo = NULL; + st->comp_algo[COMP_DIR_RES] = NULL; return 0; } @@ -441,7 +464,7 @@ select_compression_request_header(struct comp_state *st, struct stream *s, struc for (comp_algo = comp_algo_back; comp_algo; comp_algo = comp_algo->next) { if (*(ctx.value.ptr) == '*' || word_match(ctx.value.ptr, toklen, comp_algo->ua_name, comp_algo->ua_name_len)) { - st->comp_algo = comp_algo; + st->comp_algo[COMP_DIR_RES] = comp_algo; best_q = q; break; } @@ -450,7 +473,7 @@ select_compression_request_header(struct comp_state *st, struct stream *s, struc } /* remove all occurrences of the header when "compression offload" is set */ - if (st->comp_algo) { + if (st->comp_algo[COMP_DIR_RES]) { if ((s->be->comp && (s->be->comp->flags & COMP_FL_OFFLOAD)) || (strm_fe(s)->comp && (strm_fe(s)->comp->flags & COMP_FL_OFFLOAD))) { http_remove_header(htx, &ctx); @@ -466,13 +489,13 @@ select_compression_request_header(struct comp_state *st, struct stream *s, struc (strm_fe(s)->comp && (comp_algo_back = strm_fe(s)->comp->algos))) { for (comp_algo = comp_algo_back; comp_algo; comp_algo = comp_algo->next) { if (comp_algo->cfg_name_len == 8 && memcmp(comp_algo->cfg_name, "identity", 8) == 0) { - st->comp_algo = comp_algo; + st->comp_algo[COMP_DIR_RES] = comp_algo; return 1; } } } - st->comp_algo = NULL; + st->comp_algo[COMP_DIR_RES] = NULL; return 0; } @@ -488,7 +511,7 @@ select_compression_response_header(struct comp_state *st, struct stream *s, stru struct comp_type *comp_type; /* no common compression algorithm was found in request header */ - if (st->comp_algo == NULL) + if (st->comp_algo[COMP_DIR_RES] == NULL) goto fail; /* compression already in progress */ @@ -577,13 +600,13 @@ select_compression_response_header(struct comp_state *st, struct stream *s, stru goto fail; /* initialize compression */ - if (st->comp_algo->init(&st->comp_ctx, global.tune.comp_maxlevel) < 0) + if (st->comp_algo[COMP_DIR_RES]->init(&st->comp_ctx[COMP_DIR_RES], global.tune.comp_maxlevel) < 0) goto fail; msg->flags |= HTTP_MSGF_COMPRESSING; return 1; fail: - st->comp_algo = NULL; + st->comp_algo[COMP_DIR_RES] = NULL; return 0; } @@ -603,18 +626,20 @@ htx_compression_buffer_init(struct htx *htx, struct buffer *out) static int htx_compression_buffer_add_data(struct comp_state *st, const char *data, size_t len, - struct buffer *out) + struct buffer *out, int dir) { - return st->comp_algo->add_data(st->comp_ctx, data, len, out); + + return st->comp_algo[dir]->add_data(st->comp_ctx[dir], data, len, out); } static int -htx_compression_buffer_end(struct comp_state *st, struct buffer *out, int end) +htx_compression_buffer_end(struct comp_state *st, struct buffer *out, int end, int dir) { + if (end) - return st->comp_algo->finish(st->comp_ctx, out); + return st->comp_algo[dir]->finish(st->comp_ctx[dir], out); else - return st->comp_algo->flush(st->comp_ctx, out); + return st->comp_algo[dir]->flush(st->comp_ctx[dir], out); } @@ -836,8 +861,8 @@ smp_fetch_res_comp_algo(const struct arg *args, struct sample *smp, smp->data.type = SMP_T_STR; smp->flags = SMP_F_CONST; - smp->data.u.str.area = st->comp_algo->cfg_name; - smp->data.u.str.data = st->comp_algo->cfg_name_len; + smp->data.u.str.area = st->comp_algo[COMP_DIR_RES]->cfg_name; + smp->data.u.str.data = st->comp_algo[COMP_DIR_RES]->cfg_name_len; return 1; } return 0;