diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 6930419233f..bdfaface168 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -1591,6 +1591,8 @@ Pod::Spec.new do |s| ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc', 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.h', + 'src/core/ext/transport/cronet/transport/cronet_status.cc', + 'src/core/ext/transport/cronet/transport/cronet_status.h', 'src/core/ext/transport/cronet/transport/cronet_transport.cc', 'src/core/ext/transport/cronet/transport/cronet_transport.h', 'third_party/objective_c/Cronet/bidirectional_stream_c.h' diff --git a/src/core/ext/transport/cronet/BUILD b/src/core/ext/transport/cronet/BUILD index c77bf19af1f..51865d3bc3a 100644 --- a/src/core/ext/transport/cronet/BUILD +++ b/src/core/ext/transport/cronet/BUILD @@ -34,6 +34,8 @@ grpc_cc_library( srcs = [ "client/secure/cronet_channel_create.cc", "transport/cronet_api_dummy.cc", + "transport/cronet_status.cc", + "transport/cronet_status.h", "transport/cronet_transport.cc", "transport/cronet_transport.h", ], diff --git a/src/core/ext/transport/cronet/transport/cronet_status.cc b/src/core/ext/transport/cronet/transport/cronet_status.cc new file mode 100644 index 00000000000..d88c15096d1 --- /dev/null +++ b/src/core/ext/transport/cronet/transport/cronet_status.cc @@ -0,0 +1,91 @@ +/* + * + * Copyright 2020 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/ext/transport/cronet/transport/cronet_status.h" + +const char* cronet_status_as_string(cronet_status_code status) { + switch (status) { + case CRONET_STATUS_SUCCESS: + return "CRONET_STATUS_SUCCESS."; + case CRONET_STATUS_ILLEGAL_ARGUMENT: + return "CRONET_STATUS_ILLEGAL_ARGUMENT."; + case CRONET_STATUS_ILLEGAL_ARGUMENT_STORAGE_PATH_MUST_EXIST: + return "CRONET_STATUS_ILLEGAL_ARGUMENT_STORAGE_PATH_MUST_EXIST."; + case CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_PIN: + return "CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_PIN."; + case CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HOSTNAME: + return "CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HOSTNAME."; + case CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HTTP_METHOD: + return "CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HTTP_METHOD."; + case CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HTTP_HEADER: + return "CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HTTP_HEADER."; + case CRONET_STATUS_ILLEGAL_STATE: + return "CRONET_STATUS_ILLEGAL_STATE."; + case CRONET_STATUS_ILLEGAL_STATE_STORAGE_PATH_IN_USE: + return "CRONET_STATUS_ILLEGAL_STATE_STORAGE_PATH_IN_USE."; + case CRONET_STATUS_ILLEGAL_STATE_CANNOT_SHUTDOWN_ENGINE_FROM_NETWORK_THREAD: + return "CRONET_STATUS_ILLEGAL_STATE_CANNOT_SHUTDOWN_ENGINE_FROM_NETWORK_" + "THREAD."; + case CRONET_STATUS_ILLEGAL_STATE_ENGINE_ALREADY_STARTED: + return "CRONET_STATUS_ILLEGAL_STATE_ENGINE_ALREADY_STARTED."; + case CRONET_STATUS_ILLEGAL_STATE_REQUEST_ALREADY_STARTED: + return "CRONET_STATUS_ILLEGAL_STATE_REQUEST_ALREADY_STARTED."; + case CRONET_STATUS_ILLEGAL_STATE_REQUEST_NOT_INITIALIZED: + return "CRONET_STATUS_ILLEGAL_STATE_REQUEST_NOT_INITIALIZED."; + case CRONET_STATUS_ILLEGAL_STATE_REQUEST_ALREADY_INITIALIZED: + return "CRONET_STATUS_ILLEGAL_STATE_REQUEST_ALREADY_INITIALIZED."; + case CRONET_STATUS_ILLEGAL_STATE_REQUEST_NOT_STARTED: + return "CRONET_STATUS_ILLEGAL_STATE_REQUEST_NOT_STARTED."; + case CRONET_STATUS_ILLEGAL_STATE_UNEXPECTED_REDIRECT: + return "CRONET_STATUS_ILLEGAL_STATE_UNEXPECTED_REDIRECT."; + case CRONET_STATUS_ILLEGAL_STATE_UNEXPECTED_READ: + return "CRONET_STATUS_ILLEGAL_STATE_UNEXPECTED_READ."; + case CRONET_STATUS_ILLEGAL_STATE_READ_FAILED: + return "CRONET_STATUS_ILLEGAL_STATE_READ_FAILED."; + case CRONET_STATUS_NULL_POINTER: + return "CRONET_STATUS_NULL_POINTER."; + case CRONET_STATUS_NULL_POINTER_HOSTNAME: + return "CRONET_STATUS_NULL_POINTER_HOSTNAME."; + case CRONET_STATUS_NULL_POINTER_SHA256_PINS: + return "CRONET_STATUS_NULL_POINTER_SHA256_PINS."; + case CRONET_STATUS_NULL_POINTER_EXPIRATION_DATE: + return "CRONET_STATUS_NULL_POINTER_EXPIRATION_DATE."; + case CRONET_STATUS_NULL_POINTER_ENGINE: + return "CRONET_STATUS_NULL_POINTER_ENGINE."; + case CRONET_STATUS_NULL_POINTER_URL: + return "CRONET_STATUS_NULL_POINTER_URL."; + case CRONET_STATUS_NULL_POINTER_CALLBACK: + return "CRONET_STATUS_NULL_POINTER_CALLBACK."; + case CRONET_STATUS_NULL_POINTER_EXECUTOR: + return "CRONET_STATUS_NULL_POINTER_EXECUTOR."; + case CRONET_STATUS_NULL_POINTER_METHOD: + return "CRONET_STATUS_NULL_POINTER_METHOD."; + case CRONET_STATUS_NULL_POINTER_HEADER_NAME: + return "CRONET_STATUS_NULL_POINTER_HEADER_NAME."; + case CRONET_STATUS_NULL_POINTER_HEADER_VALUE: + return "CRONET_STATUS_NULL_POINTER_HEADER_VALUE"; + case CRONET_STATUS_NULL_POINTER_PARAMS: + return "CRONET_STATUS_NULL_POINTER_PARAMS."; + case CRONET_STATUS_NULL_POINTER_REQUEST_FINISHED_INFO_LISTENER_EXECUTOR: + return "CRONET_STATUS_NULL_POINTER_REQUEST_FINISHED_INFO_LISTENER_" + "EXECUTOR."; + } + return "UNAVAILABLE."; +} diff --git a/src/core/ext/transport/cronet/transport/cronet_status.h b/src/core/ext/transport/cronet/transport/cronet_status.h new file mode 100644 index 00000000000..606dd6f9cdb --- /dev/null +++ b/src/core/ext/transport/cronet/transport/cronet_status.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2020 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_STATUS_H +#define GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_STATUS_H + +/* HTTP/2 error codes are mapped to the following cronet net error codes */ +enum cronet_status_code { + CRONET_STATUS_SUCCESS = 0, + CRONET_STATUS_ILLEGAL_ARGUMENT = -100, + CRONET_STATUS_ILLEGAL_ARGUMENT_STORAGE_PATH_MUST_EXIST = -101, + CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_PIN = -102, + CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HOSTNAME = -103, + CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HTTP_METHOD = -104, + CRONET_STATUS_ILLEGAL_ARGUMENT_INVALID_HTTP_HEADER = -105, + CRONET_STATUS_ILLEGAL_STATE = -200, + CRONET_STATUS_ILLEGAL_STATE_STORAGE_PATH_IN_USE = -201, + CRONET_STATUS_ILLEGAL_STATE_CANNOT_SHUTDOWN_ENGINE_FROM_NETWORK_THREAD = -202, + CRONET_STATUS_ILLEGAL_STATE_ENGINE_ALREADY_STARTED = -203, + CRONET_STATUS_ILLEGAL_STATE_REQUEST_ALREADY_STARTED = -204, + CRONET_STATUS_ILLEGAL_STATE_REQUEST_NOT_INITIALIZED = -205, + CRONET_STATUS_ILLEGAL_STATE_REQUEST_ALREADY_INITIALIZED = -206, + CRONET_STATUS_ILLEGAL_STATE_REQUEST_NOT_STARTED = -207, + CRONET_STATUS_ILLEGAL_STATE_UNEXPECTED_REDIRECT = -208, + CRONET_STATUS_ILLEGAL_STATE_UNEXPECTED_READ = -209, + CRONET_STATUS_ILLEGAL_STATE_READ_FAILED = -210, + CRONET_STATUS_NULL_POINTER = -300, + CRONET_STATUS_NULL_POINTER_HOSTNAME = -301, + CRONET_STATUS_NULL_POINTER_SHA256_PINS = -302, + CRONET_STATUS_NULL_POINTER_EXPIRATION_DATE = -303, + CRONET_STATUS_NULL_POINTER_ENGINE = -304, + CRONET_STATUS_NULL_POINTER_URL = -305, + CRONET_STATUS_NULL_POINTER_CALLBACK = -306, + CRONET_STATUS_NULL_POINTER_EXECUTOR = -307, + CRONET_STATUS_NULL_POINTER_METHOD = -308, + CRONET_STATUS_NULL_POINTER_HEADER_NAME = -309, + CRONET_STATUS_NULL_POINTER_HEADER_VALUE = -310, + CRONET_STATUS_NULL_POINTER_PARAMS = -311, + CRONET_STATUS_NULL_POINTER_REQUEST_FINISHED_INFO_LISTENER_EXECUTOR = -312, +}; + +const char* cronet_status_as_string(cronet_status_code status); + +#endif /* GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_STATUS_H */ diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 03b652fc746..07dfb42aa7f 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -31,6 +31,7 @@ #include "src/core/ext/transport/chttp2/transport/bin_decoder.h" #include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" +#include "src/core/ext/transport/cronet/transport/cronet_status.h" #include "src/core/ext/transport/cronet/transport/cronet_transport.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gpr/string.h" @@ -164,6 +165,7 @@ struct op_state { bool pending_recv_trailing_metadata = false; /* Cronet has not issued a callback of a bidirectional read */ bool pending_read_from_cronet = false; + cronet_status_code net_error = CRONET_STATUS_SUCCESS; grpc_error* cancel_error = GRPC_ERROR_NONE; /* data structure for storing data coming from server */ struct read_state rs; @@ -435,6 +437,7 @@ static void on_failed(bidirectional_stream* stream, int net_error) { gpr_mu_lock(&s->mu); bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_FAILED] = true; + s->state.net_error = static_cast(net_error); s->cbs = nullptr; if (s->header_array.headers) { gpr_free(s->header_array.headers); @@ -1302,7 +1305,9 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { if (stream_state->state_op_done[OP_CANCEL_ERROR]) { error = GRPC_ERROR_REF(stream_state->cancel_error); } else if (stream_state->state_callback_received[OP_FAILED]) { - error = make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable."); + const char* error_message = + cronet_status_as_string(stream_state->net_error); + error = make_error_with_desc(GRPC_STATUS_UNAVAILABLE, error_message); } else if (oas->s->state.rs.trailing_metadata_valid) { grpc_chttp2_incoming_metadata_buffer_publish( &oas->s->state.rs.trailing_metadata, @@ -1339,9 +1344,11 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { } } else if (stream_state->state_callback_received[OP_FAILED]) { if (stream_op->on_complete) { + const char* error_message = + cronet_status_as_string(stream_state->net_error); grpc_core::ExecCtx::Run( DEBUG_LOCATION, stream_op->on_complete, - make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable.")); + make_error_with_desc(GRPC_STATUS_UNAVAILABLE, error_message)); } } else { /* All actions in this stream_op are complete. Call the on_complete diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index 91767265cd8..262d5cc8fa1 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -77,6 +77,8 @@ grpc_cronet_extra_impl_files = [ 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc', 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.h', + 'src/core/ext/transport/cronet/transport/cronet_status.cc', + 'src/core/ext/transport/cronet/transport/cronet_status.h', 'src/core/ext/transport/cronet/transport/cronet_transport.cc', 'src/core/ext/transport/cronet/transport/cronet_transport.h', 'third_party/objective_c/Cronet/bidirectional_stream_c.h'