blob: 10121488d68bf0f73cab6e8d2fef49f1ac25050b [file] [log] [blame]
William Lallemand82fe75c2012-10-23 10:25:10 +02001/*
2 * HTTP compression.
3 *
4 * Copyright 2012 Exceliance, David Du Colombier <dducolombier@exceliance.fr>
5 * William Lallemand <wlallemand@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 */
13
14#include <stdio.h>
Willy Tarreau34763642012-10-26 15:05:35 +020015
Willy Tarreau418b8c02015-03-29 03:32:06 +020016#if defined(USE_SLZ)
17#include <slz.h>
18#elif defined(USE_ZLIB)
Willy Tarreau34763642012-10-26 15:05:35 +020019/* Note: the crappy zlib and openssl libs both define the "free_func" type.
20 * That's a very clever idea to use such a generic name in general purpose
21 * libraries, really... The zlib one is easier to redefine than openssl's,
22 * so let's only fix this one.
23 */
24#define free_func zlib_free_func
William Lallemand82fe75c2012-10-23 10:25:10 +020025#include <zlib.h>
Willy Tarreau34763642012-10-26 15:05:35 +020026#undef free_func
William Lallemand08289f12012-10-31 11:19:18 +010027#endif /* USE_ZLIB */
William Lallemand82fe75c2012-10-23 10:25:10 +020028
29#include <common/compat.h>
William Lallemand2b502472012-10-30 14:30:39 +010030#include <common/memory.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020031
32#include <types/global.h>
33#include <types/compression.h>
34
William Lallemand727db8b2013-04-20 17:33:20 +020035#include <proto/acl.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <proto/compression.h>
William Lallemandd85f9172012-11-09 17:05:39 +010037#include <proto/freq_ctr.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020038#include <proto/proto_http.h>
Willy Tarreaue36cbcb2015-04-03 15:40:56 +020039#include <proto/stream.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020040
William Lallemand2b502472012-10-30 14:30:39 +010041
42#ifdef USE_ZLIB
43
William Lallemand8b52bb32012-11-16 18:06:41 +010044static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size);
45static void free_zlib(void *opaque, void *ptr);
46
William Lallemand2b502472012-10-30 14:30:39 +010047/* zlib allocation */
48static struct pool_head *zlib_pool_deflate_state = NULL;
49static struct pool_head *zlib_pool_window = NULL;
50static struct pool_head *zlib_pool_prev = NULL;
51static struct pool_head *zlib_pool_head = NULL;
52static struct pool_head *zlib_pool_pending_buf = NULL;
53
William Lallemande3a7d992012-11-20 11:25:20 +010054long zlib_used_memory = 0;
William Lallemand9d5f5482012-11-07 16:12:57 +010055
William Lallemand2b502472012-10-30 14:30:39 +010056#endif
57
William Lallemand072a2bf2012-11-20 17:01:01 +010058unsigned int compress_min_idle = 0;
William Lallemand8b52bb32012-11-16 18:06:41 +010059static struct pool_head *pool_comp_ctx = NULL;
60
Willy Tarreau9f640a12015-03-28 15:46:00 +010061static int identity_init(struct comp_ctx **comp_ctx, int level);
62static int identity_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
Willy Tarreau9787efa2015-03-28 19:17:31 +010063static int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out);
64static int identity_finish(struct comp_ctx *comp_ctx, struct buffer *out);
Willy Tarreau9f640a12015-03-28 15:46:00 +010065static int identity_end(struct comp_ctx **comp_ctx);
66
Willy Tarreau418b8c02015-03-29 03:32:06 +020067#if defined(USE_SLZ)
68
69static int rfc1950_init(struct comp_ctx **comp_ctx, int level);
70static int rfc1951_init(struct comp_ctx **comp_ctx, int level);
71static int rfc1952_init(struct comp_ctx **comp_ctx, int level);
72static int rfc195x_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
73static int rfc195x_flush(struct comp_ctx *comp_ctx, struct buffer *out);
74static int rfc195x_finish(struct comp_ctx *comp_ctx, struct buffer *out);
75static int rfc195x_end(struct comp_ctx **comp_ctx);
76
77#elif defined(USE_ZLIB)
Willy Tarreau7b218772015-03-28 22:08:25 +010078
Willy Tarreau9f640a12015-03-28 15:46:00 +010079static int gzip_init(struct comp_ctx **comp_ctx, int level);
Willy Tarreauc91840a2015-03-28 17:00:39 +010080static int raw_def_init(struct comp_ctx **comp_ctx, int level);
Willy Tarreau9f640a12015-03-28 15:46:00 +010081static int deflate_init(struct comp_ctx **comp_ctx, int level);
82static int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
Willy Tarreau9787efa2015-03-28 19:17:31 +010083static int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out);
84static int deflate_finish(struct comp_ctx *comp_ctx, struct buffer *out);
Willy Tarreau9f640a12015-03-28 15:46:00 +010085static int deflate_end(struct comp_ctx **comp_ctx);
Willy Tarreau7b218772015-03-28 22:08:25 +010086
Willy Tarreau9f640a12015-03-28 15:46:00 +010087#endif /* USE_ZLIB */
88
William Lallemand2b502472012-10-30 14:30:39 +010089
Cyril Bonté6162c432012-11-10 19:27:47 +010090const struct comp_algo comp_algos[] =
William Lallemand82fe75c2012-10-23 10:25:10 +020091{
Willy Tarreau7b218772015-03-28 22:08:25 +010092 { "identity", 8, "identity", 8, identity_init, identity_add_data, identity_flush, identity_finish, identity_end },
Willy Tarreau418b8c02015-03-29 03:32:06 +020093#if defined(USE_SLZ)
94 { "deflate", 7, "deflate", 7, rfc1950_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
95 { "raw-deflate", 11, "deflate", 7, rfc1951_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
96 { "gzip", 4, "gzip", 4, rfc1952_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
97#elif defined(USE_ZLIB)
Willy Tarreau7b218772015-03-28 22:08:25 +010098 { "deflate", 7, "deflate", 7, deflate_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
99 { "raw-deflate", 11, "deflate", 7, raw_def_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
100 { "gzip", 4, "gzip", 4, gzip_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
William Lallemand82fe75c2012-10-23 10:25:10 +0200101#endif /* USE_ZLIB */
Willy Tarreau615105e2015-03-28 16:40:46 +0100102 { NULL, 0, NULL, 0, NULL , NULL, NULL, NULL, NULL }
William Lallemand82fe75c2012-10-23 10:25:10 +0200103};
104
105/*
106 * Add a content-type in the configuration
107 */
108int comp_append_type(struct comp *comp, const char *type)
109{
110 struct comp_type *comp_type;
111
112 comp_type = calloc(1, sizeof(struct comp_type));
113 comp_type->name_len = strlen(type);
114 comp_type->name = strdup(type);
115 comp_type->next = comp->types;
116 comp->types = comp_type;
117 return 0;
118}
119
120/*
121 * Add an algorithm in the configuration
122 */
123int comp_append_algo(struct comp *comp, const char *algo)
124{
125 struct comp_algo *comp_algo;
126 int i;
127
Willy Tarreau615105e2015-03-28 16:40:46 +0100128 for (i = 0; comp_algos[i].cfg_name; i++) {
129 if (!strcmp(algo, comp_algos[i].cfg_name)) {
William Lallemand82fe75c2012-10-23 10:25:10 +0200130 comp_algo = calloc(1, sizeof(struct comp_algo));
131 memmove(comp_algo, &comp_algos[i], sizeof(struct comp_algo));
132 comp_algo->next = comp->algos;
133 comp->algos = comp_algo;
134 return 0;
135 }
136 }
137 return -1;
138}
139
140/* emit the chunksize followed by a CRLF on the output and return the number of
Willy Tarreau15530d22015-03-28 12:05:47 +0100141 * bytes written. It goes backwards and starts with the byte before <end>. It
142 * returns the number of bytes written which will not exceed 10 (8 digits, CR,
143 * and LF). The caller is responsible for ensuring there is enough room left in
144 * the output buffer for the string.
William Lallemand82fe75c2012-10-23 10:25:10 +0200145 */
Willy Tarreau15530d22015-03-28 12:05:47 +0100146int http_emit_chunk_size(char *end, unsigned int chksz)
William Lallemand82fe75c2012-10-23 10:25:10 +0200147{
Willy Tarreau15530d22015-03-28 12:05:47 +0100148 char *beg = end;
William Lallemand82fe75c2012-10-23 10:25:10 +0200149
Willy Tarreau15530d22015-03-28 12:05:47 +0100150 *--beg = '\n';
151 *--beg = '\r';
William Lallemand82fe75c2012-10-23 10:25:10 +0200152 do {
Willy Tarreau15530d22015-03-28 12:05:47 +0100153 *--beg = hextab[chksz & 0xF];
154 } while (chksz >>= 4);
155 return end - beg;
William Lallemand82fe75c2012-10-23 10:25:10 +0200156}
157
158/*
159 * Init HTTP compression
160 */
Willy Tarreau87b09662015-04-03 00:22:06 +0200161int http_compression_buffer_init(struct stream *s, struct buffer *in, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200162{
Willy Tarreau2aee2212015-03-28 12:20:33 +0100163 /* output stream requires at least 10 bytes for the gzip header, plus
164 * at least 8 bytes for the gzip trailer (crc+len), plus a possible
165 * plus at most 5 bytes per 32kB block and 2 bytes to close the stream.
166 */
167 if (in->size - buffer_len(in) < 20 + 5 * ((in->i + 32767) >> 15))
Willy Tarreaud328af52015-03-28 11:10:56 +0100168 return -1;
William Lallemand82fe75c2012-10-23 10:25:10 +0200169
Willy Tarreaud328af52015-03-28 11:10:56 +0100170 /* prepare an empty output buffer in which we reserve enough room for
Willy Tarreau15530d22015-03-28 12:05:47 +0100171 * copying the output bytes from <in>, plus 10 extra bytes to write
Willy Tarreaud328af52015-03-28 11:10:56 +0100172 * the chunk size. We don't copy the bytes yet so that if we have to
173 * cancel the operation later, it's cheap.
William Lallemand82fe75c2012-10-23 10:25:10 +0200174 */
Willy Tarreau474cf542014-11-24 10:54:47 +0100175 b_reset(out);
Willy Tarreaud328af52015-03-28 11:10:56 +0100176 out->o = in->o;
177 out->p += out->o;
Willy Tarreau15530d22015-03-28 12:05:47 +0100178 out->i = 10;
William Lallemand82fe75c2012-10-23 10:25:10 +0200179 return 0;
180}
181
182/*
183 * Add data to compress
184 */
Willy Tarreau87b09662015-04-03 00:22:06 +0200185int http_compression_buffer_add_data(struct stream *s, struct buffer *in, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200186{
Willy Tarreaueee5b512015-04-03 23:46:31 +0200187 struct http_msg *msg = &s->txn->rsp;
William Lallemandbf3ae612012-11-19 12:35:37 +0100188 int consumed_data = 0;
William Lallemand82fe75c2012-10-23 10:25:10 +0200189 int data_process_len;
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200190 int block1, block2;
William Lallemand82fe75c2012-10-23 10:25:10 +0200191
192 /*
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200193 * Temporarily skip already parsed data and chunks to jump to the
194 * actual data block. It is fixed before leaving.
William Lallemand82fe75c2012-10-23 10:25:10 +0200195 */
196 b_adv(in, msg->next);
William Lallemand82fe75c2012-10-23 10:25:10 +0200197
198 /*
199 * select the smallest size between the announced chunk size, the input
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200200 * data, and the available output buffer size. The compressors are
201 * assumed to be able to process all the bytes we pass to them at once.
William Lallemand82fe75c2012-10-23 10:25:10 +0200202 */
203 data_process_len = MIN(in->i, msg->chunk_len);
204 data_process_len = MIN(out->size - buffer_len(out), data_process_len);
205
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200206 block1 = data_process_len;
207 if (block1 > bi_contig_data(in))
208 block1 = bi_contig_data(in);
209 block2 = data_process_len - block1;
William Lallemand82fe75c2012-10-23 10:25:10 +0200210
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200211 /* compressors return < 0 upon error or the amount of bytes read */
212 consumed_data = s->comp_algo->add_data(s->comp_ctx, bi_ptr(in), block1, out);
213 if (consumed_data >= 0 && block2 > 0) {
214 consumed_data = s->comp_algo->add_data(s->comp_ctx, in->data, block2, out);
215 if (consumed_data >= 0)
216 consumed_data += block1;
William Lallemand82fe75c2012-10-23 10:25:10 +0200217 }
218
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200219 /* restore original buffer pointer */
220 b_rew(in, msg->next);
William Lallemand82fe75c2012-10-23 10:25:10 +0200221
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200222 if (consumed_data > 0) {
223 msg->next += consumed_data;
224 msg->chunk_len -= consumed_data;
225 }
William Lallemandbf3ae612012-11-19 12:35:37 +0100226 return consumed_data;
William Lallemand82fe75c2012-10-23 10:25:10 +0200227}
228
229/*
230 * Flush data in process, and write the header and footer of the chunk. Upon
231 * success, in and out buffers are swapped to avoid a copy.
232 */
Willy Tarreau87b09662015-04-03 00:22:06 +0200233int http_compression_buffer_end(struct stream *s, struct buffer **in, struct buffer **out, int end)
William Lallemand82fe75c2012-10-23 10:25:10 +0200234{
Willy Tarreau3ca54482014-04-23 19:31:17 +0200235 int to_forward;
William Lallemand82fe75c2012-10-23 10:25:10 +0200236 int left;
Willy Tarreaueee5b512015-04-03 23:46:31 +0200237 struct http_msg *msg = &s->txn->rsp;
William Lallemand82fe75c2012-10-23 10:25:10 +0200238 struct buffer *ib = *in, *ob = *out;
Willy Tarreaud328af52015-03-28 11:10:56 +0100239 char *tail;
William Lallemand08289f12012-10-31 11:19:18 +0100240
Willy Tarreau418b8c02015-03-29 03:32:06 +0200241#if defined(USE_SLZ) || defined(USE_ZLIB)
William Lallemand82fe75c2012-10-23 10:25:10 +0200242 int ret;
243
244 /* flush data here */
245
246 if (end)
Willy Tarreau9787efa2015-03-28 19:17:31 +0100247 ret = s->comp_algo->finish(s->comp_ctx, ob); /* end of data */
William Lallemand82fe75c2012-10-23 10:25:10 +0200248 else
Willy Tarreau9787efa2015-03-28 19:17:31 +0100249 ret = s->comp_algo->flush(s->comp_ctx, ob); /* end of buffer */
William Lallemand82fe75c2012-10-23 10:25:10 +0200250
251 if (ret < 0)
252 return -1; /* flush failed */
253
William Lallemand08289f12012-10-31 11:19:18 +0100254#endif /* USE_ZLIB */
255
Willy Tarreau15530d22015-03-28 12:05:47 +0100256 if (ob->i == 10) {
Willy Tarreaud328af52015-03-28 11:10:56 +0100257 /* No data were appended, let's drop the output buffer and
258 * keep the input buffer unchanged.
259 */
260 return 0;
261 }
William Lallemand82fe75c2012-10-23 10:25:10 +0200262
Willy Tarreaud328af52015-03-28 11:10:56 +0100263 /* OK so at this stage, we have an output buffer <ob> looking like this :
264 *
265 * <-- o --> <------ i ----->
266 * +---------+---+------------+-----------+
267 * | out | c | comp_in | empty |
268 * +---------+---+------------+-----------+
269 * data p size
270 *
271 * <out> is the room reserved to copy ib->o. It starts at ob->data and
272 * has not yet been filled. <c> is the room reserved to write the chunk
Willy Tarreau15530d22015-03-28 12:05:47 +0100273 * size (10 bytes). <comp_in> is the compressed equivalent of the data
Willy Tarreaud328af52015-03-28 11:10:56 +0100274 * part of ib->i. <empty> is the amount of empty bytes at the end of
275 * the buffer, into which we may have to copy the remaining bytes from
276 * ib->i after the data (chunk size, trailers, ...).
277 */
William Lallemand82fe75c2012-10-23 10:25:10 +0200278
Willy Tarreaud328af52015-03-28 11:10:56 +0100279 /* Write real size at the begining of the chunk, no need of wrapping.
Willy Tarreau15530d22015-03-28 12:05:47 +0100280 * We write the chunk using a dynamic length and adjust ob->p and ob->i
281 * accordingly afterwards. That will move <out> away from <data>.
Willy Tarreaud328af52015-03-28 11:10:56 +0100282 */
Willy Tarreau15530d22015-03-28 12:05:47 +0100283 left = 10 - http_emit_chunk_size(ob->p + 10, ob->i - 10);
284 ob->p += left;
285 ob->i -= left;
William Lallemand82fe75c2012-10-23 10:25:10 +0200286
Willy Tarreaud328af52015-03-28 11:10:56 +0100287 /* Copy previous data from ib->o into ob->o */
288 if (ib->o > 0) {
289 left = bo_contig_data(ib);
290 memcpy(ob->p - ob->o, bo_ptr(ib), left);
291 if (ib->o - left) /* second part of the buffer */
292 memcpy(ob->p - ob->o + left, ib->data, ib->o - left);
293 }
294
295 /* chunked encoding requires CRLF after data */
296 tail = ob->p + ob->i;
297 *tail++ = '\r';
298 *tail++ = '\n';
299
300 /* At the end of data, we must write the empty chunk 0<CRLF>,
301 * and terminate the trailers section with a last <CRLF>. If
302 * we're forwarding a chunked-encoded response, we'll have a
303 * trailers section after the empty chunk which needs to be
304 * forwarded and which will provide the last CRLF. Otherwise
305 * we write it ourselves.
306 */
307 if (msg->msg_state >= HTTP_MSG_TRAILERS) {
308 memcpy(tail, "0\r\n", 3);
309 tail += 3;
310 if (msg->msg_state >= HTTP_MSG_DONE) {
311 memcpy(tail, "\r\n", 2);
312 tail += 2;
William Lallemand82fe75c2012-10-23 10:25:10 +0200313 }
William Lallemand82fe75c2012-10-23 10:25:10 +0200314 }
Willy Tarreaud328af52015-03-28 11:10:56 +0100315 ob->i = tail - ob->p;
William Lallemand82fe75c2012-10-23 10:25:10 +0200316
317 to_forward = ob->i;
Willy Tarreau55058a72012-11-21 08:27:21 +0100318
William Lallemandd85f9172012-11-09 17:05:39 +0100319 /* update input rate */
Willy Tarreau55058a72012-11-21 08:27:21 +0100320 if (s->comp_ctx && s->comp_ctx->cur_lvl > 0) {
Willy Tarreau3ca54482014-04-23 19:31:17 +0200321 update_freq_ctr(&global.comp_bps_in, msg->next);
Willy Tarreaud0d8da92015-04-04 02:10:38 +0200322 strm_fe(s)->fe_counters.comp_in += msg->next;
Willy Tarreau3ca54482014-04-23 19:31:17 +0200323 s->be->be_counters.comp_in += msg->next;
Willy Tarreau55058a72012-11-21 08:27:21 +0100324 } else {
Willy Tarreaud0d8da92015-04-04 02:10:38 +0200325 strm_fe(s)->fe_counters.comp_byp += msg->next;
Willy Tarreau3ca54482014-04-23 19:31:17 +0200326 s->be->be_counters.comp_byp += msg->next;
Willy Tarreau55058a72012-11-21 08:27:21 +0100327 }
William Lallemandd85f9172012-11-09 17:05:39 +0100328
William Lallemand82fe75c2012-10-23 10:25:10 +0200329 /* copy the remaining data in the tmp buffer. */
Willy Tarreau7f2f8d52014-04-18 00:20:14 +0200330 b_adv(ib, msg->next);
331 msg->next = 0;
332
William Lallemand82fe75c2012-10-23 10:25:10 +0200333 if (ib->i > 0) {
Willy Tarreaud328af52015-03-28 11:10:56 +0100334 left = bi_contig_data(ib);
335 memcpy(ob->p + ob->i, bi_ptr(ib), left);
336 ob->i += left;
337 if (ib->i - left) {
338 memcpy(ob->p + ob->i, ib->data, ib->i - left);
339 ob->i += ib->i - left;
William Lallemand82fe75c2012-10-23 10:25:10 +0200340 }
341 }
342
343 /* swap the buffers */
344 *in = ob;
345 *out = ib;
346
Willy Tarreau55058a72012-11-21 08:27:21 +0100347 if (s->comp_ctx && s->comp_ctx->cur_lvl > 0) {
William Lallemandd85f9172012-11-09 17:05:39 +0100348 update_freq_ctr(&global.comp_bps_out, to_forward);
Willy Tarreaud0d8da92015-04-04 02:10:38 +0200349 strm_fe(s)->fe_counters.comp_out += to_forward;
Willy Tarreau55058a72012-11-21 08:27:21 +0100350 s->be->be_counters.comp_out += to_forward;
351 }
William Lallemandd85f9172012-11-09 17:05:39 +0100352
William Lallemand82fe75c2012-10-23 10:25:10 +0200353 /* forward the new chunk without remaining data */
354 b_adv(ob, to_forward);
355
William Lallemand82fe75c2012-10-23 10:25:10 +0200356 return to_forward;
357}
358
William Lallemand8b52bb32012-11-16 18:06:41 +0100359/*
360 * Alloc the comp_ctx
361 */
362static inline int init_comp_ctx(struct comp_ctx **comp_ctx)
363{
364#ifdef USE_ZLIB
365 z_stream *strm;
366
William Lallemande3a7d992012-11-20 11:25:20 +0100367 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < sizeof(struct comp_ctx))
William Lallemand8b52bb32012-11-16 18:06:41 +0100368 return -1;
369#endif
370
371 if (unlikely(pool_comp_ctx == NULL))
372 pool_comp_ctx = create_pool("comp_ctx", sizeof(struct comp_ctx), MEM_F_SHARED);
373
374 *comp_ctx = pool_alloc2(pool_comp_ctx);
375 if (*comp_ctx == NULL)
376 return -1;
Willy Tarreau418b8c02015-03-29 03:32:06 +0200377#if defined(USE_SLZ)
378 (*comp_ctx)->direct_ptr = NULL;
379 (*comp_ctx)->direct_len = 0;
380 (*comp_ctx)->queued = NULL;
381#elif defined(USE_ZLIB)
William Lallemande3a7d992012-11-20 11:25:20 +0100382 zlib_used_memory += sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100383
384 strm = &(*comp_ctx)->strm;
385 strm->zalloc = alloc_zlib;
386 strm->zfree = free_zlib;
387 strm->opaque = *comp_ctx;
388#endif
389 return 0;
390}
391
392/*
393 * Dealloc the comp_ctx
394 */
395static inline int deinit_comp_ctx(struct comp_ctx **comp_ctx)
396{
397 if (!*comp_ctx)
398 return 0;
399
400 pool_free2(pool_comp_ctx, *comp_ctx);
401 *comp_ctx = NULL;
402
403#ifdef USE_ZLIB
William Lallemande3a7d992012-11-20 11:25:20 +0100404 zlib_used_memory -= sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100405#endif
William Lallemand8b52bb32012-11-16 18:06:41 +0100406 return 0;
407}
408
William Lallemand82fe75c2012-10-23 10:25:10 +0200409
410/****************************
411 **** Identity algorithm ****
412 ****************************/
413
414/*
415 * Init the identity algorithm
416 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100417static int identity_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200418{
419 return 0;
420}
421
422/*
423 * Process data
William Lallemandbf3ae612012-11-19 12:35:37 +0100424 * Return size of consumed data or -1 on error
William Lallemand82fe75c2012-10-23 10:25:10 +0200425 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100426static int identity_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200427{
William Lallemandbf3ae612012-11-19 12:35:37 +0100428 char *out_data = bi_end(out);
429 int out_len = out->size - buffer_len(out);
430
William Lallemand82fe75c2012-10-23 10:25:10 +0200431 if (out_len < in_len)
432 return -1;
433
434 memcpy(out_data, in_data, in_len);
435
William Lallemandbf3ae612012-11-19 12:35:37 +0100436 out->i += in_len;
437
William Lallemand82fe75c2012-10-23 10:25:10 +0200438 return in_len;
439}
440
Willy Tarreau9787efa2015-03-28 19:17:31 +0100441static int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200442{
443 return 0;
444}
445
Willy Tarreau9787efa2015-03-28 19:17:31 +0100446static int identity_finish(struct comp_ctx *comp_ctx, struct buffer *out)
447{
448 return 0;
449}
450
Willy Tarreau418b8c02015-03-29 03:32:06 +0200451/*
452 * Deinit the algorithm
453 */
454static int identity_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200455{
456 return 0;
457}
458
Willy Tarreau418b8c02015-03-29 03:32:06 +0200459
460#ifdef USE_SLZ
461
462/* SLZ's gzip format (RFC1952). Returns < 0 on error. */
463static int rfc1952_init(struct comp_ctx **comp_ctx, int level)
464{
465 if (init_comp_ctx(comp_ctx) < 0)
466 return -1;
467
468 (*comp_ctx)->cur_lvl = !!level;
469 return slz_rfc1952_init(&(*comp_ctx)->strm, !!level);
470}
471
472/* SLZ's raw deflate format (RFC1951). Returns < 0 on error. */
473static int rfc1951_init(struct comp_ctx **comp_ctx, int level)
474{
475 if (init_comp_ctx(comp_ctx) < 0)
476 return -1;
477
478 (*comp_ctx)->cur_lvl = !!level;
479 return slz_rfc1951_init(&(*comp_ctx)->strm, !!level);
480}
481
482/* SLZ's zlib format (RFC1950). Returns < 0 on error. */
483static int rfc1950_init(struct comp_ctx **comp_ctx, int level)
484{
485 if (init_comp_ctx(comp_ctx) < 0)
486 return -1;
487
488 (*comp_ctx)->cur_lvl = !!level;
489 return slz_rfc1950_init(&(*comp_ctx)->strm, !!level);
490}
491
492/* Return the size of consumed data or -1. The output buffer is unused at this
493 * point, we only keep a reference to the input data or a copy of them if the
494 * reference is already used.
William Lallemand82fe75c2012-10-23 10:25:10 +0200495 */
Willy Tarreau418b8c02015-03-29 03:32:06 +0200496static int rfc195x_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200497{
Willy Tarreau418b8c02015-03-29 03:32:06 +0200498 static struct buffer *tmpbuf = &buf_empty;
499
500 if (in_len <= 0)
501 return 0;
502
503 if (comp_ctx->direct_ptr && !comp_ctx->queued) {
504 /* data already being pointed to, we're in front of fragmented
505 * data and need a buffer now. We reuse the same buffer, as it's
506 * not used out of the scope of a series of add_data()*, end().
507 */
508 if (unlikely(!tmpbuf->size)) {
509 /* this is the first time we need the compression buffer */
510 if (b_alloc(&tmpbuf) == NULL)
511 return -1; /* no memory */
512 }
513 b_reset(tmpbuf);
514 memcpy(bi_end(tmpbuf), comp_ctx->direct_ptr, comp_ctx->direct_len);
515 tmpbuf->i += comp_ctx->direct_len;
516 comp_ctx->direct_ptr = NULL;
517 comp_ctx->direct_len = 0;
518 comp_ctx->queued = tmpbuf;
519 /* fall through buffer copy */
520 }
521
522 if (comp_ctx->queued) {
523 /* data already pending */
524 memcpy(bi_end(comp_ctx->queued), in_data, in_len);
525 comp_ctx->queued->i += in_len;
526 return in_len;
527 }
528
529 comp_ctx->direct_ptr = in_data;
530 comp_ctx->direct_len = in_len;
531 return in_len;
532}
533
534/* Compresses the data accumulated using add_data(), and optionally sends the
535 * format-specific trailer if <finish> is non-null. <out> is expected to have a
536 * large enough free non-wrapping space as verified by http_comp_buffer_init().
537 * The number of bytes emitted is reported.
538 */
539static int rfc195x_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int finish)
540{
541 struct slz_stream *strm = &comp_ctx->strm;
542 const char *in_ptr;
543 int in_len;
544 int out_len;
545
546 in_ptr = comp_ctx->direct_ptr;
547 in_len = comp_ctx->direct_len;
548
549 if (comp_ctx->queued) {
550 in_ptr = comp_ctx->queued->p;
551 in_len = comp_ctx->queued->i;
552 }
553
554 out_len = out->i;
555
556 if (in_ptr)
557 out->i += slz_encode(strm, bi_end(out), in_ptr, in_len, !finish);
558
559 if (finish)
560 out->i += slz_finish(strm, bi_end(out));
561
562 out_len = out->i - out_len;
563
564 /* very important, we must wipe the data we've just flushed */
565 comp_ctx->direct_len = 0;
566 comp_ctx->direct_ptr = NULL;
567 comp_ctx->queued = NULL;
568
569 /* Verify compression rate limiting and CPU usage */
570 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
571 (idle_pct < compress_min_idle)) { /* idle */
572 if (comp_ctx->cur_lvl > 0)
573 strm->level = --comp_ctx->cur_lvl;
574 }
575 else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel && comp_ctx->cur_lvl < 1) {
576 strm->level = ++comp_ctx->cur_lvl;
577 }
578
579 /* and that's all */
580 return out_len;
581}
582
583static int rfc195x_flush(struct comp_ctx *comp_ctx, struct buffer *out)
584{
585 return rfc195x_flush_or_finish(comp_ctx, out, 0);
586}
587
588static int rfc195x_finish(struct comp_ctx *comp_ctx, struct buffer *out)
589{
590 return rfc195x_flush_or_finish(comp_ctx, out, 1);
591}
592
593/* we just need to free the comp_ctx here, nothing was allocated */
594static int rfc195x_end(struct comp_ctx **comp_ctx)
595{
596 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200597 return 0;
598}
599
Willy Tarreau418b8c02015-03-29 03:32:06 +0200600#elif defined(USE_ZLIB) /* ! USE_SLZ */
William Lallemand82fe75c2012-10-23 10:25:10 +0200601
William Lallemand2b502472012-10-30 14:30:39 +0100602/*
603 * This is a tricky allocation function using the zlib.
604 * This is based on the allocation order in deflateInit2.
605 */
606static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
607{
608 struct comp_ctx *ctx = opaque;
609 static char round = 0; /* order in deflateInit2 */
610 void *buf = NULL;
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100611 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100612
William Lallemande3a7d992012-11-20 11:25:20 +0100613 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < (long)(items * size))
William Lallemand9d5f5482012-11-07 16:12:57 +0100614 goto end;
William Lallemand9d5f5482012-11-07 16:12:57 +0100615
William Lallemand2b502472012-10-30 14:30:39 +0100616 switch (round) {
617 case 0:
618 if (zlib_pool_deflate_state == NULL)
619 zlib_pool_deflate_state = create_pool("zlib_state", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100620 pool = zlib_pool_deflate_state;
621 ctx->zlib_deflate_state = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100622 break;
623
624 case 1:
625 if (zlib_pool_window == NULL)
626 zlib_pool_window = create_pool("zlib_window", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100627 pool = zlib_pool_window;
628 ctx->zlib_window = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100629 break;
630
631 case 2:
632 if (zlib_pool_prev == NULL)
633 zlib_pool_prev = create_pool("zlib_prev", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100634 pool = zlib_pool_prev;
635 ctx->zlib_prev = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100636 break;
637
638 case 3:
639 if (zlib_pool_head == NULL)
640 zlib_pool_head = create_pool("zlib_head", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100641 pool = zlib_pool_head;
642 ctx->zlib_head = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100643 break;
644
645 case 4:
646 if (zlib_pool_pending_buf == NULL)
647 zlib_pool_pending_buf = create_pool("zlib_pending_buf", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100648 pool = zlib_pool_pending_buf;
649 ctx->zlib_pending_buf = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100650 break;
651 }
William Lallemande3a7d992012-11-20 11:25:20 +0100652 if (buf != NULL)
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100653 zlib_used_memory += pool->size;
William Lallemand9d5f5482012-11-07 16:12:57 +0100654
655end:
William Lallemand2b502472012-10-30 14:30:39 +0100656
Willy Tarreau46909852012-11-15 14:57:56 +0100657 /* deflateInit2() first allocates and checks the deflate_state, then if
658 * it succeeds, it allocates all other 4 areas at ones and checks them
659 * at the end. So we want to correctly count the rounds depending on when
660 * zlib is supposed to abort.
661 */
662 if (buf || round)
663 round = (round + 1) % 5;
William Lallemand2b502472012-10-30 14:30:39 +0100664 return buf;
665}
666
667static void free_zlib(void *opaque, void *ptr)
668{
669 struct comp_ctx *ctx = opaque;
Willy Tarreaub1fbd052012-11-10 17:49:37 +0100670 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100671
672 if (ptr == ctx->zlib_window)
William Lallemand9d5f5482012-11-07 16:12:57 +0100673 pool = zlib_pool_window;
William Lallemand2b502472012-10-30 14:30:39 +0100674 else if (ptr == ctx->zlib_deflate_state)
William Lallemand9d5f5482012-11-07 16:12:57 +0100675 pool = zlib_pool_deflate_state;
William Lallemand2b502472012-10-30 14:30:39 +0100676 else if (ptr == ctx->zlib_prev)
William Lallemand9d5f5482012-11-07 16:12:57 +0100677 pool = zlib_pool_prev;
William Lallemand2b502472012-10-30 14:30:39 +0100678 else if (ptr == ctx->zlib_head)
William Lallemand9d5f5482012-11-07 16:12:57 +0100679 pool = zlib_pool_head;
William Lallemand2b502472012-10-30 14:30:39 +0100680 else if (ptr == ctx->zlib_pending_buf)
William Lallemand9d5f5482012-11-07 16:12:57 +0100681 pool = zlib_pool_pending_buf;
William Lallemand2b502472012-10-30 14:30:39 +0100682
William Lallemand9d5f5482012-11-07 16:12:57 +0100683 pool_free2(pool, ptr);
William Lallemande3a7d992012-11-20 11:25:20 +0100684 zlib_used_memory -= pool->size;
William Lallemand2b502472012-10-30 14:30:39 +0100685}
686
William Lallemand82fe75c2012-10-23 10:25:10 +0200687/**************************
688**** gzip algorithm ****
689***************************/
Willy Tarreau9f640a12015-03-28 15:46:00 +0100690static int gzip_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200691{
William Lallemand8b52bb32012-11-16 18:06:41 +0100692 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200693
William Lallemand8b52bb32012-11-16 18:06:41 +0100694 if (init_comp_ctx(comp_ctx) < 0)
695 return -1;
William Lallemand9d5f5482012-11-07 16:12:57 +0100696
William Lallemand8b52bb32012-11-16 18:06:41 +0100697 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200698
William Lallemand8b52bb32012-11-16 18:06:41 +0100699 if (deflateInit2(strm, level, Z_DEFLATED, global.tune.zlibwindowsize + 16, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
700 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200701 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100702 }
703
704 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200705
706 return 0;
707}
Willy Tarreauc91840a2015-03-28 17:00:39 +0100708
709/* Raw deflate algorithm */
710static int raw_def_init(struct comp_ctx **comp_ctx, int level)
711{
712 z_stream *strm;
713
714 if (init_comp_ctx(comp_ctx) < 0)
715 return -1;
716
717 strm = &(*comp_ctx)->strm;
718
719 if (deflateInit2(strm, level, Z_DEFLATED, -global.tune.zlibwindowsize, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
720 deinit_comp_ctx(comp_ctx);
721 return -1;
722 }
723
724 (*comp_ctx)->cur_lvl = level;
725 return 0;
726}
727
William Lallemand82fe75c2012-10-23 10:25:10 +0200728/**************************
729**** Deflate algorithm ****
730***************************/
731
Willy Tarreau9f640a12015-03-28 15:46:00 +0100732static int deflate_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200733{
William Lallemand8b52bb32012-11-16 18:06:41 +0100734 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200735
William Lallemand8b52bb32012-11-16 18:06:41 +0100736 if (init_comp_ctx(comp_ctx) < 0)
737 return -1;
738
739 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200740
Willy Tarreauc5599e72013-04-28 08:52:52 +0200741 if (deflateInit2(strm, level, Z_DEFLATED, global.tune.zlibwindowsize, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
William Lallemand8b52bb32012-11-16 18:06:41 +0100742 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200743 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100744 }
745
746 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200747
748 return 0;
749}
750
William Lallemandbf3ae612012-11-19 12:35:37 +0100751/* Return the size of consumed data or -1 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100752static int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200753{
William Lallemand82fe75c2012-10-23 10:25:10 +0200754 int ret;
William Lallemandbf3ae612012-11-19 12:35:37 +0100755 z_stream *strm = &comp_ctx->strm;
756 char *out_data = bi_end(out);
757 int out_len = out->size - buffer_len(out);
William Lallemand82fe75c2012-10-23 10:25:10 +0200758
759 if (in_len <= 0)
760 return 0;
761
762
763 if (out_len <= 0)
764 return -1;
765
William Lallemand82fe75c2012-10-23 10:25:10 +0200766 strm->next_in = (unsigned char *)in_data;
767 strm->avail_in = in_len;
768 strm->next_out = (unsigned char *)out_data;
769 strm->avail_out = out_len;
770
771 ret = deflate(strm, Z_NO_FLUSH);
772 if (ret != Z_OK)
773 return -1;
774
775 /* deflate update the available data out */
William Lallemandbf3ae612012-11-19 12:35:37 +0100776 out->i += out_len - strm->avail_out;
William Lallemand82fe75c2012-10-23 10:25:10 +0200777
William Lallemandbf3ae612012-11-19 12:35:37 +0100778 return in_len - strm->avail_in;
William Lallemand82fe75c2012-10-23 10:25:10 +0200779}
780
Willy Tarreau9787efa2015-03-28 19:17:31 +0100781static int deflate_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int flag)
William Lallemand82fe75c2012-10-23 10:25:10 +0200782{
783 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200784 int out_len = 0;
William Lallemand1c2d6222012-10-30 15:52:53 +0100785 z_stream *strm = &comp_ctx->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200786
William Lallemand82fe75c2012-10-23 10:25:10 +0200787 strm->next_out = (unsigned char *)bi_end(out);
788 strm->avail_out = out->size - buffer_len(out);
789
790 ret = deflate(strm, flag);
791 if (ret != Z_OK && ret != Z_STREAM_END)
792 return -1;
793
794 out_len = (out->size - buffer_len(out)) - strm->avail_out;
795 out->i += out_len;
796
William Lallemand072a2bf2012-11-20 17:01:01 +0100797 /* compression limit */
798 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
799 (idle_pct < compress_min_idle)) { /* idle */
800 /* decrease level */
801 if (comp_ctx->cur_lvl > 0) {
802 comp_ctx->cur_lvl--;
William Lallemandd85f9172012-11-09 17:05:39 +0100803 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
804 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100805
806 } else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel) {
807 /* increase level */
808 comp_ctx->cur_lvl++ ;
809 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
William Lallemandd85f9172012-11-09 17:05:39 +0100810 }
811
William Lallemand82fe75c2012-10-23 10:25:10 +0200812 return out_len;
813}
814
Willy Tarreau9787efa2015-03-28 19:17:31 +0100815static int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out)
816{
817 return deflate_flush_or_finish(comp_ctx, out, Z_SYNC_FLUSH);
818}
819
820static int deflate_finish(struct comp_ctx *comp_ctx, struct buffer *out)
821{
822 return deflate_flush_or_finish(comp_ctx, out, Z_FINISH);
823}
824
Willy Tarreau9f640a12015-03-28 15:46:00 +0100825static int deflate_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200826{
William Lallemand8b52bb32012-11-16 18:06:41 +0100827 z_stream *strm = &(*comp_ctx)->strm;
828 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200829
William Lallemand8b52bb32012-11-16 18:06:41 +0100830 ret = deflateEnd(strm);
William Lallemand82fe75c2012-10-23 10:25:10 +0200831
William Lallemand8b52bb32012-11-16 18:06:41 +0100832 deinit_comp_ctx(comp_ctx);
833
834 return ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200835}
836
837#endif /* USE_ZLIB */
838
William Lallemand727db8b2013-04-20 17:33:20 +0200839/* boolean, returns true if compression is used (either gzip or deflate) in the response */
840static int
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +0200841smp_fetch_res_comp(unsigned int opt, const struct arg *args, struct sample *smp,
842 const char *kw, void *private)
William Lallemand727db8b2013-04-20 17:33:20 +0200843{
844 smp->type = SMP_T_BOOL;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +0200845 smp->data.uint = (smp->strm->comp_algo != NULL);
William Lallemand727db8b2013-04-20 17:33:20 +0200846 return 1;
847}
848
849/* string, returns algo */
850static int
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +0200851smp_fetch_res_comp_algo(unsigned int opt, const struct arg *args, struct sample *smp,
852 const char *kw, void *private)
William Lallemand727db8b2013-04-20 17:33:20 +0200853{
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +0200854 if (!smp->strm->comp_algo)
William Lallemand727db8b2013-04-20 17:33:20 +0200855 return 0;
856
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100857 smp->type = SMP_T_STR;
858 smp->flags = SMP_F_CONST;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +0200859 smp->data.str.str = smp->strm->comp_algo->cfg_name;
860 smp->data.str.len = smp->strm->comp_algo->cfg_name_len;
William Lallemand727db8b2013-04-20 17:33:20 +0200861 return 1;
862}
863
864/* Note: must not be declared <const> as its list will be overwritten */
Willy Tarreaudc13c112013-06-21 23:16:39 +0200865static struct acl_kw_list acl_kws = {ILH, {
Willy Tarreau7f6fa692013-04-23 19:39:43 +0200866 { /* END */ },
William Lallemand727db8b2013-04-20 17:33:20 +0200867}};
868
869/* Note: must not be declared <const> as its list will be overwritten */
Willy Tarreaudc13c112013-06-21 23:16:39 +0200870static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
William Lallemand727db8b2013-04-20 17:33:20 +0200871 { "res.comp", smp_fetch_res_comp, 0, NULL, SMP_T_BOOL, SMP_USE_HRSHP },
872 { "res.comp_algo", smp_fetch_res_comp_algo, 0, NULL, SMP_T_STR, SMP_USE_HRSHP },
873 { /* END */ },
874}};
875
876__attribute__((constructor))
877static void __comp_fetch_init(void)
878{
Willy Tarreau418b8c02015-03-29 03:32:06 +0200879#ifdef USE_SLZ
880 slz_make_crc_table();
881 slz_prepare_dist_table();
882#endif
William Lallemand727db8b2013-04-20 17:33:20 +0200883 acl_register_keywords(&acl_kws);
884 sample_register_fetches(&sample_fetch_keywords);
885}