Merge pull request #12399 from muxi/fix-stream-compression-transport-duplicate

Fix stream compression transport duplicate
pull/12244/head^2
Muxi Yan 8 years ago committed by GitHub
commit 31c66c576a
  1. 4
      BUILD
  2. 12
      CMakeLists.txt
  3. 12
      Makefile
  4. 2
      binding.gyp
  5. 4
      build.yaml
  6. 2
      config.m4
  7. 2
      config.w32
  8. 6
      gRPC-Core.podspec
  9. 4
      grpc.gemspec
  10. 8
      grpc.gyp
  11. 4
      package.xml
  12. 74
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  13. 4
      src/core/ext/transport/chttp2/transport/frame_data.c
  14. 17
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  15. 20
      src/core/ext/transport/chttp2/transport/internal.h
  16. 89
      src/core/ext/transport/chttp2/transport/writing.c
  17. 179
      src/core/lib/compression/stream_compression.c
  18. 32
      src/core/lib/compression/stream_compression.h
  19. 228
      src/core/lib/compression/stream_compression_gzip.c
  20. 26
      src/core/lib/compression/stream_compression_gzip.h
  21. 94
      src/core/lib/compression/stream_compression_identity.c
  22. 27
      src/core/lib/compression/stream_compression_identity.h
  23. 2
      src/python/grpcio/grpc_core_dependencies.py
  24. 31
      test/core/compression/stream_compression_test.c
  25. 9
      test/core/end2end/tests/compressed_payload.c
  26. 9
      test/core/end2end/tests/stream_compression_compressed_payload.c
  27. 2
      tools/doxygen/Doxyfile.c++.internal
  28. 4
      tools/doxygen/Doxyfile.core.internal
  29. 6
      tools/run_tests/generated/sources_and_headers.json

@ -574,6 +574,8 @@ grpc_cc_library(
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/compression/stream_compression.c",
"src/core/lib/compression/stream_compression_gzip.c",
"src/core/lib/compression/stream_compression_identity.c",
"src/core/lib/debug/stats.c",
"src/core/lib/debug/stats_data.c",
"src/core/lib/http/format_request.c",
@ -705,6 +707,8 @@ grpc_cc_library(
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/compression/stream_compression.h",
"src/core/lib/compression/stream_compression_gzip.h",
"src/core/lib/compression/stream_compression_identity.h",
"src/core/lib/debug/stats.h",
"src/core/lib/debug/stats_data.h",
"src/core/lib/http/format_request.h",

@ -965,6 +965,8 @@ add_library(grpc
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c
@ -1314,6 +1316,8 @@ add_library(grpc_cronet
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c
@ -1631,6 +1635,8 @@ add_library(grpc_test_util
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c
@ -1892,6 +1898,8 @@ add_library(grpc_test_util_unsecure
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c
@ -2139,6 +2147,8 @@ add_library(grpc_unsecure
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c
@ -2894,6 +2904,8 @@ add_library(grpc++_cronet
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c

@ -2956,6 +2956,8 @@ LIBGRPC_SRC = \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \
@ -3305,6 +3307,8 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \
@ -3621,6 +3625,8 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \
@ -3873,6 +3879,8 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \
@ -4098,6 +4106,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \
@ -4836,6 +4846,8 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \

@ -667,6 +667,8 @@
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c',

@ -195,6 +195,8 @@ filegroups:
- src/core/lib/compression/compression.c
- src/core/lib/compression/message_compress.c
- src/core/lib/compression/stream_compression.c
- src/core/lib/compression/stream_compression_gzip.c
- src/core/lib/compression/stream_compression_identity.c
- src/core/lib/debug/stats.c
- src/core/lib/debug/stats_data.c
- src/core/lib/http/format_request.c
@ -346,6 +348,8 @@ filegroups:
- src/core/lib/compression/algorithm_metadata.h
- src/core/lib/compression/message_compress.h
- src/core/lib/compression/stream_compression.h
- src/core/lib/compression/stream_compression_gzip.h
- src/core/lib/compression/stream_compression_identity.h
- src/core/lib/debug/stats.h
- src/core/lib/debug/stats_data.h
- src/core/lib/http/format_request.h

@ -96,6 +96,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \

@ -73,6 +73,8 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\compression\\compression.c " +
"src\\core\\lib\\compression\\message_compress.c " +
"src\\core\\lib\\compression\\stream_compression.c " +
"src\\core\\lib\\compression\\stream_compression_gzip.c " +
"src\\core\\lib\\compression\\stream_compression_identity.c " +
"src\\core\\lib\\debug\\stats.c " +
"src\\core\\lib\\debug\\stats_data.c " +
"src\\core\\lib\\http\\format_request.c " +

@ -330,6 +330,8 @@ Pod::Spec.new do |s|
'src/core/lib/compression/algorithm_metadata.h',
'src/core/lib/compression/message_compress.h',
'src/core/lib/compression/stream_compression.h',
'src/core/lib/compression/stream_compression_gzip.h',
'src/core/lib/compression/stream_compression_identity.h',
'src/core/lib/debug/stats.h',
'src/core/lib/debug/stats_data.h',
'src/core/lib/http/format_request.h',
@ -479,6 +481,8 @@ Pod::Spec.new do |s|
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c',
@ -825,6 +829,8 @@ Pod::Spec.new do |s|
'src/core/lib/compression/algorithm_metadata.h',
'src/core/lib/compression/message_compress.h',
'src/core/lib/compression/stream_compression.h',
'src/core/lib/compression/stream_compression_gzip.h',
'src/core/lib/compression/stream_compression_identity.h',
'src/core/lib/debug/stats.h',
'src/core/lib/debug/stats_data.h',
'src/core/lib/http/format_request.h',

@ -263,6 +263,8 @@ Gem::Specification.new do |s|
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/compression/stream_compression_gzip.h )
s.files += %w( src/core/lib/compression/stream_compression_identity.h )
s.files += %w( src/core/lib/debug/stats.h )
s.files += %w( src/core/lib/debug/stats_data.h )
s.files += %w( src/core/lib/http/format_request.h )
@ -416,6 +418,8 @@ Gem::Specification.new do |s|
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/compression/stream_compression_gzip.c )
s.files += %w( src/core/lib/compression/stream_compression_identity.c )
s.files += %w( src/core/lib/debug/stats.c )
s.files += %w( src/core/lib/debug/stats_data.c )
s.files += %w( src/core/lib/http/format_request.c )

@ -233,6 +233,8 @@
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c',
@ -532,6 +534,8 @@
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c',
@ -736,6 +740,8 @@
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c',
@ -925,6 +931,8 @@
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c',

@ -275,6 +275,8 @@
<file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_gzip.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_identity.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats_data.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/format_request.h" role="src" />
@ -428,6 +430,8 @@
<file baseinstalldir="/" name="src/core/lib/compression/compression.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_gzip.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_identity.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats_data.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/format_request.c" role="src" />

@ -706,7 +706,10 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_schedule_on_exec_ctx);
grpc_slice_buffer_init(&s->unprocessed_incoming_frames_buffer);
grpc_slice_buffer_init(&s->frame_storage);
grpc_slice_buffer_init(&s->compressed_data_buffer);
grpc_slice_buffer_init(&s->decompressed_data_buffer);
s->pending_byte_stream = false;
s->decompressed_header_bytes = 0;
GRPC_CLOSURE_INIT(&s->reset_byte_stream, reset_byte_stream, s,
grpc_combiner_scheduler(t->combiner));
@ -740,14 +743,8 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
grpc_slice_buffer_destroy_internal(exec_ctx,
&s->unprocessed_incoming_frames_buffer);
grpc_slice_buffer_destroy_internal(exec_ctx, &s->frame_storage);
if (s->compressed_data_buffer) {
grpc_slice_buffer_destroy_internal(exec_ctx, s->compressed_data_buffer);
gpr_free(s->compressed_data_buffer);
}
if (s->decompressed_data_buffer) {
grpc_slice_buffer_destroy_internal(exec_ctx, s->decompressed_data_buffer);
gpr_free(s->decompressed_data_buffer);
}
grpc_slice_buffer_destroy_internal(exec_ctx, &s->compressed_data_buffer);
grpc_slice_buffer_destroy_internal(exec_ctx, &s->decompressed_data_buffer);
grpc_chttp2_list_remove_stalled_by_transport(t, s);
grpc_chttp2_list_remove_stalled_by_stream(t, s);
@ -1448,12 +1445,14 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
/* Identify stream compression */
if ((s->stream_compression_send_enabled =
(op_payload->send_initial_metadata.send_initial_metadata->idx.named
.content_encoding != NULL)) == true) {
s->compressed_data_buffer =
(grpc_slice_buffer *)gpr_malloc(sizeof(grpc_slice_buffer));
grpc_slice_buffer_init(s->compressed_data_buffer);
if (op_payload->send_initial_metadata.send_initial_metadata->idx.named
.content_encoding == NULL ||
grpc_stream_compression_method_parse(
GRPC_MDVALUE(
op_payload->send_initial_metadata.send_initial_metadata->idx
.named.content_encoding->md),
true, &s->stream_compression_method) == 0) {
s->stream_compression_method = GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS;
}
s->send_initial_metadata_finished = add_closure_barrier(on_complete);
@ -1902,20 +1901,20 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
&s->frame_storage);
s->unprocessed_incoming_frames_decompressed = false;
}
if (s->stream_compression_recv_enabled &&
!s->unprocessed_incoming_frames_decompressed) {
GPR_ASSERT(s->decompressed_data_buffer->length == 0);
if (!s->unprocessed_incoming_frames_decompressed) {
GPR_ASSERT(s->decompressed_data_buffer.length == 0);
bool end_of_context;
if (!s->stream_decompression_ctx) {
s->stream_decompression_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
s->stream_decompression_method);
}
if (!grpc_stream_decompress(s->stream_decompression_ctx,
&s->unprocessed_incoming_frames_buffer,
s->decompressed_data_buffer, NULL,
GRPC_HEADER_SIZE_IN_BYTES,
&end_of_context)) {
if (!grpc_stream_decompress(
s->stream_decompression_ctx,
&s->unprocessed_incoming_frames_buffer,
&s->decompressed_data_buffer, NULL,
GRPC_HEADER_SIZE_IN_BYTES - s->decompressed_header_bytes,
&end_of_context)) {
grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
&s->frame_storage);
grpc_slice_buffer_reset_and_unref_internal(
@ -1923,9 +1922,13 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Stream decompression error.");
} else {
s->decompressed_header_bytes += s->decompressed_data_buffer.length;
if (s->decompressed_header_bytes == GRPC_HEADER_SIZE_IN_BYTES) {
s->decompressed_header_bytes = 0;
}
error = grpc_deframe_unprocessed_incoming_frames(
exec_ctx, &s->data_parser, s, s->decompressed_data_buffer, NULL,
s->recv_message);
exec_ctx, &s->data_parser, s, &s->decompressed_data_buffer,
NULL, s->recv_message);
if (end_of_context) {
grpc_stream_compression_context_destroy(
s->stream_decompression_ctx);
@ -1974,15 +1977,14 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
}
bool pending_data = s->pending_byte_stream ||
s->unprocessed_incoming_frames_buffer.length > 0;
if (s->stream_compression_recv_enabled && s->read_closed &&
s->frame_storage.length > 0 && !pending_data && !s->seen_error &&
s->recv_trailing_metadata_finished != NULL) {
if (s->read_closed && s->frame_storage.length > 0 && !pending_data &&
!s->seen_error && s->recv_trailing_metadata_finished != NULL) {
/* Maybe some SYNC_FLUSH data is left in frame_storage. Consume them and
* maybe decompress the next 5 bytes in the stream. */
bool end_of_context;
if (!s->stream_decompression_ctx) {
s->stream_decompression_ctx = grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
s->stream_decompression_method);
}
if (!grpc_stream_decompress(s->stream_decompression_ctx,
&s->frame_storage,
@ -1995,6 +1997,7 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
} else {
if (s->unprocessed_incoming_frames_buffer.length > 0) {
s->unprocessed_incoming_frames_decompressed = true;
pending_data = true;
}
if (end_of_context) {
grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
@ -2813,7 +2816,7 @@ static void reset_byte_stream(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_UNREF(s->byte_stream_error);
s->byte_stream_error = GRPC_ERROR_NONE;
grpc_chttp2_cancel_stream(exec_ctx, s->t, s, GRPC_ERROR_REF(error));
s->byte_stream_error = error;
s->byte_stream_error = GRPC_ERROR_REF(error);
}
}
@ -2911,24 +2914,23 @@ static grpc_error *incoming_byte_stream_pull(grpc_exec_ctx *exec_ctx,
grpc_error *error;
if (s->unprocessed_incoming_frames_buffer.length > 0) {
if (s->stream_compression_recv_enabled &&
!s->unprocessed_incoming_frames_decompressed) {
if (!s->unprocessed_incoming_frames_decompressed) {
bool end_of_context;
if (!s->stream_decompression_ctx) {
s->stream_decompression_ctx = grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
s->stream_decompression_method);
}
if (!grpc_stream_decompress(s->stream_decompression_ctx,
&s->unprocessed_incoming_frames_buffer,
s->decompressed_data_buffer, NULL, MAX_SIZE_T,
&end_of_context)) {
&s->decompressed_data_buffer, NULL,
MAX_SIZE_T, &end_of_context)) {
error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error.");
return error;
}
GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer,
s->decompressed_data_buffer);
&s->decompressed_data_buffer);
s->unprocessed_incoming_frames_decompressed = true;
if (end_of_context) {
grpc_stream_compression_context_destroy(s->stream_decompression_ctx);

@ -210,7 +210,7 @@ grpc_error *grpc_deframe_unprocessed_incoming_frames(
if (cur != end) {
grpc_slice_buffer_undo_take_first(
&s->unprocessed_incoming_frames_buffer,
slices,
grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
}
grpc_slice_unref_internal(exec_ctx, slice);
@ -277,7 +277,7 @@ grpc_error *grpc_deframe_unprocessed_incoming_frames(
p->state = GRPC_CHTTP2_DATA_FH_0;
cur += p->frame_size;
grpc_slice_buffer_undo_take_first(
&s->unprocessed_incoming_frames_buffer,
slices,
grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
grpc_slice_unref_internal(exec_ctx, slice);
return GRPC_ERROR_NONE;

@ -1683,17 +1683,12 @@ static void parse_stream_compression_md(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_metadata_batch *initial_metadata) {
if (initial_metadata->idx.named.content_encoding != NULL) {
grpc_slice content_encoding =
GRPC_MDVALUE(initial_metadata->idx.named.content_encoding->md);
if (!grpc_slice_eq(content_encoding, GRPC_MDSTR_IDENTITY)) {
if (grpc_slice_eq(content_encoding, GRPC_MDSTR_GZIP)) {
s->stream_compression_recv_enabled = true;
s->decompressed_data_buffer =
(grpc_slice_buffer *)gpr_malloc(sizeof(grpc_slice_buffer));
grpc_slice_buffer_init(s->decompressed_data_buffer);
}
}
if (initial_metadata->idx.named.content_encoding == NULL ||
grpc_stream_compression_method_parse(
GRPC_MDVALUE(initial_metadata->idx.named.content_encoding->md), false,
&s->stream_decompression_method) == 0) {
s->stream_decompression_method =
GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS;
}
}

@ -592,25 +592,27 @@ struct grpc_chttp2_stream {
grpc_chttp2_write_cb *finish_after_write;
size_t sending_bytes;
/** Whether stream compression send is enabled */
bool stream_compression_recv_enabled;
/** Whether stream compression recv is enabled */
bool stream_compression_send_enabled;
/** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed
*/
bool unprocessed_incoming_frames_decompressed;
/* Stream compression method to be used. */
grpc_stream_compression_method stream_compression_method;
/* Stream decompression method to be used. */
grpc_stream_compression_method stream_decompression_method;
/** Stream compression decompress context */
grpc_stream_compression_context *stream_decompression_ctx;
/** Stream compression compress context */
grpc_stream_compression_context *stream_compression_ctx;
/** Buffer storing data that is compressed but not sent */
grpc_slice_buffer *compressed_data_buffer;
grpc_slice_buffer compressed_data_buffer;
/** Amount of uncompressed bytes sent out when compressed_data_buffer is
* emptied */
size_t uncompressed_data_size;
/** Temporary buffer storing decompressed data */
grpc_slice_buffer *decompressed_data_buffer;
grpc_slice_buffer decompressed_data_buffer;
/** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed
*/
bool unprocessed_incoming_frames_decompressed;
/** gRPC header bytes that are already decompressed */
size_t decompressed_header_bytes;
};
/** Transport writing call flow:

@ -317,8 +317,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
if (sent_initial_metadata) {
/* send any body bytes, if allowed by flow control */
if (s->flow_controlled_buffer.length > 0 ||
(s->stream_compression_send_enabled &&
s->compressed_data_buffer->length > 0)) {
s->compressed_data_buffer.length > 0) {
uint32_t stream_remote_window = (uint32_t)GPR_MAX(
0,
s->flow_control.remote_window_delta +
@ -332,56 +331,40 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
bool is_last_data_frame = false;
bool is_last_frame = false;
size_t sending_bytes_before = s->sending_bytes;
if (s->stream_compression_send_enabled) {
while ((s->flow_controlled_buffer.length > 0 ||
s->compressed_data_buffer->length > 0) &&
max_outgoing > 0) {
if (s->compressed_data_buffer->length > 0) {
uint32_t send_bytes = (uint32_t)GPR_MIN(
max_outgoing, s->compressed_data_buffer->length);
is_last_data_frame =
(send_bytes == s->compressed_data_buffer->length &&
s->flow_controlled_buffer.length == 0 &&
s->fetching_send_message == NULL);
is_last_frame =
is_last_data_frame && s->send_trailing_metadata != NULL &&
grpc_metadata_batch_is_empty(s->send_trailing_metadata);
grpc_chttp2_encode_data(s->id, s->compressed_data_buffer,
send_bytes, is_last_frame,
&s->stats.outgoing, &t->outbuf);
grpc_chttp2_flowctl_sent_data(&t->flow_control,
&s->flow_control, send_bytes);
max_outgoing -= send_bytes;
if (s->compressed_data_buffer->length == 0) {
s->sending_bytes += s->uncompressed_data_size;
}
} else {
if (s->stream_compression_ctx == NULL) {
s->stream_compression_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_COMPRESS);
}
s->uncompressed_data_size = s->flow_controlled_buffer.length;
GPR_ASSERT(grpc_stream_compress(
s->stream_compression_ctx, &s->flow_controlled_buffer,
s->compressed_data_buffer, NULL, MAX_SIZE_T,
GRPC_STREAM_COMPRESSION_FLUSH_SYNC));
while ((s->flow_controlled_buffer.length > 0 ||
s->compressed_data_buffer.length > 0) &&
max_outgoing > 0) {
if (s->compressed_data_buffer.length > 0) {
uint32_t send_bytes = (uint32_t)GPR_MIN(
max_outgoing, s->compressed_data_buffer.length);
is_last_data_frame =
(send_bytes == s->compressed_data_buffer.length &&
s->flow_controlled_buffer.length == 0 &&
s->fetching_send_message == NULL);
is_last_frame =
is_last_data_frame && s->send_trailing_metadata != NULL &&
grpc_metadata_batch_is_empty(s->send_trailing_metadata);
grpc_chttp2_encode_data(s->id, &s->compressed_data_buffer,
send_bytes, is_last_frame,
&s->stats.outgoing, &t->outbuf);
grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
send_bytes);
max_outgoing -= send_bytes;
if (s->compressed_data_buffer.length == 0) {
s->sending_bytes += s->uncompressed_data_size;
}
} else {
if (s->stream_compression_ctx == NULL) {
s->stream_compression_ctx =
grpc_stream_compression_context_create(
s->stream_compression_method);
}
s->uncompressed_data_size = s->flow_controlled_buffer.length;
GPR_ASSERT(grpc_stream_compress(
s->stream_compression_ctx, &s->flow_controlled_buffer,
&s->compressed_data_buffer, NULL, MAX_SIZE_T,
GRPC_STREAM_COMPRESSION_FLUSH_SYNC));
}
} else {
uint32_t send_bytes = (uint32_t)GPR_MIN(
max_outgoing, s->flow_controlled_buffer.length);
is_last_data_frame = s->fetching_send_message == NULL &&
send_bytes == s->flow_controlled_buffer.length;
is_last_frame =
is_last_data_frame && s->send_trailing_metadata != NULL &&
grpc_metadata_batch_is_empty(s->send_trailing_metadata);
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer,
send_bytes, is_last_frame,
&s->stats.outgoing, &t->outbuf);
grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
send_bytes);
s->sending_bytes += send_bytes;
}
if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time =
@ -406,8 +389,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
&s->flow_controlled_bytes_flowed, GRPC_ERROR_NONE);
now_writing = true;
if (s->flow_controlled_buffer.length > 0 ||
(s->stream_compression_send_enabled &&
s->compressed_data_buffer->length > 0)) {
s->compressed_data_buffer.length > 0) {
GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:fork");
grpc_chttp2_list_add_writable_stream(t, s);
}
@ -423,8 +405,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
if (s->send_trailing_metadata != NULL &&
s->fetching_send_message == NULL &&
s->flow_controlled_buffer.length == 0 &&
(!s->stream_compression_send_enabled ||
s->compressed_data_buffer->length == 0)) {
s->compressed_data_buffer.length == 0) {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) {
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,

@ -16,177 +16,62 @@
*
*/
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/compression/stream_compression.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/compression/stream_compression_gzip.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;
}
extern const grpc_stream_compression_vtable
grpc_stream_compression_identity_vtable;
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);
return ctx->vtable->compress(ctx, in, out, output_size, max_output_size,
flush);
}
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);
return ctx->vtable->decompress(ctx, in, out, output_size, max_output_size,
end_of_context);
}
grpc_stream_compression_context *grpc_stream_compression_context_create(
grpc_stream_compression_method method) {
grpc_stream_compression_context *ctx =
(grpc_stream_compression_context *)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;
switch (method) {
case GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS:
case GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS:
return grpc_stream_compression_identity_vtable.context_create(method);
case GRPC_STREAM_COMPRESSION_GZIP_COMPRESS:
case GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS:
return grpc_stream_compression_gzip_vtable.context_create(method);
default:
gpr_log(GPR_ERROR, "Unknown stream compression method: %d", method);
return NULL;
}
return ctx;
}
void grpc_stream_compression_context_destroy(
grpc_stream_compression_context *ctx) {
if (ctx->flate == inflate) {
inflateEnd(&ctx->zs);
ctx->vtable->context_destroy(ctx);
}
int grpc_stream_compression_method_parse(
grpc_slice value, bool is_compress,
grpc_stream_compression_method *method) {
if (grpc_slice_eq(value, GRPC_MDSTR_IDENTITY)) {
*method = is_compress ? GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS
: GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS;
return 1;
} else if (grpc_slice_eq(value, GRPC_MDSTR_GZIP)) {
*method = is_compress ? GRPC_STREAM_COMPRESSION_GZIP_COMPRESS
: GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS;
return 1;
} else {
deflateEnd(&ctx->zs);
return 0;
}
gpr_free(ctx);
}

@ -24,15 +24,20 @@
#include <grpc/slice_buffer.h>
#include <zlib.h>
#include "src/core/lib/transport/static_metadata.h"
typedef struct grpc_stream_compression_vtable grpc_stream_compression_vtable;
/* Stream compression/decompression context */
typedef struct grpc_stream_compression_context {
z_stream zs;
int (*flate)(z_stream *zs, int flush);
const grpc_stream_compression_vtable *vtable;
} grpc_stream_compression_context;
typedef enum grpc_stream_compression_method {
GRPC_STREAM_COMPRESSION_COMPRESS = 0,
GRPC_STREAM_COMPRESSION_DECOMPRESS,
GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS = 0,
GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS,
GRPC_STREAM_COMPRESSION_GZIP_COMPRESS,
GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS,
GRPC_STREAM_COMPRESSION_METHOD_COUNT
} grpc_stream_compression_method;
@ -43,6 +48,19 @@ typedef enum grpc_stream_compression_flush {
GRPC_STREAM_COMPRESSION_FLUSH_COUNT
} grpc_stream_compression_flush;
struct grpc_stream_compression_vtable {
bool (*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);
bool (*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);
grpc_stream_compression_context *(*context_create)(
grpc_stream_compression_method method);
void (*context_destroy)(grpc_stream_compression_context *ctx);
};
/**
* 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
@ -87,4 +105,10 @@ grpc_stream_compression_context *grpc_stream_compression_context_create(
void grpc_stream_compression_context_destroy(
grpc_stream_compression_context *ctx);
/**
* Parse stream compression method based on algorithm name
*/
int grpc_stream_compression_method_parse(
grpc_slice value, bool is_compress, grpc_stream_compression_method *method);
#endif

@ -0,0 +1,228 @@
/*
*
* 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 <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/compression/stream_compression_gzip.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"
#define OUTPUT_BLOCK_SIZE (1024)
typedef struct grpc_stream_compression_context_gzip {
grpc_stream_compression_context base;
z_stream zs;
int (*flate)(z_stream *zs, int flush);
} grpc_stream_compression_context_gzip;
static bool gzip_flate(grpc_stream_compression_context_gzip *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;
}
static bool grpc_stream_compress_gzip(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) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)ctx;
GPR_ASSERT(gzip_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(gzip_ctx, in, out, output_size, max_output_size, gzip_flush,
NULL);
}
static bool grpc_stream_decompress_gzip(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) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)ctx;
GPR_ASSERT(gzip_ctx->flate == inflate);
return gzip_flate(gzip_ctx, in, out, output_size, max_output_size,
Z_SYNC_FLUSH, end_of_context);
}
static grpc_stream_compression_context *
grpc_stream_compression_context_create_gzip(
grpc_stream_compression_method method) {
GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_GZIP_COMPRESS ||
method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS);
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)gpr_zalloc(
sizeof(grpc_stream_compression_context_gzip));
int r;
if (gzip_ctx == NULL) {
return NULL;
}
if (method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS) {
r = inflateInit2(&gzip_ctx->zs, 0x1F);
gzip_ctx->flate = inflate;
} else {
r = deflateInit2(&gzip_ctx->zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8,
Z_DEFAULT_STRATEGY);
gzip_ctx->flate = deflate;
}
if (r != Z_OK) {
gpr_free(gzip_ctx);
return NULL;
}
gzip_ctx->base.vtable = &grpc_stream_compression_gzip_vtable;
return (grpc_stream_compression_context *)gzip_ctx;
}
static void grpc_stream_compression_context_destroy_gzip(
grpc_stream_compression_context *ctx) {
if (ctx == NULL) {
return;
}
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)ctx;
if (gzip_ctx->flate == inflate) {
inflateEnd(&gzip_ctx->zs);
} else {
deflateEnd(&gzip_ctx->zs);
}
gpr_free(ctx);
}
const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable = {
.compress = grpc_stream_compress_gzip,
.decompress = grpc_stream_decompress_gzip,
.context_create = grpc_stream_compression_context_create_gzip,
.context_destroy = grpc_stream_compression_context_destroy_gzip};

@ -0,0 +1,26 @@
/*
*
* 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_GZIP_H
#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H
#include "src/core/lib/compression/stream_compression.h"
extern const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable;
#endif

@ -0,0 +1,94 @@
/*
*
* 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 <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/compression/stream_compression_identity.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"
#define OUTPUT_BLOCK_SIZE (1024)
/* Singleton context used for all identity streams. */
static grpc_stream_compression_context identity_ctx = {
.vtable = &grpc_stream_compression_identity_vtable};
static void grpc_stream_compression_pass_through(grpc_slice_buffer *in,
grpc_slice_buffer *out,
size_t *output_size,
size_t max_output_size) {
if (max_output_size >= in->length) {
if (output_size) {
*output_size = in->length;
}
grpc_slice_buffer_move_into(in, out);
} else {
if (output_size) {
*output_size = max_output_size;
}
grpc_slice_buffer_move_first(in, max_output_size, out);
}
}
static bool grpc_stream_compress_identity(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) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_pass_through(in, out, output_size, max_output_size);
return true;
}
static bool grpc_stream_decompress_identity(
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) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_pass_through(in, out, output_size, max_output_size);
if (end_of_context) {
*end_of_context = false;
}
return true;
}
static grpc_stream_compression_context *
grpc_stream_compression_context_create_identity(
grpc_stream_compression_method method) {
GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS ||
method == GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS);
/* No context needed in this case. Use fake context instead. */
return (grpc_stream_compression_context *)&identity_ctx;
}
static void grpc_stream_compression_context_destroy_identity(
grpc_stream_compression_context *ctx) {
return;
}
const grpc_stream_compression_vtable grpc_stream_compression_identity_vtable = {
.compress = grpc_stream_compress_identity,
.decompress = grpc_stream_decompress_identity,
.context_create = grpc_stream_compression_context_create_identity,
.context_destroy = grpc_stream_compression_context_destroy_identity};

@ -0,0 +1,27 @@
/*
*
* 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_IDENTITY_H
#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_IDENTITY_H
#include "src/core/lib/compression/stream_compression.h"
extern const grpc_stream_compression_vtable
grpc_stream_compression_identity_vtable;
#endif

@ -72,6 +72,8 @@ CORE_SOURCE_FILES = [
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c',

@ -59,10 +59,11 @@ static void test_stream_compression_simple_compress_decompress() {
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_create(
GRPC_STREAM_COMPRESSION_GZIP_COMPRESS);
grpc_stream_compression_context *decompress_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
GRPC_STREAM_COMPRESSION_GZIP_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,
@ -91,10 +92,11 @@ test_stream_compression_simple_compress_decompress_with_output_size_constraint()
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_create(
GRPC_STREAM_COMPRESSION_GZIP_COMPRESS);
grpc_stream_compression_context *decompress_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
GRPC_STREAM_COMPRESSION_GZIP_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,
@ -139,10 +141,11 @@ test_stream_compression_simple_compress_decompress_with_large_data() {
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_create(
GRPC_STREAM_COMPRESSION_GZIP_COMPRESS);
grpc_stream_compression_context *decompress_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
GRPC_STREAM_COMPRESSION_GZIP_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,
@ -172,7 +175,8 @@ static void test_stream_compression_drop_context() {
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_create(
GRPC_STREAM_COMPRESSION_GZIP_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,
@ -180,8 +184,8 @@ static void test_stream_compression_drop_context() {
GRPC_STREAM_COMPRESSION_FLUSH_FINISH));
grpc_stream_compression_context_destroy(compress_ctx);
compress_ctx =
grpc_stream_compression_context_create(GRPC_STREAM_COMPRESSION_COMPRESS);
compress_ctx = grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_GZIP_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,
@ -205,7 +209,7 @@ static void test_stream_compression_drop_context() {
grpc_stream_compression_context *decompress_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS);
bool end_of_context;
size_t output_size;
GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
@ -219,7 +223,7 @@ static void test_stream_compression_drop_context() {
grpc_slice_buffer_init(&sink);
decompress_ctx = grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS);
GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,
~(size_t)0, &end_of_context));
GPR_ASSERT(end_of_context == true);
@ -240,7 +244,8 @@ static void test_stream_compression_sync_flush() {
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_create(
GRPC_STREAM_COMPRESSION_GZIP_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,
@ -249,7 +254,7 @@ static void test_stream_compression_sync_flush() {
grpc_stream_compression_context *decompress_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS);
GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS);
bool end_of_context;
size_t output_size;
GPR_ASSERT(grpc_stream_decompress(decompress_ctx, &relay, &sink, &output_size,

@ -151,6 +151,11 @@ static void request_for_disabled_algorithm(
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
error =
grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
@ -187,10 +192,6 @@ static void request_for_disabled_algorithm(
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
error =
grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(101), true);
cq_verify(cqv);

@ -151,6 +151,11 @@ static void request_for_disabled_algorithm(
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
error =
grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
@ -187,10 +192,6 @@ static void request_for_disabled_algorithm(
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
error =
grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(101), true);
cq_verify(cqv);

@ -944,6 +944,8 @@ 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/compression/stream_compression_gzip.h \
src/core/lib/compression/stream_compression_identity.h \
src/core/lib/debug/stats.h \
src/core/lib/debug/stats_data.h \
src/core/lib/debug/trace.h \

@ -1078,6 +1078,10 @@ 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/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_gzip.h \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/compression/stream_compression_identity.h \
src/core/lib/debug/stats.c \
src/core/lib/debug/stats.h \
src/core/lib/debug/stats_data.c \

@ -8007,6 +8007,8 @@
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/compression/stream_compression.c",
"src/core/lib/compression/stream_compression_gzip.c",
"src/core/lib/compression/stream_compression_identity.c",
"src/core/lib/debug/stats.c",
"src/core/lib/debug/stats_data.c",
"src/core/lib/http/format_request.c",
@ -8159,6 +8161,8 @@
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/compression/stream_compression.h",
"src/core/lib/compression/stream_compression_gzip.h",
"src/core/lib/compression/stream_compression_identity.h",
"src/core/lib/debug/stats.h",
"src/core/lib/debug/stats_data.h",
"src/core/lib/http/format_request.h",
@ -8290,6 +8294,8 @@
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/compression/stream_compression.h",
"src/core/lib/compression/stream_compression_gzip.h",
"src/core/lib/compression/stream_compression_identity.h",
"src/core/lib/debug/stats.h",
"src/core/lib/debug/stats_data.h",
"src/core/lib/http/format_request.h",

Loading…
Cancel
Save