grpc 1.1.2 → 1.2.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +1257 -404
- data/etc/roots.pem +189 -102
- data/include/grpc/census.h +7 -7
- data/include/grpc/compression.h +4 -4
- data/include/grpc/grpc.h +13 -7
- data/include/grpc/impl/codegen/atm_gcc_atomic.h +26 -9
- data/include/grpc/impl/codegen/grpc_types.h +39 -30
- data/include/grpc/impl/codegen/slice.h +24 -6
- data/include/grpc/impl/codegen/sync.h +8 -0
- data/include/grpc/load_reporting.h +63 -0
- data/include/grpc/slice.h +37 -1
- data/include/grpc/slice_buffer.h +7 -0
- data/include/grpc/support/alloc.h +3 -0
- data/include/grpc/support/useful.h +3 -0
- data/src/core/ext/census/gen/census.pb.h +1 -1
- data/src/core/ext/census/gen/trace_context.pb.c +9 -36
- data/src/core/ext/census/gen/trace_context.pb.h +20 -26
- data/src/core/ext/census/grpc_filter.c +3 -5
- data/src/core/ext/census/trace_context.c +1 -1
- data/src/core/ext/census/trace_context.h +3 -0
- data/src/core/ext/census/trace_label.h +61 -0
- data/src/core/ext/census/trace_propagation.h +63 -0
- data/src/core/ext/census/trace_status.h +45 -0
- data/src/core/ext/census/trace_string.h +50 -0
- data/src/core/ext/census/tracing.c +31 -11
- data/src/core/ext/census/tracing.h +124 -0
- data/src/core/ext/client_channel/client_channel.c +456 -368
- data/src/core/ext/client_channel/client_channel.h +4 -0
- data/src/core/ext/client_channel/client_channel_plugin.c +6 -1
- data/src/core/ext/client_channel/connector.c +3 -3
- data/src/core/ext/client_channel/connector.h +4 -3
- data/src/core/ext/client_channel/http_connect_handshaker.c +62 -72
- data/src/core/ext/client_channel/http_connect_handshaker.h +7 -10
- data/src/core/ext/client_channel/http_proxy.c +125 -0
- data/src/core/ext/client_channel/http_proxy.h +39 -0
- data/src/core/ext/client_channel/lb_policy.c +56 -35
- data/src/core/ext/client_channel/lb_policy.h +46 -39
- data/src/core/ext/client_channel/lb_policy_factory.h +1 -0
- data/src/core/ext/client_channel/parse_address.c +32 -6
- data/src/core/ext/client_channel/proxy_mapper.c +63 -0
- data/src/core/ext/client_channel/proxy_mapper.h +89 -0
- data/src/core/ext/client_channel/proxy_mapper_registry.c +133 -0
- data/src/core/ext/client_channel/proxy_mapper_registry.h +59 -0
- data/src/core/ext/client_channel/resolver.c +16 -9
- data/src/core/ext/client_channel/resolver.h +23 -12
- data/src/core/ext/client_channel/resolver_factory.h +1 -0
- data/src/core/ext/client_channel/resolver_registry.c +15 -11
- data/src/core/ext/client_channel/resolver_registry.h +5 -3
- data/src/core/ext/client_channel/subchannel.c +44 -27
- data/src/core/ext/client_channel/subchannel.h +6 -2
- data/src/core/ext/client_channel/uri_parser.c +26 -14
- data/src/core/ext/client_channel/uri_parser.h +3 -1
- data/src/core/ext/lb_policy/grpclb/grpclb.c +220 -209
- data/src/core/ext/lb_policy/grpclb/grpclb_channel.h +56 -0
- data/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c +107 -0
- data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +3 -6
- data/src/core/ext/lb_policy/pick_first/pick_first.c +71 -116
- data/src/core/ext/lb_policy/round_robin/round_robin.c +52 -67
- data/src/core/ext/load_reporting/load_reporting.c +20 -0
- data/src/core/ext/load_reporting/load_reporting.h +1 -16
- data/src/core/ext/load_reporting/load_reporting_filter.c +28 -54
- data/src/core/ext/resolver/dns/native/dns_resolver.c +31 -45
- data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +20 -29
- data/src/core/ext/transport/chttp2/client/chttp2_connector.c +11 -8
- data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +11 -2
- data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +143 -46
- data/src/core/ext/transport/chttp2/server/chttp2_server.c +12 -50
- data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +1 -1
- data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +1 -1
- data/src/core/ext/transport/chttp2/transport/bin_decoder.c +7 -7
- data/src/core/ext/transport/chttp2/transport/bin_encoder.c +1 -2
- data/src/core/ext/transport/chttp2/transport/bin_encoder.h +1 -2
- data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +0 -3
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +606 -374
- data/src/core/ext/transport/chttp2/transport/frame_ping.c +17 -5
- data/src/core/ext/transport/chttp2/transport/frame_ping.h +2 -2
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +9 -13
- data/src/core/ext/transport/chttp2/transport/frame_settings.c +12 -11
- data/src/core/ext/transport/chttp2/transport/frame_settings.h +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_window_update.c +5 -6
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +100 -53
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +2 -2
- data/src/core/ext/transport/chttp2/transport/hpack_parser.c +126 -70
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +13 -7
- data/src/core/ext/transport/chttp2/transport/hpack_table.c +22 -19
- data/src/core/ext/transport/chttp2/transport/hpack_table.h +6 -6
- data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +23 -11
- data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +6 -2
- data/src/core/ext/transport/chttp2/transport/internal.h +169 -42
- data/src/core/ext/transport/chttp2/transport/parsing.c +98 -41
- data/src/core/ext/transport/chttp2/transport/stream_lists.c +29 -14
- data/src/core/ext/transport/chttp2/transport/writing.c +137 -15
- data/src/core/lib/channel/channel_stack.c +14 -44
- data/src/core/lib/channel/channel_stack.h +10 -17
- data/src/core/lib/channel/channel_stack_builder.c +2 -3
- data/src/core/lib/channel/compress_filter.c +54 -46
- data/src/core/lib/channel/connected_channel.c +4 -4
- data/src/core/lib/channel/connected_channel.h +5 -0
- data/src/core/lib/channel/context.h +3 -0
- data/src/core/lib/channel/deadline_filter.c +61 -61
- data/src/core/lib/channel/deadline_filter.h +8 -5
- data/src/core/lib/channel/handshaker.c +47 -7
- data/src/core/lib/channel/handshaker.h +21 -3
- data/src/core/lib/channel/http_client_filter.c +149 -99
- data/src/core/lib/channel/http_server_filter.c +163 -147
- data/src/core/lib/channel/message_size_filter.c +15 -10
- data/src/core/lib/compression/algorithm_metadata.h +4 -4
- data/src/core/lib/compression/compression.c +17 -23
- data/src/core/lib/http/httpcli.c +3 -2
- data/src/core/lib/http/httpcli.h +2 -1
- data/src/core/lib/http/httpcli_security_connector.c +2 -3
- data/src/core/lib/http/parser.c +2 -2
- data/src/core/lib/iomgr/closure.c +6 -3
- data/src/core/lib/iomgr/closure.h +4 -2
- data/src/core/lib/iomgr/combiner.c +35 -5
- data/src/core/lib/iomgr/combiner.h +21 -2
- data/src/core/lib/iomgr/endpoint.c +3 -2
- data/src/core/lib/iomgr/endpoint.h +3 -2
- data/src/core/lib/iomgr/error.c +60 -94
- data/src/core/lib/iomgr/error.h +7 -10
- data/src/core/lib/iomgr/error_internal.h +54 -0
- data/src/core/lib/iomgr/ev_epoll_linux.c +253 -109
- data/src/core/lib/iomgr/ev_poll_posix.c +61 -29
- data/src/core/lib/iomgr/ev_posix.c +7 -8
- data/src/core/lib/iomgr/ev_posix.h +4 -4
- data/src/core/lib/iomgr/exec_ctx.c +11 -6
- data/src/core/lib/iomgr/exec_ctx.h +11 -14
- data/src/core/lib/iomgr/executor.c +2 -2
- data/src/core/lib/iomgr/load_file.c +1 -1
- data/src/core/lib/iomgr/network_status_tracker.c +5 -81
- data/src/core/lib/iomgr/pollset.h +1 -3
- data/src/core/lib/iomgr/pollset_set.h +2 -1
- data/src/core/lib/iomgr/pollset_set_uv.c +2 -1
- data/src/core/lib/iomgr/pollset_set_windows.c +2 -1
- data/src/core/lib/iomgr/pollset_uv.c +25 -11
- data/src/core/lib/iomgr/pollset_windows.c +0 -11
- data/src/core/lib/iomgr/resolve_address_uv.c +50 -2
- data/src/core/lib/iomgr/resource_quota.c +41 -11
- data/src/core/lib/iomgr/resource_quota.h +6 -0
- data/src/core/lib/iomgr/sockaddr_utils.c +33 -17
- data/src/core/lib/iomgr/sockaddr_utils.h +4 -0
- data/src/core/lib/iomgr/tcp_client_posix.c +2 -3
- data/src/core/lib/iomgr/tcp_client_uv.c +1 -3
- data/src/core/lib/iomgr/tcp_client_windows.c +21 -6
- data/src/core/lib/iomgr/tcp_posix.c +4 -5
- data/src/core/lib/iomgr/tcp_server_posix.c +269 -94
- data/src/core/lib/iomgr/tcp_server_windows.c +1 -1
- data/src/core/lib/iomgr/tcp_uv.c +11 -5
- data/src/core/lib/iomgr/tcp_windows.c +20 -7
- data/src/core/lib/iomgr/timer_generic.c +15 -22
- data/src/core/lib/iomgr/timer_generic.h +1 -1
- data/src/core/lib/iomgr/timer_uv.c +10 -6
- data/src/core/lib/iomgr/timer_uv.h +1 -1
- data/src/core/lib/iomgr/udp_server.c +45 -6
- data/src/core/lib/iomgr/udp_server.h +7 -1
- data/src/core/lib/iomgr/unix_sockets_posix.c +11 -1
- data/src/core/lib/json/json.c +1 -2
- data/src/core/lib/profiling/basic_timers.c +17 -3
- data/src/core/lib/security/context/security_context.c +3 -10
- data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -8
- data/src/core/lib/security/credentials/credentials.c +48 -2
- data/src/core/lib/security/credentials/credentials.h +13 -0
- data/src/core/lib/security/credentials/credentials_metadata.c +1 -2
- data/src/core/lib/security/credentials/fake/fake_credentials.c +6 -8
- data/src/core/lib/security/credentials/fake/fake_credentials.h +15 -0
- data/src/core/lib/security/credentials/google_default/google_default_credentials.c +3 -3
- data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -2
- data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -2
- data/src/core/lib/security/credentials/jwt/jwt_verifier.c +5 -8
- data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -1
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +3 -5
- data/src/core/lib/security/credentials/plugin/plugin_credentials.c +15 -13
- data/src/core/lib/security/credentials/ssl/ssl_credentials.c +2 -4
- data/src/core/lib/security/transport/client_auth_filter.c +72 -47
- data/src/core/lib/security/transport/lb_targets_info.c +70 -0
- data/src/core/lib/security/transport/lb_targets_info.h +47 -0
- data/src/core/lib/security/transport/secure_endpoint.c +3 -3
- data/src/core/lib/security/transport/security_connector.c +125 -28
- data/src/core/lib/security/transport/security_connector.h +4 -3
- data/src/core/lib/security/transport/security_handshaker.c +13 -9
- data/src/core/lib/security/transport/server_auth_filter.c +31 -40
- data/src/core/lib/security/util/b64.c +1 -1
- data/src/core/lib/slice/slice.c +110 -20
- data/src/core/lib/slice/slice_buffer.c +92 -39
- data/src/core/lib/{transport/mdstr_hash_table.c → slice/slice_hash_table.c} +40 -33
- data/src/core/lib/{transport/mdstr_hash_table.h → slice/slice_hash_table.h} +21 -21
- data/src/core/lib/slice/slice_intern.c +346 -0
- data/src/core/lib/slice/slice_internal.h +15 -0
- data/src/core/lib/slice/slice_string_helpers.c +5 -0
- data/src/core/lib/slice/slice_string_helpers.h +5 -0
- data/src/core/lib/support/alloc.c +26 -1
- data/src/core/lib/support/cmdline.c +2 -4
- data/src/core/lib/support/cpu_posix.c +2 -7
- data/src/core/lib/support/histogram.c +1 -2
- data/src/core/lib/support/log_posix.c +8 -4
- data/src/core/lib/support/spinlock.h +52 -0
- data/src/core/lib/support/subprocess_posix.c +1 -2
- data/src/core/lib/support/sync.c +7 -1
- data/src/core/lib/support/sync_posix.c +9 -0
- data/src/core/lib/support/time_windows.c +7 -1
- data/src/core/lib/surface/call.c +647 -629
- data/src/core/lib/surface/call.h +4 -1
- data/src/core/lib/surface/call_details.c +8 -2
- data/src/core/lib/surface/call_log_batch.c +17 -6
- data/src/core/lib/surface/channel.c +49 -59
- data/src/core/lib/surface/channel.h +5 -6
- data/src/core/lib/surface/completion_queue.c +16 -45
- data/src/core/lib/surface/completion_queue.h +0 -3
- data/src/core/lib/surface/init.c +6 -2
- data/src/core/lib/surface/init_secure.c +1 -1
- data/src/core/lib/surface/lame_client.c +14 -4
- data/src/core/lib/surface/server.c +79 -82
- data/src/core/lib/surface/validate_metadata.c +46 -15
- data/src/core/lib/surface/validate_metadata.h +43 -0
- data/src/core/lib/surface/version.c +2 -2
- data/src/core/lib/transport/bdp_estimator.c +104 -0
- data/src/core/lib/transport/bdp_estimator.h +76 -0
- data/src/core/lib/transport/connectivity_state.c +33 -13
- data/src/core/lib/transport/connectivity_state.h +15 -5
- data/src/core/lib/transport/error_utils.c +124 -0
- data/src/core/lib/transport/error_utils.h +56 -0
- data/src/core/{ext/transport/chttp2 → lib}/transport/http2_errors.h +18 -18
- data/src/core/lib/transport/metadata.c +259 -503
- data/src/core/lib/transport/metadata.h +69 -68
- data/src/core/lib/transport/metadata_batch.c +183 -63
- data/src/core/lib/transport/metadata_batch.h +50 -26
- data/src/core/lib/transport/pid_controller.c +28 -8
- data/src/core/lib/transport/pid_controller.h +15 -2
- data/src/core/lib/transport/service_config.c +21 -18
- data/src/core/lib/transport/service_config.h +5 -5
- data/src/core/lib/transport/static_metadata.c +753 -112
- data/src/core/lib/transport/static_metadata.h +403 -264
- data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.c +18 -20
- data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.h +9 -10
- data/src/core/lib/transport/timeout_encoding.c +11 -9
- data/src/core/lib/transport/timeout_encoding.h +3 -1
- data/src/core/lib/transport/transport.c +47 -87
- data/src/core/lib/transport/transport.h +20 -25
- data/src/core/lib/transport/transport_op_string.c +7 -19
- data/src/core/lib/tsi/fake_transport_security.c +2 -4
- data/src/core/lib/tsi/ssl_transport_security.c +7 -16
- data/src/core/lib/tsi/transport_security.c +2 -4
- data/src/ruby/ext/grpc/extconf.rb +4 -1
- data/src/ruby/ext/grpc/rb_byte_buffer.c +7 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.h +3 -0
- data/src/ruby/ext/grpc/rb_call.c +47 -46
- data/src/ruby/ext/grpc/rb_channel.c +21 -6
- data/src/ruby/ext/grpc/rb_compression_options.c +9 -6
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +36 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +59 -8
- data/src/ruby/ext/grpc/rb_server.c +6 -4
- data/src/ruby/lib/grpc/generic/client_stub.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +33 -9
|
@@ -46,4 +46,19 @@ void grpc_slice_buffer_reset_and_unref_internal(grpc_exec_ctx *exec_ctx,
|
|
|
46
46
|
void grpc_slice_buffer_destroy_internal(grpc_exec_ctx *exec_ctx,
|
|
47
47
|
grpc_slice_buffer *sb);
|
|
48
48
|
|
|
49
|
+
/* Check if a slice is interned */
|
|
50
|
+
bool grpc_slice_is_interned(grpc_slice slice);
|
|
51
|
+
|
|
52
|
+
void grpc_slice_intern_init(void);
|
|
53
|
+
void grpc_slice_intern_shutdown(void);
|
|
54
|
+
void grpc_test_only_set_slice_hash_seed(uint32_t key);
|
|
55
|
+
// if slice matches a static slice, returns the static slice
|
|
56
|
+
// otherwise returns the passed in slice (without reffing it)
|
|
57
|
+
// used for surface boundaries where we might receive an un-interned static
|
|
58
|
+
// string
|
|
59
|
+
grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice,
|
|
60
|
+
bool *returned_slice_is_different);
|
|
61
|
+
uint32_t grpc_static_slice_hash(grpc_slice s);
|
|
62
|
+
int grpc_static_slice_eq(grpc_slice a, grpc_slice b);
|
|
63
|
+
|
|
49
64
|
#endif /* GRPC_CORE_LIB_SLICE_SLICE_INTERNAL_H */
|
|
@@ -88,3 +88,8 @@ void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst) {
|
|
|
88
88
|
grpc_slice_buffer_add_indexed(dst, grpc_slice_ref_internal(str));
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
+
|
|
92
|
+
bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result) {
|
|
93
|
+
return gpr_parse_bytes_to_uint32((const char *)GRPC_SLICE_START_PTR(str),
|
|
94
|
+
GRPC_SLICE_LENGTH(str), result) != 0;
|
|
95
|
+
}
|
|
@@ -34,12 +34,15 @@
|
|
|
34
34
|
#ifndef GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
|
|
35
35
|
#define GRPC_CORE_LIB_SLICE_SLICE_STRING_HELPERS_H
|
|
36
36
|
|
|
37
|
+
#include <stdbool.h>
|
|
37
38
|
#include <stddef.h>
|
|
38
39
|
|
|
39
40
|
#include <grpc/slice.h>
|
|
40
41
|
#include <grpc/slice_buffer.h>
|
|
41
42
|
#include <grpc/support/port_platform.h>
|
|
42
43
|
|
|
44
|
+
#include "src/core/lib/support/string.h"
|
|
45
|
+
|
|
43
46
|
#ifdef __cplusplus
|
|
44
47
|
extern "C" {
|
|
45
48
|
#endif
|
|
@@ -51,6 +54,8 @@ char *grpc_dump_slice(grpc_slice slice, uint32_t flags);
|
|
|
51
54
|
* should be a properly initialized instance. */
|
|
52
55
|
void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst);
|
|
53
56
|
|
|
57
|
+
bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result);
|
|
58
|
+
|
|
54
59
|
#ifdef __cplusplus
|
|
55
60
|
}
|
|
56
61
|
#endif
|
|
@@ -36,9 +36,19 @@
|
|
|
36
36
|
#include <grpc/support/log.h>
|
|
37
37
|
#include <grpc/support/port_platform.h>
|
|
38
38
|
#include <stdlib.h>
|
|
39
|
+
#include <string.h>
|
|
39
40
|
#include "src/core/lib/profiling/timers.h"
|
|
40
41
|
|
|
41
|
-
static
|
|
42
|
+
static void *zalloc_with_calloc(size_t sz) { return calloc(sz, 1); }
|
|
43
|
+
|
|
44
|
+
static void *zalloc_with_gpr_malloc(size_t sz) {
|
|
45
|
+
void *p = gpr_malloc(sz);
|
|
46
|
+
memset(p, 0, sz);
|
|
47
|
+
return p;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static gpr_allocation_functions g_alloc_functions = {malloc, zalloc_with_calloc,
|
|
51
|
+
realloc, free};
|
|
42
52
|
|
|
43
53
|
gpr_allocation_functions gpr_get_allocation_functions() {
|
|
44
54
|
return g_alloc_functions;
|
|
@@ -48,6 +58,9 @@ void gpr_set_allocation_functions(gpr_allocation_functions functions) {
|
|
|
48
58
|
GPR_ASSERT(functions.malloc_fn != NULL);
|
|
49
59
|
GPR_ASSERT(functions.realloc_fn != NULL);
|
|
50
60
|
GPR_ASSERT(functions.free_fn != NULL);
|
|
61
|
+
if (functions.zalloc_fn == NULL) {
|
|
62
|
+
functions.zalloc_fn = zalloc_with_gpr_malloc;
|
|
63
|
+
}
|
|
51
64
|
g_alloc_functions = functions;
|
|
52
65
|
}
|
|
53
66
|
|
|
@@ -63,6 +76,18 @@ void *gpr_malloc(size_t size) {
|
|
|
63
76
|
return p;
|
|
64
77
|
}
|
|
65
78
|
|
|
79
|
+
void *gpr_zalloc(size_t size) {
|
|
80
|
+
void *p;
|
|
81
|
+
if (size == 0) return NULL;
|
|
82
|
+
GPR_TIMER_BEGIN("gpr_zalloc", 0);
|
|
83
|
+
p = g_alloc_functions.zalloc_fn(size);
|
|
84
|
+
if (!p) {
|
|
85
|
+
abort();
|
|
86
|
+
}
|
|
87
|
+
GPR_TIMER_END("gpr_zalloc", 0);
|
|
88
|
+
return p;
|
|
89
|
+
}
|
|
90
|
+
|
|
66
91
|
void gpr_free(void *p) {
|
|
67
92
|
GPR_TIMER_BEGIN("gpr_free", 0);
|
|
68
93
|
g_alloc_functions.free_fn(p);
|
|
@@ -71,8 +71,7 @@ struct gpr_cmdline {
|
|
|
71
71
|
static int normal_state(gpr_cmdline *cl, char *arg);
|
|
72
72
|
|
|
73
73
|
gpr_cmdline *gpr_cmdline_create(const char *description) {
|
|
74
|
-
gpr_cmdline *cl =
|
|
75
|
-
memset(cl, 0, sizeof(gpr_cmdline));
|
|
74
|
+
gpr_cmdline *cl = gpr_zalloc(sizeof(gpr_cmdline));
|
|
76
75
|
|
|
77
76
|
cl->description = description;
|
|
78
77
|
cl->state = normal_state;
|
|
@@ -101,8 +100,7 @@ static void add_arg(gpr_cmdline *cl, const char *name, const char *help,
|
|
|
101
100
|
GPR_ASSERT(0 != strcmp(a->name, name));
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
a =
|
|
105
|
-
memset(a, 0, sizeof(arg));
|
|
103
|
+
a = gpr_zalloc(sizeof(arg));
|
|
106
104
|
a->name = name;
|
|
107
105
|
a->help = help;
|
|
108
106
|
a->type = type;
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
#include <grpc/support/log.h>
|
|
43
43
|
#include <grpc/support/sync.h>
|
|
44
|
+
#include <grpc/support/useful.h>
|
|
44
45
|
|
|
45
46
|
static __thread char magic_thread_local;
|
|
46
47
|
|
|
@@ -60,18 +61,12 @@ unsigned gpr_cpu_num_cores(void) {
|
|
|
60
61
|
return (unsigned)ncpus;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
/* This is a cheap, but good enough, pointer hash for sharding things: */
|
|
64
|
-
static size_t shard_ptr(const void *info) {
|
|
65
|
-
size_t x = (size_t)info;
|
|
66
|
-
return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) % gpr_cpu_num_cores();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
64
|
unsigned gpr_cpu_current_cpu(void) {
|
|
70
65
|
/* NOTE: there's no way I know to return the actual cpu index portably...
|
|
71
66
|
most code that's using this is using it to shard across work queues though,
|
|
72
67
|
so here we use thread identity instead to achieve a similar though not
|
|
73
68
|
identical effect */
|
|
74
|
-
return (unsigned)
|
|
69
|
+
return (unsigned)GPR_HASH_POINTER(&magic_thread_local, gpr_cpu_num_cores());
|
|
75
70
|
}
|
|
76
71
|
|
|
77
72
|
#endif /* GPR_CPU_POSIX */
|
|
@@ -102,8 +102,7 @@ gpr_histogram *gpr_histogram_create(double resolution,
|
|
|
102
102
|
h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
|
|
103
103
|
GPR_ASSERT(h->num_buckets > 1);
|
|
104
104
|
GPR_ASSERT(h->num_buckets < 100000000);
|
|
105
|
-
h->buckets =
|
|
106
|
-
memset(h->buckets, 0, sizeof(uint32_t) * h->num_buckets);
|
|
105
|
+
h->buckets = gpr_zalloc(sizeof(uint32_t) * h->num_buckets);
|
|
107
106
|
return h;
|
|
108
107
|
}
|
|
109
108
|
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
#include <grpc/support/alloc.h>
|
|
39
39
|
#include <grpc/support/log.h>
|
|
40
|
+
#include <grpc/support/string_util.h>
|
|
40
41
|
#include <grpc/support/time.h>
|
|
41
42
|
#include <pthread.h>
|
|
42
43
|
#include <stdarg.h>
|
|
@@ -93,10 +94,13 @@ void gpr_default_log(gpr_log_func_args *args) {
|
|
|
93
94
|
strcpy(time_buffer, "error:strftime");
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
char *prefix;
|
|
98
|
+
gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]",
|
|
99
|
+
gpr_log_severity_string(args->severity), time_buffer,
|
|
100
|
+
(int)(now.tv_nsec), gettid(), display_file, args->line);
|
|
101
|
+
|
|
102
|
+
fprintf(stderr, "%-70s %s\n", prefix, args->message);
|
|
103
|
+
gpr_free(prefix);
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
#endif /* defined(GPR_POSIX_LOG) */
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* Copyright 2015, Google Inc.
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
|
7
|
+
* modification, are permitted provided that the following conditions are
|
|
8
|
+
* met:
|
|
9
|
+
*
|
|
10
|
+
* * Redistributions of source code must retain the above copyright
|
|
11
|
+
* notice, this list of conditions and the following disclaimer.
|
|
12
|
+
* * Redistributions in binary form must reproduce the above
|
|
13
|
+
* copyright notice, this list of conditions and the following disclaimer
|
|
14
|
+
* in the documentation and/or other materials provided with the
|
|
15
|
+
* distribution.
|
|
16
|
+
* * Neither the name of Google Inc. nor the names of its
|
|
17
|
+
* contributors may be used to endorse or promote products derived from
|
|
18
|
+
* this software without specific prior written permission.
|
|
19
|
+
*
|
|
20
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
21
|
+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
22
|
+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
23
|
+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
24
|
+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
25
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
26
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
27
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
28
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
29
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
30
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
#ifndef GRPC_CORE_LIB_SUPPORT_SPINLOCK_H
|
|
35
|
+
#define GRPC_CORE_LIB_SUPPORT_SPINLOCK_H
|
|
36
|
+
|
|
37
|
+
#include <grpc/support/atm.h>
|
|
38
|
+
|
|
39
|
+
/* Simple spinlock. No backoff strategy, gpr_spinlock_lock is almost always
|
|
40
|
+
a concurrency code smell. */
|
|
41
|
+
typedef struct { gpr_atm atm; } gpr_spinlock;
|
|
42
|
+
|
|
43
|
+
#define GPR_SPINLOCK_INITIALIZER ((gpr_spinlock){0})
|
|
44
|
+
#define GPR_SPINLOCK_STATIC_INITIALIZER \
|
|
45
|
+
{ 0 }
|
|
46
|
+
#define gpr_spinlock_trylock(lock) (gpr_atm_acq_cas(&(lock)->atm, 0, 1))
|
|
47
|
+
#define gpr_spinlock_unlock(lock) (gpr_atm_rel_store(&(lock)->atm, 0))
|
|
48
|
+
#define gpr_spinlock_lock(lock) \
|
|
49
|
+
do { \
|
|
50
|
+
} while (!gpr_spinlock_trylock((lock)))
|
|
51
|
+
|
|
52
|
+
#endif /* GRPC_CORE_LIB_SUPPORT_SPINLOCK_H */
|
|
@@ -76,8 +76,7 @@ gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
|
|
|
76
76
|
_exit(1);
|
|
77
77
|
return NULL;
|
|
78
78
|
} else {
|
|
79
|
-
r =
|
|
80
|
-
memset(r, 0, sizeof(*r));
|
|
79
|
+
r = gpr_zalloc(sizeof(gpr_subprocess));
|
|
81
80
|
r->pid = pid;
|
|
82
81
|
return r;
|
|
83
82
|
}
|
data/src/core/lib/support/sync.c
CHANGED
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
#include <grpc/support/log.h>
|
|
38
38
|
#include <grpc/support/sync.h>
|
|
39
39
|
|
|
40
|
+
#include <assert.h>
|
|
41
|
+
|
|
40
42
|
/* Number of mutexes to allocate for events, to avoid lock contention.
|
|
41
43
|
Should be a prime. */
|
|
42
44
|
enum { event_sync_partitions = 31 };
|
|
@@ -99,8 +101,12 @@ void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
|
|
|
99
101
|
void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
|
|
100
102
|
|
|
101
103
|
void gpr_ref_non_zero(gpr_refcount *r) {
|
|
104
|
+
#ifndef NDEBUG
|
|
102
105
|
gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
|
|
103
|
-
|
|
106
|
+
assert(prior > 0);
|
|
107
|
+
#else
|
|
108
|
+
gpr_ref(r);
|
|
109
|
+
#endif
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
void gpr_refn(gpr_refcount *r, int n) {
|
|
@@ -42,11 +42,20 @@
|
|
|
42
42
|
#include <time.h>
|
|
43
43
|
#include "src/core/lib/profiling/timers.h"
|
|
44
44
|
|
|
45
|
+
#ifdef GPR_LOW_LEVEL_COUNTERS
|
|
46
|
+
gpr_atm gpr_mu_locks = 0;
|
|
47
|
+
gpr_atm gpr_counter_atm_cas = 0;
|
|
48
|
+
gpr_atm gpr_counter_atm_add = 0;
|
|
49
|
+
#endif
|
|
50
|
+
|
|
45
51
|
void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
|
|
46
52
|
|
|
47
53
|
void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); }
|
|
48
54
|
|
|
49
55
|
void gpr_mu_lock(gpr_mu* mu) {
|
|
56
|
+
#ifdef GPR_LOW_LEVEL_COUNTERS
|
|
57
|
+
GPR_ATM_INC_COUNTER(gpr_mu_locks);
|
|
58
|
+
#endif
|
|
50
59
|
GPR_TIMER_BEGIN("gpr_mu_lock", 0);
|
|
51
60
|
GPR_ASSERT(pthread_mutex_lock(mu) == 0);
|
|
52
61
|
GPR_TIMER_END("gpr_mu_lock", 0);
|
|
@@ -56,7 +56,7 @@ void gpr_time_init(void) {
|
|
|
56
56
|
g_time_scale = 1.0 / (double)frequency.QuadPart;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
gpr_timespec
|
|
59
|
+
static gpr_timespec now_impl(gpr_clock_type clock) {
|
|
60
60
|
gpr_timespec now_tv;
|
|
61
61
|
LONGLONG diff;
|
|
62
62
|
struct _timeb now_tb;
|
|
@@ -84,6 +84,12 @@ gpr_timespec gpr_now(gpr_clock_type clock) {
|
|
|
84
84
|
return now_tv;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl;
|
|
88
|
+
|
|
89
|
+
gpr_timespec gpr_now(gpr_clock_type clock_type) {
|
|
90
|
+
return gpr_now_impl(clock_type);
|
|
91
|
+
}
|
|
92
|
+
|
|
87
93
|
void gpr_sleep_until(gpr_timespec until) {
|
|
88
94
|
gpr_timespec now;
|
|
89
95
|
gpr_timespec delta;
|
data/src/core/lib/surface/call.c
CHANGED
|
@@ -56,13 +56,15 @@
|
|
|
56
56
|
#include "src/core/lib/surface/call.h"
|
|
57
57
|
#include "src/core/lib/surface/channel.h"
|
|
58
58
|
#include "src/core/lib/surface/completion_queue.h"
|
|
59
|
+
#include "src/core/lib/surface/validate_metadata.h"
|
|
60
|
+
#include "src/core/lib/transport/error_utils.h"
|
|
59
61
|
#include "src/core/lib/transport/metadata.h"
|
|
60
62
|
#include "src/core/lib/transport/static_metadata.h"
|
|
61
63
|
#include "src/core/lib/transport/transport.h"
|
|
62
64
|
|
|
63
65
|
/** The maximum number of concurrent batches possible.
|
|
64
66
|
Based upon the maximum number of individually queueable ops in the batch
|
|
65
|
-
|
|
67
|
+
api:
|
|
66
68
|
- initial metadata send
|
|
67
69
|
- message send
|
|
68
70
|
- status/close send (depending on client/server)
|
|
@@ -84,26 +86,43 @@ typedef enum {
|
|
|
84
86
|
/* Status came from 'the wire' - or somewhere below the surface
|
|
85
87
|
layer */
|
|
86
88
|
STATUS_FROM_WIRE,
|
|
87
|
-
/* Status was created by some internal channel stack operation
|
|
89
|
+
/* Status was created by some internal channel stack operation: must come via
|
|
90
|
+
add_batch_error */
|
|
88
91
|
STATUS_FROM_CORE,
|
|
92
|
+
/* Status was created by some surface error */
|
|
93
|
+
STATUS_FROM_SURFACE,
|
|
89
94
|
/* Status came from the server sending status */
|
|
90
95
|
STATUS_FROM_SERVER_STATUS,
|
|
91
96
|
STATUS_SOURCE_COUNT
|
|
92
97
|
} status_source;
|
|
93
98
|
|
|
94
99
|
typedef struct {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
grpc_mdstr *details;
|
|
100
|
+
bool is_set;
|
|
101
|
+
grpc_error *error;
|
|
98
102
|
} received_status;
|
|
99
103
|
|
|
104
|
+
static gpr_atm pack_received_status(received_status r) {
|
|
105
|
+
return r.is_set ? (1 | (gpr_atm)r.error) : 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static received_status unpack_received_status(gpr_atm atm) {
|
|
109
|
+
return (atm & 1) == 0
|
|
110
|
+
? (received_status){.is_set = false, .error = GRPC_ERROR_NONE}
|
|
111
|
+
: (received_status){.is_set = true,
|
|
112
|
+
.error = (grpc_error *)(atm & ~(gpr_atm)1)};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
#define MAX_ERRORS_PER_BATCH 4
|
|
116
|
+
|
|
100
117
|
typedef struct batch_control {
|
|
101
118
|
grpc_call *call;
|
|
102
119
|
grpc_cq_completion cq_completion;
|
|
103
120
|
grpc_closure finish_batch;
|
|
104
121
|
void *notify_tag;
|
|
105
122
|
gpr_refcount steps_to_complete;
|
|
106
|
-
|
|
123
|
+
|
|
124
|
+
grpc_error *errors[MAX_ERRORS_PER_BATCH];
|
|
125
|
+
gpr_atm num_errors;
|
|
107
126
|
|
|
108
127
|
uint8_t send_initial_metadata;
|
|
109
128
|
uint8_t send_message;
|
|
@@ -134,8 +153,6 @@ struct grpc_call {
|
|
|
134
153
|
bool destroy_called;
|
|
135
154
|
/** flag indicating that cancellation is inherited */
|
|
136
155
|
bool cancellation_is_inherited;
|
|
137
|
-
/** bitmask of live batches */
|
|
138
|
-
uint8_t used_batches;
|
|
139
156
|
/** which ops are in-flight */
|
|
140
157
|
bool sent_initial_metadata;
|
|
141
158
|
bool sending_message;
|
|
@@ -144,6 +161,7 @@ struct grpc_call {
|
|
|
144
161
|
bool receiving_message;
|
|
145
162
|
bool requested_final_op;
|
|
146
163
|
bool received_final_op;
|
|
164
|
+
bool sent_any_op;
|
|
147
165
|
|
|
148
166
|
/* have we received initial metadata */
|
|
149
167
|
bool has_initial_md_been_received;
|
|
@@ -157,8 +175,8 @@ struct grpc_call {
|
|
|
157
175
|
Element 0 is initial metadata, element 1 is trailing metadata. */
|
|
158
176
|
grpc_metadata_array *buffered_metadata[2];
|
|
159
177
|
|
|
160
|
-
/*
|
|
161
|
-
|
|
178
|
+
/* Packed received call statuses from various sources */
|
|
179
|
+
gpr_atm status[STATUS_SOURCE_COUNT];
|
|
162
180
|
|
|
163
181
|
/* Call data useful used for reporting. Only valid after the call has
|
|
164
182
|
* completed */
|
|
@@ -185,6 +203,7 @@ struct grpc_call {
|
|
|
185
203
|
grpc_call *sibling_prev;
|
|
186
204
|
|
|
187
205
|
grpc_slice_buffer_stream sending_stream;
|
|
206
|
+
|
|
188
207
|
grpc_byte_stream *receiving_stream;
|
|
189
208
|
grpc_byte_buffer **receiving_buffer;
|
|
190
209
|
grpc_slice receiving_slice;
|
|
@@ -196,8 +215,7 @@ struct grpc_call {
|
|
|
196
215
|
union {
|
|
197
216
|
struct {
|
|
198
217
|
grpc_status_code *status;
|
|
199
|
-
|
|
200
|
-
size_t *status_details_capacity;
|
|
218
|
+
grpc_slice *status_details;
|
|
201
219
|
} client;
|
|
202
220
|
struct {
|
|
203
221
|
int *cancelled;
|
|
@@ -207,6 +225,8 @@ struct grpc_call {
|
|
|
207
225
|
void *saved_receiving_stream_ready_bctlp;
|
|
208
226
|
};
|
|
209
227
|
|
|
228
|
+
int grpc_call_error_trace = 0;
|
|
229
|
+
|
|
210
230
|
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
|
|
211
231
|
#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
|
|
212
232
|
#define CALL_ELEM_FROM_CALL(call, idx) \
|
|
@@ -216,28 +236,45 @@ struct grpc_call {
|
|
|
216
236
|
|
|
217
237
|
static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
|
|
218
238
|
grpc_transport_stream_op *op);
|
|
219
|
-
static
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
static
|
|
223
|
-
|
|
224
|
-
const char *description);
|
|
239
|
+
static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
|
|
240
|
+
status_source source, grpc_status_code status,
|
|
241
|
+
const char *description);
|
|
242
|
+
static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
|
|
243
|
+
status_source source, grpc_error *error);
|
|
225
244
|
static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack,
|
|
226
245
|
grpc_error *error);
|
|
227
246
|
static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
|
|
228
247
|
grpc_error *error);
|
|
248
|
+
static void get_final_status(grpc_call *call,
|
|
249
|
+
void (*set_value)(grpc_status_code code,
|
|
250
|
+
void *user_data),
|
|
251
|
+
void *set_value_user_data, grpc_slice *details);
|
|
252
|
+
static void set_status_value_directly(grpc_status_code status, void *dest);
|
|
253
|
+
static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
|
|
254
|
+
status_source source, grpc_error *error);
|
|
255
|
+
static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl);
|
|
256
|
+
static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl);
|
|
257
|
+
static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
|
|
258
|
+
grpc_error *error, bool has_cancelled);
|
|
259
|
+
|
|
260
|
+
static void add_init_error(grpc_error **composite, grpc_error *new) {
|
|
261
|
+
if (new == GRPC_ERROR_NONE) return;
|
|
262
|
+
if (*composite == GRPC_ERROR_NONE)
|
|
263
|
+
*composite = GRPC_ERROR_CREATE("Call creation failed");
|
|
264
|
+
*composite = grpc_error_add_child(*composite, new);
|
|
265
|
+
}
|
|
229
266
|
|
|
230
267
|
grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
231
268
|
const grpc_call_create_args *args,
|
|
232
269
|
grpc_call **out_call) {
|
|
233
270
|
size_t i, j;
|
|
271
|
+
grpc_error *error = GRPC_ERROR_NONE;
|
|
234
272
|
grpc_channel_stack *channel_stack =
|
|
235
273
|
grpc_channel_get_channel_stack(args->channel);
|
|
236
274
|
grpc_call *call;
|
|
237
275
|
GPR_TIMER_BEGIN("grpc_call_create", 0);
|
|
238
|
-
call =
|
|
276
|
+
call = gpr_zalloc(sizeof(grpc_call) + channel_stack->call_stack_size);
|
|
239
277
|
*out_call = call;
|
|
240
|
-
memset(call, 0, sizeof(grpc_call));
|
|
241
278
|
gpr_mu_init(&call->mu);
|
|
242
279
|
call->channel = args->channel;
|
|
243
280
|
call->cq = args->cq;
|
|
@@ -246,14 +283,16 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
|
246
283
|
/* Always support no compression */
|
|
247
284
|
GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
|
|
248
285
|
call->is_client = args->server_transport_data == NULL;
|
|
249
|
-
|
|
286
|
+
grpc_slice path = grpc_empty_slice();
|
|
250
287
|
if (call->is_client) {
|
|
251
288
|
GPR_ASSERT(args->add_initial_metadata_count <
|
|
252
289
|
MAX_SEND_EXTRA_METADATA_COUNT);
|
|
253
290
|
for (i = 0; i < args->add_initial_metadata_count; i++) {
|
|
254
291
|
call->send_extra_metadata[i].md = args->add_initial_metadata[i];
|
|
255
|
-
if (args->add_initial_metadata[i]
|
|
256
|
-
|
|
292
|
+
if (grpc_slice_eq(GRPC_MDKEY(args->add_initial_metadata[i]),
|
|
293
|
+
GRPC_MDSTR_PATH)) {
|
|
294
|
+
path = grpc_slice_ref_internal(
|
|
295
|
+
GRPC_MDVALUE(args->add_initial_metadata[i]));
|
|
257
296
|
}
|
|
258
297
|
}
|
|
259
298
|
call->send_extra_metadata_count = (int)args->add_initial_metadata_count;
|
|
@@ -287,12 +326,18 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
|
287
326
|
/* TODO(ctiller): This should change to use the appropriate census start_op
|
|
288
327
|
* call. */
|
|
289
328
|
if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) {
|
|
290
|
-
|
|
329
|
+
if (0 == (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)) {
|
|
330
|
+
add_init_error(&error,
|
|
331
|
+
GRPC_ERROR_CREATE("Census tracing propagation requested "
|
|
332
|
+
"without Census context propagation"));
|
|
333
|
+
}
|
|
291
334
|
grpc_call_context_set(
|
|
292
335
|
call, GRPC_CONTEXT_TRACING,
|
|
293
336
|
args->parent_call->context[GRPC_CONTEXT_TRACING].value, NULL);
|
|
294
|
-
} else {
|
|
295
|
-
|
|
337
|
+
} else if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT) {
|
|
338
|
+
add_init_error(&error,
|
|
339
|
+
GRPC_ERROR_CREATE("Census context propagation requested "
|
|
340
|
+
"without Census tracing propagation"));
|
|
296
341
|
}
|
|
297
342
|
if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
|
|
298
343
|
call->cancellation_is_inherited = 1;
|
|
@@ -315,15 +360,14 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
|
315
360
|
|
|
316
361
|
GRPC_CHANNEL_INTERNAL_REF(args->channel, "call");
|
|
317
362
|
/* initial refcount dropped by grpc_call_destroy */
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
363
|
+
add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1,
|
|
364
|
+
destroy_call, call, call->context,
|
|
365
|
+
args->server_transport_data, path,
|
|
366
|
+
call->start_time, send_deadline,
|
|
367
|
+
CALL_STACK_FROM_CALL(call)));
|
|
322
368
|
if (error != GRPC_ERROR_NONE) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
grpc_error_get_status(error, &status, &error_str);
|
|
326
|
-
close_with_status(exec_ctx, call, status, error_str);
|
|
369
|
+
cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
|
|
370
|
+
GRPC_ERROR_REF(error));
|
|
327
371
|
}
|
|
328
372
|
if (args->cq != NULL) {
|
|
329
373
|
GPR_ASSERT(
|
|
@@ -342,7 +386,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
|
342
386
|
exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent);
|
|
343
387
|
}
|
|
344
388
|
|
|
345
|
-
|
|
389
|
+
grpc_slice_unref_internal(exec_ctx, path);
|
|
346
390
|
|
|
347
391
|
GPR_TIMER_END("grpc_call_create", 0);
|
|
348
392
|
return error;
|
|
@@ -377,24 +421,6 @@ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
|
|
|
377
421
|
GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
|
|
378
422
|
}
|
|
379
423
|
|
|
380
|
-
static void get_final_status(grpc_call *call,
|
|
381
|
-
void (*set_value)(grpc_status_code code,
|
|
382
|
-
void *user_data),
|
|
383
|
-
void *set_value_user_data) {
|
|
384
|
-
int i;
|
|
385
|
-
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
386
|
-
if (call->status[i].is_set) {
|
|
387
|
-
set_value(call->status[i].code, set_value_user_data);
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
if (call->is_client) {
|
|
392
|
-
set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
|
|
393
|
-
} else {
|
|
394
|
-
set_value(GRPC_STATUS_OK, set_value_user_data);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
424
|
static void set_status_value_directly(grpc_status_code status, void *dest);
|
|
399
425
|
static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
|
|
400
426
|
grpc_error *error) {
|
|
@@ -410,11 +436,6 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
|
|
|
410
436
|
grpc_byte_stream_destroy(exec_ctx, c->receiving_stream);
|
|
411
437
|
}
|
|
412
438
|
gpr_mu_destroy(&c->mu);
|
|
413
|
-
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
414
|
-
if (c->status[i].details) {
|
|
415
|
-
GRPC_MDSTR_UNREF(exec_ctx, c->status[i].details);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
439
|
for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
|
|
419
440
|
GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md);
|
|
420
441
|
}
|
|
@@ -428,42 +449,263 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
|
|
|
428
449
|
}
|
|
429
450
|
grpc_channel *channel = c->channel;
|
|
430
451
|
|
|
431
|
-
get_final_status(call, set_status_value_directly,
|
|
432
|
-
|
|
452
|
+
get_final_status(call, set_status_value_directly, &c->final_info.final_status,
|
|
453
|
+
NULL);
|
|
433
454
|
c->final_info.stats.latency =
|
|
434
455
|
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
|
|
435
456
|
|
|
457
|
+
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
458
|
+
GRPC_ERROR_UNREF(
|
|
459
|
+
unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error);
|
|
460
|
+
}
|
|
461
|
+
|
|
436
462
|
grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c);
|
|
437
463
|
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call");
|
|
438
464
|
GPR_TIMER_END("destroy_call", 0);
|
|
439
465
|
}
|
|
440
466
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
467
|
+
void grpc_call_destroy(grpc_call *c) {
|
|
468
|
+
int cancel;
|
|
469
|
+
grpc_call *parent = c->parent;
|
|
470
|
+
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
|
471
|
+
|
|
472
|
+
GPR_TIMER_BEGIN("grpc_call_destroy", 0);
|
|
473
|
+
GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
|
|
474
|
+
|
|
475
|
+
if (parent) {
|
|
476
|
+
gpr_mu_lock(&parent->mu);
|
|
477
|
+
if (c == parent->first_child) {
|
|
478
|
+
parent->first_child = c->sibling_next;
|
|
479
|
+
if (c == parent->first_child) {
|
|
480
|
+
parent->first_child = NULL;
|
|
481
|
+
}
|
|
482
|
+
c->sibling_prev->sibling_next = c->sibling_next;
|
|
483
|
+
c->sibling_next->sibling_prev = c->sibling_prev;
|
|
484
|
+
}
|
|
485
|
+
gpr_mu_unlock(&parent->mu);
|
|
486
|
+
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
gpr_mu_lock(&c->mu);
|
|
490
|
+
GPR_ASSERT(!c->destroy_called);
|
|
491
|
+
c->destroy_called = 1;
|
|
492
|
+
cancel = c->sent_any_op && !c->received_final_op;
|
|
493
|
+
gpr_mu_unlock(&c->mu);
|
|
494
|
+
if (cancel) {
|
|
495
|
+
cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
|
|
496
|
+
GRPC_ERROR_CANCELLED);
|
|
497
|
+
}
|
|
498
|
+
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
|
|
499
|
+
grpc_exec_ctx_finish(&exec_ctx);
|
|
500
|
+
GPR_TIMER_END("grpc_call_destroy", 0);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
|
|
504
|
+
GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
|
|
505
|
+
GPR_ASSERT(!reserved);
|
|
506
|
+
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
|
507
|
+
cancel_with_error(&exec_ctx, call, STATUS_FROM_API_OVERRIDE,
|
|
508
|
+
GRPC_ERROR_CANCELLED);
|
|
509
|
+
grpc_exec_ctx_finish(&exec_ctx);
|
|
510
|
+
return GRPC_CALL_OK;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
|
|
514
|
+
grpc_transport_stream_op *op) {
|
|
515
|
+
grpc_call_element *elem;
|
|
516
|
+
|
|
517
|
+
GPR_TIMER_BEGIN("execute_op", 0);
|
|
518
|
+
elem = CALL_ELEM_FROM_CALL(call, 0);
|
|
519
|
+
op->context = call->context;
|
|
520
|
+
elem->filter->start_transport_stream_op(exec_ctx, elem, op);
|
|
521
|
+
GPR_TIMER_END("execute_op", 0);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
char *grpc_call_get_peer(grpc_call *call) {
|
|
525
|
+
grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
|
|
526
|
+
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
|
527
|
+
char *result;
|
|
528
|
+
GRPC_API_TRACE("grpc_call_get_peer(%p)", 1, (call));
|
|
529
|
+
result = elem->filter->get_peer(&exec_ctx, elem);
|
|
530
|
+
if (result == NULL) {
|
|
531
|
+
result = grpc_channel_get_target(call->channel);
|
|
532
|
+
}
|
|
533
|
+
if (result == NULL) {
|
|
534
|
+
result = gpr_strdup("unknown");
|
|
535
|
+
}
|
|
536
|
+
grpc_exec_ctx_finish(&exec_ctx);
|
|
537
|
+
return result;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
|
|
541
|
+
return CALL_FROM_TOP_ELEM(elem);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/*******************************************************************************
|
|
545
|
+
* CANCELLATION
|
|
546
|
+
*/
|
|
547
|
+
|
|
548
|
+
grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
|
|
549
|
+
grpc_status_code status,
|
|
550
|
+
const char *description,
|
|
551
|
+
void *reserved) {
|
|
552
|
+
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
|
553
|
+
GRPC_API_TRACE(
|
|
554
|
+
"grpc_call_cancel_with_status("
|
|
555
|
+
"c=%p, status=%d, description=%s, reserved=%p)",
|
|
556
|
+
4, (c, (int)status, description, reserved));
|
|
557
|
+
GPR_ASSERT(reserved == NULL);
|
|
558
|
+
gpr_mu_lock(&c->mu);
|
|
559
|
+
cancel_with_status(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, status,
|
|
560
|
+
description);
|
|
561
|
+
gpr_mu_unlock(&c->mu);
|
|
562
|
+
grpc_exec_ctx_finish(&exec_ctx);
|
|
563
|
+
return GRPC_CALL_OK;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
typedef struct termination_closure {
|
|
567
|
+
grpc_closure closure;
|
|
568
|
+
grpc_call *call;
|
|
569
|
+
grpc_transport_stream_op op;
|
|
570
|
+
} termination_closure;
|
|
571
|
+
|
|
572
|
+
static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp,
|
|
573
|
+
grpc_error *error) {
|
|
574
|
+
termination_closure *tc = tcp;
|
|
575
|
+
GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "termination");
|
|
576
|
+
gpr_free(tc);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
static void send_termination(grpc_exec_ctx *exec_ctx, void *tcp,
|
|
580
|
+
grpc_error *error) {
|
|
581
|
+
termination_closure *tc = tcp;
|
|
582
|
+
memset(&tc->op, 0, sizeof(tc->op));
|
|
583
|
+
tc->op.cancel_error = GRPC_ERROR_REF(error);
|
|
584
|
+
/* reuse closure to catch completion */
|
|
585
|
+
tc->op.on_complete = grpc_closure_init(&tc->closure, done_termination, tc,
|
|
586
|
+
grpc_schedule_on_exec_ctx);
|
|
587
|
+
execute_op(exec_ctx, tc->call, &tc->op);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
static void terminate_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
|
|
591
|
+
grpc_error *error) {
|
|
592
|
+
termination_closure *tc = gpr_malloc(sizeof(*tc));
|
|
593
|
+
memset(tc, 0, sizeof(*tc));
|
|
594
|
+
tc->call = c;
|
|
595
|
+
GRPC_CALL_INTERNAL_REF(tc->call, "termination");
|
|
596
|
+
grpc_closure_sched(exec_ctx, grpc_closure_init(&tc->closure, send_termination,
|
|
597
|
+
tc, grpc_schedule_on_exec_ctx),
|
|
598
|
+
error);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
|
|
602
|
+
status_source source, grpc_error *error) {
|
|
603
|
+
set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error));
|
|
604
|
+
terminate_with_error(exec_ctx, c, error);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
static grpc_error *error_from_status(grpc_status_code status,
|
|
608
|
+
const char *description) {
|
|
609
|
+
return grpc_error_set_int(
|
|
610
|
+
grpc_error_set_str(GRPC_ERROR_CREATE(description),
|
|
611
|
+
GRPC_ERROR_STR_GRPC_MESSAGE, description),
|
|
612
|
+
GRPC_ERROR_INT_GRPC_STATUS, status);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
|
|
616
|
+
status_source source, grpc_status_code status,
|
|
617
|
+
const char *description) {
|
|
618
|
+
cancel_with_error(exec_ctx, c, source,
|
|
619
|
+
error_from_status(status, description));
|
|
620
|
+
}
|
|
444
621
|
|
|
445
|
-
|
|
446
|
-
|
|
622
|
+
/*******************************************************************************
|
|
623
|
+
* FINAL STATUS CODE MANIPULATION
|
|
624
|
+
*/
|
|
625
|
+
|
|
626
|
+
static bool get_final_status_from(
|
|
627
|
+
grpc_call *call, grpc_error *error, bool allow_ok_status,
|
|
628
|
+
void (*set_value)(grpc_status_code code, void *user_data),
|
|
629
|
+
void *set_value_user_data, grpc_slice *details) {
|
|
630
|
+
grpc_status_code code;
|
|
631
|
+
const char *msg = NULL;
|
|
632
|
+
grpc_error_get_status(error, call->send_deadline, &code, &msg, NULL);
|
|
633
|
+
if (code == GRPC_STATUS_OK && !allow_ok_status) {
|
|
634
|
+
return false;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
set_value(code, set_value_user_data);
|
|
638
|
+
if (details != NULL) {
|
|
639
|
+
*details =
|
|
640
|
+
msg == NULL ? grpc_empty_slice() : grpc_slice_from_copied_string(msg);
|
|
641
|
+
}
|
|
642
|
+
return true;
|
|
447
643
|
}
|
|
448
644
|
|
|
449
|
-
static void
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
645
|
+
static void get_final_status(grpc_call *call,
|
|
646
|
+
void (*set_value)(grpc_status_code code,
|
|
647
|
+
void *user_data),
|
|
648
|
+
void *set_value_user_data, grpc_slice *details) {
|
|
649
|
+
int i;
|
|
650
|
+
received_status status[STATUS_SOURCE_COUNT];
|
|
651
|
+
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
652
|
+
status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
|
|
653
|
+
}
|
|
654
|
+
if (grpc_call_error_trace) {
|
|
655
|
+
gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
|
|
656
|
+
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
657
|
+
if (status[i].is_set) {
|
|
658
|
+
gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error));
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
/* first search through ignoring "OK" statuses: if something went wrong,
|
|
663
|
+
* ensure we report it */
|
|
664
|
+
for (int allow_ok_status = 0; allow_ok_status < 2; allow_ok_status++) {
|
|
665
|
+
/* search for the best status we can present: ideally the error we use has a
|
|
666
|
+
clearly defined grpc-status, and we'll prefer that. */
|
|
667
|
+
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
668
|
+
if (status[i].is_set &&
|
|
669
|
+
grpc_error_has_clear_grpc_status(status[i].error)) {
|
|
670
|
+
if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
|
|
671
|
+
set_value, set_value_user_data, details)) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
/* If no clearly defined status exists, search for 'anything' */
|
|
677
|
+
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
678
|
+
if (status[i].is_set) {
|
|
679
|
+
if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
|
|
680
|
+
set_value, set_value_user_data, details)) {
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
/* If nothing exists, set some default */
|
|
687
|
+
if (call->is_client) {
|
|
688
|
+
set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
|
|
453
689
|
} else {
|
|
454
|
-
|
|
690
|
+
set_value(GRPC_STATUS_OK, set_value_user_data);
|
|
455
691
|
}
|
|
456
692
|
}
|
|
457
693
|
|
|
458
694
|
static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
|
|
459
695
|
status_source source, grpc_error *error) {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
696
|
+
if (!gpr_atm_rel_cas(&call->status[source],
|
|
697
|
+
pack_received_status((received_status){
|
|
698
|
+
.is_set = false, .error = GRPC_ERROR_NONE}),
|
|
699
|
+
pack_received_status((received_status){
|
|
700
|
+
.is_set = true, .error = error}))) {
|
|
701
|
+
GRPC_ERROR_UNREF(error);
|
|
702
|
+
}
|
|
465
703
|
}
|
|
466
704
|
|
|
705
|
+
/*******************************************************************************
|
|
706
|
+
* COMPRESSION
|
|
707
|
+
*/
|
|
708
|
+
|
|
467
709
|
static void set_incoming_compression_algorithm(
|
|
468
710
|
grpc_call *call, grpc_compression_algorithm algo) {
|
|
469
711
|
GPR_ASSERT(algo < GRPC_COMPRESS_ALGORITHMS_COUNT);
|
|
@@ -496,7 +738,7 @@ uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
|
|
|
496
738
|
static void destroy_encodings_accepted_by_peer(void *p) { return; }
|
|
497
739
|
|
|
498
740
|
static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
|
|
499
|
-
grpc_call *call, grpc_mdelem
|
|
741
|
+
grpc_call *call, grpc_mdelem mdel) {
|
|
500
742
|
size_t i;
|
|
501
743
|
grpc_compression_algorithm algorithm;
|
|
502
744
|
grpc_slice_buffer accept_encoding_parts;
|
|
@@ -511,7 +753,7 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
|
|
|
511
753
|
return;
|
|
512
754
|
}
|
|
513
755
|
|
|
514
|
-
accept_encoding_slice = mdel
|
|
756
|
+
accept_encoding_slice = GRPC_MDVALUE(mdel);
|
|
515
757
|
grpc_slice_buffer_init(&accept_encoding_parts);
|
|
516
758
|
grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
|
|
517
759
|
|
|
@@ -520,15 +762,13 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
|
|
|
520
762
|
/* Always support no compression */
|
|
521
763
|
GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
|
|
522
764
|
for (i = 0; i < accept_encoding_parts.count; i++) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
(const char *)GRPC_SLICE_START_PTR(*accept_encoding_entry_slice),
|
|
527
|
-
GRPC_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
|
|
765
|
+
grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
|
|
766
|
+
if (grpc_compression_algorithm_parse(accept_encoding_entry_slice,
|
|
767
|
+
&algorithm)) {
|
|
528
768
|
GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
|
|
529
769
|
} else {
|
|
530
770
|
char *accept_encoding_entry_str =
|
|
531
|
-
|
|
771
|
+
grpc_slice_to_c_string(accept_encoding_entry_slice);
|
|
532
772
|
gpr_log(GPR_ERROR,
|
|
533
773
|
"Invalid entry in accept encoding metadata: '%s'. Ignoring.",
|
|
534
774
|
accept_encoding_entry_str);
|
|
@@ -539,354 +779,84 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
|
|
|
539
779
|
grpc_slice_buffer_destroy_internal(exec_ctx, &accept_encoding_parts);
|
|
540
780
|
|
|
541
781
|
grpc_mdelem_set_user_data(
|
|
542
|
-
mdel, destroy_encodings_accepted_by_peer,
|
|
543
|
-
(void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
|
|
547
|
-
uint32_t encodings_accepted_by_peer;
|
|
548
|
-
gpr_mu_lock(&call->mu);
|
|
549
|
-
encodings_accepted_by_peer = call->encodings_accepted_by_peer;
|
|
550
|
-
gpr_mu_unlock(&call->mu);
|
|
551
|
-
return encodings_accepted_by_peer;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
static void get_final_details(grpc_call *call, char **out_details,
|
|
555
|
-
size_t *out_details_capacity) {
|
|
556
|
-
int i;
|
|
557
|
-
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
|
558
|
-
if (call->status[i].is_set) {
|
|
559
|
-
if (call->status[i].details) {
|
|
560
|
-
grpc_slice details = call->status[i].details->slice;
|
|
561
|
-
size_t len = GRPC_SLICE_LENGTH(details);
|
|
562
|
-
if (len + 1 > *out_details_capacity) {
|
|
563
|
-
*out_details_capacity =
|
|
564
|
-
GPR_MAX(len + 1, *out_details_capacity * 3 / 2);
|
|
565
|
-
*out_details = gpr_realloc(*out_details, *out_details_capacity);
|
|
566
|
-
}
|
|
567
|
-
memcpy(*out_details, GRPC_SLICE_START_PTR(details), len);
|
|
568
|
-
(*out_details)[len] = 0;
|
|
569
|
-
} else {
|
|
570
|
-
goto no_details;
|
|
571
|
-
}
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
no_details:
|
|
577
|
-
if (0 == *out_details_capacity) {
|
|
578
|
-
*out_details_capacity = 8;
|
|
579
|
-
*out_details = gpr_malloc(*out_details_capacity);
|
|
580
|
-
}
|
|
581
|
-
**out_details = 0;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
|
|
585
|
-
return (grpc_linked_mdelem *)&md->internal_data;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
static grpc_metadata *get_md_elem(grpc_metadata *metadata,
|
|
589
|
-
grpc_metadata *additional_metadata, int i,
|
|
590
|
-
int count) {
|
|
591
|
-
grpc_metadata *res =
|
|
592
|
-
i < count ? &metadata[i] : &additional_metadata[i - count];
|
|
593
|
-
GPR_ASSERT(res);
|
|
594
|
-
return res;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
static int prepare_application_metadata(
|
|
598
|
-
grpc_exec_ctx *exec_ctx, grpc_call *call, int count,
|
|
599
|
-
grpc_metadata *metadata, int is_trailing, int prepend_extra_metadata,
|
|
600
|
-
grpc_metadata *additional_metadata, int additional_metadata_count) {
|
|
601
|
-
int total_count = count + additional_metadata_count;
|
|
602
|
-
int i;
|
|
603
|
-
grpc_metadata_batch *batch =
|
|
604
|
-
&call->metadata_batch[0 /* is_receiving */][is_trailing];
|
|
605
|
-
for (i = 0; i < total_count; i++) {
|
|
606
|
-
const grpc_metadata *md =
|
|
607
|
-
get_md_elem(metadata, additional_metadata, i, count);
|
|
608
|
-
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
|
|
609
|
-
GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
|
|
610
|
-
l->md = grpc_mdelem_from_string_and_buffer(
|
|
611
|
-
exec_ctx, md->key, (const uint8_t *)md->value, md->value_length);
|
|
612
|
-
if (!grpc_header_key_is_legal(grpc_mdstr_as_c_string(l->md->key),
|
|
613
|
-
GRPC_MDSTR_LENGTH(l->md->key))) {
|
|
614
|
-
gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
|
|
615
|
-
grpc_mdstr_as_c_string(l->md->key));
|
|
616
|
-
break;
|
|
617
|
-
} else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
|
|
618
|
-
GRPC_MDSTR_LENGTH(l->md->key)) &&
|
|
619
|
-
!grpc_header_nonbin_value_is_legal(
|
|
620
|
-
grpc_mdstr_as_c_string(l->md->value),
|
|
621
|
-
GRPC_MDSTR_LENGTH(l->md->value))) {
|
|
622
|
-
gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
|
|
623
|
-
break;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
if (i != total_count) {
|
|
627
|
-
for (int j = 0; j <= i; j++) {
|
|
628
|
-
const grpc_metadata *md =
|
|
629
|
-
get_md_elem(metadata, additional_metadata, j, count);
|
|
630
|
-
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
|
|
631
|
-
GRPC_MDELEM_UNREF(exec_ctx, l->md);
|
|
632
|
-
}
|
|
633
|
-
return 0;
|
|
634
|
-
}
|
|
635
|
-
if (prepend_extra_metadata) {
|
|
636
|
-
if (call->send_extra_metadata_count == 0) {
|
|
637
|
-
prepend_extra_metadata = 0;
|
|
638
|
-
} else {
|
|
639
|
-
for (i = 1; i < call->send_extra_metadata_count; i++) {
|
|
640
|
-
call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
|
|
641
|
-
}
|
|
642
|
-
for (i = 0; i < call->send_extra_metadata_count - 1; i++) {
|
|
643
|
-
call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1];
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
for (i = 1; i < total_count; i++) {
|
|
648
|
-
grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
|
|
649
|
-
grpc_metadata *prev_md =
|
|
650
|
-
get_md_elem(metadata, additional_metadata, i - 1, count);
|
|
651
|
-
linked_from_md(md)->prev = linked_from_md(prev_md);
|
|
652
|
-
}
|
|
653
|
-
for (i = 0; i < total_count - 1; i++) {
|
|
654
|
-
grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
|
|
655
|
-
grpc_metadata *next_md =
|
|
656
|
-
get_md_elem(metadata, additional_metadata, i + 1, count);
|
|
657
|
-
linked_from_md(md)->next = linked_from_md(next_md);
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
switch (prepend_extra_metadata * 2 + (total_count != 0)) {
|
|
661
|
-
case 0:
|
|
662
|
-
/* no prepend, no metadata => nothing to do */
|
|
663
|
-
batch->list.head = batch->list.tail = NULL;
|
|
664
|
-
break;
|
|
665
|
-
case 1: {
|
|
666
|
-
/* metadata, but no prepend */
|
|
667
|
-
grpc_metadata *first_md =
|
|
668
|
-
get_md_elem(metadata, additional_metadata, 0, count);
|
|
669
|
-
grpc_metadata *last_md =
|
|
670
|
-
get_md_elem(metadata, additional_metadata, total_count - 1, count);
|
|
671
|
-
batch->list.head = linked_from_md(first_md);
|
|
672
|
-
batch->list.tail = linked_from_md(last_md);
|
|
673
|
-
batch->list.head->prev = NULL;
|
|
674
|
-
batch->list.tail->next = NULL;
|
|
675
|
-
break;
|
|
676
|
-
}
|
|
677
|
-
case 2:
|
|
678
|
-
/* prepend, but no md */
|
|
679
|
-
batch->list.head = &call->send_extra_metadata[0];
|
|
680
|
-
batch->list.tail =
|
|
681
|
-
&call->send_extra_metadata[call->send_extra_metadata_count - 1];
|
|
682
|
-
batch->list.head->prev = NULL;
|
|
683
|
-
batch->list.tail->next = NULL;
|
|
684
|
-
call->send_extra_metadata_count = 0;
|
|
685
|
-
break;
|
|
686
|
-
case 3: {
|
|
687
|
-
/* prepend AND md */
|
|
688
|
-
grpc_metadata *first_md =
|
|
689
|
-
get_md_elem(metadata, additional_metadata, 0, count);
|
|
690
|
-
grpc_metadata *last_md =
|
|
691
|
-
get_md_elem(metadata, additional_metadata, total_count - 1, count);
|
|
692
|
-
batch->list.head = &call->send_extra_metadata[0];
|
|
693
|
-
call->send_extra_metadata[call->send_extra_metadata_count - 1].next =
|
|
694
|
-
linked_from_md(first_md);
|
|
695
|
-
linked_from_md(first_md)->prev =
|
|
696
|
-
&call->send_extra_metadata[call->send_extra_metadata_count - 1];
|
|
697
|
-
batch->list.tail = linked_from_md(last_md);
|
|
698
|
-
batch->list.head->prev = NULL;
|
|
699
|
-
batch->list.tail->next = NULL;
|
|
700
|
-
call->send_extra_metadata_count = 0;
|
|
701
|
-
break;
|
|
702
|
-
}
|
|
703
|
-
default:
|
|
704
|
-
GPR_UNREACHABLE_CODE(return 0);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
return 1;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
void grpc_call_destroy(grpc_call *c) {
|
|
711
|
-
int cancel;
|
|
712
|
-
grpc_call *parent = c->parent;
|
|
713
|
-
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
|
714
|
-
|
|
715
|
-
GPR_TIMER_BEGIN("grpc_call_destroy", 0);
|
|
716
|
-
GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
|
|
717
|
-
|
|
718
|
-
if (parent) {
|
|
719
|
-
gpr_mu_lock(&parent->mu);
|
|
720
|
-
if (c == parent->first_child) {
|
|
721
|
-
parent->first_child = c->sibling_next;
|
|
722
|
-
if (c == parent->first_child) {
|
|
723
|
-
parent->first_child = NULL;
|
|
724
|
-
}
|
|
725
|
-
c->sibling_prev->sibling_next = c->sibling_next;
|
|
726
|
-
c->sibling_next->sibling_prev = c->sibling_prev;
|
|
727
|
-
}
|
|
728
|
-
gpr_mu_unlock(&parent->mu);
|
|
729
|
-
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
gpr_mu_lock(&c->mu);
|
|
733
|
-
GPR_ASSERT(!c->destroy_called);
|
|
734
|
-
c->destroy_called = 1;
|
|
735
|
-
cancel = !c->received_final_op;
|
|
736
|
-
gpr_mu_unlock(&c->mu);
|
|
737
|
-
if (cancel) grpc_call_cancel(c, NULL);
|
|
738
|
-
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
|
|
739
|
-
grpc_exec_ctx_finish(&exec_ctx);
|
|
740
|
-
GPR_TIMER_END("grpc_call_destroy", 0);
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
|
|
744
|
-
GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
|
|
745
|
-
GPR_ASSERT(!reserved);
|
|
746
|
-
return grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Cancelled",
|
|
747
|
-
NULL);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
|
|
751
|
-
grpc_status_code status,
|
|
752
|
-
const char *description,
|
|
753
|
-
void *reserved) {
|
|
754
|
-
grpc_call_error r;
|
|
755
|
-
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
|
756
|
-
GRPC_API_TRACE(
|
|
757
|
-
"grpc_call_cancel_with_status("
|
|
758
|
-
"c=%p, status=%d, description=%s, reserved=%p)",
|
|
759
|
-
4, (c, (int)status, description, reserved));
|
|
760
|
-
GPR_ASSERT(reserved == NULL);
|
|
761
|
-
gpr_mu_lock(&c->mu);
|
|
762
|
-
r = cancel_with_status(&exec_ctx, c, status, description);
|
|
763
|
-
gpr_mu_unlock(&c->mu);
|
|
764
|
-
grpc_exec_ctx_finish(&exec_ctx);
|
|
765
|
-
return r;
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
typedef struct termination_closure {
|
|
769
|
-
grpc_closure closure;
|
|
770
|
-
grpc_call *call;
|
|
771
|
-
grpc_error *error;
|
|
772
|
-
enum { TC_CANCEL, TC_CLOSE } type;
|
|
773
|
-
grpc_transport_stream_op op;
|
|
774
|
-
} termination_closure;
|
|
775
|
-
|
|
776
|
-
static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp,
|
|
777
|
-
grpc_error *error) {
|
|
778
|
-
termination_closure *tc = tcp;
|
|
779
|
-
switch (tc->type) {
|
|
780
|
-
case TC_CANCEL:
|
|
781
|
-
GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "cancel");
|
|
782
|
-
break;
|
|
783
|
-
case TC_CLOSE:
|
|
784
|
-
GRPC_CALL_INTERNAL_UNREF(exec_ctx, tc->call, "close");
|
|
785
|
-
break;
|
|
786
|
-
}
|
|
787
|
-
GRPC_ERROR_UNREF(tc->error);
|
|
788
|
-
gpr_free(tc);
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) {
|
|
792
|
-
termination_closure *tc = tcp;
|
|
793
|
-
memset(&tc->op, 0, sizeof(tc->op));
|
|
794
|
-
tc->op.cancel_error = tc->error;
|
|
795
|
-
/* reuse closure to catch completion */
|
|
796
|
-
grpc_closure_init(&tc->closure, done_termination, tc,
|
|
797
|
-
grpc_schedule_on_exec_ctx);
|
|
798
|
-
tc->op.on_complete = &tc->closure;
|
|
799
|
-
execute_op(exec_ctx, tc->call, &tc->op);
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) {
|
|
803
|
-
termination_closure *tc = tcp;
|
|
804
|
-
memset(&tc->op, 0, sizeof(tc->op));
|
|
805
|
-
tc->op.close_error = tc->error;
|
|
806
|
-
/* reuse closure to catch completion */
|
|
807
|
-
grpc_closure_init(&tc->closure, done_termination, tc,
|
|
808
|
-
grpc_schedule_on_exec_ctx);
|
|
809
|
-
tc->op.on_complete = &tc->closure;
|
|
810
|
-
execute_op(exec_ctx, tc->call, &tc->op);
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
static grpc_call_error terminate_with_status(grpc_exec_ctx *exec_ctx,
|
|
814
|
-
termination_closure *tc) {
|
|
815
|
-
set_status_from_error(exec_ctx, tc->call, STATUS_FROM_API_OVERRIDE,
|
|
816
|
-
tc->error);
|
|
817
|
-
|
|
818
|
-
if (tc->type == TC_CANCEL) {
|
|
819
|
-
grpc_closure_init(&tc->closure, send_cancel, tc, grpc_schedule_on_exec_ctx);
|
|
820
|
-
GRPC_CALL_INTERNAL_REF(tc->call, "cancel");
|
|
821
|
-
} else if (tc->type == TC_CLOSE) {
|
|
822
|
-
grpc_closure_init(&tc->closure, send_close, tc, grpc_schedule_on_exec_ctx);
|
|
823
|
-
GRPC_CALL_INTERNAL_REF(tc->call, "close");
|
|
824
|
-
}
|
|
825
|
-
grpc_closure_sched(exec_ctx, &tc->closure, GRPC_ERROR_NONE);
|
|
826
|
-
return GRPC_CALL_OK;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
|
|
830
|
-
grpc_status_code status,
|
|
831
|
-
const char *description) {
|
|
832
|
-
GPR_ASSERT(status != GRPC_STATUS_OK);
|
|
833
|
-
termination_closure *tc = gpr_malloc(sizeof(*tc));
|
|
834
|
-
memset(tc, 0, sizeof(termination_closure));
|
|
835
|
-
tc->type = TC_CANCEL;
|
|
836
|
-
tc->call = c;
|
|
837
|
-
tc->error = grpc_error_set_int(
|
|
838
|
-
grpc_error_set_str(GRPC_ERROR_CREATE(description),
|
|
839
|
-
GRPC_ERROR_STR_GRPC_MESSAGE, description),
|
|
840
|
-
GRPC_ERROR_INT_GRPC_STATUS, status);
|
|
841
|
-
|
|
842
|
-
return terminate_with_status(exec_ctx, tc);
|
|
782
|
+
mdel, destroy_encodings_accepted_by_peer,
|
|
783
|
+
(void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
|
|
843
784
|
}
|
|
844
785
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
tc->type = TC_CLOSE;
|
|
852
|
-
tc->call = c;
|
|
853
|
-
tc->error = grpc_error_set_int(
|
|
854
|
-
grpc_error_set_str(GRPC_ERROR_CREATE(description),
|
|
855
|
-
GRPC_ERROR_STR_GRPC_MESSAGE, description),
|
|
856
|
-
GRPC_ERROR_INT_GRPC_STATUS, status);
|
|
857
|
-
|
|
858
|
-
return terminate_with_status(exec_ctx, tc);
|
|
786
|
+
uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
|
|
787
|
+
uint32_t encodings_accepted_by_peer;
|
|
788
|
+
gpr_mu_lock(&call->mu);
|
|
789
|
+
encodings_accepted_by_peer = call->encodings_accepted_by_peer;
|
|
790
|
+
gpr_mu_unlock(&call->mu);
|
|
791
|
+
return encodings_accepted_by_peer;
|
|
859
792
|
}
|
|
860
793
|
|
|
861
|
-
static
|
|
862
|
-
|
|
863
|
-
|
|
794
|
+
static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
|
|
795
|
+
return (grpc_linked_mdelem *)&md->internal_data;
|
|
796
|
+
}
|
|
864
797
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
798
|
+
static grpc_metadata *get_md_elem(grpc_metadata *metadata,
|
|
799
|
+
grpc_metadata *additional_metadata, int i,
|
|
800
|
+
int count) {
|
|
801
|
+
grpc_metadata *res =
|
|
802
|
+
i < count ? &metadata[i] : &additional_metadata[i - count];
|
|
803
|
+
GPR_ASSERT(res);
|
|
804
|
+
return res;
|
|
870
805
|
}
|
|
871
806
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
807
|
+
static int prepare_application_metadata(
|
|
808
|
+
grpc_exec_ctx *exec_ctx, grpc_call *call, int count,
|
|
809
|
+
grpc_metadata *metadata, int is_trailing, int prepend_extra_metadata,
|
|
810
|
+
grpc_metadata *additional_metadata, int additional_metadata_count) {
|
|
811
|
+
int total_count = count + additional_metadata_count;
|
|
812
|
+
int i;
|
|
813
|
+
grpc_metadata_batch *batch =
|
|
814
|
+
&call->metadata_batch[0 /* is_receiving */][is_trailing];
|
|
815
|
+
for (i = 0; i < total_count; i++) {
|
|
816
|
+
const grpc_metadata *md =
|
|
817
|
+
get_md_elem(metadata, additional_metadata, i, count);
|
|
818
|
+
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
|
|
819
|
+
GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
|
|
820
|
+
if (!GRPC_LOG_IF_ERROR("validate_metadata",
|
|
821
|
+
grpc_validate_header_key_is_legal(md->key))) {
|
|
822
|
+
break;
|
|
823
|
+
} else if (!grpc_is_binary_header(md->key) &&
|
|
824
|
+
!GRPC_LOG_IF_ERROR(
|
|
825
|
+
"validate_metadata",
|
|
826
|
+
grpc_validate_header_nonbin_value_is_legal(md->value))) {
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
l->md = grpc_mdelem_from_grpc_metadata(exec_ctx, (grpc_metadata *)md);
|
|
880
830
|
}
|
|
881
|
-
if (
|
|
882
|
-
|
|
831
|
+
if (i != total_count) {
|
|
832
|
+
for (int j = 0; j < i; j++) {
|
|
833
|
+
const grpc_metadata *md =
|
|
834
|
+
get_md_elem(metadata, additional_metadata, j, count);
|
|
835
|
+
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
|
|
836
|
+
GRPC_MDELEM_UNREF(exec_ctx, l->md);
|
|
837
|
+
}
|
|
838
|
+
return 0;
|
|
883
839
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
840
|
+
if (prepend_extra_metadata) {
|
|
841
|
+
if (call->send_extra_metadata_count == 0) {
|
|
842
|
+
prepend_extra_metadata = 0;
|
|
843
|
+
} else {
|
|
844
|
+
for (i = 0; i < call->send_extra_metadata_count; i++) {
|
|
845
|
+
GRPC_LOG_IF_ERROR("prepare_application_metadata",
|
|
846
|
+
grpc_metadata_batch_link_tail(
|
|
847
|
+
exec_ctx, batch, &call->send_extra_metadata[i]));
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
for (i = 0; i < total_count; i++) {
|
|
852
|
+
grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
|
|
853
|
+
GRPC_LOG_IF_ERROR(
|
|
854
|
+
"prepare_application_metadata",
|
|
855
|
+
grpc_metadata_batch_link_tail(exec_ctx, batch, linked_from_md(md)));
|
|
856
|
+
}
|
|
857
|
+
call->send_extra_metadata_count = 0;
|
|
887
858
|
|
|
888
|
-
|
|
889
|
-
return CALL_FROM_TOP_ELEM(elem);
|
|
859
|
+
return 1;
|
|
890
860
|
}
|
|
891
861
|
|
|
892
862
|
/* we offset status by a small amount when storing it into transport metadata
|
|
@@ -895,19 +865,17 @@ grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
|
|
|
895
865
|
#define STATUS_OFFSET 1
|
|
896
866
|
static void destroy_status(void *ignored) {}
|
|
897
867
|
|
|
898
|
-
static uint32_t decode_status(grpc_mdelem
|
|
868
|
+
static uint32_t decode_status(grpc_mdelem md) {
|
|
899
869
|
uint32_t status;
|
|
900
870
|
void *user_data;
|
|
901
|
-
if (md
|
|
902
|
-
if (md
|
|
903
|
-
if (md
|
|
871
|
+
if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) return 0;
|
|
872
|
+
if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_1)) return 1;
|
|
873
|
+
if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_2)) return 2;
|
|
904
874
|
user_data = grpc_mdelem_get_user_data(md, destroy_status);
|
|
905
875
|
if (user_data != NULL) {
|
|
906
876
|
status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
|
|
907
877
|
} else {
|
|
908
|
-
if (!
|
|
909
|
-
GRPC_SLICE_LENGTH(md->value->slice),
|
|
910
|
-
&status)) {
|
|
878
|
+
if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(md), &status)) {
|
|
911
879
|
status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
|
|
912
880
|
}
|
|
913
881
|
grpc_mdelem_set_user_data(md, destroy_status,
|
|
@@ -916,93 +884,104 @@ static uint32_t decode_status(grpc_mdelem *md) {
|
|
|
916
884
|
return status;
|
|
917
885
|
}
|
|
918
886
|
|
|
919
|
-
static grpc_compression_algorithm decode_compression(grpc_mdelem
|
|
887
|
+
static grpc_compression_algorithm decode_compression(grpc_mdelem md) {
|
|
920
888
|
grpc_compression_algorithm algorithm =
|
|
921
|
-
|
|
889
|
+
grpc_compression_algorithm_from_slice(GRPC_MDVALUE(md));
|
|
922
890
|
if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
|
|
923
|
-
|
|
891
|
+
char *md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
|
|
924
892
|
gpr_log(GPR_ERROR,
|
|
925
893
|
"Invalid incoming compression algorithm: '%s'. Interpreting "
|
|
926
894
|
"incoming data as uncompressed.",
|
|
927
895
|
md_c_str);
|
|
896
|
+
gpr_free(md_c_str);
|
|
928
897
|
return GRPC_COMPRESS_NONE;
|
|
929
898
|
}
|
|
930
899
|
return algorithm;
|
|
931
900
|
}
|
|
932
901
|
|
|
933
|
-
static
|
|
934
|
-
|
|
935
|
-
if (
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
902
|
+
static void recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
|
|
903
|
+
grpc_metadata_batch *b) {
|
|
904
|
+
if (b->idx.named.grpc_status != NULL) {
|
|
905
|
+
uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
|
|
906
|
+
grpc_error *error =
|
|
907
|
+
status_code == GRPC_STATUS_OK
|
|
908
|
+
? GRPC_ERROR_NONE
|
|
909
|
+
: grpc_error_set_int(GRPC_ERROR_CREATE("Error received from peer"),
|
|
910
|
+
GRPC_ERROR_INT_GRPC_STATUS,
|
|
911
|
+
(intptr_t)status_code);
|
|
912
|
+
|
|
913
|
+
if (b->idx.named.grpc_message != NULL) {
|
|
914
|
+
char *msg =
|
|
915
|
+
grpc_slice_to_c_string(GRPC_MDVALUE(b->idx.named.grpc_message->md));
|
|
916
|
+
error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, msg);
|
|
917
|
+
gpr_free(msg);
|
|
918
|
+
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message);
|
|
919
|
+
} else if (error != GRPC_ERROR_NONE) {
|
|
920
|
+
error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "");
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error);
|
|
924
|
+
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status);
|
|
946
925
|
}
|
|
947
|
-
return elem;
|
|
948
926
|
}
|
|
949
927
|
|
|
950
|
-
static
|
|
951
|
-
|
|
928
|
+
static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
|
|
929
|
+
int is_trailing) {
|
|
930
|
+
if (b->list.count == 0) return;
|
|
931
|
+
GPR_TIMER_BEGIN("publish_app_metadata", 0);
|
|
952
932
|
grpc_metadata_array *dest;
|
|
953
933
|
grpc_metadata *mdusr;
|
|
954
|
-
GPR_TIMER_BEGIN("publish_app_metadata", 0);
|
|
955
934
|
dest = call->buffered_metadata[is_trailing];
|
|
956
|
-
if (dest->count
|
|
957
|
-
dest->capacity =
|
|
935
|
+
if (dest->count + b->list.count > dest->capacity) {
|
|
936
|
+
dest->capacity =
|
|
937
|
+
GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2);
|
|
958
938
|
dest->metadata =
|
|
959
939
|
gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
|
|
960
940
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
941
|
+
for (grpc_linked_mdelem *l = b->list.head; l != NULL; l = l->next) {
|
|
942
|
+
mdusr = &dest->metadata[dest->count++];
|
|
943
|
+
/* we pass back borrowed slices that are valid whilst the call is valid */
|
|
944
|
+
mdusr->key = GRPC_MDKEY(l->md);
|
|
945
|
+
mdusr->value = GRPC_MDVALUE(l->md);
|
|
946
|
+
}
|
|
965
947
|
GPR_TIMER_END("publish_app_metadata", 0);
|
|
966
|
-
return elem;
|
|
967
948
|
}
|
|
968
949
|
|
|
969
|
-
static
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
if (
|
|
974
|
-
return NULL;
|
|
975
|
-
} else if (elem->key == GRPC_MDSTR_GRPC_ENCODING) {
|
|
950
|
+
static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
|
|
951
|
+
grpc_metadata_batch *b) {
|
|
952
|
+
recv_common_filter(exec_ctx, call, b);
|
|
953
|
+
|
|
954
|
+
if (b->idx.named.grpc_encoding != NULL) {
|
|
976
955
|
GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
|
|
977
|
-
set_incoming_compression_algorithm(
|
|
956
|
+
set_incoming_compression_algorithm(
|
|
957
|
+
call, decode_compression(b->idx.named.grpc_encoding->md));
|
|
978
958
|
GPR_TIMER_END("incoming_compression_algorithm", 0);
|
|
979
|
-
|
|
980
|
-
}
|
|
959
|
+
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding);
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
if (b->idx.named.grpc_accept_encoding != NULL) {
|
|
981
963
|
GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
|
|
982
|
-
set_encodings_accepted_by_peer(exec_ctx, call,
|
|
964
|
+
set_encodings_accepted_by_peer(exec_ctx, call,
|
|
965
|
+
b->idx.named.grpc_accept_encoding->md);
|
|
966
|
+
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding);
|
|
983
967
|
GPR_TIMER_END("encodings_accepted_by_peer", 0);
|
|
984
|
-
return NULL;
|
|
985
|
-
} else {
|
|
986
|
-
return publish_app_metadata(call, elem, 0);
|
|
987
968
|
}
|
|
969
|
+
|
|
970
|
+
publish_app_metadata(call, b, false);
|
|
988
971
|
}
|
|
989
972
|
|
|
990
|
-
static
|
|
991
|
-
|
|
973
|
+
static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args,
|
|
974
|
+
grpc_metadata_batch *b) {
|
|
992
975
|
grpc_call *call = args;
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
return NULL;
|
|
996
|
-
} else {
|
|
997
|
-
return publish_app_metadata(call, elem, 1);
|
|
998
|
-
}
|
|
976
|
+
recv_common_filter(exec_ctx, call, b);
|
|
977
|
+
publish_app_metadata(call, b, true);
|
|
999
978
|
}
|
|
1000
979
|
|
|
1001
980
|
grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
|
|
1002
981
|
return CALL_STACK_FROM_CALL(call);
|
|
1003
982
|
}
|
|
1004
983
|
|
|
1005
|
-
|
|
984
|
+
/*******************************************************************************
|
|
1006
985
|
* BATCH API IMPLEMENTATION
|
|
1007
986
|
*/
|
|
1008
987
|
|
|
@@ -1031,44 +1010,132 @@ static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
|
|
|
1031
1010
|
return !(flags & invalid_positions);
|
|
1032
1011
|
}
|
|
1033
1012
|
|
|
1034
|
-
static
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
return
|
|
1040
|
-
|
|
1013
|
+
static int batch_slot_for_op(grpc_op_type type) {
|
|
1014
|
+
switch (type) {
|
|
1015
|
+
case GRPC_OP_SEND_INITIAL_METADATA:
|
|
1016
|
+
return 0;
|
|
1017
|
+
case GRPC_OP_SEND_MESSAGE:
|
|
1018
|
+
return 1;
|
|
1019
|
+
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
|
|
1020
|
+
case GRPC_OP_SEND_STATUS_FROM_SERVER:
|
|
1021
|
+
return 2;
|
|
1022
|
+
case GRPC_OP_RECV_INITIAL_METADATA:
|
|
1023
|
+
return 3;
|
|
1024
|
+
case GRPC_OP_RECV_MESSAGE:
|
|
1025
|
+
return 4;
|
|
1026
|
+
case GRPC_OP_RECV_CLOSE_ON_SERVER:
|
|
1027
|
+
case GRPC_OP_RECV_STATUS_ON_CLIENT:
|
|
1028
|
+
return 5;
|
|
1029
|
+
}
|
|
1030
|
+
GPR_UNREACHABLE_CODE(return 123456789);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
static batch_control *allocate_batch_control(grpc_call *call,
|
|
1034
|
+
const grpc_op *ops,
|
|
1035
|
+
size_t num_ops) {
|
|
1036
|
+
int slot = batch_slot_for_op(ops[0].op);
|
|
1037
|
+
for (size_t i = 1; i < num_ops; i++) {
|
|
1038
|
+
int op_slot = batch_slot_for_op(ops[i].op);
|
|
1039
|
+
slot = GPR_MIN(slot, op_slot);
|
|
1040
|
+
}
|
|
1041
|
+
batch_control *bctl = &call->active_batches[slot];
|
|
1042
|
+
if (bctl->call != NULL) {
|
|
1043
|
+
return NULL;
|
|
1041
1044
|
}
|
|
1042
|
-
|
|
1045
|
+
memset(bctl, 0, sizeof(*bctl));
|
|
1046
|
+
bctl->call = call;
|
|
1047
|
+
return bctl;
|
|
1043
1048
|
}
|
|
1044
1049
|
|
|
1045
1050
|
static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
|
|
1046
1051
|
grpc_cq_completion *storage) {
|
|
1047
1052
|
batch_control *bctl = user_data;
|
|
1048
1053
|
grpc_call *call = bctl->call;
|
|
1049
|
-
|
|
1050
|
-
call->used_batches = (uint8_t)(
|
|
1051
|
-
call->used_batches & ~(uint8_t)(1 << (bctl - call->active_batches)));
|
|
1052
|
-
gpr_mu_unlock(&call->mu);
|
|
1054
|
+
bctl->call = NULL;
|
|
1053
1055
|
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
|
|
1054
1056
|
}
|
|
1055
1057
|
|
|
1058
|
+
static grpc_error *consolidate_batch_errors(batch_control *bctl) {
|
|
1059
|
+
size_t n = (size_t)gpr_atm_no_barrier_load(&bctl->num_errors);
|
|
1060
|
+
if (n == 0) {
|
|
1061
|
+
return GRPC_ERROR_NONE;
|
|
1062
|
+
} else if (n == 1) {
|
|
1063
|
+
/* Skip creating a composite error in the case that only one error was
|
|
1064
|
+
logged */
|
|
1065
|
+
grpc_error *e = bctl->errors[0];
|
|
1066
|
+
bctl->errors[0] = NULL;
|
|
1067
|
+
return e;
|
|
1068
|
+
} else {
|
|
1069
|
+
grpc_error *error =
|
|
1070
|
+
GRPC_ERROR_CREATE_REFERENCING("Call batch failed", bctl->errors, n);
|
|
1071
|
+
for (size_t i = 0; i < n; i++) {
|
|
1072
|
+
GRPC_ERROR_UNREF(bctl->errors[i]);
|
|
1073
|
+
bctl->errors[i] = NULL;
|
|
1074
|
+
}
|
|
1075
|
+
return error;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1056
1079
|
static void post_batch_completion(grpc_exec_ctx *exec_ctx,
|
|
1057
1080
|
batch_control *bctl) {
|
|
1081
|
+
grpc_call *child_call;
|
|
1082
|
+
grpc_call *next_child_call;
|
|
1058
1083
|
grpc_call *call = bctl->call;
|
|
1059
|
-
grpc_error *error = bctl
|
|
1084
|
+
grpc_error *error = consolidate_batch_errors(bctl);
|
|
1085
|
+
|
|
1086
|
+
gpr_mu_lock(&call->mu);
|
|
1087
|
+
|
|
1088
|
+
if (bctl->send_initial_metadata) {
|
|
1089
|
+
grpc_metadata_batch_destroy(
|
|
1090
|
+
exec_ctx,
|
|
1091
|
+
&call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
|
|
1092
|
+
}
|
|
1093
|
+
if (bctl->send_message) {
|
|
1094
|
+
call->sending_message = false;
|
|
1095
|
+
}
|
|
1096
|
+
if (bctl->send_final_op) {
|
|
1097
|
+
grpc_metadata_batch_destroy(
|
|
1098
|
+
exec_ctx,
|
|
1099
|
+
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
|
|
1100
|
+
}
|
|
1060
1101
|
if (bctl->recv_final_op) {
|
|
1102
|
+
grpc_metadata_batch *md =
|
|
1103
|
+
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
|
|
1104
|
+
recv_trailing_filter(exec_ctx, call, md);
|
|
1105
|
+
|
|
1106
|
+
call->received_final_op = true;
|
|
1107
|
+
/* propagate cancellation to any interested children */
|
|
1108
|
+
child_call = call->first_child;
|
|
1109
|
+
if (child_call != NULL) {
|
|
1110
|
+
do {
|
|
1111
|
+
next_child_call = child_call->sibling_next;
|
|
1112
|
+
if (child_call->cancellation_is_inherited) {
|
|
1113
|
+
GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
|
|
1114
|
+
grpc_call_cancel(child_call, NULL);
|
|
1115
|
+
GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
|
|
1116
|
+
}
|
|
1117
|
+
child_call = next_child_call;
|
|
1118
|
+
} while (child_call != call->first_child);
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
if (call->is_client) {
|
|
1122
|
+
get_final_status(call, set_status_value_directly,
|
|
1123
|
+
call->final_op.client.status,
|
|
1124
|
+
call->final_op.client.status_details);
|
|
1125
|
+
} else {
|
|
1126
|
+
get_final_status(call, set_cancelled_value,
|
|
1127
|
+
call->final_op.server.cancelled, NULL);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1061
1130
|
GRPC_ERROR_UNREF(error);
|
|
1062
1131
|
error = GRPC_ERROR_NONE;
|
|
1063
1132
|
}
|
|
1133
|
+
gpr_mu_unlock(&call->mu);
|
|
1134
|
+
|
|
1064
1135
|
if (bctl->is_notify_tag_closure) {
|
|
1065
1136
|
/* unrefs bctl->error */
|
|
1137
|
+
bctl->call = NULL;
|
|
1066
1138
|
grpc_closure_run(exec_ctx, bctl->notify_tag, error);
|
|
1067
|
-
gpr_mu_lock(&call->mu);
|
|
1068
|
-
bctl->call->used_batches =
|
|
1069
|
-
(uint8_t)(bctl->call->used_batches &
|
|
1070
|
-
~(uint8_t)(1 << (bctl - bctl->call->active_batches)));
|
|
1071
|
-
gpr_mu_unlock(&call->mu);
|
|
1072
1139
|
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
|
|
1073
1140
|
} else {
|
|
1074
1141
|
/* unrefs bctl->error */
|
|
@@ -1077,6 +1144,12 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
|
|
|
1077
1144
|
}
|
|
1078
1145
|
}
|
|
1079
1146
|
|
|
1147
|
+
static void finish_batch_step(grpc_exec_ctx *exec_ctx, batch_control *bctl) {
|
|
1148
|
+
if (gpr_unref(&bctl->steps_to_complete)) {
|
|
1149
|
+
post_batch_completion(exec_ctx, bctl);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1080
1153
|
static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
|
|
1081
1154
|
batch_control *bctl) {
|
|
1082
1155
|
grpc_call *call = bctl->call;
|
|
@@ -1087,9 +1160,7 @@ static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
|
|
|
1087
1160
|
call->receiving_message = 0;
|
|
1088
1161
|
grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
|
|
1089
1162
|
call->receiving_stream = NULL;
|
|
1090
|
-
|
|
1091
|
-
post_batch_completion(exec_ctx, bctl);
|
|
1092
|
-
}
|
|
1163
|
+
finish_batch_step(exec_ctx, bctl);
|
|
1093
1164
|
return;
|
|
1094
1165
|
}
|
|
1095
1166
|
if (grpc_byte_stream_next(exec_ctx, call->receiving_stream,
|
|
@@ -1120,9 +1191,7 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
|
|
|
1120
1191
|
call->receiving_stream = NULL;
|
|
1121
1192
|
grpc_byte_buffer_destroy(*call->receiving_buffer);
|
|
1122
1193
|
*call->receiving_buffer = NULL;
|
|
1123
|
-
|
|
1124
|
-
post_batch_completion(exec_ctx, bctl);
|
|
1125
|
-
}
|
|
1194
|
+
finish_batch_step(exec_ctx, bctl);
|
|
1126
1195
|
}
|
|
1127
1196
|
}
|
|
1128
1197
|
|
|
@@ -1132,9 +1201,7 @@ static void process_data_after_md(grpc_exec_ctx *exec_ctx,
|
|
|
1132
1201
|
if (call->receiving_stream == NULL) {
|
|
1133
1202
|
*call->receiving_buffer = NULL;
|
|
1134
1203
|
call->receiving_message = 0;
|
|
1135
|
-
|
|
1136
|
-
post_batch_completion(exec_ctx, bctl);
|
|
1137
|
-
}
|
|
1204
|
+
finish_batch_step(exec_ctx, bctl);
|
|
1138
1205
|
} else {
|
|
1139
1206
|
call->test_only_last_message_flags = call->receiving_stream->flags;
|
|
1140
1207
|
if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&
|
|
@@ -1154,14 +1221,17 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
|
|
|
1154
1221
|
grpc_error *error) {
|
|
1155
1222
|
batch_control *bctl = bctlp;
|
|
1156
1223
|
grpc_call *call = bctl->call;
|
|
1224
|
+
gpr_mu_lock(&bctl->call->mu);
|
|
1157
1225
|
if (error != GRPC_ERROR_NONE) {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1226
|
+
if (call->receiving_stream != NULL) {
|
|
1227
|
+
grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
|
|
1228
|
+
call->receiving_stream = NULL;
|
|
1229
|
+
}
|
|
1230
|
+
add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), true);
|
|
1231
|
+
cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
|
|
1232
|
+
GRPC_ERROR_REF(error));
|
|
1162
1233
|
}
|
|
1163
|
-
|
|
1164
|
-
if (bctl->call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
|
|
1234
|
+
if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
|
|
1165
1235
|
call->receiving_stream == NULL) {
|
|
1166
1236
|
gpr_mu_unlock(&bctl->call->mu);
|
|
1167
1237
|
process_data_after_md(exec_ctx, bctlp);
|
|
@@ -1186,7 +1256,8 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
|
|
|
1186
1256
|
gpr_asprintf(&error_msg, "Invalid compression algorithm value '%d'.",
|
|
1187
1257
|
algo);
|
|
1188
1258
|
gpr_log(GPR_ERROR, "%s", error_msg);
|
|
1189
|
-
|
|
1259
|
+
cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
|
|
1260
|
+
GRPC_STATUS_UNIMPLEMENTED, error_msg);
|
|
1190
1261
|
} else if (grpc_compression_options_is_algorithm_enabled(
|
|
1191
1262
|
&compression_options, algo) == 0) {
|
|
1192
1263
|
/* check if algorithm is supported by current channel config */
|
|
@@ -1195,7 +1266,8 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
|
|
|
1195
1266
|
gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.",
|
|
1196
1267
|
algo_name);
|
|
1197
1268
|
gpr_log(GPR_ERROR, "%s", error_msg);
|
|
1198
|
-
|
|
1269
|
+
cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
|
|
1270
|
+
GRPC_STATUS_UNIMPLEMENTED, error_msg);
|
|
1199
1271
|
} else {
|
|
1200
1272
|
call->incoming_compression_algorithm = algo;
|
|
1201
1273
|
}
|
|
@@ -1221,12 +1293,15 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
|
|
|
1221
1293
|
}
|
|
1222
1294
|
}
|
|
1223
1295
|
|
|
1224
|
-
static void add_batch_error(
|
|
1296
|
+
static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
|
|
1297
|
+
grpc_error *error, bool has_cancelled) {
|
|
1225
1298
|
if (error == GRPC_ERROR_NONE) return;
|
|
1226
|
-
|
|
1227
|
-
|
|
1299
|
+
int idx = (int)gpr_atm_no_barrier_fetch_add(&bctl->num_errors, 1);
|
|
1300
|
+
if (idx == 0 && !has_cancelled) {
|
|
1301
|
+
cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE,
|
|
1302
|
+
GRPC_ERROR_REF(error));
|
|
1228
1303
|
}
|
|
1229
|
-
bctl->
|
|
1304
|
+
bctl->errors[idx] = error;
|
|
1230
1305
|
}
|
|
1231
1306
|
|
|
1232
1307
|
static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
|
|
@@ -1236,12 +1311,13 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
|
|
|
1236
1311
|
|
|
1237
1312
|
gpr_mu_lock(&call->mu);
|
|
1238
1313
|
|
|
1239
|
-
add_batch_error(bctl, GRPC_ERROR_REF(error));
|
|
1314
|
+
add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
|
|
1240
1315
|
if (error == GRPC_ERROR_NONE) {
|
|
1241
1316
|
grpc_metadata_batch *md =
|
|
1242
1317
|
&call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
|
|
1243
|
-
|
|
1318
|
+
recv_initial_filter(exec_ctx, call, md);
|
|
1244
1319
|
|
|
1320
|
+
/* TODO(ctiller): this could be moved into recv_initial_filter now */
|
|
1245
1321
|
GPR_TIMER_BEGIN("validate_filtered_metadata", 0);
|
|
1246
1322
|
validate_filtered_metadata(exec_ctx, bctl);
|
|
1247
1323
|
GPR_TIMER_END("validate_filtered_metadata", 0);
|
|
@@ -1260,90 +1336,25 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
|
|
|
1260
1336
|
receiving_stream_ready, call->saved_receiving_stream_ready_bctlp,
|
|
1261
1337
|
grpc_schedule_on_exec_ctx);
|
|
1262
1338
|
call->saved_receiving_stream_ready_bctlp = NULL;
|
|
1263
|
-
grpc_closure_sched(exec_ctx, saved_rsr_closure, error);
|
|
1339
|
+
grpc_closure_sched(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error));
|
|
1264
1340
|
}
|
|
1265
1341
|
|
|
1266
1342
|
gpr_mu_unlock(&call->mu);
|
|
1267
1343
|
|
|
1268
|
-
|
|
1269
|
-
post_batch_completion(exec_ctx, bctl);
|
|
1270
|
-
}
|
|
1344
|
+
finish_batch_step(exec_ctx, bctl);
|
|
1271
1345
|
}
|
|
1272
1346
|
|
|
1273
1347
|
static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
|
|
1274
1348
|
grpc_error *error) {
|
|
1275
1349
|
batch_control *bctl = bctlp;
|
|
1276
|
-
grpc_call *call = bctl->call;
|
|
1277
|
-
grpc_call *child_call;
|
|
1278
|
-
grpc_call *next_child_call;
|
|
1279
|
-
|
|
1280
|
-
GRPC_ERROR_REF(error);
|
|
1281
|
-
|
|
1282
|
-
gpr_mu_lock(&call->mu);
|
|
1283
|
-
|
|
1284
|
-
// If the error has an associated status code, set the call's status.
|
|
1285
|
-
intptr_t status;
|
|
1286
|
-
if (error != GRPC_ERROR_NONE &&
|
|
1287
|
-
grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status)) {
|
|
1288
|
-
set_status_from_error(exec_ctx, call, STATUS_FROM_CORE, error);
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
if (bctl->send_initial_metadata) {
|
|
1292
|
-
if (error != GRPC_ERROR_NONE) {
|
|
1293
|
-
set_status_from_error(exec_ctx, call, STATUS_FROM_CORE, error);
|
|
1294
|
-
}
|
|
1295
|
-
grpc_metadata_batch_destroy(
|
|
1296
|
-
exec_ctx,
|
|
1297
|
-
&call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
|
|
1298
|
-
}
|
|
1299
|
-
if (bctl->send_message) {
|
|
1300
|
-
call->sending_message = 0;
|
|
1301
|
-
}
|
|
1302
|
-
if (bctl->send_final_op) {
|
|
1303
|
-
grpc_metadata_batch_destroy(
|
|
1304
|
-
exec_ctx,
|
|
1305
|
-
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
|
|
1306
|
-
}
|
|
1307
|
-
if (bctl->recv_final_op) {
|
|
1308
|
-
grpc_metadata_batch *md =
|
|
1309
|
-
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
|
|
1310
|
-
grpc_metadata_batch_filter(exec_ctx, md, recv_trailing_filter, call);
|
|
1311
|
-
|
|
1312
|
-
call->received_final_op = true;
|
|
1313
|
-
/* propagate cancellation to any interested children */
|
|
1314
|
-
child_call = call->first_child;
|
|
1315
|
-
if (child_call != NULL) {
|
|
1316
|
-
do {
|
|
1317
|
-
next_child_call = child_call->sibling_next;
|
|
1318
|
-
if (child_call->cancellation_is_inherited) {
|
|
1319
|
-
GRPC_CALL_INTERNAL_REF(child_call, "propagate_cancel");
|
|
1320
|
-
grpc_call_cancel(child_call, NULL);
|
|
1321
|
-
GRPC_CALL_INTERNAL_UNREF(exec_ctx, child_call, "propagate_cancel");
|
|
1322
|
-
}
|
|
1323
|
-
child_call = next_child_call;
|
|
1324
|
-
} while (child_call != call->first_child);
|
|
1325
|
-
}
|
|
1326
1350
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
get_final_details(call, call->final_op.client.status_details,
|
|
1331
|
-
call->final_op.client.status_details_capacity);
|
|
1332
|
-
} else {
|
|
1333
|
-
get_final_status(call, set_cancelled_value,
|
|
1334
|
-
call->final_op.server.cancelled);
|
|
1335
|
-
}
|
|
1336
|
-
|
|
1337
|
-
GRPC_ERROR_UNREF(error);
|
|
1338
|
-
error = GRPC_ERROR_NONE;
|
|
1339
|
-
}
|
|
1340
|
-
add_batch_error(bctl, GRPC_ERROR_REF(error));
|
|
1341
|
-
gpr_mu_unlock(&call->mu);
|
|
1342
|
-
if (gpr_unref(&bctl->steps_to_complete)) {
|
|
1343
|
-
post_batch_completion(exec_ctx, bctl);
|
|
1344
|
-
}
|
|
1351
|
+
add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
|
|
1352
|
+
finish_batch_step(exec_ctx, bctl);
|
|
1353
|
+
}
|
|
1345
1354
|
|
|
1346
|
-
|
|
1355
|
+
static void free_no_op_completion(grpc_exec_ctx *exec_ctx, void *p,
|
|
1356
|
+
grpc_cq_completion *completion) {
|
|
1357
|
+
gpr_free(completion);
|
|
1347
1358
|
}
|
|
1348
1359
|
|
|
1349
1360
|
static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
|
|
@@ -1360,33 +1371,33 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
|
|
|
1360
1371
|
grpc_metadata compression_md;
|
|
1361
1372
|
|
|
1362
1373
|
GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
|
|
1363
|
-
|
|
1364
1374
|
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
|
|
1365
1375
|
|
|
1366
|
-
/* TODO(ctiller): this feels like it could be made lock-free */
|
|
1367
|
-
gpr_mu_lock(&call->mu);
|
|
1368
|
-
bctl = allocate_batch_control(call);
|
|
1369
|
-
memset(bctl, 0, sizeof(*bctl));
|
|
1370
|
-
bctl->call = call;
|
|
1371
|
-
bctl->notify_tag = notify_tag;
|
|
1372
|
-
bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
|
|
1373
|
-
|
|
1374
|
-
grpc_transport_stream_op *stream_op = &bctl->op;
|
|
1375
|
-
memset(stream_op, 0, sizeof(*stream_op));
|
|
1376
|
-
stream_op->covered_by_poller = true;
|
|
1377
|
-
|
|
1378
1376
|
if (nops == 0) {
|
|
1379
|
-
GRPC_CALL_INTERNAL_REF(call, "completion");
|
|
1380
|
-
bctl->error = GRPC_ERROR_NONE;
|
|
1381
1377
|
if (!is_notify_tag_closure) {
|
|
1382
1378
|
grpc_cq_begin_op(call->cq, notify_tag);
|
|
1379
|
+
grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
|
|
1380
|
+
free_no_op_completion, NULL,
|
|
1381
|
+
gpr_malloc(sizeof(grpc_cq_completion)));
|
|
1382
|
+
} else {
|
|
1383
|
+
grpc_closure_sched(exec_ctx, notify_tag, GRPC_ERROR_NONE);
|
|
1383
1384
|
}
|
|
1384
|
-
gpr_mu_unlock(&call->mu);
|
|
1385
|
-
post_batch_completion(exec_ctx, bctl);
|
|
1386
1385
|
error = GRPC_CALL_OK;
|
|
1387
1386
|
goto done;
|
|
1388
1387
|
}
|
|
1389
1388
|
|
|
1389
|
+
bctl = allocate_batch_control(call, ops, nops);
|
|
1390
|
+
if (bctl == NULL) {
|
|
1391
|
+
return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
|
|
1392
|
+
}
|
|
1393
|
+
bctl->notify_tag = notify_tag;
|
|
1394
|
+
bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
|
|
1395
|
+
|
|
1396
|
+
gpr_mu_lock(&call->mu);
|
|
1397
|
+
grpc_transport_stream_op *stream_op = &bctl->op;
|
|
1398
|
+
memset(stream_op, 0, sizeof(*stream_op));
|
|
1399
|
+
stream_op->covered_by_poller = true;
|
|
1400
|
+
|
|
1390
1401
|
/* rewrite batch ops into a transport op */
|
|
1391
1402
|
for (i = 0; i < nops; i++) {
|
|
1392
1403
|
op = &ops[i];
|
|
@@ -1426,13 +1437,10 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
|
|
|
1426
1437
|
const grpc_compression_algorithm calgo =
|
|
1427
1438
|
compression_algorithm_for_level_locked(
|
|
1428
1439
|
call, effective_compression_level);
|
|
1429
|
-
char *calgo_name = NULL;
|
|
1430
|
-
grpc_compression_algorithm_name(calgo, &calgo_name);
|
|
1431
1440
|
// the following will be picked up by the compress filter and used as
|
|
1432
1441
|
// the call's compression algorithm.
|
|
1433
|
-
compression_md.key =
|
|
1434
|
-
compression_md.value =
|
|
1435
|
-
compression_md.value_length = strlen(calgo_name);
|
|
1442
|
+
compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
|
|
1443
|
+
compression_md.value = grpc_compression_algorithm_slice(calgo);
|
|
1436
1444
|
additional_metadata_count++;
|
|
1437
1445
|
}
|
|
1438
1446
|
|
|
@@ -1524,28 +1532,39 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
|
|
|
1524
1532
|
}
|
|
1525
1533
|
bctl->send_final_op = 1;
|
|
1526
1534
|
call->sent_final_op = 1;
|
|
1535
|
+
GPR_ASSERT(call->send_extra_metadata_count == 0);
|
|
1527
1536
|
call->send_extra_metadata_count = 1;
|
|
1528
1537
|
call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
|
|
1529
1538
|
exec_ctx, call->channel, op->data.send_status_from_server.status);
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1539
|
+
{
|
|
1540
|
+
grpc_error *override_error = GRPC_ERROR_NONE;
|
|
1541
|
+
if (op->data.send_status_from_server.status != GRPC_STATUS_OK) {
|
|
1542
|
+
override_error = GRPC_ERROR_CREATE("Error from server send status");
|
|
1543
|
+
}
|
|
1544
|
+
if (op->data.send_status_from_server.status_details != NULL) {
|
|
1545
|
+
call->send_extra_metadata[1].md = grpc_mdelem_from_slices(
|
|
1546
|
+
exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
|
|
1547
|
+
grpc_slice_ref_internal(
|
|
1548
|
+
*op->data.send_status_from_server.status_details));
|
|
1549
|
+
call->send_extra_metadata_count++;
|
|
1550
|
+
char *msg = grpc_slice_to_c_string(
|
|
1551
|
+
GRPC_MDVALUE(call->send_extra_metadata[1].md));
|
|
1552
|
+
override_error = grpc_error_set_str(
|
|
1553
|
+
override_error, GRPC_ERROR_STR_GRPC_MESSAGE, msg);
|
|
1554
|
+
gpr_free(msg);
|
|
1555
|
+
}
|
|
1556
|
+
set_status_from_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE,
|
|
1557
|
+
override_error);
|
|
1543
1558
|
}
|
|
1544
1559
|
if (!prepare_application_metadata(
|
|
1545
1560
|
exec_ctx, call,
|
|
1546
1561
|
(int)op->data.send_status_from_server.trailing_metadata_count,
|
|
1547
1562
|
op->data.send_status_from_server.trailing_metadata, 1, 1, NULL,
|
|
1548
1563
|
0)) {
|
|
1564
|
+
for (int n = 0; n < call->send_extra_metadata_count; n++) {
|
|
1565
|
+
GRPC_MDELEM_UNREF(exec_ctx, call->send_extra_metadata[n].md);
|
|
1566
|
+
}
|
|
1567
|
+
call->send_extra_metadata_count = 0;
|
|
1549
1568
|
error = GRPC_CALL_ERROR_INVALID_METADATA;
|
|
1550
1569
|
goto done_with_error;
|
|
1551
1570
|
}
|
|
@@ -1618,8 +1637,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
|
|
|
1618
1637
|
call->final_op.client.status = op->data.recv_status_on_client.status;
|
|
1619
1638
|
call->final_op.client.status_details =
|
|
1620
1639
|
op->data.recv_status_on_client.status_details;
|
|
1621
|
-
call->final_op.client.status_details_capacity =
|
|
1622
|
-
op->data.recv_status_on_client.status_details_capacity;
|
|
1623
1640
|
bctl->recv_final_op = 1;
|
|
1624
1641
|
stream_op->recv_trailing_metadata =
|
|
1625
1642
|
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
|
|
@@ -1662,6 +1679,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
|
|
|
1662
1679
|
grpc_closure_init(&bctl->finish_batch, finish_batch, bctl,
|
|
1663
1680
|
grpc_schedule_on_exec_ctx);
|
|
1664
1681
|
stream_op->on_complete = &bctl->finish_batch;
|
|
1682
|
+
call->sent_any_op = true;
|
|
1665
1683
|
gpr_mu_unlock(&call->mu);
|
|
1666
1684
|
|
|
1667
1685
|
execute_op(exec_ctx, call, stream_op);
|