1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26
27 static int
lcs_init_compression_deflate(lws_comp_ctx_t * ctx,int decomp)28 lcs_init_compression_deflate(lws_comp_ctx_t *ctx, int decomp)
29 {
30 int n;
31
32 ctx->is_decompression = decomp;
33 ctx->u.deflate = lws_malloc(sizeof(*ctx->u.deflate), __func__);
34
35 if (!ctx->u.deflate)
36 return 2;
37
38 memset(ctx->u.deflate, 0, sizeof(*ctx->u.deflate));
39
40 if (!decomp &&
41 (n = deflateInit2(ctx->u.deflate, 1, Z_DEFLATED, -15, 8,
42 Z_DEFAULT_STRATEGY)) != Z_OK) {
43 lwsl_err("deflate init failed: %d\n", n);
44 lws_free_set_NULL(ctx->u.deflate);
45
46 return 1;
47 }
48
49 if (decomp &&
50 inflateInit2(ctx->u.deflate, 16 + 15) != Z_OK) {
51 lws_free_set_NULL(ctx->u.deflate);
52 return 1;
53 }
54
55 return 0;
56 }
57
58 static int
lcs_process_deflate(lws_comp_ctx_t * ctx,const void * in,size_t * ilen_iused,void * out,size_t * olen_oused)59 lcs_process_deflate(lws_comp_ctx_t *ctx, const void *in, size_t *ilen_iused,
60 void *out, size_t *olen_oused)
61 {
62 size_t olen_oused_in = *olen_oused;
63 int n;
64
65 ctx->u.deflate->next_in = (void *)in;
66 ctx->u.deflate->avail_in = *ilen_iused;
67
68 ctx->u.deflate->next_out = out;
69 ctx->u.deflate->avail_out = *olen_oused;
70
71 if (!ctx->is_decompression)
72 n = deflate(ctx->u.deflate, Z_SYNC_FLUSH);
73 else
74 n = inflate(ctx->u.deflate, Z_SYNC_FLUSH);
75
76 switch (n) {
77 case Z_NEED_DICT:
78 case Z_STREAM_ERROR:
79 case Z_DATA_ERROR:
80 case Z_MEM_ERROR:
81 lwsl_err("zlib error inflate %d\n", n);
82 return -1;
83 }
84
85 *ilen_iused -= ctx->u.deflate->avail_in;
86 *olen_oused -= ctx->u.deflate->avail_out;
87
88 /* it's ambiguous with zlib... */
89 ctx->may_have_more = (*olen_oused == olen_oused_in);
90
91 return n == Z_STREAM_END;
92 }
93
94 static void
lcs_destroy_deflate(lws_comp_ctx_t * ctx)95 lcs_destroy_deflate(lws_comp_ctx_t *ctx)
96 {
97 if (!ctx)
98 return;
99
100 if (!(*ctx).is_decompression)
101 deflateEnd((*ctx).u.deflate);
102 else
103 inflateEnd((*ctx).u.deflate);
104
105 lws_free_set_NULL(ctx->u.deflate);
106 }
107
108 struct lws_compression_support lcs_deflate = {
109 /* .encoding_name */ "deflate",
110 /* .init_compression */ lcs_init_compression_deflate,
111 /* .process */ lcs_process_deflate,
112 /* .destroy */ lcs_destroy_deflate,
113 };
114