blob: 02ff724c01550ab5dcbc72a5652a104ef10e37ab [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 +010059
Willy Tarreau9f640a12015-03-28 15:46:00 +010060static int identity_init(struct comp_ctx **comp_ctx, int level);
61static 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 +010062static int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out);
63static int identity_finish(struct comp_ctx *comp_ctx, struct buffer *out);
Willy Tarreau9f640a12015-03-28 15:46:00 +010064static int identity_end(struct comp_ctx **comp_ctx);
65
Willy Tarreau418b8c02015-03-29 03:32:06 +020066#if defined(USE_SLZ)
67
68static int rfc1950_init(struct comp_ctx **comp_ctx, int level);
69static int rfc1951_init(struct comp_ctx **comp_ctx, int level);
70static int rfc1952_init(struct comp_ctx **comp_ctx, int level);
71static int rfc195x_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
72static int rfc195x_flush(struct comp_ctx *comp_ctx, struct buffer *out);
73static int rfc195x_finish(struct comp_ctx *comp_ctx, struct buffer *out);
74static int rfc195x_end(struct comp_ctx **comp_ctx);
75
76#elif defined(USE_ZLIB)
Willy Tarreau7b218772015-03-28 22:08:25 +010077
Willy Tarreau9f640a12015-03-28 15:46:00 +010078static int gzip_init(struct comp_ctx **comp_ctx, int level);
Willy Tarreauc91840a2015-03-28 17:00:39 +010079static int raw_def_init(struct comp_ctx **comp_ctx, int level);
Willy Tarreau9f640a12015-03-28 15:46:00 +010080static int deflate_init(struct comp_ctx **comp_ctx, int level);
81static 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 +010082static int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out);
83static int deflate_finish(struct comp_ctx *comp_ctx, struct buffer *out);
Willy Tarreau9f640a12015-03-28 15:46:00 +010084static int deflate_end(struct comp_ctx **comp_ctx);
Willy Tarreau7b218772015-03-28 22:08:25 +010085
Willy Tarreau9f640a12015-03-28 15:46:00 +010086#endif /* USE_ZLIB */
87
William Lallemand2b502472012-10-30 14:30:39 +010088
Cyril Bonté6162c432012-11-10 19:27:47 +010089const struct comp_algo comp_algos[] =
William Lallemand82fe75c2012-10-23 10:25:10 +020090{
Willy Tarreau7b218772015-03-28 22:08:25 +010091 { "identity", 8, "identity", 8, identity_init, identity_add_data, identity_flush, identity_finish, identity_end },
Willy Tarreau418b8c02015-03-29 03:32:06 +020092#if defined(USE_SLZ)
93 { "deflate", 7, "deflate", 7, rfc1950_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
94 { "raw-deflate", 11, "deflate", 7, rfc1951_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
95 { "gzip", 4, "gzip", 4, rfc1952_init, rfc195x_add_data, rfc195x_flush, rfc195x_finish, rfc195x_end },
96#elif defined(USE_ZLIB)
Willy Tarreau7b218772015-03-28 22:08:25 +010097 { "deflate", 7, "deflate", 7, deflate_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
98 { "raw-deflate", 11, "deflate", 7, raw_def_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
99 { "gzip", 4, "gzip", 4, gzip_init, deflate_add_data, deflate_flush, deflate_finish, deflate_end },
William Lallemand82fe75c2012-10-23 10:25:10 +0200100#endif /* USE_ZLIB */
Willy Tarreau615105e2015-03-28 16:40:46 +0100101 { NULL, 0, NULL, 0, NULL , NULL, NULL, NULL, NULL }
William Lallemand82fe75c2012-10-23 10:25:10 +0200102};
103
104/*
105 * Add a content-type in the configuration
106 */
107int comp_append_type(struct comp *comp, const char *type)
108{
109 struct comp_type *comp_type;
110
Vincent Bernat02779b62016-04-03 13:48:43 +0200111 comp_type = calloc(1, sizeof(*comp_type));
William Lallemand82fe75c2012-10-23 10:25:10 +0200112 comp_type->name_len = strlen(type);
113 comp_type->name = strdup(type);
114 comp_type->next = comp->types;
115 comp->types = comp_type;
116 return 0;
117}
118
119/*
120 * Add an algorithm in the configuration
121 */
122int comp_append_algo(struct comp *comp, const char *algo)
123{
124 struct comp_algo *comp_algo;
125 int i;
126
Willy Tarreau615105e2015-03-28 16:40:46 +0100127 for (i = 0; comp_algos[i].cfg_name; i++) {
128 if (!strcmp(algo, comp_algos[i].cfg_name)) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200129 comp_algo = calloc(1, sizeof(*comp_algo));
William Lallemand82fe75c2012-10-23 10:25:10 +0200130 memmove(comp_algo, &comp_algos[i], sizeof(struct comp_algo));
131 comp_algo->next = comp->algos;
132 comp->algos = comp_algo;
133 return 0;
134 }
135 }
136 return -1;
137}
138
Willy Tarreaue1cc4b52016-08-10 21:17:06 +0200139#if defined(USE_ZLIB) || defined(USE_SLZ)
140static struct pool_head *pool_comp_ctx = NULL;
William Lallemand8b52bb32012-11-16 18:06:41 +0100141/*
142 * Alloc the comp_ctx
143 */
144static inline int init_comp_ctx(struct comp_ctx **comp_ctx)
145{
146#ifdef USE_ZLIB
147 z_stream *strm;
148
William Lallemande3a7d992012-11-20 11:25:20 +0100149 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < sizeof(struct comp_ctx))
William Lallemand8b52bb32012-11-16 18:06:41 +0100150 return -1;
151#endif
152
153 if (unlikely(pool_comp_ctx == NULL))
154 pool_comp_ctx = create_pool("comp_ctx", sizeof(struct comp_ctx), MEM_F_SHARED);
155
156 *comp_ctx = pool_alloc2(pool_comp_ctx);
157 if (*comp_ctx == NULL)
158 return -1;
Willy Tarreau418b8c02015-03-29 03:32:06 +0200159#if defined(USE_SLZ)
160 (*comp_ctx)->direct_ptr = NULL;
161 (*comp_ctx)->direct_len = 0;
162 (*comp_ctx)->queued = NULL;
163#elif defined(USE_ZLIB)
William Lallemande3a7d992012-11-20 11:25:20 +0100164 zlib_used_memory += sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100165
166 strm = &(*comp_ctx)->strm;
167 strm->zalloc = alloc_zlib;
168 strm->zfree = free_zlib;
169 strm->opaque = *comp_ctx;
170#endif
171 return 0;
172}
173
174/*
175 * Dealloc the comp_ctx
176 */
177static inline int deinit_comp_ctx(struct comp_ctx **comp_ctx)
178{
179 if (!*comp_ctx)
180 return 0;
181
182 pool_free2(pool_comp_ctx, *comp_ctx);
183 *comp_ctx = NULL;
184
185#ifdef USE_ZLIB
William Lallemande3a7d992012-11-20 11:25:20 +0100186 zlib_used_memory -= sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100187#endif
William Lallemand8b52bb32012-11-16 18:06:41 +0100188 return 0;
189}
Willy Tarreaue1cc4b52016-08-10 21:17:06 +0200190#endif
William Lallemand8b52bb32012-11-16 18:06:41 +0100191
William Lallemand82fe75c2012-10-23 10:25:10 +0200192
193/****************************
194 **** Identity algorithm ****
195 ****************************/
196
197/*
198 * Init the identity algorithm
199 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100200static int identity_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200201{
202 return 0;
203}
204
205/*
206 * Process data
William Lallemandbf3ae612012-11-19 12:35:37 +0100207 * Return size of consumed data or -1 on error
William Lallemand82fe75c2012-10-23 10:25:10 +0200208 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100209static 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 +0200210{
William Lallemandbf3ae612012-11-19 12:35:37 +0100211 char *out_data = bi_end(out);
212 int out_len = out->size - buffer_len(out);
213
William Lallemand82fe75c2012-10-23 10:25:10 +0200214 if (out_len < in_len)
215 return -1;
216
217 memcpy(out_data, in_data, in_len);
218
William Lallemandbf3ae612012-11-19 12:35:37 +0100219 out->i += in_len;
220
William Lallemand82fe75c2012-10-23 10:25:10 +0200221 return in_len;
222}
223
Willy Tarreau9787efa2015-03-28 19:17:31 +0100224static int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200225{
226 return 0;
227}
228
Willy Tarreau9787efa2015-03-28 19:17:31 +0100229static int identity_finish(struct comp_ctx *comp_ctx, struct buffer *out)
230{
231 return 0;
232}
233
Willy Tarreau418b8c02015-03-29 03:32:06 +0200234/*
235 * Deinit the algorithm
236 */
237static int identity_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200238{
239 return 0;
240}
241
Willy Tarreau418b8c02015-03-29 03:32:06 +0200242
243#ifdef USE_SLZ
244
245/* SLZ's gzip format (RFC1952). Returns < 0 on error. */
246static int rfc1952_init(struct comp_ctx **comp_ctx, int level)
247{
248 if (init_comp_ctx(comp_ctx) < 0)
249 return -1;
250
251 (*comp_ctx)->cur_lvl = !!level;
252 return slz_rfc1952_init(&(*comp_ctx)->strm, !!level);
253}
254
255/* SLZ's raw deflate format (RFC1951). Returns < 0 on error. */
256static int rfc1951_init(struct comp_ctx **comp_ctx, int level)
257{
258 if (init_comp_ctx(comp_ctx) < 0)
259 return -1;
260
261 (*comp_ctx)->cur_lvl = !!level;
262 return slz_rfc1951_init(&(*comp_ctx)->strm, !!level);
263}
264
265/* SLZ's zlib format (RFC1950). Returns < 0 on error. */
266static int rfc1950_init(struct comp_ctx **comp_ctx, int level)
267{
268 if (init_comp_ctx(comp_ctx) < 0)
269 return -1;
270
271 (*comp_ctx)->cur_lvl = !!level;
272 return slz_rfc1950_init(&(*comp_ctx)->strm, !!level);
273}
274
275/* Return the size of consumed data or -1. The output buffer is unused at this
276 * point, we only keep a reference to the input data or a copy of them if the
277 * reference is already used.
William Lallemand82fe75c2012-10-23 10:25:10 +0200278 */
Willy Tarreau418b8c02015-03-29 03:32:06 +0200279static 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 +0200280{
Willy Tarreau418b8c02015-03-29 03:32:06 +0200281 static struct buffer *tmpbuf = &buf_empty;
282
283 if (in_len <= 0)
284 return 0;
285
286 if (comp_ctx->direct_ptr && !comp_ctx->queued) {
287 /* data already being pointed to, we're in front of fragmented
288 * data and need a buffer now. We reuse the same buffer, as it's
289 * not used out of the scope of a series of add_data()*, end().
290 */
291 if (unlikely(!tmpbuf->size)) {
292 /* this is the first time we need the compression buffer */
293 if (b_alloc(&tmpbuf) == NULL)
294 return -1; /* no memory */
295 }
296 b_reset(tmpbuf);
297 memcpy(bi_end(tmpbuf), comp_ctx->direct_ptr, comp_ctx->direct_len);
298 tmpbuf->i += comp_ctx->direct_len;
299 comp_ctx->direct_ptr = NULL;
300 comp_ctx->direct_len = 0;
301 comp_ctx->queued = tmpbuf;
302 /* fall through buffer copy */
303 }
304
305 if (comp_ctx->queued) {
306 /* data already pending */
307 memcpy(bi_end(comp_ctx->queued), in_data, in_len);
308 comp_ctx->queued->i += in_len;
309 return in_len;
310 }
311
312 comp_ctx->direct_ptr = in_data;
313 comp_ctx->direct_len = in_len;
314 return in_len;
315}
316
317/* Compresses the data accumulated using add_data(), and optionally sends the
318 * format-specific trailer if <finish> is non-null. <out> is expected to have a
319 * large enough free non-wrapping space as verified by http_comp_buffer_init().
320 * The number of bytes emitted is reported.
321 */
322static int rfc195x_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int finish)
323{
324 struct slz_stream *strm = &comp_ctx->strm;
325 const char *in_ptr;
326 int in_len;
327 int out_len;
328
329 in_ptr = comp_ctx->direct_ptr;
330 in_len = comp_ctx->direct_len;
331
332 if (comp_ctx->queued) {
333 in_ptr = comp_ctx->queued->p;
334 in_len = comp_ctx->queued->i;
335 }
336
337 out_len = out->i;
338
339 if (in_ptr)
340 out->i += slz_encode(strm, bi_end(out), in_ptr, in_len, !finish);
341
342 if (finish)
343 out->i += slz_finish(strm, bi_end(out));
344
345 out_len = out->i - out_len;
346
347 /* very important, we must wipe the data we've just flushed */
348 comp_ctx->direct_len = 0;
349 comp_ctx->direct_ptr = NULL;
350 comp_ctx->queued = NULL;
351
352 /* Verify compression rate limiting and CPU usage */
353 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
354 (idle_pct < compress_min_idle)) { /* idle */
355 if (comp_ctx->cur_lvl > 0)
356 strm->level = --comp_ctx->cur_lvl;
357 }
358 else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel && comp_ctx->cur_lvl < 1) {
359 strm->level = ++comp_ctx->cur_lvl;
360 }
361
362 /* and that's all */
363 return out_len;
364}
365
366static int rfc195x_flush(struct comp_ctx *comp_ctx, struct buffer *out)
367{
368 return rfc195x_flush_or_finish(comp_ctx, out, 0);
369}
370
371static int rfc195x_finish(struct comp_ctx *comp_ctx, struct buffer *out)
372{
373 return rfc195x_flush_or_finish(comp_ctx, out, 1);
374}
375
376/* we just need to free the comp_ctx here, nothing was allocated */
377static int rfc195x_end(struct comp_ctx **comp_ctx)
378{
379 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200380 return 0;
381}
382
Willy Tarreau418b8c02015-03-29 03:32:06 +0200383#elif defined(USE_ZLIB) /* ! USE_SLZ */
William Lallemand82fe75c2012-10-23 10:25:10 +0200384
William Lallemand2b502472012-10-30 14:30:39 +0100385/*
386 * This is a tricky allocation function using the zlib.
387 * This is based on the allocation order in deflateInit2.
388 */
389static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
390{
391 struct comp_ctx *ctx = opaque;
392 static char round = 0; /* order in deflateInit2 */
393 void *buf = NULL;
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100394 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100395
William Lallemande3a7d992012-11-20 11:25:20 +0100396 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < (long)(items * size))
William Lallemand9d5f5482012-11-07 16:12:57 +0100397 goto end;
William Lallemand9d5f5482012-11-07 16:12:57 +0100398
William Lallemand2b502472012-10-30 14:30:39 +0100399 switch (round) {
400 case 0:
401 if (zlib_pool_deflate_state == NULL)
402 zlib_pool_deflate_state = create_pool("zlib_state", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100403 pool = zlib_pool_deflate_state;
404 ctx->zlib_deflate_state = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100405 break;
406
407 case 1:
408 if (zlib_pool_window == NULL)
409 zlib_pool_window = create_pool("zlib_window", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100410 pool = zlib_pool_window;
411 ctx->zlib_window = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100412 break;
413
414 case 2:
415 if (zlib_pool_prev == NULL)
416 zlib_pool_prev = create_pool("zlib_prev", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100417 pool = zlib_pool_prev;
418 ctx->zlib_prev = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100419 break;
420
421 case 3:
422 if (zlib_pool_head == NULL)
423 zlib_pool_head = create_pool("zlib_head", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100424 pool = zlib_pool_head;
425 ctx->zlib_head = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100426 break;
427
428 case 4:
429 if (zlib_pool_pending_buf == NULL)
430 zlib_pool_pending_buf = create_pool("zlib_pending_buf", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100431 pool = zlib_pool_pending_buf;
432 ctx->zlib_pending_buf = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100433 break;
434 }
William Lallemande3a7d992012-11-20 11:25:20 +0100435 if (buf != NULL)
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100436 zlib_used_memory += pool->size;
William Lallemand9d5f5482012-11-07 16:12:57 +0100437
438end:
William Lallemand2b502472012-10-30 14:30:39 +0100439
Willy Tarreau46909852012-11-15 14:57:56 +0100440 /* deflateInit2() first allocates and checks the deflate_state, then if
441 * it succeeds, it allocates all other 4 areas at ones and checks them
442 * at the end. So we want to correctly count the rounds depending on when
443 * zlib is supposed to abort.
444 */
445 if (buf || round)
446 round = (round + 1) % 5;
William Lallemand2b502472012-10-30 14:30:39 +0100447 return buf;
448}
449
450static void free_zlib(void *opaque, void *ptr)
451{
452 struct comp_ctx *ctx = opaque;
Willy Tarreaub1fbd052012-11-10 17:49:37 +0100453 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100454
455 if (ptr == ctx->zlib_window)
William Lallemand9d5f5482012-11-07 16:12:57 +0100456 pool = zlib_pool_window;
William Lallemand2b502472012-10-30 14:30:39 +0100457 else if (ptr == ctx->zlib_deflate_state)
William Lallemand9d5f5482012-11-07 16:12:57 +0100458 pool = zlib_pool_deflate_state;
William Lallemand2b502472012-10-30 14:30:39 +0100459 else if (ptr == ctx->zlib_prev)
William Lallemand9d5f5482012-11-07 16:12:57 +0100460 pool = zlib_pool_prev;
William Lallemand2b502472012-10-30 14:30:39 +0100461 else if (ptr == ctx->zlib_head)
William Lallemand9d5f5482012-11-07 16:12:57 +0100462 pool = zlib_pool_head;
William Lallemand2b502472012-10-30 14:30:39 +0100463 else if (ptr == ctx->zlib_pending_buf)
William Lallemand9d5f5482012-11-07 16:12:57 +0100464 pool = zlib_pool_pending_buf;
William Lallemand2b502472012-10-30 14:30:39 +0100465
William Lallemand9d5f5482012-11-07 16:12:57 +0100466 pool_free2(pool, ptr);
William Lallemande3a7d992012-11-20 11:25:20 +0100467 zlib_used_memory -= pool->size;
William Lallemand2b502472012-10-30 14:30:39 +0100468}
469
William Lallemand82fe75c2012-10-23 10:25:10 +0200470/**************************
471**** gzip algorithm ****
472***************************/
Willy Tarreau9f640a12015-03-28 15:46:00 +0100473static int gzip_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200474{
William Lallemand8b52bb32012-11-16 18:06:41 +0100475 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200476
William Lallemand8b52bb32012-11-16 18:06:41 +0100477 if (init_comp_ctx(comp_ctx) < 0)
478 return -1;
William Lallemand9d5f5482012-11-07 16:12:57 +0100479
William Lallemand8b52bb32012-11-16 18:06:41 +0100480 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200481
William Lallemand8b52bb32012-11-16 18:06:41 +0100482 if (deflateInit2(strm, level, Z_DEFLATED, global.tune.zlibwindowsize + 16, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
483 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200484 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100485 }
486
487 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200488
489 return 0;
490}
Willy Tarreauc91840a2015-03-28 17:00:39 +0100491
492/* Raw deflate algorithm */
493static int raw_def_init(struct comp_ctx **comp_ctx, int level)
494{
495 z_stream *strm;
496
497 if (init_comp_ctx(comp_ctx) < 0)
498 return -1;
499
500 strm = &(*comp_ctx)->strm;
501
502 if (deflateInit2(strm, level, Z_DEFLATED, -global.tune.zlibwindowsize, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
503 deinit_comp_ctx(comp_ctx);
504 return -1;
505 }
506
507 (*comp_ctx)->cur_lvl = level;
508 return 0;
509}
510
William Lallemand82fe75c2012-10-23 10:25:10 +0200511/**************************
512**** Deflate algorithm ****
513***************************/
514
Willy Tarreau9f640a12015-03-28 15:46:00 +0100515static int deflate_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200516{
William Lallemand8b52bb32012-11-16 18:06:41 +0100517 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200518
William Lallemand8b52bb32012-11-16 18:06:41 +0100519 if (init_comp_ctx(comp_ctx) < 0)
520 return -1;
521
522 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200523
Willy Tarreauc5599e72013-04-28 08:52:52 +0200524 if (deflateInit2(strm, level, Z_DEFLATED, global.tune.zlibwindowsize, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
William Lallemand8b52bb32012-11-16 18:06:41 +0100525 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200526 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100527 }
528
529 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200530
531 return 0;
532}
533
William Lallemandbf3ae612012-11-19 12:35:37 +0100534/* Return the size of consumed data or -1 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100535static 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 +0200536{
William Lallemand82fe75c2012-10-23 10:25:10 +0200537 int ret;
William Lallemandbf3ae612012-11-19 12:35:37 +0100538 z_stream *strm = &comp_ctx->strm;
539 char *out_data = bi_end(out);
540 int out_len = out->size - buffer_len(out);
William Lallemand82fe75c2012-10-23 10:25:10 +0200541
542 if (in_len <= 0)
543 return 0;
544
545
546 if (out_len <= 0)
547 return -1;
548
William Lallemand82fe75c2012-10-23 10:25:10 +0200549 strm->next_in = (unsigned char *)in_data;
550 strm->avail_in = in_len;
551 strm->next_out = (unsigned char *)out_data;
552 strm->avail_out = out_len;
553
554 ret = deflate(strm, Z_NO_FLUSH);
555 if (ret != Z_OK)
556 return -1;
557
558 /* deflate update the available data out */
William Lallemandbf3ae612012-11-19 12:35:37 +0100559 out->i += out_len - strm->avail_out;
William Lallemand82fe75c2012-10-23 10:25:10 +0200560
William Lallemandbf3ae612012-11-19 12:35:37 +0100561 return in_len - strm->avail_in;
William Lallemand82fe75c2012-10-23 10:25:10 +0200562}
563
Willy Tarreau9787efa2015-03-28 19:17:31 +0100564static int deflate_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int flag)
William Lallemand82fe75c2012-10-23 10:25:10 +0200565{
566 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200567 int out_len = 0;
William Lallemand1c2d6222012-10-30 15:52:53 +0100568 z_stream *strm = &comp_ctx->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200569
Willy Tarreaud8b8b532016-08-08 16:41:01 +0200570 strm->next_in = NULL;
571 strm->avail_in = 0;
William Lallemand82fe75c2012-10-23 10:25:10 +0200572 strm->next_out = (unsigned char *)bi_end(out);
573 strm->avail_out = out->size - buffer_len(out);
574
575 ret = deflate(strm, flag);
576 if (ret != Z_OK && ret != Z_STREAM_END)
577 return -1;
578
579 out_len = (out->size - buffer_len(out)) - strm->avail_out;
580 out->i += out_len;
581
William Lallemand072a2bf2012-11-20 17:01:01 +0100582 /* compression limit */
583 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
584 (idle_pct < compress_min_idle)) { /* idle */
585 /* decrease level */
586 if (comp_ctx->cur_lvl > 0) {
587 comp_ctx->cur_lvl--;
William Lallemandd85f9172012-11-09 17:05:39 +0100588 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
589 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100590
591 } else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel) {
592 /* increase level */
593 comp_ctx->cur_lvl++ ;
594 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
William Lallemandd85f9172012-11-09 17:05:39 +0100595 }
596
William Lallemand82fe75c2012-10-23 10:25:10 +0200597 return out_len;
598}
599
Willy Tarreau9787efa2015-03-28 19:17:31 +0100600static int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out)
601{
602 return deflate_flush_or_finish(comp_ctx, out, Z_SYNC_FLUSH);
603}
604
605static int deflate_finish(struct comp_ctx *comp_ctx, struct buffer *out)
606{
607 return deflate_flush_or_finish(comp_ctx, out, Z_FINISH);
608}
609
Willy Tarreau9f640a12015-03-28 15:46:00 +0100610static int deflate_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200611{
William Lallemand8b52bb32012-11-16 18:06:41 +0100612 z_stream *strm = &(*comp_ctx)->strm;
613 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200614
William Lallemand8b52bb32012-11-16 18:06:41 +0100615 ret = deflateEnd(strm);
William Lallemand82fe75c2012-10-23 10:25:10 +0200616
William Lallemand8b52bb32012-11-16 18:06:41 +0100617 deinit_comp_ctx(comp_ctx);
618
619 return ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200620}
621
622#endif /* USE_ZLIB */
623
William Lallemand727db8b2013-04-20 17:33:20 +0200624__attribute__((constructor))
625static void __comp_fetch_init(void)
626{
Willy Tarreau418b8c02015-03-29 03:32:06 +0200627#ifdef USE_SLZ
628 slz_make_crc_table();
629 slz_prepare_dist_table();
630#endif
William Lallemand727db8b2013-04-20 17:33:20 +0200631}