aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext
diff options
context:
space:
mode:
authorGravatar Muxi Yan <mxyan@google.com>2017-07-13 21:07:29 -0700
committerGravatar Muxi Yan <mxyan@google.com>2017-07-17 11:19:13 -0700
commit0fd37e1951ae541d873d0f2803ebeb88d9c9f848 (patch)
tree2db3599b67e0bcd4dcf33841376dc68fd9bc0037 /src/core/ext
parentd07b88457440d0e5ba5b4e714a13637dff85ee0d (diff)
Transport - Fix a bug in decompression path
Diffstat (limited to 'src/core/ext')
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 00b0738b20..1427b8f330 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -1671,9 +1671,8 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
}
if (s->stream_compression_recv_enabled &&
!s->unprocessed_incoming_frames_decompressed) {
- grpc_slice_buffer decompressed_data;
+ GPR_ASSERT(s->decompressed_data_buffer.length == 0);
bool end_of_context;
- grpc_slice_buffer_init(&decompressed_data);
if (!s->stream_decompression_ctx) {
s->stream_decompression_ctx =
grpc_stream_compression_context_create(
@@ -1681,17 +1680,18 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
}
if (!grpc_stream_decompress(s->stream_decompression_ctx,
&s->unprocessed_incoming_frames_buffer,
- &decompressed_data, NULL, 5,
+ &s->decompressed_data_buffer, NULL, 5,
&end_of_context)) {
grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
&s->frame_storage);
grpc_slice_buffer_reset_and_unref_internal(
exec_ctx, &s->unprocessed_incoming_frames_buffer);
- s->seen_error = true;
+ error =
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error.");
} else {
error = grpc_deframe_unprocessed_incoming_frames(
- exec_ctx, &s->data_parser, s, &decompressed_data, 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);
@@ -1740,7 +1740,38 @@ 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->read_closed && s->frame_storage.length == 0 &&
+ if (s->stream_compression_recv_enabled && s->read_closed &&
+ s->frame_storage.length > 0 &&
+ s->unprocessed_incoming_frames_buffer.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);
+ }
+ if (!grpc_stream_decompress(s->stream_decompression_ctx,
+ &s->frame_storage,
+ &s->unprocessed_incoming_frames_buffer,
+ NULL, 5, &end_of_context)) {
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
+ &s->frame_storage);
+ grpc_slice_buffer_reset_and_unref_internal(
+ exec_ctx, &s->unprocessed_incoming_frames_buffer);
+ s->seen_error = true;
+ } else {
+ if (s->unprocessed_incoming_frames_buffer.length > 0) {
+ s->unprocessed_incoming_frames_decompressed = true;
+ }
+ if (end_of_context) {
+ grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
+ s->stream_decompression_ctx = NULL;
+ }
+ }
+ }
+ if (s->read_closed && s->frame_storage.length == 0 && s->unprocessed_incoming_frames_buffer.length == 0 &&
(!pending_data || s->seen_error) &&
s->recv_trailing_metadata_finished != NULL) {
grpc_chttp2_incoming_metadata_buffer_publish(