blob: 2810a38b68afc143652ac168ed00ea7b6626d197 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tillerbefa1ff2016-01-05 07:54:11 -08003 * Copyright 2015-2016, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
David Garcia Quintase29feb22015-06-15 18:08:13 -070034#include <stdlib.h>
David Garcia Quintasfc0fa332015-06-25 18:11:07 -070035#include <string.h>
David Garcia Quintasbeac88c2015-08-10 13:39:52 -070036
David Garcia Quintas59f905d2015-06-08 16:31:19 -070037#include <grpc/compression.h>
David Garcia Quintasbeac88c2015-08-10 13:39:52 -070038#include <grpc/support/useful.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039
Craig Tillerebdef9d2015-11-19 17:09:49 -080040#include "src/core/compression/algorithm_metadata.h"
Masood Malekghassemi76c3d742015-08-19 18:22:53 -070041#include "src/core/surface/api_trace.h"
Craig Tillerebdef9d2015-11-19 17:09:49 -080042#include "src/core/transport/static_metadata.h"
Masood Malekghassemi76c3d742015-08-19 18:22:53 -070043
Craig Tillera82950e2015-09-22 12:33:20 -070044int grpc_compression_algorithm_parse(const char *name, size_t name_length,
45 grpc_compression_algorithm *algorithm) {
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -070046 /* we use strncmp not only because it's safer (even though in this case it
47 * doesn't matter, given that we are comparing against string literals, but
48 * because this way we needn't have "name" nil-terminated (useful for slice
49 * data, for example) */
Masood Malekghassemi76c3d742015-08-19 18:22:53 -070050 GRPC_API_TRACE(
51 "grpc_compression_algorithm_parse("
Craig Tiller4de3e4f2015-10-05 08:55:50 -070052 "name=%*.*s, name_length=%lu, algorithm=%p)",
53 5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
54 algorithm));
Craig Tillera82950e2015-09-22 12:33:20 -070055 if (name_length == 0) {
56 return 0;
57 }
58 if (strncmp(name, "identity", name_length) == 0) {
59 *algorithm = GRPC_COMPRESS_NONE;
60 } else if (strncmp(name, "gzip", name_length) == 0) {
61 *algorithm = GRPC_COMPRESS_GZIP;
62 } else if (strncmp(name, "deflate", name_length) == 0) {
63 *algorithm = GRPC_COMPRESS_DEFLATE;
64 } else {
65 return 0;
66 }
David Garcia Quintasfc0fa332015-06-25 18:11:07 -070067 return 1;
68}
69
Craig Tillera82950e2015-09-22 12:33:20 -070070int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
71 char **name) {
Masood Malekghassemi76c3d742015-08-19 18:22:53 -070072 GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
73 ((int)algorithm, name));
Craig Tillera82950e2015-09-22 12:33:20 -070074 switch (algorithm) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080075 case GRPC_COMPRESS_NONE:
David Garcia Quintascddd95b2015-08-13 16:59:16 -070076 *name = "identity";
Craig Tillerebdef9d2015-11-19 17:09:49 -080077 return 1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078 case GRPC_COMPRESS_DEFLATE:
David Garcia Quintasfc0fa332015-06-25 18:11:07 -070079 *name = "deflate";
Craig Tillerebdef9d2015-11-19 17:09:49 -080080 return 1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080081 case GRPC_COMPRESS_GZIP:
David Garcia Quintasfc0fa332015-06-25 18:11:07 -070082 *name = "gzip";
Craig Tillerebdef9d2015-11-19 17:09:49 -080083 return 1;
84 case GRPC_COMPRESS_ALGORITHMS_COUNT:
David Garcia Quintasfc0fa332015-06-25 18:11:07 -070085 return 0;
Craig Tillera82950e2015-09-22 12:33:20 -070086 }
David Garcia Quintas48ec8062015-12-11 14:04:59 -080087 return 0;
Craig Tillerebdef9d2015-11-19 17:09:49 -080088}
89
90grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
91 grpc_mdstr *str) {
92 if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
93 if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
94 if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
95 return GRPC_COMPRESS_ALGORITHMS_COUNT;
96}
97
98grpc_mdstr *grpc_compression_algorithm_mdstr(
99 grpc_compression_algorithm algorithm) {
100 switch (algorithm) {
101 case GRPC_COMPRESS_NONE:
102 return GRPC_MDSTR_IDENTITY;
103 case GRPC_COMPRESS_DEFLATE:
104 return GRPC_MDSTR_DEFLATE;
105 case GRPC_COMPRESS_GZIP:
106 return GRPC_MDSTR_GZIP;
107 case GRPC_COMPRESS_ALGORITHMS_COUNT:
108 return NULL;
109 }
110 return NULL;
111}
112
113grpc_mdelem *grpc_compression_encoding_mdelem(
114 grpc_compression_algorithm algorithm) {
115 switch (algorithm) {
116 case GRPC_COMPRESS_NONE:
117 return GRPC_MDELEM_GRPC_ENCODING_IDENTITY;
118 case GRPC_COMPRESS_DEFLATE:
119 return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
120 case GRPC_COMPRESS_GZIP:
121 return GRPC_MDELEM_GRPC_ENCODING_GZIP;
David Garcia Quintas48ec8062015-12-11 14:04:59 -0800122 default:
123 break;
Craig Tillerebdef9d2015-11-19 17:09:49 -0800124 }
125 return NULL;
Craig Tiller190d3602015-02-18 09:23:38 -0800126}
David Garcia Quintase29feb22015-06-15 18:08:13 -0700127
128/* TODO(dgq): Add the ability to specify parameters to the individual
129 * compression algorithms */
Craig Tillera82950e2015-09-22 12:33:20 -0700130grpc_compression_algorithm grpc_compression_algorithm_for_level(
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700131 grpc_compression_level level, uint32_t accepted_encodings) {
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700132 GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1,
133 ((int)level));
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700134 if (level > GRPC_COMPRESS_LEVEL_HIGH) {
135 gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
136 abort();
137 }
138
139 const size_t num_supported =
140 GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */
141 if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) {
142 return GRPC_COMPRESS_NONE;
143 }
144
145 GPR_ASSERT(level > 0);
146
147 /* Establish a "ranking" or compression algorithms in increasing order of
148 * compression.
149 * This is simplistic and we will probably want to introduce other dimensions
150 * in the future (cpu/memory cost, etc). */
151 const grpc_compression_algorithm algos_ranking[] = {GRPC_COMPRESS_GZIP,
152 GRPC_COMPRESS_DEFLATE};
153
154 /* intersect algos_ranking with the supported ones keeping the ranked order */
David Garcia Quintas0a5fce82016-03-18 09:58:55 -0700155 grpc_compression_algorithm
156 sorted_supported_algos[GRPC_COMPRESS_ALGORITHMS_COUNT];
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700157 size_t algos_supported_idx = 0;
158 for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) {
159 const grpc_compression_algorithm alg = algos_ranking[i];
160 for (size_t j = 0; j < num_supported; j++) {
161 if (GPR_BITGET(accepted_encodings, alg) == 1) {
162 /* if \a alg in supported */
163 sorted_supported_algos[algos_supported_idx++] = alg;
164 break;
165 }
166 }
167 if (algos_supported_idx == num_supported) break;
168 }
169
Craig Tillera82950e2015-09-22 12:33:20 -0700170 switch (level) {
David Garcia Quintasf74a49e2015-06-18 17:22:45 -0700171 case GRPC_COMPRESS_LEVEL_NONE:
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700172 abort(); /* should have been handled already */
David Garcia Quintase29feb22015-06-15 18:08:13 -0700173 case GRPC_COMPRESS_LEVEL_LOW:
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700174 return sorted_supported_algos[0];
David Garcia Quintase29feb22015-06-15 18:08:13 -0700175 case GRPC_COMPRESS_LEVEL_MED:
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700176 return sorted_supported_algos[num_supported / 2];
David Garcia Quintase29feb22015-06-15 18:08:13 -0700177 case GRPC_COMPRESS_LEVEL_HIGH:
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700178 return sorted_supported_algos[num_supported - 1];
David Garcia Quintase29feb22015-06-15 18:08:13 -0700179 default:
yang-g3fd28362016-01-04 10:08:58 -0800180 abort();
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -0700181 };
David Garcia Quintasfc0fa332015-06-25 18:11:07 -0700182}
David Garcia Quintasbeac88c2015-08-10 13:39:52 -0700183
Craig Tillera82950e2015-09-22 12:33:20 -0700184void grpc_compression_options_init(grpc_compression_options *opts) {
Craig Tilleraf73d782015-09-22 09:30:46 -0700185 opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
David Garcia Quintasbeac88c2015-08-10 13:39:52 -0700186 opts->default_compression_algorithm = GRPC_COMPRESS_NONE;
187}
188
Craig Tillera82950e2015-09-22 12:33:20 -0700189void grpc_compression_options_enable_algorithm(
190 grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
191 GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm);
David Garcia Quintasbeac88c2015-08-10 13:39:52 -0700192}
193
Craig Tillera82950e2015-09-22 12:33:20 -0700194void grpc_compression_options_disable_algorithm(
195 grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
196 GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm);
David Garcia Quintasbeac88c2015-08-10 13:39:52 -0700197}
198
Craig Tillera82950e2015-09-22 12:33:20 -0700199int grpc_compression_options_is_algorithm_enabled(
200 const grpc_compression_options *opts,
201 grpc_compression_algorithm algorithm) {
202 return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
David Garcia Quintasbeac88c2015-08-10 13:39:52 -0700203}