|
|
|
@ -730,6 +730,14 @@ 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_chttp2_list_remove_stalled_by_transport(t, s); |
|
|
|
|
grpc_chttp2_list_remove_stalled_by_stream(t, s); |
|
|
|
@ -780,6 +788,15 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, |
|
|
|
|
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; |
|
|
|
|
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; |
|
|
|
|
|
|
|
|
|
if (s->stream_compression_ctx != NULL) { |
|
|
|
|
grpc_stream_compression_context_destroy(s->stream_compression_ctx); |
|
|
|
|
s->stream_compression_ctx = NULL; |
|
|
|
|
} |
|
|
|
|
if (s->stream_decompression_ctx != NULL) { |
|
|
|
|
grpc_stream_compression_context_destroy(s->stream_decompression_ctx); |
|
|
|
|
s->stream_decompression_ctx = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
s->destroy_stream_arg = then_schedule_closure; |
|
|
|
|
GRPC_CLOSURE_SCHED( |
|
|
|
|
exec_ctx, GRPC_CLOSURE_INIT(&s->destroy_stream, destroy_stream_locked, s, |
|
|
|
@ -1367,8 +1384,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, |
|
|
|
|
"fetching_send_message_finished"); |
|
|
|
|
} else { |
|
|
|
|
GPR_ASSERT(s->fetching_send_message == NULL); |
|
|
|
|
uint8_t *frame_hdr = |
|
|
|
|
grpc_slice_buffer_tiny_add(&s->flow_controlled_buffer, 5); |
|
|
|
|
uint8_t *frame_hdr = grpc_slice_buffer_tiny_add( |
|
|
|
|
&s->flow_controlled_buffer, GRPC_HEADER_SIZE_IN_BYTES); |
|
|
|
|
uint32_t flags = op_payload->send_message.send_message->flags; |
|
|
|
|
frame_hdr[0] = (flags & GRPC_WRITE_INTERNAL_COMPRESS) != 0; |
|
|
|
|
size_t len = op_payload->send_message.send_message->length; |
|
|
|
@ -1459,14 +1476,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, |
|
|
|
|
s->recv_message_ready = op_payload->recv_message.recv_message_ready; |
|
|
|
|
s->recv_message = op_payload->recv_message.recv_message; |
|
|
|
|
if (s->id != 0) { |
|
|
|
|
if (s->pending_byte_stream) { |
|
|
|
|
already_received = s->frame_storage.length; |
|
|
|
|
} else { |
|
|
|
|
already_received = s->frame_storage.length + |
|
|
|
|
s->unprocessed_incoming_frames_buffer.length; |
|
|
|
|
} |
|
|
|
|
incoming_byte_stream_update_flow_control(exec_ctx, t, s, 5, |
|
|
|
|
already_received); |
|
|
|
|
incoming_byte_stream_update_flow_control( |
|
|
|
|
exec_ctx, t, s, GRPC_HEADER_SIZE_IN_BYTES, already_received); |
|
|
|
|
} |
|
|
|
|
grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); |
|
|
|
|
} |
|
|
|
@ -1703,10 +1715,43 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx, |
|
|
|
|
if (s->unprocessed_incoming_frames_buffer.length == 0) { |
|
|
|
|
grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer, |
|
|
|
|
&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); |
|
|
|
|
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->unprocessed_incoming_frames_buffer, |
|
|
|
|
s->decompressed_data_buffer, NULL, |
|
|
|
|
GRPC_HEADER_SIZE_IN_BYTES, |
|
|
|
|
&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); |
|
|
|
|
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
|
|
|
|
"Stream decompression error."); |
|
|
|
|
} else { |
|
|
|
|
error = grpc_deframe_unprocessed_incoming_frames( |
|
|
|
|
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); |
|
|
|
|
s->stream_decompression_ctx = NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
error = grpc_deframe_unprocessed_incoming_frames( |
|
|
|
|
exec_ctx, &s->data_parser, s, |
|
|
|
|
&s->unprocessed_incoming_frames_buffer, NULL, s->recv_message); |
|
|
|
|
} |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
s->seen_error = true; |
|
|
|
|
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, |
|
|
|
@ -1744,7 +1789,37 @@ 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 && |
|
|
|
|
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, |
|
|
|
|
GRPC_HEADER_SIZE_IN_BYTES, &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( |
|
|
|
@ -2612,6 +2687,7 @@ static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx, |
|
|
|
|
if (s->frame_storage.length > 0) { |
|
|
|
|
grpc_slice_buffer_swap(&s->frame_storage, |
|
|
|
|
&s->unprocessed_incoming_frames_buffer); |
|
|
|
|
s->unprocessed_incoming_frames_decompressed = false; |
|
|
|
|
GRPC_CLOSURE_SCHED(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE); |
|
|
|
|
} else if (s->byte_stream_error != GRPC_ERROR_NONE) { |
|
|
|
|
GRPC_CLOSURE_SCHED(exec_ctx, bs->next_action.on_complete, |
|
|
|
@ -2673,17 +2749,41 @@ static grpc_error *incoming_byte_stream_pull(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_chttp2_incoming_byte_stream *bs = |
|
|
|
|
(grpc_chttp2_incoming_byte_stream *)byte_stream; |
|
|
|
|
grpc_chttp2_stream *s = bs->stream; |
|
|
|
|
grpc_error *error; |
|
|
|
|
|
|
|
|
|
if (s->unprocessed_incoming_frames_buffer.length > 0) { |
|
|
|
|
grpc_error *error = grpc_deframe_unprocessed_incoming_frames( |
|
|
|
|
if (s->stream_compression_recv_enabled && |
|
|
|
|
!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); |
|
|
|
|
} |
|
|
|
|
if (!grpc_stream_decompress(s->stream_decompression_ctx, |
|
|
|
|
&s->unprocessed_incoming_frames_buffer, |
|
|
|
|
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->unprocessed_incoming_frames_decompressed = true; |
|
|
|
|
if (end_of_context) { |
|
|
|
|
grpc_stream_compression_context_destroy(s->stream_decompression_ctx); |
|
|
|
|
s->stream_decompression_ctx = NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
error = grpc_deframe_unprocessed_incoming_frames( |
|
|
|
|
exec_ctx, &s->data_parser, s, &s->unprocessed_incoming_frames_buffer, |
|
|
|
|
slice, NULL); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
grpc_error *error = |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message"); |
|
|
|
|
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message"); |
|
|
|
|
GRPC_CLOSURE_SCHED(exec_ctx, &s->reset_byte_stream, GRPC_ERROR_REF(error)); |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|