grpc 1.20.0 → 1.21.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +500 -29
  3. data/etc/roots.pem +146 -0
  4. data/include/grpc/grpc_security.h +1 -1
  5. data/include/grpc/impl/codegen/grpc_types.h +10 -7
  6. data/include/grpc/impl/codegen/port_platform.h +11 -1
  7. data/include/grpc/impl/codegen/slice.h +1 -21
  8. data/include/grpc/impl/codegen/status.h +2 -1
  9. data/include/grpc/slice.h +1 -1
  10. data/src/core/ext/filters/client_channel/backup_poller.cc +19 -13
  11. data/src/core/ext/filters/client_channel/backup_poller.h +3 -0
  12. data/src/core/ext/filters/client_channel/channel_connectivity.cc +1 -1
  13. data/src/core/ext/filters/client_channel/client_channel.cc +2084 -1673
  14. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +2 -3
  15. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +4 -0
  16. data/src/core/ext/filters/client_channel/health/health_check_client.cc +54 -49
  17. data/src/core/ext/filters/client_channel/health/health_check_client.h +20 -9
  18. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +1 -2
  19. data/src/core/ext/filters/client_channel/http_connect_handshaker.h +1 -1
  20. data/src/core/ext/filters/client_channel/lb_policy.cc +3 -30
  21. data/src/core/ext/filters/client_channel/lb_policy.h +16 -25
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +106 -81
  23. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +6 -2
  24. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +8 -12
  25. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +2 -2
  26. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +1 -1
  27. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +57 -49
  28. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +47 -41
  29. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +24 -20
  30. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +989 -284
  31. data/src/core/ext/filters/client_channel/lb_policy_factory.h +4 -1
  32. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +105 -2
  33. data/src/core/ext/filters/client_channel/lb_policy_registry.h +9 -2
  34. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +79 -36
  35. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +84 -2
  36. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +3 -0
  37. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +179 -0
  38. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +15 -3
  39. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +80 -4
  40. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +7 -13
  41. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +2 -2
  42. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +39 -0
  43. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +0 -6
  44. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +2 -64
  45. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc +28 -0
  46. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h +29 -0
  47. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +4 -4
  48. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +367 -232
  49. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +55 -76
  50. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +50 -39
  51. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +18 -12
  52. data/src/core/ext/filters/client_channel/service_config.cc +247 -27
  53. data/src/core/ext/filters/client_channel/service_config.h +119 -166
  54. data/src/core/ext/filters/client_channel/subchannel.cc +46 -84
  55. data/src/core/ext/filters/client_channel/subchannel.h +7 -7
  56. data/src/core/ext/filters/deadline/deadline_filter.cc +3 -4
  57. data/src/core/ext/filters/deadline/deadline_filter.h +3 -2
  58. data/src/core/ext/filters/http/client/http_client_filter.cc +7 -5
  59. data/src/core/ext/filters/http/client/http_client_filter.h +1 -1
  60. data/src/core/ext/filters/http/client_authority_filter.cc +1 -1
  61. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +4 -3
  62. data/src/core/ext/filters/http/server/http_server_filter.cc +18 -12
  63. data/src/core/ext/filters/message_size/message_size_filter.cc +118 -76
  64. data/src/core/ext/filters/message_size/message_size_filter.h +33 -0
  65. data/src/core/ext/transport/chttp2/alpn/alpn.h +1 -1
  66. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc +9 -7
  67. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +93 -60
  68. data/src/core/ext/transport/chttp2/transport/flow_control.h +1 -1
  69. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +4 -3
  70. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +3 -3
  71. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +8 -2
  72. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +2 -2
  73. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +1 -1
  74. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +3 -2
  75. data/src/core/ext/transport/chttp2/transport/internal.h +35 -23
  76. data/src/core/ext/transport/chttp2/transport/parsing.cc +4 -4
  77. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +3 -3
  78. data/src/core/ext/transport/chttp2/transport/writing.cc +61 -27
  79. data/src/core/ext/transport/inproc/inproc_transport.cc +18 -18
  80. data/src/core/lib/channel/channel_args.cc +0 -101
  81. data/src/core/lib/channel/channel_args.h +0 -37
  82. data/src/core/lib/channel/channel_stack.h +9 -5
  83. data/src/core/lib/channel/channelz_registry.cc +1 -1
  84. data/src/core/lib/channel/connected_channel.cc +2 -2
  85. data/src/core/lib/channel/context.h +3 -0
  86. data/src/core/lib/channel/handshaker.cc +4 -4
  87. data/src/core/lib/channel/handshaker.h +1 -1
  88. data/src/core/lib/compression/compression_args.cc +127 -0
  89. data/src/core/lib/compression/compression_args.h +55 -0
  90. data/src/core/lib/debug/trace.cc +13 -7
  91. data/src/core/lib/debug/trace.h +12 -0
  92. data/src/core/lib/gpr/arena.h +13 -9
  93. data/src/core/lib/gpr/env.h +2 -5
  94. data/src/core/lib/gpr/env_linux.cc +6 -1
  95. data/src/core/lib/gpr/env_posix.cc +5 -0
  96. data/src/core/lib/gpr/env_windows.cc +7 -5
  97. data/src/core/lib/gpr/log.cc +9 -13
  98. data/src/core/lib/gpr/string.cc +12 -6
  99. data/src/core/lib/gpr/string.h +4 -2
  100. data/src/core/lib/gpr/time_posix.cc +13 -0
  101. data/src/core/lib/gprpp/arena.cc +103 -0
  102. data/src/core/lib/gprpp/arena.h +121 -0
  103. data/src/core/lib/gprpp/fork.cc +12 -29
  104. data/src/core/lib/gprpp/global_config.h +87 -0
  105. data/src/core/lib/gprpp/global_config_custom.h +29 -0
  106. data/src/core/lib/gprpp/global_config_env.cc +135 -0
  107. data/src/core/lib/gprpp/global_config_env.h +131 -0
  108. data/src/core/lib/gprpp/global_config_generic.h +44 -0
  109. data/src/core/lib/gprpp/map.h +419 -0
  110. data/src/core/lib/gprpp/optional.h +1 -0
  111. data/src/core/lib/gprpp/orphanable.h +2 -2
  112. data/src/core/lib/gprpp/{mutex_lock.h → pair.h} +15 -19
  113. data/src/core/lib/gprpp/ref_counted.h +18 -2
  114. data/src/core/lib/gprpp/sync.h +126 -0
  115. data/src/core/lib/http/parser.cc +1 -1
  116. data/src/core/lib/iomgr/call_combiner.cc +84 -90
  117. data/src/core/lib/iomgr/call_combiner.h +75 -82
  118. data/src/core/lib/iomgr/cfstream_handle.cc +202 -0
  119. data/src/core/lib/iomgr/cfstream_handle.h +82 -0
  120. data/src/core/lib/iomgr/combiner.h +1 -1
  121. data/src/core/lib/iomgr/endpoint_cfstream.cc +375 -0
  122. data/src/core/lib/iomgr/endpoint_cfstream.h +49 -0
  123. data/src/core/lib/iomgr/endpoint_pair_windows.cc +2 -2
  124. data/src/core/lib/iomgr/error.h +23 -0
  125. data/src/core/lib/iomgr/error_cfstream.cc +52 -0
  126. data/src/core/lib/iomgr/error_cfstream.h +31 -0
  127. data/src/core/lib/iomgr/ev_epoll1_linux.cc +34 -27
  128. data/src/core/lib/iomgr/ev_epollex_linux.cc +33 -33
  129. data/src/core/lib/iomgr/ev_poll_posix.cc +7 -7
  130. data/src/core/lib/iomgr/ev_posix.cc +15 -13
  131. data/src/core/lib/iomgr/ev_posix.h +4 -1
  132. data/src/core/lib/iomgr/executor.cc +13 -9
  133. data/src/core/lib/iomgr/fork_posix.cc +0 -1
  134. data/src/core/lib/iomgr/internal_errqueue.cc +1 -1
  135. data/src/core/lib/iomgr/iomgr.cc +6 -5
  136. data/src/core/lib/iomgr/iomgr_custom.cc +3 -0
  137. data/src/core/lib/iomgr/iomgr_custom.h +2 -0
  138. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +93 -0
  139. data/src/core/lib/iomgr/iomgr_windows.cc +1 -0
  140. data/src/core/lib/iomgr/lockfree_event.cc +3 -3
  141. data/src/core/lib/iomgr/port.h +11 -0
  142. data/src/core/lib/iomgr/resource_quota.cc +40 -37
  143. data/src/core/lib/iomgr/socket_utils_common_posix.cc +6 -2
  144. data/src/core/lib/iomgr/socket_windows.cc +19 -0
  145. data/src/core/lib/iomgr/socket_windows.h +8 -0
  146. data/src/core/lib/iomgr/tcp_client_cfstream.cc +216 -0
  147. data/src/core/lib/iomgr/tcp_client_custom.cc +2 -2
  148. data/src/core/lib/iomgr/tcp_client_posix.cc +3 -3
  149. data/src/core/lib/iomgr/tcp_client_windows.cc +1 -1
  150. data/src/core/lib/iomgr/tcp_custom.cc +9 -9
  151. data/src/core/lib/iomgr/tcp_posix.cc +41 -41
  152. data/src/core/lib/iomgr/tcp_server_custom.cc +3 -3
  153. data/src/core/lib/iomgr/tcp_server_posix.cc +14 -1
  154. data/src/core/lib/iomgr/tcp_server_windows.cc +2 -2
  155. data/src/core/lib/iomgr/tcp_windows.cc +7 -9
  156. data/src/core/lib/iomgr/timer_generic.cc +16 -16
  157. data/src/core/lib/iomgr/timer_manager.cc +12 -11
  158. data/src/core/lib/profiling/basic_timers.cc +10 -4
  159. data/src/core/lib/security/context/security_context.cc +6 -7
  160. data/src/core/lib/security/context/security_context.h +3 -4
  161. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +1 -1
  162. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +2 -3
  163. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
  164. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +7 -7
  165. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +7 -5
  166. data/src/core/lib/security/security_connector/security_connector.cc +0 -1
  167. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +3 -2
  168. data/src/core/lib/security/security_connector/ssl_utils.cc +30 -26
  169. data/src/core/lib/security/security_connector/ssl_utils.h +5 -1
  170. data/src/core/lib/security/transport/client_auth_filter.cc +7 -11
  171. data/src/core/lib/security/transport/secure_endpoint.cc +4 -4
  172. data/src/core/lib/security/transport/server_auth_filter.cc +2 -3
  173. data/src/core/lib/slice/slice.cc +99 -116
  174. data/src/core/lib/slice/slice_buffer.cc +5 -0
  175. data/src/core/lib/slice/slice_intern.cc +38 -95
  176. data/src/core/lib/slice/slice_internal.h +200 -2
  177. data/src/core/lib/surface/api_trace.h +1 -1
  178. data/src/core/lib/surface/call.cc +41 -35
  179. data/src/core/lib/surface/call.h +7 -2
  180. data/src/core/lib/surface/call_details.cc +0 -1
  181. data/src/core/lib/surface/completion_queue.cc +36 -27
  182. data/src/core/lib/surface/init.cc +3 -4
  183. data/src/core/lib/surface/lame_client.cc +1 -1
  184. data/src/core/lib/surface/server.cc +18 -25
  185. data/src/core/lib/surface/version.cc +1 -1
  186. data/src/core/lib/transport/bdp_estimator.cc +3 -3
  187. data/src/core/lib/transport/bdp_estimator.h +2 -2
  188. data/src/core/lib/transport/connectivity_state.cc +10 -40
  189. data/src/core/lib/transport/connectivity_state.h +0 -8
  190. data/src/core/lib/transport/error_utils.cc +12 -0
  191. data/src/core/lib/transport/metadata.cc +206 -278
  192. data/src/core/lib/transport/metadata.h +205 -10
  193. data/src/core/lib/transport/static_metadata.cc +108 -116
  194. data/src/core/lib/transport/static_metadata.h +1 -2
  195. data/src/core/lib/transport/status_metadata.cc +3 -3
  196. data/src/core/lib/transport/transport.cc +29 -66
  197. data/src/core/lib/transport/transport.h +36 -8
  198. data/src/core/lib/transport/transport_impl.h +1 -1
  199. data/src/core/tsi/fake_transport_security.cc +4 -4
  200. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +1 -1
  201. data/src/core/tsi/ssl_transport_security.cc +1 -1
  202. data/src/ruby/ext/grpc/rb_grpc.c +1 -1
  203. data/src/ruby/lib/grpc/errors.rb +22 -3
  204. data/src/ruby/lib/grpc/generic/bidi_call.rb +1 -1
  205. data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
  206. data/src/ruby/lib/grpc/version.rb +1 -1
  207. data/src/ruby/spec/errors_spec.rb +141 -0
  208. metadata +57 -33
  209. data/src/core/lib/gpr/arena.cc +0 -192
@@ -33,43 +33,189 @@
33
33
 
34
34
  namespace grpc_core {
35
35
 
36
- RefCountedPtr<ServiceConfig> ServiceConfig::Create(const char* json) {
36
+ namespace {
37
+ typedef InlinedVector<UniquePtr<ServiceConfig::Parser>,
38
+ ServiceConfig::kNumPreallocatedParsers>
39
+ ServiceConfigParserList;
40
+ ServiceConfigParserList* g_registered_parsers;
41
+ } // namespace
42
+
43
+ RefCountedPtr<ServiceConfig> ServiceConfig::Create(const char* json,
44
+ grpc_error** error) {
37
45
  UniquePtr<char> service_config_json(gpr_strdup(json));
38
46
  UniquePtr<char> json_string(gpr_strdup(json));
47
+ GPR_DEBUG_ASSERT(error != nullptr);
39
48
  grpc_json* json_tree = grpc_json_parse_string(json_string.get());
40
49
  if (json_tree == nullptr) {
41
- gpr_log(GPR_INFO, "failed to parse JSON for service config");
50
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
51
+ "failed to parse JSON for service config");
42
52
  return nullptr;
43
53
  }
44
- return MakeRefCounted<ServiceConfig>(std::move(service_config_json),
45
- std::move(json_string), json_tree);
54
+ return MakeRefCounted<ServiceConfig>(
55
+ std::move(service_config_json), std::move(json_string), json_tree, error);
46
56
  }
47
57
 
48
58
  ServiceConfig::ServiceConfig(UniquePtr<char> service_config_json,
49
- UniquePtr<char> json_string, grpc_json* json_tree)
59
+ UniquePtr<char> json_string, grpc_json* json_tree,
60
+ grpc_error** error)
50
61
  : service_config_json_(std::move(service_config_json)),
51
62
  json_string_(std::move(json_string)),
52
- json_tree_(json_tree) {}
63
+ json_tree_(json_tree) {
64
+ GPR_DEBUG_ASSERT(error != nullptr);
65
+ if (json_tree->type != GRPC_JSON_OBJECT || json_tree->key != nullptr) {
66
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
67
+ "Malformed service Config JSON object");
68
+ return;
69
+ }
70
+ grpc_error* error_list[2];
71
+ int error_count = 0;
72
+ grpc_error* global_error = ParseGlobalParams(json_tree);
73
+ grpc_error* local_error = ParsePerMethodParams(json_tree);
74
+ if (global_error != GRPC_ERROR_NONE) {
75
+ error_list[error_count++] = global_error;
76
+ }
77
+ if (local_error != GRPC_ERROR_NONE) {
78
+ error_list[error_count++] = local_error;
79
+ }
80
+ if (error_count > 0) {
81
+ *error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
82
+ "Service config parsing error", error_list, error_count);
83
+ GRPC_ERROR_UNREF(global_error);
84
+ GRPC_ERROR_UNREF(local_error);
85
+ }
86
+ }
53
87
 
54
- ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); }
88
+ grpc_error* ServiceConfig::ParseGlobalParams(const grpc_json* json_tree) {
89
+ GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT);
90
+ GPR_DEBUG_ASSERT(json_tree_->key == nullptr);
91
+ InlinedVector<grpc_error*, 4> error_list;
92
+ for (size_t i = 0; i < g_registered_parsers->size(); i++) {
93
+ grpc_error* parser_error = GRPC_ERROR_NONE;
94
+ auto parsed_obj =
95
+ (*g_registered_parsers)[i]->ParseGlobalParams(json_tree, &parser_error);
96
+ if (parser_error != GRPC_ERROR_NONE) {
97
+ error_list.push_back(parser_error);
98
+ }
99
+ parsed_global_service_config_objects_.push_back(std::move(parsed_obj));
100
+ }
101
+ return GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
102
+ }
55
103
 
56
- const char* ServiceConfig::GetLoadBalancingPolicyName() const {
57
- if (json_tree_->type != GRPC_JSON_OBJECT || json_tree_->key != nullptr) {
58
- return nullptr;
104
+ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable(
105
+ const grpc_json* json,
106
+ SliceHashTable<const ServiceConfigObjectsVector*>::Entry* entries,
107
+ size_t* idx) {
108
+ auto objs_vector = MakeUnique<ServiceConfigObjectsVector>();
109
+ InlinedVector<grpc_error*, 4> error_list;
110
+ for (size_t i = 0; i < g_registered_parsers->size(); i++) {
111
+ grpc_error* parser_error = GRPC_ERROR_NONE;
112
+ auto parsed_obj =
113
+ (*g_registered_parsers)[i]->ParsePerMethodParams(json, &parser_error);
114
+ if (parser_error != GRPC_ERROR_NONE) {
115
+ error_list.push_back(parser_error);
116
+ }
117
+ objs_vector->push_back(std::move(parsed_obj));
59
118
  }
60
- const char* lb_policy_name = nullptr;
61
- for (grpc_json* field = json_tree_->child; field != nullptr;
119
+ service_config_objects_vectors_storage_.push_back(std::move(objs_vector));
120
+ const auto* vector_ptr =
121
+ service_config_objects_vectors_storage_
122
+ [service_config_objects_vectors_storage_.size() - 1]
123
+ .get();
124
+ // Construct list of paths.
125
+ InlinedVector<UniquePtr<char>, 10> paths;
126
+ for (grpc_json* child = json->child; child != nullptr; child = child->next) {
127
+ if (child->key == nullptr) continue;
128
+ if (strcmp(child->key, "name") == 0) {
129
+ if (child->type != GRPC_JSON_ARRAY) {
130
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
131
+ "field:name error:not of type Array"));
132
+ goto wrap_error;
133
+ }
134
+ for (grpc_json* name = child->child; name != nullptr; name = name->next) {
135
+ grpc_error* parse_error = GRPC_ERROR_NONE;
136
+ UniquePtr<char> path = ParseJsonMethodName(name, &parse_error);
137
+ if (path == nullptr) {
138
+ error_list.push_back(parse_error);
139
+ } else {
140
+ GPR_DEBUG_ASSERT(parse_error == GRPC_ERROR_NONE);
141
+ paths.push_back(std::move(path));
142
+ }
143
+ }
144
+ }
145
+ }
146
+ if (paths.size() == 0) {
147
+ error_list.push_back(
148
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("No names specified"));
149
+ }
150
+ // Add entry for each path.
151
+ for (size_t i = 0; i < paths.size(); ++i) {
152
+ entries[*idx].key = grpc_slice_from_copied_string(paths[i].get());
153
+ entries[*idx].value = vector_ptr;
154
+ ++*idx;
155
+ }
156
+ wrap_error:
157
+ return GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
158
+ }
159
+
160
+ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) {
161
+ GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT);
162
+ GPR_DEBUG_ASSERT(json_tree_->key == nullptr);
163
+ SliceHashTable<const ServiceConfigObjectsVector*>::Entry* entries = nullptr;
164
+ size_t num_entries = 0;
165
+ InlinedVector<grpc_error*, 4> error_list;
166
+ for (grpc_json* field = json_tree->child; field != nullptr;
62
167
  field = field->next) {
63
- if (field->key == nullptr) return nullptr;
64
- if (strcmp(field->key, "loadBalancingPolicy") == 0) {
65
- if (lb_policy_name != nullptr) return nullptr; // Duplicate.
66
- if (field->type != GRPC_JSON_STRING) return nullptr;
67
- lb_policy_name = field->value;
168
+ if (field->key == nullptr) {
169
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
170
+ "error:Illegal key value - NULL"));
171
+ continue;
68
172
  }
173
+ if (strcmp(field->key, "methodConfig") == 0) {
174
+ if (entries != nullptr) {
175
+ GPR_ASSERT(false);
176
+ }
177
+ if (field->type != GRPC_JSON_ARRAY) {
178
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
179
+ "field:methodConfig error:not of type Array"));
180
+ }
181
+ for (grpc_json* method = field->child; method != nullptr;
182
+ method = method->next) {
183
+ int count = CountNamesInMethodConfig(method);
184
+ if (count <= 0) {
185
+ error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
186
+ "field:methodConfig error:No names found"));
187
+ }
188
+ num_entries += static_cast<size_t>(count);
189
+ }
190
+ entries = static_cast<
191
+ SliceHashTable<const ServiceConfigObjectsVector*>::Entry*>(gpr_zalloc(
192
+ num_entries *
193
+ sizeof(SliceHashTable<const ServiceConfigObjectsVector*>::Entry)));
194
+ size_t idx = 0;
195
+ for (grpc_json* method = field->child; method != nullptr;
196
+ method = method->next) {
197
+ grpc_error* error = ParseJsonMethodConfigToServiceConfigObjectsTable(
198
+ method, entries, &idx);
199
+ if (error != GRPC_ERROR_NONE) {
200
+ error_list.push_back(error);
201
+ }
202
+ }
203
+ // idx might not be equal to num_entries due to parsing errors
204
+ num_entries = idx;
205
+ break;
206
+ }
207
+ }
208
+ if (entries != nullptr) {
209
+ parsed_method_service_config_objects_table_ =
210
+ SliceHashTable<const ServiceConfigObjectsVector*>::Create(
211
+ num_entries, entries, nullptr);
212
+ gpr_free(entries);
69
213
  }
70
- return lb_policy_name;
214
+ return GRPC_ERROR_CREATE_FROM_VECTOR("Method Params", &error_list);
71
215
  }
72
216
 
217
+ ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); }
218
+
73
219
  int ServiceConfig::CountNamesInMethodConfig(grpc_json* json) {
74
220
  int num_names = 0;
75
221
  for (grpc_json* field = json->child; field != nullptr; field = field->next) {
@@ -84,28 +230,102 @@ int ServiceConfig::CountNamesInMethodConfig(grpc_json* json) {
84
230
  return num_names;
85
231
  }
86
232
 
87
- UniquePtr<char> ServiceConfig::ParseJsonMethodName(grpc_json* json) {
88
- if (json->type != GRPC_JSON_OBJECT) return nullptr;
233
+ UniquePtr<char> ServiceConfig::ParseJsonMethodName(grpc_json* json,
234
+ grpc_error** error) {
235
+ if (json->type != GRPC_JSON_OBJECT) {
236
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
237
+ "field:name error:type is not object");
238
+ return nullptr;
239
+ }
89
240
  const char* service_name = nullptr;
90
241
  const char* method_name = nullptr;
91
242
  for (grpc_json* child = json->child; child != nullptr; child = child->next) {
92
- if (child->key == nullptr) return nullptr;
93
- if (child->type != GRPC_JSON_STRING) return nullptr;
243
+ if (child->key == nullptr) {
244
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
245
+ "field:name error:Child entry with no key");
246
+ return nullptr;
247
+ }
248
+ if (child->type != GRPC_JSON_STRING) {
249
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
250
+ "field:name error:Child entry not of type string");
251
+ return nullptr;
252
+ }
94
253
  if (strcmp(child->key, "service") == 0) {
95
- if (service_name != nullptr) return nullptr; // Duplicate.
96
- if (child->value == nullptr) return nullptr;
254
+ if (service_name != nullptr) {
255
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
256
+ "field:name error: field:service error:Multiple entries");
257
+ return nullptr; // Duplicate.
258
+ }
259
+ if (child->value == nullptr) {
260
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
261
+ "field:name error: field:service error:empty value");
262
+ return nullptr;
263
+ }
97
264
  service_name = child->value;
98
265
  } else if (strcmp(child->key, "method") == 0) {
99
- if (method_name != nullptr) return nullptr; // Duplicate.
100
- if (child->value == nullptr) return nullptr;
266
+ if (method_name != nullptr) {
267
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
268
+ "field:name error: field:method error:multiple entries");
269
+ return nullptr; // Duplicate.
270
+ }
271
+ if (child->value == nullptr) {
272
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
273
+ "field:name error: field:method error:empty value");
274
+ return nullptr;
275
+ }
101
276
  method_name = child->value;
102
277
  }
103
278
  }
104
- if (service_name == nullptr) return nullptr; // Required field.
279
+ if (service_name == nullptr) {
280
+ *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
281
+ "field:name error: field:service error:not found");
282
+ return nullptr; // Required field.
283
+ }
105
284
  char* path;
106
285
  gpr_asprintf(&path, "/%s/%s", service_name,
107
286
  method_name == nullptr ? "*" : method_name);
108
287
  return UniquePtr<char>(path);
109
288
  }
110
289
 
290
+ const ServiceConfig::ServiceConfigObjectsVector*
291
+ ServiceConfig::GetMethodServiceConfigObjectsVector(const grpc_slice& path) {
292
+ if (parsed_method_service_config_objects_table_.get() == nullptr) {
293
+ return nullptr;
294
+ }
295
+ const auto* value = parsed_method_service_config_objects_table_->Get(path);
296
+ // If we didn't find a match for the path, try looking for a wildcard
297
+ // entry (i.e., change "/service/method" to "/service/*").
298
+ if (value == nullptr) {
299
+ char* path_str = grpc_slice_to_c_string(path);
300
+ const char* sep = strrchr(path_str, '/') + 1;
301
+ const size_t len = (size_t)(sep - path_str);
302
+ char* buf = (char*)gpr_malloc(len + 2); // '*' and NUL
303
+ memcpy(buf, path_str, len);
304
+ buf[len] = '*';
305
+ buf[len + 1] = '\0';
306
+ grpc_slice wildcard_path = grpc_slice_from_copied_string(buf);
307
+ gpr_free(buf);
308
+ value = parsed_method_service_config_objects_table_->Get(wildcard_path);
309
+ grpc_slice_unref_internal(wildcard_path);
310
+ gpr_free(path_str);
311
+ if (value == nullptr) return nullptr;
312
+ }
313
+ return *value;
314
+ }
315
+
316
+ size_t ServiceConfig::RegisterParser(UniquePtr<Parser> parser) {
317
+ g_registered_parsers->push_back(std::move(parser));
318
+ return g_registered_parsers->size() - 1;
319
+ }
320
+
321
+ void ServiceConfig::Init() {
322
+ GPR_ASSERT(g_registered_parsers == nullptr);
323
+ g_registered_parsers = New<ServiceConfigParserList>();
324
+ }
325
+
326
+ void ServiceConfig::Shutdown() {
327
+ Delete(g_registered_parsers);
328
+ g_registered_parsers = nullptr;
329
+ }
330
+
111
331
  } // namespace grpc_core
@@ -25,6 +25,7 @@
25
25
  #include "src/core/lib/gprpp/inlined_vector.h"
26
26
  #include "src/core/lib/gprpp/ref_counted.h"
27
27
  #include "src/core/lib/gprpp/ref_counted_ptr.h"
28
+ #include "src/core/lib/iomgr/error.h"
28
29
  #include "src/core/lib/json/json.h"
29
30
  #include "src/core/lib/slice/slice_hash_table.h"
30
31
 
@@ -56,45 +57,106 @@ namespace grpc_core {
56
57
 
57
58
  class ServiceConfig : public RefCounted<ServiceConfig> {
58
59
  public:
60
+ /// This is the base class that all service config parsers MUST use to store
61
+ /// parsed service config data.
62
+ class ParsedConfig {
63
+ public:
64
+ virtual ~ParsedConfig() = default;
65
+
66
+ GRPC_ABSTRACT_BASE_CLASS;
67
+ };
68
+
69
+ /// This is the base class that all service config parsers should derive from.
70
+ class Parser {
71
+ public:
72
+ virtual ~Parser() = default;
73
+
74
+ virtual UniquePtr<ParsedConfig> ParseGlobalParams(const grpc_json* json,
75
+ grpc_error** error) {
76
+ GPR_DEBUG_ASSERT(error != nullptr);
77
+ return nullptr;
78
+ }
79
+
80
+ virtual UniquePtr<ParsedConfig> ParsePerMethodParams(const grpc_json* json,
81
+ grpc_error** error) {
82
+ GPR_DEBUG_ASSERT(error != nullptr);
83
+ return nullptr;
84
+ }
85
+
86
+ GRPC_ABSTRACT_BASE_CLASS;
87
+ };
88
+
89
+ static constexpr int kNumPreallocatedParsers = 4;
90
+ typedef InlinedVector<UniquePtr<ParsedConfig>, kNumPreallocatedParsers>
91
+ ServiceConfigObjectsVector;
92
+
93
+ /// When a service config is applied to a call in the client_channel_filter,
94
+ /// we create an instance of this object and store it in the call_data for
95
+ /// client_channel. A pointer to this object is also stored in the
96
+ /// call_context, so that future filters can easily access method and global
97
+ /// parameters for the call.
98
+ class CallData {
99
+ public:
100
+ CallData() = default;
101
+ CallData(RefCountedPtr<ServiceConfig> svc_cfg, const grpc_slice& path)
102
+ : service_config_(std::move(svc_cfg)) {
103
+ if (service_config_ != nullptr) {
104
+ method_params_vector_ =
105
+ service_config_->GetMethodServiceConfigObjectsVector(path);
106
+ }
107
+ }
108
+
109
+ ServiceConfig* service_config() { return service_config_.get(); }
110
+
111
+ ParsedConfig* GetMethodParsedObject(size_t index) const {
112
+ return method_params_vector_ != nullptr
113
+ ? (*method_params_vector_)[index].get()
114
+ : nullptr;
115
+ }
116
+
117
+ ParsedConfig* GetGlobalParsedObject(size_t index) const {
118
+ return service_config_->GetParsedGlobalServiceConfigObject(index);
119
+ }
120
+
121
+ private:
122
+ RefCountedPtr<ServiceConfig> service_config_;
123
+ const ServiceConfigObjectsVector* method_params_vector_ = nullptr;
124
+ };
125
+
59
126
  /// Creates a new service config from parsing \a json_string.
60
127
  /// Returns null on parse error.
61
- static RefCountedPtr<ServiceConfig> Create(const char* json);
128
+ static RefCountedPtr<ServiceConfig> Create(const char* json,
129
+ grpc_error** error);
62
130
 
63
131
  ~ServiceConfig();
64
132
 
65
133
  const char* service_config_json() const { return service_config_json_.get(); }
66
134
 
67
- /// Invokes \a process_json() for each global parameter in the service
68
- /// config. \a arg is passed as the second argument to \a process_json().
69
- template <typename T>
70
- using ProcessJson = void (*)(const grpc_json*, T*);
71
- template <typename T>
72
- void ParseGlobalParams(ProcessJson<T> process_json, T* arg) const;
73
-
74
- /// Gets the LB policy name from \a service_config.
75
- /// Returns NULL if no LB policy name was specified.
76
- /// Caller does NOT take ownership.
77
- const char* GetLoadBalancingPolicyName() const;
78
-
79
- /// Creates a method config table based on the data in \a json.
80
- /// The table's keys are request paths. The table's value type is
81
- /// returned by \a create_value(), based on data parsed from the JSON tree.
82
- /// Returns null on error.
83
- template <typename T>
84
- using CreateValue = RefCountedPtr<T> (*)(const grpc_json* method_config_json);
85
- template <typename T>
86
- RefCountedPtr<SliceHashTable<RefCountedPtr<T>>> CreateMethodConfigTable(
87
- CreateValue<T> create_value) const;
88
-
89
- /// A helper function for looking up values in the table returned by
90
- /// \a CreateMethodConfigTable().
91
- /// Gets the method config for the specified \a path, which should be of
92
- /// the form "/service/method".
93
- /// Returns null if the method has no config.
94
- /// Caller does NOT own a reference to the result.
95
- template <typename T>
96
- static RefCountedPtr<T> MethodConfigTableLookup(
97
- const SliceHashTable<RefCountedPtr<T>>& table, const grpc_slice& path);
135
+ /// Retrieves the parsed global service config object at index \a index. The
136
+ /// lifetime of the returned object is tied to the lifetime of the
137
+ /// ServiceConfig object.
138
+ ParsedConfig* GetParsedGlobalServiceConfigObject(size_t index) {
139
+ GPR_DEBUG_ASSERT(index < parsed_global_service_config_objects_.size());
140
+ return parsed_global_service_config_objects_[index].get();
141
+ }
142
+
143
+ /// Retrieves the vector of method service config objects for a given path \a
144
+ /// path. The lifetime of the returned vector and contained objects is tied to
145
+ /// the lifetime of the ServiceConfig object.
146
+ const ServiceConfigObjectsVector* GetMethodServiceConfigObjectsVector(
147
+ const grpc_slice& path);
148
+
149
+ /// Globally register a service config parser. On successful registration, it
150
+ /// returns the index at which the parser was registered. On failure, -1 is
151
+ /// returned. Each new service config update will go through all the
152
+ /// registered parser. Each parser is responsible for reading the service
153
+ /// config json and returning a parsed object. This parsed object can later be
154
+ /// retrieved using the same index that was returned at registration time.
155
+ static size_t RegisterParser(UniquePtr<Parser> parser);
156
+
157
+ static void Init();
158
+
159
+ static void Shutdown();
98
160
 
99
161
  private:
100
162
  // So New() can call our private ctor.
@@ -103,151 +165,42 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
103
165
 
104
166
  // Takes ownership of \a json_tree.
105
167
  ServiceConfig(UniquePtr<char> service_config_json,
106
- UniquePtr<char> json_string, grpc_json* json_tree);
168
+ UniquePtr<char> json_string, grpc_json* json_tree,
169
+ grpc_error** error);
170
+
171
+ // Helper functions to parse the service config
172
+ grpc_error* ParseGlobalParams(const grpc_json* json_tree);
173
+ grpc_error* ParsePerMethodParams(const grpc_json* json_tree);
107
174
 
108
175
  // Returns the number of names specified in the method config \a json.
109
176
  static int CountNamesInMethodConfig(grpc_json* json);
110
177
 
111
178
  // Returns a path string for the JSON name object specified by \a json.
112
- // Returns null on error.
113
- static UniquePtr<char> ParseJsonMethodName(grpc_json* json);
179
+ // Returns null on error, and stores error in \a error.
180
+ static UniquePtr<char> ParseJsonMethodName(grpc_json* json,
181
+ grpc_error** error);
114
182
 
115
- // Parses the method config from \a json. Adds an entry to \a entries for
116
- // each name found, incrementing \a idx for each entry added.
117
- // Returns false on error.
118
- template <typename T>
119
- static bool ParseJsonMethodConfig(
120
- grpc_json* json, CreateValue<T> create_value,
121
- typename SliceHashTable<RefCountedPtr<T>>::Entry* entries, size_t* idx);
183
+ grpc_error* ParseJsonMethodConfigToServiceConfigObjectsTable(
184
+ const grpc_json* json,
185
+ SliceHashTable<const ServiceConfigObjectsVector*>::Entry* entries,
186
+ size_t* idx);
122
187
 
123
188
  UniquePtr<char> service_config_json_;
124
189
  UniquePtr<char> json_string_; // Underlying storage for json_tree.
125
190
  grpc_json* json_tree_;
126
- };
127
191
 
128
- //
129
- // implementation -- no user-serviceable parts below
130
- //
131
-
132
- template <typename T>
133
- void ServiceConfig::ParseGlobalParams(ProcessJson<T> process_json,
134
- T* arg) const {
135
- if (json_tree_->type != GRPC_JSON_OBJECT || json_tree_->key != nullptr) {
136
- return;
137
- }
138
- for (grpc_json* field = json_tree_->child; field != nullptr;
139
- field = field->next) {
140
- if (field->key == nullptr) return;
141
- if (strcmp(field->key, "methodConfig") == 0) continue;
142
- process_json(field, arg);
143
- }
144
- }
145
-
146
- template <typename T>
147
- bool ServiceConfig::ParseJsonMethodConfig(
148
- grpc_json* json, CreateValue<T> create_value,
149
- typename SliceHashTable<RefCountedPtr<T>>::Entry* entries, size_t* idx) {
150
- // Construct value.
151
- RefCountedPtr<T> method_config = create_value(json);
152
- if (method_config == nullptr) return false;
153
- // Construct list of paths.
154
- InlinedVector<UniquePtr<char>, 10> paths;
155
- for (grpc_json* child = json->child; child != nullptr; child = child->next) {
156
- if (child->key == nullptr) continue;
157
- if (strcmp(child->key, "name") == 0) {
158
- if (child->type != GRPC_JSON_ARRAY) return false;
159
- for (grpc_json* name = child->child; name != nullptr; name = name->next) {
160
- UniquePtr<char> path = ParseJsonMethodName(name);
161
- if (path == nullptr) return false;
162
- paths.push_back(std::move(path));
163
- }
164
- }
165
- }
166
- if (paths.size() == 0) return false; // No names specified.
167
- // Add entry for each path.
168
- for (size_t i = 0; i < paths.size(); ++i) {
169
- entries[*idx].key = grpc_slice_from_copied_string(paths[i].get());
170
- entries[*idx].value = method_config; // Takes a new ref.
171
- ++*idx;
172
- }
173
- // Success.
174
- return true;
175
- }
176
-
177
- template <typename T>
178
- RefCountedPtr<SliceHashTable<RefCountedPtr<T>>>
179
- ServiceConfig::CreateMethodConfigTable(CreateValue<T> create_value) const {
180
- // Traverse parsed JSON tree.
181
- if (json_tree_->type != GRPC_JSON_OBJECT || json_tree_->key != nullptr) {
182
- return nullptr;
183
- }
184
- size_t num_entries = 0;
185
- typename SliceHashTable<RefCountedPtr<T>>::Entry* entries = nullptr;
186
- for (grpc_json* field = json_tree_->child; field != nullptr;
187
- field = field->next) {
188
- if (field->key == nullptr) return nullptr;
189
- if (strcmp(field->key, "methodConfig") == 0) {
190
- if (entries != nullptr) return nullptr; // Duplicate.
191
- if (field->type != GRPC_JSON_ARRAY) return nullptr;
192
- // Find number of entries.
193
- for (grpc_json* method = field->child; method != nullptr;
194
- method = method->next) {
195
- int count = CountNamesInMethodConfig(method);
196
- if (count <= 0) return nullptr;
197
- num_entries += static_cast<size_t>(count);
198
- }
199
- // Populate method config table entries.
200
- entries = static_cast<typename SliceHashTable<RefCountedPtr<T>>::Entry*>(
201
- gpr_zalloc(num_entries *
202
- sizeof(typename SliceHashTable<RefCountedPtr<T>>::Entry)));
203
- size_t idx = 0;
204
- for (grpc_json* method = field->child; method != nullptr;
205
- method = method->next) {
206
- if (!ParseJsonMethodConfig(method, create_value, entries, &idx)) {
207
- for (size_t i = 0; i < idx; ++i) {
208
- grpc_slice_unref_internal(entries[i].key);
209
- entries[i].value.reset();
210
- }
211
- gpr_free(entries);
212
- return nullptr;
213
- }
214
- }
215
- GPR_ASSERT(idx == num_entries);
216
- }
217
- }
218
- // Instantiate method config table.
219
- RefCountedPtr<SliceHashTable<RefCountedPtr<T>>> method_config_table;
220
- if (entries != nullptr) {
221
- method_config_table =
222
- SliceHashTable<RefCountedPtr<T>>::Create(num_entries, entries, nullptr);
223
- gpr_free(entries);
224
- }
225
- return method_config_table;
226
- }
227
-
228
- template <typename T>
229
- RefCountedPtr<T> ServiceConfig::MethodConfigTableLookup(
230
- const SliceHashTable<RefCountedPtr<T>>& table, const grpc_slice& path) {
231
- const RefCountedPtr<T>* value = table.Get(path);
232
- // If we didn't find a match for the path, try looking for a wildcard
233
- // entry (i.e., change "/service/method" to "/service/*").
234
- if (value == nullptr) {
235
- char* path_str = grpc_slice_to_c_string(path);
236
- const char* sep = strrchr(path_str, '/') + 1;
237
- const size_t len = (size_t)(sep - path_str);
238
- char* buf = (char*)gpr_malloc(len + 2); // '*' and NUL
239
- memcpy(buf, path_str, len);
240
- buf[len] = '*';
241
- buf[len + 1] = '\0';
242
- grpc_slice wildcard_path = grpc_slice_from_copied_string(buf);
243
- gpr_free(buf);
244
- value = table.Get(wildcard_path);
245
- grpc_slice_unref_internal(wildcard_path);
246
- gpr_free(path_str);
247
- if (value == nullptr) return nullptr;
248
- }
249
- return RefCountedPtr<T>(*value);
250
- }
192
+ InlinedVector<UniquePtr<ParsedConfig>, kNumPreallocatedParsers>
193
+ parsed_global_service_config_objects_;
194
+ // A map from the method name to the service config objects vector. Note that
195
+ // we are using a raw pointer and not a unique pointer so that we can use the
196
+ // same vector for multiple names.
197
+ RefCountedPtr<SliceHashTable<const ServiceConfigObjectsVector*>>
198
+ parsed_method_service_config_objects_table_;
199
+ // Storage for all the vectors that are being used in
200
+ // parsed_method_service_config_objects_table_.
201
+ InlinedVector<UniquePtr<ServiceConfigObjectsVector>, 32>
202
+ service_config_objects_vectors_storage_;
203
+ };
251
204
 
252
205
  } // namespace grpc_core
253
206