aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/compression
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lib/compression')
-rw-r--r--src/core/lib/compression/algorithm_metadata.h19
-rw-r--r--src/core/lib/compression/compression.cc273
-rw-r--r--src/core/lib/compression/compression_internal.cc313
-rw-r--r--src/core/lib/compression/compression_internal.h118
-rw-r--r--src/core/lib/compression/message_compress.cc22
-rw-r--r--src/core/lib/compression/message_compress.h9
6 files changed, 544 insertions, 210 deletions
diff --git a/src/core/lib/compression/algorithm_metadata.h b/src/core/lib/compression/algorithm_metadata.h
index 3eb7088230..23333ac0c4 100644
--- a/src/core/lib/compression/algorithm_metadata.h
+++ b/src/core/lib/compression/algorithm_metadata.h
@@ -20,6 +20,7 @@
#define GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H
#include <grpc/compression.h>
+#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/transport/metadata.h"
#ifdef __cplusplus
@@ -30,14 +31,20 @@ extern "C" {
grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm);
-/** Return stream compression algorithm based metadata value */
-grpc_slice grpc_stream_compression_algorithm_slice(
- grpc_stream_compression_algorithm algorithm);
+/** Find compression algorithm based on passed in mdstr - returns
+ * GRPC_COMPRESS_ALGORITHM_COUNT on failure */
+grpc_compression_algorithm grpc_compression_algorithm_from_slice(
+ grpc_slice str);
-/** Return compression algorithm based metadata element (grpc-encoding: xxx) */
+/** Return compression algorithm based metadata element */
grpc_mdelem grpc_compression_encoding_mdelem(
grpc_compression_algorithm algorithm);
+/** Return message compression algorithm based metadata element (grpc-encoding:
+ * xxx) */
+grpc_mdelem grpc_message_compression_encoding_mdelem(
+ grpc_message_compression_algorithm algorithm);
+
/** Return stream compression algorithm based metadata element
* (content-encoding: xxx) */
grpc_mdelem grpc_stream_compression_encoding_mdelem(
@@ -45,8 +52,8 @@ grpc_mdelem grpc_stream_compression_encoding_mdelem(
/** Find compression algorithm based on passed in mdstr - returns
* GRPC_COMPRESS_ALGORITHM_COUNT on failure */
-grpc_compression_algorithm grpc_compression_algorithm_from_slice(
- grpc_slice str);
+grpc_message_compression_algorithm
+grpc_message_compression_algorithm_from_slice(grpc_slice str);
/** Find stream compression algorithm based on passed in mdstr - returns
* GRPC_STREAM_COMPRESS_ALGORITHM_COUNT on failure */
diff --git a/src/core/lib/compression/compression.cc b/src/core/lib/compression/compression.cc
index 1cfac23129..31349a58cd 100644
--- a/src/core/lib/compression/compression.cc
+++ b/src/core/lib/compression/compression.cc
@@ -23,40 +23,40 @@
#include <grpc/support/useful.h>
#include "src/core/lib/compression/algorithm_metadata.h"
+#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/static_metadata.h"
+int grpc_compression_algorithm_is_message(
+ grpc_compression_algorithm algorithm) {
+ return (algorithm >= GRPC_COMPRESS_MESSAGE_DEFLATE &&
+ algorithm <= GRPC_COMPRESS_MESSAGE_GZIP)
+ ? 1
+ : 0;
+}
+
+int grpc_compression_algorithm_is_stream(grpc_compression_algorithm algorithm) {
+ return (algorithm == GRPC_COMPRESS_STREAM_GZIP) ? 1 : 0;
+}
+
int grpc_compression_algorithm_parse(grpc_slice name,
grpc_compression_algorithm *algorithm) {
- /* we use strncmp not only because it's safer (even though in this case it
- * doesn't matter, given that we are comparing against string literals, but
- * because this way we needn't have "name" nil-terminated (useful for slice
- * data, for example) */
if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) {
*algorithm = GRPC_COMPRESS_NONE;
return 1;
- } else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) {
- *algorithm = GRPC_COMPRESS_GZIP;
- return 1;
} else if (grpc_slice_eq(name, GRPC_MDSTR_DEFLATE)) {
- *algorithm = GRPC_COMPRESS_DEFLATE;
- return 1;
- } else {
- return 0;
- }
-}
-
-int grpc_stream_compression_algorithm_parse(
- grpc_slice name, grpc_stream_compression_algorithm *algorithm) {
- if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) {
- *algorithm = GRPC_STREAM_COMPRESS_NONE;
+ *algorithm = GRPC_COMPRESS_MESSAGE_DEFLATE;
return 1;
} else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) {
- *algorithm = GRPC_STREAM_COMPRESS_GZIP;
+ *algorithm = GRPC_COMPRESS_MESSAGE_GZIP;
+ return 1;
+ } else if (grpc_slice_eq(name, GRPC_MDSTR_STREAM_GZIP)) {
+ *algorithm = GRPC_COMPRESS_STREAM_GZIP;
return 1;
} else {
return 0;
}
+ return 0;
}
int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
@@ -67,49 +67,69 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
case GRPC_COMPRESS_NONE:
*name = "identity";
return 1;
- case GRPC_COMPRESS_DEFLATE:
+ case GRPC_COMPRESS_MESSAGE_DEFLATE:
*name = "deflate";
return 1;
- case GRPC_COMPRESS_GZIP:
+ case GRPC_COMPRESS_MESSAGE_GZIP:
*name = "gzip";
return 1;
+ case GRPC_COMPRESS_STREAM_GZIP:
+ *name = "stream-gzip";
+ return 1;
case GRPC_COMPRESS_ALGORITHMS_COUNT:
return 0;
}
return 0;
}
-int grpc_stream_compression_algorithm_name(
- grpc_stream_compression_algorithm algorithm, const char **name) {
- GRPC_API_TRACE(
- "grpc_stream_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
- ((int)algorithm, name));
- switch (algorithm) {
- case GRPC_STREAM_COMPRESS_NONE:
- *name = "identity";
- return 1;
- case GRPC_STREAM_COMPRESS_GZIP:
- *name = "gzip";
- return 1;
- case GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT:
- return 0;
+grpc_compression_algorithm grpc_compression_algorithm_for_level(
+ grpc_compression_level level, uint32_t accepted_encodings) {
+ grpc_compression_algorithm algo;
+ if (level == GRPC_COMPRESS_LEVEL_NONE) {
+ return GRPC_COMPRESS_NONE;
+ } else if (level <= GRPC_COMPRESS_LEVEL_MESSAGE_HIGH) {
+ GPR_ASSERT(
+ grpc_compression_algorithm_from_message_stream_compression_algorithm(
+ &algo,
+ grpc_message_compression_algorithm_for_level(
+ grpc_compression_level_to_message_compression_level(level),
+ grpc_compression_bitset_to_message_bitset(accepted_encodings)),
+ (grpc_stream_compression_algorithm)0));
+ return algo;
+ } else if (level <= GRPC_COMPRESS_LEVEL_STREAM_HIGH) {
+ GPR_ASSERT(
+ grpc_compression_algorithm_from_message_stream_compression_algorithm(
+ &algo, (grpc_message_compression_algorithm)0,
+ grpc_stream_compression_algorithm_for_level(
+ grpc_compression_level_to_stream_compression_level(level),
+ grpc_compression_bitset_to_stream_bitset(accepted_encodings))));
+ return algo;
+ } else {
+ gpr_log(GPR_ERROR, "Unknown compression level: %d", level);
+ return GRPC_COMPRESS_NONE;
}
- return 0;
}
-grpc_compression_algorithm grpc_compression_algorithm_from_slice(
- grpc_slice str) {
- if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE;
- if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE)) return GRPC_COMPRESS_DEFLATE;
- if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_COMPRESS_GZIP;
- return GRPC_COMPRESS_ALGORITHMS_COUNT;
+void grpc_compression_options_init(grpc_compression_options *opts) {
+ memset(opts, 0, sizeof(*opts));
+ /* all enabled by default */
+ opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
}
-grpc_stream_compression_algorithm grpc_stream_compression_algorithm_from_slice(
- grpc_slice str) {
- if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_STREAM_COMPRESS_NONE;
- if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_STREAM_COMPRESS_GZIP;
- return GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT;
+void grpc_compression_options_enable_algorithm(
+ grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
+ GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm);
+}
+
+void grpc_compression_options_disable_algorithm(
+ grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
+ GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm);
+}
+
+int grpc_compression_options_is_algorithm_enabled(
+ const grpc_compression_options *opts,
+ grpc_compression_algorithm algorithm) {
+ return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
}
grpc_slice grpc_compression_algorithm_slice(
@@ -117,27 +137,27 @@ grpc_slice grpc_compression_algorithm_slice(
switch (algorithm) {
case GRPC_COMPRESS_NONE:
return GRPC_MDSTR_IDENTITY;
- case GRPC_COMPRESS_DEFLATE:
+ case GRPC_COMPRESS_MESSAGE_DEFLATE:
return GRPC_MDSTR_DEFLATE;
- case GRPC_COMPRESS_GZIP:
+ case GRPC_COMPRESS_MESSAGE_GZIP:
return GRPC_MDSTR_GZIP;
+ case GRPC_COMPRESS_STREAM_GZIP:
+ return GRPC_MDSTR_STREAM_GZIP;
case GRPC_COMPRESS_ALGORITHMS_COUNT:
return grpc_empty_slice();
}
return grpc_empty_slice();
}
-grpc_slice grpc_stream_compression_algorithm_slice(
- grpc_stream_compression_algorithm algorithm) {
- switch (algorithm) {
- case GRPC_STREAM_COMPRESS_NONE:
- return GRPC_MDSTR_IDENTITY;
- case GRPC_STREAM_COMPRESS_GZIP:
- return GRPC_MDSTR_GZIP;
- case GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT:
- return grpc_empty_slice();
- }
- return grpc_empty_slice();
+grpc_compression_algorithm grpc_compression_algorithm_from_slice(
+ grpc_slice str) {
+ if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE;
+ if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE))
+ return GRPC_COMPRESS_MESSAGE_DEFLATE;
+ if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_COMPRESS_MESSAGE_GZIP;
+ if (grpc_slice_eq(str, GRPC_MDSTR_STREAM_GZIP))
+ return GRPC_COMPRESS_STREAM_GZIP;
+ return GRPC_COMPRESS_ALGORITHMS_COUNT;
}
grpc_mdelem grpc_compression_encoding_mdelem(
@@ -145,139 +165,14 @@ grpc_mdelem grpc_compression_encoding_mdelem(
switch (algorithm) {
case GRPC_COMPRESS_NONE:
return GRPC_MDELEM_GRPC_ENCODING_IDENTITY;
- case GRPC_COMPRESS_DEFLATE:
+ case GRPC_COMPRESS_MESSAGE_DEFLATE:
return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
- case GRPC_COMPRESS_GZIP:
+ case GRPC_COMPRESS_MESSAGE_GZIP:
+ return GRPC_MDELEM_GRPC_ENCODING_GZIP;
+ case GRPC_COMPRESS_STREAM_GZIP:
return GRPC_MDELEM_GRPC_ENCODING_GZIP;
default:
break;
}
return GRPC_MDNULL;
}
-
-grpc_mdelem grpc_stream_compression_encoding_mdelem(
- grpc_stream_compression_algorithm algorithm) {
- switch (algorithm) {
- case GRPC_STREAM_COMPRESS_NONE:
- return GRPC_MDELEM_CONTENT_ENCODING_IDENTITY;
- case GRPC_STREAM_COMPRESS_GZIP:
- return GRPC_MDELEM_CONTENT_ENCODING_GZIP;
- default:
- break;
- }
- return GRPC_MDNULL;
-}
-
-void grpc_compression_options_init(grpc_compression_options *opts) {
- memset(opts, 0, sizeof(*opts));
- /* all enabled by default */
- opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
- opts->enabled_stream_compression_algorithms_bitset =
- (1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 1;
-}
-
-void grpc_compression_options_enable_algorithm(
- grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
- GPR_BITSET(&opts->enabled_algorithms_bitset, algorithm);
-}
-
-void grpc_compression_options_disable_algorithm(
- grpc_compression_options *opts, grpc_compression_algorithm algorithm) {
- GPR_BITCLEAR(&opts->enabled_algorithms_bitset, algorithm);
-}
-
-int grpc_compression_options_is_algorithm_enabled(
- const grpc_compression_options *opts,
- grpc_compression_algorithm algorithm) {
- return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
-}
-
-int grpc_compression_options_is_stream_compression_algorithm_enabled(
- const grpc_compression_options *opts,
- grpc_stream_compression_algorithm algorithm) {
- return GPR_BITGET(opts->enabled_stream_compression_algorithms_bitset,
- algorithm);
-}
-
-/* TODO(dgq): Add the ability to specify parameters to the individual
- * compression algorithms */
-grpc_compression_algorithm grpc_compression_algorithm_for_level(
- grpc_compression_level level, uint32_t accepted_encodings) {
- GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1,
- ((int)level));
- if (level > GRPC_COMPRESS_LEVEL_HIGH) {
- gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
- abort();
- }
-
- const size_t num_supported =
- GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */
- if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) {
- return GRPC_COMPRESS_NONE;
- }
-
- GPR_ASSERT(level > 0);
-
- /* Establish a "ranking" or compression algorithms in increasing order of
- * compression.
- * This is simplistic and we will probably want to introduce other dimensions
- * in the future (cpu/memory cost, etc). */
- const grpc_compression_algorithm algos_ranking[] = {GRPC_COMPRESS_GZIP,
- GRPC_COMPRESS_DEFLATE};
-
- /* intersect algos_ranking with the supported ones keeping the ranked order */
- grpc_compression_algorithm
- sorted_supported_algos[GRPC_COMPRESS_ALGORITHMS_COUNT];
- size_t algos_supported_idx = 0;
- for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) {
- const grpc_compression_algorithm alg = algos_ranking[i];
- for (size_t j = 0; j < num_supported; j++) {
- if (GPR_BITGET(accepted_encodings, alg) == 1) {
- /* if \a alg in supported */
- sorted_supported_algos[algos_supported_idx++] = alg;
- break;
- }
- }
- if (algos_supported_idx == num_supported) break;
- }
-
- switch (level) {
- case GRPC_COMPRESS_LEVEL_NONE:
- abort(); /* should have been handled already */
- case GRPC_COMPRESS_LEVEL_LOW:
- return sorted_supported_algos[0];
- case GRPC_COMPRESS_LEVEL_MED:
- return sorted_supported_algos[num_supported / 2];
- case GRPC_COMPRESS_LEVEL_HIGH:
- return sorted_supported_algos[num_supported - 1];
- default:
- abort();
- };
-}
-
-GRPCAPI grpc_stream_compression_algorithm
-grpc_stream_compression_algorithm_for_level(
- grpc_stream_compression_level level, uint32_t accepted_stream_encodings) {
- GRPC_API_TRACE("grpc_stream_compression_algorithm_for_level(level=%d)", 1,
- ((int)level));
- if (level > GRPC_STREAM_COMPRESS_LEVEL_HIGH) {
- gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
- abort();
- }
-
- switch (level) {
- case GRPC_STREAM_COMPRESS_LEVEL_NONE:
- return GRPC_STREAM_COMPRESS_NONE;
- case GRPC_STREAM_COMPRESS_LEVEL_LOW:
- case GRPC_STREAM_COMPRESS_LEVEL_MED:
- case GRPC_STREAM_COMPRESS_LEVEL_HIGH:
- if (GPR_BITGET(accepted_stream_encodings, GRPC_STREAM_COMPRESS_GZIP) ==
- 1) {
- return GRPC_STREAM_COMPRESS_GZIP;
- } else {
- return GRPC_STREAM_COMPRESS_NONE;
- }
- default:
- abort();
- }
-}
diff --git a/src/core/lib/compression/compression_internal.cc b/src/core/lib/compression/compression_internal.cc
new file mode 100644
index 0000000000..e31eb830f1
--- /dev/null
+++ b/src/core/lib/compression/compression_internal.cc
@@ -0,0 +1,313 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <grpc/compression.h>
+#include <grpc/support/useful.h>
+
+#include "src/core/lib/compression/algorithm_metadata.h"
+#include "src/core/lib/compression/compression_internal.h"
+#include "src/core/lib/surface/api_trace.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+/* Interfaces related to MD */
+
+grpc_message_compression_algorithm
+grpc_message_compression_algorithm_from_slice(grpc_slice str) {
+ if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY))
+ return GRPC_MESSAGE_COMPRESS_NONE;
+ if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE))
+ return GRPC_MESSAGE_COMPRESS_DEFLATE;
+ if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_MESSAGE_COMPRESS_GZIP;
+ return GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT;
+}
+
+grpc_stream_compression_algorithm grpc_stream_compression_algorithm_from_slice(
+ grpc_slice str) {
+ if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_STREAM_COMPRESS_NONE;
+ if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_STREAM_COMPRESS_GZIP;
+ return GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT;
+}
+
+grpc_mdelem grpc_message_compression_encoding_mdelem(
+ grpc_message_compression_algorithm algorithm) {
+ switch (algorithm) {
+ case GRPC_MESSAGE_COMPRESS_NONE:
+ return GRPC_MDELEM_GRPC_ENCODING_IDENTITY;
+ case GRPC_MESSAGE_COMPRESS_DEFLATE:
+ return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
+ case GRPC_MESSAGE_COMPRESS_GZIP:
+ return GRPC_MDELEM_GRPC_ENCODING_GZIP;
+ default:
+ break;
+ }
+ return GRPC_MDNULL;
+}
+
+grpc_mdelem grpc_stream_compression_encoding_mdelem(
+ grpc_stream_compression_algorithm algorithm) {
+ switch (algorithm) {
+ case GRPC_STREAM_COMPRESS_NONE:
+ return GRPC_MDELEM_CONTENT_ENCODING_IDENTITY;
+ case GRPC_STREAM_COMPRESS_GZIP:
+ return GRPC_MDELEM_CONTENT_ENCODING_GZIP;
+ default:
+ break;
+ }
+ return GRPC_MDNULL;
+}
+
+/* Interfaces performing transformation between compression algorithms and
+ * levels. */
+grpc_message_compression_level
+grpc_compression_level_to_message_compression_level(
+ grpc_compression_level level) {
+ if (level >= GRPC_COMPRESS_LEVEL_COUNT) {
+ return GRPC_MESSAGE_COMPRESS_LEVEL_NONE;
+ }
+ return (grpc_message_compression_level)(
+ (uint32_t)(level - GRPC_COMPRESS_LEVEL_NONE) +
+ (uint32_t)GRPC_MESSAGE_COMPRESS_LEVEL_NONE);
+}
+
+grpc_stream_compression_level
+grpc_compression_level_to_stream_compression_level(
+ grpc_compression_level level) {
+ if (level >= GRPC_COMPRESS_LEVEL_COUNT) {
+ return GRPC_STREAM_COMPRESS_LEVEL_NONE;
+ }
+ return (grpc_stream_compression_level)(
+ (uint32_t)(level - (GRPC_MESSAGE_COMPRESS_LEVEL_COUNT - 1) -
+ GRPC_COMPRESS_LEVEL_NONE) +
+ (uint32_t)GRPC_STREAM_COMPRESS_LEVEL_NONE);
+}
+
+grpc_message_compression_algorithm
+grpc_compression_algorithm_to_message_compression_algorithm(
+ grpc_compression_algorithm algo) {
+ switch (algo) {
+ case GRPC_COMPRESS_MESSAGE_DEFLATE:
+ return GRPC_MESSAGE_COMPRESS_DEFLATE;
+ case GRPC_COMPRESS_MESSAGE_GZIP:
+ return GRPC_MESSAGE_COMPRESS_GZIP;
+ default:
+ return GRPC_MESSAGE_COMPRESS_NONE;
+ }
+}
+
+grpc_stream_compression_algorithm
+grpc_compression_algorithm_to_stream_compression_algorithm(
+ grpc_compression_algorithm algo) {
+ switch (algo) {
+ case GRPC_COMPRESS_STREAM_GZIP:
+ return GRPC_STREAM_COMPRESS_GZIP;
+ default:
+ return GRPC_STREAM_COMPRESS_NONE;
+ }
+}
+
+uint32_t grpc_compression_bitset_to_message_bitset(uint32_t bitset) {
+ return bitset & ((1u << GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT) - 1);
+}
+
+uint32_t grpc_compression_bitset_to_stream_bitset(uint32_t bitset) {
+ uint32_t identity = (bitset & 1u);
+ uint32_t other_bits =
+ (bitset >> (GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT - 1)) &
+ ((1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 2);
+ return identity | other_bits;
+}
+
+uint32_t grpc_compression_bitset_from_message_stream_compression_bitset(
+ uint32_t message_bitset, uint32_t stream_bitset) {
+ uint32_t offset_stream_bitset =
+ (stream_bitset & 1u) |
+ ((stream_bitset & (~1u)) << (GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT - 1));
+ return message_bitset | offset_stream_bitset;
+}
+
+int grpc_compression_algorithm_from_message_stream_compression_algorithm(
+ grpc_compression_algorithm *algorithm,
+ grpc_message_compression_algorithm message_algorithm,
+ grpc_stream_compression_algorithm stream_algorithm) {
+ if (message_algorithm != GRPC_MESSAGE_COMPRESS_NONE &&
+ stream_algorithm != GRPC_STREAM_COMPRESS_NONE) {
+ *algorithm = GRPC_COMPRESS_NONE;
+ return 0;
+ }
+ if (message_algorithm == GRPC_MESSAGE_COMPRESS_NONE) {
+ switch (stream_algorithm) {
+ case GRPC_STREAM_COMPRESS_NONE:
+ *algorithm = GRPC_COMPRESS_NONE;
+ return 1;
+ case GRPC_STREAM_COMPRESS_GZIP:
+ *algorithm = GRPC_COMPRESS_STREAM_GZIP;
+ return 1;
+ default:
+ *algorithm = GRPC_COMPRESS_NONE;
+ return 0;
+ }
+ } else {
+ switch (message_algorithm) {
+ case GRPC_MESSAGE_COMPRESS_NONE:
+ *algorithm = GRPC_COMPRESS_NONE;
+ return 1;
+ case GRPC_MESSAGE_COMPRESS_DEFLATE:
+ *algorithm = GRPC_COMPRESS_MESSAGE_DEFLATE;
+ return 1;
+ case GRPC_MESSAGE_COMPRESS_GZIP:
+ *algorithm = GRPC_COMPRESS_MESSAGE_GZIP;
+ return 1;
+ default:
+ *algorithm = GRPC_COMPRESS_NONE;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/* Interfaces for message compression. */
+
+int grpc_message_compression_algorithm_name(
+ grpc_message_compression_algorithm algorithm, const char **name) {
+ GRPC_API_TRACE(
+ "grpc_message_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
+ ((int)algorithm, name));
+ switch (algorithm) {
+ case GRPC_MESSAGE_COMPRESS_NONE:
+ *name = "identity";
+ return 1;
+ case GRPC_MESSAGE_COMPRESS_DEFLATE:
+ *name = "deflate";
+ return 1;
+ case GRPC_MESSAGE_COMPRESS_GZIP:
+ *name = "gzip";
+ return 1;
+ case GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT:
+ return 0;
+ }
+ return 0;
+}
+
+/* TODO(dgq): Add the ability to specify parameters to the individual
+ * compression algorithms */
+grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level(
+ grpc_message_compression_level level, uint32_t accepted_encodings) {
+ GRPC_API_TRACE("grpc_message_compression_algorithm_for_level(level=%d)", 1,
+ ((int)level));
+ if (level > GRPC_MESSAGE_COMPRESS_LEVEL_HIGH) {
+ gpr_log(GPR_ERROR, "Unknown message compression level %d.", (int)level);
+ abort();
+ }
+
+ const size_t num_supported =
+ GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */
+ if (level == GRPC_MESSAGE_COMPRESS_LEVEL_NONE || num_supported == 0) {
+ return GRPC_MESSAGE_COMPRESS_NONE;
+ }
+
+ GPR_ASSERT(level > 0);
+
+ /* Establish a "ranking" or compression algorithms in increasing order of
+ * compression.
+ * This is simplistic and we will probably want to introduce other dimensions
+ * in the future (cpu/memory cost, etc). */
+ const grpc_message_compression_algorithm algos_ranking[] = {
+ GRPC_MESSAGE_COMPRESS_GZIP, GRPC_MESSAGE_COMPRESS_DEFLATE};
+
+ /* intersect algos_ranking with the supported ones keeping the ranked order */
+ grpc_message_compression_algorithm
+ sorted_supported_algos[GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT];
+ size_t algos_supported_idx = 0;
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) {
+ const grpc_message_compression_algorithm alg = algos_ranking[i];
+ for (size_t j = 0; j < num_supported; j++) {
+ if (GPR_BITGET(accepted_encodings, alg) == 1) {
+ /* if \a alg in supported */
+ sorted_supported_algos[algos_supported_idx++] = alg;
+ break;
+ }
+ }
+ if (algos_supported_idx == num_supported) break;
+ }
+
+ switch (level) {
+ case GRPC_MESSAGE_COMPRESS_LEVEL_NONE:
+ abort(); /* should have been handled already */
+ case GRPC_MESSAGE_COMPRESS_LEVEL_LOW:
+ return sorted_supported_algos[0];
+ case GRPC_MESSAGE_COMPRESS_LEVEL_MED:
+ return sorted_supported_algos[num_supported / 2];
+ case GRPC_MESSAGE_COMPRESS_LEVEL_HIGH:
+ return sorted_supported_algos[num_supported - 1];
+ default:
+ abort();
+ };
+}
+
+int grpc_message_compression_algorithm_parse(
+ grpc_slice value, grpc_message_compression_algorithm *algorithm) {
+ if (grpc_slice_eq(value, GRPC_MDSTR_IDENTITY)) {
+ *algorithm = GRPC_MESSAGE_COMPRESS_NONE;
+ return 1;
+ } else if (grpc_slice_eq(value, GRPC_MDSTR_DEFLATE)) {
+ *algorithm = GRPC_MESSAGE_COMPRESS_DEFLATE;
+ return 1;
+ } else if (grpc_slice_eq(value, GRPC_MDSTR_GZIP)) {
+ *algorithm = GRPC_MESSAGE_COMPRESS_GZIP;
+ return 1;
+ } else {
+ return 0;
+ }
+ return 0;
+}
+
+/* Interfaces for stream compression. */
+
+grpc_stream_compression_algorithm grpc_stream_compression_algorithm_for_level(
+ grpc_stream_compression_level level, uint32_t accepted_encodings) {
+ GRPC_API_TRACE("grpc_stream_compression_algorithm_for_level(level=%d)", 1,
+ ((int)level));
+ if (level > GRPC_STREAM_COMPRESS_LEVEL_HIGH) {
+ gpr_log(GPR_ERROR, "Unknown stream compression level %d.", (int)level);
+ abort();
+ }
+
+ /* TODO(mxyan): Use more sophisticated scheme when more algorithms added. */
+ if (level != GRPC_STREAM_COMPRESS_LEVEL_NONE &&
+ GPR_BITGET(accepted_encodings, GRPC_STREAM_COMPRESS_GZIP)) {
+ return GRPC_STREAM_COMPRESS_GZIP;
+ }
+ return GRPC_STREAM_COMPRESS_NONE;
+}
+
+int grpc_stream_compression_algorithm_parse(
+ grpc_slice value, grpc_stream_compression_algorithm *algorithm) {
+ if (grpc_slice_eq(value, GRPC_MDSTR_IDENTITY)) {
+ *algorithm = GRPC_STREAM_COMPRESS_NONE;
+ return 1;
+ } else if (grpc_slice_eq(value, GRPC_MDSTR_GZIP)) {
+ *algorithm = GRPC_STREAM_COMPRESS_GZIP;
+ return 1;
+ } else {
+ return 0;
+ }
+ return 0;
+}
diff --git a/src/core/lib/compression/compression_internal.h b/src/core/lib/compression/compression_internal.h
new file mode 100644
index 0000000000..aab5324b67
--- /dev/null
+++ b/src/core/lib/compression/compression_internal.h
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_COMPRESSION_COMPRESSION_INTERNAL_H
+#define GRPC_CORE_LIB_COMPRESSION_COMPRESSION_INTERNAL_H
+
+#include <grpc/impl/codegen/compression_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ GRPC_MESSAGE_COMPRESS_NONE = 0,
+ GRPC_MESSAGE_COMPRESS_DEFLATE,
+ GRPC_MESSAGE_COMPRESS_GZIP,
+ /* TODO(ctiller): snappy */
+ GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT
+} grpc_message_compression_algorithm;
+
+/** Stream compresssion algorithms supported by gRPC */
+typedef enum {
+ GRPC_STREAM_COMPRESS_NONE = 0,
+ GRPC_STREAM_COMPRESS_GZIP,
+ GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT
+} grpc_stream_compression_algorithm;
+
+/** Compression levels allow a party with knowledge of its peer's accepted
+ * encodings to request compression in an abstract way. The level-algorithm
+ * mapping is performed internally and depends on the peer's supported
+ * compression algorithms. */
+typedef enum {
+ GRPC_MESSAGE_COMPRESS_LEVEL_NONE = 0,
+ GRPC_MESSAGE_COMPRESS_LEVEL_LOW,
+ GRPC_MESSAGE_COMPRESS_LEVEL_MED,
+ GRPC_MESSAGE_COMPRESS_LEVEL_HIGH,
+ GRPC_MESSAGE_COMPRESS_LEVEL_COUNT
+} grpc_message_compression_level;
+
+/** Compression levels for stream compression algorithms */
+typedef enum {
+ GRPC_STREAM_COMPRESS_LEVEL_NONE = 0,
+ GRPC_STREAM_COMPRESS_LEVEL_LOW,
+ GRPC_STREAM_COMPRESS_LEVEL_MED,
+ GRPC_STREAM_COMPRESS_LEVEL_HIGH,
+ GRPC_STREAM_COMPRESS_LEVEL_COUNT
+} grpc_stream_compression_level;
+
+/* Interfaces performing transformation between compression algorithms and
+ * levels. */
+
+grpc_message_compression_level
+grpc_compression_level_to_message_compression_level(
+ grpc_compression_level level);
+
+grpc_stream_compression_level
+grpc_compression_level_to_stream_compression_level(
+ grpc_compression_level level);
+
+grpc_message_compression_algorithm
+grpc_compression_algorithm_to_message_compression_algorithm(
+ grpc_compression_algorithm algo);
+
+grpc_stream_compression_algorithm
+grpc_compression_algorithm_to_stream_compression_algorithm(
+ grpc_compression_algorithm algo);
+
+uint32_t grpc_compression_bitset_to_message_bitset(uint32_t bitset);
+
+uint32_t grpc_compression_bitset_to_stream_bitset(uint32_t bitset);
+
+uint32_t grpc_compression_bitset_from_message_stream_compression_bitset(
+ uint32_t message_bitset, uint32_t stream_bitset);
+
+int grpc_compression_algorithm_from_message_stream_compression_algorithm(
+ grpc_compression_algorithm *algorithm,
+ grpc_message_compression_algorithm message_algorithm,
+ grpc_stream_compression_algorithm stream_algorithm);
+
+/* Interfaces for message compression. */
+
+int grpc_message_compression_algorithm_name(
+ grpc_message_compression_algorithm algorithm, const char **name);
+
+grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level(
+ grpc_message_compression_level level, uint32_t accepted_encodings);
+
+int grpc_message_compression_algorithm_parse(
+ grpc_slice value, grpc_message_compression_algorithm *algorithm);
+
+/* Interfaces for stream compression. */
+
+grpc_stream_compression_algorithm grpc_stream_compression_algorithm_for_level(
+ grpc_stream_compression_level level, uint32_t accepted_encodings);
+
+int grpc_stream_compression_algorithm_parse(
+ grpc_slice value, grpc_stream_compression_algorithm *algorithm);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_CORE_LIB_COMPRESSION_COMPRESSION_INTERNAL_H */
diff --git a/src/core/lib/compression/message_compress.cc b/src/core/lib/compression/message_compress.cc
index c051e28864..d174992355 100644
--- a/src/core/lib/compression/message_compress.cc
+++ b/src/core/lib/compression/message_compress.cc
@@ -143,18 +143,18 @@ static int copy(grpc_slice_buffer* input, grpc_slice_buffer* output) {
}
static int compress_inner(grpc_exec_ctx* exec_ctx,
- grpc_compression_algorithm algorithm,
+ grpc_message_compression_algorithm algorithm,
grpc_slice_buffer* input, grpc_slice_buffer* output) {
switch (algorithm) {
- case GRPC_COMPRESS_NONE:
+ case GRPC_MESSAGE_COMPRESS_NONE:
/* the fallback path always needs to be send uncompressed: we simply
rely on that here */
return 0;
- case GRPC_COMPRESS_DEFLATE:
+ case GRPC_MESSAGE_COMPRESS_DEFLATE:
return zlib_compress(exec_ctx, input, output, 0);
- case GRPC_COMPRESS_GZIP:
+ case GRPC_MESSAGE_COMPRESS_GZIP:
return zlib_compress(exec_ctx, input, output, 1);
- case GRPC_COMPRESS_ALGORITHMS_COUNT:
+ case GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT:
break;
}
gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm);
@@ -162,7 +162,7 @@ static int compress_inner(grpc_exec_ctx* exec_ctx,
}
int grpc_msg_compress(grpc_exec_ctx* exec_ctx,
- grpc_compression_algorithm algorithm,
+ grpc_message_compression_algorithm algorithm,
grpc_slice_buffer* input, grpc_slice_buffer* output) {
if (!compress_inner(exec_ctx, algorithm, input, output)) {
copy(input, output);
@@ -172,16 +172,16 @@ int grpc_msg_compress(grpc_exec_ctx* exec_ctx,
}
int grpc_msg_decompress(grpc_exec_ctx* exec_ctx,
- grpc_compression_algorithm algorithm,
+ grpc_message_compression_algorithm algorithm,
grpc_slice_buffer* input, grpc_slice_buffer* output) {
switch (algorithm) {
- case GRPC_COMPRESS_NONE:
+ case GRPC_MESSAGE_COMPRESS_NONE:
return copy(input, output);
- case GRPC_COMPRESS_DEFLATE:
+ case GRPC_MESSAGE_COMPRESS_DEFLATE:
return zlib_decompress(exec_ctx, input, output, 0);
- case GRPC_COMPRESS_GZIP:
+ case GRPC_MESSAGE_COMPRESS_GZIP:
return zlib_decompress(exec_ctx, input, output, 1);
- case GRPC_COMPRESS_ALGORITHMS_COUNT:
+ case GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT:
break;
}
gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm);
diff --git a/src/core/lib/compression/message_compress.h b/src/core/lib/compression/message_compress.h
index d2545a02c2..7c2eb99443 100644
--- a/src/core/lib/compression/message_compress.h
+++ b/src/core/lib/compression/message_compress.h
@@ -19,9 +19,10 @@
#ifndef GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H
#define GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H
-#include <grpc/compression.h>
#include <grpc/slice_buffer.h>
+#include "src/core/lib/compression/compression_internal.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -30,18 +31,18 @@ extern "C" {
On success, appends compressed slices to output and returns 1.
On failure, appends uncompressed slices to output and returns 0. */
int grpc_msg_compress(grpc_exec_ctx* exec_ctx,
- grpc_compression_algorithm algorithm,
+ grpc_message_compression_algorithm algorithm,
grpc_slice_buffer* input, grpc_slice_buffer* output);
/* decompress 'input' to 'output' using 'algorithm'.
On success, appends slices to output and returns 1.
On failure, output is unchanged, and returns 0. */
int grpc_msg_decompress(grpc_exec_ctx* exec_ctx,
- grpc_compression_algorithm algorithm,
+ grpc_message_compression_algorithm algorithm,
grpc_slice_buffer* input, grpc_slice_buffer* output);
#ifdef __cplusplus
}
#endif
-#endif /* GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H */ \ No newline at end of file
+#endif /* GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H */