diff --git a/BUILD b/BUILD index 6f92ef3858f..9f1ab2a5384 100644 --- a/BUILD +++ b/BUILD @@ -571,6 +571,7 @@ grpc_cc_library( "src/core/lib/channel/handshaker_registry.c", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", + "src/core/lib/compression/stream_compression.c", "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", @@ -697,6 +698,7 @@ grpc_cc_library( "src/core/lib/channel/handshaker_registry.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", + "src/core/lib/compression/stream_compression.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ee9490c250..5413bbcc0f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -528,6 +528,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c socket_utils_test) endif() add_dependencies(buildtests_c status_conversion_test) +add_dependencies(buildtests_c stream_compression_test) add_dependencies(buildtests_c stream_owned_slice_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c tcp_client_posix_test) @@ -954,6 +955,7 @@ add_library(grpc src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c + src/core/lib/compression/stream_compression.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -1295,6 +1297,7 @@ add_library(grpc_cronet src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c + src/core/lib/compression/stream_compression.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -1614,6 +1617,7 @@ add_library(grpc_test_util src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c + src/core/lib/compression/stream_compression.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -1876,6 +1880,7 @@ add_library(grpc_unsecure src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c + src/core/lib/compression/stream_compression.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -2534,6 +2539,7 @@ add_library(grpc++_cronet src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c + src/core/lib/compression/stream_compression.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -8181,6 +8187,37 @@ target_link_libraries(status_conversion_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(stream_compression_test + test/core/compression/stream_compression_test.c +) + + +target_include_directories(stream_compression_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_BUILD_INCLUDE_DIR} + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CARES_PLATFORM_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include +) + +target_link_libraries(stream_compression_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(stream_owned_slice_test test/core/transport/stream_owned_slice_test.c ) diff --git a/Makefile b/Makefile index 72468f8f928..210d6768222 100644 --- a/Makefile +++ b/Makefile @@ -1075,6 +1075,7 @@ sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test +stream_compression_test: $(BINDIR)/$(CONFIG)/stream_compression_test stream_owned_slice_test: $(BINDIR)/$(CONFIG)/stream_owned_slice_test tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test tcp_client_uv_test: $(BINDIR)/$(CONFIG)/tcp_client_uv_test @@ -1445,6 +1446,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/sockaddr_utils_test \ $(BINDIR)/$(CONFIG)/socket_utils_test \ $(BINDIR)/$(CONFIG)/status_conversion_test \ + $(BINDIR)/$(CONFIG)/stream_compression_test \ $(BINDIR)/$(CONFIG)/stream_owned_slice_test \ $(BINDIR)/$(CONFIG)/tcp_client_posix_test \ $(BINDIR)/$(CONFIG)/tcp_client_uv_test \ @@ -1929,6 +1931,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 ) $(E) "[RUN] Testing status_conversion_test" $(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 ) + $(E) "[RUN] Testing stream_compression_test" + $(Q) $(BINDIR)/$(CONFIG)/stream_compression_test || ( echo test stream_compression_test failed ; exit 1 ) $(E) "[RUN] Testing stream_owned_slice_test" $(Q) $(BINDIR)/$(CONFIG)/stream_owned_slice_test || ( echo test stream_owned_slice_test failed ; exit 1 ) $(E) "[RUN] Testing tcp_client_posix_test" @@ -2891,6 +2895,7 @@ LIBGRPC_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ + src/core/lib/compression/stream_compression.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -3230,6 +3235,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ + src/core/lib/compression/stream_compression.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -3546,6 +3552,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ + src/core/lib/compression/stream_compression.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -3780,6 +3787,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ + src/core/lib/compression/stream_compression.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -4422,6 +4430,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ + src/core/lib/compression/stream_compression.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -12265,6 +12274,38 @@ endif endif +STREAM_COMPRESSION_TEST_SRC = \ + test/core/compression/stream_compression_test.c \ + +STREAM_COMPRESSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STREAM_COMPRESSION_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/stream_compression_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/stream_compression_test: $(STREAM_COMPRESSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(STREAM_COMPRESSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/stream_compression_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/compression/stream_compression_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_stream_compression_test: $(STREAM_COMPRESSION_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(STREAM_COMPRESSION_TEST_OBJS:.o=.dep) +endif +endif + + STREAM_OWNED_SLICE_TEST_SRC = \ test/core/transport/stream_owned_slice_test.c \ diff --git a/binding.gyp b/binding.gyp index 00fbe70fee8..ae78d931f2d 100644 --- a/binding.gyp +++ b/binding.gyp @@ -645,6 +645,7 @@ 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', + 'src/core/lib/compression/stream_compression.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', diff --git a/build.yaml b/build.yaml index 1b9eb63bcdc..581fa65a235 100644 --- a/build.yaml +++ b/build.yaml @@ -191,6 +191,7 @@ filegroups: - src/core/lib/channel/handshaker_registry.h - src/core/lib/compression/algorithm_metadata.h - src/core/lib/compression/message_compress.h + - src/core/lib/compression/stream_compression.h - src/core/lib/http/format_request.h - src/core/lib/http/httpcli.h - src/core/lib/http/parser.h @@ -300,6 +301,7 @@ filegroups: - src/core/lib/channel/handshaker_registry.c - src/core/lib/compression/compression.c - src/core/lib/compression/message_compress.c + - src/core/lib/compression/stream_compression.c - src/core/lib/http/format_request.c - src/core/lib/http/httpcli.c - src/core/lib/http/parser.c @@ -3009,6 +3011,16 @@ targets: - grpc - gpr_test_util - gpr +- name: stream_compression_test + build: test + language: c + src: + - test/core/compression/stream_compression_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr - name: stream_owned_slice_test build: test language: c diff --git a/config.m4 b/config.m4 index 71e5776d851..e214f9c5464 100644 --- a/config.m4 +++ b/config.m4 @@ -95,6 +95,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ + src/core/lib/compression/stream_compression.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ diff --git a/config.w32 b/config.w32 index cd374bae650..6d50712fb54 100644 --- a/config.w32 +++ b/config.w32 @@ -72,6 +72,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\channel\\handshaker_registry.c " + "src\\core\\lib\\compression\\compression.c " + "src\\core\\lib\\compression\\message_compress.c " + + "src\\core\\lib\\compression\\stream_compression.c " + "src\\core\\lib\\http\\format_request.c " + "src\\core\\lib\\http\\httpcli.c " + "src\\core\\lib\\http\\parser.c " + diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index fc51a92daf8..cf3fc3598a2 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -254,6 +254,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker_registry.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', + 'src/core/lib/compression/stream_compression.h', 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', @@ -467,6 +468,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', + 'src/core/lib/compression/stream_compression.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', @@ -734,6 +736,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker_registry.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', + 'src/core/lib/compression/stream_compression.h', 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', diff --git a/grpc.gemspec b/grpc.gemspec index ab4a634c9b0..a87c113b04b 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -186,6 +186,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/handshaker_registry.h ) s.files += %w( src/core/lib/compression/algorithm_metadata.h ) s.files += %w( src/core/lib/compression/message_compress.h ) + s.files += %w( src/core/lib/compression/stream_compression.h ) s.files += %w( src/core/lib/http/format_request.h ) s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) @@ -403,6 +404,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/handshaker_registry.c ) s.files += %w( src/core/lib/compression/compression.c ) s.files += %w( src/core/lib/compression/message_compress.c ) + s.files += %w( src/core/lib/compression/stream_compression.c ) s.files += %w( src/core/lib/http/format_request.c ) s.files += %w( src/core/lib/http/httpcli.c ) s.files += %w( src/core/lib/http/parser.c ) diff --git a/package.xml b/package.xml index 602800b1b51..256a21d017b 100644 --- a/package.xml +++ b/package.xml @@ -200,6 +200,7 @@ + @@ -417,6 +418,7 @@ + diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index bd25f69a1de..731ebf400f7 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -33,6 +33,7 @@ #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/compression/stream_compression.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/timer.h" diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index a5b67e5abaa..4563b78e755 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -33,6 +33,7 @@ #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" +#include "src/core/lib/compression/stream_compression.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/timer.h" diff --git a/src/core/lib/compression/stream_compression.c b/src/core/lib/compression/stream_compression.c new file mode 100644 index 00000000000..df13d53e06f --- /dev/null +++ b/src/core/lib/compression/stream_compression.c @@ -0,0 +1,191 @@ +/* + * + * 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. + * + */ + +#include +#include + +#include "src/core/lib/compression/stream_compression.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/slice/slice_internal.h" + +#define OUTPUT_BLOCK_SIZE (1024) + +static bool gzip_flate(grpc_stream_compression_context *ctx, + grpc_slice_buffer *in, grpc_slice_buffer *out, + size_t *output_size, size_t max_output_size, int flush, + bool *end_of_context) { + GPR_ASSERT(flush == 0 || flush == Z_SYNC_FLUSH || flush == Z_FINISH); + /* Full flush is not allowed when inflating. */ + GPR_ASSERT(!(ctx->flate == inflate && (flush == Z_FINISH))); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + int r; + bool eoc = false; + size_t original_max_output_size = max_output_size; + while (max_output_size > 0 && (in->length > 0 || flush) && !eoc) { + size_t slice_size = max_output_size < OUTPUT_BLOCK_SIZE ? max_output_size + : OUTPUT_BLOCK_SIZE; + grpc_slice slice_out = GRPC_SLICE_MALLOC(slice_size); + ctx->zs.avail_out = (uInt)slice_size; + ctx->zs.next_out = GRPC_SLICE_START_PTR(slice_out); + while (ctx->zs.avail_out > 0 && in->length > 0 && !eoc) { + grpc_slice slice = grpc_slice_buffer_take_first(in); + ctx->zs.avail_in = (uInt)GRPC_SLICE_LENGTH(slice); + ctx->zs.next_in = GRPC_SLICE_START_PTR(slice); + r = ctx->flate(&ctx->zs, Z_NO_FLUSH); + if (r < 0 && r != Z_BUF_ERROR) { + gpr_log(GPR_ERROR, "zlib error (%d)", r); + grpc_slice_unref_internal(&exec_ctx, slice_out); + grpc_exec_ctx_finish(&exec_ctx); + return false; + } else if (r == Z_STREAM_END && ctx->flate == inflate) { + eoc = true; + } + if (ctx->zs.avail_in > 0) { + grpc_slice_buffer_undo_take_first( + in, + grpc_slice_sub(slice, GRPC_SLICE_LENGTH(slice) - ctx->zs.avail_in, + GRPC_SLICE_LENGTH(slice))); + } + grpc_slice_unref_internal(&exec_ctx, slice); + } + if (flush != 0 && ctx->zs.avail_out > 0 && !eoc) { + GPR_ASSERT(in->length == 0); + r = ctx->flate(&ctx->zs, flush); + if (flush == Z_SYNC_FLUSH) { + switch (r) { + case Z_OK: + /* Maybe flush is not complete; just made some partial progress. */ + if (ctx->zs.avail_out > 0) { + flush = 0; + } + break; + case Z_BUF_ERROR: + case Z_STREAM_END: + flush = 0; + break; + default: + gpr_log(GPR_ERROR, "zlib error (%d)", r); + grpc_slice_unref_internal(&exec_ctx, slice_out); + grpc_exec_ctx_finish(&exec_ctx); + return false; + } + } else if (flush == Z_FINISH) { + switch (r) { + case Z_OK: + case Z_BUF_ERROR: + /* Wait for the next loop to assign additional output space. */ + GPR_ASSERT(ctx->zs.avail_out == 0); + break; + case Z_STREAM_END: + flush = 0; + break; + default: + gpr_log(GPR_ERROR, "zlib error (%d)", r); + grpc_slice_unref_internal(&exec_ctx, slice_out); + grpc_exec_ctx_finish(&exec_ctx); + return false; + } + } + } + + if (ctx->zs.avail_out == 0) { + grpc_slice_buffer_add(out, slice_out); + } else if (ctx->zs.avail_out < slice_size) { + slice_out.data.refcounted.length -= ctx->zs.avail_out; + grpc_slice_buffer_add(out, slice_out); + } else { + grpc_slice_unref_internal(&exec_ctx, slice_out); + } + max_output_size -= (slice_size - ctx->zs.avail_out); + } + grpc_exec_ctx_finish(&exec_ctx); + if (end_of_context) { + *end_of_context = eoc; + } + if (output_size) { + *output_size = original_max_output_size - max_output_size; + } + return true; +} + +bool grpc_stream_compress(grpc_stream_compression_context *ctx, + grpc_slice_buffer *in, grpc_slice_buffer *out, + size_t *output_size, size_t max_output_size, + grpc_stream_compression_flush flush) { + GPR_ASSERT(ctx->flate == deflate); + int gzip_flush; + switch (flush) { + case GRPC_STREAM_COMPRESSION_FLUSH_NONE: + gzip_flush = 0; + break; + case GRPC_STREAM_COMPRESSION_FLUSH_SYNC: + gzip_flush = Z_SYNC_FLUSH; + break; + case GRPC_STREAM_COMPRESSION_FLUSH_FINISH: + gzip_flush = Z_FINISH; + break; + default: + gzip_flush = 0; + } + return gzip_flate(ctx, in, out, output_size, max_output_size, gzip_flush, + NULL); +} + +bool grpc_stream_decompress(grpc_stream_compression_context *ctx, + grpc_slice_buffer *in, grpc_slice_buffer *out, + size_t *output_size, size_t max_output_size, + bool *end_of_context) { + GPR_ASSERT(ctx->flate == inflate); + return gzip_flate(ctx, in, out, output_size, max_output_size, Z_SYNC_FLUSH, + end_of_context); +} + +grpc_stream_compression_context *grpc_stream_compression_context_create( + grpc_stream_compression_method method) { + grpc_stream_compression_context *ctx = + gpr_zalloc(sizeof(grpc_stream_compression_context)); + int r; + if (ctx == NULL) { + return NULL; + } + if (method == GRPC_STREAM_COMPRESSION_DECOMPRESS) { + r = inflateInit2(&ctx->zs, 0x1F); + ctx->flate = inflate; + } else { + r = deflateInit2(&ctx->zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8, + Z_DEFAULT_STRATEGY); + ctx->flate = deflate; + } + if (r != Z_OK) { + gpr_free(ctx); + return NULL; + } + + return ctx; +} + +void grpc_stream_compression_context_destroy( + grpc_stream_compression_context *ctx) { + if (ctx->flate == inflate) { + inflateEnd(&ctx->zs); + } else { + deflateEnd(&ctx->zs); + } + gpr_free(ctx); +} diff --git a/src/core/lib/compression/stream_compression.h b/src/core/lib/compression/stream_compression.h new file mode 100644 index 00000000000..844dff81a3b --- /dev/null +++ b/src/core/lib/compression/stream_compression.h @@ -0,0 +1,90 @@ +/* + * + * 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_STREAM_COMPRESSION_H +#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_H + +#include + +#include +#include + +/* Stream compression/decompression context */ +typedef struct grpc_stream_compression_context { + z_stream zs; + int (*flate)(z_stream *zs, int flush); +} grpc_stream_compression_context; + +typedef enum grpc_stream_compression_method { + GRPC_STREAM_COMPRESSION_COMPRESS = 0, + GRPC_STREAM_COMPRESSION_DECOMPRESS, + GRPC_STREAM_COMPRESSION_METHOD_COUNT +} grpc_stream_compression_method; + +typedef enum grpc_stream_compression_flush { + GRPC_STREAM_COMPRESSION_FLUSH_NONE = 0, + GRPC_STREAM_COMPRESSION_FLUSH_SYNC, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH, + GRPC_STREAM_COMPRESSION_FLUSH_COUNT +} grpc_stream_compression_flush; + +/** + * Compress bytes provided in \a in with a given context, with an optional flush + * at the end of compression. Emits at most \a max_output_size compressed bytes + * into \a out. If all the bytes in input buffer \a in are depleted and \a flush + * is not GRPC_STREAM_COMPRESSION_FLUSH_NONE, the corresponding flush method is + * executed. The total number of bytes emitted is outputed in \a output_size. + * + * A SYNC flush indicates that the entire messages in \a in can be decompressed + * from \a out. A FINISH flush implies a SYNC flush, and that any further + * compression will not be dependent on the state of the current context and any + * previous compressed bytes. It allows corresponding decompression context to + * be dropped when reaching this boundary. + */ +bool grpc_stream_compress(grpc_stream_compression_context *ctx, + grpc_slice_buffer *in, grpc_slice_buffer *out, + size_t *output_size, size_t max_output_size, + grpc_stream_compression_flush flush); + +/** + * Decompress bytes provided in \a in with a given context. Emits at most \a + * max_output_size decompressed bytes into \a out. If decompression process + * reached the end of a gzip stream, \a end_of_context is set to true; otherwise + * it is set to false. The total number of bytes emitted is outputed in \a + * output_size. + */ +bool grpc_stream_decompress(grpc_stream_compression_context *ctx, + grpc_slice_buffer *in, grpc_slice_buffer *out, + size_t *output_size, size_t max_output_size, + bool *end_of_context); + +/** + * Creates a stream compression context. \a pending_bytes_buffer is the input + * buffer for compression/decompression operations. \a method specifies whether + * the context is for compression or decompression. + */ +grpc_stream_compression_context *grpc_stream_compression_context_create( + grpc_stream_compression_method method); + +/** + * Destroys a stream compression context. + */ +void grpc_stream_compression_context_destroy( + grpc_stream_compression_context *ctx); + +#endif diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index b30d340ce56..e7f7332b995 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -71,6 +71,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', + 'src/core/lib/compression/stream_compression.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', diff --git a/test/core/compression/stream_compression_test.c b/test/core/compression/stream_compression_test.c new file mode 100644 index 00000000000..e576507aaf6 --- /dev/null +++ b/test/core/compression/stream_compression_test.c @@ -0,0 +1,292 @@ +/* + * + * 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. + * + */ + +#include + +#include +#include +#include +#include + +#include "src/core/lib/compression/stream_compression.h" + +static void generate_random_payload(char *payload, size_t size) { + size_t i; + static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + for (i = 0; i < size - 1; ++i) { + payload[i] = chars[rand() % (int)(sizeof(chars) - 1)]; + } + payload[size - 1] = '\0'; +} + +static bool slice_buffer_equals_string(grpc_slice_buffer *buf, + const char *str) { + size_t i; + if (buf->length != strlen(str)) { + return false; + } + size_t pointer = 0; + for (i = 0; i < buf->count; i++) { + size_t slice_len = GRPC_SLICE_LENGTH(buf->slices[i]); + if (0 != strncmp(str + pointer, + (char *)GRPC_SLICE_START_PTR(buf->slices[i]), slice_len)) { + return false; + } + pointer += slice_len; + } + return true; +} + +static void test_stream_compression_simple_compress_decompress() { + const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS); + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_DECOMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(output_size == sizeof(test_str) - 1); + grpc_stream_compression_context_destroy(compress_ctx); + grpc_stream_compression_context_destroy(decompress_ctx); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +static void +test_stream_compression_simple_compress_decompress_with_output_size_constraint() { + const char test_str[] = "aaaaaaabbbbbbbccccccctesttesttest"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS); + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_DECOMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + bool end_of_context; + size_t output_size; + size_t max_output_size = 2; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + max_output_size, &end_of_context)); + GPR_ASSERT(output_size == max_output_size); + GPR_ASSERT(end_of_context == false); + grpc_slice slice_recv = grpc_slice_buffer_take_first(&sink); + char *str_recv = (char *)GRPC_SLICE_START_PTR(slice_recv); + GPR_ASSERT(GRPC_SLICE_LENGTH(slice_recv) == max_output_size); + GPR_ASSERT(0 == strncmp(test_str, str_recv, max_output_size)); + grpc_slice_unref(slice_recv); + + size_t remaining_size = sizeof(test_str) - 1 - max_output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + remaining_size, &end_of_context)); + GPR_ASSERT(output_size == remaining_size); + GPR_ASSERT(end_of_context == true); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str + max_output_size)); + + grpc_stream_compression_context_destroy(decompress_ctx); + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +#define LARGE_DATA_SIZE (1024 * 1024) +static void +test_stream_compression_simple_compress_decompress_with_large_data() { + char *test_str = gpr_malloc(LARGE_DATA_SIZE * sizeof(char)); + generate_random_payload(test_str, LARGE_DATA_SIZE); + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS); + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_DECOMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(output_size == LARGE_DATA_SIZE - 1); + grpc_stream_compression_context_destroy(compress_ctx); + grpc_stream_compression_context_destroy(decompress_ctx); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); + gpr_free(test_str); +} + +static void test_stream_compression_drop_context() { + const char test_str[] = "aaaaaaabbbbbbbccccccc"; + const char test_str2[] = "dddddddeeeeeeefffffffggggg"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + compress_ctx = + grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS); + slice = grpc_slice_from_static_string(test_str2); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + /* Concatenate the two compressed sliced into one to test decompressing two + * contexts */ + grpc_slice slice1 = grpc_slice_buffer_take_first(&relay); + grpc_slice slice2 = grpc_slice_buffer_take_first(&relay); + grpc_slice slice3 = + grpc_slice_malloc(GRPC_SLICE_LENGTH(slice1) + GRPC_SLICE_LENGTH(slice2)); + memcpy(GRPC_SLICE_START_PTR(slice3), GRPC_SLICE_START_PTR(slice1), + GRPC_SLICE_LENGTH(slice1)); + memcpy(GRPC_SLICE_START_PTR(slice3) + GRPC_SLICE_LENGTH(slice1), + GRPC_SLICE_START_PTR(slice2), GRPC_SLICE_LENGTH(slice2)); + grpc_slice_unref(slice1); + grpc_slice_unref(slice2); + grpc_slice_buffer_add(&relay, slice3); + + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_DECOMPRESS); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == true); + GPR_ASSERT(output_size == sizeof(test_str) - 1); + + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + grpc_stream_compression_context_destroy(decompress_ctx); + grpc_slice_buffer_destroy(&sink); + + grpc_slice_buffer_init(&sink); + decompress_ctx = grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_DECOMPRESS); + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == true); + GPR_ASSERT(output_size == sizeof(test_str2) - 1); + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2)); + grpc_stream_compression_context_destroy(decompress_ctx); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +static void test_stream_compression_sync_flush() { + const char test_str[] = "aaaaaaabbbbbbbccccccc"; + const char test_str2[] = "dddddddeeeeeeefffffffggggg"; + grpc_slice_buffer source, relay, sink; + grpc_slice_buffer_init(&source); + grpc_slice_buffer_init(&relay); + grpc_slice_buffer_init(&sink); + grpc_stream_compression_context *compress_ctx = + grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS); + grpc_slice slice = grpc_slice_from_static_string(test_str); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_SYNC)); + + grpc_stream_compression_context *decompress_ctx = + grpc_stream_compression_context_create( + GRPC_STREAM_COMPRESSION_DECOMPRESS); + bool end_of_context; + size_t output_size; + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == false); + GPR_ASSERT(output_size == sizeof(test_str) - 1); + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str)); + grpc_slice_buffer_destroy(&sink); + + grpc_slice_buffer_init(&sink); + slice = grpc_slice_from_static_string(test_str2); + grpc_slice_buffer_add(&source, slice); + GPR_ASSERT(grpc_stream_compress(compress_ctx, &source, &relay, NULL, + ~(size_t)0, + GRPC_STREAM_COMPRESSION_FLUSH_FINISH)); + grpc_stream_compression_context_destroy(compress_ctx); + + GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size, + ~(size_t)0, &end_of_context)); + GPR_ASSERT(end_of_context == true); + GPR_ASSERT(output_size == sizeof(test_str2) - 1); + GPR_ASSERT(slice_buffer_equals_string(&sink, test_str2)); + grpc_stream_compression_context_destroy(decompress_ctx); + + grpc_slice_buffer_destroy(&source); + grpc_slice_buffer_destroy(&relay); + grpc_slice_buffer_destroy(&sink); +} + +int main(int argc, char **argv) { + grpc_init(); + test_stream_compression_simple_compress_decompress(); + test_stream_compression_simple_compress_decompress_with_output_size_constraint(); + test_stream_compression_simple_compress_decompress_with_large_data(); + test_stream_compression_sync_flush(); + test_stream_compression_drop_context(); + grpc_shutdown(); + + return 0; +} diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 4c6c656b1b5..7c1e75a99cd 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1071,6 +1071,8 @@ src/core/lib/compression/algorithm_metadata.h \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.h \ +src/core/lib/compression/stream_compression.c \ +src/core/lib/compression/stream_compression.h \ src/core/lib/debug/trace.c \ src/core/lib/debug/trace.h \ src/core/lib/http/format_request.c \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 0a91a0cec45..c7cc9cb6945 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -2163,6 +2163,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "stream_compression_test", + "src": [ + "test/core/compression/stream_compression_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -7672,6 +7689,7 @@ "src/core/lib/channel/handshaker_registry.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", + "src/core/lib/compression/stream_compression.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", @@ -7806,6 +7824,8 @@ "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", "src/core/lib/compression/message_compress.h", + "src/core/lib/compression/stream_compression.c", + "src/core/lib/compression/stream_compression.h", "src/core/lib/http/format_request.c", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.c", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 82437c94cb5..d24209506a7 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -2271,6 +2271,28 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "stream_compression_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ diff --git a/tools/ubsan_suppressions.txt b/tools/ubsan_suppressions.txt index 83dcfc3d058..2dcfeea9afa 100644 --- a/tools/ubsan_suppressions.txt +++ b/tools/ubsan_suppressions.txt @@ -7,3 +7,4 @@ alignment:CRYPTO_cbc128_encrypt alignment:CRYPTO_gcm128_encrypt nonnull-attribute:google::protobuf::* alignment:google::protobuf::* +nonnull-attribute:_tr_stored_block diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index 3bcc832db00..55de734b427 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -1585,6 +1585,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "status_conversion_test", "v {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stream_compression_test", "vcxproj\test\stream_compression_test\stream_compression_test.vcxproj", "{A5EE72A2-656C-0896-12F3-A92583CF7C61}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stream_owned_slice_test", "vcxproj\test\stream_owned_slice_test\stream_owned_slice_test.vcxproj", "{D5A20C05-D9B2-970B-8429-94BC3F58D1C4}" ProjectSection(myProperties) = preProject lib = "False" @@ -4121,6 +4132,22 @@ Global {21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|Win32.Build.0 = Release|Win32 {21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|x64.ActiveCfg = Release|x64 {21E2A241-9D48-02CD-92E4-4EEC98424CF5}.Release-DLL|x64.Build.0 = Release|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|Win32.ActiveCfg = Debug|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|x64.ActiveCfg = Debug|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|Win32.ActiveCfg = Release|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|x64.ActiveCfg = Release|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|Win32.Build.0 = Debug|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug|x64.Build.0 = Debug|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|Win32.Build.0 = Release|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release|x64.Build.0 = Release|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Debug-DLL|x64.Build.0 = Debug|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|Win32.Build.0 = Release|Win32 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|x64.ActiveCfg = Release|x64 + {A5EE72A2-656C-0896-12F3-A92583CF7C61}.Release-DLL|x64.Build.0 = Release|x64 {D5A20C05-D9B2-970B-8429-94BC3F58D1C4}.Debug|Win32.ActiveCfg = Debug|Win32 {D5A20C05-D9B2-970B-8429-94BC3F58D1C4}.Debug|x64.ActiveCfg = Debug|x64 {D5A20C05-D9B2-970B-8429-94BC3F58D1C4}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 112f3ec30ac..dbc148e0f81 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -311,6 +311,7 @@ + @@ -540,6 +541,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 5c29e58badb..45d11933c1a 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -31,6 +31,9 @@ src\core\lib\compression + + src\core\lib\compression + src\core\lib\http @@ -884,6 +887,9 @@ src\core\lib\compression + + src\core\lib\compression + src\core\lib\http diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 1899be91db3..32809ca5899 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -206,6 +206,7 @@ + @@ -366,6 +367,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 9c81fc5bf51..def8de42028 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -88,6 +88,9 @@ src\core\lib\compression + + src\core\lib\compression + src\core\lib\http @@ -611,6 +614,9 @@ src\core\lib\compression + + src\core\lib\compression + src\core\lib\http diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 730ac01ea3a..ac98dc05401 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -301,6 +301,7 @@ + @@ -507,6 +508,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 427352eb3b0..fea68c51dc8 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -34,6 +34,9 @@ src\core\lib\compression + + src\core\lib\compression + src\core\lib\http @@ -794,6 +797,9 @@ src\core\lib\compression + + src\core\lib\compression + src\core\lib\http diff --git a/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj new file mode 100644 index 00000000000..7faf665b20d --- /dev/null +++ b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {A5EE72A2-656C-0896-12F3-A92583CF7C61} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + stream_compression_test + static + Debug + static + Debug + + + stream_compression_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj.filters b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj.filters new file mode 100644 index 00000000000..a63628279da --- /dev/null +++ b/vsprojects/vcxproj/test/stream_compression_test/stream_compression_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\compression + + + + + + {22ec1dc6-29e1-32ac-1494-43bb7f211422} + + + {62cac7ff-76a5-35ff-1e73-a8508e826ba3} + + + {02c8e4fc-eeda-2f58-227f-ebef22a39562} + + + +