blob: ecd2fa5a3cf1a0d289f53101446751663236aeaf [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
Willy Tarreau36878032016-12-22 19:46:17 +010029#include <common/cfgparse.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020030#include <common/compat.h>
William Lallemand2b502472012-10-30 14:30:39 +010031#include <common/memory.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020032
33#include <types/global.h>
34#include <types/compression.h>
35
William Lallemand727db8b2013-04-20 17:33:20 +020036#include <proto/acl.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020037#include <proto/compression.h>
William Lallemandd85f9172012-11-09 17:05:39 +010038#include <proto/freq_ctr.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020039#include <proto/proto_http.h>
Willy Tarreaue36cbcb2015-04-03 15:40:56 +020040#include <proto/stream.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020041
William Lallemand2b502472012-10-30 14:30:39 +010042
43#ifdef USE_ZLIB
44
William Lallemand8b52bb32012-11-16 18:06:41 +010045static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size);
46static void free_zlib(void *opaque, void *ptr);
47
William Lallemand2b502472012-10-30 14:30:39 +010048/* zlib allocation */
49static struct pool_head *zlib_pool_deflate_state = NULL;
50static struct pool_head *zlib_pool_window = NULL;
51static struct pool_head *zlib_pool_prev = NULL;
52static struct pool_head *zlib_pool_head = NULL;
53static struct pool_head *zlib_pool_pending_buf = NULL;
54
William Lallemande3a7d992012-11-20 11:25:20 +010055long zlib_used_memory = 0;
William Lallemand9d5f5482012-11-07 16:12:57 +010056
Willy Tarreau36878032016-12-22 19:46:17 +010057static int global_tune_zlibmemlevel = 8; /* zlib memlevel */
58static int global_tune_zlibwindowsize = MAX_WBITS; /* zlib window size */
59
William Lallemand2b502472012-10-30 14:30:39 +010060#endif
61
William Lallemand072a2bf2012-11-20 17:01:01 +010062unsigned int compress_min_idle = 0;
William Lallemand8b52bb32012-11-16 18:06:41 +010063
Willy Tarreau9f640a12015-03-28 15:46:00 +010064static int identity_init(struct comp_ctx **comp_ctx, int level);
65static 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 +010066static int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out);
67static int identity_finish(struct comp_ctx *comp_ctx, struct buffer *out);
Willy Tarreau9f640a12015-03-28 15:46:00 +010068static int identity_end(struct comp_ctx **comp_ctx);
69
Willy Tarreau418b8c02015-03-29 03:32:06 +020070#if defined(USE_SLZ)
71
72static int rfc1950_init(struct comp_ctx **comp_ctx, int level);
73static int rfc1951_init(struct comp_ctx **comp_ctx, int level);
74static int rfc1952_init(struct comp_ctx **comp_ctx, int level);
75static int rfc195x_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
76static int rfc195x_flush(struct comp_ctx *comp_ctx, struct buffer *out);
77static int rfc195x_finish(struct comp_ctx *comp_ctx, struct buffer *out);
78static int rfc195x_end(struct comp_ctx **comp_ctx);
79
80#elif defined(USE_ZLIB)
Willy Tarreau7b218772015-03-28 22:08:25 +010081
Willy Tarreau9f640a12015-03-28 15:46:00 +010082static int gzip_init(struct comp_ctx **comp_ctx, int level);
Willy Tarreauc91840a2015-03-28 17:00:39 +010083static int raw_def_init(struct comp_ctx **comp_ctx, int level);
Willy Tarreau9f640a12015-03-28 15:46:00 +010084static int deflate_init(struct comp_ctx **comp_ctx, int level);
85static 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 +010086static int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out);
87static int deflate_finish(struct comp_ctx *comp_ctx, struct buffer *out);
Willy Tarreau9f640a12015-03-28 15:46:00 +010088static int deflate_end(struct comp_ctx **comp_ctx);
Willy Tarreau7b218772015-03-28 22:08:25 +010089
Willy Tarreau9f640a12015-03-28 15:46:00 +010090#endif /* USE_ZLIB */
91
William Lallemand2b502472012-10-30 14:30:39 +010092
Cyril Bonté6162c432012-11-10 19:27:47 +010093const struct comp_algo comp_algos[] =
William Lallemand82fe75c2012-10-23 10:25:10 +020094{
Willy Tarreau7b218772015-03-28 22:08:25 +010095 { "identity", 8, "identity", 8, identity_init, identity_add_data, identity_flush, identity_finish, identity_end },
Willy Tarreau418b8c02015-03-29 03:32:06 +020096#if defined(USE_SLZ)
97 { "deflate", 7, "deflate", 7, rfc1950_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
98 { "raw-deflate", 11, "deflate", 7, rfc1951_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
99 { "gzip", 4, "gzip", 4, rfc1952_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
100#elif defined(USE_ZLIB)
Willy Tarreau7b218772015-03-28 22:08:25 +0100101 { "deflate", 7, "deflate", 7, deflate_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
102 { "raw-deflate", 11, "deflate", 7, raw_def_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
103 { "gzip", 4, "gzip", 4, gzip_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
William Lallemand82fe75c2012-10-23 10:25:10 +0200104#endif /* USE_ZLIB */
Willy Tarreau615105e2015-03-28 16:40:46 +0100105 { NULL, 0, NULL, 0, NULL , NULL, NULL, NULL, NULL }
William Lallemand82fe75c2012-10-23 10:25:10 +0200106};
107
108/*
109 * Add a content-type in the configuration
110 */
111int comp_append_type(struct comp *comp, const char *type)
112{
113 struct comp_type *comp_type;
114
Vincent Bernat02779b62016-04-03 13:48:43 +0200115 comp_type = calloc(1, sizeof(*comp_type));
William Lallemand82fe75c2012-10-23 10:25:10 +0200116 comp_type->name_len = strlen(type);
117 comp_type->name = strdup(type);
118 comp_type->next = comp->types;
119 comp->types = comp_type;
120 return 0;
121}
122
123/*
124 * Add an algorithm in the configuration
125 */
126int comp_append_algo(struct comp *comp, const char *algo)
127{
128 struct comp_algo *comp_algo;
129 int i;
130
Willy Tarreau615105e2015-03-28 16:40:46 +0100131 for (i = 0; comp_algos[i].cfg_name; i++) {
132 if (!strcmp(algo, comp_algos[i].cfg_name)) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200133 comp_algo = calloc(1, sizeof(*comp_algo));
William Lallemand82fe75c2012-10-23 10:25:10 +0200134 memmove(comp_algo, &comp_algos[i], sizeof(struct comp_algo));
135 comp_algo->next = comp->algos;
136 comp->algos = comp_algo;
137 return 0;
138 }
139 }
140 return -1;
141}
142
Willy Tarreaue1cc4b52016-08-10 21:17:06 +0200143#if defined(USE_ZLIB) || defined(USE_SLZ)
144static struct pool_head *pool_comp_ctx = NULL;
William Lallemand8b52bb32012-11-16 18:06:41 +0100145/*
146 * Alloc the comp_ctx
147 */
148static inline int init_comp_ctx(struct comp_ctx **comp_ctx)
149{
150#ifdef USE_ZLIB
151 z_stream *strm;
152
William Lallemande3a7d992012-11-20 11:25:20 +0100153 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < sizeof(struct comp_ctx))
William Lallemand8b52bb32012-11-16 18:06:41 +0100154 return -1;
155#endif
156
157 if (unlikely(pool_comp_ctx == NULL))
158 pool_comp_ctx = create_pool("comp_ctx", sizeof(struct comp_ctx), MEM_F_SHARED);
159
160 *comp_ctx = pool_alloc2(pool_comp_ctx);
161 if (*comp_ctx == NULL)
162 return -1;
Willy Tarreau418b8c02015-03-29 03:32:06 +0200163#if defined(USE_SLZ)
164 (*comp_ctx)->direct_ptr = NULL;
165 (*comp_ctx)->direct_len = 0;
166 (*comp_ctx)->queued = NULL;
167#elif defined(USE_ZLIB)
William Lallemande3a7d992012-11-20 11:25:20 +0100168 zlib_used_memory += sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100169
170 strm = &(*comp_ctx)->strm;
171 strm->zalloc = alloc_zlib;
172 strm->zfree = free_zlib;
173 strm->opaque = *comp_ctx;
174#endif
175 return 0;
176}
177
178/*
179 * Dealloc the comp_ctx
180 */
181static inline int deinit_comp_ctx(struct comp_ctx **comp_ctx)
182{
183 if (!*comp_ctx)
184 return 0;
185
186 pool_free2(pool_comp_ctx, *comp_ctx);
187 *comp_ctx = NULL;
188
189#ifdef USE_ZLIB
William Lallemande3a7d992012-11-20 11:25:20 +0100190 zlib_used_memory -= sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100191#endif
William Lallemand8b52bb32012-11-16 18:06:41 +0100192 return 0;
193}
Willy Tarreaue1cc4b52016-08-10 21:17:06 +0200194#endif
William Lallemand8b52bb32012-11-16 18:06:41 +0100195
William Lallemand82fe75c2012-10-23 10:25:10 +0200196
197/****************************
198 **** Identity algorithm ****
199 ****************************/
200
201/*
202 * Init the identity algorithm
203 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100204static int identity_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200205{
206 return 0;
207}
208
209/*
210 * Process data
William Lallemandbf3ae612012-11-19 12:35:37 +0100211 * Return size of consumed data or -1 on error
William Lallemand82fe75c2012-10-23 10:25:10 +0200212 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100213static 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 +0200214{
William Lallemandbf3ae612012-11-19 12:35:37 +0100215 char *out_data = bi_end(out);
216 int out_len = out->size - buffer_len(out);
217
William Lallemand82fe75c2012-10-23 10:25:10 +0200218 if (out_len < in_len)
219 return -1;
220
221 memcpy(out_data, in_data, in_len);
222
William Lallemandbf3ae612012-11-19 12:35:37 +0100223 out->i += in_len;
224
William Lallemand82fe75c2012-10-23 10:25:10 +0200225 return in_len;
226}
227
Willy Tarreau9787efa2015-03-28 19:17:31 +0100228static int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200229{
230 return 0;
231}
232
Willy Tarreau9787efa2015-03-28 19:17:31 +0100233static int identity_finish(struct comp_ctx *comp_ctx, struct buffer *out)
234{
235 return 0;
236}
237
Willy Tarreau418b8c02015-03-29 03:32:06 +0200238/*
239 * Deinit the algorithm
240 */
241static int identity_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200242{
243 return 0;
244}
245
Willy Tarreau418b8c02015-03-29 03:32:06 +0200246
247#ifdef USE_SLZ
248
249/* SLZ's gzip format (RFC1952). Returns < 0 on error. */
250static int rfc1952_init(struct comp_ctx **comp_ctx, int level)
251{
252 if (init_comp_ctx(comp_ctx) < 0)
253 return -1;
254
255 (*comp_ctx)->cur_lvl = !!level;
256 return slz_rfc1952_init(&(*comp_ctx)->strm, !!level);
257}
258
259/* SLZ's raw deflate format (RFC1951). Returns < 0 on error. */
260static int rfc1951_init(struct comp_ctx **comp_ctx, int level)
261{
262 if (init_comp_ctx(comp_ctx) < 0)
263 return -1;
264
265 (*comp_ctx)->cur_lvl = !!level;
266 return slz_rfc1951_init(&(*comp_ctx)->strm, !!level);
267}
268
269/* SLZ's zlib format (RFC1950). Returns < 0 on error. */
270static int rfc1950_init(struct comp_ctx **comp_ctx, int level)
271{
272 if (init_comp_ctx(comp_ctx) < 0)
273 return -1;
274
275 (*comp_ctx)->cur_lvl = !!level;
276 return slz_rfc1950_init(&(*comp_ctx)->strm, !!level);
277}
278
279/* Return the size of consumed data or -1. The output buffer is unused at this
280 * point, we only keep a reference to the input data or a copy of them if the
281 * reference is already used.
William Lallemand82fe75c2012-10-23 10:25:10 +0200282 */
Willy Tarreau418b8c02015-03-29 03:32:06 +0200283static 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 +0200284{
Willy Tarreau418b8c02015-03-29 03:32:06 +0200285 static struct buffer *tmpbuf = &buf_empty;
286
287 if (in_len <= 0)
288 return 0;
289
290 if (comp_ctx->direct_ptr && !comp_ctx->queued) {
291 /* data already being pointed to, we're in front of fragmented
292 * data and need a buffer now. We reuse the same buffer, as it's
293 * not used out of the scope of a series of add_data()*, end().
294 */
295 if (unlikely(!tmpbuf->size)) {
296 /* this is the first time we need the compression buffer */
297 if (b_alloc(&tmpbuf) == NULL)
298 return -1; /* no memory */
299 }
300 b_reset(tmpbuf);
301 memcpy(bi_end(tmpbuf), comp_ctx->direct_ptr, comp_ctx->direct_len);
302 tmpbuf->i += comp_ctx->direct_len;
303 comp_ctx->direct_ptr = NULL;
304 comp_ctx->direct_len = 0;
305 comp_ctx->queued = tmpbuf;
306 /* fall through buffer copy */
307 }
308
309 if (comp_ctx->queued) {
310 /* data already pending */
311 memcpy(bi_end(comp_ctx->queued), in_data, in_len);
312 comp_ctx->queued->i += in_len;
313 return in_len;
314 }
315
316 comp_ctx->direct_ptr = in_data;
317 comp_ctx->direct_len = in_len;
318 return in_len;
319}
320
321/* Compresses the data accumulated using add_data(), and optionally sends the
322 * format-specific trailer if <finish> is non-null. <out> is expected to have a
323 * large enough free non-wrapping space as verified by http_comp_buffer_init().
324 * The number of bytes emitted is reported.
325 */
326static int rfc195x_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int finish)
327{
328 struct slz_stream *strm = &comp_ctx->strm;
329 const char *in_ptr;
330 int in_len;
331 int out_len;
332
333 in_ptr = comp_ctx->direct_ptr;
334 in_len = comp_ctx->direct_len;
335
336 if (comp_ctx->queued) {
337 in_ptr = comp_ctx->queued->p;
338 in_len = comp_ctx->queued->i;
339 }
340
341 out_len = out->i;
342
343 if (in_ptr)
344 out->i += slz_encode(strm, bi_end(out), in_ptr, in_len, !finish);
345
346 if (finish)
347 out->i += slz_finish(strm, bi_end(out));
348
349 out_len = out->i - out_len;
350
351 /* very important, we must wipe the data we've just flushed */
352 comp_ctx->direct_len = 0;
353 comp_ctx->direct_ptr = NULL;
354 comp_ctx->queued = NULL;
355
356 /* Verify compression rate limiting and CPU usage */
357 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
358 (idle_pct < compress_min_idle)) { /* idle */
359 if (comp_ctx->cur_lvl > 0)
360 strm->level = --comp_ctx->cur_lvl;
361 }
362 else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel && comp_ctx->cur_lvl < 1) {
363 strm->level = ++comp_ctx->cur_lvl;
364 }
365
366 /* and that's all */
367 return out_len;
368}
369
370static int rfc195x_flush(struct comp_ctx *comp_ctx, struct buffer *out)
371{
372 return rfc195x_flush_or_finish(comp_ctx, out, 0);
373}
374
375static int rfc195x_finish(struct comp_ctx *comp_ctx, struct buffer *out)
376{
377 return rfc195x_flush_or_finish(comp_ctx, out, 1);
378}
379
380/* we just need to free the comp_ctx here, nothing was allocated */
381static int rfc195x_end(struct comp_ctx **comp_ctx)
382{
383 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200384 return 0;
385}
386
Willy Tarreau418b8c02015-03-29 03:32:06 +0200387#elif defined(USE_ZLIB) /* ! USE_SLZ */
William Lallemand82fe75c2012-10-23 10:25:10 +0200388
William Lallemand2b502472012-10-30 14:30:39 +0100389/*
390 * This is a tricky allocation function using the zlib.
391 * This is based on the allocation order in deflateInit2.
392 */
393static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
394{
395 struct comp_ctx *ctx = opaque;
396 static char round = 0; /* order in deflateInit2 */
397 void *buf = NULL;
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100398 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100399
William Lallemande3a7d992012-11-20 11:25:20 +0100400 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < (long)(items * size))
William Lallemand9d5f5482012-11-07 16:12:57 +0100401 goto end;
William Lallemand9d5f5482012-11-07 16:12:57 +0100402
William Lallemand2b502472012-10-30 14:30:39 +0100403 switch (round) {
404 case 0:
405 if (zlib_pool_deflate_state == NULL)
406 zlib_pool_deflate_state = create_pool("zlib_state", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100407 pool = zlib_pool_deflate_state;
408 ctx->zlib_deflate_state = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100409 break;
410
411 case 1:
412 if (zlib_pool_window == NULL)
413 zlib_pool_window = create_pool("zlib_window", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100414 pool = zlib_pool_window;
415 ctx->zlib_window = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100416 break;
417
418 case 2:
419 if (zlib_pool_prev == NULL)
420 zlib_pool_prev = create_pool("zlib_prev", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100421 pool = zlib_pool_prev;
422 ctx->zlib_prev = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100423 break;
424
425 case 3:
426 if (zlib_pool_head == NULL)
427 zlib_pool_head = create_pool("zlib_head", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100428 pool = zlib_pool_head;
429 ctx->zlib_head = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100430 break;
431
432 case 4:
433 if (zlib_pool_pending_buf == NULL)
434 zlib_pool_pending_buf = create_pool("zlib_pending_buf", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100435 pool = zlib_pool_pending_buf;
436 ctx->zlib_pending_buf = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100437 break;
438 }
William Lallemande3a7d992012-11-20 11:25:20 +0100439 if (buf != NULL)
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100440 zlib_used_memory += pool->size;
William Lallemand9d5f5482012-11-07 16:12:57 +0100441
442end:
William Lallemand2b502472012-10-30 14:30:39 +0100443
Willy Tarreau46909852012-11-15 14:57:56 +0100444 /* deflateInit2() first allocates and checks the deflate_state, then if
445 * it succeeds, it allocates all other 4 areas at ones and checks them
446 * at the end. So we want to correctly count the rounds depending on when
447 * zlib is supposed to abort.
448 */
449 if (buf || round)
450 round = (round + 1) % 5;
William Lallemand2b502472012-10-30 14:30:39 +0100451 return buf;
452}
453
454static void free_zlib(void *opaque, void *ptr)
455{
456 struct comp_ctx *ctx = opaque;
Willy Tarreaub1fbd052012-11-10 17:49:37 +0100457 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100458
459 if (ptr == ctx->zlib_window)
William Lallemand9d5f5482012-11-07 16:12:57 +0100460 pool = zlib_pool_window;
William Lallemand2b502472012-10-30 14:30:39 +0100461 else if (ptr == ctx->zlib_deflate_state)
William Lallemand9d5f5482012-11-07 16:12:57 +0100462 pool = zlib_pool_deflate_state;
William Lallemand2b502472012-10-30 14:30:39 +0100463 else if (ptr == ctx->zlib_prev)
William Lallemand9d5f5482012-11-07 16:12:57 +0100464 pool = zlib_pool_prev;
William Lallemand2b502472012-10-30 14:30:39 +0100465 else if (ptr == ctx->zlib_head)
William Lallemand9d5f5482012-11-07 16:12:57 +0100466 pool = zlib_pool_head;
William Lallemand2b502472012-10-30 14:30:39 +0100467 else if (ptr == ctx->zlib_pending_buf)
William Lallemand9d5f5482012-11-07 16:12:57 +0100468 pool = zlib_pool_pending_buf;
William Lallemand2b502472012-10-30 14:30:39 +0100469
William Lallemand9d5f5482012-11-07 16:12:57 +0100470 pool_free2(pool, ptr);
William Lallemande3a7d992012-11-20 11:25:20 +0100471 zlib_used_memory -= pool->size;
William Lallemand2b502472012-10-30 14:30:39 +0100472}
473
William Lallemand82fe75c2012-10-23 10:25:10 +0200474/**************************
475**** gzip algorithm ****
476***************************/
Willy Tarreau9f640a12015-03-28 15:46:00 +0100477static int gzip_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200478{
William Lallemand8b52bb32012-11-16 18:06:41 +0100479 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200480
William Lallemand8b52bb32012-11-16 18:06:41 +0100481 if (init_comp_ctx(comp_ctx) < 0)
482 return -1;
William Lallemand9d5f5482012-11-07 16:12:57 +0100483
William Lallemand8b52bb32012-11-16 18:06:41 +0100484 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200485
Willy Tarreau36878032016-12-22 19:46:17 +0100486 if (deflateInit2(strm, level, Z_DEFLATED, global_tune_zlibwindowsize + 16, global_tune_zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
William Lallemand8b52bb32012-11-16 18:06:41 +0100487 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200488 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100489 }
490
491 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200492
493 return 0;
494}
Willy Tarreauc91840a2015-03-28 17:00:39 +0100495
496/* Raw deflate algorithm */
497static int raw_def_init(struct comp_ctx **comp_ctx, int level)
498{
499 z_stream *strm;
500
501 if (init_comp_ctx(comp_ctx) < 0)
502 return -1;
503
504 strm = &(*comp_ctx)->strm;
505
Willy Tarreau36878032016-12-22 19:46:17 +0100506 if (deflateInit2(strm, level, Z_DEFLATED, -global_tune_zlibwindowsize, global_tune_zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
Willy Tarreauc91840a2015-03-28 17:00:39 +0100507 deinit_comp_ctx(comp_ctx);
508 return -1;
509 }
510
511 (*comp_ctx)->cur_lvl = level;
512 return 0;
513}
514
William Lallemand82fe75c2012-10-23 10:25:10 +0200515/**************************
516**** Deflate algorithm ****
517***************************/
518
Willy Tarreau9f640a12015-03-28 15:46:00 +0100519static int deflate_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200520{
William Lallemand8b52bb32012-11-16 18:06:41 +0100521 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200522
William Lallemand8b52bb32012-11-16 18:06:41 +0100523 if (init_comp_ctx(comp_ctx) < 0)
524 return -1;
525
526 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200527
Willy Tarreau36878032016-12-22 19:46:17 +0100528 if (deflateInit2(strm, level, Z_DEFLATED, global_tune_zlibwindowsize, global_tune_zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
William Lallemand8b52bb32012-11-16 18:06:41 +0100529 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200530 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100531 }
532
533 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200534
535 return 0;
536}
537
William Lallemandbf3ae612012-11-19 12:35:37 +0100538/* Return the size of consumed data or -1 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100539static 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 +0200540{
William Lallemand82fe75c2012-10-23 10:25:10 +0200541 int ret;
William Lallemandbf3ae612012-11-19 12:35:37 +0100542 z_stream *strm = &comp_ctx->strm;
543 char *out_data = bi_end(out);
544 int out_len = out->size - buffer_len(out);
William Lallemand82fe75c2012-10-23 10:25:10 +0200545
546 if (in_len <= 0)
547 return 0;
548
549
550 if (out_len <= 0)
551 return -1;
552
William Lallemand82fe75c2012-10-23 10:25:10 +0200553 strm->next_in = (unsigned char *)in_data;
554 strm->avail_in = in_len;
555 strm->next_out = (unsigned char *)out_data;
556 strm->avail_out = out_len;
557
558 ret = deflate(strm, Z_NO_FLUSH);
559 if (ret != Z_OK)
560 return -1;
561
562 /* deflate update the available data out */
William Lallemandbf3ae612012-11-19 12:35:37 +0100563 out->i += out_len - strm->avail_out;
William Lallemand82fe75c2012-10-23 10:25:10 +0200564
William Lallemandbf3ae612012-11-19 12:35:37 +0100565 return in_len - strm->avail_in;
William Lallemand82fe75c2012-10-23 10:25:10 +0200566}
567
Willy Tarreau9787efa2015-03-28 19:17:31 +0100568static int deflate_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int flag)
William Lallemand82fe75c2012-10-23 10:25:10 +0200569{
570 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200571 int out_len = 0;
William Lallemand1c2d6222012-10-30 15:52:53 +0100572 z_stream *strm = &comp_ctx->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200573
Willy Tarreaud8b8b532016-08-08 16:41:01 +0200574 strm->next_in = NULL;
575 strm->avail_in = 0;
William Lallemand82fe75c2012-10-23 10:25:10 +0200576 strm->next_out = (unsigned char *)bi_end(out);
577 strm->avail_out = out->size - buffer_len(out);
578
579 ret = deflate(strm, flag);
580 if (ret != Z_OK && ret != Z_STREAM_END)
581 return -1;
582
583 out_len = (out->size - buffer_len(out)) - strm->avail_out;
584 out->i += out_len;
585
William Lallemand072a2bf2012-11-20 17:01:01 +0100586 /* compression limit */
587 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
588 (idle_pct < compress_min_idle)) { /* idle */
589 /* decrease level */
590 if (comp_ctx->cur_lvl > 0) {
591 comp_ctx->cur_lvl--;
William Lallemandd85f9172012-11-09 17:05:39 +0100592 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
593 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100594
595 } else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel) {
596 /* increase level */
597 comp_ctx->cur_lvl++ ;
598 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
William Lallemandd85f9172012-11-09 17:05:39 +0100599 }
600
William Lallemand82fe75c2012-10-23 10:25:10 +0200601 return out_len;
602}
603
Willy Tarreau9787efa2015-03-28 19:17:31 +0100604static int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out)
605{
606 return deflate_flush_or_finish(comp_ctx, out, Z_SYNC_FLUSH);
607}
608
609static int deflate_finish(struct comp_ctx *comp_ctx, struct buffer *out)
610{
611 return deflate_flush_or_finish(comp_ctx, out, Z_FINISH);
612}
613
Willy Tarreau9f640a12015-03-28 15:46:00 +0100614static int deflate_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200615{
William Lallemand8b52bb32012-11-16 18:06:41 +0100616 z_stream *strm = &(*comp_ctx)->strm;
617 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200618
William Lallemand8b52bb32012-11-16 18:06:41 +0100619 ret = deflateEnd(strm);
William Lallemand82fe75c2012-10-23 10:25:10 +0200620
William Lallemand8b52bb32012-11-16 18:06:41 +0100621 deinit_comp_ctx(comp_ctx);
622
623 return ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200624}
625
Willy Tarreau36878032016-12-22 19:46:17 +0100626/* config parser for global "tune.zlibmemlevel" */
627static int zlib_parse_global_memlevel(char **args, int section_type, struct proxy *curpx,
628 struct proxy *defpx, const char *file, int line,
629 char **err)
630{
631 if (too_many_args(1, args, err, NULL))
632 return -1;
633
634 if (*(args[1]) == 0) {
635 memprintf(err, "'%s' expects a numeric value between 1 and 9.", args[0]);
636 return -1;
637 }
638
639 global_tune_zlibmemlevel = atoi(args[1]);
640 if (global_tune_zlibmemlevel < 1 || global_tune_zlibmemlevel > 9) {
641 memprintf(err, "'%s' expects a numeric value between 1 and 9.", args[0]);
642 return -1;
643 }
644 return 0;
645}
646
647
648/* config parser for global "tune.zlibwindowsize" */
649static int zlib_parse_global_windowsize(char **args, int section_type, struct proxy *curpx,
650 struct proxy *defpx, const char *file, int line,
651 char **err)
652{
653 if (too_many_args(1, args, err, NULL))
654 return -1;
655
656 if (*(args[1]) == 0) {
657 memprintf(err, "'%s' expects a numeric value between 8 and 15.", args[0]);
658 return -1;
659 }
660
661 global_tune_zlibwindowsize = atoi(args[1]);
662 if (global_tune_zlibwindowsize < 8 || global_tune_zlibwindowsize > 15) {
663 memprintf(err, "'%s' expects a numeric value between 8 and 15.", args[0]);
664 return -1;
665 }
666 return 0;
667}
668
William Lallemand82fe75c2012-10-23 10:25:10 +0200669#endif /* USE_ZLIB */
670
Willy Tarreau36878032016-12-22 19:46:17 +0100671
672/* config keyword parsers */
673static struct cfg_kw_list cfg_kws = {ILH, {
674#ifdef USE_ZLIB
675 { CFG_GLOBAL, "tune.zlib.memlevel", zlib_parse_global_memlevel },
676 { CFG_GLOBAL, "tune.zlib.windowsize", zlib_parse_global_windowsize },
677#endif
678 { 0, NULL, NULL }
679}};
680
William Lallemand727db8b2013-04-20 17:33:20 +0200681__attribute__((constructor))
682static void __comp_fetch_init(void)
683{
Willy Tarreaub97c6fb2016-12-21 19:30:30 +0100684 char *ptr = NULL;
685 int i;
686
Willy Tarreau418b8c02015-03-29 03:32:06 +0200687#ifdef USE_SLZ
688 slz_make_crc_table();
689 slz_prepare_dist_table();
690#endif
Willy Tarreau36878032016-12-22 19:46:17 +0100691#if defined(USE_ZLIB) && defined(DEFAULT_MAXZLIBMEM)
692 global.tune.maxzlibmem = DEFAULT_MAXZLIBMEM * 1024U * 1024U,
693#endif
Willy Tarreaub97c6fb2016-12-21 19:30:30 +0100694#ifdef USE_ZLIB
695 memprintf(&ptr, "Built with zlib version : " ZLIB_VERSION);
696 memprintf(&ptr, "%s\nRunning on zlib version : %s", ptr, zlibVersion());
697#elif defined(USE_SLZ)
698 memprintf(&ptr, "Built with libslz for stateless compression.");
Lukas Tribusb7323212017-01-11 14:24:35 +0000699#else
700 memprintf(&ptr, "Built without compression support (neither USE_ZLIB nor USE_SLZ are set).");
Willy Tarreaub97c6fb2016-12-21 19:30:30 +0100701#endif
702 memprintf(&ptr, "%s\nCompression algorithms supported :", ptr);
703
704 for (i = 0; comp_algos[i].cfg_name; i++)
705 memprintf(&ptr, "%s%s %s(\"%s\")", ptr, (i == 0 ? "" : ","), comp_algos[i].cfg_name, comp_algos[i].ua_name);
706
707 if (i == 0)
708 memprintf(&ptr, "%s none", ptr);
709
710 hap_register_build_opts(ptr, 1);
Willy Tarreau36878032016-12-22 19:46:17 +0100711 cfg_register_keywords(&cfg_kws);
William Lallemand727db8b2013-04-20 17:33:20 +0200712}