Remove unneeded stuff.
[gnutls.git] / lib / gnutls_compress.c
blob3821a848798eeed4535e8c8326ede7c4f0bf126e
1 /*
2 * Copyright (C) 2000, 2004, 2005, 2007, 2008, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 3 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>
24 /* This file contains the functions which convert the TLS plaintext
25 * packet to TLS compressed packet.
28 #include "gnutls_int.h"
29 #include "gnutls_compress.h"
30 #include "gnutls_errors.h"
31 #include "gnutls_constate.h"
32 #include <algorithms.h>
33 #include <gnutls/gnutls.h>
35 /* Compression Section */
36 #define GNUTLS_COMPRESSION_ENTRY(name, id, wb, ml, cl) \
37 { #name, name, id, wb, ml, cl}
40 #define MAX_COMP_METHODS 5
41 const int _gnutls_comp_algorithms_size = MAX_COMP_METHODS;
43 gnutls_compression_entry _gnutls_compression_algorithms[MAX_COMP_METHODS] = {
44 GNUTLS_COMPRESSION_ENTRY (GNUTLS_COMP_NULL, 0x00, 0, 0, 0),
45 #ifdef HAVE_LIBZ
46 /* draft-ietf-tls-compression-02 */
47 GNUTLS_COMPRESSION_ENTRY (GNUTLS_COMP_DEFLATE, 0x01, 15, 8, 3),
48 #endif
49 {0, 0, 0, 0, 0, 0}
52 static const gnutls_compression_method_t supported_compressions[] = {
53 #ifdef HAVE_LIBZ
54 GNUTLS_COMP_DEFLATE,
55 #endif
56 GNUTLS_COMP_NULL,
60 #define GNUTLS_COMPRESSION_LOOP(b) \
61 const gnutls_compression_entry *p; \
62 for(p = _gnutls_compression_algorithms; p->name != NULL; p++) { b ; }
63 #define GNUTLS_COMPRESSION_ALG_LOOP(a) \
64 GNUTLS_COMPRESSION_LOOP( if(p->id == algorithm) { a; break; } )
65 #define GNUTLS_COMPRESSION_ALG_LOOP_NUM(a) \
66 GNUTLS_COMPRESSION_LOOP( if(p->num == num) { a; break; } )
68 /* Compression Functions */
70 /**
71 * gnutls_compression_get_name:
72 * @algorithm: is a Compression algorithm
74 * Convert a #gnutls_compression_method_t value to a string.
76 * Returns: a pointer to a string that contains the name of the
77 * specified compression algorithm, or %NULL.
78 **/
79 const char *
80 gnutls_compression_get_name (gnutls_compression_method_t algorithm)
82 const char *ret = NULL;
84 /* avoid prefix */
85 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_COMP_") - 1);
87 return ret;
90 /**
91 * gnutls_compression_get_id:
92 * @name: is a compression method name
94 * The names are compared in a case insensitive way.
96 * Returns: an id of the specified in a string compression method, or
97 * %GNUTLS_COMP_UNKNOWN on error.
98 **/
99 gnutls_compression_method_t
100 gnutls_compression_get_id (const char *name)
102 gnutls_compression_method_t ret = GNUTLS_COMP_UNKNOWN;
104 GNUTLS_COMPRESSION_LOOP (if
105 (strcasecmp
106 (p->name + sizeof ("GNUTLS_COMP_") - 1,
107 name) == 0) ret = p->id);
109 return ret;
113 * gnutls_compression_list:
115 * Get a list of compression methods.
117 * Returns: a zero-terminated list of #gnutls_compression_method_t
118 * integers indicating the available compression methods.
120 const gnutls_compression_method_t *
121 gnutls_compression_list (void)
123 return supported_compressions;
126 /* return the tls number of the specified algorithm */
128 _gnutls_compression_get_num (gnutls_compression_method_t algorithm)
130 int ret = -1;
132 /* avoid prefix */
133 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->num);
135 return ret;
138 #ifdef HAVE_LIBZ
140 static int
141 get_wbits (gnutls_compression_method_t algorithm)
143 int ret = -1;
144 /* avoid prefix */
145 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->window_bits);
146 return ret;
149 static int
150 get_mem_level (gnutls_compression_method_t algorithm)
152 int ret = -1;
153 /* avoid prefix */
154 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->mem_level);
155 return ret;
158 static int
159 get_comp_level (gnutls_compression_method_t algorithm)
161 int ret = -1;
162 /* avoid prefix */
163 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->comp_level);
164 return ret;
167 #endif
169 /* returns the gnutls internal ID of the TLS compression
170 * method num
172 gnutls_compression_method_t
173 _gnutls_compression_get_id (int num)
175 gnutls_compression_method_t ret = -1;
177 /* avoid prefix */
178 GNUTLS_COMPRESSION_ALG_LOOP_NUM (ret = p->id);
180 return ret;
184 _gnutls_compression_is_ok (gnutls_compression_method_t algorithm)
186 ssize_t ret = -1;
187 GNUTLS_COMPRESSION_ALG_LOOP (ret = p->id);
188 if (ret >= 0)
189 ret = 0;
190 else
191 ret = 1;
192 return ret;
197 /* For compression */
199 #define MIN_PRIVATE_COMP_ALGO 0xEF
201 /* returns the TLS numbers of the compression methods we support
203 #define SUPPORTED_COMPRESSION_METHODS session->internals.priorities.compression.algorithms
205 _gnutls_supported_compression_methods (gnutls_session_t session,
206 uint8_t * comp, size_t comp_size)
208 unsigned int i, j;
210 if (comp_size < SUPPORTED_COMPRESSION_METHODS)
211 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
213 for (i = j = 0; i < SUPPORTED_COMPRESSION_METHODS; i++)
215 int tmp =
216 _gnutls_compression_get_num (session->internals.
217 priorities.compression.priority[i]);
219 /* remove private compression algorithms, if requested.
221 if (tmp == -1 || (tmp >= MIN_PRIVATE_COMP_ALGO &&
222 session->internals.enable_private == 0))
224 gnutls_assert ();
225 continue;
228 comp[j] = (uint8_t) tmp;
229 j++;
232 if (j == 0)
234 gnutls_assert ();
235 return GNUTLS_E_NO_COMPRESSION_ALGORITHMS;
237 return j;
241 /* The flag d is the direction (compress, decompress). Non zero is
242 * decompress.
244 int _gnutls_comp_init (comp_hd_st* handle, gnutls_compression_method_t method, int d)
246 handle->algo = method;
247 handle->handle = NULL;
249 switch (method)
251 case GNUTLS_COMP_DEFLATE:
252 #ifdef HAVE_LIBZ
254 int window_bits, mem_level;
255 int comp_level;
256 z_stream *zhandle;
257 int err;
259 window_bits = get_wbits (method);
260 mem_level = get_mem_level (method);
261 comp_level = get_comp_level (method);
263 handle->handle = gnutls_malloc (sizeof (z_stream));
264 if (handle->handle == NULL)
265 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
267 zhandle = handle->handle;
269 zhandle->zalloc = (alloc_func) 0;
270 zhandle->zfree = (free_func) 0;
271 zhandle->opaque = (voidpf) 0;
273 if (d)
274 err = inflateInit2 (zhandle, window_bits);
275 else
277 err = deflateInit2 (zhandle,
278 comp_level, Z_DEFLATED,
279 window_bits, mem_level, Z_DEFAULT_STRATEGY);
281 if (err != Z_OK)
283 gnutls_assert ();
284 gnutls_free (handle->handle);
285 return GNUTLS_E_COMPRESSION_FAILED;
288 break;
289 #endif
290 case GNUTLS_COMP_NULL:
291 case GNUTLS_COMP_UNKNOWN:
292 break;
293 default:
294 return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
297 return 0;
300 /* The flag d is the direction (compress, decompress). Non zero is
301 * decompress.
303 void
304 _gnutls_comp_deinit (comp_hd_st* handle, int d)
306 if (handle != NULL)
308 switch (handle->algo)
310 #ifdef HAVE_LIBZ
311 case GNUTLS_COMP_DEFLATE:
313 if (d)
314 inflateEnd (handle->handle);
315 else
316 deflateEnd (handle->handle);
317 break;
319 #endif
320 default:
321 break;
323 gnutls_free (handle->handle);
324 handle->handle = NULL;
328 /* These functions are memory consuming
332 _gnutls_compress (comp_hd_st *handle, const opaque * plain,
333 size_t plain_size, opaque * compressed,
334 size_t max_comp_size)
336 int compressed_size = GNUTLS_E_COMPRESSION_FAILED;
338 /* NULL compression is not handled here
340 if (handle == NULL)
342 gnutls_assert ();
343 return GNUTLS_E_INTERNAL_ERROR;
346 switch (handle->algo)
348 #ifdef HAVE_LIBZ
349 case GNUTLS_COMP_DEFLATE:
351 z_stream *zhandle;
352 int err;
354 zhandle = handle->handle;
356 zhandle->next_in = (Bytef *) plain;
357 zhandle->avail_in = plain_size;
358 zhandle->next_out = (Bytef *) compressed;
359 zhandle->avail_out = max_comp_size;
361 err = deflate (zhandle, Z_SYNC_FLUSH);
362 if (err != Z_OK || zhandle->avail_in != 0)
363 return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED);
366 compressed_size = max_comp_size - zhandle->avail_out;
367 break;
369 #endif
370 default:
371 gnutls_assert ();
372 return GNUTLS_E_INTERNAL_ERROR;
373 } /* switch */
375 #ifdef COMPRESSION_DEBUG
376 _gnutls_debug_log ("Compression ratio: %f\n",
377 (float) ((float) compressed_size / (float) plain_size));
378 #endif
380 return compressed_size;
386 _gnutls_decompress (comp_hd_st *handle, opaque * compressed,
387 size_t compressed_size, opaque * plain,
388 size_t max_plain_size)
390 int plain_size = GNUTLS_E_DECOMPRESSION_FAILED;
392 if (compressed_size > max_plain_size + EXTRA_COMP_SIZE)
394 gnutls_assert ();
395 return GNUTLS_E_DECOMPRESSION_FAILED;
398 /* NULL compression is not handled here
401 if (handle == NULL)
403 gnutls_assert ();
404 return GNUTLS_E_INTERNAL_ERROR;
407 switch (handle->algo)
409 #ifdef HAVE_LIBZ
410 case GNUTLS_COMP_DEFLATE:
412 z_stream *zhandle;
413 int err;
415 zhandle = handle->handle;
417 zhandle->next_in = (Bytef *) compressed;
418 zhandle->avail_in = compressed_size;
420 zhandle->next_out = (Bytef *) plain;
421 zhandle->avail_out = max_plain_size;
422 err = inflate (zhandle, Z_SYNC_FLUSH);
424 if (err != Z_OK)
425 return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED);
427 plain_size = max_plain_size - zhandle->avail_out;
428 break;
430 #endif
431 default:
432 gnutls_assert ();
433 return GNUTLS_E_INTERNAL_ERROR;
434 } /* switch */
436 return plain_size;