Error handling progress in chttp2 transport

pull/6897/head
Craig Tiller 9 years ago
parent 2b782d877c
commit 781bab5399
  1. 85
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  2. 58
      src/core/ext/transport/chttp2/transport/frame_data.c
  3. 11
      src/core/ext/transport/chttp2/transport/frame_data.h
  4. 37
      src/core/ext/transport/chttp2/transport/frame_goaway.c
  5. 4
      src/core/ext/transport/chttp2/transport/frame_goaway.h
  6. 19
      src/core/ext/transport/chttp2/transport/frame_ping.c
  7. 6
      src/core/ext/transport/chttp2/transport/frame_ping.h
  8. 19
      src/core/ext/transport/chttp2/transport/frame_rst_stream.c
  9. 4
      src/core/ext/transport/chttp2/transport/frame_rst_stream.h
  10. 44
      src/core/ext/transport/chttp2/transport/frame_settings.c
  11. 4
      src/core/ext/transport/chttp2/transport/frame_settings.h
  12. 26
      src/core/ext/transport/chttp2/transport/frame_window_update.c
  13. 4
      src/core/ext/transport/chttp2/transport/frame_window_update.h
  14. 632
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  15. 14
      src/core/ext/transport/chttp2/transport/hpack_parser.h
  16. 44
      src/core/ext/transport/chttp2/transport/hpack_table.c
  17. 9
      src/core/ext/transport/chttp2/transport/hpack_table.h
  18. 7
      src/core/ext/transport/chttp2/transport/internal.h
  19. 14
      src/core/lib/iomgr/closure.c
  20. 8
      src/core/lib/iomgr/closure.h
  21. 16
      src/core/lib/iomgr/error.c
  22. 7
      src/core/lib/iomgr/error.h
  23. 4
      src/core/lib/iomgr/exec_ctx.c

@ -142,7 +142,8 @@ static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream *s,
void *byte_stream);
static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global);
grpc_chttp2_stream_global *stream_global,
grpc_error *error);
/*******************************************************************************
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
@ -746,7 +747,7 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global;
while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
&stream_global)) {
fail_pending_writes(exec_ctx, stream_global);
fail_pending_writes(exec_ctx, stream_global, grpc_error_ref(error));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
}
@ -844,34 +845,36 @@ static void maybe_start_some_streams(
}
#define CLOSURE_BARRIER_STATS_BIT (1 << 0)
#define CLOSURE_BARRIER_FAILURE_BIT (1 << 1)
#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
static grpc_closure *add_closure_barrier(grpc_closure *closure) {
closure->final_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT;
closure->next_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT;
return closure;
}
void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global,
grpc_closure **pclosure, int success) {
grpc_closure **pclosure,
grpc_error *error) {
grpc_closure *closure = *pclosure;
if (closure == NULL) {
return;
}
closure->final_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
if (!success) {
closure->final_data.scratch |= CLOSURE_BARRIER_FAILURE_BIT;
closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
if (error != GRPC_ERROR_NONE) {
if (closure->error == GRPC_ERROR_NONE) {
closure->error =
GRPC_ERROR_CREATE("Error in HTTP transport completing operation");
}
closure->error = grpc_error_add_child(closure->error, error);
}
if (closure->final_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
if (closure->final_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
grpc_transport_move_stats(&stream_global->stats,
stream_global->collecting_stats);
stream_global->collecting_stats = NULL;
}
grpc_exec_ctx_push(
exec_ctx, closure,
(closure->final_data.scratch & CLOSURE_BARRIER_FAILURE_BIT) == 0, NULL);
grpc_exec_ctx_push(exec_ctx, closure, closure->error, NULL);
}
*pclosure = NULL;
}
@ -906,12 +909,12 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
}
/* use final_data as a barrier until enqueue time; the inital counter is
dropped at the end of this function */
on_complete->final_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
if (op->collect_stats != NULL) {
GPR_ASSERT(stream_global->collecting_stats == NULL);
stream_global->collecting_stats = op->collect_stats;
on_complete->final_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
}
if (op->cancel_with_status != GRPC_STATUS_OK) {
@ -946,7 +949,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
} else {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_initial_metadata_finished, 0);
&stream_global->send_initial_metadata_finished,
GRPC_ERROR_CREATE(
"Attempt to send initial metadata after stream was closed"));
}
}
@ -956,7 +961,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
stream_global->send_message_finished = add_closure_barrier(on_complete);
if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_message_finished, 0);
exec_ctx, stream_global, &stream_global->send_message_finished,
GRPC_ERROR_CREATE("Attempt to send message after stream was closed"));
} else {
stream_global->send_message = op->send_message;
if (stream_global->id != 0) {
@ -978,7 +984,10 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_trailing_metadata_finished,
grpc_metadata_batch_is_empty(op->send_trailing_metadata));
grpc_metadata_batch_is_empty(op->send_trailing_metadata)
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE("Attempt to send trailing metadata after "
"stream was closed"));
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
@ -1016,7 +1025,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &on_complete, 1);
grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &on_complete,
GRPC_ERROR_NONE);
GPR_TIMER_END("perform_stream_op_locked", 0);
}
@ -1185,7 +1195,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
stream_global->recv_trailing_metadata);
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->recv_trailing_metadata_finished, 1);
&stream_global->recv_trailing_metadata_finished, GRPC_ERROR_NONE);
}
}
}
@ -1256,8 +1266,10 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
stream_global->seen_error = 1;
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1);
grpc_chttp2_mark_stream_closed(
exec_ctx, transport_global, stream_global, 1, 1,
grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
GRPC_ERROR_INT_GRPC_STATUS, status));
}
void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
@ -1298,23 +1310,25 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
}
static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global) {
grpc_chttp2_stream_global *stream_global,
grpc_error *error) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_initial_metadata_finished,
0);
grpc_error_ref(error));
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_trailing_metadata_finished,
0);
grpc_chttp2_complete_closure_step(exec_ctx, stream_global,
&stream_global->send_message_finished, 0);
grpc_error_ref(error));
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_message_finished, error);
}
void grpc_chttp2_mark_stream_closed(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, int close_reads,
int close_writes) {
grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
grpc_error *error) {
if (stream_global->read_closed && stream_global->write_closed) {
/* already closed */
grpc_error_unref(error);
return;
}
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
@ -1331,7 +1345,7 @@ void grpc_chttp2_mark_stream_closed(
grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
stream_global);
} else {
fail_pending_writes(exec_ctx, stream_global);
fail_pending_writes(exec_ctx, stream_global, grpc_error_ref(error));
}
}
if (stream_global->read_closed && stream_global->write_closed) {
@ -1347,6 +1361,7 @@ void grpc_chttp2_mark_stream_closed(
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
}
}
grpc_error_unref(error);
}
static void close_from_api(grpc_exec_ctx *exec_ctx,
@ -1451,8 +1466,16 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
}
grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
optional_message);
grpc_error *err = GRPC_ERROR_CREATE("Stream closed");
err = grpc_error_set_int(err, GRPC_ERROR_INT_GRPC_STATUS, status);
if (optional_message) {
char *str =
gpr_dump_slice(*optional_message, GPR_DUMP_HEX | GPR_DUMP_ASCII);
err = grpc_error_set_str(err, GRPC_ERROR_STR_GRPC_MESSAGE, str);
gpr_free(str);
}
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1);
1, err);
}
static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,

@ -37,16 +37,16 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/transport.h"
grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
grpc_chttp2_data_parser *parser) {
grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser) {
parser->state = GRPC_CHTTP2_DATA_FH_0;
parser->parsing_frame = NULL;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
@ -62,11 +62,16 @@ void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
}
}
grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
grpc_chttp2_data_parser *parser, uint8_t flags) {
grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser,
uint8_t flags,
uint32_t stream_id) {
if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
return GRPC_CHTTP2_STREAM_ERROR;
char *msg;
gpr_asprintf(&msg, "unsupported data flags: 0x%02x", flags);
grpc_error *err = grpc_error_set_int(GRPC_ERROR_CREATE(msg),
GRPC_ERROR_INT_STREAM_ID, stream_id);
gpr_free(msg);
return err;
}
if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
@ -75,7 +80,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
parser->is_last_frame = 0;
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
void grpc_chttp2_incoming_frame_queue_merge(
@ -139,7 +144,7 @@ void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf,
stats->data_bytes += write_bytes;
}
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_error *grpc_chttp2_data_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -149,19 +154,20 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_chttp2_data_parser *p = parser;
uint32_t message_flags;
grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
char *msg;
if (is_last && p->is_last_frame) {
stream_parsing->received_close = 1;
}
if (cur == end) {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
switch (p->state) {
case GRPC_CHTTP2_DATA_ERROR:
p->state = GRPC_CHTTP2_DATA_ERROR;
return GRPC_CHTTP2_STREAM_ERROR;
return grpc_error_ref(p->error);
fh_0:
case GRPC_CHTTP2_DATA_FH_0:
stream_parsing->stats.incoming.framing_bytes++;
@ -174,13 +180,23 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->is_frame_compressed = 1; /* GPR_TRUE */
break;
default:
gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type);
p->error = GRPC_ERROR_CREATE(msg);
p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID,
stream_parsing->id);
gpr_free(msg);
msg = gpr_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
p->error =
grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES, msg);
gpr_free(msg);
p->error =
grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
p->state = GRPC_CHTTP2_DATA_ERROR;
return GRPC_CHTTP2_STREAM_ERROR;
return grpc_error_ref(p->error);
}
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_1:
@ -188,7 +204,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_size = ((uint32_t)*cur) << 24;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_2:
@ -196,7 +212,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_size |= ((uint32_t)*cur) << 16;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_3:
@ -204,7 +220,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_size |= ((uint32_t)*cur) << 8;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_4;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_4:
@ -225,7 +241,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
if (cur == end) {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
uint32_t remaining = (uint32_t)(end - cur);
if (remaining == p->frame_size) {
@ -237,7 +253,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
1);
p->parsing_frame = NULL;
p->state = GRPC_CHTTP2_DATA_FH_0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
} else if (remaining > p->frame_size) {
stream_parsing->stats.incoming.data_bytes += p->frame_size;
grpc_chttp2_incoming_byte_stream_push(
@ -256,9 +272,9 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
p->frame_size -= remaining;
stream_parsing->stats.incoming.data_bytes += remaining;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
}
GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}

@ -66,6 +66,7 @@ typedef struct {
uint8_t is_last_frame;
uint8_t frame_type;
uint32_t frame_size;
grpc_error *error;
int is_frame_compressed;
grpc_chttp2_incoming_frame_queue incoming_frames;
@ -79,19 +80,19 @@ grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
grpc_chttp2_incoming_frame_queue *q);
/* initialize per-stream state for data frame parsing */
grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
grpc_chttp2_data_parser *parser);
grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser);
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
grpc_chttp2_data_parser *parser);
/* start processing a new data frame */
grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
grpc_chttp2_data_parser *parser, uint8_t flags);
grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser,
uint8_t flags,
uint32_t stream_id);
/* handle a slice of a data frame - is_last indicates the last slice of a
frame */
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_error *grpc_chttp2_data_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) {
p->debug_data = NULL;
@ -47,11 +48,15 @@ void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p) {
gpr_free(p->debug_data);
}
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) {
grpc_error *grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser *p,
uint32_t length,
uint8_t flags) {
if (length < 8) {
gpr_log(GPR_ERROR, "goaway frame too short (%d bytes)", length);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "goaway frame too short (%d bytes)", length);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
gpr_free(p->debug_data);
@ -59,10 +64,10 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
p->debug_data = gpr_malloc(p->debug_length);
p->debug_pos = 0;
p->state = GRPC_CHTTP2_GOAWAY_LSI0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
grpc_error *grpc_chttp2_goaway_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -75,7 +80,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI0:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id = ((uint32_t)*cur) << 24;
++cur;
@ -83,7 +88,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI1:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id |= ((uint32_t)*cur) << 16;
++cur;
@ -91,7 +96,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI2:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id |= ((uint32_t)*cur) << 8;
++cur;
@ -99,7 +104,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI3:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id |= ((uint32_t)*cur);
++cur;
@ -107,7 +112,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR0:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code = ((uint32_t)*cur) << 24;
++cur;
@ -115,7 +120,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR1:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code |= ((uint32_t)*cur) << 16;
++cur;
@ -123,7 +128,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR2:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code |= ((uint32_t)*cur) << 8;
++cur;
@ -131,7 +136,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR3:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code |= ((uint32_t)*cur);
++cur;
@ -150,9 +155,9 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
gpr_slice_new(p->debug_data, p->debug_length, gpr_free);
p->debug_data = NULL;
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,

@ -63,9 +63,9 @@ typedef struct {
void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p);
void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p);
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_error *grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_goaway_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
grpc_error *grpc_chttp2_goaway_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
gpr_slice slice = gpr_slice_malloc(9 + 8);
@ -57,18 +58,22 @@ gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
return slice;
}
grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags) {
grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
uint32_t length,
uint8_t flags) {
if (flags & 0xfe || length != 8) {
gpr_log(GPR_ERROR, "invalid ping: length=%d, flags=%02x", length, flags);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid ping: length=%d, flags=%02x", length, flags);
grpc_error *error = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return error;
}
parser->byte = 0;
parser->is_ack = flags;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
grpc_error *grpc_chttp2_ping_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -93,5 +98,5 @@ grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
}
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}

@ -46,9 +46,9 @@ typedef struct {
gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
uint32_t length, uint8_t flags);
grpc_error *grpc_chttp2_ping_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -34,7 +34,9 @@
#include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/transport/chttp2/transport/frame.h"
@ -62,18 +64,21 @@ gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code,
return slice;
}
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_error *grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags) {
if (length != 4) {
gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length,
flags);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid rst_stream: length=%d, flags=%02x", length,
flags);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
parser->byte = 0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
grpc_error *grpc_chttp2_rst_stream_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -99,5 +104,5 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
(((uint32_t)p->reason_bytes[3]));
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}

@ -47,9 +47,9 @@ typedef struct {
gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code,
grpc_transport_one_way_stats *stats);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_error *grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
grpc_error *grpc_chttp2_rst_stream_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -36,7 +36,9 @@
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
@ -118,7 +120,7 @@ gpr_slice grpc_chttp2_settings_ack_create(void) {
return output;
}
grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
grpc_error *grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
uint32_t *settings) {
parser->target_settings = settings;
@ -129,31 +131,29 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
if (flags == GRPC_CHTTP2_FLAG_ACK) {
parser->is_ack = 1;
if (length != 0) {
gpr_log(GPR_ERROR, "non-empty settings ack frame received");
return GRPC_CHTTP2_CONNECTION_ERROR;
return GRPC_ERROR_CREATE("non-empty settings ack frame received");
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
} else if (flags != 0) {
gpr_log(GPR_ERROR, "invalid flags on settings frame");
return GRPC_CHTTP2_CONNECTION_ERROR;
return GRPC_ERROR_CREATE("invalid flags on settings frame");
} else if (length % 6 != 0) {
gpr_log(GPR_ERROR, "settings frames must be a multiple of six bytes");
return GRPC_CHTTP2_CONNECTION_ERROR;
return GRPC_ERROR_CREATE("settings frames must be a multiple of six bytes");
} else {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
}
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
grpc_error *grpc_chttp2_settings_parser_parse(
grpc_exec_ctx *exec_ctx, void *p,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_settings_parser *parser = p;
const uint8_t *cur = GPR_SLICE_START_PTR(slice);
const uint8_t *end = GPR_SLICE_END_PTR(slice);
char *msg;
if (parser->is_ack) {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
for (;;) {
@ -168,7 +168,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
gpr_slice_buffer_add(&transport_parsing->qbuf,
grpc_chttp2_settings_ack_create());
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->id = (uint16_t)(((uint16_t)*cur) << 8);
cur++;
@ -176,7 +176,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_ID1:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_ID1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->id = (uint16_t)(parser->id | (*cur));
cur++;
@ -184,7 +184,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL0:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->value = ((uint32_t)*cur) << 24;
cur++;
@ -192,7 +192,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL1:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->value |= ((uint32_t)*cur) << 16;
cur++;
@ -200,7 +200,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL2:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->value |= ((uint32_t)*cur) << 8;
cur++;
@ -208,7 +208,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL3:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
} else {
parser->state = GRPC_CHTTP2_SPS_ID0;
}
@ -229,9 +229,11 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
transport_parsing->last_incoming_stream_id, sp->error_value,
gpr_slice_from_static_string("HTTP2 settings error"),
&transport_parsing->qbuf);
gpr_log(GPR_ERROR, "invalid value %u passed for %s",
parser->value, sp->name);
return GRPC_CHTTP2_CONNECTION_ERROR;
gpr_asprintf(&msg, "invalid value %u passed for %s",
parser->value, sp->name);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
}
if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
@ -249,7 +251,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
transport_parsing->is_client ? "CLI" : "SVR", parser->id,
parser->value);
}
} else {
} else if (grpc_http_trace) {
gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
parser->id, parser->value);
}

@ -92,10 +92,10 @@ gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
/* Create an ack settings frame */
gpr_slice grpc_chttp2_settings_ack_create(void);
grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
grpc_error *grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
uint32_t *settings);
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
grpc_error *grpc_chttp2_settings_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -34,7 +34,9 @@
#include "src/core/ext/transport/chttp2/transport/frame_window_update.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
gpr_slice grpc_chttp2_window_update_create(
uint32_t id, uint32_t window_update, grpc_transport_one_way_stats *stats) {
@ -62,19 +64,22 @@ gpr_slice grpc_chttp2_window_update_create(
return slice;
}
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
grpc_error *grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags) {
if (flags || length != 4) {
gpr_log(GPR_ERROR, "invalid window update: length=%d, flags=%02x", length,
flags);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid window update: length=%d, flags=%02x", length,
flags);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
parser->byte = 0;
parser->amount = 0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
grpc_error *grpc_chttp2_window_update_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -96,8 +101,11 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
if (p->byte == 4) {
uint32_t received_update = p->amount;
if (received_update == 0 || (received_update & 0x80000000u)) {
gpr_log(GPR_ERROR, "invalid window update bytes: %d", p->amount);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid window update bytes: %d", p->amount);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
GPR_ASSERT(is_last);
@ -115,5 +123,5 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
}
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}

@ -48,9 +48,9 @@ typedef struct {
gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta,
grpc_transport_one_way_stats *stats);
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
grpc_error *grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
grpc_error *grpc_chttp2_window_update_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

File diff suppressed because it is too large Load Diff

@ -44,9 +44,8 @@
typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser;
typedef int (*grpc_chttp2_hpack_parser_state)(grpc_chttp2_hpack_parser *p,
const uint8_t *beg,
const uint8_t *end);
typedef grpc_error *(*grpc_chttp2_hpack_parser_state)(
grpc_chttp2_hpack_parser *p, const uint8_t *beg, const uint8_t *end);
typedef struct {
char *str;
@ -59,6 +58,8 @@ struct grpc_chttp2_hpack_parser {
void (*on_header)(void *user_data, grpc_mdelem *md);
void *on_header_user_data;
grpc_error *last_error;
/* current parse state - or a function that implements it */
grpc_chttp2_hpack_parser_state state;
/* future states dependent on the opening op code */
@ -103,12 +104,13 @@ void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p);
void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p);
/* returns 1 on success, 0 on error */
int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
const uint8_t *beg, const uint8_t *end);
grpc_error *grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
const uint8_t *beg,
const uint8_t *end);
/* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
the transport */
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
grpc_error *grpc_chttp2_header_parser_parse(
grpc_exec_ctx *exec_ctx, void *hpack_parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/support/murmur_hash.h"
@ -260,18 +261,19 @@ void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
tbl->max_bytes = max_bytes;
}
int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes) {
grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes) {
if (tbl->current_table_bytes == bytes) {
return 1;
return GRPC_ERROR_NONE;
}
if (bytes > tbl->max_bytes) {
if (grpc_http_trace) {
gpr_log(GPR_ERROR,
"Attempt to make hpack table %d bytes when max is %d bytes",
bytes, tbl->max_bytes);
}
return 0;
char *msg;
gpr_asprintf(&msg,
"Attempt to make hpack table %d bytes when max is %d bytes",
bytes, tbl->max_bytes);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
@ -289,23 +291,25 @@ int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
rebuild_ents(tbl, new_cap);
}
}
return 1;
return GRPC_ERROR_NONE;
}
int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
grpc_error *grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
/* determine how many bytes of buffer this entry represents */
size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) +
GPR_SLICE_LENGTH(md->value->slice) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
if (tbl->current_table_bytes > tbl->max_bytes) {
if (grpc_http_trace) {
gpr_log(GPR_ERROR,
"HPACK max table size reduced to %d but not reflected by hpack "
"stream (still at %d)",
tbl->max_bytes, tbl->current_table_bytes);
}
return 0;
char *msg;
gpr_asprintf(
&msg,
"HPACK max table size reduced to %d but not reflected by hpack "
"stream (still at %d)",
tbl->max_bytes, tbl->current_table_bytes);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
/* we can't add elements bigger than the max table size */
@ -322,7 +326,7 @@ int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
while (tbl->num_ents) {
evict1(tbl);
}
return 1;
return GRPC_ERROR_NONE;
}
/* evict entries to ensure no overflow */
@ -337,7 +341,7 @@ int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
/* update accounting values */
tbl->num_ents++;
tbl->mem_used += (uint32_t)elem_bytes;
return 1;
return GRPC_ERROR_NONE;
}
grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(

@ -36,6 +36,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/transport/metadata.h"
/* HPACK header table */
@ -87,15 +88,15 @@ void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl);
void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl);
void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
uint32_t max_bytes);
int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes);
grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes);
/* lookup a table entry based on its hpack index */
grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
uint32_t index);
/* add a table entry to the index */
int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
grpc_mdelem *md) GRPC_MUST_USE_RESULT;
grpc_error *grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
grpc_mdelem *md) GRPC_MUST_USE_RESULT;
/* Find a key/value pair in the table... returns the index in the table of the
most similar entry, or 0 if the value was not found */
typedef struct {

@ -673,7 +673,8 @@ void grpc_chttp2_parsing_become_skip_parser(
void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global,
grpc_closure **pclosure, int success);
grpc_closure **pclosure,
grpc_error *error);
void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *transport,
@ -776,8 +777,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
grpc_status_code status, gpr_slice *details);
void grpc_chttp2_mark_stream_closed(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, int close_reads,
int close_writes);
grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
grpc_error *error);
void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global);

@ -44,21 +44,21 @@ void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
void grpc_closure_list_append(grpc_closure_list *closure_list,
grpc_closure *closure, grpc_error *error) {
if (closure == NULL) return;
closure->final_data.error = error;
closure->next = NULL;
closure->error = error;
closure->next_data.next = NULL;
if (closure_list->head == NULL) {
closure_list->head = closure;
} else {
closure_list->tail->next = closure;
closure_list->tail->next_data.next = closure;
}
closure_list->tail = closure;
}
void grpc_closure_list_fail_all(grpc_closure_list *list,
grpc_error *forced_failure) {
for (grpc_closure *c = list->head; c != NULL; c = c->next) {
if (c->final_data.error == NULL) {
c->final_data.error = grpc_error_ref(forced_failure);
for (grpc_closure *c = list->head; c != NULL; c = c->next_data.next) {
if (c->error == GRPC_ERROR_NONE) {
c->error = grpc_error_ref(forced_failure);
}
}
grpc_error_unref(forced_failure);
@ -75,7 +75,7 @@ void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst) {
if (dst->head == NULL) {
*dst = *src;
} else {
dst->tail->next = src->head;
dst->tail->next_data.next = src->head;
dst->tail = src->tail;
}
src->head = src->tail = NULL;

@ -66,12 +66,12 @@ struct grpc_closure {
/** Arguments to be passed to "cb". */
void *cb_arg;
grpc_error *error;
union {
grpc_error *error;
grpc_closure *next;
uintptr_t scratch;
} final_data;
grpc_closure *next;
} next_data;
};
/** Initializes \a closure with \a cb and \a cb_arg. */

@ -90,6 +90,18 @@ static const char *error_int_name(grpc_error_ints key) {
return "errno";
case GRPC_ERROR_INT_FILE_LINE:
return "file_line";
case GRPC_ERROR_INT_WARNING:
return "warning";
case GRPC_ERROR_INT_STREAM_ID:
return "stream_id";
case GRPC_ERROR_INT_GRPC_STATUS:
return "grpc_status";
case GRPC_ERROR_INT_OFFSET:
return "offset";
case GRPC_ERROR_INT_INDEX:
return "index";
case GRPC_ERROR_INT_SIZE:
return "size";
}
GPR_UNREACHABLE_CODE(return "unknown");
}
@ -106,6 +118,10 @@ static const char *error_str_name(grpc_error_strs key) {
return "syscall";
case GRPC_ERROR_STR_FILE:
return "file";
case GRPC_ERROR_STR_GRPC_MESSAGE:
return "grpc_message";
case GRPC_ERROR_STR_RAW_BYTES:
return "raw_bytes";
}
GPR_UNREACHABLE_CODE(return "unknown");
}

@ -45,6 +45,11 @@ typedef enum {
GRPC_ERROR_INT_FILE_LINE,
GRPC_ERROR_INT_STATUS_CODE,
GRPC_ERROR_INT_WARNING,
GRPC_ERROR_INT_STREAM_ID,
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_ERROR_INT_OFFSET,
GRPC_ERROR_INT_INDEX,
GRPC_ERROR_INT_SIZE,
} grpc_error_ints;
typedef enum {
@ -53,6 +58,8 @@ typedef enum {
GRPC_ERROR_STR_OS_ERROR,
GRPC_ERROR_STR_SYSCALL,
GRPC_ERROR_STR_TARGET_ADDRESS,
GRPC_ERROR_STR_GRPC_MESSAGE,
GRPC_ERROR_STR_RAW_BYTES,
} grpc_error_strs;
typedef enum {

@ -47,8 +47,8 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
grpc_closure *c = exec_ctx->closure_list.head;
exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
while (c != NULL) {
grpc_closure *next = c->next;
grpc_error *error = c->final_data.error;
grpc_closure *next = c->next_data.next;
grpc_error *error = c->error;
did_something = true;
GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
c->cb(exec_ctx, c->cb_arg, error);

Loading…
Cancel
Save