aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2016-12-13 17:33:51 -0800
committerGravatar Craig Tiller <ctiller@google.com>2017-01-06 14:52:21 -0800
commitdc21a4efb281459b4d3d046cc17ea89e5b56f878 (patch)
treeadc378617d414bc154c19bbe9e94a00fce1bf92c /src/core
parent732351f8267e51711abd3a390d940c8177871c97 (diff)
Error handling cleanup
Diffstat (limited to 'src/core')
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c96
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_rst_stream.c13
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_settings.c14
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_parser.c2
-rw-r--r--src/core/ext/transport/chttp2/transport/internal.h3
-rw-r--r--src/core/ext/transport/chttp2/transport/parsing.c8
-rw-r--r--src/core/ext/transport/chttp2/transport/writing.c6
-rw-r--r--src/core/lib/surface/call.c8
-rw-r--r--src/core/lib/surface/server.c10
-rw-r--r--src/core/lib/transport/error_utils.c66
-rw-r--r--src/core/lib/transport/error_utils.h10
-rw-r--r--src/core/lib/transport/http2_errors.h30
-rw-r--r--src/core/lib/transport/status_conversion.c36
-rw-r--r--src/core/lib/transport/status_conversion.h11
-rw-r--r--src/core/lib/transport/transport.h7
-rw-r--r--src/core/lib/transport/transport_op_string.c11
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);
}