grpc 1.26.0 → 1.27.0.pre1

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 +1654 -1519
  3. data/etc/roots.pem +44 -0
  4. data/include/grpc/grpc_security.h +37 -15
  5. data/include/grpc/grpc_security_constants.h +27 -0
  6. data/include/grpc/impl/codegen/grpc_types.h +14 -0
  7. data/include/grpc/impl/codegen/port_platform.h +1 -1
  8. data/src/core/ext/filters/client_channel/client_channel.cc +0 -20
  9. data/src/core/ext/filters/client_channel/http_proxy.cc +4 -4
  10. data/src/core/ext/filters/client_channel/lb_policy.cc +4 -3
  11. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +191 -201
  12. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +89 -0
  13. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +40 -0
  14. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +3 -2
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +88 -121
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +28 -57
  17. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +0 -7
  18. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +8 -9
  19. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +53 -34
  20. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +18 -5
  21. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +24 -19
  22. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +2 -1
  23. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +4 -2
  24. data/src/core/ext/filters/client_channel/server_address.cc +6 -9
  25. data/src/core/ext/filters/client_channel/server_address.h +3 -10
  26. data/src/core/ext/filters/client_channel/xds/xds_api.cc +394 -150
  27. data/src/core/ext/filters/client_channel/xds/xds_api.h +75 -35
  28. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.cc +59 -22
  29. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.h +13 -9
  30. data/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc +8 -6
  31. data/src/core/ext/filters/client_channel/xds/xds_client.cc +456 -175
  32. data/src/core/ext/filters/client_channel/xds/xds_client.h +33 -21
  33. data/src/core/ext/filters/client_channel/xds/xds_client_stats.cc +5 -8
  34. data/src/core/ext/filters/client_channel/xds/xds_client_stats.h +18 -24
  35. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +2 -2
  36. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c +13 -5
  37. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h +34 -0
  38. data/src/core/lib/channel/channelz.h +11 -1
  39. data/src/core/lib/gpr/time_precise.cc +1 -1
  40. data/src/core/lib/gprpp/optional.h +26 -0
  41. data/src/core/lib/gprpp/string_view.h +14 -10
  42. data/src/core/lib/iomgr/executor.cc +1 -1
  43. data/src/core/lib/iomgr/fork_posix.cc +4 -0
  44. data/src/core/lib/iomgr/poller/eventmanager_libuv.cc +87 -0
  45. data/src/core/lib/iomgr/poller/eventmanager_libuv.h +88 -0
  46. data/src/core/lib/iomgr/socket_utils_common_posix.cc +14 -0
  47. data/src/core/lib/iomgr/socket_utils_posix.h +12 -0
  48. data/src/core/lib/iomgr/tcp_custom.h +3 -0
  49. data/src/core/lib/iomgr/tcp_posix.cc +607 -56
  50. data/src/core/lib/iomgr/tcp_server_custom.cc +15 -2
  51. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +8 -0
  52. data/src/core/lib/json/json.h +11 -1
  53. data/src/core/lib/json/json_reader.cc +206 -28
  54. data/src/core/lib/json/json_writer.cc +111 -24
  55. data/src/core/lib/security/credentials/composite/composite_credentials.cc +7 -0
  56. data/src/core/lib/security/credentials/composite/composite_credentials.h +5 -1
  57. data/src/core/lib/security/credentials/credentials.h +10 -1
  58. data/src/core/lib/security/credentials/fake/fake_credentials.h +2 -1
  59. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
  60. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +6 -4
  61. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -1
  62. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +20 -0
  63. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +8 -0
  64. data/src/core/lib/security/credentials/tls/{spiffe_credentials.cc → tls_credentials.cc} +23 -24
  65. data/src/core/lib/security/credentials/tls/{spiffe_credentials.h → tls_credentials.h} +9 -9
  66. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +13 -0
  67. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +22 -2
  68. data/src/core/lib/security/security_connector/load_system_roots_fallback.cc +2 -2
  69. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +2 -2
  70. data/src/core/lib/security/security_connector/local/local_security_connector.cc +30 -3
  71. data/src/core/lib/security/security_connector/ssl_utils.cc +45 -3
  72. data/src/core/lib/security/security_connector/ssl_utils.h +12 -0
  73. data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.cc → tls_security_connector.cc} +82 -69
  74. data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.h → tls_security_connector.h} +17 -18
  75. data/src/core/lib/security/transport/client_auth_filter.cc +33 -0
  76. data/src/core/lib/surface/completion_queue.cc +22 -1
  77. data/src/core/lib/surface/version.cc +1 -1
  78. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +11 -1
  79. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +1 -1
  80. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +3 -3
  81. data/src/core/tsi/fake_transport_security.cc +7 -3
  82. data/src/core/tsi/fake_transport_security.h +2 -0
  83. data/src/core/tsi/ssl_transport_security.cc +144 -8
  84. data/src/core/tsi/ssl_transport_security.h +15 -1
  85. data/src/core/tsi/transport_security.cc +13 -0
  86. data/src/core/tsi/transport_security_grpc.cc +2 -2
  87. data/src/core/tsi/transport_security_grpc.h +2 -2
  88. data/src/core/tsi/transport_security_interface.h +12 -0
  89. data/src/ruby/bin/math_pb.rb +5 -5
  90. data/src/ruby/ext/grpc/rb_call_credentials.c +4 -1
  91. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  92. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  93. data/src/ruby/lib/grpc/version.rb +1 -1
  94. data/src/ruby/pb/grpc/health/v1/health_pb.rb +3 -3
  95. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +1 -1
  96. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +23 -13
  97. data/third_party/abseil-cpp/absl/algorithm/algorithm.h +159 -0
  98. data/third_party/abseil-cpp/absl/base/attributes.h +609 -0
  99. data/third_party/abseil-cpp/absl/base/call_once.h +226 -0
  100. data/third_party/abseil-cpp/absl/base/casts.h +184 -0
  101. data/third_party/abseil-cpp/absl/base/config.h +622 -0
  102. data/third_party/abseil-cpp/absl/base/const_init.h +76 -0
  103. data/third_party/abseil-cpp/absl/base/dynamic_annotations.cc +129 -0
  104. data/third_party/abseil-cpp/absl/base/dynamic_annotations.h +389 -0
  105. data/third_party/abseil-cpp/absl/base/internal/atomic_hook.h +179 -0
  106. data/third_party/abseil-cpp/absl/base/internal/bits.h +218 -0
  107. data/third_party/abseil-cpp/absl/base/internal/cycleclock.cc +107 -0
  108. data/third_party/abseil-cpp/absl/base/internal/cycleclock.h +94 -0
  109. data/third_party/abseil-cpp/absl/base/internal/endian.h +266 -0
  110. data/third_party/abseil-cpp/absl/base/internal/hide_ptr.h +51 -0
  111. data/third_party/abseil-cpp/absl/base/internal/identity.h +37 -0
  112. data/third_party/abseil-cpp/absl/base/internal/inline_variable.h +107 -0
  113. data/third_party/abseil-cpp/absl/base/internal/invoke.h +187 -0
  114. data/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h +107 -0
  115. data/third_party/abseil-cpp/absl/base/internal/per_thread_tls.h +52 -0
  116. data/third_party/abseil-cpp/absl/base/internal/raw_logging.cc +237 -0
  117. data/third_party/abseil-cpp/absl/base/internal/raw_logging.h +179 -0
  118. data/third_party/abseil-cpp/absl/base/internal/scheduling_mode.h +58 -0
  119. data/third_party/abseil-cpp/absl/base/internal/spinlock.cc +233 -0
  120. data/third_party/abseil-cpp/absl/base/internal/spinlock.h +243 -0
  121. data/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc +35 -0
  122. data/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc +67 -0
  123. data/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc +46 -0
  124. data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc +81 -0
  125. data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h +93 -0
  126. data/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc +37 -0
  127. data/third_party/abseil-cpp/absl/base/internal/sysinfo.cc +414 -0
  128. data/third_party/abseil-cpp/absl/base/internal/sysinfo.h +66 -0
  129. data/third_party/abseil-cpp/absl/base/internal/thread_annotations.h +271 -0
  130. data/third_party/abseil-cpp/absl/base/internal/thread_identity.cc +140 -0
  131. data/third_party/abseil-cpp/absl/base/internal/thread_identity.h +250 -0
  132. data/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc +108 -0
  133. data/third_party/abseil-cpp/absl/base/internal/throw_delegate.h +75 -0
  134. data/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h +66 -0
  135. data/third_party/abseil-cpp/absl/base/internal/unaligned_access.h +158 -0
  136. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +103 -0
  137. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h +124 -0
  138. data/third_party/abseil-cpp/absl/base/log_severity.cc +27 -0
  139. data/third_party/abseil-cpp/absl/base/log_severity.h +121 -0
  140. data/third_party/abseil-cpp/absl/base/macros.h +220 -0
  141. data/third_party/abseil-cpp/absl/base/optimization.h +181 -0
  142. data/third_party/abseil-cpp/absl/base/options.h +214 -0
  143. data/third_party/abseil-cpp/absl/base/policy_checks.h +111 -0
  144. data/third_party/abseil-cpp/absl/base/port.h +26 -0
  145. data/third_party/abseil-cpp/absl/base/thread_annotations.h +280 -0
  146. data/third_party/abseil-cpp/absl/container/inlined_vector.h +848 -0
  147. data/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h +265 -0
  148. data/third_party/abseil-cpp/absl/container/internal/inlined_vector.h +892 -0
  149. data/third_party/abseil-cpp/absl/memory/memory.h +695 -0
  150. data/third_party/abseil-cpp/absl/meta/type_traits.h +759 -0
  151. data/third_party/abseil-cpp/absl/numeric/int128.cc +404 -0
  152. data/third_party/abseil-cpp/absl/numeric/int128.h +1091 -0
  153. data/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc +302 -0
  154. data/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc +308 -0
  155. data/third_party/abseil-cpp/absl/strings/ascii.cc +200 -0
  156. data/third_party/abseil-cpp/absl/strings/ascii.h +241 -0
  157. data/third_party/abseil-cpp/absl/strings/charconv.cc +985 -0
  158. data/third_party/abseil-cpp/absl/strings/charconv.h +119 -0
  159. data/third_party/abseil-cpp/absl/strings/escaping.cc +949 -0
  160. data/third_party/abseil-cpp/absl/strings/escaping.h +164 -0
  161. data/third_party/abseil-cpp/absl/strings/internal/char_map.h +156 -0
  162. data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc +359 -0
  163. data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h +421 -0
  164. data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc +504 -0
  165. data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.h +99 -0
  166. data/third_party/abseil-cpp/absl/strings/internal/escaping.cc +180 -0
  167. data/third_party/abseil-cpp/absl/strings/internal/escaping.h +58 -0
  168. data/third_party/abseil-cpp/absl/strings/internal/memutil.cc +112 -0
  169. data/third_party/abseil-cpp/absl/strings/internal/memutil.h +148 -0
  170. data/third_party/abseil-cpp/absl/strings/internal/ostringstream.cc +36 -0
  171. data/third_party/abseil-cpp/absl/strings/internal/ostringstream.h +89 -0
  172. data/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h +73 -0
  173. data/third_party/abseil-cpp/absl/strings/internal/stl_type_traits.h +248 -0
  174. data/third_party/abseil-cpp/absl/strings/internal/str_join_internal.h +314 -0
  175. data/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h +455 -0
  176. data/third_party/abseil-cpp/absl/strings/internal/utf8.cc +53 -0
  177. data/third_party/abseil-cpp/absl/strings/internal/utf8.h +50 -0
  178. data/third_party/abseil-cpp/absl/strings/match.cc +40 -0
  179. data/third_party/abseil-cpp/absl/strings/match.h +90 -0
  180. data/third_party/abseil-cpp/absl/strings/numbers.cc +916 -0
  181. data/third_party/abseil-cpp/absl/strings/numbers.h +263 -0
  182. data/third_party/abseil-cpp/absl/strings/str_cat.cc +246 -0
  183. data/third_party/abseil-cpp/absl/strings/str_cat.h +408 -0
  184. data/third_party/abseil-cpp/absl/strings/str_join.h +293 -0
  185. data/third_party/abseil-cpp/absl/strings/str_replace.cc +82 -0
  186. data/third_party/abseil-cpp/absl/strings/str_replace.h +219 -0
  187. data/third_party/abseil-cpp/absl/strings/str_split.cc +139 -0
  188. data/third_party/abseil-cpp/absl/strings/str_split.h +513 -0
  189. data/third_party/abseil-cpp/absl/strings/string_view.cc +235 -0
  190. data/third_party/abseil-cpp/absl/strings/string_view.h +615 -0
  191. data/third_party/abseil-cpp/absl/strings/strip.h +91 -0
  192. data/third_party/abseil-cpp/absl/strings/substitute.cc +171 -0
  193. data/third_party/abseil-cpp/absl/strings/substitute.h +693 -0
  194. data/third_party/abseil-cpp/absl/types/bad_optional_access.cc +48 -0
  195. data/third_party/abseil-cpp/absl/types/bad_optional_access.h +78 -0
  196. data/third_party/abseil-cpp/absl/types/internal/optional.h +396 -0
  197. data/third_party/abseil-cpp/absl/types/internal/span.h +128 -0
  198. data/third_party/abseil-cpp/absl/types/optional.h +776 -0
  199. data/third_party/abseil-cpp/absl/types/span.h +713 -0
  200. data/third_party/abseil-cpp/absl/utility/utility.h +350 -0
  201. data/third_party/upb/upb/decode.c +4 -0
  202. data/third_party/upb/upb/port.c +0 -1
  203. data/third_party/upb/upb/port_def.inc +1 -3
  204. data/third_party/upb/upb/table.c +2 -1
  205. metadata +147 -43
  206. data/src/core/lib/json/json_common.h +0 -34
  207. data/src/core/lib/json/json_reader.h +0 -146
  208. data/src/core/lib/json/json_string.cc +0 -367
  209. data/src/core/lib/json/json_writer.h +0 -84
@@ -26,6 +26,7 @@
26
26
  #include <grpc/support/alloc.h>
27
27
  #include <grpc/support/log.h>
28
28
 
29
+ #include "src/core/lib/channel/channel_args.h"
29
30
  #include "src/core/lib/iomgr/error.h"
30
31
  #include "src/core/lib/iomgr/exec_ctx.h"
31
32
  #include "src/core/lib/iomgr/iomgr_custom.h"
@@ -72,6 +73,7 @@ struct grpc_tcp_server {
72
73
  grpc_closure* shutdown_complete;
73
74
 
74
75
  bool shutdown;
76
+ bool so_reuseport;
75
77
 
76
78
  grpc_resource_quota* resource_quota;
77
79
  };
@@ -80,8 +82,13 @@ static grpc_error* tcp_server_create(grpc_closure* shutdown_complete,
80
82
  const grpc_channel_args* args,
81
83
  grpc_tcp_server** server) {
82
84
  grpc_tcp_server* s = (grpc_tcp_server*)gpr_malloc(sizeof(grpc_tcp_server));
85
+ // Let the implementation decide if so_reuseport can be enabled or not.
86
+ s->so_reuseport = true;
83
87
  s->resource_quota = grpc_resource_quota_create(nullptr);
84
88
  for (size_t i = 0; i < (args == nullptr ? 0 : args->num_args); i++) {
89
+ if (!grpc_channel_args_find_bool(args, GRPC_ARG_ALLOW_REUSEPORT, true)) {
90
+ s->so_reuseport = false;
91
+ }
85
92
  if (0 == strcmp(GRPC_ARG_RESOURCE_QUOTA, args->args[i].key)) {
86
93
  if (args->args[i].type == GRPC_ARG_POINTER) {
87
94
  grpc_resource_quota_unref_internal(s->resource_quota);
@@ -280,9 +287,15 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s,
280
287
  grpc_error* error;
281
288
  grpc_resolved_address sockname_temp;
282
289
 
283
- // The last argument to uv_tcp_bind is flags
290
+ // NOTE(lidiz) The last argument is "flags" which is unused by other
291
+ // implementations. Python IO managers uses it to specify SO_REUSEPORT.
292
+ int flags = 0;
293
+ if (s->so_reuseport) {
294
+ flags |= GRPC_CUSTOM_SOCKET_OPT_SO_REUSEPORT;
295
+ }
296
+
284
297
  error = grpc_custom_socket_vtable->bind(socket, (grpc_sockaddr*)addr->addr,
285
- addr->len, 0);
298
+ addr->len, flags);
286
299
  if (error != GRPC_ERROR_NONE) {
287
300
  return error;
288
301
  }
@@ -157,6 +157,14 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd,
157
157
  if (err != GRPC_ERROR_NONE) goto error;
158
158
  }
159
159
 
160
+ #ifdef GRPC_LINUX_ERRQUEUE
161
+ err = grpc_set_socket_zerocopy(fd);
162
+ if (err != GRPC_ERROR_NONE) {
163
+ /* it's not fatal, so just log it. */
164
+ gpr_log(GPR_DEBUG, "Node does not support SO_ZEROCOPY, continuing.");
165
+ GRPC_ERROR_UNREF(err);
166
+ }
167
+ #endif
160
168
  err = grpc_set_socket_nonblocking(fd, 1);
161
169
  if (err != GRPC_ERROR_NONE) goto error;
162
170
  err = grpc_set_socket_cloexec(fd, 1);
@@ -24,7 +24,17 @@
24
24
  #include <stdbool.h>
25
25
  #include <stdlib.h>
26
26
 
27
- #include "src/core/lib/json/json_common.h"
27
+ /* The various json types. */
28
+ typedef enum {
29
+ GRPC_JSON_OBJECT,
30
+ GRPC_JSON_ARRAY,
31
+ GRPC_JSON_STRING,
32
+ GRPC_JSON_NUMBER,
33
+ GRPC_JSON_TRUE,
34
+ GRPC_JSON_FALSE,
35
+ GRPC_JSON_NULL,
36
+ GRPC_JSON_TOP_LEVEL
37
+ } grpc_json_type;
28
38
 
29
39
  /* A tree-like structure to hold json values. The key and value pointers
30
40
  * are not owned by it.
@@ -22,76 +22,227 @@
22
22
 
23
23
  #include <grpc/support/log.h>
24
24
 
25
- #include "src/core/lib/json/json_reader.h"
25
+ #include "src/core/lib/json/json.h"
26
+
27
+ typedef enum {
28
+ GRPC_JSON_STATE_OBJECT_KEY_BEGIN,
29
+ GRPC_JSON_STATE_OBJECT_KEY_STRING,
30
+ GRPC_JSON_STATE_OBJECT_KEY_END,
31
+ GRPC_JSON_STATE_VALUE_BEGIN,
32
+ GRPC_JSON_STATE_VALUE_STRING,
33
+ GRPC_JSON_STATE_STRING_ESCAPE,
34
+ GRPC_JSON_STATE_STRING_ESCAPE_U1,
35
+ GRPC_JSON_STATE_STRING_ESCAPE_U2,
36
+ GRPC_JSON_STATE_STRING_ESCAPE_U3,
37
+ GRPC_JSON_STATE_STRING_ESCAPE_U4,
38
+ GRPC_JSON_STATE_VALUE_NUMBER,
39
+ GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL,
40
+ GRPC_JSON_STATE_VALUE_NUMBER_ZERO,
41
+ GRPC_JSON_STATE_VALUE_NUMBER_DOT,
42
+ GRPC_JSON_STATE_VALUE_NUMBER_E,
43
+ GRPC_JSON_STATE_VALUE_NUMBER_EPM,
44
+ GRPC_JSON_STATE_VALUE_TRUE_R,
45
+ GRPC_JSON_STATE_VALUE_TRUE_U,
46
+ GRPC_JSON_STATE_VALUE_TRUE_E,
47
+ GRPC_JSON_STATE_VALUE_FALSE_A,
48
+ GRPC_JSON_STATE_VALUE_FALSE_L,
49
+ GRPC_JSON_STATE_VALUE_FALSE_S,
50
+ GRPC_JSON_STATE_VALUE_FALSE_E,
51
+ GRPC_JSON_STATE_VALUE_NULL_U,
52
+ GRPC_JSON_STATE_VALUE_NULL_L1,
53
+ GRPC_JSON_STATE_VALUE_NULL_L2,
54
+ GRPC_JSON_STATE_VALUE_END,
55
+ GRPC_JSON_STATE_END
56
+ } grpc_json_reader_state;
57
+
58
+ enum {
59
+ /* The first non-unicode value is 0x110000. But let's pick
60
+ * a value high enough to start our error codes from. These
61
+ * values are safe to return from the read_char function.
62
+ */
63
+ GRPC_JSON_READ_CHAR_EOF = 0x7ffffff0,
64
+ GRPC_JSON_READ_CHAR_EAGAIN,
65
+ GRPC_JSON_READ_CHAR_ERROR
66
+ };
67
+
68
+ typedef struct grpc_json_reader {
69
+ /* That structure is fully private, and initialized by grpc_json_reader_init.
70
+ * The definition is public so you can put it on your stack.
71
+ */
72
+
73
+ int depth;
74
+ int in_object;
75
+ int in_array;
76
+ int escaped_string_was_key;
77
+ int container_just_begun;
78
+ uint16_t unicode_char, unicode_high_surrogate;
79
+ grpc_json_reader_state state;
80
+
81
+ grpc_json* top;
82
+ grpc_json* current_container;
83
+ grpc_json* current_value;
84
+ uint8_t* input;
85
+ uint8_t* key;
86
+ uint8_t* string;
87
+ uint8_t* string_ptr;
88
+ size_t remaining_input;
89
+ } grpc_json_reader;
90
+
91
+ /* The return type of the parser. */
92
+ typedef enum {
93
+ GRPC_JSON_DONE, /* The parser finished successfully. */
94
+ GRPC_JSON_EAGAIN, /* The parser yields to get more data. */
95
+ GRPC_JSON_READ_ERROR, /* The parser passes through a read error. */
96
+ GRPC_JSON_PARSE_ERROR, /* The parser found an error in the json stream. */
97
+ GRPC_JSON_INTERNAL_ERROR /* The parser got an internal error. */
98
+ } grpc_json_reader_status;
26
99
 
27
100
  static void json_reader_string_clear(grpc_json_reader* reader) {
28
- reader->vtable->string_clear(reader->userdata);
101
+ if (reader->string) {
102
+ GPR_ASSERT(reader->string_ptr < reader->input);
103
+ *reader->string_ptr++ = 0;
104
+ }
105
+ reader->string = reader->string_ptr;
29
106
  }
30
107
 
31
108
  static void json_reader_string_add_char(grpc_json_reader* reader, uint32_t c) {
32
- reader->vtable->string_add_char(reader->userdata, c);
109
+ GPR_ASSERT(reader->string_ptr < reader->input);
110
+ GPR_ASSERT(c <= 0xff);
111
+ *reader->string_ptr++ = static_cast<uint8_t>(c);
33
112
  }
34
113
 
35
- static void json_reader_string_add_utf32(grpc_json_reader* reader,
36
- uint32_t utf32) {
37
- reader->vtable->string_add_utf32(reader->userdata, utf32);
114
+ static void json_reader_string_add_utf32(grpc_json_reader* reader, uint32_t c) {
115
+ if (c <= 0x7f) {
116
+ json_reader_string_add_char(reader, c);
117
+ } else if (c <= 0x7ff) {
118
+ uint32_t b1 = 0xc0 | ((c >> 6) & 0x1f);
119
+ uint32_t b2 = 0x80 | (c & 0x3f);
120
+ json_reader_string_add_char(reader, b1);
121
+ json_reader_string_add_char(reader, b2);
122
+ } else if (c <= 0xffff) {
123
+ uint32_t b1 = 0xe0 | ((c >> 12) & 0x0f);
124
+ uint32_t b2 = 0x80 | ((c >> 6) & 0x3f);
125
+ uint32_t b3 = 0x80 | (c & 0x3f);
126
+ json_reader_string_add_char(reader, b1);
127
+ json_reader_string_add_char(reader, b2);
128
+ json_reader_string_add_char(reader, b3);
129
+ } else if (c <= 0x1fffff) {
130
+ uint32_t b1 = 0xf0 | ((c >> 18) & 0x07);
131
+ uint32_t b2 = 0x80 | ((c >> 12) & 0x3f);
132
+ uint32_t b3 = 0x80 | ((c >> 6) & 0x3f);
133
+ uint32_t b4 = 0x80 | (c & 0x3f);
134
+ json_reader_string_add_char(reader, b1);
135
+ json_reader_string_add_char(reader, b2);
136
+ json_reader_string_add_char(reader, b3);
137
+ json_reader_string_add_char(reader, b4);
138
+ }
38
139
  }
39
140
 
40
141
  static uint32_t grpc_json_reader_read_char(grpc_json_reader* reader) {
41
- return reader->vtable->read_char(reader->userdata);
142
+ if (reader->remaining_input == 0) return GRPC_JSON_READ_CHAR_EOF;
143
+ uint32_t r = *reader->input++;
144
+ reader->remaining_input--;
145
+ if (r == 0) {
146
+ reader->remaining_input = 0;
147
+ return GRPC_JSON_READ_CHAR_EOF;
148
+ }
149
+ return r;
150
+ }
151
+
152
+ /* Helper function to create a new grpc_json object and link it into
153
+ * our tree-in-progress inside our opaque structure.
154
+ */
155
+ static grpc_json* json_create_and_link(grpc_json_reader* reader,
156
+ grpc_json_type type) {
157
+ grpc_json* json = grpc_json_create(type);
158
+ json->parent = reader->current_container;
159
+ json->prev = reader->current_value;
160
+ reader->current_value = json;
161
+ if (json->prev) {
162
+ json->prev->next = json;
163
+ }
164
+ if (json->parent) {
165
+ if (!json->parent->child) {
166
+ json->parent->child = json;
167
+ }
168
+ if (json->parent->type == GRPC_JSON_OBJECT) {
169
+ json->key = reinterpret_cast<char*>(reader->key);
170
+ }
171
+ }
172
+ if (!reader->top) {
173
+ reader->top = json;
174
+ }
175
+ return json;
42
176
  }
43
177
 
44
178
  static void json_reader_container_begins(grpc_json_reader* reader,
45
179
  grpc_json_type type) {
46
- reader->vtable->container_begins(reader->userdata, type);
180
+ GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT);
181
+ grpc_json* container = json_create_and_link(reader, type);
182
+ reader->current_container = container;
183
+ reader->current_value = nullptr;
47
184
  }
48
185
 
49
186
  static grpc_json_type grpc_json_reader_container_ends(
50
187
  grpc_json_reader* reader) {
51
- return reader->vtable->container_ends(reader->userdata);
188
+ grpc_json_type container_type = GRPC_JSON_TOP_LEVEL;
189
+ GPR_ASSERT(reader->current_container);
190
+ reader->current_value = reader->current_container;
191
+ reader->current_container = reader->current_container->parent;
192
+ if (reader->current_container) {
193
+ container_type = reader->current_container->type;
194
+ }
195
+ return container_type;
52
196
  }
53
197
 
54
198
  static void json_reader_set_key(grpc_json_reader* reader) {
55
- reader->vtable->set_key(reader->userdata);
199
+ reader->key = reader->string;
56
200
  }
57
201
 
58
202
  static void json_reader_set_string(grpc_json_reader* reader) {
59
- reader->vtable->set_string(reader->userdata);
203
+ grpc_json* json = json_create_and_link(reader, GRPC_JSON_STRING);
204
+ json->value = reinterpret_cast<char*>(reader->string);
60
205
  }
61
206
 
62
207
  static int json_reader_set_number(grpc_json_reader* reader) {
63
- return reader->vtable->set_number(reader->userdata);
208
+ grpc_json* json = json_create_and_link(reader, GRPC_JSON_NUMBER);
209
+ json->value = reinterpret_cast<char*>(reader->string);
210
+ return 1;
64
211
  }
65
212
 
66
213
  static void json_reader_set_true(grpc_json_reader* reader) {
67
- reader->vtable->set_true(reader->userdata);
214
+ json_create_and_link(reader, GRPC_JSON_TRUE);
68
215
  }
69
216
 
70
217
  static void json_reader_set_false(grpc_json_reader* reader) {
71
- reader->vtable->set_false(reader->userdata);
218
+ json_create_and_link(reader, GRPC_JSON_FALSE);
72
219
  }
73
220
 
74
221
  static void json_reader_set_null(grpc_json_reader* reader) {
75
- reader->vtable->set_null(reader->userdata);
76
- }
77
-
78
- /* Call this function to initialize the reader structure. */
79
- void grpc_json_reader_init(grpc_json_reader* reader,
80
- grpc_json_reader_vtable* vtable, void* userdata) {
81
- memset(reader, 0, sizeof(*reader));
82
- reader->vtable = vtable;
83
- reader->userdata = userdata;
84
- json_reader_string_clear(reader);
85
- reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
222
+ json_create_and_link(reader, GRPC_JSON_NULL);
86
223
  }
87
224
 
88
- int grpc_json_reader_is_complete(grpc_json_reader* reader) {
225
+ static int json_reader_is_complete(grpc_json_reader* reader) {
89
226
  return ((reader->depth == 0) &&
90
227
  ((reader->state == GRPC_JSON_STATE_END) ||
91
228
  (reader->state == GRPC_JSON_STATE_VALUE_END)));
92
229
  }
93
230
 
94
- grpc_json_reader_status grpc_json_reader_run(grpc_json_reader* reader) {
231
+ /* Call this function to start parsing the input. It will return the following:
232
+ * . GRPC_JSON_DONE if the input got eof, and the parsing finished
233
+ * successfully.
234
+ * . GRPC_JSON_EAGAIN if the read_char function returned again. Call the
235
+ * parser again as needed. It is okay to call the parser in polling mode,
236
+ * although a bit dull.
237
+ * . GRPC_JSON_READ_ERROR if the read_char function returned an error. The
238
+ * state isn't broken however, and the function can be called again if the
239
+ * error has been corrected. But please use the EAGAIN feature instead for
240
+ * consistency.
241
+ * . GRPC_JSON_PARSE_ERROR if the input was somehow invalid.
242
+ * . GRPC_JSON_INTERNAL_ERROR if the parser somehow ended into an invalid
243
+ * internal state.
244
+ */
245
+ static grpc_json_reader_status grpc_json_reader_run(grpc_json_reader* reader) {
95
246
  uint32_t c, success;
96
247
 
97
248
  /* This state-machine is a strict implementation of ECMA-404 */
@@ -106,7 +257,7 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader* reader) {
106
257
  return GRPC_JSON_EAGAIN;
107
258
 
108
259
  case GRPC_JSON_READ_CHAR_EOF:
109
- if (grpc_json_reader_is_complete(reader)) {
260
+ if (json_reader_is_complete(reader)) {
110
261
  return GRPC_JSON_DONE;
111
262
  } else {
112
263
  return GRPC_JSON_PARSE_ERROR;
@@ -661,3 +812,30 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader* reader) {
661
812
 
662
813
  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
663
814
  }
815
+
816
+ /* And finally, let's define our public API. */
817
+ grpc_json* grpc_json_parse_string_with_len(char* input, size_t size) {
818
+ if (input == nullptr) return nullptr;
819
+ // Initialize reader.
820
+ grpc_json_reader reader;
821
+ memset(&reader, 0, sizeof(reader));
822
+ reader.string_ptr = reader.input = reinterpret_cast<uint8_t*>(input);
823
+ reader.remaining_input = size;
824
+ json_reader_string_clear(&reader);
825
+ reader.state = GRPC_JSON_STATE_VALUE_BEGIN;
826
+ // Perform read.
827
+ grpc_json_reader_status status = grpc_json_reader_run(&reader);
828
+ // Process results.
829
+ grpc_json* json = reader.top;
830
+ if ((status != GRPC_JSON_DONE) && json != nullptr) {
831
+ grpc_json_destroy(json);
832
+ json = nullptr;
833
+ }
834
+ return json;
835
+ }
836
+
837
+ #define UNBOUND_JSON_STRING_LENGTH 0x7fffffff
838
+
839
+ grpc_json* grpc_json_parse_string(char* input) {
840
+ return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH);
841
+ }
@@ -18,31 +18,70 @@
18
18
 
19
19
  #include <grpc/support/port_platform.h>
20
20
 
21
+ #include <stdlib.h>
21
22
  #include <string.h>
22
23
 
23
- #include "src/core/lib/json/json_writer.h"
24
+ #include <grpc/support/alloc.h>
25
+ #include <grpc/support/log.h>
24
26
 
25
- static void json_writer_output_char(grpc_json_writer* writer, char c) {
26
- writer->vtable->output_char(writer->userdata, c);
27
+ #include "src/core/lib/json/json.h"
28
+
29
+ /* The idea of the writer is basically symmetrical of the reader. While the
30
+ * reader emits various calls to your code, the writer takes basically the
31
+ * same calls and emit json out of it. It doesn't try to make any check on
32
+ * the order of the calls you do on it. Meaning you can theorically force
33
+ * it to generate invalid json.
34
+ *
35
+ * Also, unlike the reader, the writer expects UTF-8 encoded input strings.
36
+ * These strings will be UTF-8 validated, and any invalid character will
37
+ * cut the conversion short, before any invalid UTF-8 sequence, thus forming
38
+ * a valid UTF-8 string overall.
39
+ */
40
+
41
+ typedef struct grpc_json_writer {
42
+ int indent;
43
+ int depth;
44
+ int container_empty;
45
+ int got_key;
46
+ char* output;
47
+ size_t free_space;
48
+ size_t string_len;
49
+ size_t allocated;
50
+ } grpc_json_writer;
51
+
52
+ /* This function checks if there's enough space left in the output buffer,
53
+ * and will enlarge it if necessary. We're only allocating chunks of 256
54
+ * bytes at a time (or multiples thereof).
55
+ */
56
+ static void json_writer_output_check(grpc_json_writer* writer, size_t needed) {
57
+ if (writer->free_space >= needed) return;
58
+ needed -= writer->free_space;
59
+ /* Round up by 256 bytes. */
60
+ needed = (needed + 0xff) & ~0xffU;
61
+ writer->output = static_cast<char*>(
62
+ gpr_realloc(writer->output, writer->allocated + needed));
63
+ writer->free_space += needed;
64
+ writer->allocated += needed;
27
65
  }
28
66
 
29
- static void json_writer_output_string(grpc_json_writer* writer,
30
- const char* str) {
31
- writer->vtable->output_string(writer->userdata, str);
67
+ static void json_writer_output_char(grpc_json_writer* writer, char c) {
68
+ json_writer_output_check(writer, 1);
69
+ writer->output[writer->string_len++] = c;
70
+ writer->free_space--;
32
71
  }
33
72
 
34
73
  static void json_writer_output_string_with_len(grpc_json_writer* writer,
35
74
  const char* str, size_t len) {
36
- writer->vtable->output_string_with_len(writer->userdata, str, len);
75
+ json_writer_output_check(writer, len);
76
+ memcpy(writer->output + writer->string_len, str, len);
77
+ writer->string_len += len;
78
+ writer->free_space -= len;
37
79
  }
38
80
 
39
- void grpc_json_writer_init(grpc_json_writer* writer, int indent,
40
- grpc_json_writer_vtable* vtable, void* userdata) {
41
- memset(writer, 0, sizeof(*writer));
42
- writer->container_empty = 1;
43
- writer->indent = indent;
44
- writer->vtable = vtable;
45
- writer->userdata = userdata;
81
+ static void json_writer_output_string(grpc_json_writer* writer,
82
+ const char* str) {
83
+ size_t len = strlen(str);
84
+ json_writer_output_string_with_len(writer, str, len);
46
85
  }
47
86
 
48
87
  static void json_writer_output_indent(grpc_json_writer* writer) {
@@ -192,8 +231,8 @@ static void json_writer_escape_string(grpc_json_writer* writer,
192
231
  json_writer_output_char(writer, '"');
193
232
  }
194
233
 
195
- void grpc_json_writer_container_begins(grpc_json_writer* writer,
196
- grpc_json_type type) {
234
+ static void grpc_json_writer_container_begins(grpc_json_writer* writer,
235
+ grpc_json_type type) {
197
236
  if (!writer->got_key) json_writer_value_end(writer);
198
237
  json_writer_output_indent(writer);
199
238
  json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '[');
@@ -202,8 +241,8 @@ void grpc_json_writer_container_begins(grpc_json_writer* writer,
202
241
  writer->depth++;
203
242
  }
204
243
 
205
- void grpc_json_writer_container_ends(grpc_json_writer* writer,
206
- grpc_json_type type) {
244
+ static void grpc_json_writer_container_ends(grpc_json_writer* writer,
245
+ grpc_json_type type) {
207
246
  if (writer->indent && !writer->container_empty)
208
247
  json_writer_output_char(writer, '\n');
209
248
  writer->depth--;
@@ -213,7 +252,8 @@ void grpc_json_writer_container_ends(grpc_json_writer* writer,
213
252
  writer->got_key = 0;
214
253
  }
215
254
 
216
- void grpc_json_writer_object_key(grpc_json_writer* writer, const char* string) {
255
+ static void grpc_json_writer_object_key(grpc_json_writer* writer,
256
+ const char* string) {
217
257
  json_writer_value_end(writer);
218
258
  json_writer_output_indent(writer);
219
259
  json_writer_escape_string(writer, string);
@@ -221,25 +261,72 @@ void grpc_json_writer_object_key(grpc_json_writer* writer, const char* string) {
221
261
  writer->got_key = 1;
222
262
  }
223
263
 
224
- void grpc_json_writer_value_raw(grpc_json_writer* writer, const char* string) {
264
+ static void grpc_json_writer_value_raw(grpc_json_writer* writer,
265
+ const char* string) {
225
266
  if (!writer->got_key) json_writer_value_end(writer);
226
267
  json_writer_output_indent(writer);
227
268
  json_writer_output_string(writer, string);
228
269
  writer->got_key = 0;
229
270
  }
230
271
 
231
- void grpc_json_writer_value_raw_with_len(grpc_json_writer* writer,
232
- const char* string, size_t len) {
272
+ static void grpc_json_writer_value_raw_with_len(grpc_json_writer* writer,
273
+ const char* string,
274
+ size_t len) {
233
275
  if (!writer->got_key) json_writer_value_end(writer);
234
276
  json_writer_output_indent(writer);
235
277
  json_writer_output_string_with_len(writer, string, len);
236
278
  writer->got_key = 0;
237
279
  }
238
280
 
239
- void grpc_json_writer_value_string(grpc_json_writer* writer,
240
- const char* string) {
281
+ static void grpc_json_writer_value_string(grpc_json_writer* writer,
282
+ const char* string) {
241
283
  if (!writer->got_key) json_writer_value_end(writer);
242
284
  json_writer_output_indent(writer);
243
285
  json_writer_escape_string(writer, string);
244
286
  writer->got_key = 0;
245
287
  }
288
+
289
+ static void json_dump_recursive(grpc_json_writer* writer, const grpc_json* json,
290
+ int in_object) {
291
+ while (json) {
292
+ if (in_object) grpc_json_writer_object_key(writer, json->key);
293
+ switch (json->type) {
294
+ case GRPC_JSON_OBJECT:
295
+ case GRPC_JSON_ARRAY:
296
+ grpc_json_writer_container_begins(writer, json->type);
297
+ if (json->child)
298
+ json_dump_recursive(writer, json->child,
299
+ json->type == GRPC_JSON_OBJECT);
300
+ grpc_json_writer_container_ends(writer, json->type);
301
+ break;
302
+ case GRPC_JSON_STRING:
303
+ grpc_json_writer_value_string(writer, json->value);
304
+ break;
305
+ case GRPC_JSON_NUMBER:
306
+ grpc_json_writer_value_raw(writer, json->value);
307
+ break;
308
+ case GRPC_JSON_TRUE:
309
+ grpc_json_writer_value_raw_with_len(writer, "true", 4);
310
+ break;
311
+ case GRPC_JSON_FALSE:
312
+ grpc_json_writer_value_raw_with_len(writer, "false", 5);
313
+ break;
314
+ case GRPC_JSON_NULL:
315
+ grpc_json_writer_value_raw_with_len(writer, "null", 4);
316
+ break;
317
+ default:
318
+ GPR_UNREACHABLE_CODE(abort());
319
+ }
320
+ json = json->next;
321
+ }
322
+ }
323
+
324
+ char* grpc_json_dump_to_string(const grpc_json* json, int indent) {
325
+ grpc_json_writer writer;
326
+ memset(&writer, 0, sizeof(writer));
327
+ writer.container_empty = 1;
328
+ writer.indent = indent;
329
+ json_dump_recursive(&writer, json, 0);
330
+ json_writer_output_char(&writer, 0);
331
+ return writer.output;
332
+ }