diff options
author | 2016-12-13 17:33:51 -0800 | |
---|---|---|
committer | 2017-01-06 14:52:21 -0800 | |
commit | dc21a4efb281459b4d3d046cc17ea89e5b56f878 (patch) | |
tree | adc378617d414bc154c19bbe9e94a00fce1bf92c /src/core | |
parent | 732351f8267e51711abd3a390d940c8177871c97 (diff) |
Error handling cleanup
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/ext/transport/chttp2/transport/chttp2_transport.c | 96 | ||||
-rw-r--r-- | src/core/ext/transport/chttp2/transport/frame_rst_stream.c | 13 | ||||
-rw-r--r-- | src/core/ext/transport/chttp2/transport/frame_settings.c | 14 | ||||
-rw-r--r-- | src/core/ext/transport/chttp2/transport/hpack_parser.c | 2 | ||||
-rw-r--r-- | src/core/ext/transport/chttp2/transport/internal.h | 3 | ||||
-rw-r--r-- | src/core/ext/transport/chttp2/transport/parsing.c | 8 | ||||
-rw-r--r-- | src/core/ext/transport/chttp2/transport/writing.c | 6 | ||||
-rw-r--r-- | src/core/lib/surface/call.c | 8 | ||||
-rw-r--r-- | src/core/lib/surface/server.c | 10 | ||||
-rw-r--r-- | src/core/lib/transport/error_utils.c | 66 | ||||
-rw-r--r-- | src/core/lib/transport/error_utils.h | 10 | ||||
-rw-r--r-- | src/core/lib/transport/http2_errors.h | 30 | ||||
-rw-r--r-- | src/core/lib/transport/status_conversion.c | 36 | ||||
-rw-r--r-- | src/core/lib/transport/status_conversion.h | 11 | ||||
-rw-r--r-- | src/core/lib/transport/transport.h | 7 | ||||
-rw-r--r-- | src/core/lib/transport/transport_op_string.c | 11 |
16 files changed, 156 insertions, 175 deletions
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 3711e0cba1..6a2a54a660 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -1252,11 +1252,16 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, } static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_error_code error, grpc_slice data) { + grpc_error *error) { t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; - grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)error, data, - &t->qbuf); + grpc_http2_error_code http_error; + const char *msg; + grpc_error_get_status(error, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL, &msg, + &http_error); + grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error, + grpc_slice_from_copied_string(msg), &t->qbuf); grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent"); + GRPC_ERROR_UNREF(error); } static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, @@ -1272,10 +1277,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, op->on_connectivity_state_change); } - if (op->send_goaway) { - send_goaway(exec_ctx, t, - grpc_chttp2_grpc_status_to_http2_error(op->goaway_status), - grpc_slice_ref_internal(*op->goaway_message)); + if (op->goaway_error) { + send_goaway(exec_ctx, t, op->goaway_error); } if (op->set_accept_stream) { @@ -1428,33 +1431,6 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, maybe_start_some_streams(exec_ctx, t); } -static void status_codes_from_error(grpc_error *error, gpr_timespec deadline, - grpc_chttp2_error_code *http2_error, - grpc_status_code *grpc_status) { - intptr_t ip_http; - intptr_t ip_grpc; - bool have_http = - grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &ip_http); - bool have_grpc = - grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &ip_grpc); - if (have_http) { - *http2_error = (grpc_chttp2_error_code)ip_http; - } else if (have_grpc) { - *http2_error = - grpc_chttp2_grpc_status_to_http2_error((grpc_status_code)ip_grpc); - } else { - *http2_error = GRPC_CHTTP2_INTERNAL_ERROR; - } - if (have_grpc) { - *grpc_status = (grpc_status_code)ip_grpc; - } else if (have_http) { - *grpc_status = grpc_chttp2_http2_error_to_grpc_status( - (grpc_chttp2_error_code)ip_http, deadline); - } else { - *grpc_status = GRPC_STATUS_INTERNAL; - } -} - void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *due_to_error) { @@ -1465,28 +1441,14 @@ void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, } if (!s->read_closed || !s->write_closed) { - grpc_status_code grpc_status; - grpc_chttp2_error_code http_error; - status_codes_from_error(due_to_error, s->deadline, &http_error, - &grpc_status); - if (s->id != 0) { + grpc_http2_error_code http_error; + grpc_error_get_status(due_to_error, s->deadline, NULL, NULL, &http_error); grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error, &s->stats.outgoing)); grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream"); } - - const char *msg = - grpc_error_get_str(due_to_error, GRPC_ERROR_STR_GRPC_MESSAGE); - bool free_msg = false; - if (msg == NULL) { - free_msg = true; - msg = grpc_error_string(due_to_error); - } - grpc_slice msg_slice = grpc_slice_from_copied_string(msg); - grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice); - if (free_msg) grpc_error_free_string(msg); } if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) { s->seen_error = true; @@ -1496,8 +1458,11 @@ void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, } void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *s, grpc_status_code status, - grpc_slice *slice) { + grpc_chttp2_stream *s, grpc_error *error) { + grpc_status_code status; + const char *msg; + grpc_error_get_status(error, s->deadline, &status, &msg, NULL); + if (status != GRPC_STATUS_OK) { s->seen_error = true; } @@ -1515,18 +1480,17 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, &s->metadata_buffer[1], grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_slice_from_copied_string(status_string))); - if (slice) { + if (msg != NULL) { grpc_chttp2_incoming_metadata_buffer_add( &s->metadata_buffer[1], grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, - grpc_slice_ref_internal(*slice))); + grpc_slice_from_copied_string(msg))); } s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); } - if (slice) { - grpc_slice_unref_internal(exec_ctx, *slice); - } + + GRPC_ERROR_UNREF(error); } static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) { @@ -1596,6 +1560,7 @@ void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx, return; } if (close_reads && !s->read_closed) { + grpc_chttp2_fake_status(exec_ctx, t, s, GRPC_ERROR_REF(error)); s->read_closed_error = GRPC_ERROR_REF(error); s->read_closed = true; for (int i = 0; i < 2; i++) { @@ -1636,7 +1601,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, uint32_t len = 0; grpc_status_code grpc_status; const char *msg; - grpc_error_get_status(error, &grpc_status, &msg); + grpc_error_get_status(error, s->deadline, &grpc_status, &msg, NULL); GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100); @@ -1719,14 +1684,9 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_slice_buffer_add(&t->qbuf, grpc_slice_from_copied_string(msg)); } grpc_slice_buffer_add( - &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR, + &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); - grpc_slice msg_slice = - msg == NULL ? grpc_empty_slice() : grpc_slice_from_copied_string(msg); - grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, - msg == NULL ? NULL : &msg_slice); - grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error); grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api"); } @@ -2173,8 +2133,10 @@ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory", t->peer_string); } - send_goaway(exec_ctx, t, GRPC_CHTTP2_ENHANCE_YOUR_CALM, - grpc_slice_from_static_string("Buffers full")); + send_goaway(exec_ctx, t, + grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"), + GRPC_ERROR_INT_HTTP2_ERROR, + GRPC_HTTP2_ENHANCE_YOUR_CALM)); } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR @@ -2203,7 +2165,7 @@ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"), GRPC_ERROR_INT_HTTP2_ERROR, - GRPC_CHTTP2_ENHANCE_YOUR_CALM)); + GRPC_HTTP2_ENHANCE_YOUR_CALM)); if (n > 1) { /* Since we cancel one stream per destructive reclamation, if there are more streams left, we can immediately post a new 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 b4c5ed769b..583ac9e98e 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c @@ -39,8 +39,7 @@ #include <grpc/support/string_util.h> #include "src/core/ext/transport/chttp2/transport/frame.h" -#include "src/core/ext/transport/chttp2/transport/http2_errors.h" -#include "src/core/ext/transport/chttp2/transport/status_conversion.h" +#include "src/core/lib/transport/http2_errors.h" grpc_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code, grpc_transport_one_way_stats *stats) { @@ -109,17 +108,9 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx, (((uint32_t)p->reason_bytes[2]) << 8) | (((uint32_t)p->reason_bytes[3])); grpc_error *error = GRPC_ERROR_NONE; - if (reason != GRPC_CHTTP2_NO_ERROR) { + if (reason != GRPC_HTTP2_NO_ERROR) { error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"), GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason); - grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status( - (grpc_chttp2_error_code)reason, s->deadline); - char *status_details; - gpr_asprintf(&status_details, "Received RST_STREAM with error code %d", - reason); - grpc_slice slice_details = grpc_slice_from_copied_string(status_details); - gpr_free(status_details); - grpc_chttp2_fake_status(exec_ctx, t, s, status_code, &slice_details); } grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error); } diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c index bfed41fadb..be9b663ac1 100644 --- a/src/core/ext/transport/chttp2/transport/frame_settings.c +++ b/src/core/ext/transport/chttp2/transport/frame_settings.c @@ -52,21 +52,21 @@ const grpc_chttp2_setting_parameters grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = { {NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, - GRPC_CHTTP2_PROTOCOL_ERROR}, + GRPC_HTTP2_PROTOCOL_ERROR}, {"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff, - GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, + GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, - GRPC_CHTTP2_PROTOCOL_ERROR}, + GRPC_HTTP2_PROTOCOL_ERROR}, {"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu, - GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, + GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, - GRPC_CHTTP2_FLOW_CONTROL_ERROR}, + GRPC_HTTP2_FLOW_CONTROL_ERROR}, {"MAX_FRAME_SIZE", 16384, 16384, 16777215, - GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, + GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR}, {"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0, MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE, - GRPC_CHTTP2_PROTOCOL_ERROR}, + GRPC_HTTP2_PROTOCOL_ERROR}, }; static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) { diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c index 6d6d0de742..40f5120308 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.c +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c @@ -1644,7 +1644,7 @@ static void force_client_rst_stream(grpc_exec_ctx *exec_ctx, void *sp, grpc_chttp2_transport *t = s->t; if (!s->write_closed) { grpc_slice_buffer_add( - &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR, + &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); grpc_chttp2_initiate_write(exec_ctx, t, false, "force_rst_stream"); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, GRPC_ERROR_NONE); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index a52acbacdb..43fd10f0fd 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -612,8 +612,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase, uint32_t stream_id, int64_t val1, int64_t val2); void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *stream, - grpc_status_code status, grpc_slice *details); + grpc_chttp2_stream *stream, grpc_error *error); void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, int close_reads, diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index c5a99e5424..11e4655f11 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -39,11 +39,11 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> -#include "src/core/ext/transport/chttp2/transport/http2_errors.h" -#include "src/core/ext/transport/chttp2/transport/status_conversion.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/transport/http2_errors.h" #include "src/core/lib/transport/static_metadata.h" +#include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/timeout_encoding.h" static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx, @@ -433,7 +433,7 @@ error_handler: } grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id, - GRPC_CHTTP2_PROTOCOL_ERROR, + GRPC_HTTP2_PROTOCOL_ERROR, &s->stats.outgoing)); return init_skip_frame_parser(exec_ctx, t, 0); } else { @@ -758,7 +758,7 @@ static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx, s->forced_close_error = err; grpc_slice_buffer_add( &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id, - GRPC_CHTTP2_PROTOCOL_ERROR, + GRPC_HTTP2_PROTOCOL_ERROR, &s->stats.outgoing)); } else { GRPC_ERROR_UNREF(err); diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index ef2010af7b..182aff1e3f 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -37,9 +37,9 @@ #include <grpc/support/log.h> -#include "src/core/ext/transport/chttp2/transport/http2_errors.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/http2_errors.h" static void add_to_write_list(grpc_chttp2_write_cb **list, grpc_chttp2_write_cb *cb) { @@ -164,7 +164,7 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, s->sent_trailing_metadata = true; if (!t->is_client && !s->read_closed) { grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_rst_stream_create( - s->id, GRPC_CHTTP2_NO_ERROR, + s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); } } @@ -197,7 +197,7 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, if (!t->is_client && !s->read_closed) { grpc_slice_buffer_add( &t->outbuf, grpc_chttp2_rst_stream_create( - s->id, GRPC_CHTTP2_NO_ERROR, &s->stats.outgoing)); + s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); } now_writing = true; } diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 4abf981997..17fda435aa 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -336,10 +336,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, args->server_transport_data, path, call->start_time, send_deadline, CALL_STACK_FROM_CALL(call)); if (error != GRPC_ERROR_NONE) { - grpc_status_code status; - const char *error_str; - grpc_error_get_status(error, &status, &error_str); - cancel_with_status(exec_ctx, call, status, error_str); + cancel_with_error(exec_ctx, call, GRPC_ERROR_REF(error)); } if (args->cq != NULL) { GPR_ASSERT( @@ -612,7 +609,8 @@ static void get_final_status(grpc_call *call, grpc_status_code code; const char *msg = NULL; - grpc_error_get_status(call->status[i].error, &code, &msg); + grpc_error_get_status(call->status[i].error, call->send_deadline, &code, + &msg, NULL); set_value(code, set_value_user_data); if (details != NULL) { *details = grpc_slice_from_copied_string(msg); diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 7af951f2a0..b5f905bf04 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -280,18 +280,20 @@ static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg, } static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, - int send_goaway, grpc_error *send_disconnect) { + bool send_goaway, grpc_error *send_disconnect) { struct shutdown_cleanup_args *sc = gpr_malloc(sizeof(*sc)); grpc_closure_init(&sc->closure, shutdown_cleanup, sc, grpc_schedule_on_exec_ctx); grpc_transport_op *op = grpc_make_transport_op(&sc->closure); grpc_channel_element *elem; - op->send_goaway = send_goaway; + op->goaway_error = + send_goaway + ? grpc_error_set_int(GRPC_ERROR_CREATE("Server shutdown"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK) + : GRPC_ERROR_NONE; op->set_accept_stream = true; sc->slice = grpc_slice_from_copied_string("Server shutdown"); - op->goaway_message = &sc->slice; - op->goaway_status = GRPC_STATUS_OK; op->disconnect_with_error = send_disconnect; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); diff --git a/src/core/lib/transport/error_utils.c b/src/core/lib/transport/error_utils.c index 6403cf80d8..da77828d9c 100644 --- a/src/core/lib/transport/error_utils.c +++ b/src/core/lib/transport/error_utils.c @@ -32,12 +32,14 @@ */ #include "src/core/lib/transport/error_utils.h" + #include "src/core/lib/iomgr/error_internal.h" +#include "src/core/lib/transport/status_conversion.h" -static grpc_error *recursively_find_error_with_status(grpc_error *error, - intptr_t *status) { +static grpc_error *recursively_find_error_with_field(grpc_error *error, + grpc_error_ints which) { // If the error itself has a status code, return it. - if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, status)) { + if (grpc_error_get_int(error, which, NULL)) { return error; } if (grpc_error_is_special(error)) return NULL; @@ -46,32 +48,64 @@ static grpc_error *recursively_find_error_with_status(grpc_error *error, while (true) { grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++); if (child_error == NULL) break; - grpc_error *result = - recursively_find_error_with_status(child_error, status); + grpc_error *result = recursively_find_error_with_field(child_error, which); if (result != NULL) return result; } return NULL; } -void grpc_error_get_status(grpc_error *error, grpc_status_code *code, - const char **msg) { - // Populate code. +void grpc_error_get_status(grpc_error *error, gpr_timespec deadline, + grpc_status_code *code, const char **msg, + grpc_http2_error_code *http_error) { // Start with the parent error and recurse through the tree of children // until we find the first one that has a status code. - intptr_t status = GRPC_STATUS_UNKNOWN; // Default in case we don't find one. - grpc_error *found_error = recursively_find_error_with_status(error, &status); - *code = (grpc_status_code)status; - // Now populate msg. + grpc_error *found_error = + recursively_find_error_with_field(error, GRPC_ERROR_INT_GRPC_STATUS); + if (found_error == NULL) { + /// If no grpc-status exists, retry through the tree to find a http2 error + /// code + found_error = + recursively_find_error_with_field(error, GRPC_ERROR_INT_HTTP2_ERROR); + } + // If we found an error with a status code above, use that; otherwise, // fall back to using the parent error. if (found_error == NULL) found_error = error; + + grpc_status_code status = GRPC_STATUS_UNKNOWN; + intptr_t integer; + if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) { + status = (grpc_status_code)integer; + } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, + &integer)) { + status = grpc_http2_error_to_grpc_status((grpc_http2_error_code)integer, + deadline); + } + if (code != NULL) *code = status; + + if (http_error != NULL) { + if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, &integer)) { + *http_error = (grpc_http2_error_code)integer; + } else if (grpc_error_get_int(found_error, GRPC_ERROR_INT_GRPC_STATUS, + &integer)) { + *http_error = grpc_status_to_http2_error((grpc_status_code)integer); + } else { + *http_error = found_error == GRPC_ERROR_NONE ? GRPC_HTTP2_NO_ERROR + : GRPC_HTTP2_INTERNAL_ERROR; + } + } + // If the error has a status message, use it. Otherwise, fall back to // the error description. - *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE); - if (*msg == NULL && status != GRPC_STATUS_OK) { - *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION); - if (*msg == NULL) *msg = "unknown error"; // Just in case. + if (msg != NULL) { + *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE); + if (*msg == NULL && error != GRPC_ERROR_NONE) { + *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION); + if (*msg == NULL) *msg = "unknown error"; // Just in case. + } } + + if (found_error == NULL) found_error = error; } bool grpc_error_has_clear_grpc_status(grpc_error *error) { diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h index 541dba852f..f72c3dca0e 100644 --- a/src/core/lib/transport/error_utils.h +++ b/src/core/lib/transport/error_utils.h @@ -35,12 +35,18 @@ #define GRPC_ERROR_UTILS_H #include "src/core/lib/iomgr/error.h" +#include "src/core/lib/transport/http2_errors.h" /// A utility function to get the status code and message to be returned /// to the application. If not set in the top-level message, looks /// through child errors until it finds the first one with these attributes. -void grpc_error_get_status(grpc_error *error, grpc_status_code *code, - const char **msg); +/// All attributes are pulled from the same child error. If any of the +/// attributes (code, msg, http_status) are unneeded, they can be passed as +/// NULL. +void grpc_error_get_status(grpc_error *error, gpr_timespec deadline, + grpc_status_code *code, const char **msg, + grpc_http2_error_code *http_status); + /// A utility function to check whether there is a clear status code that /// doesn't need to be guessed in \a error. This means that \a error or some /// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or diff --git a/src/core/lib/transport/http2_errors.h b/src/core/lib/transport/http2_errors.h index deab2b7e3e..bf24438dde 100644 --- a/src/core/lib/transport/http2_errors.h +++ b/src/core/lib/transport/http2_errors.h @@ -36,21 +36,21 @@ /* error codes for RST_STREAM from http2 draft 14 section 7 */ typedef enum { - GRPC_CHTTP2_NO_ERROR = 0x0, - GRPC_CHTTP2_PROTOCOL_ERROR = 0x1, - GRPC_CHTTP2_INTERNAL_ERROR = 0x2, - GRPC_CHTTP2_FLOW_CONTROL_ERROR = 0x3, - GRPC_CHTTP2_SETTINGS_TIMEOUT = 0x4, - GRPC_CHTTP2_STREAM_CLOSED = 0x5, - GRPC_CHTTP2_FRAME_SIZE_ERROR = 0x6, - GRPC_CHTTP2_REFUSED_STREAM = 0x7, - GRPC_CHTTP2_CANCEL = 0x8, - GRPC_CHTTP2_COMPRESSION_ERROR = 0x9, - GRPC_CHTTP2_CONNECT_ERROR = 0xa, - GRPC_CHTTP2_ENHANCE_YOUR_CALM = 0xb, - GRPC_CHTTP2_INADEQUATE_SECURITY = 0xc, + GRPC_HTTP2_NO_ERROR = 0x0, + GRPC_HTTP2_PROTOCOL_ERROR = 0x1, + GRPC_HTTP2_INTERNAL_ERROR = 0x2, + GRPC_HTTP2_FLOW_CONTROL_ERROR = 0x3, + GRPC_HTTP2_SETTINGS_TIMEOUT = 0x4, + GRPC_HTTP2_STREAM_CLOSED = 0x5, + GRPC_HTTP2_FRAME_SIZE_ERROR = 0x6, + GRPC_HTTP2_REFUSED_STREAM = 0x7, + GRPC_HTTP2_CANCEL = 0x8, + GRPC_HTTP2_COMPRESSION_ERROR = 0x9, + GRPC_HTTP2_CONNECT_ERROR = 0xa, + GRPC_HTTP2_ENHANCE_YOUR_CALM = 0xb, + GRPC_HTTP2_INADEQUATE_SECURITY = 0xc, /* force use of a default clause */ - GRPC_CHTTP2__ERROR_DO_NOT_USE = -1 -} grpc_chttp2_error_code; + GRPC_HTTP2__ERROR_DO_NOT_USE = -1 +} grpc_http2_error_code; #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_ERRORS_H */ diff --git a/src/core/lib/transport/status_conversion.c b/src/core/lib/transport/status_conversion.c index eb1d53c8d1..af0ac89db7 100644 --- a/src/core/lib/transport/status_conversion.c +++ b/src/core/lib/transport/status_conversion.c @@ -33,49 +33,49 @@ #include "src/core/lib/transport/status_conversion.h" -int grpc_chttp2_grpc_status_to_http2_error(grpc_status_code status) { +int grpc_status_to_http2_error(grpc_status_code status) { switch (status) { case GRPC_STATUS_OK: - return GRPC_CHTTP2_NO_ERROR; + return GRPC_HTTP2_NO_ERROR; case GRPC_STATUS_CANCELLED: - return GRPC_CHTTP2_CANCEL; + return GRPC_HTTP2_CANCEL; case GRPC_STATUS_DEADLINE_EXCEEDED: - return GRPC_CHTTP2_CANCEL; + return GRPC_HTTP2_CANCEL; case GRPC_STATUS_RESOURCE_EXHAUSTED: - return GRPC_CHTTP2_ENHANCE_YOUR_CALM; + return GRPC_HTTP2_ENHANCE_YOUR_CALM; case GRPC_STATUS_PERMISSION_DENIED: - return GRPC_CHTTP2_INADEQUATE_SECURITY; + return GRPC_HTTP2_INADEQUATE_SECURITY; case GRPC_STATUS_UNAVAILABLE: - return GRPC_CHTTP2_REFUSED_STREAM; + return GRPC_HTTP2_REFUSED_STREAM; default: - return GRPC_CHTTP2_INTERNAL_ERROR; + return GRPC_HTTP2_INTERNAL_ERROR; } } -grpc_status_code grpc_chttp2_http2_error_to_grpc_status( - grpc_chttp2_error_code error, gpr_timespec deadline) { +grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error, + gpr_timespec deadline) { switch (error) { - case GRPC_CHTTP2_NO_ERROR: + case GRPC_HTTP2_NO_ERROR: /* should never be received */ return GRPC_STATUS_INTERNAL; - case GRPC_CHTTP2_CANCEL: + case GRPC_HTTP2_CANCEL: /* http2 cancel translates to STATUS_CANCELLED iff deadline hasn't been * exceeded */ return gpr_time_cmp(gpr_now(deadline.clock_type), deadline) >= 0 ? GRPC_STATUS_DEADLINE_EXCEEDED : GRPC_STATUS_CANCELLED; - case GRPC_CHTTP2_ENHANCE_YOUR_CALM: + case GRPC_HTTP2_ENHANCE_YOUR_CALM: return GRPC_STATUS_RESOURCE_EXHAUSTED; - case GRPC_CHTTP2_INADEQUATE_SECURITY: + case GRPC_HTTP2_INADEQUATE_SECURITY: return GRPC_STATUS_PERMISSION_DENIED; - case GRPC_CHTTP2_REFUSED_STREAM: + case GRPC_HTTP2_REFUSED_STREAM: return GRPC_STATUS_UNAVAILABLE; default: return GRPC_STATUS_INTERNAL; } } -grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status) { +grpc_status_code grpc_http2_status_to_grpc_status(int status) { switch (status) { /* these HTTP2 status codes are called out explicitly in status.proto */ case 200: @@ -110,6 +110,4 @@ grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status) { } } -int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status) { - return 200; -} +int grpc_status_to_http2_status(grpc_status_code status) { return 200; } diff --git a/src/core/lib/transport/status_conversion.h b/src/core/lib/transport/status_conversion.h index 592411529d..3885ac90a5 100644 --- a/src/core/lib/transport/status_conversion.h +++ b/src/core/lib/transport/status_conversion.h @@ -38,13 +38,12 @@ #include "src/core/lib/transport/http2_errors.h" /* Conversion of grpc status codes to http2 error codes (for RST_STREAM) */ -grpc_chttp2_error_code grpc_chttp2_grpc_status_to_http2_error( - grpc_status_code status); -grpc_status_code grpc_chttp2_http2_error_to_grpc_status( - grpc_chttp2_error_code error, gpr_timespec deadline); +grpc_http2_error_code grpc_status_to_http2_error(grpc_status_code status); +grpc_status_code grpc_http2_error_to_grpc_status(grpc_http2_error_code error, + gpr_timespec deadline); /* Conversion of HTTP status codes (:status) to grpc status codes */ -grpc_status_code grpc_chttp2_http2_status_to_grpc_status(int status); -int grpc_chttp2_grpc_status_to_http2_status(grpc_status_code status); +grpc_status_code grpc_http2_status_to_grpc_status(int status); +int grpc_status_to_http2_status(grpc_status_code status); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_STATUS_CONVERSION_H */ diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 2dbb842a53..9a0abe1ca4 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -181,13 +181,8 @@ typedef struct grpc_transport_op { grpc_connectivity_state *connectivity_state; /** should the transport be disconnected */ grpc_error *disconnect_with_error; - /** should we send a goaway? - after a goaway is sent, once there are no more active calls on - the transport, the transport should disconnect */ - bool send_goaway; /** what should the goaway contain? */ - grpc_status_code goaway_status; - grpc_slice *goaway_message; + grpc_error *goaway_error; /** set the callback for accepting new streams; this is a permanent callback, unlike the other one-shot closures. If true, the callback is set to set_accept_stream_fn, with its diff --git a/src/core/lib/transport/transport_op_string.c b/src/core/lib/transport/transport_op_string.c index 33bd35bd45..8810a6bbda 100644 --- a/src/core/lib/transport/transport_op_string.c +++ b/src/core/lib/transport/transport_op_string.c @@ -163,15 +163,12 @@ char *grpc_transport_op_string(grpc_transport_op *op) { grpc_error_free_string(err); } - if (op->send_goaway) { + if (op->goaway_error) { if (!first) gpr_strvec_add(&b, gpr_strdup(" ")); first = false; - char *msg = op->goaway_message == NULL - ? "null" - : grpc_dump_slice(*op->goaway_message, - GPR_DUMP_ASCII | GPR_DUMP_HEX); - gpr_asprintf(&tmp, "SEND_GOAWAY:status=%d:msg=%s", op->goaway_status, msg); - if (op->goaway_message != NULL) gpr_free(msg); + const char *msg = grpc_error_string(op->goaway_error); + gpr_asprintf(&tmp, "SEND_GOAWAY:%s", msg); + grpc_error_free_string(msg); gpr_strvec_add(&b, tmp); } |