aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext/transport
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2016-05-05 08:15:28 -0700
committerGravatar Craig Tiller <ctiller@google.com>2016-05-05 08:15:28 -0700
commit781bab5399e91c99b70af3ec242c321585d22c07 (patch)
tree12d48e3e3728b78e7d87c91fdacab925b5e3ed8a /src/core/ext/transport
parent2b782d877c5f6e774addd40b7584c39d9da9d198 (diff)
Error handling progress in chttp2 transport
Diffstat (limited to 'src/core/ext/transport')
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c85
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_data.c58
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_data.h11
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_goaway.c37
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_goaway.h4
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_ping.c19
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_ping.h6
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_rst_stream.c19
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_rst_stream.h4
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_settings.c44
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_settings.h4
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_window_update.c26
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_window_update.h4
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_parser.c632
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_parser.h14
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_table.c44
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_table.h9
-rw-r--r--src/core/ext/transport/chttp2/transport/internal.h7
18 files changed, 579 insertions, 448 deletions
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index d49c56ab63..25d37711e5 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.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,
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.c b/src/core/ext/transport/chttp2/transport/frame_data.c
index 3a6d80e0a3..828d0427ac 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.c
+++ b/src/core/ext/transport/chttp2/transport/frame_data.c
@@ -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"));
}
diff --git a/src/core/ext/transport/chttp2/transport/frame_data.h b/src/core/ext/transport/chttp2/transport/frame_data.h
index af71f483a2..a21a7942b9 100644
--- a/src/core/ext/transport/chttp2/transport/frame_data.h
+++ b/src/core/ext/transport/chttp2/transport/frame_data.h
@@ -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);
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.c b/src/core/ext/transport/chttp2/transport/frame_goaway.c
index 69accb7696..c985169f51 100644
--- a/src/core/ext/transport/chttp2/transport/frame_goaway.c
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.c
@@ -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,
diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.h b/src/core/ext/transport/chttp2/transport/frame_goaway.h
index 7c38b26a39..eb4303405a 100644
--- a/src/core/ext/transport/chttp2/transport/frame_goaway.h
+++ b/src/core/ext/transport/chttp2/transport/frame_goaway.h
@@ -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);
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.c b/src/core/ext/transport/chttp2/transport/frame_ping.c
index 7e1815f0fe..1f814ab1bd 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.c
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -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;
}
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.h b/src/core/ext/transport/chttp2/transport/frame_ping.h
index 4f7fcc1305..5a8723421c 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.h
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.h
@@ -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);
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
index 22467e9ddd..d49df0fcc2 100644
--- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c
@@ -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;
}
diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
index 9c1e756a94..11cf94f3ea 100644
--- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
+++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h
@@ -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);
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c
index a3c1e15f35..04b96c4cd9 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.c
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.c
@@ -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);
}
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h
index d9e30f1ed0..f654c598c8 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.h
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.h
@@ -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);
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.c b/src/core/ext/transport/chttp2/transport/frame_window_update.c
index 90243418bd..3cf848fd5c 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.c
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.c
@@ -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;
}
diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.h b/src/core/ext/transport/chttp2/transport/frame_window_update.h
index d6e87b9329..1bcbbf9247 100644
--- a/src/core/ext/transport/chttp2/transport/frame_window_update.h
+++ b/src/core/ext/transport/chttp2/transport/frame_window_update.h
@@ -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);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c
index 687936bfd3..993c6d0204 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c
@@ -46,6 +46,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
+#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
@@ -77,63 +78,70 @@ typedef enum {
a set of indirect jumps, and so not waste stack space. */
/* forward declarations for parsing states */
-static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-
-static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+static grpc_error *parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
const uint8_t *end);
-static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur,
- const uint8_t *end);
-static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur,
- const uint8_t *end);
-
-static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-
-static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end);
-static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end);
-static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end);
-static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+static grpc_error *parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end, grpc_error *error);
+static grpc_error *still_parse_error(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_illegal_op(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+
+static grpc_error *parse_string_prefix(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_key_string(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_value_string_with_indexed_key(
+ grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_value_string_with_literal_key(
+ grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end);
+
+static grpc_error *parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
const uint8_t *end);
+static grpc_error *parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_value5up(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+
+static grpc_error *parse_indexed_field(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_lithdr_incidx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_lithdr_notidx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end);
+static grpc_error *parse_max_tbl_size(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
+static grpc_error *parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end);
/* we translate the first byte of a hpack field into one of these decoding
cases, then use a lookup table to jump directly to the appropriate parser.
@@ -631,19 +639,18 @@ static const uint8_t inverse_base64[256] = {
};
/* emission helpers */
-static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
- int add_to_table) {
+static grpc_error *on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
+ int add_to_table) {
if (add_to_table) {
- if (!grpc_chttp2_hptbl_add(&p->table, md)) {
- return 0;
- }
+ grpc_error *err = grpc_chttp2_hptbl_add(&p->table, md);
+ if (err != GRPC_ERROR_NONE) return err;
}
if (p->on_header == NULL) {
GRPC_MDELEM_UNREF(md);
- return 0;
+ return GRPC_ERROR_CREATE("on_header callback not set");
}
p->on_header(p->on_header_user_data, md);
- return 1;
+ return GRPC_ERROR_NONE;
}
static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
@@ -654,70 +661,70 @@ static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
}
/* jump to the next state */
-static int parse_next(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_next(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
p->state = *p->next_state++;
return p->state(p, cur, end);
}
/* begin parsing a header: all functionality is encoded into lookup tables
above */
-static int parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_begin(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
if (cur == end) {
p->state = parse_begin;
- return 1;
+ return GRPC_ERROR_NONE;
}
return first_byte_action[first_byte_lut[*cur]](p, cur, end);
}
/* stream dependency and prioritization data: we just skip it */
-static int parse_stream_weight(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_stream_weight(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (cur == end) {
p->state = parse_stream_weight;
- return 1;
+ return GRPC_ERROR_NONE;
}
return p->after_prioritization(p, cur + 1, end);
}
-static int parse_stream_dep3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_stream_dep3(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (cur == end) {
p->state = parse_stream_dep3;
- return 1;
+ return GRPC_ERROR_NONE;
}
return parse_stream_weight(p, cur + 1, end);
}
-static int parse_stream_dep2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_stream_dep2(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (cur == end) {
p->state = parse_stream_dep2;
- return 1;
+ return GRPC_ERROR_NONE;
}
return parse_stream_dep3(p, cur + 1, end);
}
-static int parse_stream_dep1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_stream_dep1(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (cur == end) {
p->state = parse_stream_dep1;
- return 1;
+ return GRPC_ERROR_NONE;
}
return parse_stream_dep2(p, cur + 1, end);
}
-static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_stream_dep0(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (cur == end) {
p->state = parse_stream_dep0;
- return 1;
+ return GRPC_ERROR_NONE;
}
return parse_stream_dep1(p, cur + 1, end);
@@ -725,30 +732,34 @@ static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
/* emit an indexed field; for now just logs it to console; jumps to
begin the next field on completion */
-static int finish_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *finish_indexed_field(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
if (md == NULL) {
- if (grpc_http_trace) {
- gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
- }
- return 0;
+ return grpc_error_set_int(
+ grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
+ GRPC_ERROR_INT_INDEX, p->index),
+ GRPC_ERROR_INT_SIZE, p->table.num_ents);
}
GRPC_MDELEM_REF(md);
- return on_hdr(p, md, 0) && parse_begin(p, cur, end);
+ grpc_error *err = on_hdr(p, md, 0);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* parse an indexed field with index < 127 */
-static int parse_indexed_field(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_indexed_field(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
p->dynamic_table_update_allowed = 0;
p->index = (*cur) & 0x7f;
return finish_indexed_field(p, cur + 1, end);
}
/* parse an indexed field with index >= 127 */
-static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
finish_indexed_field};
p->dynamic_table_update_allowed = 0;
@@ -760,28 +771,34 @@ static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
/* finish a literal header with incremental indexing: just log, and jump to '
begin */
-static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *finish_lithdr_incidx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
- return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
- take_string(p, &p->value)),
- 1) &&
- parse_begin(p, cur, end);
+ grpc_error *err =
+ on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+ take_string(p, &p->value)),
+ 1);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* finish a literal header with incremental indexing with no index */
-static int finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
- return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
- take_string(p, &p->value)),
- 1) &&
- parse_begin(p, cur, end);
+static grpc_error *finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
+ grpc_error *err =
+ on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+ take_string(p, &p->value)),
+ 1);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* parse a literal header with incremental indexing; index < 63 */
-static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_lithdr_incidx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_value_string_with_indexed_key, finish_lithdr_incidx};
p->dynamic_table_update_allowed = 0;
@@ -791,8 +808,9 @@ static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
/* parse a literal header with incremental indexing; index >= 63 */
-static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_string_prefix, parse_value_string_with_indexed_key,
finish_lithdr_incidx};
@@ -804,8 +822,9 @@ static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
}
/* parse a literal header with incremental indexing; index = 0 */
-static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_key_string, parse_string_prefix,
parse_value_string_with_literal_key, finish_lithdr_incidx_v};
@@ -815,28 +834,34 @@ static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
}
/* finish a literal header without incremental indexing */
-static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *finish_lithdr_notidx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
- return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
- take_string(p, &p->value)),
- 0) &&
- parse_begin(p, cur, end);
+ grpc_error *err =
+ on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+ take_string(p, &p->value)),
+ 0);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* finish a literal header without incremental indexing with index = 0 */
-static int finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
- return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
- take_string(p, &p->value)),
- 0) &&
- parse_begin(p, cur, end);
+static grpc_error *finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
+ grpc_error *err =
+ on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+ take_string(p, &p->value)),
+ 0);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* parse a literal header without incremental indexing; index < 15 */
-static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_lithdr_notidx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_value_string_with_indexed_key, finish_lithdr_notidx};
p->dynamic_table_update_allowed = 0;
@@ -846,8 +871,9 @@ static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
/* parse a literal header without incremental indexing; index >= 15 */
-static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_string_prefix, parse_value_string_with_indexed_key,
finish_lithdr_notidx};
@@ -859,8 +885,9 @@ static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
}
/* parse a literal header without incremental indexing; index == 0 */
-static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_key_string, parse_string_prefix,
parse_value_string_with_literal_key, finish_lithdr_notidx_v};
@@ -870,28 +897,34 @@ static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
}
/* finish a literal header that is never indexed */
-static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
- return on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
- take_string(p, &p->value)),
- 0) &&
- parse_begin(p, cur, end);
+ grpc_error *err =
+ on_hdr(p, grpc_mdelem_from_metadata_strings(GRPC_MDSTR_REF(md->key),
+ take_string(p, &p->value)),
+ 0);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* finish a literal header that is never indexed with an extra value */
-static int finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
- return on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
- take_string(p, &p->value)),
- 0) &&
- parse_begin(p, cur, end);
+static grpc_error *finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
+ grpc_error *err =
+ on_hdr(p, grpc_mdelem_from_metadata_strings(take_string(p, &p->key),
+ take_string(p, &p->value)),
+ 0);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* parse a literal header that is never indexed; index < 15 */
-static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_value_string_with_indexed_key, finish_lithdr_nvridx};
p->dynamic_table_update_allowed = 0;
@@ -901,8 +934,9 @@ static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
/* parse a literal header that is never indexed; index >= 15 */
-static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_string_prefix, parse_value_string_with_indexed_key,
finish_lithdr_nvridx};
@@ -914,8 +948,9 @@ static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
}
/* parse a literal header that is never indexed; index == 0 */
-static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur, const uint8_t *end) {
+static grpc_error *parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_key_string, parse_string_prefix,
parse_value_string_with_literal_key, finish_lithdr_nvridx_v};
@@ -925,20 +960,23 @@ static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
}
/* finish parsing a max table size change */
-static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *finish_max_tbl_size(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (grpc_http_trace) {
gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index);
}
- return grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index) &&
- parse_begin(p, cur, end);
+ grpc_error *err =
+ grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_begin(p, cur, end);
}
/* parse a max table size change, max size < 15 */
-static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_max_tbl_size(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (p->dynamic_table_update_allowed == 0) {
- return 0;
+ return GRPC_ERROR_CREATE(
+ "More than two max table size changes in a single frame");
}
p->dynamic_table_update_allowed--;
p->index = (*cur) & 0x1f;
@@ -946,12 +984,14 @@ static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
/* parse a max table size change, max size >= 15 */
-static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur,
+ const uint8_t *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = {
finish_max_tbl_size};
if (p->dynamic_table_update_allowed == 0) {
- return 0;
+ return GRPC_ERROR_CREATE(
+ "More than two max table size changes in a single frame");
}
p->dynamic_table_update_allowed--;
p->next_state = and_then;
@@ -961,28 +1001,36 @@ static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
/* a parse error: jam the parse state into parse_error, and return error */
-static int parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
- p->state = parse_error;
- return 0;
+static grpc_error *parse_error(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end, grpc_error *err) {
+ GPR_ASSERT(err != GRPC_ERROR_NONE);
+ p->last_error = grpc_error_ref(err);
+ p->state = still_parse_error;
+ return err;
+}
+
+static grpc_error *still_parse_error(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
+ return grpc_error_ref(p->last_error);
}
-static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_illegal_op(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
GPR_ASSERT(cur != end);
- if (grpc_http_trace) {
- gpr_log(GPR_DEBUG, "Illegal hpack op code %d", *cur);
- }
- return parse_error(p, cur, end);
+ char *msg;
+ gpr_asprintf(&msg, "Illegal hpack op code %d", *cur);
+ grpc_error *err = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
+ return parse_error(p, cur, end, err);
}
/* parse the 1st byte of a varint into p->parsing.value
no overflow is possible */
-static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
if (cur == end) {
p->state = parse_value0;
- return 1;
+ return GRPC_ERROR_NONE;
}
*p->parsing.value += (*cur) & 0x7f;
@@ -996,11 +1044,11 @@ static int parse_value0(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
/* parse the 2nd byte of a varint into p->parsing.value
no overflow is possible */
-static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
if (cur == end) {
p->state = parse_value1;
- return 1;
+ return GRPC_ERROR_NONE;
}
*p->parsing.value += (((uint32_t)*cur) & 0x7f) << 7;
@@ -1014,11 +1062,11 @@ static int parse_value1(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
/* parse the 3rd byte of a varint into p->parsing.value
no overflow is possible */
-static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
if (cur == end) {
p->state = parse_value2;
- return 1;
+ return GRPC_ERROR_NONE;
}
*p->parsing.value += (((uint32_t)*cur) & 0x7f) << 14;
@@ -1032,11 +1080,11 @@ static int parse_value2(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
/* parse the 4th byte of a varint into p->parsing.value
no overflow is possible */
-static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
if (cur == end) {
p->state = parse_value3;
- return 1;
+ return GRPC_ERROR_NONE;
}
*p->parsing.value += (((uint32_t)*cur) & 0x7f) << 21;
@@ -1050,15 +1098,16 @@ static int parse_value3(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
/* parse the 5th byte of a varint into p->parsing.value
depending on the byte, we may overflow, and care must be taken */
-static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
uint8_t c;
uint32_t cur_value;
uint32_t add_value;
+ char *msg;
if (cur == end) {
p->state = parse_value4;
- return 1;
+ return GRPC_ERROR_NONE;
}
c = (*cur) & 0x7f;
@@ -1081,48 +1130,49 @@ static int parse_value4(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
error:
- if (grpc_http_trace) {
- gpr_log(GPR_ERROR,
- "integer overflow in hpack integer decoding: have 0x%08x, "
- "got byte 0x%02x on byte 5",
- *p->parsing.value, *cur);
- }
- return parse_error(p, cur, end);
+ gpr_asprintf(&msg,
+ "integer overflow in hpack integer decoding: have 0x%08x, "
+ "got byte 0x%02x on byte 5",
+ *p->parsing.value, *cur);
+ grpc_error *err = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
+ return parse_error(p, cur, end, err);
}
/* parse any trailing bytes in a varint: it's possible to append an arbitrary
number of 0x80's and not affect the value - a zero will terminate - and
anything else will overflow */
-static int parse_value5up(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_value5up(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
while (cur != end && *cur == 0x80) {
++cur;
}
if (cur == end) {
p->state = parse_value5up;
- return 1;
+ return GRPC_ERROR_NONE;
}
if (*cur == 0) {
return parse_next(p, cur + 1, end);
}
- if (grpc_http_trace) {
- gpr_log(GPR_ERROR,
- "integer overflow in hpack integer decoding: have 0x%08x, "
- "got byte 0x%02x sometime after byte 5",
- *p->parsing.value, *cur);
- }
- return parse_error(p, cur, end);
+ char *msg;
+ gpr_asprintf(&msg,
+ "integer overflow in hpack integer decoding: have 0x%08x, "
+ "got byte 0x%02x sometime after byte 5",
+ *p->parsing.value, *cur);
+ grpc_error *err = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
+ return parse_error(p, cur, end, err);
}
/* parse a string prefix */
-static int parse_string_prefix(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_string_prefix(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (cur == end) {
p->state = parse_string_prefix;
- return 1;
+ return GRPC_ERROR_NONE;
}
p->strlen = (*cur) & 0x7f;
@@ -1148,25 +1198,25 @@ static void append_bytes(grpc_chttp2_hpack_parser_string *str,
str->length += (uint32_t)length;
}
-static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *append_string(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
grpc_chttp2_hpack_parser_string *str = p->parsing.str;
uint32_t bits;
uint8_t decoded[3];
switch ((binary_state)p->binary) {
case NOT_BINARY:
append_bytes(str, cur, (size_t)(end - cur));
- return 1;
+ return GRPC_ERROR_NONE;
b64_byte0:
case B64_BYTE0:
if (cur == end) {
p->binary = B64_BYTE0;
- return 1;
+ return GRPC_ERROR_NONE;
}
bits = inverse_base64[*cur];
++cur;
if (bits == 255)
- return 0;
+ return GRPC_ERROR_CREATE("Illegal base64 character");
else if (bits == 64)
goto b64_byte0;
p->base64_buffer = bits << 18;
@@ -1175,12 +1225,12 @@ static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
case B64_BYTE1:
if (cur == end) {
p->binary = B64_BYTE1;
- return 1;
+ return GRPC_ERROR_NONE;
}
bits = inverse_base64[*cur];
++cur;
if (bits == 255)
- return 0;
+ return GRPC_ERROR_CREATE("Illegal base64 character");
else if (bits == 64)
goto b64_byte1;
p->base64_buffer |= bits << 12;
@@ -1189,12 +1239,12 @@ static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
case B64_BYTE2:
if (cur == end) {
p->binary = B64_BYTE2;
- return 1;
+ return GRPC_ERROR_NONE;
}
bits = inverse_base64[*cur];
++cur;
if (bits == 255)
- return 0;
+ return GRPC_ERROR_CREATE("Illegal base64 character");
else if (bits == 64)
goto b64_byte2;
p->base64_buffer |= bits << 6;
@@ -1203,12 +1253,12 @@ static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
case B64_BYTE3:
if (cur == end) {
p->binary = B64_BYTE3;
- return 1;
+ return GRPC_ERROR_NONE;
}
bits = inverse_base64[*cur];
++cur;
if (bits == 255)
- return 0;
+ return GRPC_ERROR_CREATE("Illegal base64 character");
else if (bits == 64)
goto b64_byte3;
p->base64_buffer |= bits;
@@ -1219,11 +1269,11 @@ static int append_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
append_bytes(str, decoded, 3);
goto b64_byte0;
}
- GPR_UNREACHABLE_CODE(return 1);
+ GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
/* append a null terminator to a string */
-static int finish_str(grpc_chttp2_hpack_parser *p) {
+static grpc_error *finish_str(grpc_chttp2_hpack_parser *p) {
uint8_t terminator = 0;
uint8_t decoded[2];
uint32_t bits;
@@ -1234,14 +1284,17 @@ static int finish_str(grpc_chttp2_hpack_parser *p) {
case B64_BYTE0:
break;
case B64_BYTE1:
- gpr_log(GPR_ERROR, "illegal base64 encoding");
- return 0; /* illegal encoding */
+ return GRPC_ERROR_CREATE(
+ "illegal base64 encoding"); /* illegal encoding */
case B64_BYTE2:
bits = p->base64_buffer;
if (bits & 0xffff) {
- gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%04x",
- bits & 0xffff);
- return 0;
+ char *msg;
+ gpr_asprintf(&msg, "trailing bits in base64 encoding: 0x%04x",
+ bits & 0xffff);
+ grpc_error *err = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
+ return err;
}
decoded[0] = (uint8_t)(bits >> 16);
append_bytes(str, decoded, 1);
@@ -1249,9 +1302,12 @@ static int finish_str(grpc_chttp2_hpack_parser *p) {
case B64_BYTE3:
bits = p->base64_buffer;
if (bits & 0xff) {
- gpr_log(GPR_ERROR, "trailing bits in base64 encoding: 0x%02x",
- bits & 0xff);
- return 0;
+ char *msg;
+ gpr_asprintf(&msg, "trailing bits in base64 encoding: 0x%02x",
+ bits & 0xff);
+ grpc_error *err = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
+ return err;
}
decoded[0] = (uint8_t)(bits >> 16);
decoded[1] = (uint8_t)(bits >> 8);
@@ -1260,38 +1316,42 @@ static int finish_str(grpc_chttp2_hpack_parser *p) {
}
append_bytes(str, &terminator, 1);
p->parsing.str->length--; /* don't actually count the null terminator */
- return 1;
+ return GRPC_ERROR_NONE;
}
/* decode a nibble from a huffman encoded stream */
-static int huff_nibble(grpc_chttp2_hpack_parser *p, uint8_t nibble) {
+static grpc_error *huff_nibble(grpc_chttp2_hpack_parser *p, uint8_t nibble) {
int16_t emit = emit_sub_tbl[16 * emit_tbl[p->huff_state] + nibble];
int16_t next = next_sub_tbl[16 * next_tbl[p->huff_state] + nibble];
if (emit != -1) {
if (emit >= 0 && emit < 256) {
uint8_t c = (uint8_t)emit;
- if (!append_string(p, &c, (&c) + 1)) return 0;
+ grpc_error *err = append_string(p, &c, (&c) + 1);
+ if (err != GRPC_ERROR_NONE) return err;
} else {
assert(emit == 256);
}
}
p->huff_state = next;
- return 1;
+ return GRPC_ERROR_NONE;
}
/* decode full bytes from a huffman encoded stream */
-static int add_huff_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *add_huff_bytes(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
for (; cur != end; ++cur) {
- if (!huff_nibble(p, *cur >> 4) || !huff_nibble(p, *cur & 0xf)) return 0;
+ grpc_error *err = huff_nibble(p, *cur >> 4);
+ if (err != GRPC_ERROR_NONE) return err;
+ err = huff_nibble(p, *cur & 0xf);
+ if (err != GRPC_ERROR_NONE) return err;
}
- return 1;
+ return GRPC_ERROR_NONE;
}
/* decode some string bytes based on the current decoding mode
(huffman or not) */
-static int add_str_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *add_str_bytes(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
if (p->huff) {
return add_huff_bytes(p, cur, end);
} else {
@@ -1300,26 +1360,31 @@ static int add_str_bytes(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
/* parse a string - tries to do large chunks at a time */
-static int parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
+ const uint8_t *end) {
size_t remaining = p->strlen - p->strgot;
size_t given = (size_t)(end - cur);
if (remaining <= given) {
- return add_str_bytes(p, cur, cur + remaining) && finish_str(p) &&
- parse_next(p, cur + remaining, end);
+ grpc_error *err = add_str_bytes(p, cur, cur + remaining);
+ if (err != GRPC_ERROR_NONE) return err;
+ err = finish_str(p);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_next(p, cur + remaining, end);
} else {
- if (!add_str_bytes(p, cur, cur + given)) return 0;
+ grpc_error *err = add_str_bytes(p, cur, cur + given);
+ if (err != GRPC_ERROR_NONE) return err;
GPR_ASSERT(given <= UINT32_MAX - p->strgot);
p->strgot += (uint32_t)given;
p->state = parse_string;
- return 1;
+ return GRPC_ERROR_NONE;
}
}
/* begin parsing a string - performs setup, calls parse_string */
-static int begin_parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end, uint8_t binary,
- grpc_chttp2_hpack_parser_string *str) {
+static grpc_error *begin_parse_string(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end,
+ uint8_t binary,
+ grpc_chttp2_hpack_parser_string *str) {
p->strgot = 0;
str->length = 0;
p->parsing.str = str;
@@ -1329,58 +1394,50 @@ static int begin_parse_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
}
/* parse the key string */
-static int parse_key_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_key_string(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end) {
return begin_parse_string(p, cur, end, NOT_BINARY, &p->key);
}
/* check if a key represents a binary header or not */
-typedef enum { BINARY_HEADER, PLAINTEXT_HEADER, ERROR_HEADER } is_binary_header;
-static is_binary_header is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
- return grpc_is_binary_header(p->key.str, p->key.length) ? BINARY_HEADER
- : PLAINTEXT_HEADER;
+static bool is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
+ return grpc_is_binary_header(p->key.str, p->key.length);
}
-static is_binary_header is_binary_indexed_header(grpc_chttp2_hpack_parser *p) {
+static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p,
+ bool *is) {
grpc_mdelem *elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
if (!elem) {
- if (grpc_http_trace) {
- gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
- }
- return ERROR_HEADER;
+ return grpc_error_set_int(
+ grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
+ GRPC_ERROR_INT_INDEX, p->index),
+ GRPC_ERROR_INT_SIZE, p->table.num_ents);
}
- return grpc_is_binary_header(
- (const char *)GPR_SLICE_START_PTR(elem->key->slice),
- GPR_SLICE_LENGTH(elem->key->slice))
- ? BINARY_HEADER
- : PLAINTEXT_HEADER;
+ *is =
+ grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(elem->key->slice),
+ GPR_SLICE_LENGTH(elem->key->slice));
+ return GRPC_ERROR_NONE;
}
/* parse the value string */
-static int parse_value_string(grpc_chttp2_hpack_parser *p, const uint8_t *cur,
- const uint8_t *end, is_binary_header type) {
- switch (type) {
- case BINARY_HEADER:
- return begin_parse_string(p, cur, end, B64_BYTE0, &p->value);
- case PLAINTEXT_HEADER:
- return begin_parse_string(p, cur, end, NOT_BINARY, &p->value);
- case ERROR_HEADER:
- return 0;
- }
- /* Add code to prevent return without value error */
- GPR_UNREACHABLE_CODE(return 0);
+static grpc_error *parse_value_string(grpc_chttp2_hpack_parser *p,
+ const uint8_t *cur, const uint8_t *end,
+ bool is_binary) {
+ return begin_parse_string(p, cur, end, is_binary ? B64_BYTE0 : NOT_BINARY,
+ &p->value);
}
-static int parse_value_string_with_indexed_key(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur,
- const uint8_t *end) {
- return parse_value_string(p, cur, end, is_binary_indexed_header(p));
+static grpc_error *parse_value_string_with_indexed_key(
+ grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) {
+ bool is_binary;
+ grpc_error *err = is_binary_indexed_header(p, &is_binary);
+ if (err != GRPC_ERROR_NONE) return err;
+ return parse_value_string(p, cur, end, is_binary);
}
-static int parse_value_string_with_literal_key(grpc_chttp2_hpack_parser *p,
- const uint8_t *cur,
- const uint8_t *end) {
+static grpc_error *parse_value_string_with_literal_key(
+ grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) {
return parse_value_string(p, cur, end, is_binary_literal_header(p));
}
@@ -1411,8 +1468,9 @@ void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser *p) {
gpr_free(p->value.str);
}
-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) {
/* TODO(ctiller): limit the distance of end from beg, and perform multiple
steps in the event of a large chunk of data to limit
stack space usage when no tail call optimization is
@@ -1420,7 +1478,7 @@ int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
return p->state(p, beg, end);
}
-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) {
@@ -1429,17 +1487,17 @@ grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
if (stream_parsing != NULL) {
stream_parsing->stats.incoming.header_bytes += GPR_SLICE_LENGTH(slice);
}
- if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice),
- GPR_SLICE_END_PTR(slice))) {
+ grpc_error *error = grpc_chttp2_hpack_parser_parse(
+ parser, GPR_SLICE_START_PTR(slice), GPR_SLICE_END_PTR(slice));
+ if (error != GRPC_ERROR_NONE) {
GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
- return GRPC_CHTTP2_CONNECTION_ERROR;
+ return error;
}
if (is_last) {
if (parser->is_boundary && parser->state != parse_begin) {
- gpr_log(GPR_ERROR,
- "end of header frame not aligned with a hpack record boundary");
GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
- return GRPC_CHTTP2_CONNECTION_ERROR;
+ return GRPC_ERROR_CREATE(
+ "end of header frame not aligned with a hpack record boundary");
}
/* need to check for null stream: this can occur if we receive an invalid
stream id on a header */
@@ -1462,5 +1520,5 @@ grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
parser->dynamic_table_update_allowed = 2;
}
GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
- return GRPC_CHTTP2_PARSE_OK;
+ return GRPC_ERROR_NONE;
}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.h b/src/core/ext/transport/chttp2/transport/hpack_parser.h
index 855d6c5d52..78eb38db5e 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.h
@@ -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);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.c b/src/core/ext/transport/chttp2/transport/hpack_table.c
index 4d64506de2..0684d49899 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.c
@@ -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(
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.h b/src/core/ext/transport/chttp2/transport/hpack_table.h
index 074fea36d8..45bd9255bf 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.h
@@ -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 {
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index cb5ed9fc25..ae35d58117 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -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);