blob: 7b5a93915f9cf10e976d0c7c926b1ec244db7086 [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
William Lallemand8b52bb32012-11-16 18:06:41 +0100140/*
141 * Alloc the comp_ctx
142 */
143static inline int init_comp_ctx(struct comp_ctx **comp_ctx)
144{
145#ifdef USE_ZLIB
146 z_stream *strm;
147
William Lallemande3a7d992012-11-20 11:25:20 +0100148 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < sizeof(struct comp_ctx))
William Lallemand8b52bb32012-11-16 18:06:41 +0100149 return -1;
150#endif
151
152 if (unlikely(pool_comp_ctx == NULL))
153 pool_comp_ctx = create_pool("comp_ctx", sizeof(struct comp_ctx), MEM_F_SHARED);
154
155 *comp_ctx = pool_alloc2(pool_comp_ctx);
156 if (*comp_ctx == NULL)
157 return -1;
Willy Tarreau418b8c02015-03-29 03:32:06 +0200158#if defined(USE_SLZ)
159 (*comp_ctx)->direct_ptr = NULL;
160 (*comp_ctx)->direct_len = 0;
161 (*comp_ctx)->queued = NULL;
162#elif defined(USE_ZLIB)
William Lallemande3a7d992012-11-20 11:25:20 +0100163 zlib_used_memory += sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100164
165 strm = &(*comp_ctx)->strm;
166 strm->zalloc = alloc_zlib;
167 strm->zfree = free_zlib;
168 strm->opaque = *comp_ctx;
169#endif
170 return 0;
171}
172
173/*
174 * Dealloc the comp_ctx
175 */
176static inline int deinit_comp_ctx(struct comp_ctx **comp_ctx)
177{
178 if (!*comp_ctx)
179 return 0;
180
181 pool_free2(pool_comp_ctx, *comp_ctx);
182 *comp_ctx = NULL;
183
184#ifdef USE_ZLIB
William Lallemande3a7d992012-11-20 11:25:20 +0100185 zlib_used_memory -= sizeof(struct comp_ctx);
William Lallemand8b52bb32012-11-16 18:06:41 +0100186#endif
William Lallemand8b52bb32012-11-16 18:06:41 +0100187 return 0;
188}
189
William Lallemand82fe75c2012-10-23 10:25:10 +0200190
191/****************************
192 **** Identity algorithm ****
193 ****************************/
194
195/*
196 * Init the identity algorithm
197 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100198static int identity_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200199{
200 return 0;
201}
202
203/*
204 * Process data
William Lallemandbf3ae612012-11-19 12:35:37 +0100205 * Return size of consumed data or -1 on error
William Lallemand82fe75c2012-10-23 10:25:10 +0200206 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100207static 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 +0200208{
William Lallemandbf3ae612012-11-19 12:35:37 +0100209 char *out_data = bi_end(out);
210 int out_len = out->size - buffer_len(out);
211
William Lallemand82fe75c2012-10-23 10:25:10 +0200212 if (out_len < in_len)
213 return -1;
214
215 memcpy(out_data, in_data, in_len);
216
William Lallemandbf3ae612012-11-19 12:35:37 +0100217 out->i += in_len;
218
William Lallemand82fe75c2012-10-23 10:25:10 +0200219 return in_len;
220}
221
Willy Tarreau9787efa2015-03-28 19:17:31 +0100222static int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out)
William Lallemand82fe75c2012-10-23 10:25:10 +0200223{
224 return 0;
225}
226
Willy Tarreau9787efa2015-03-28 19:17:31 +0100227static int identity_finish(struct comp_ctx *comp_ctx, struct buffer *out)
228{
229 return 0;
230}
231
Willy Tarreau418b8c02015-03-29 03:32:06 +0200232/*
233 * Deinit the algorithm
234 */
235static int identity_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200236{
237 return 0;
238}
239
Willy Tarreau418b8c02015-03-29 03:32:06 +0200240
241#ifdef USE_SLZ
242
243/* SLZ's gzip format (RFC1952). Returns < 0 on error. */
244static int rfc1952_init(struct comp_ctx **comp_ctx, int level)
245{
246 if (init_comp_ctx(comp_ctx) < 0)
247 return -1;
248
249 (*comp_ctx)->cur_lvl = !!level;
250 return slz_rfc1952_init(&(*comp_ctx)->strm, !!level);
251}
252
253/* SLZ's raw deflate format (RFC1951). Returns < 0 on error. */
254static int rfc1951_init(struct comp_ctx **comp_ctx, int level)
255{
256 if (init_comp_ctx(comp_ctx) < 0)
257 return -1;
258
259 (*comp_ctx)->cur_lvl = !!level;
260 return slz_rfc1951_init(&(*comp_ctx)->strm, !!level);
261}
262
263/* SLZ's zlib format (RFC1950). Returns < 0 on error. */
264static int rfc1950_init(struct comp_ctx **comp_ctx, int level)
265{
266 if (init_comp_ctx(comp_ctx) < 0)
267 return -1;
268
269 (*comp_ctx)->cur_lvl = !!level;
270 return slz_rfc1950_init(&(*comp_ctx)->strm, !!level);
271}
272
273/* Return the size of consumed data or -1. The output buffer is unused at this
274 * point, we only keep a reference to the input data or a copy of them if the
275 * reference is already used.
William Lallemand82fe75c2012-10-23 10:25:10 +0200276 */
Willy Tarreau418b8c02015-03-29 03:32:06 +0200277static 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 +0200278{
Willy Tarreau418b8c02015-03-29 03:32:06 +0200279 static struct buffer *tmpbuf = &buf_empty;
280
281 if (in_len <= 0)
282 return 0;
283
284 if (comp_ctx->direct_ptr && !comp_ctx->queued) {
285 /* data already being pointed to, we're in front of fragmented
286 * data and need a buffer now. We reuse the same buffer, as it's
287 * not used out of the scope of a series of add_data()*, end().
288 */
289 if (unlikely(!tmpbuf->size)) {
290 /* this is the first time we need the compression buffer */
291 if (b_alloc(&tmpbuf) == NULL)
292 return -1; /* no memory */
293 }
294 b_reset(tmpbuf);
295 memcpy(bi_end(tmpbuf), comp_ctx->direct_ptr, comp_ctx->direct_len);
296 tmpbuf->i += comp_ctx->direct_len;
297 comp_ctx->direct_ptr = NULL;
298 comp_ctx->direct_len = 0;
299 comp_ctx->queued = tmpbuf;
300 /* fall through buffer copy */
301 }
302
303 if (comp_ctx->queued) {
304 /* data already pending */
305 memcpy(bi_end(comp_ctx->queued), in_data, in_len);
306 comp_ctx->queued->i += in_len;
307 return in_len;
308 }
309
310 comp_ctx->direct_ptr = in_data;
311 comp_ctx->direct_len = in_len;
312 return in_len;
313}
314
315/* Compresses the data accumulated using add_data(), and optionally sends the
316 * format-specific trailer if <finish> is non-null. <out> is expected to have a
317 * large enough free non-wrapping space as verified by http_comp_buffer_init().
318 * The number of bytes emitted is reported.
319 */
320static int rfc195x_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int finish)
321{
322 struct slz_stream *strm = &comp_ctx->strm;
323 const char *in_ptr;
324 int in_len;
325 int out_len;
326
327 in_ptr = comp_ctx->direct_ptr;
328 in_len = comp_ctx->direct_len;
329
330 if (comp_ctx->queued) {
331 in_ptr = comp_ctx->queued->p;
332 in_len = comp_ctx->queued->i;
333 }
334
335 out_len = out->i;
336
337 if (in_ptr)
338 out->i += slz_encode(strm, bi_end(out), in_ptr, in_len, !finish);
339
340 if (finish)
341 out->i += slz_finish(strm, bi_end(out));
342
343 out_len = out->i - out_len;
344
345 /* very important, we must wipe the data we've just flushed */
346 comp_ctx->direct_len = 0;
347 comp_ctx->direct_ptr = NULL;
348 comp_ctx->queued = NULL;
349
350 /* Verify compression rate limiting and CPU usage */
351 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
352 (idle_pct < compress_min_idle)) { /* idle */
353 if (comp_ctx->cur_lvl > 0)
354 strm->level = --comp_ctx->cur_lvl;
355 }
356 else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel && comp_ctx->cur_lvl < 1) {
357 strm->level = ++comp_ctx->cur_lvl;
358 }
359
360 /* and that's all */
361 return out_len;
362}
363
364static int rfc195x_flush(struct comp_ctx *comp_ctx, struct buffer *out)
365{
366 return rfc195x_flush_or_finish(comp_ctx, out, 0);
367}
368
369static int rfc195x_finish(struct comp_ctx *comp_ctx, struct buffer *out)
370{
371 return rfc195x_flush_or_finish(comp_ctx, out, 1);
372}
373
374/* we just need to free the comp_ctx here, nothing was allocated */
375static int rfc195x_end(struct comp_ctx **comp_ctx)
376{
377 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200378 return 0;
379}
380
Willy Tarreau418b8c02015-03-29 03:32:06 +0200381#elif defined(USE_ZLIB) /* ! USE_SLZ */
William Lallemand82fe75c2012-10-23 10:25:10 +0200382
William Lallemand2b502472012-10-30 14:30:39 +0100383/*
384 * This is a tricky allocation function using the zlib.
385 * This is based on the allocation order in deflateInit2.
386 */
387static void *alloc_zlib(void *opaque, unsigned int items, unsigned int size)
388{
389 struct comp_ctx *ctx = opaque;
390 static char round = 0; /* order in deflateInit2 */
391 void *buf = NULL;
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100392 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100393
William Lallemande3a7d992012-11-20 11:25:20 +0100394 if (global.maxzlibmem > 0 && (global.maxzlibmem - zlib_used_memory) < (long)(items * size))
William Lallemand9d5f5482012-11-07 16:12:57 +0100395 goto end;
William Lallemand9d5f5482012-11-07 16:12:57 +0100396
William Lallemand2b502472012-10-30 14:30:39 +0100397 switch (round) {
398 case 0:
399 if (zlib_pool_deflate_state == NULL)
400 zlib_pool_deflate_state = create_pool("zlib_state", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100401 pool = zlib_pool_deflate_state;
402 ctx->zlib_deflate_state = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100403 break;
404
405 case 1:
406 if (zlib_pool_window == NULL)
407 zlib_pool_window = create_pool("zlib_window", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100408 pool = zlib_pool_window;
409 ctx->zlib_window = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100410 break;
411
412 case 2:
413 if (zlib_pool_prev == NULL)
414 zlib_pool_prev = create_pool("zlib_prev", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100415 pool = zlib_pool_prev;
416 ctx->zlib_prev = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100417 break;
418
419 case 3:
420 if (zlib_pool_head == NULL)
421 zlib_pool_head = create_pool("zlib_head", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100422 pool = zlib_pool_head;
423 ctx->zlib_head = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100424 break;
425
426 case 4:
427 if (zlib_pool_pending_buf == NULL)
428 zlib_pool_pending_buf = create_pool("zlib_pending_buf", size * items, MEM_F_SHARED);
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100429 pool = zlib_pool_pending_buf;
430 ctx->zlib_pending_buf = buf = pool_alloc2(pool);
William Lallemand2b502472012-10-30 14:30:39 +0100431 break;
432 }
William Lallemande3a7d992012-11-20 11:25:20 +0100433 if (buf != NULL)
Willy Tarreau4f31fc22014-12-24 18:07:55 +0100434 zlib_used_memory += pool->size;
William Lallemand9d5f5482012-11-07 16:12:57 +0100435
436end:
William Lallemand2b502472012-10-30 14:30:39 +0100437
Willy Tarreau46909852012-11-15 14:57:56 +0100438 /* deflateInit2() first allocates and checks the deflate_state, then if
439 * it succeeds, it allocates all other 4 areas at ones and checks them
440 * at the end. So we want to correctly count the rounds depending on when
441 * zlib is supposed to abort.
442 */
443 if (buf || round)
444 round = (round + 1) % 5;
William Lallemand2b502472012-10-30 14:30:39 +0100445 return buf;
446}
447
448static void free_zlib(void *opaque, void *ptr)
449{
450 struct comp_ctx *ctx = opaque;
Willy Tarreaub1fbd052012-11-10 17:49:37 +0100451 struct pool_head *pool = NULL;
William Lallemand2b502472012-10-30 14:30:39 +0100452
453 if (ptr == ctx->zlib_window)
William Lallemand9d5f5482012-11-07 16:12:57 +0100454 pool = zlib_pool_window;
William Lallemand2b502472012-10-30 14:30:39 +0100455 else if (ptr == ctx->zlib_deflate_state)
William Lallemand9d5f5482012-11-07 16:12:57 +0100456 pool = zlib_pool_deflate_state;
William Lallemand2b502472012-10-30 14:30:39 +0100457 else if (ptr == ctx->zlib_prev)
William Lallemand9d5f5482012-11-07 16:12:57 +0100458 pool = zlib_pool_prev;
William Lallemand2b502472012-10-30 14:30:39 +0100459 else if (ptr == ctx->zlib_head)
William Lallemand9d5f5482012-11-07 16:12:57 +0100460 pool = zlib_pool_head;
William Lallemand2b502472012-10-30 14:30:39 +0100461 else if (ptr == ctx->zlib_pending_buf)
William Lallemand9d5f5482012-11-07 16:12:57 +0100462 pool = zlib_pool_pending_buf;
William Lallemand2b502472012-10-30 14:30:39 +0100463
William Lallemand9d5f5482012-11-07 16:12:57 +0100464 pool_free2(pool, ptr);
William Lallemande3a7d992012-11-20 11:25:20 +0100465 zlib_used_memory -= pool->size;
William Lallemand2b502472012-10-30 14:30:39 +0100466}
467
William Lallemand82fe75c2012-10-23 10:25:10 +0200468/**************************
469**** gzip algorithm ****
470***************************/
Willy Tarreau9f640a12015-03-28 15:46:00 +0100471static int gzip_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200472{
William Lallemand8b52bb32012-11-16 18:06:41 +0100473 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200474
William Lallemand8b52bb32012-11-16 18:06:41 +0100475 if (init_comp_ctx(comp_ctx) < 0)
476 return -1;
William Lallemand9d5f5482012-11-07 16:12:57 +0100477
William Lallemand8b52bb32012-11-16 18:06:41 +0100478 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200479
William Lallemand8b52bb32012-11-16 18:06:41 +0100480 if (deflateInit2(strm, level, Z_DEFLATED, global.tune.zlibwindowsize + 16, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
481 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200482 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100483 }
484
485 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200486
487 return 0;
488}
Willy Tarreauc91840a2015-03-28 17:00:39 +0100489
490/* Raw deflate algorithm */
491static int raw_def_init(struct comp_ctx **comp_ctx, int level)
492{
493 z_stream *strm;
494
495 if (init_comp_ctx(comp_ctx) < 0)
496 return -1;
497
498 strm = &(*comp_ctx)->strm;
499
500 if (deflateInit2(strm, level, Z_DEFLATED, -global.tune.zlibwindowsize, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
501 deinit_comp_ctx(comp_ctx);
502 return -1;
503 }
504
505 (*comp_ctx)->cur_lvl = level;
506 return 0;
507}
508
William Lallemand82fe75c2012-10-23 10:25:10 +0200509/**************************
510**** Deflate algorithm ****
511***************************/
512
Willy Tarreau9f640a12015-03-28 15:46:00 +0100513static int deflate_init(struct comp_ctx **comp_ctx, int level)
William Lallemand82fe75c2012-10-23 10:25:10 +0200514{
William Lallemand8b52bb32012-11-16 18:06:41 +0100515 z_stream *strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200516
William Lallemand8b52bb32012-11-16 18:06:41 +0100517 if (init_comp_ctx(comp_ctx) < 0)
518 return -1;
519
520 strm = &(*comp_ctx)->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200521
Willy Tarreauc5599e72013-04-28 08:52:52 +0200522 if (deflateInit2(strm, level, Z_DEFLATED, global.tune.zlibwindowsize, global.tune.zlibmemlevel, Z_DEFAULT_STRATEGY) != Z_OK) {
William Lallemand8b52bb32012-11-16 18:06:41 +0100523 deinit_comp_ctx(comp_ctx);
William Lallemand82fe75c2012-10-23 10:25:10 +0200524 return -1;
William Lallemand8b52bb32012-11-16 18:06:41 +0100525 }
526
527 (*comp_ctx)->cur_lvl = level;
William Lallemand82fe75c2012-10-23 10:25:10 +0200528
529 return 0;
530}
531
William Lallemandbf3ae612012-11-19 12:35:37 +0100532/* Return the size of consumed data or -1 */
Willy Tarreau9f640a12015-03-28 15:46:00 +0100533static 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 +0200534{
William Lallemand82fe75c2012-10-23 10:25:10 +0200535 int ret;
William Lallemandbf3ae612012-11-19 12:35:37 +0100536 z_stream *strm = &comp_ctx->strm;
537 char *out_data = bi_end(out);
538 int out_len = out->size - buffer_len(out);
William Lallemand82fe75c2012-10-23 10:25:10 +0200539
540 if (in_len <= 0)
541 return 0;
542
543
544 if (out_len <= 0)
545 return -1;
546
William Lallemand82fe75c2012-10-23 10:25:10 +0200547 strm->next_in = (unsigned char *)in_data;
548 strm->avail_in = in_len;
549 strm->next_out = (unsigned char *)out_data;
550 strm->avail_out = out_len;
551
552 ret = deflate(strm, Z_NO_FLUSH);
553 if (ret != Z_OK)
554 return -1;
555
556 /* deflate update the available data out */
William Lallemandbf3ae612012-11-19 12:35:37 +0100557 out->i += out_len - strm->avail_out;
William Lallemand82fe75c2012-10-23 10:25:10 +0200558
William Lallemandbf3ae612012-11-19 12:35:37 +0100559 return in_len - strm->avail_in;
William Lallemand82fe75c2012-10-23 10:25:10 +0200560}
561
Willy Tarreau9787efa2015-03-28 19:17:31 +0100562static int deflate_flush_or_finish(struct comp_ctx *comp_ctx, struct buffer *out, int flag)
William Lallemand82fe75c2012-10-23 10:25:10 +0200563{
564 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200565 int out_len = 0;
William Lallemand1c2d6222012-10-30 15:52:53 +0100566 z_stream *strm = &comp_ctx->strm;
William Lallemand82fe75c2012-10-23 10:25:10 +0200567
William Lallemand82fe75c2012-10-23 10:25:10 +0200568 strm->next_out = (unsigned char *)bi_end(out);
569 strm->avail_out = out->size - buffer_len(out);
570
571 ret = deflate(strm, flag);
572 if (ret != Z_OK && ret != Z_STREAM_END)
573 return -1;
574
575 out_len = (out->size - buffer_len(out)) - strm->avail_out;
576 out->i += out_len;
577
William Lallemand072a2bf2012-11-20 17:01:01 +0100578 /* compression limit */
579 if ((global.comp_rate_lim > 0 && (read_freq_ctr(&global.comp_bps_out) > global.comp_rate_lim)) || /* rate */
580 (idle_pct < compress_min_idle)) { /* idle */
581 /* decrease level */
582 if (comp_ctx->cur_lvl > 0) {
583 comp_ctx->cur_lvl--;
William Lallemandd85f9172012-11-09 17:05:39 +0100584 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
585 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100586
587 } else if (comp_ctx->cur_lvl < global.tune.comp_maxlevel) {
588 /* increase level */
589 comp_ctx->cur_lvl++ ;
590 deflateParams(&comp_ctx->strm, comp_ctx->cur_lvl, Z_DEFAULT_STRATEGY);
William Lallemandd85f9172012-11-09 17:05:39 +0100591 }
592
William Lallemand82fe75c2012-10-23 10:25:10 +0200593 return out_len;
594}
595
Willy Tarreau9787efa2015-03-28 19:17:31 +0100596static int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out)
597{
598 return deflate_flush_or_finish(comp_ctx, out, Z_SYNC_FLUSH);
599}
600
601static int deflate_finish(struct comp_ctx *comp_ctx, struct buffer *out)
602{
603 return deflate_flush_or_finish(comp_ctx, out, Z_FINISH);
604}
605
Willy Tarreau9f640a12015-03-28 15:46:00 +0100606static int deflate_end(struct comp_ctx **comp_ctx)
William Lallemand82fe75c2012-10-23 10:25:10 +0200607{
William Lallemand8b52bb32012-11-16 18:06:41 +0100608 z_stream *strm = &(*comp_ctx)->strm;
609 int ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200610
William Lallemand8b52bb32012-11-16 18:06:41 +0100611 ret = deflateEnd(strm);
William Lallemand82fe75c2012-10-23 10:25:10 +0200612
William Lallemand8b52bb32012-11-16 18:06:41 +0100613 deinit_comp_ctx(comp_ctx);
614
615 return ret;
William Lallemand82fe75c2012-10-23 10:25:10 +0200616}
617
618#endif /* USE_ZLIB */
619
William Lallemand727db8b2013-04-20 17:33:20 +0200620__attribute__((constructor))
621static void __comp_fetch_init(void)
622{
Willy Tarreau418b8c02015-03-29 03:32:06 +0200623#ifdef USE_SLZ
624 slz_make_crc_table();
625 slz_prepare_dist_table();
626#endif
William Lallemand727db8b2013-04-20 17:33:20 +0200627}