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 cdbf0d1..6851103 100644
--- a/include/haproxy/compression-t.h
+++ b/include/haproxy/compression-t.h
@@ -34,6 +34,11 @@
#include <haproxy/buf-t.h>
+/* 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 5070096..ad2b77c 100644
--- a/src/flt_http_comp.c
+++ b/src/flt_http_comp.c
@@ -32,8 +32,12 @@
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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
/***********************************************************************/
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 @@
* 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 @@
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 @@
*(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 @@
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 @@
}
/* 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 @@
(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 @@
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 @@
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 @@
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->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;