Fix server side handling of incoming partial requests in core

pull/4453/head
Craig Tiller 9 years ago
parent 6cb69172c1
commit 38edec6606
  1. 12
      src/core/surface/call.c
  2. 9
      src/core/transport/chttp2/frame_data.c
  3. 4
      src/core/transport/chttp2/internal.h
  4. 43
      src/core/transport/chttp2_transport.c

@ -974,11 +974,19 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
batch_control *bctl = bctlp; batch_control *bctl = bctlp;
grpc_call *call = bctl->call; grpc_call *call = bctl->call;
GPR_ASSERT(success); if (success) {
gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer, gpr_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
call->receiving_slice); call->receiving_slice);
continue_receiving_slices(exec_ctx, bctl); continue_receiving_slices(exec_ctx, bctl);
} else {
grpc_byte_stream_destroy(call->receiving_stream);
call->receiving_stream = NULL;
grpc_byte_buffer_destroy(*call->receiving_buffer);
*call->receiving_buffer = NULL;
if (gpr_unref(&bctl->steps_to_complete)) {
post_batch_completion(exec_ctx, bctl);
}
}
} }
static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, int success) { static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, int success) {

@ -53,7 +53,8 @@ void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
grpc_chttp2_data_parser *parser) { grpc_chttp2_data_parser *parser) {
grpc_byte_stream *bs; grpc_byte_stream *bs;
if (parser->parsing_frame) { if (parser->parsing_frame) {
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame); grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame,
0, 1);
} }
while ( while (
(bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) { (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
@ -218,7 +219,8 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_chttp2_incoming_byte_stream_push( grpc_chttp2_incoming_byte_stream_push(
exec_ctx, p->parsing_frame, exec_ctx, p->parsing_frame,
gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame); grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
1);
p->parsing_frame = NULL; p->parsing_frame = NULL;
p->state = GRPC_CHTTP2_DATA_FH_0; p->state = GRPC_CHTTP2_DATA_FH_0;
return GRPC_CHTTP2_PARSE_OK; return GRPC_CHTTP2_PARSE_OK;
@ -227,7 +229,8 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
exec_ctx, p->parsing_frame, exec_ctx, p->parsing_frame,
gpr_slice_sub(slice, (size_t)(cur - beg), gpr_slice_sub(slice, (size_t)(cur - beg),
(size_t)(cur + p->frame_size - beg))); (size_t)(cur + p->frame_size - beg)));
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame); grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
1);
p->parsing_frame = NULL; p->parsing_frame = NULL;
cur += p->frame_size; cur += p->frame_size;
goto fh_0; /* loop */ goto fh_0; /* loop */

@ -151,6 +151,7 @@ struct grpc_chttp2_incoming_byte_stream {
grpc_byte_stream base; grpc_byte_stream base;
gpr_refcount refs; gpr_refcount refs;
struct grpc_chttp2_incoming_byte_stream *next_message; struct grpc_chttp2_incoming_byte_stream *next_message;
int failed;
grpc_chttp2_transport *transport; grpc_chttp2_transport *transport;
grpc_chttp2_stream *stream; grpc_chttp2_stream *stream;
@ -742,7 +743,8 @@ void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
grpc_chttp2_incoming_byte_stream *bs, grpc_chttp2_incoming_byte_stream *bs,
gpr_slice slice); gpr_slice slice);
void grpc_chttp2_incoming_byte_stream_finished( void grpc_chttp2_incoming_byte_stream_finished(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs); grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
int from_parsing_thread);
void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *parsing, grpc_chttp2_transport_parsing *parsing,

@ -115,7 +115,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
grpc_status_code status, grpc_status_code status,
gpr_slice *optional_message); gpr_slice *optional_message);
/** Fail any outstanding ops */ /** Fail any outstanding ops: must be called under lock, whilst not parsing */
static void fail_all_outstanding_ops( static void fail_all_outstanding_ops(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global); grpc_chttp2_stream_global *stream_global);
@ -756,6 +756,9 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
static void fail_all_outstanding_ops( static void fail_all_outstanding_ops(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) { grpc_chttp2_stream_global *stream_global) {
grpc_chttp2_stream_parsing *stream_parsing;
GPR_ASSERT(!TRANSPORT_FROM_GLOBAL(transport_global)->parsing_active);
stream_parsing = &STREAM_FROM_GLOBAL(stream_global)->parsing;
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->send_initial_metadata_finished, 0); exec_ctx, &stream_global->send_initial_metadata_finished, 0);
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
@ -766,6 +769,15 @@ static void fail_all_outstanding_ops(
exec_ctx, &stream_global->recv_initial_metadata_finished, 0); exec_ctx, &stream_global->recv_initial_metadata_finished, 0);
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->recv_trailing_metadata_finished, 0); exec_ctx, &stream_global->recv_trailing_metadata_finished, 0);
if (stream_global->recv_message_ready != NULL) {
grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, 0);
stream_global->recv_message_ready = 0;
}
if (stream_parsing->data_parser.parsing_frame != NULL) {
grpc_chttp2_incoming_byte_stream_finished(
exec_ctx, stream_parsing->data_parser.parsing_frame, 0, 0);
stream_parsing->data_parser.parsing_frame = NULL;
}
} }
static int contains_non_ok_status( static int contains_non_ok_status(
@ -1502,6 +1514,10 @@ static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx,
*slice = gpr_slice_buffer_take_first(&bs->slices); *slice = gpr_slice_buffer_take_first(&bs->slices);
unlock(exec_ctx, bs->transport); unlock(exec_ctx, bs->transport);
return 1; return 1;
} else if (bs->failed) {
grpc_exec_ctx_enqueue(exec_ctx, on_complete, 0);
unlock(exec_ctx, bs->transport);
return 0;
} else { } else {
bs->on_next = on_complete; bs->on_next = on_complete;
bs->next = slice; bs->next = slice;
@ -1536,7 +1552,29 @@ void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
} }
void grpc_chttp2_incoming_byte_stream_finished( void grpc_chttp2_incoming_byte_stream_finished(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs) { grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
int from_parsing_thread) {
if (!success) {
if (from_parsing_thread) {
gpr_mu_lock(&bs->transport->mu);
}
grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, 0);
bs->on_next = NULL;
bs->failed = 1;
if (from_parsing_thread) {
gpr_mu_unlock(&bs->transport->mu);
}
} else {
#ifndef NDEBUG
if (from_parsing_thread) {
gpr_mu_lock(&bs->transport->mu);
}
GPR_ASSERT(bs->on_next == NULL);
if (from_parsing_thread) {
gpr_mu_unlock(&bs->transport->mu);
}
#endif
}
incoming_byte_stream_unref(bs); incoming_byte_stream_unref(bs);
} }
@ -1557,6 +1595,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
gpr_slice_buffer_init(&incoming_byte_stream->slices); gpr_slice_buffer_init(&incoming_byte_stream->slices);
incoming_byte_stream->on_next = NULL; incoming_byte_stream->on_next = NULL;
incoming_byte_stream->is_tail = 1; incoming_byte_stream->is_tail = 1;
incoming_byte_stream->failed = 0;
if (add_to_queue->head == NULL) { if (add_to_queue->head == NULL) {
add_to_queue->head = incoming_byte_stream; add_to_queue->head = incoming_byte_stream;
} else { } else {

Loading…
Cancel
Save