grpc 1.22.0 → 1.23.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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +487 -649
  3. data/include/grpc/grpc_security.h +25 -0
  4. data/include/grpc/impl/codegen/grpc_types.h +11 -2
  5. data/include/grpc/impl/codegen/port_platform.h +12 -0
  6. data/src/core/ext/filters/client_channel/backup_poller.cc +4 -2
  7. data/src/core/ext/filters/client_channel/client_channel.cc +477 -182
  8. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +25 -16
  9. data/src/core/ext/filters/client_channel/client_channel_channelz.h +11 -6
  10. data/src/core/ext/filters/client_channel/connector.h +10 -2
  11. data/src/core/ext/filters/client_channel/health/health_check_client.cc +3 -3
  12. data/src/core/ext/filters/client_channel/http_proxy.cc +9 -10
  13. data/src/core/ext/filters/client_channel/lb_policy.cc +2 -17
  14. data/src/core/ext/filters/client_channel/lb_policy.h +36 -8
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +22 -8
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +86 -52
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h +7 -0
  18. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +73 -72
  19. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +8 -12
  20. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +25 -101
  21. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +5 -5
  22. data/src/core/ext/filters/client_channel/parse_address.cc +29 -26
  23. data/src/core/ext/filters/client_channel/resolver.h +3 -11
  24. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +5 -3
  25. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +405 -82
  26. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +44 -51
  27. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +0 -1
  28. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +0 -1
  29. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +11 -6
  30. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +130 -65
  31. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +8 -3
  32. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +31 -14
  33. data/src/core/ext/filters/client_channel/resolver_factory.h +4 -0
  34. data/src/core/ext/filters/client_channel/resolver_registry.cc +11 -0
  35. data/src/core/ext/filters/client_channel/resolver_registry.h +3 -0
  36. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +10 -49
  37. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +1 -14
  38. data/src/core/ext/filters/client_channel/retry_throttle.h +2 -3
  39. data/src/core/ext/filters/client_channel/subchannel.cc +65 -58
  40. data/src/core/ext/filters/client_channel/subchannel.h +65 -45
  41. data/src/core/ext/filters/client_channel/subchannel_interface.h +15 -30
  42. data/src/core/ext/filters/client_idle/client_idle_filter.cc +262 -0
  43. data/src/core/ext/filters/http/client/http_client_filter.cc +4 -5
  44. data/src/core/ext/filters/http/client_authority_filter.cc +2 -2
  45. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +140 -152
  46. data/src/core/ext/filters/max_age/max_age_filter.cc +3 -3
  47. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +3 -4
  48. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +7 -6
  49. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +63 -38
  50. data/src/core/ext/transport/chttp2/transport/context_list.cc +3 -1
  51. data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -4
  52. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +1 -1
  53. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +1 -0
  54. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +8 -0
  55. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +7 -0
  56. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +1 -0
  57. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +37 -22
  58. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +136 -81
  59. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +8 -0
  60. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +7 -166
  61. data/src/core/ext/transport/chttp2/transport/hpack_table.h +41 -15
  62. data/src/core/ext/transport/chttp2/transport/internal.h +13 -2
  63. data/src/core/ext/transport/chttp2/transport/parsing.cc +35 -22
  64. data/src/core/ext/transport/chttp2/transport/stream_map.cc +28 -18
  65. data/src/core/ext/transport/chttp2/transport/writing.cc +1 -0
  66. data/src/core/ext/transport/inproc/inproc_transport.cc +1 -1
  67. data/src/core/lib/channel/channelz.cc +80 -33
  68. data/src/core/lib/channel/channelz.h +28 -13
  69. data/src/core/lib/compression/compression.cc +1 -2
  70. data/src/core/lib/compression/compression_args.cc +13 -6
  71. data/src/core/lib/compression/compression_args.h +3 -2
  72. data/src/core/lib/compression/compression_internal.cc +1 -1
  73. data/src/core/lib/gpr/env_linux.cc +10 -21
  74. data/src/core/lib/gpr/env_posix.cc +0 -5
  75. data/src/core/lib/gpr/string.cc +7 -2
  76. data/src/core/lib/gpr/string.h +1 -0
  77. data/src/core/lib/gpr/sync_posix.cc +0 -129
  78. data/src/core/lib/gprpp/debug_location.h +3 -2
  79. data/src/core/lib/gprpp/fork.cc +14 -21
  80. data/src/core/lib/gprpp/fork.h +15 -4
  81. data/src/core/lib/gprpp/host_port.cc +118 -0
  82. data/src/core/lib/{gpr → gprpp}/host_port.h +27 -11
  83. data/src/core/lib/gprpp/map.h +25 -0
  84. data/src/core/lib/gprpp/memory.h +26 -9
  85. data/src/core/lib/gprpp/ref_counted.h +63 -21
  86. data/src/core/lib/gprpp/string_view.h +143 -0
  87. data/src/core/lib/gprpp/thd.h +10 -1
  88. data/src/core/lib/gprpp/thd_posix.cc +25 -0
  89. data/src/core/lib/gprpp/thd_windows.cc +9 -1
  90. data/src/core/lib/http/httpcli_security_connector.cc +3 -1
  91. data/src/core/lib/iomgr/cfstream_handle.cc +6 -1
  92. data/src/core/lib/iomgr/cfstream_handle.h +8 -2
  93. data/src/core/lib/iomgr/combiner.cc +4 -4
  94. data/src/core/lib/iomgr/error.cc +18 -8
  95. data/src/core/lib/iomgr/error.h +2 -0
  96. data/src/core/lib/iomgr/ev_posix.cc +4 -2
  97. data/src/core/lib/iomgr/executor.cc +4 -1
  98. data/src/core/lib/iomgr/executor/mpmcqueue.cc +183 -0
  99. data/src/core/lib/iomgr/executor/mpmcqueue.h +178 -0
  100. data/src/core/lib/iomgr/executor/threadpool.cc +138 -0
  101. data/src/core/lib/iomgr/executor/threadpool.h +153 -0
  102. data/src/core/lib/iomgr/fork_posix.cc +4 -2
  103. data/src/core/lib/iomgr/iocp_windows.cc +2 -2
  104. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +14 -0
  105. data/src/core/lib/iomgr/iomgr_uv.cc +3 -0
  106. data/src/core/lib/iomgr/lockfree_event.cc +3 -3
  107. data/src/core/lib/iomgr/resolve_address_custom.cc +16 -20
  108. data/src/core/lib/iomgr/resolve_address_posix.cc +8 -10
  109. data/src/core/lib/iomgr/resolve_address_windows.cc +6 -8
  110. data/src/core/lib/iomgr/sockaddr_utils.cc +5 -3
  111. data/src/core/lib/iomgr/socket_utils_common_posix.cc +0 -1
  112. data/src/core/lib/iomgr/socket_windows.h +1 -1
  113. data/src/core/lib/iomgr/tcp_client_cfstream.cc +7 -6
  114. data/src/core/lib/iomgr/tcp_client_custom.cc +1 -0
  115. data/src/core/lib/iomgr/tcp_custom.cc +4 -0
  116. data/src/core/lib/iomgr/tcp_posix.cc +8 -2
  117. data/src/core/lib/iomgr/tcp_server_custom.cc +1 -0
  118. data/src/core/lib/iomgr/tcp_server_windows.cc +1 -1
  119. data/src/core/lib/iomgr/tcp_windows.cc +7 -7
  120. data/src/core/lib/iomgr/timer_custom.cc +1 -0
  121. data/src/core/lib/iomgr/timer_manager.cc +0 -29
  122. data/src/core/lib/security/credentials/credentials.cc +84 -0
  123. data/src/core/lib/security/credentials/credentials.h +58 -2
  124. data/src/core/lib/security/credentials/jwt/json_token.cc +6 -2
  125. data/src/core/lib/security/credentials/jwt/json_token.h +1 -1
  126. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +245 -24
  127. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +16 -0
  128. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +3 -2
  129. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +21 -25
  130. data/src/core/lib/security/security_connector/local/local_security_connector.cc +3 -2
  131. data/src/core/lib/security/security_connector/security_connector.cc +1 -1
  132. data/src/core/lib/security/security_connector/security_connector.h +1 -1
  133. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +19 -19
  134. data/src/core/lib/security/security_connector/ssl_utils.cc +26 -31
  135. data/src/core/lib/security/security_connector/ssl_utils.h +11 -8
  136. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +16 -20
  137. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +4 -3
  138. data/src/core/lib/security/transport/client_auth_filter.cc +1 -2
  139. data/src/core/lib/security/util/json_util.cc +19 -5
  140. data/src/core/lib/security/util/json_util.h +3 -1
  141. data/src/core/lib/slice/slice.cc +69 -50
  142. data/src/core/lib/slice/slice_buffer.cc +6 -5
  143. data/src/core/lib/slice/slice_hash_table.h +3 -7
  144. data/src/core/lib/slice/slice_intern.cc +130 -39
  145. data/src/core/lib/slice/slice_internal.h +8 -0
  146. data/src/core/lib/slice/slice_utils.h +120 -0
  147. data/src/core/lib/slice/slice_weak_hash_table.h +2 -7
  148. data/src/core/lib/surface/call.cc +8 -3
  149. data/src/core/lib/surface/channel.cc +31 -8
  150. data/src/core/lib/surface/completion_queue.cc +17 -7
  151. data/src/core/lib/surface/init_secure.cc +4 -1
  152. data/src/core/lib/surface/lame_client.cc +2 -2
  153. data/src/core/lib/surface/server.cc +34 -35
  154. data/src/core/lib/surface/server.h +8 -17
  155. data/src/core/lib/surface/version.cc +1 -1
  156. data/src/core/lib/transport/byte_stream.cc +3 -5
  157. data/src/core/lib/transport/byte_stream.h +1 -2
  158. data/src/core/lib/transport/error_utils.cc +10 -1
  159. data/src/core/lib/transport/metadata.cc +202 -35
  160. data/src/core/lib/transport/metadata.h +81 -6
  161. data/src/core/lib/transport/static_metadata.cc +1257 -465
  162. data/src/core/lib/transport/static_metadata.h +190 -347
  163. data/src/core/lib/transport/timeout_encoding.cc +7 -0
  164. data/src/core/lib/transport/timeout_encoding.h +3 -2
  165. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -0
  166. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +0 -1
  167. data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +2 -7
  168. data/src/core/tsi/ssl_transport_security.cc +35 -43
  169. data/src/core/tsi/ssl_transport_security.h +2 -1
  170. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  171. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
  172. data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
  173. data/src/ruby/lib/grpc/grpc.rb +1 -1
  174. data/src/ruby/lib/grpc/version.rb +1 -1
  175. metadata +39 -33
  176. data/src/core/lib/gpr/host_port.cc +0 -98
@@ -47,7 +47,7 @@
47
47
 
48
48
  namespace {
49
49
  struct channel_data {
50
- /* We take a reference to the channel stack for the timer callback */
50
+ /* The channel stack to which we take refs for pending callbacks. */
51
51
  grpc_channel_stack* channel_stack;
52
52
  /* Guards access to max_age_timer, max_age_timer_pending, max_age_grace_timer
53
53
  and max_age_grace_timer_pending */
@@ -122,8 +122,8 @@ struct channel_data {
122
122
 
123
123
  MAX_IDLE_STATE_SEEN_ENTER_IDLE: The state after the timer is set and the at
124
124
  least one call has arrived after the timer is set, BUT the channel
125
- currently has 1 or 1+ active calls. If the timer is fired in this state, we
126
- will reschudle it.
125
+ currently has 0 active calls. If the timer is fired in this state, we will
126
+ reschudle it.
127
127
 
128
128
  max_idle_timer will not be cancelled (unless the channel is shutting down).
129
129
  If the timer callback is called when the max_idle_timer is valid (i.e.
@@ -111,15 +111,14 @@ static void on_handshake_done(void* arg, grpc_error* error) {
111
111
  } else {
112
112
  error = GRPC_ERROR_REF(error);
113
113
  }
114
- memset(c->result, 0, sizeof(*c->result));
114
+ c->result->reset();
115
115
  } else {
116
116
  grpc_endpoint_delete_from_pollset_set(args->endpoint,
117
117
  c->args.interested_parties);
118
118
  c->result->transport =
119
119
  grpc_create_chttp2_transport(args->args, args->endpoint, true);
120
- grpc_core::RefCountedPtr<grpc_core::channelz::SocketNode> socket_node =
120
+ c->result->socket =
121
121
  grpc_chttp2_transport_get_socket_node(c->result->transport);
122
- c->result->socket_uuid = socket_node == nullptr ? 0 : socket_node->uuid();
123
122
  GPR_ASSERT(c->result->transport);
124
123
  // TODO(roth): We ideally want to wait until we receive HTTP/2
125
124
  // settings from the server before we consider the connection
@@ -180,7 +179,7 @@ static void connected(void* arg, grpc_error* error) {
180
179
  } else {
181
180
  error = GRPC_ERROR_REF(error);
182
181
  }
183
- memset(c->result, 0, sizeof(*c->result));
182
+ c->result->reset();
184
183
  grpc_closure* notify = c->notify;
185
184
  c->notify = nullptr;
186
185
  GRPC_CLOSURE_SCHED(notify, error);
@@ -37,7 +37,6 @@
37
37
  #include "src/core/lib/channel/channel_args.h"
38
38
  #include "src/core/lib/channel/handshaker.h"
39
39
  #include "src/core/lib/channel/handshaker_registry.h"
40
- #include "src/core/lib/gpr/host_port.h"
41
40
  #include "src/core/lib/iomgr/endpoint.h"
42
41
  #include "src/core/lib/iomgr/resolve_address.h"
43
42
  #include "src/core/lib/iomgr/resource_quota.h"
@@ -318,7 +317,7 @@ static grpc_error* chttp2_server_add_acceptor(grpc_server* server,
318
317
  *arg_val = grpc_tcp_server_create_fd_handler(tcp_server);
319
318
 
320
319
  grpc_server_add_listener(server, state, server_start_listener,
321
- server_destroy_listener, /* socket_uuid */ 0);
320
+ server_destroy_listener, /* node */ nullptr);
322
321
  return err;
323
322
 
324
323
  /* Error path: cleanup and return */
@@ -346,7 +345,6 @@ grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr,
346
345
  grpc_error** errors = nullptr;
347
346
  size_t naddrs = 0;
348
347
  const grpc_arg* arg = nullptr;
349
- intptr_t socket_uuid = 0;
350
348
 
351
349
  *port_num = -1;
352
350
 
@@ -414,15 +412,18 @@ grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr,
414
412
 
415
413
  arg = grpc_channel_args_find(args, GRPC_ARG_ENABLE_CHANNELZ);
416
414
  if (grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT)) {
415
+ char* socket_name = nullptr;
416
+ gpr_asprintf(&socket_name, "chttp2 listener %s", addr);
417
417
  state->channelz_listen_socket =
418
418
  grpc_core::MakeRefCounted<grpc_core::channelz::ListenSocketNode>(
419
- grpc_core::UniquePtr<char>(gpr_strdup(addr)));
420
- socket_uuid = state->channelz_listen_socket->uuid();
419
+ grpc_core::UniquePtr<char>(gpr_strdup(addr)),
420
+ grpc_core::UniquePtr<char>(socket_name));
421
421
  }
422
422
 
423
423
  /* Register with the server only upon success */
424
424
  grpc_server_add_listener(server, state, server_start_listener,
425
- server_destroy_listener, socket_uuid);
425
+ server_destroy_listener,
426
+ state->channelz_listen_socket);
426
427
  goto done;
427
428
 
428
429
  /* Error path: cleanup and return */
@@ -74,6 +74,8 @@
74
74
  #define DEFAULT_MAX_PINGS_BETWEEN_DATA 2
75
75
  #define DEFAULT_MAX_PING_STRIKES 2
76
76
 
77
+ #define DEFAULT_MAX_PENDING_INDUCED_FRAMES 10000
78
+
77
79
  static int g_default_client_keepalive_time_ms =
78
80
  DEFAULT_CLIENT_KEEPALIVE_TIME_MS;
79
81
  static int g_default_client_keepalive_timeout_ms =
@@ -105,6 +107,7 @@ static void write_action(void* t, grpc_error* error);
105
107
  static void write_action_end_locked(void* t, grpc_error* error);
106
108
 
107
109
  static void read_action_locked(void* t, grpc_error* error);
110
+ static void continue_read_action_locked(grpc_chttp2_transport* t);
108
111
 
109
112
  static void complete_fetch_locked(void* gs, grpc_error* error);
110
113
  /** Set a transport level setting, and push it to our peer */
@@ -378,10 +381,13 @@ static bool read_channel_args(grpc_chttp2_transport* t,
378
381
  if (channelz_enabled) {
379
382
  // TODO(ncteisen): add an API to endpoint to query for local addr, and pass
380
383
  // it in here, so SocketNode knows its own address.
384
+ char* socket_name = nullptr;
385
+ gpr_asprintf(&socket_name, "%s %s", get_vtable()->name, t->peer_string);
381
386
  t->channelz_socket =
382
387
  grpc_core::MakeRefCounted<grpc_core::channelz::SocketNode>(
383
388
  grpc_core::UniquePtr<char>(),
384
- grpc_core::UniquePtr<char>(gpr_strdup(t->peer_string)));
389
+ grpc_core::UniquePtr<char>(gpr_strdup(t->peer_string)),
390
+ grpc_core::UniquePtr<char>(socket_name));
385
391
  }
386
392
  return enable_bdp;
387
393
  }
@@ -782,12 +788,6 @@ static void destroy_stream(grpc_transport* gt, grpc_stream* gs,
782
788
  GRPC_ERROR_NONE);
783
789
  }
784
790
 
785
- grpc_chttp2_stream* grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport* t,
786
- uint32_t id) {
787
- return static_cast<grpc_chttp2_stream*>(
788
- grpc_chttp2_stream_map_find(&t->stream_map, id));
789
- }
790
-
791
791
  grpc_chttp2_stream* grpc_chttp2_parsing_accept_stream(grpc_chttp2_transport* t,
792
792
  uint32_t id) {
793
793
  if (t->channel_callback.accept_stream == nullptr) {
@@ -800,10 +800,8 @@ grpc_chttp2_stream* grpc_chttp2_parsing_accept_stream(grpc_chttp2_transport* t,
800
800
  !grpc_resource_user_safe_alloc(t->resource_user,
801
801
  GRPC_RESOURCE_QUOTA_CALL_SIZE)) {
802
802
  gpr_log(GPR_ERROR, "Memory exhausted, rejecting the stream.");
803
- grpc_slice_buffer_add(
804
- &t->qbuf,
805
- grpc_chttp2_rst_stream_create(
806
- id, static_cast<uint32_t>(GRPC_HTTP2_REFUSED_STREAM), nullptr));
803
+ grpc_chttp2_add_rst_stream_to_next_write(t, id, GRPC_HTTP2_REFUSED_STREAM,
804
+ nullptr);
807
805
  grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM);
808
806
  return nullptr;
809
807
  }
@@ -1048,6 +1046,19 @@ static void write_action_begin_locked(void* gt, grpc_error* error_ignored) {
1048
1046
  GRPC_CLOSURE_SCHED(
1049
1047
  GRPC_CLOSURE_INIT(&t->write_action, write_action, t, scheduler),
1050
1048
  GRPC_ERROR_NONE);
1049
+ if (t->reading_paused_on_pending_induced_frames) {
1050
+ GPR_ASSERT(t->num_pending_induced_frames == 0);
1051
+ /* We had paused reading, because we had many induced frames (SETTINGS
1052
+ * ACK, PINGS ACK and RST_STREAMS) pending in t->qbuf. Now that we have
1053
+ * been able to flush qbuf, we can resume reading. */
1054
+ GRPC_CHTTP2_IF_TRACING(gpr_log(
1055
+ GPR_INFO,
1056
+ "transport %p : Resuming reading after being paused due to too "
1057
+ "many unwritten SETTINGS ACK, PINGS ACK and RST_STREAM frames",
1058
+ t));
1059
+ t->reading_paused_on_pending_induced_frames = false;
1060
+ continue_read_action_locked(t);
1061
+ }
1051
1062
  } else {
1052
1063
  GRPC_STATS_INC_HTTP2_SPURIOUS_WRITES_BEGUN();
1053
1064
  set_write_state(t, GRPC_CHTTP2_WRITE_STATE_IDLE, "begin writing nothing");
@@ -1117,7 +1128,6 @@ static void write_action_end_locked(void* tp, grpc_error* error) {
1117
1128
  }
1118
1129
 
1119
1130
  grpc_chttp2_end_write(t, GRPC_ERROR_REF(error));
1120
-
1121
1131
  GRPC_CHTTP2_UNREF_TRANSPORT(t, "writing");
1122
1132
  }
1123
1133
 
@@ -1140,6 +1150,7 @@ static void queue_setting_update(grpc_chttp2_transport* t,
1140
1150
 
1141
1151
  void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
1142
1152
  uint32_t goaway_error,
1153
+ uint32_t last_stream_id,
1143
1154
  const grpc_slice& goaway_text) {
1144
1155
  // Discard the error from a previous goaway frame (if any)
1145
1156
  if (t->goaway_error != GRPC_ERROR_NONE) {
@@ -1153,6 +1164,9 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
1153
1164
  GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
1154
1165
  GRPC_ERROR_STR_RAW_BYTES, goaway_text);
1155
1166
 
1167
+ GRPC_CHTTP2_IF_TRACING(
1168
+ gpr_log(GPR_INFO, "transport %p got goaway with last stream id %d", t,
1169
+ last_stream_id));
1156
1170
  /* We want to log this irrespective of whether http tracing is enabled */
1157
1171
  gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s", t->peer_string, goaway_error,
1158
1172
  grpc_error_string(t->goaway_error));
@@ -1191,8 +1205,9 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
1191
1205
  grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
1192
1206
  /* safe since we can't (legally) be parsing this stream yet */
1193
1207
  GRPC_CHTTP2_IF_TRACING(gpr_log(
1194
- GPR_INFO, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
1195
- t->is_client ? "CLI" : "SVR", s, t->next_stream_id));
1208
+ GPR_INFO,
1209
+ "HTTP:%s: Transport %p allocating new grpc_chttp2_stream %p to id %d",
1210
+ t->is_client ? "CLI" : "SVR", t, s, t->next_stream_id));
1196
1211
 
1197
1212
  GPR_ASSERT(s->id == 0);
1198
1213
  s->id = t->next_stream_id;
@@ -1232,10 +1247,10 @@ static grpc_closure* add_closure_barrier(grpc_closure* closure) {
1232
1247
  return closure;
1233
1248
  }
1234
1249
 
1235
- static void null_then_run_closure(grpc_closure** closure, grpc_error* error) {
1250
+ static void null_then_sched_closure(grpc_closure** closure) {
1236
1251
  grpc_closure* c = *closure;
1237
1252
  *closure = nullptr;
1238
- GRPC_CLOSURE_RUN(c, error);
1253
+ GRPC_CLOSURE_SCHED(c, GRPC_ERROR_NONE);
1239
1254
  }
1240
1255
 
1241
1256
  void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
@@ -1902,7 +1917,7 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_chttp2_transport* t,
1902
1917
  }
1903
1918
  grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[0],
1904
1919
  s->recv_initial_metadata);
1905
- null_then_run_closure(&s->recv_initial_metadata_ready, GRPC_ERROR_NONE);
1920
+ null_then_sched_closure(&s->recv_initial_metadata_ready);
1906
1921
  }
1907
1922
  }
1908
1923
 
@@ -1982,10 +1997,10 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_chttp2_transport* t,
1982
1997
  s->unprocessed_incoming_frames_buffer_cached_length =
1983
1998
  s->unprocessed_incoming_frames_buffer.length;
1984
1999
  if (error == GRPC_ERROR_NONE && *s->recv_message != nullptr) {
1985
- null_then_run_closure(&s->recv_message_ready, GRPC_ERROR_NONE);
2000
+ null_then_sched_closure(&s->recv_message_ready);
1986
2001
  } else if (s->published_metadata[1] != GRPC_METADATA_NOT_PUBLISHED) {
1987
2002
  *s->recv_message = nullptr;
1988
- null_then_run_closure(&s->recv_message_ready, GRPC_ERROR_NONE);
2003
+ null_then_sched_closure(&s->recv_message_ready);
1989
2004
  }
1990
2005
  GRPC_ERROR_UNREF(error);
1991
2006
  }
@@ -2011,9 +2026,10 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
2011
2026
  * maybe decompress the next 5 bytes in the stream. */
2012
2027
  if (s->stream_decompression_method ==
2013
2028
  GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS) {
2014
- grpc_slice_buffer_move_first(&s->frame_storage,
2015
- GRPC_HEADER_SIZE_IN_BYTES,
2016
- &s->unprocessed_incoming_frames_buffer);
2029
+ grpc_slice_buffer_move_first(
2030
+ &s->frame_storage,
2031
+ GPR_MIN(s->frame_storage.length, GRPC_HEADER_SIZE_IN_BYTES),
2032
+ &s->unprocessed_incoming_frames_buffer);
2017
2033
  if (s->unprocessed_incoming_frames_buffer.length > 0) {
2018
2034
  s->unprocessed_incoming_frames_decompressed = true;
2019
2035
  pending_data = true;
@@ -2051,8 +2067,7 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
2051
2067
  s->collecting_stats = nullptr;
2052
2068
  grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1],
2053
2069
  s->recv_trailing_metadata);
2054
- null_then_run_closure(&s->recv_trailing_metadata_finished,
2055
- GRPC_ERROR_NONE);
2070
+ null_then_sched_closure(&s->recv_trailing_metadata_finished);
2056
2071
  }
2057
2072
  }
2058
2073
  }
@@ -2061,7 +2076,7 @@ static void remove_stream(grpc_chttp2_transport* t, uint32_t id,
2061
2076
  grpc_error* error) {
2062
2077
  grpc_chttp2_stream* s = static_cast<grpc_chttp2_stream*>(
2063
2078
  grpc_chttp2_stream_map_delete(&t->stream_map, id));
2064
- GPR_ASSERT(s);
2079
+ GPR_DEBUG_ASSERT(s);
2065
2080
  if (t->incoming_stream == s) {
2066
2081
  t->incoming_stream = nullptr;
2067
2082
  grpc_chttp2_parsing_become_skip_parser(t);
@@ -2111,10 +2126,8 @@ void grpc_chttp2_cancel_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
2111
2126
  grpc_http2_error_code http_error;
2112
2127
  grpc_error_get_status(due_to_error, s->deadline, nullptr, nullptr,
2113
2128
  &http_error, nullptr);
2114
- grpc_slice_buffer_add(
2115
- &t->qbuf,
2116
- grpc_chttp2_rst_stream_create(
2117
- s->id, static_cast<uint32_t>(http_error), &s->stats.outgoing));
2129
+ grpc_chttp2_add_rst_stream_to_next_write(
2130
+ t, s->id, static_cast<uint32_t>(http_error), &s->stats.outgoing);
2118
2131
  grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM);
2119
2132
  }
2120
2133
  }
@@ -2147,7 +2160,7 @@ void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
2147
2160
  &s->metadata_buffer[1],
2148
2161
  grpc_mdelem_from_slices(
2149
2162
  GRPC_MDSTR_GRPC_STATUS,
2150
- grpc_slice_from_copied_string(status_string))));
2163
+ grpc_core::UnmanagedMemorySlice(status_string))));
2151
2164
  if (!GRPC_SLICE_IS_EMPTY(slice)) {
2152
2165
  GRPC_LOG_IF_ERROR(
2153
2166
  "add_status_message",
@@ -2425,9 +2438,8 @@ static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
2425
2438
  grpc_slice_buffer_add(&t->qbuf, status_hdr);
2426
2439
  grpc_slice_buffer_add(&t->qbuf, message_pfx);
2427
2440
  grpc_slice_buffer_add(&t->qbuf, grpc_slice_ref_internal(slice));
2428
- grpc_slice_buffer_add(
2429
- &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
2430
- &s->stats.outgoing));
2441
+ grpc_chttp2_add_rst_stream_to_next_write(t, s->id, GRPC_HTTP2_NO_ERROR,
2442
+ &s->stats.outgoing);
2431
2443
 
2432
2444
  grpc_chttp2_mark_stream_closed(t, s, 1, 1, error);
2433
2445
  grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API);
@@ -2598,10 +2610,16 @@ static void read_action_locked(void* tp, grpc_error* error) {
2598
2610
  grpc_slice_buffer_reset_and_unref_internal(&t->read_buffer);
2599
2611
 
2600
2612
  if (keep_reading) {
2601
- const bool urgent = t->goaway_error != GRPC_ERROR_NONE;
2602
- grpc_endpoint_read(t->ep, &t->read_buffer, &t->read_action_locked, urgent);
2603
- grpc_chttp2_act_on_flowctl_action(t->flow_control->MakeAction(), t,
2604
- nullptr);
2613
+ if (t->num_pending_induced_frames >= DEFAULT_MAX_PENDING_INDUCED_FRAMES) {
2614
+ t->reading_paused_on_pending_induced_frames = true;
2615
+ GRPC_CHTTP2_IF_TRACING(
2616
+ gpr_log(GPR_INFO,
2617
+ "transport %p : Pausing reading due to too "
2618
+ "many unwritten SETTINGS ACK and RST_STREAM frames",
2619
+ t));
2620
+ } else {
2621
+ continue_read_action_locked(t);
2622
+ }
2605
2623
  GRPC_CHTTP2_UNREF_TRANSPORT(t, "keep_reading");
2606
2624
  } else {
2607
2625
  GRPC_CHTTP2_UNREF_TRANSPORT(t, "reading_action");
@@ -2610,6 +2628,12 @@ static void read_action_locked(void* tp, grpc_error* error) {
2610
2628
  GRPC_ERROR_UNREF(error);
2611
2629
  }
2612
2630
 
2631
+ static void continue_read_action_locked(grpc_chttp2_transport* t) {
2632
+ const bool urgent = t->goaway_error != GRPC_ERROR_NONE;
2633
+ grpc_endpoint_read(t->ep, &t->read_buffer, &t->read_action_locked, urgent);
2634
+ grpc_chttp2_act_on_flowctl_action(t->flow_control->MakeAction(), t, nullptr);
2635
+ }
2636
+
2613
2637
  // t is reffed prior to calling the first time, and once the callback chain
2614
2638
  // that kicks off finishes, it's unreffed
2615
2639
  static void schedule_bdp_ping_locked(grpc_chttp2_transport* t) {
@@ -2825,7 +2849,8 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) {
2825
2849
  static void connectivity_state_set(grpc_chttp2_transport* t,
2826
2850
  grpc_connectivity_state state,
2827
2851
  const char* reason) {
2828
- GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "set connectivity_state=%d", state));
2852
+ GRPC_CHTTP2_IF_TRACING(
2853
+ gpr_log(GPR_INFO, "transport %p set connectivity_state=%d", t, state));
2829
2854
  grpc_connectivity_state_set(&t->channel_callback.state_tracker, state,
2830
2855
  reason);
2831
2856
  }
@@ -46,7 +46,9 @@ void ContextList::Execute(void* arg, grpc_core::Timestamps* ts,
46
46
  ContextList* to_be_freed;
47
47
  while (head != nullptr) {
48
48
  if (write_timestamps_callback_g) {
49
- ts->byte_offset = static_cast<uint32_t>(head->byte_offset_);
49
+ if (ts) {
50
+ ts->byte_offset = static_cast<uint32_t>(head->byte_offset_);
51
+ }
50
52
  write_timestamps_callback_g(head->trace_context_, ts, error);
51
53
  }
52
54
  to_be_freed = head;
@@ -137,10 +137,10 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
137
137
  p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID,
138
138
  static_cast<intptr_t>(s->id));
139
139
  gpr_free(msg);
140
- p->error =
141
- grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES,
142
- grpc_dump_slice_to_slice(
143
- *slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
140
+ p->error = grpc_error_set_str(
141
+ p->error, GRPC_ERROR_STR_RAW_BYTES,
142
+ grpc_slice_from_moved_string(grpc_core::UniquePtr<char>(
143
+ grpc_dump_slice(*slice, GPR_DUMP_HEX | GPR_DUMP_ASCII))));
144
144
  p->error =
145
145
  grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
146
146
  p->state = GRPC_CHTTP2_DATA_ERROR;
@@ -139,7 +139,7 @@ grpc_error* grpc_chttp2_goaway_parser_parse(void* parser,
139
139
  p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
140
140
  if (is_last) {
141
141
  grpc_chttp2_add_incoming_goaway(
142
- t, p->error_code,
142
+ t, p->error_code, p->last_stream_id,
143
143
  grpc_slice_new(p->debug_data, p->debug_length, gpr_free));
144
144
  p->debug_data = nullptr;
145
145
  }
@@ -118,6 +118,7 @@ grpc_error* grpc_chttp2_ping_parser_parse(void* parser,
118
118
  t->ping_acks = static_cast<uint64_t*>(gpr_realloc(
119
119
  t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks)));
120
120
  }
121
+ t->num_pending_induced_frames++;
121
122
  t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes;
122
123
  grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE);
123
124
  }
@@ -58,6 +58,14 @@ grpc_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code,
58
58
  return slice;
59
59
  }
60
60
 
61
+ void grpc_chttp2_add_rst_stream_to_next_write(
62
+ grpc_chttp2_transport* t, uint32_t id, uint32_t code,
63
+ grpc_transport_one_way_stats* stats) {
64
+ t->num_pending_induced_frames++;
65
+ grpc_slice_buffer_add(&t->qbuf,
66
+ grpc_chttp2_rst_stream_create(id, code, stats));
67
+ }
68
+
61
69
  grpc_error* grpc_chttp2_rst_stream_parser_begin_frame(
62
70
  grpc_chttp2_rst_stream_parser* parser, uint32_t length, uint8_t flags) {
63
71
  if (length != 4) {
@@ -33,6 +33,13 @@ typedef struct {
33
33
  grpc_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code,
34
34
  grpc_transport_one_way_stats* stats);
35
35
 
36
+ // Adds RST_STREAM frame to t->qbuf (buffer for the next write). Should be
37
+ // called when we want to add RST_STREAM and we are not in
38
+ // write_action_begin_locked.
39
+ void grpc_chttp2_add_rst_stream_to_next_write(
40
+ grpc_chttp2_transport* t, uint32_t id, uint32_t code,
41
+ grpc_transport_one_way_stats* stats);
42
+
36
43
  grpc_error* grpc_chttp2_rst_stream_parser_begin_frame(
37
44
  grpc_chttp2_rst_stream_parser* parser, uint32_t length, uint8_t flags);
38
45
  grpc_error* grpc_chttp2_rst_stream_parser_parse(void* parser,
@@ -132,6 +132,7 @@ grpc_error* grpc_chttp2_settings_parser_parse(void* p, grpc_chttp2_transport* t,
132
132
  if (is_last) {
133
133
  memcpy(parser->target_settings, parser->incoming_settings,
134
134
  GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
135
+ t->num_pending_induced_frames++;
135
136
  grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_settings_ack_create());
136
137
  if (t->notify_on_receive_settings != nullptr) {
137
138
  GRPC_CLOSURE_SCHED(t->notify_on_receive_settings,
@@ -130,8 +130,9 @@ static void begin_frame(framer_state* st) {
130
130
  space to add at least about_to_add bytes -- finishes the current frame if
131
131
  needed */
132
132
  static void ensure_space(framer_state* st, size_t need_bytes) {
133
- if (st->output->length - st->output_length_at_start_of_frame + need_bytes <=
134
- st->max_frame_size) {
133
+ if (GPR_LIKELY(st->output->length - st->output_length_at_start_of_frame +
134
+ need_bytes <=
135
+ st->max_frame_size)) {
135
136
  return;
136
137
  }
137
138
  finish_frame(st, 0, 0);
@@ -380,10 +381,11 @@ static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor* c,
380
381
  uint32_t len_val_len;
381
382
  GPR_ASSERT(len_val <= UINT32_MAX);
382
383
  len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
383
- GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40,
384
- add_tiny_header_data(st, len_pfx), len_pfx);
384
+ GPR_DEBUG_ASSERT(len_pfx + len_val_len < GRPC_SLICE_INLINED_SIZE);
385
+ uint8_t* data = add_tiny_header_data(st, len_pfx + len_val_len);
386
+ GRPC_CHTTP2_WRITE_VARINT(key_index, 2, 0x40, data, len_pfx);
385
387
  GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix,
386
- add_tiny_header_data(st, len_val_len), len_val_len);
388
+ &data[len_pfx], len_val_len);
387
389
  add_wire_value(st, value);
388
390
  }
389
391
 
@@ -397,10 +399,11 @@ static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor* c,
397
399
  uint32_t len_val_len;
398
400
  GPR_ASSERT(len_val <= UINT32_MAX);
399
401
  len_val_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)len_val, 1);
400
- GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00,
401
- add_tiny_header_data(st, len_pfx), len_pfx);
402
+ GPR_DEBUG_ASSERT(len_pfx + len_val_len < GRPC_SLICE_INLINED_SIZE);
403
+ uint8_t* data = add_tiny_header_data(st, len_pfx + len_val_len);
404
+ GRPC_CHTTP2_WRITE_VARINT(key_index, 4, 0x00, data, len_pfx);
402
405
  GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, value.huffman_prefix,
403
- add_tiny_header_data(st, len_val_len), len_val_len);
406
+ &data[len_pfx], len_val_len);
404
407
  add_wire_value(st, value);
405
408
  }
406
409
 
@@ -417,9 +420,10 @@ static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor* c,
417
420
  uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
418
421
  GPR_ASSERT(len_key <= UINT32_MAX);
419
422
  GPR_ASSERT(wire_value_length(value) <= UINT32_MAX);
420
- *add_tiny_header_data(st, 1) = 0x40;
421
- GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
422
- add_tiny_header_data(st, len_key_len), len_key_len);
423
+ GPR_DEBUG_ASSERT(1 + len_key_len < GRPC_SLICE_INLINED_SIZE);
424
+ uint8_t* data = add_tiny_header_data(st, 1 + len_key_len);
425
+ data[0] = 0x40;
426
+ GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, &data[1], len_key_len);
423
427
  add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
424
428
  GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix,
425
429
  add_tiny_header_data(st, len_val_len), len_val_len);
@@ -439,9 +443,10 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor* c,
439
443
  uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
440
444
  GPR_ASSERT(len_key <= UINT32_MAX);
441
445
  GPR_ASSERT(wire_value_length(value) <= UINT32_MAX);
442
- *add_tiny_header_data(st, 1) = 0x00;
443
- GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
444
- add_tiny_header_data(st, len_key_len), len_key_len);
446
+ /* Preconditions passed; emit header. */
447
+ uint8_t* data = add_tiny_header_data(st, 1 + len_key_len);
448
+ data[0] = 0x00;
449
+ GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, &data[1], len_key_len);
445
450
  add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
446
451
  GRPC_CHTTP2_WRITE_VARINT(len_val, 1, value.huffman_prefix,
447
452
  add_tiny_header_data(st, len_val_len), len_val_len);
@@ -599,8 +604,8 @@ static void deadline_enc(grpc_chttp2_hpack_compressor* c, grpc_millis deadline,
599
604
  grpc_mdelem mdelem;
600
605
  grpc_http2_encode_timeout(deadline - grpc_core::ExecCtx::Get()->Now(),
601
606
  timeout_str);
602
- mdelem = grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_TIMEOUT,
603
- grpc_slice_from_copied_string(timeout_str));
607
+ mdelem = grpc_mdelem_from_slices(
608
+ GRPC_MDSTR_GRPC_TIMEOUT, grpc_core::UnmanagedMemorySlice(timeout_str));
604
609
  hpack_enc(c, mdelem, st);
605
610
  GRPC_MDELEM_UNREF(mdelem);
606
611
  }
@@ -711,18 +716,28 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
711
716
  }
712
717
  for (size_t i = 0; i < extra_headers_size; ++i) {
713
718
  grpc_mdelem md = *extra_headers[i];
714
- uintptr_t static_index = grpc_chttp2_get_static_hpack_table_index(md);
715
- if (static_index) {
716
- emit_indexed(c, static_cast<uint32_t>(static_index), &st);
719
+ const bool is_static =
720
+ GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC;
721
+ uintptr_t static_index;
722
+ if (is_static &&
723
+ (static_index =
724
+ reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(md))
725
+ ->StaticIndex()) < GRPC_CHTTP2_LAST_STATIC_ENTRY) {
726
+ emit_indexed(c, static_cast<uint32_t>(static_index + 1), &st);
717
727
  } else {
718
728
  hpack_enc(c, md, &st);
719
729
  }
720
730
  }
721
731
  grpc_metadata_batch_assert_ok(metadata);
722
732
  for (grpc_linked_mdelem* l = metadata->list.head; l; l = l->next) {
723
- uintptr_t static_index = grpc_chttp2_get_static_hpack_table_index(l->md);
724
- if (static_index) {
725
- emit_indexed(c, static_cast<uint32_t>(static_index), &st);
733
+ const bool is_static =
734
+ GRPC_MDELEM_STORAGE(l->md) == GRPC_MDELEM_STORAGE_STATIC;
735
+ uintptr_t static_index;
736
+ if (is_static &&
737
+ (static_index = reinterpret_cast<grpc_core::StaticMetadata*>(
738
+ GRPC_MDELEM_DATA(l->md))
739
+ ->StaticIndex()) < GRPC_CHTTP2_LAST_STATIC_ENTRY) {
740
+ emit_indexed(c, static_cast<uint32_t>(static_index + 1), &st);
726
741
  } else {
727
742
  hpack_enc(c, l->md, &st);
728
743
  }