Merge remote-tracking branch 'upstream/master' into cares_bazel_rule

reviewable/pr7771/r12
Yuchen Zeng 8 years ago
commit 92edda5129
  1. 5
      .gitignore
  2. 20
      BUILD
  3. 115
      CMakeLists.txt
  4. 323
      Makefile
  5. 7
      binding.gyp
  6. 83
      build.yaml
  7. 1
      composer.json
  8. 6
      config.m4
  9. 10
      doc/service_config.md
  10. 24
      gRPC-Core.podspec
  11. 15
      grpc.def
  12. 15
      grpc.gemspec
  13. 146
      include/grpc++/impl/codegen/call.h
  14. 10
      include/grpc++/impl/codegen/client_context.h
  15. 9
      include/grpc++/impl/codegen/client_unary_call.h
  16. 8
      include/grpc++/impl/codegen/core_codegen.h
  17. 17
      include/grpc++/impl/codegen/core_codegen_interface.h
  18. 71
      include/grpc++/impl/codegen/metadata_map.h
  19. 8
      include/grpc++/impl/codegen/method_handler_impl.h
  20. 8
      include/grpc++/impl/codegen/proto_utils.h
  21. 9
      include/grpc++/impl/codegen/rpc_service_method.h
  22. 5
      include/grpc++/impl/codegen/server_context.h
  23. 5
      include/grpc++/impl/codegen/server_interface.h
  24. 65
      include/grpc++/impl/codegen/slice.h
  25. 8
      include/grpc++/impl/codegen/sync_stream.h
  26. 3
      include/grpc++/support/byte_buffer.h
  27. 8
      include/grpc/compression.h
  28. 10
      include/grpc/grpc.h
  29. 54
      include/grpc/impl/codegen/grpc_types.h
  30. 21
      include/grpc/impl/codegen/slice.h
  31. 38
      include/grpc/slice.h
  32. 15
      package.xml
  33. 28
      src/compiler/php_generator.cc
  34. 3
      src/compiler/php_generator.h
  35. 15
      src/compiler/php_generator_helpers.h
  36. 20
      src/compiler/php_plugin.cc
  37. 2
      src/core/ext/census/gen/census.pb.h
  38. 2
      src/core/ext/census/gen/trace_context.pb.h
  39. 4
      src/core/ext/census/grpc_filter.c
  40. 29
      src/core/ext/client_channel/client_channel.c
  41. 6
      src/core/ext/client_channel/connector.c
  42. 7
      src/core/ext/client_channel/connector.h
  43. 10
      src/core/ext/client_channel/http_connect_handshaker.c
  44. 13
      src/core/ext/client_channel/subchannel.c
  45. 2
      src/core/ext/client_channel/subchannel.h
  46. 75
      src/core/ext/lb_policy/grpclb/grpclb.c
  47. 84
      src/core/ext/load_reporting/load_reporting_filter.c
  48. 5
      src/core/ext/resolver/dns/native/dns_resolver.c
  49. 2
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  50. 14
      src/core/ext/transport/chttp2/client/chttp2_connector.c
  51. 16
      src/core/ext/transport/chttp2/server/chttp2_server.c
  52. 2
      src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
  53. 2
      src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
  54. 14
      src/core/ext/transport/chttp2/transport/bin_decoder.c
  55. 3
      src/core/ext/transport/chttp2/transport/bin_encoder.c
  56. 3
      src/core/ext/transport/chttp2/transport/bin_encoder.h
  57. 3
      src/core/ext/transport/chttp2/transport/chttp2_plugin.c
  58. 374
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  59. 13
      src/core/ext/transport/chttp2/transport/frame_rst_stream.c
  60. 16
      src/core/ext/transport/chttp2/transport/frame_settings.c
  61. 152
      src/core/ext/transport/chttp2/transport/hpack_encoder.c
  62. 4
      src/core/ext/transport/chttp2/transport/hpack_encoder.h
  63. 196
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  64. 20
      src/core/ext/transport/chttp2/transport/hpack_parser.h
  65. 41
      src/core/ext/transport/chttp2/transport/hpack_table.c
  66. 12
      src/core/ext/transport/chttp2/transport/hpack_table.h
  67. 34
      src/core/ext/transport/chttp2/transport/incoming_metadata.c
  68. 8
      src/core/ext/transport/chttp2/transport/incoming_metadata.h
  69. 3
      src/core/ext/transport/chttp2/transport/internal.h
  70. 69
      src/core/ext/transport/chttp2/transport/parsing.c
  71. 22
      src/core/ext/transport/chttp2/transport/writing.c
  72. 53
      src/core/ext/transport/cronet/transport/cronet_transport.c
  73. 43
      src/core/lib/channel/channel_stack.c
  74. 19
      src/core/lib/channel/channel_stack.h
  75. 94
      src/core/lib/channel/compress_filter.c
  76. 15
      src/core/lib/channel/deadline_filter.c
  77. 14
      src/core/lib/channel/handshaker.c
  78. 8
      src/core/lib/channel/handshaker.h
  79. 246
      src/core/lib/channel/http_client_filter.c
  80. 296
      src/core/lib/channel/http_server_filter.c
  81. 22
      src/core/lib/channel/message_size_filter.c
  82. 8
      src/core/lib/compression/algorithm_metadata.h
  83. 40
      src/core/lib/compression/compression.c
  84. 2
      src/core/lib/http/httpcli_security_connector.c
  85. 1
      src/core/lib/iomgr/closure.c
  86. 1
      src/core/lib/iomgr/closure.h
  87. 12
      src/core/lib/iomgr/combiner.c
  88. 5
      src/core/lib/iomgr/endpoint.c
  89. 5
      src/core/lib/iomgr/endpoint.h
  90. 154
      src/core/lib/iomgr/error.c
  91. 13
      src/core/lib/iomgr/error.h
  92. 54
      src/core/lib/iomgr/error_internal.h
  93. 22
      src/core/lib/iomgr/ev_epoll_linux.c
  94. 17
      src/core/lib/iomgr/ev_poll_posix.c
  95. 6
      src/core/lib/iomgr/ev_posix.c
  96. 4
      src/core/lib/iomgr/ev_posix.h
  97. 17
      src/core/lib/iomgr/exec_ctx.c
  98. 25
      src/core/lib/iomgr/exec_ctx.h
  99. 4
      src/core/lib/iomgr/executor.c
  100. 2
      src/core/lib/iomgr/load_file.c
  101. Some files were not shown because too many files have changed in this diff Show More

5
.gitignore vendored

@ -32,7 +32,7 @@ coverage
# python compiled objects # python compiled objects
*.pyc *.pyc
#eclipse project files # eclipse project files
.cproject .cproject
.project .project
.settings .settings
@ -111,3 +111,6 @@ bazel-genfiles
bazel-grpc bazel-grpc
bazel-out bazel-out
bazel-testlogs bazel-testlogs
# Debug output
gdb.txt

20
BUILD

@ -500,6 +500,8 @@ grpc_cc_library(
"src/core/lib/slice/percent_encoding.c", "src/core/lib/slice/percent_encoding.c",
"src/core/lib/slice/slice.c", "src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c", "src/core/lib/slice/slice_buffer.c",
"src/core/lib/slice/slice_hash_table.c",
"src/core/lib/slice/slice_intern.c",
"src/core/lib/slice/slice_string_helpers.c", "src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/surface/alarm.c", "src/core/lib/surface/alarm.c",
"src/core/lib/surface/api_trace.c", "src/core/lib/surface/api_trace.c",
@ -521,12 +523,13 @@ grpc_cc_library(
"src/core/lib/surface/version.c", "src/core/lib/surface/version.c",
"src/core/lib/transport/byte_stream.c", "src/core/lib/transport/byte_stream.c",
"src/core/lib/transport/connectivity_state.c", "src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/error_utils.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c", "src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/status_conversion.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
"src/core/lib/transport/transport_op_string.c", "src/core/lib/transport/transport_op_string.c",
@ -556,6 +559,7 @@ grpc_cc_library(
"src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/error.h", "src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_epoll_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/ev_posix.h",
@ -608,6 +612,7 @@ grpc_cc_library(
"src/core/lib/json/json_reader.h", "src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h", "src/core/lib/json/json_writer.h",
"src/core/lib/slice/percent_encoding.h", "src/core/lib/slice/percent_encoding.h",
"src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_internal.h", "src/core/lib/slice/slice_internal.h",
"src/core/lib/slice/slice_string_helpers.h", "src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/api_trace.h", "src/core/lib/surface/api_trace.h",
@ -619,16 +624,19 @@ grpc_cc_library(
"src/core/lib/surface/completion_queue.h", "src/core/lib/surface/completion_queue.h",
"src/core/lib/surface/event_string.h", "src/core/lib/surface/event_string.h",
"src/core/lib/surface/init.h", "src/core/lib/surface/init.h",
"src/core/lib/surface/validate_metadata.h",
"src/core/lib/surface/lame_client.h", "src/core/lib/surface/lame_client.h",
"src/core/lib/surface/server.h", "src/core/lib/surface/server.h",
"src/core/lib/transport/byte_stream.h", "src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h", "src/core/lib/transport/connectivity_state.h",
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/error_utils.h",
"src/core/lib/transport/http2_errors.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h", "src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/status_conversion.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
"src/core/lib/transport/transport_impl.h", "src/core/lib/transport/transport_impl.h",
@ -910,7 +918,6 @@ grpc_cc_library(
"src/core/ext/transport/chttp2/transport/huffsyms.c", "src/core/ext/transport/chttp2/transport/huffsyms.c",
"src/core/ext/transport/chttp2/transport/incoming_metadata.c", "src/core/ext/transport/chttp2/transport/incoming_metadata.c",
"src/core/ext/transport/chttp2/transport/parsing.c", "src/core/ext/transport/chttp2/transport/parsing.c",
"src/core/ext/transport/chttp2/transport/status_conversion.c",
"src/core/ext/transport/chttp2/transport/stream_lists.c", "src/core/ext/transport/chttp2/transport/stream_lists.c",
"src/core/ext/transport/chttp2/transport/stream_map.c", "src/core/ext/transport/chttp2/transport/stream_map.c",
"src/core/ext/transport/chttp2/transport/varint.c", "src/core/ext/transport/chttp2/transport/varint.c",
@ -930,11 +937,9 @@ grpc_cc_library(
"src/core/ext/transport/chttp2/transport/hpack_encoder.h", "src/core/ext/transport/chttp2/transport/hpack_encoder.h",
"src/core/ext/transport/chttp2/transport/hpack_parser.h", "src/core/ext/transport/chttp2/transport/hpack_parser.h",
"src/core/ext/transport/chttp2/transport/hpack_table.h", "src/core/ext/transport/chttp2/transport/hpack_table.h",
"src/core/ext/transport/chttp2/transport/http2_errors.h",
"src/core/ext/transport/chttp2/transport/huffsyms.h", "src/core/ext/transport/chttp2/transport/huffsyms.h",
"src/core/ext/transport/chttp2/transport/incoming_metadata.h", "src/core/ext/transport/chttp2/transport/incoming_metadata.h",
"src/core/ext/transport/chttp2/transport/internal.h", "src/core/ext/transport/chttp2/transport/internal.h",
"src/core/ext/transport/chttp2/transport/status_conversion.h",
"src/core/ext/transport/chttp2/transport/stream_map.h", "src/core/ext/transport/chttp2/transport/stream_map.h",
"src/core/ext/transport/chttp2/transport/varint.h", "src/core/ext/transport/chttp2/transport/varint.h",
], ],
@ -1202,6 +1207,7 @@ grpc_cc_library(
"include/grpc++/impl/codegen/core_codegen_interface.h", "include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/create_auth_context.h", "include/grpc++/impl/codegen/create_auth_context.h",
"include/grpc++/impl/codegen/grpc_library.h", "include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/metadata_map.h",
"include/grpc++/impl/codegen/method_handler_impl.h", "include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/rpc_method.h", "include/grpc++/impl/codegen/rpc_method.h",
"include/grpc++/impl/codegen/rpc_service_method.h", "include/grpc++/impl/codegen/rpc_service_method.h",
@ -1210,6 +1216,7 @@ grpc_cc_library(
"include/grpc++/impl/codegen/server_context.h", "include/grpc++/impl/codegen/server_context.h",
"include/grpc++/impl/codegen/server_interface.h", "include/grpc++/impl/codegen/server_interface.h",
"include/grpc++/impl/codegen/service_type.h", "include/grpc++/impl/codegen/service_type.h",
"include/grpc++/impl/codegen/slice.h",
"include/grpc++/impl/codegen/status.h", "include/grpc++/impl/codegen/status.h",
"include/grpc++/impl/codegen/status_code_enum.h", "include/grpc++/impl/codegen/status_code_enum.h",
"include/grpc++/impl/codegen/status_helper.h", "include/grpc++/impl/codegen/status_helper.h",
@ -1252,6 +1259,9 @@ grpc_cc_library(
public_hdrs = [ public_hdrs = [
"include/grpc++/impl/codegen/config_protobuf.h", "include/grpc++/impl/codegen/config_protobuf.h",
], ],
external_deps = [
"protobuf",
],
) )
grpc_cc_library( grpc_cc_library(

@ -510,6 +510,8 @@ add_library(grpc
src/core/lib/slice/percent_encoding.c src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c src/core/lib/surface/api_trace.c
@ -531,12 +533,13 @@ add_library(grpc
src/core/lib/surface/version.c src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c src/core/lib/transport/connectivity_state.c
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/error_utils.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/status_conversion.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c src/core/lib/transport/transport_op_string.c
@ -557,7 +560,6 @@ add_library(grpc
src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/huffsyms.c
src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/incoming_metadata.c
src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/parsing.c
src/core/ext/transport/chttp2/transport/status_conversion.c
src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_lists.c
src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/stream_map.c
src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/varint.c
@ -806,6 +808,8 @@ add_library(grpc_cronet
src/core/lib/slice/percent_encoding.c src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c src/core/lib/surface/api_trace.c
@ -827,12 +831,13 @@ add_library(grpc_cronet
src/core/lib/surface/version.c src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c src/core/lib/transport/connectivity_state.c
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/error_utils.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/status_conversion.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c src/core/lib/transport/transport_op_string.c
@ -856,7 +861,6 @@ add_library(grpc_cronet
src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/huffsyms.c
src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/incoming_metadata.c
src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/parsing.c
src/core/ext/transport/chttp2/transport/status_conversion.c
src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_lists.c
src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/stream_map.c
src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/varint.c
@ -1088,6 +1092,8 @@ add_library(grpc_test_util
src/core/lib/slice/percent_encoding.c src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c src/core/lib/surface/api_trace.c
@ -1109,12 +1115,13 @@ add_library(grpc_test_util
src/core/lib/surface/version.c src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c src/core/lib/transport/connectivity_state.c
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/error_utils.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/status_conversion.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c src/core/lib/transport/transport_op_string.c
@ -1307,6 +1314,8 @@ add_library(grpc_unsecure
src/core/lib/slice/percent_encoding.c src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c src/core/lib/surface/api_trace.c
@ -1328,12 +1337,13 @@ add_library(grpc_unsecure
src/core/lib/surface/version.c src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c src/core/lib/transport/connectivity_state.c
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/error_utils.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/status_conversion.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c src/core/lib/transport/transport_op_string.c
@ -1355,7 +1365,6 @@ add_library(grpc_unsecure
src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/huffsyms.c
src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/incoming_metadata.c
src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/parsing.c
src/core/ext/transport/chttp2/transport/status_conversion.c
src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_lists.c
src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/stream_map.c
src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/varint.c
@ -1657,6 +1666,7 @@ foreach(_hdr
include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/core_codegen_interface.h
include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/create_auth_context.h
include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/grpc_library.h
include/grpc++/impl/codegen/metadata_map.h
include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/method_handler_impl.h
include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_method.h
include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/rpc_service_method.h
@ -1665,6 +1675,7 @@ foreach(_hdr
include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_context.h
include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/server_interface.h
include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/service_type.h
include/grpc++/impl/codegen/slice.h
include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status.h
include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_code_enum.h
include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/status_helper.h
@ -1762,7 +1773,6 @@ add_library(grpc++_cronet
src/core/ext/transport/chttp2/transport/huffsyms.c src/core/ext/transport/chttp2/transport/huffsyms.c
src/core/ext/transport/chttp2/transport/incoming_metadata.c src/core/ext/transport/chttp2/transport/incoming_metadata.c
src/core/ext/transport/chttp2/transport/parsing.c src/core/ext/transport/chttp2/transport/parsing.c
src/core/ext/transport/chttp2/transport/status_conversion.c
src/core/ext/transport/chttp2/transport/stream_lists.c src/core/ext/transport/chttp2/transport/stream_lists.c
src/core/ext/transport/chttp2/transport/stream_map.c src/core/ext/transport/chttp2/transport/stream_map.c
src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/varint.c
@ -1851,6 +1861,8 @@ add_library(grpc++_cronet
src/core/lib/slice/percent_encoding.c src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c src/core/lib/surface/api_trace.c
@ -1872,12 +1884,13 @@ add_library(grpc++_cronet
src/core/lib/surface/version.c src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c src/core/lib/transport/connectivity_state.c
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/error_utils.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/status_conversion.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c src/core/lib/transport/transport_op_string.c
@ -2001,6 +2014,7 @@ foreach(_hdr
include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/core_codegen_interface.h
include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/create_auth_context.h
include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/grpc_library.h
include/grpc++/impl/codegen/metadata_map.h
include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/method_handler_impl.h
include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_method.h
include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/rpc_service_method.h
@ -2009,6 +2023,7 @@ foreach(_hdr
include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_context.h
include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/server_interface.h
include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/service_type.h
include/grpc++/impl/codegen/slice.h
include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status.h
include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_code_enum.h
include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/status_helper.h
@ -2275,6 +2290,7 @@ foreach(_hdr
include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/core_codegen_interface.h
include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/create_auth_context.h
include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/grpc_library.h
include/grpc++/impl/codegen/metadata_map.h
include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/method_handler_impl.h
include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_method.h
include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/rpc_service_method.h
@ -2283,6 +2299,7 @@ foreach(_hdr
include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_context.h
include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/server_interface.h
include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/service_type.h
include/grpc++/impl/codegen/slice.h
include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status.h
include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_code_enum.h
include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/status_helper.h
@ -2434,6 +2451,7 @@ foreach(_hdr
include/grpc++/impl/codegen/core_codegen_interface.h include/grpc++/impl/codegen/core_codegen_interface.h
include/grpc++/impl/codegen/create_auth_context.h include/grpc++/impl/codegen/create_auth_context.h
include/grpc++/impl/codegen/grpc_library.h include/grpc++/impl/codegen/grpc_library.h
include/grpc++/impl/codegen/metadata_map.h
include/grpc++/impl/codegen/method_handler_impl.h include/grpc++/impl/codegen/method_handler_impl.h
include/grpc++/impl/codegen/rpc_method.h include/grpc++/impl/codegen/rpc_method.h
include/grpc++/impl/codegen/rpc_service_method.h include/grpc++/impl/codegen/rpc_service_method.h
@ -2442,6 +2460,7 @@ foreach(_hdr
include/grpc++/impl/codegen/server_context.h include/grpc++/impl/codegen/server_context.h
include/grpc++/impl/codegen/server_interface.h include/grpc++/impl/codegen/server_interface.h
include/grpc++/impl/codegen/service_type.h include/grpc++/impl/codegen/service_type.h
include/grpc++/impl/codegen/slice.h
include/grpc++/impl/codegen/status.h include/grpc++/impl/codegen/status.h
include/grpc++/impl/codegen/status_code_enum.h include/grpc++/impl/codegen/status_code_enum.h
include/grpc++/impl/codegen/status_helper.h include/grpc++/impl/codegen/status_helper.h
@ -5262,32 +5281,6 @@ target_link_libraries(chttp2_hpack_encoder_test
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_executable(chttp2_status_conversion_test
test/core/transport/chttp2/status_conversion_test.c
)
target_include_directories(chttp2_status_conversion_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/c-ares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(chttp2_status_conversion_test
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(chttp2_stream_map_test add_executable(chttp2_stream_map_test
test/core/transport/chttp2/stream_map_test.c test/core/transport/chttp2/stream_map_test.c
) )
@ -7383,6 +7376,32 @@ target_link_libraries(percent_encoding_test
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_executable(resolve_address_posix_test
test/core/iomgr/resolve_address_posix_test.c
)
target_include_directories(resolve_address_posix_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/c-ares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(resolve_address_posix_test
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(resolve_address_test add_executable(resolve_address_test
test/core/iomgr/resolve_address_test.c test/core/iomgr/resolve_address_test.c
) )
@ -7748,6 +7767,32 @@ target_link_libraries(socket_utils_test
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_executable(status_conversion_test
test/core/transport/status_conversion_test.c
)
target_include_directories(status_conversion_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/c-ares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(status_conversion_test
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(tcp_client_posix_test add_executable(tcp_client_posix_test
test/core/iomgr/tcp_client_posix_test.c test/core/iomgr/tcp_client_posix_test.c
) )

@ -95,56 +95,6 @@ LDXX_opt = $(DEFAULT_CXX)
CPPFLAGS_opt = -O2 CPPFLAGS_opt = -O2
DEFINES_opt = NDEBUG DEFINES_opt = NDEBUG
VALID_CONFIG_asan-trace-cmp = 1
REQUIRE_CUSTOM_LIBRARIES_asan-trace-cmp = 1
CC_asan-trace-cmp = clang
CXX_asan-trace-cmp = clang++
LD_asan-trace-cmp = clang
LDXX_asan-trace-cmp = clang++
CPPFLAGS_asan-trace-cmp = -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_asan-trace-cmp = -fsanitize=address
DEFINES_asan-trace-cmp += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
VALID_CONFIG_dbg = 1
CC_dbg = $(DEFAULT_CC)
CXX_dbg = $(DEFAULT_CXX)
LD_dbg = $(DEFAULT_CC)
LDXX_dbg = $(DEFAULT_CXX)
CPPFLAGS_dbg = -O0
DEFINES_dbg = _DEBUG DEBUG
VALID_CONFIG_easan = 1
REQUIRE_CUSTOM_LIBRARIES_easan = 1
CC_easan = clang
CXX_easan = clang++
LD_easan = clang
LDXX_easan = clang++
CPPFLAGS_easan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_easan = -fsanitize=address
DEFINES_easan = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
DEFINES_easan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
VALID_CONFIG_asan = 1
REQUIRE_CUSTOM_LIBRARIES_asan = 1
CC_asan = clang
CXX_asan = clang++
LD_asan = clang
LDXX_asan = clang++
CPPFLAGS_asan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_asan = -fsanitize=address
DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
VALID_CONFIG_msan = 1
REQUIRE_CUSTOM_LIBRARIES_msan = 1
CC_msan = clang
CXX_msan = clang++
LD_msan = clang
LDXX_msan = clang++
CPPFLAGS_msan = -O0 -fsanitize-coverage=edge -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
DEFINES_msan = NDEBUG
DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=4
VALID_CONFIG_basicprof = 1 VALID_CONFIG_basicprof = 1
CC_basicprof = $(DEFAULT_CC) CC_basicprof = $(DEFAULT_CC)
CXX_basicprof = $(DEFAULT_CXX) CXX_basicprof = $(DEFAULT_CXX)
@ -173,35 +123,23 @@ CPPFLAGS_asan-noleaks = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omi
LDFLAGS_asan-noleaks = -fsanitize=address LDFLAGS_asan-noleaks = -fsanitize=address
DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3 DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
VALID_CONFIG_edbg = 1 VALID_CONFIG_asan-trace-cmp = 1
CC_edbg = $(DEFAULT_CC) REQUIRE_CUSTOM_LIBRARIES_asan-trace-cmp = 1
CXX_edbg = $(DEFAULT_CXX) CC_asan-trace-cmp = clang
LD_edbg = $(DEFAULT_CC) CXX_asan-trace-cmp = clang++
LDXX_edbg = $(DEFAULT_CXX) LD_asan-trace-cmp = clang
CPPFLAGS_edbg = -O0 LDXX_asan-trace-cmp = clang++
DEFINES_edbg = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER CPPFLAGS_asan-trace-cmp = -O0 -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_asan-trace-cmp = -fsanitize=address
VALID_CONFIG_ubsan = 1 DEFINES_asan-trace-cmp += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
REQUIRE_CUSTOM_LIBRARIES_ubsan = 1
CC_ubsan = clang
CXX_ubsan = clang++
LD_ubsan = clang
LDXX_ubsan = clang++
CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs
LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow
DEFINES_ubsan = NDEBUG
DEFINES_ubsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
VALID_CONFIG_tsan = 1 VALID_CONFIG_dbg = 1
REQUIRE_CUSTOM_LIBRARIES_tsan = 1 CC_dbg = $(DEFAULT_CC)
CC_tsan = clang CXX_dbg = $(DEFAULT_CXX)
CXX_tsan = clang++ LD_dbg = $(DEFAULT_CC)
LD_tsan = clang LDXX_dbg = $(DEFAULT_CXX)
LDXX_tsan = clang++ CPPFLAGS_dbg = -O0
CPPFLAGS_tsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS DEFINES_dbg = _DEBUG DEBUG
LDFLAGS_tsan = -fsanitize=thread
DEFINES_tsan = GRPC_TSAN
DEFINES_tsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
VALID_CONFIG_stapprof = 1 VALID_CONFIG_stapprof = 1
CC_stapprof = $(DEFAULT_CC) CC_stapprof = $(DEFAULT_CC)
@ -211,14 +149,14 @@ LDXX_stapprof = $(DEFAULT_CXX)
CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER
DEFINES_stapprof = NDEBUG DEFINES_stapprof = NDEBUG
VALID_CONFIG_mutrace = 1 VALID_CONFIG_gcov = 1
CC_mutrace = $(DEFAULT_CC) CC_gcov = gcc
CXX_mutrace = $(DEFAULT_CXX) CXX_gcov = g++
LD_mutrace = $(DEFAULT_CC) LD_gcov = gcc
LDXX_mutrace = $(DEFAULT_CXX) LDXX_gcov = g++
CPPFLAGS_mutrace = -O3 -fno-omit-frame-pointer CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage -Wno-return-type
LDFLAGS_mutrace = -rdynamic LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -rdynamic
DEFINES_mutrace = NDEBUG DEFINES_gcov = _DEBUG DEBUG GPR_GCOV
VALID_CONFIG_memcheck = 1 VALID_CONFIG_memcheck = 1
CC_memcheck = $(DEFAULT_CC) CC_memcheck = $(DEFAULT_CC)
@ -230,25 +168,57 @@ LDFLAGS_memcheck = -rdynamic
DEFINES_memcheck = _DEBUG DEBUG DEFINES_memcheck = _DEBUG DEBUG
DEFINES_memcheck += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=10 DEFINES_memcheck += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=10
VALID_CONFIG_etsan = 1 VALID_CONFIG_asan = 1
REQUIRE_CUSTOM_LIBRARIES_etsan = 1 REQUIRE_CUSTOM_LIBRARIES_asan = 1
CC_etsan = clang CC_asan = clang
CXX_etsan = clang++ CXX_asan = clang++
LD_etsan = clang LD_asan = clang
LDXX_etsan = clang++ LDXX_asan = clang++
CPPFLAGS_etsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS CPPFLAGS_asan = -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_etsan = -fsanitize=thread LDFLAGS_asan = -fsanitize=address
DEFINES_etsan = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
DEFINES_etsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
VALID_CONFIG_gcov = 1 VALID_CONFIG_tsan = 1
CC_gcov = gcc REQUIRE_CUSTOM_LIBRARIES_tsan = 1
CXX_gcov = g++ CC_tsan = clang
LD_gcov = gcc CXX_tsan = clang++
LDXX_gcov = g++ LD_tsan = clang
CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage -Wno-return-type LDXX_tsan = clang++
LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -rdynamic CPPFLAGS_tsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
DEFINES_gcov = _DEBUG DEBUG GPR_GCOV LDFLAGS_tsan = -fsanitize=thread
DEFINES_tsan = GRPC_TSAN
DEFINES_tsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
VALID_CONFIG_ubsan = 1
REQUIRE_CUSTOM_LIBRARIES_ubsan = 1
CC_ubsan = clang
CXX_ubsan = clang++
LD_ubsan = clang
LDXX_ubsan = clang++
CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs
LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow
DEFINES_ubsan = NDEBUG
DEFINES_ubsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
VALID_CONFIG_msan = 1
REQUIRE_CUSTOM_LIBRARIES_msan = 1
CC_msan = clang
CXX_msan = clang++
LD_msan = clang
LDXX_msan = clang++
CPPFLAGS_msan = -O0 -fsanitize-coverage=edge -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
DEFINES_msan = NDEBUG
DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=4
VALID_CONFIG_mutrace = 1
CC_mutrace = $(DEFAULT_CC)
CXX_mutrace = $(DEFAULT_CXX)
LD_mutrace = $(DEFAULT_CC)
LDXX_mutrace = $(DEFAULT_CXX)
CPPFLAGS_mutrace = -O3 -fno-omit-frame-pointer
LDFLAGS_mutrace = -rdynamic
DEFINES_mutrace = NDEBUG
@ -988,7 +958,6 @@ census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test
chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test
client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer
@ -1080,6 +1049,7 @@ no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer
percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test
resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test
resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test
resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test
secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test
@ -1096,6 +1066,7 @@ sockaddr_resolver_test: $(BINDIR)/$(CONFIG)/sockaddr_resolver_test
sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test
socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test
ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test
tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test
tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test
tcp_server_posix_test: $(BINDIR)/$(CONFIG)/tcp_server_posix_test tcp_server_posix_test: $(BINDIR)/$(CONFIG)/tcp_server_posix_test
@ -1348,7 +1319,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/census_trace_context_test \ $(BINDIR)/$(CONFIG)/census_trace_context_test \
$(BINDIR)/$(CONFIG)/channel_create_test \ $(BINDIR)/$(CONFIG)/channel_create_test \
$(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \ $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \
$(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \
$(BINDIR)/$(CONFIG)/chttp2_varint_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \
$(BINDIR)/$(CONFIG)/combiner_test \ $(BINDIR)/$(CONFIG)/combiner_test \
@ -1424,6 +1394,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/murmur_hash_test \ $(BINDIR)/$(CONFIG)/murmur_hash_test \
$(BINDIR)/$(CONFIG)/no_server_test \ $(BINDIR)/$(CONFIG)/no_server_test \
$(BINDIR)/$(CONFIG)/percent_encoding_test \ $(BINDIR)/$(CONFIG)/percent_encoding_test \
$(BINDIR)/$(CONFIG)/resolve_address_posix_test \
$(BINDIR)/$(CONFIG)/resolve_address_test \ $(BINDIR)/$(CONFIG)/resolve_address_test \
$(BINDIR)/$(CONFIG)/resource_quota_test \ $(BINDIR)/$(CONFIG)/resource_quota_test \
$(BINDIR)/$(CONFIG)/secure_channel_create_test \ $(BINDIR)/$(CONFIG)/secure_channel_create_test \
@ -1438,6 +1409,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/sockaddr_resolver_test \ $(BINDIR)/$(CONFIG)/sockaddr_resolver_test \
$(BINDIR)/$(CONFIG)/sockaddr_utils_test \ $(BINDIR)/$(CONFIG)/sockaddr_utils_test \
$(BINDIR)/$(CONFIG)/socket_utils_test \ $(BINDIR)/$(CONFIG)/socket_utils_test \
$(BINDIR)/$(CONFIG)/status_conversion_test \
$(BINDIR)/$(CONFIG)/tcp_client_posix_test \ $(BINDIR)/$(CONFIG)/tcp_client_posix_test \
$(BINDIR)/$(CONFIG)/tcp_posix_test \ $(BINDIR)/$(CONFIG)/tcp_posix_test \
$(BINDIR)/$(CONFIG)/tcp_server_posix_test \ $(BINDIR)/$(CONFIG)/tcp_server_posix_test \
@ -1701,8 +1673,6 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_hpack_encoder_test" $(E) "[RUN] Testing chttp2_hpack_encoder_test"
$(Q) $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test || ( echo test chttp2_hpack_encoder_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test || ( echo test chttp2_hpack_encoder_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_status_conversion_test"
$(Q) $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test || ( echo test chttp2_status_conversion_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_stream_map_test" $(E) "[RUN] Testing chttp2_stream_map_test"
$(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_varint_test" $(E) "[RUN] Testing chttp2_varint_test"
@ -1831,6 +1801,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 )
$(E) "[RUN] Testing percent_encoding_test" $(E) "[RUN] Testing percent_encoding_test"
$(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 )
$(E) "[RUN] Testing resolve_address_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 )
$(E) "[RUN] Testing resolve_address_test" $(E) "[RUN] Testing resolve_address_test"
$(Q) $(BINDIR)/$(CONFIG)/resolve_address_test || ( echo test resolve_address_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/resolve_address_test || ( echo test resolve_address_test failed ; exit 1 )
$(E) "[RUN] Testing resource_quota_test" $(E) "[RUN] Testing resource_quota_test"
@ -1859,6 +1831,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/sockaddr_utils_test || ( echo test sockaddr_utils_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/sockaddr_utils_test || ( echo test sockaddr_utils_test failed ; exit 1 )
$(E) "[RUN] Testing socket_utils_test" $(E) "[RUN] Testing socket_utils_test"
$(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 )
$(E) "[RUN] Testing status_conversion_test"
$(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 )
$(E) "[RUN] Testing tcp_client_posix_test" $(E) "[RUN] Testing tcp_client_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/tcp_client_posix_test || ( echo test tcp_client_posix_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/tcp_client_posix_test || ( echo test tcp_client_posix_test failed ; exit 1 )
$(E) "[RUN] Testing tcp_posix_test" $(E) "[RUN] Testing tcp_posix_test"
@ -2787,6 +2761,8 @@ LIBGRPC_SRC = \
src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \ src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \ src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \ src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \ src/core/lib/surface/api_trace.c \
@ -2808,12 +2784,13 @@ LIBGRPC_SRC = \
src/core/lib/surface/version.c \ src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \ src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \ src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \ src/core/lib/transport/transport_op_string.c \
@ -2834,7 +2811,6 @@ LIBGRPC_SRC = \
src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/status_conversion.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/varint.c \
@ -3096,6 +3072,8 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \ src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \ src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \ src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \ src/core/lib/surface/api_trace.c \
@ -3117,12 +3095,13 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/surface/version.c \ src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \ src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \ src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \ src/core/lib/transport/transport_op_string.c \
@ -3146,7 +3125,6 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/status_conversion.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/varint.c \
@ -3392,6 +3370,8 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \ src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \ src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \ src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \ src/core/lib/surface/api_trace.c \
@ -3413,12 +3393,13 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/surface/version.c \ src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \ src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \ src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \ src/core/lib/transport/transport_op_string.c \
@ -3613,6 +3594,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \ src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \ src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \ src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \ src/core/lib/surface/api_trace.c \
@ -3634,12 +3617,13 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/surface/version.c \ src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \ src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \ src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \ src/core/lib/transport/transport_op_string.c \
@ -3661,7 +3645,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/status_conversion.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/varint.c \
@ -3964,6 +3947,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/create_auth_context.h \
include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/metadata_map.h \
include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_method.h \
include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \
@ -3972,6 +3956,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_context.h \
include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/server_interface.h \
include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/service_type.h \
include/grpc++/impl/codegen/slice.h \
include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status.h \
include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_code_enum.h \
include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/status_helper.h \
@ -4115,7 +4100,6 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/status_conversion.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/varint.c \
@ -4204,6 +4188,8 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \ src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \ src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \ src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \ src/core/lib/surface/api_trace.c \
@ -4225,12 +4211,13 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/surface/version.c \ src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \ src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \ src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \ src/core/lib/transport/transport_op_string.c \
@ -4333,6 +4320,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/create_auth_context.h \
include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/metadata_map.h \
include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_method.h \
include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \
@ -4341,6 +4329,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_context.h \
include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/server_interface.h \
include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/service_type.h \
include/grpc++/impl/codegen/slice.h \
include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status.h \
include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_code_enum.h \
include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/status_helper.h \
@ -4690,6 +4679,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/create_auth_context.h \
include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/metadata_map.h \
include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_method.h \
include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \
@ -4698,6 +4688,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_context.h \
include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/server_interface.h \
include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/service_type.h \
include/grpc++/impl/codegen/slice.h \
include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status.h \
include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_code_enum.h \
include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/status_helper.h \
@ -4870,6 +4861,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/core_codegen_interface.h \ include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/create_auth_context.h \ include/grpc++/impl/codegen/create_auth_context.h \
include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/metadata_map.h \
include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/rpc_method.h \ include/grpc++/impl/codegen/rpc_method.h \
include/grpc++/impl/codegen/rpc_service_method.h \ include/grpc++/impl/codegen/rpc_service_method.h \
@ -4878,6 +4870,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/server_context.h \ include/grpc++/impl/codegen/server_context.h \
include/grpc++/impl/codegen/server_interface.h \ include/grpc++/impl/codegen/server_interface.h \
include/grpc++/impl/codegen/service_type.h \ include/grpc++/impl/codegen/service_type.h \
include/grpc++/impl/codegen/slice.h \
include/grpc++/impl/codegen/status.h \ include/grpc++/impl/codegen/status.h \
include/grpc++/impl/codegen/status_code_enum.h \ include/grpc++/impl/codegen/status_code_enum.h \
include/grpc++/impl/codegen/status_helper.h \ include/grpc++/impl/codegen/status_helper.h \
@ -8330,38 +8323,6 @@ endif
endif endif
CHTTP2_STATUS_CONVERSION_TEST_SRC = \
test/core/transport/chttp2/status_conversion_test.c \
CHTTP2_STATUS_CONVERSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_STATUS_CONVERSION_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test: $(CHTTP2_STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(CHTTP2_STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
endif
$(OBJDIR)/$(CONFIG)/test/core/transport/chttp2/status_conversion_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_chttp2_status_conversion_test: $(CHTTP2_STATUS_CONVERSION_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CHTTP2_STATUS_CONVERSION_TEST_OBJS:.o=.dep)
endif
endif
CHTTP2_STREAM_MAP_TEST_SRC = \ CHTTP2_STREAM_MAP_TEST_SRC = \
test/core/transport/chttp2/stream_map_test.c \ test/core/transport/chttp2/stream_map_test.c \
@ -11274,6 +11235,38 @@ endif
endif endif
RESOLVE_ADDRESS_POSIX_TEST_SRC = \
test/core/iomgr/resolve_address_posix_test.c \
RESOLVE_ADDRESS_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_POSIX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/resolve_address_posix_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_posix_test
endif
$(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep)
endif
endif
RESOLVE_ADDRESS_TEST_SRC = \ RESOLVE_ADDRESS_TEST_SRC = \
test/core/iomgr/resolve_address_test.c \ test/core/iomgr/resolve_address_test.c \
@ -11786,6 +11779,38 @@ endif
endif endif
STATUS_CONVERSION_TEST_SRC = \
test/core/transport/status_conversion_test.c \
STATUS_CONVERSION_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_CONVERSION_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/status_conversion_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/status_conversion_test: $(STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(STATUS_CONVERSION_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/status_conversion_test
endif
$(OBJDIR)/$(CONFIG)/test/core/transport/status_conversion_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_status_conversion_test: $(STATUS_CONVERSION_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(STATUS_CONVERSION_TEST_OBJS:.o=.dep)
endif
endif
TCP_CLIENT_POSIX_TEST_SRC = \ TCP_CLIENT_POSIX_TEST_SRC = \
test/core/iomgr/tcp_client_posix_test.c \ test/core/iomgr/tcp_client_posix_test.c \

@ -691,6 +691,8 @@
'src/core/lib/slice/percent_encoding.c', 'src/core/lib/slice/percent_encoding.c',
'src/core/lib/slice/slice.c', 'src/core/lib/slice/slice.c',
'src/core/lib/slice/slice_buffer.c', 'src/core/lib/slice/slice_buffer.c',
'src/core/lib/slice/slice_hash_table.c',
'src/core/lib/slice/slice_intern.c',
'src/core/lib/slice/slice_string_helpers.c', 'src/core/lib/slice/slice_string_helpers.c',
'src/core/lib/surface/alarm.c', 'src/core/lib/surface/alarm.c',
'src/core/lib/surface/api_trace.c', 'src/core/lib/surface/api_trace.c',
@ -712,12 +714,13 @@
'src/core/lib/surface/version.c', 'src/core/lib/surface/version.c',
'src/core/lib/transport/byte_stream.c', 'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c', 'src/core/lib/transport/connectivity_state.c',
'src/core/lib/transport/mdstr_hash_table.c', 'src/core/lib/transport/error_utils.c',
'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/pid_controller.c',
'src/core/lib/transport/service_config.c', 'src/core/lib/transport/service_config.c',
'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/status_conversion.c',
'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport.c',
'src/core/lib/transport/transport_op_string.c', 'src/core/lib/transport/transport_op_string.c',
@ -738,7 +741,6 @@
'src/core/ext/transport/chttp2/transport/huffsyms.c', 'src/core/ext/transport/chttp2/transport/huffsyms.c',
'src/core/ext/transport/chttp2/transport/incoming_metadata.c', 'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
'src/core/ext/transport/chttp2/transport/parsing.c', 'src/core/ext/transport/chttp2/transport/parsing.c',
'src/core/ext/transport/chttp2/transport/status_conversion.c',
'src/core/ext/transport/chttp2/transport/stream_lists.c', 'src/core/ext/transport/chttp2/transport/stream_lists.c',
'src/core/ext/transport/chttp2/transport/stream_map.c', 'src/core/ext/transport/chttp2/transport/stream_map.c',
'src/core/ext/transport/chttp2/transport/varint.c', 'src/core/ext/transport/chttp2/transport/varint.c',
@ -892,6 +894,7 @@
"src/node/ext/node_grpc.cc", "src/node/ext/node_grpc.cc",
"src/node/ext/server.cc", "src/node/ext/server.cc",
"src/node/ext/server_credentials.cc", "src/node/ext/server_credentials.cc",
"src/node/ext/slice.cc",
"src/node/ext/timeval.cc", "src/node/ext/timeval.cc",
], ],
"dependencies": [ "dependencies": [

@ -188,6 +188,7 @@ filegroups:
- src/core/lib/iomgr/endpoint.h - src/core/lib/iomgr/endpoint.h
- src/core/lib/iomgr/endpoint_pair.h - src/core/lib/iomgr/endpoint_pair.h
- src/core/lib/iomgr/error.h - src/core/lib/iomgr/error.h
- src/core/lib/iomgr/error_internal.h
- src/core/lib/iomgr/ev_epoll_linux.h - src/core/lib/iomgr/ev_epoll_linux.h
- src/core/lib/iomgr/ev_poll_posix.h - src/core/lib/iomgr/ev_poll_posix.h
- src/core/lib/iomgr/ev_posix.h - src/core/lib/iomgr/ev_posix.h
@ -240,6 +241,7 @@ filegroups:
- src/core/lib/json/json_reader.h - src/core/lib/json/json_reader.h
- src/core/lib/json/json_writer.h - src/core/lib/json/json_writer.h
- src/core/lib/slice/percent_encoding.h - src/core/lib/slice/percent_encoding.h
- src/core/lib/slice/slice_hash_table.h
- src/core/lib/slice/slice_internal.h - src/core/lib/slice/slice_internal.h
- src/core/lib/slice/slice_string_helpers.h - src/core/lib/slice/slice_string_helpers.h
- src/core/lib/surface/api_trace.h - src/core/lib/surface/api_trace.h
@ -253,14 +255,17 @@ filegroups:
- src/core/lib/surface/init.h - src/core/lib/surface/init.h
- src/core/lib/surface/lame_client.h - src/core/lib/surface/lame_client.h
- src/core/lib/surface/server.h - src/core/lib/surface/server.h
- src/core/lib/surface/validate_metadata.h
- src/core/lib/transport/byte_stream.h - src/core/lib/transport/byte_stream.h
- src/core/lib/transport/connectivity_state.h - src/core/lib/transport/connectivity_state.h
- src/core/lib/transport/mdstr_hash_table.h - src/core/lib/transport/error_utils.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/metadata.h - src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h - src/core/lib/transport/metadata_batch.h
- src/core/lib/transport/pid_controller.h - src/core/lib/transport/pid_controller.h
- src/core/lib/transport/service_config.h - src/core/lib/transport/service_config.h
- src/core/lib/transport/static_metadata.h - src/core/lib/transport/static_metadata.h
- src/core/lib/transport/status_conversion.h
- src/core/lib/transport/timeout_encoding.h - src/core/lib/transport/timeout_encoding.h
- src/core/lib/transport/transport.h - src/core/lib/transport/transport.h
- src/core/lib/transport/transport_impl.h - src/core/lib/transport/transport_impl.h
@ -349,6 +354,8 @@ filegroups:
- src/core/lib/slice/percent_encoding.c - src/core/lib/slice/percent_encoding.c
- src/core/lib/slice/slice.c - src/core/lib/slice/slice.c
- src/core/lib/slice/slice_buffer.c - src/core/lib/slice/slice_buffer.c
- src/core/lib/slice/slice_hash_table.c
- src/core/lib/slice/slice_intern.c
- src/core/lib/slice/slice_string_helpers.c - src/core/lib/slice/slice_string_helpers.c
- src/core/lib/surface/alarm.c - src/core/lib/surface/alarm.c
- src/core/lib/surface/api_trace.c - src/core/lib/surface/api_trace.c
@ -370,12 +377,13 @@ filegroups:
- src/core/lib/surface/version.c - src/core/lib/surface/version.c
- src/core/lib/transport/byte_stream.c - src/core/lib/transport/byte_stream.c
- src/core/lib/transport/connectivity_state.c - src/core/lib/transport/connectivity_state.c
- src/core/lib/transport/mdstr_hash_table.c - src/core/lib/transport/error_utils.c
- src/core/lib/transport/metadata.c - src/core/lib/transport/metadata.c
- src/core/lib/transport/metadata_batch.c - src/core/lib/transport/metadata_batch.c
- src/core/lib/transport/pid_controller.c - src/core/lib/transport/pid_controller.c
- src/core/lib/transport/service_config.c - src/core/lib/transport/service_config.c
- src/core/lib/transport/static_metadata.c - src/core/lib/transport/static_metadata.c
- src/core/lib/transport/status_conversion.c
- src/core/lib/transport/timeout_encoding.c - src/core/lib/transport/timeout_encoding.c
- src/core/lib/transport/transport.c - src/core/lib/transport/transport.c
- src/core/lib/transport/transport_op_string.c - src/core/lib/transport/transport_op_string.c
@ -606,11 +614,9 @@ filegroups:
- src/core/ext/transport/chttp2/transport/hpack_encoder.h - src/core/ext/transport/chttp2/transport/hpack_encoder.h
- src/core/ext/transport/chttp2/transport/hpack_parser.h - src/core/ext/transport/chttp2/transport/hpack_parser.h
- src/core/ext/transport/chttp2/transport/hpack_table.h - src/core/ext/transport/chttp2/transport/hpack_table.h
- src/core/ext/transport/chttp2/transport/http2_errors.h
- src/core/ext/transport/chttp2/transport/huffsyms.h - src/core/ext/transport/chttp2/transport/huffsyms.h
- src/core/ext/transport/chttp2/transport/incoming_metadata.h - src/core/ext/transport/chttp2/transport/incoming_metadata.h
- src/core/ext/transport/chttp2/transport/internal.h - src/core/ext/transport/chttp2/transport/internal.h
- src/core/ext/transport/chttp2/transport/status_conversion.h
- src/core/ext/transport/chttp2/transport/stream_map.h - src/core/ext/transport/chttp2/transport/stream_map.h
- src/core/ext/transport/chttp2/transport/varint.h - src/core/ext/transport/chttp2/transport/varint.h
src: src:
@ -630,7 +636,6 @@ filegroups:
- src/core/ext/transport/chttp2/transport/huffsyms.c - src/core/ext/transport/chttp2/transport/huffsyms.c
- src/core/ext/transport/chttp2/transport/incoming_metadata.c - src/core/ext/transport/chttp2/transport/incoming_metadata.c
- src/core/ext/transport/chttp2/transport/parsing.c - src/core/ext/transport/chttp2/transport/parsing.c
- src/core/ext/transport/chttp2/transport/status_conversion.c
- src/core/ext/transport/chttp2/transport/stream_lists.c - src/core/ext/transport/chttp2/transport/stream_lists.c
- src/core/ext/transport/chttp2/transport/stream_map.c - src/core/ext/transport/chttp2/transport/stream_map.c
- src/core/ext/transport/chttp2/transport/varint.c - src/core/ext/transport/chttp2/transport/varint.c
@ -832,6 +837,7 @@ filegroups:
- include/grpc++/impl/codegen/core_codegen_interface.h - include/grpc++/impl/codegen/core_codegen_interface.h
- include/grpc++/impl/codegen/create_auth_context.h - include/grpc++/impl/codegen/create_auth_context.h
- include/grpc++/impl/codegen/grpc_library.h - include/grpc++/impl/codegen/grpc_library.h
- include/grpc++/impl/codegen/metadata_map.h
- include/grpc++/impl/codegen/method_handler_impl.h - include/grpc++/impl/codegen/method_handler_impl.h
- include/grpc++/impl/codegen/rpc_method.h - include/grpc++/impl/codegen/rpc_method.h
- include/grpc++/impl/codegen/rpc_service_method.h - include/grpc++/impl/codegen/rpc_service_method.h
@ -840,6 +846,7 @@ filegroups:
- include/grpc++/impl/codegen/server_context.h - include/grpc++/impl/codegen/server_context.h
- include/grpc++/impl/codegen/server_interface.h - include/grpc++/impl/codegen/server_interface.h
- include/grpc++/impl/codegen/service_type.h - include/grpc++/impl/codegen/service_type.h
- include/grpc++/impl/codegen/slice.h
- include/grpc++/impl/codegen/status.h - include/grpc++/impl/codegen/status.h
- include/grpc++/impl/codegen/status_code_enum.h - include/grpc++/impl/codegen/status_code_enum.h
- include/grpc++/impl/codegen/status_helper.h - include/grpc++/impl/codegen/status_helper.h
@ -1513,16 +1520,6 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: chttp2_status_conversion_test
build: test
language: c
src:
- test/core/transport/chttp2/status_conversion_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: chttp2_stream_map_test - name: chttp2_stream_map_test
build: test build: test
language: c language: c
@ -2507,6 +2504,20 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: resolve_address_posix_test
build: test
language: c
src:
- test/core/iomgr/resolve_address_posix_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
platforms:
- mac
- linux
- posix
- name: resolve_address_test - name: resolve_address_test
build: test build: test
language: c language: c
@ -2691,6 +2702,16 @@ targets:
corpus_dirs: corpus_dirs:
- test/core/security/corpus/ssl_server_corpus - test/core/security/corpus/ssl_server_corpus
maxlen: 2048 maxlen: 2048
- name: status_conversion_test
build: test
language: c
src:
- test/core/transport/status_conversion_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: tcp_client_posix_test - name: tcp_client_posix_test
cpu_cost: 0.5 cpu_cost: 0.5
build: test build: test
@ -3782,36 +3803,6 @@ configs:
dbg: dbg:
CPPFLAGS: -O0 CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG DEFINES: _DEBUG DEBUG
easan:
CC: clang
CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=address -fno-omit-frame-pointer
-Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
CXX: clang++
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
LD: clang
LDFLAGS: -fsanitize=address
LDXX: clang++
compile_the_world: true
test_environ:
ASAN_OPTIONS: detect_leaks=1:color=always
LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
timeout_multiplier: 3
edbg:
CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
etsan:
CC: clang
CPPFLAGS: -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument
-DGPR_NO_DIRECT_SYSCALLS
CXX: clang++
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
LD: clang
LDFLAGS: -fsanitize=thread
LDXX: clang++
compile_the_world: true
test_environ:
TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
timeout_multiplier: 5
gcov: gcov:
CC: gcc CC: gcc
CPPFLAGS: -O0 -fprofile-arcs -ftest-coverage -Wno-return-type CPPFLAGS: -O0 -fprofile-arcs -ftest-coverage -Wno-return-type
@ -3915,6 +3906,7 @@ node_modules:
- src/node/ext/completion_queue.h - src/node/ext/completion_queue.h
- src/node/ext/server.h - src/node/ext/server.h
- src/node/ext/server_credentials.h - src/node/ext/server_credentials.h
- src/node/ext/slice.h
- src/node/ext/timeval.h - src/node/ext/timeval.h
js: js:
- src/node/index.js - src/node/index.js
@ -3936,6 +3928,7 @@ node_modules:
- src/node/ext/node_grpc.cc - src/node/ext/node_grpc.cc
- src/node/ext/server.cc - src/node/ext/server.cc
- src/node/ext/server_credentials.cc - src/node/ext/server_credentials.cc
- src/node/ext/slice.cc
- src/node/ext/timeval.cc - src/node/ext/timeval.cc
openssl_fallback: openssl_fallback:
base_uri: https://openssl.org/source/old/1.0.2/ base_uri: https://openssl.org/source/old/1.0.2/

@ -7,7 +7,6 @@
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"require": { "require": {
"php": ">=5.5.0", "php": ">=5.5.0",
"ext-grpc": "*",
"google/protobuf": "v3.1.0-alpha-1" "google/protobuf": "v3.1.0-alpha-1"
}, },
"require-dev": { "require-dev": {

@ -165,6 +165,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/slice/percent_encoding.c \ src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \ src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \ src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \ src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \ src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \ src/core/lib/surface/api_trace.c \
@ -186,12 +188,13 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/surface/version.c \ src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \ src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \ src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \ src/core/lib/transport/transport_op_string.c \
@ -212,7 +215,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/transport/chttp2/transport/huffsyms.c \ src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \ src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \ src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/status_conversion.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \ src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \ src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/varint.c \

@ -95,10 +95,7 @@ The service config is a JSON string of the following form:
# will not be sent and the client will see an error. # will not be sent and the client will see an error.
# Note that 0 is a valid value, meaning that the request message must # Note that 0 is a valid value, meaning that the request message must
# be empty. # be empty.
# 'maxRequestMessageBytes': number,
# The format of the value is that of the 'uint64' type defined here:
# https://developers.google.com/protocol-buffers/docs/proto3#json
'maxRequestMessageBytes': string,
# The maximum allowed payload size for an individual response or object # The maximum allowed payload size for an individual response or object
# in a stream (server->client) in bytes. The size which is measured is # in a stream (server->client) in bytes. The size which is measured is
@ -114,10 +111,7 @@ The service config is a JSON string of the following form:
# will not be sent, and the client will see an error. # will not be sent, and the client will see an error.
# Note that 0 is a valid value, meaning that the response message must # Note that 0 is a valid value, meaning that the response message must
# be empty. # be empty.
# 'maxResponseMessageBytes': number
# The format of the value is that of the 'uint64' type defined here:
# https://developers.google.com/protocol-buffers/docs/proto3#json
'maxResponseMessageBytes': string
} }
] ]
} }

@ -275,6 +275,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint.h',
'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/endpoint_pair.h',
'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_epoll_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/ev_posix.h',
@ -327,6 +328,7 @@ Pod::Spec.new do |s|
'src/core/lib/json/json_reader.h', 'src/core/lib/json/json_reader.h',
'src/core/lib/json/json_writer.h', 'src/core/lib/json/json_writer.h',
'src/core/lib/slice/percent_encoding.h', 'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_internal.h', 'src/core/lib/slice/slice_internal.h',
'src/core/lib/slice/slice_string_helpers.h', 'src/core/lib/slice/slice_string_helpers.h',
'src/core/lib/surface/api_trace.h', 'src/core/lib/surface/api_trace.h',
@ -340,14 +342,17 @@ Pod::Spec.new do |s|
'src/core/lib/surface/init.h', 'src/core/lib/surface/init.h',
'src/core/lib/surface/lame_client.h', 'src/core/lib/surface/lame_client.h',
'src/core/lib/surface/server.h', 'src/core/lib/surface/server.h',
'src/core/lib/surface/validate_metadata.h',
'src/core/lib/transport/byte_stream.h', 'src/core/lib/transport/byte_stream.h',
'src/core/lib/transport/connectivity_state.h', 'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/mdstr_hash_table.h', 'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h', 'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/status_conversion.h',
'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport.h',
'src/core/lib/transport/transport_impl.h', 'src/core/lib/transport/transport_impl.h',
@ -364,11 +369,9 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/hpack_encoder.h', 'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
'src/core/ext/transport/chttp2/transport/hpack_parser.h', 'src/core/ext/transport/chttp2/transport/hpack_parser.h',
'src/core/ext/transport/chttp2/transport/hpack_table.h', 'src/core/ext/transport/chttp2/transport/hpack_table.h',
'src/core/ext/transport/chttp2/transport/http2_errors.h',
'src/core/ext/transport/chttp2/transport/huffsyms.h', 'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/incoming_metadata.h', 'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
'src/core/ext/transport/chttp2/transport/internal.h', 'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/status_conversion.h',
'src/core/ext/transport/chttp2/transport/stream_map.h', 'src/core/ext/transport/chttp2/transport/stream_map.h',
'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/chttp2/transport/varint.h',
'src/core/ext/transport/chttp2/alpn/alpn.h', 'src/core/ext/transport/chttp2/alpn/alpn.h',
@ -523,6 +526,8 @@ Pod::Spec.new do |s|
'src/core/lib/slice/percent_encoding.c', 'src/core/lib/slice/percent_encoding.c',
'src/core/lib/slice/slice.c', 'src/core/lib/slice/slice.c',
'src/core/lib/slice/slice_buffer.c', 'src/core/lib/slice/slice_buffer.c',
'src/core/lib/slice/slice_hash_table.c',
'src/core/lib/slice/slice_intern.c',
'src/core/lib/slice/slice_string_helpers.c', 'src/core/lib/slice/slice_string_helpers.c',
'src/core/lib/surface/alarm.c', 'src/core/lib/surface/alarm.c',
'src/core/lib/surface/api_trace.c', 'src/core/lib/surface/api_trace.c',
@ -544,12 +549,13 @@ Pod::Spec.new do |s|
'src/core/lib/surface/version.c', 'src/core/lib/surface/version.c',
'src/core/lib/transport/byte_stream.c', 'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c', 'src/core/lib/transport/connectivity_state.c',
'src/core/lib/transport/mdstr_hash_table.c', 'src/core/lib/transport/error_utils.c',
'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/pid_controller.c',
'src/core/lib/transport/service_config.c', 'src/core/lib/transport/service_config.c',
'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/status_conversion.c',
'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport.c',
'src/core/lib/transport/transport_op_string.c', 'src/core/lib/transport/transport_op_string.c',
@ -570,7 +576,6 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/huffsyms.c', 'src/core/ext/transport/chttp2/transport/huffsyms.c',
'src/core/ext/transport/chttp2/transport/incoming_metadata.c', 'src/core/ext/transport/chttp2/transport/incoming_metadata.c',
'src/core/ext/transport/chttp2/transport/parsing.c', 'src/core/ext/transport/chttp2/transport/parsing.c',
'src/core/ext/transport/chttp2/transport/status_conversion.c',
'src/core/ext/transport/chttp2/transport/stream_lists.c', 'src/core/ext/transport/chttp2/transport/stream_lists.c',
'src/core/ext/transport/chttp2/transport/stream_map.c', 'src/core/ext/transport/chttp2/transport/stream_map.c',
'src/core/ext/transport/chttp2/transport/varint.c', 'src/core/ext/transport/chttp2/transport/varint.c',
@ -698,6 +703,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint.h',
'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/endpoint_pair.h',
'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_epoll_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/ev_posix.h',
@ -750,6 +756,7 @@ Pod::Spec.new do |s|
'src/core/lib/json/json_reader.h', 'src/core/lib/json/json_reader.h',
'src/core/lib/json/json_writer.h', 'src/core/lib/json/json_writer.h',
'src/core/lib/slice/percent_encoding.h', 'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_internal.h', 'src/core/lib/slice/slice_internal.h',
'src/core/lib/slice/slice_string_helpers.h', 'src/core/lib/slice/slice_string_helpers.h',
'src/core/lib/surface/api_trace.h', 'src/core/lib/surface/api_trace.h',
@ -763,14 +770,17 @@ Pod::Spec.new do |s|
'src/core/lib/surface/init.h', 'src/core/lib/surface/init.h',
'src/core/lib/surface/lame_client.h', 'src/core/lib/surface/lame_client.h',
'src/core/lib/surface/server.h', 'src/core/lib/surface/server.h',
'src/core/lib/surface/validate_metadata.h',
'src/core/lib/transport/byte_stream.h', 'src/core/lib/transport/byte_stream.h',
'src/core/lib/transport/connectivity_state.h', 'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/mdstr_hash_table.h', 'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h', 'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/status_conversion.h',
'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport.h',
'src/core/lib/transport/transport_impl.h', 'src/core/lib/transport/transport_impl.h',
@ -787,11 +797,9 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/hpack_encoder.h', 'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
'src/core/ext/transport/chttp2/transport/hpack_parser.h', 'src/core/ext/transport/chttp2/transport/hpack_parser.h',
'src/core/ext/transport/chttp2/transport/hpack_table.h', 'src/core/ext/transport/chttp2/transport/hpack_table.h',
'src/core/ext/transport/chttp2/transport/http2_errors.h',
'src/core/ext/transport/chttp2/transport/huffsyms.h', 'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/incoming_metadata.h', 'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
'src/core/ext/transport/chttp2/transport/internal.h', 'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/status_conversion.h',
'src/core/ext/transport/chttp2/transport/stream_map.h', 'src/core/ext/transport/chttp2/transport/stream_map.h',
'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/chttp2/transport/varint.h',
'src/core/ext/transport/chttp2/alpn/alpn.h', 'src/core/ext/transport/chttp2/alpn/alpn.h',

@ -141,17 +141,30 @@ EXPORTS
grpc_slice_new_with_user_data grpc_slice_new_with_user_data
grpc_slice_new_with_len grpc_slice_new_with_len
grpc_slice_malloc grpc_slice_malloc
grpc_slice_intern
grpc_slice_from_copied_string grpc_slice_from_copied_string
grpc_slice_from_copied_buffer grpc_slice_from_copied_buffer
grpc_slice_from_static_string grpc_slice_from_static_string
grpc_slice_from_static_buffer
grpc_slice_sub grpc_slice_sub
grpc_slice_sub_no_ref grpc_slice_sub_no_ref
grpc_slice_split_tail grpc_slice_split_tail
grpc_slice_split_head grpc_slice_split_head
gpr_empty_slice grpc_empty_slice
grpc_slice_default_hash_impl
grpc_slice_default_eq_impl
grpc_slice_eq
grpc_slice_cmp grpc_slice_cmp
grpc_slice_str_cmp grpc_slice_str_cmp
grpc_slice_buf_cmp
grpc_slice_buf_start_eq
grpc_slice_rchr
grpc_slice_chr
grpc_slice_slice
grpc_slice_hash
grpc_slice_is_equivalent grpc_slice_is_equivalent
grpc_slice_dup
grpc_slice_to_c_string
grpc_slice_buffer_init grpc_slice_buffer_init
grpc_slice_buffer_destroy grpc_slice_buffer_destroy
grpc_slice_buffer_add grpc_slice_buffer_add

@ -191,6 +191,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/endpoint.h ) s.files += %w( src/core/lib/iomgr/endpoint.h )
s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) s.files += %w( src/core/lib/iomgr/endpoint_pair.h )
s.files += %w( src/core/lib/iomgr/error.h ) s.files += %w( src/core/lib/iomgr/error.h )
s.files += %w( src/core/lib/iomgr/error_internal.h )
s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
s.files += %w( src/core/lib/iomgr/ev_posix.h ) s.files += %w( src/core/lib/iomgr/ev_posix.h )
@ -243,6 +244,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/json/json_reader.h ) s.files += %w( src/core/lib/json/json_reader.h )
s.files += %w( src/core/lib/json/json_writer.h ) s.files += %w( src/core/lib/json/json_writer.h )
s.files += %w( src/core/lib/slice/percent_encoding.h ) s.files += %w( src/core/lib/slice/percent_encoding.h )
s.files += %w( src/core/lib/slice/slice_hash_table.h )
s.files += %w( src/core/lib/slice/slice_internal.h ) s.files += %w( src/core/lib/slice/slice_internal.h )
s.files += %w( src/core/lib/slice/slice_string_helpers.h ) s.files += %w( src/core/lib/slice/slice_string_helpers.h )
s.files += %w( src/core/lib/surface/api_trace.h ) s.files += %w( src/core/lib/surface/api_trace.h )
@ -256,14 +258,17 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/init.h ) s.files += %w( src/core/lib/surface/init.h )
s.files += %w( src/core/lib/surface/lame_client.h ) s.files += %w( src/core/lib/surface/lame_client.h )
s.files += %w( src/core/lib/surface/server.h ) s.files += %w( src/core/lib/surface/server.h )
s.files += %w( src/core/lib/surface/validate_metadata.h )
s.files += %w( src/core/lib/transport/byte_stream.h ) s.files += %w( src/core/lib/transport/byte_stream.h )
s.files += %w( src/core/lib/transport/connectivity_state.h ) s.files += %w( src/core/lib/transport/connectivity_state.h )
s.files += %w( src/core/lib/transport/mdstr_hash_table.h ) s.files += %w( src/core/lib/transport/error_utils.h )
s.files += %w( src/core/lib/transport/http2_errors.h )
s.files += %w( src/core/lib/transport/metadata.h ) s.files += %w( src/core/lib/transport/metadata.h )
s.files += %w( src/core/lib/transport/metadata_batch.h ) s.files += %w( src/core/lib/transport/metadata_batch.h )
s.files += %w( src/core/lib/transport/pid_controller.h ) s.files += %w( src/core/lib/transport/pid_controller.h )
s.files += %w( src/core/lib/transport/service_config.h ) s.files += %w( src/core/lib/transport/service_config.h )
s.files += %w( src/core/lib/transport/static_metadata.h ) s.files += %w( src/core/lib/transport/static_metadata.h )
s.files += %w( src/core/lib/transport/status_conversion.h )
s.files += %w( src/core/lib/transport/timeout_encoding.h ) s.files += %w( src/core/lib/transport/timeout_encoding.h )
s.files += %w( src/core/lib/transport/transport.h ) s.files += %w( src/core/lib/transport/transport.h )
s.files += %w( src/core/lib/transport/transport_impl.h ) s.files += %w( src/core/lib/transport/transport_impl.h )
@ -280,11 +285,9 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.h ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_encoder.h )
s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.h ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_parser.h )
s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.h ) s.files += %w( src/core/ext/transport/chttp2/transport/hpack_table.h )
s.files += %w( src/core/ext/transport/chttp2/transport/http2_errors.h )
s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h ) s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h ) s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.h )
s.files += %w( src/core/ext/transport/chttp2/transport/internal.h ) s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )
s.files += %w( src/core/ext/transport/chttp2/transport/status_conversion.h )
s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.h ) s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.h )
s.files += %w( src/core/ext/transport/chttp2/transport/varint.h ) s.files += %w( src/core/ext/transport/chttp2/transport/varint.h )
s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h ) s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h )
@ -439,6 +442,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/slice/percent_encoding.c ) s.files += %w( src/core/lib/slice/percent_encoding.c )
s.files += %w( src/core/lib/slice/slice.c ) s.files += %w( src/core/lib/slice/slice.c )
s.files += %w( src/core/lib/slice/slice_buffer.c ) s.files += %w( src/core/lib/slice/slice_buffer.c )
s.files += %w( src/core/lib/slice/slice_hash_table.c )
s.files += %w( src/core/lib/slice/slice_intern.c )
s.files += %w( src/core/lib/slice/slice_string_helpers.c ) s.files += %w( src/core/lib/slice/slice_string_helpers.c )
s.files += %w( src/core/lib/surface/alarm.c ) s.files += %w( src/core/lib/surface/alarm.c )
s.files += %w( src/core/lib/surface/api_trace.c ) s.files += %w( src/core/lib/surface/api_trace.c )
@ -460,12 +465,13 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/version.c ) s.files += %w( src/core/lib/surface/version.c )
s.files += %w( src/core/lib/transport/byte_stream.c ) s.files += %w( src/core/lib/transport/byte_stream.c )
s.files += %w( src/core/lib/transport/connectivity_state.c ) s.files += %w( src/core/lib/transport/connectivity_state.c )
s.files += %w( src/core/lib/transport/mdstr_hash_table.c ) s.files += %w( src/core/lib/transport/error_utils.c )
s.files += %w( src/core/lib/transport/metadata.c ) s.files += %w( src/core/lib/transport/metadata.c )
s.files += %w( src/core/lib/transport/metadata_batch.c ) s.files += %w( src/core/lib/transport/metadata_batch.c )
s.files += %w( src/core/lib/transport/pid_controller.c ) s.files += %w( src/core/lib/transport/pid_controller.c )
s.files += %w( src/core/lib/transport/service_config.c ) s.files += %w( src/core/lib/transport/service_config.c )
s.files += %w( src/core/lib/transport/static_metadata.c ) s.files += %w( src/core/lib/transport/static_metadata.c )
s.files += %w( src/core/lib/transport/status_conversion.c )
s.files += %w( src/core/lib/transport/timeout_encoding.c ) s.files += %w( src/core/lib/transport/timeout_encoding.c )
s.files += %w( src/core/lib/transport/transport.c ) s.files += %w( src/core/lib/transport/transport.c )
s.files += %w( src/core/lib/transport/transport_op_string.c ) s.files += %w( src/core/lib/transport/transport_op_string.c )
@ -486,7 +492,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.c ) s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.c )
s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.c ) s.files += %w( src/core/ext/transport/chttp2/transport/incoming_metadata.c )
s.files += %w( src/core/ext/transport/chttp2/transport/parsing.c ) s.files += %w( src/core/ext/transport/chttp2/transport/parsing.c )
s.files += %w( src/core/ext/transport/chttp2/transport/status_conversion.c )
s.files += %w( src/core/ext/transport/chttp2/transport/stream_lists.c ) s.files += %w( src/core/ext/transport/chttp2/transport/stream_lists.c )
s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.c ) s.files += %w( src/core/ext/transport/chttp2/transport/stream_map.c )
s.files += %w( src/core/ext/transport/chttp2/transport/varint.c ) s.files += %w( src/core/ext/transport/chttp2/transport/varint.c )

@ -45,6 +45,7 @@
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h> #include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h> #include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/slice.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/status_helper.h> #include <grpc++/impl/codegen/status_helper.h>
#include <grpc++/impl/codegen/string_ref.h> #include <grpc++/impl/codegen/string_ref.h>
@ -62,19 +63,6 @@ class CallHook;
class CompletionQueue; class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface; extern CoreCodegenInterface* g_core_codegen_interface;
inline void FillMetadataMap(
grpc_metadata_array* arr,
std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
for (size_t i = 0; i < arr->count; i++) {
// TODO(yangg) handle duplicates?
metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
arr->metadata[i].value_length)));
}
g_core_codegen_interface->grpc_metadata_array_destroy(arr);
g_core_codegen_interface->grpc_metadata_array_init(arr);
}
// TODO(yangg) if the map is changed before we send, the pointers will be a // TODO(yangg) if the map is changed before we send, the pointers will be a
// mess. Make sure it does not happen. // mess. Make sure it does not happen.
inline grpc_metadata* FillMetadataArray( inline grpc_metadata* FillMetadataArray(
@ -87,9 +75,8 @@ inline grpc_metadata* FillMetadataArray(
metadata.size() * sizeof(grpc_metadata))); metadata.size() * sizeof(grpc_metadata)));
size_t i = 0; size_t i = 0;
for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) { for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
metadata_array[i].key = iter->first.c_str(); metadata_array[i].key = SliceReferencingString(iter->first);
metadata_array[i].value = iter->second.c_str(); metadata_array[i].value = SliceReferencingString(iter->second);
metadata_array[i].value_length = iter->second.size();
} }
return metadata_array; return metadata_array;
} }
@ -175,7 +162,7 @@ template <int I>
class CallNoOp { class CallNoOp {
protected: protected:
void AddOp(grpc_op* ops, size_t* nops) {} void AddOp(grpc_op* ops, size_t* nops) {}
void FinishOp(bool* status, int max_receive_message_size) {} void FinishOp(bool* status) {}
}; };
class CallOpSendInitialMetadata { class CallOpSendInitialMetadata {
@ -213,7 +200,7 @@ class CallOpSendInitialMetadata {
op->data.send_initial_metadata.maybe_compression_level.level = op->data.send_initial_metadata.maybe_compression_level.level =
maybe_compression_level_.level; maybe_compression_level_.level;
} }
void FinishOp(bool* status, int max_receive_message_size) { void FinishOp(bool* status) {
if (!send_) return; if (!send_) return;
g_core_codegen_interface->gpr_free(initial_metadata_); g_core_codegen_interface->gpr_free(initial_metadata_);
send_ = false; send_ = false;
@ -249,11 +236,11 @@ class CallOpSendMessage {
op->op = GRPC_OP_SEND_MESSAGE; op->op = GRPC_OP_SEND_MESSAGE;
op->flags = write_options_.flags(); op->flags = write_options_.flags();
op->reserved = NULL; op->reserved = NULL;
op->data.send_message = send_buf_; op->data.send_message.send_message = send_buf_;
// Flags are per-message: clear them after use. // Flags are per-message: clear them after use.
write_options_.Clear(); write_options_.Clear();
} }
void FinishOp(bool* status, int max_receive_message_size) { void FinishOp(bool* status) {
if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_); if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
send_buf_ = nullptr; send_buf_ = nullptr;
} }
@ -298,17 +285,15 @@ class CallOpRecvMessage {
op->op = GRPC_OP_RECV_MESSAGE; op->op = GRPC_OP_RECV_MESSAGE;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op->data.recv_message = &recv_buf_; op->data.recv_message.recv_message = &recv_buf_;
} }
void FinishOp(bool* status, int max_receive_message_size) { void FinishOp(bool* status) {
if (message_ == nullptr) return; if (message_ == nullptr) return;
if (recv_buf_) { if (recv_buf_) {
if (*status) { if (*status) {
got_message = *status = got_message = *status =
SerializationTraits<R>::Deserialize(recv_buf_, message_, SerializationTraits<R>::Deserialize(recv_buf_, message_).ok();
max_receive_message_size)
.ok();
} else { } else {
got_message = false; got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_); g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@ -331,8 +316,7 @@ class CallOpRecvMessage {
namespace CallOpGenericRecvMessageHelper { namespace CallOpGenericRecvMessageHelper {
class DeserializeFunc { class DeserializeFunc {
public: public:
virtual Status Deserialize(grpc_byte_buffer* buf, virtual Status Deserialize(grpc_byte_buffer* buf) = 0;
int max_receive_message_size) = 0;
virtual ~DeserializeFunc() {} virtual ~DeserializeFunc() {}
}; };
@ -340,10 +324,8 @@ template <class R>
class DeserializeFuncType final : public DeserializeFunc { class DeserializeFuncType final : public DeserializeFunc {
public: public:
DeserializeFuncType(R* message) : message_(message) {} DeserializeFuncType(R* message) : message_(message) {}
Status Deserialize(grpc_byte_buffer* buf, Status Deserialize(grpc_byte_buffer* buf) override {
int max_receive_message_size) override { return SerializationTraits<R>::Deserialize(buf, message_);
return SerializationTraits<R>::Deserialize(buf, message_,
max_receive_message_size);
} }
~DeserializeFuncType() override {} ~DeserializeFuncType() override {}
@ -379,16 +361,15 @@ class CallOpGenericRecvMessage {
op->op = GRPC_OP_RECV_MESSAGE; op->op = GRPC_OP_RECV_MESSAGE;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op->data.recv_message = &recv_buf_; op->data.recv_message.recv_message = &recv_buf_;
} }
void FinishOp(bool* status, int max_receive_message_size) { void FinishOp(bool* status) {
if (!deserialize_) return; if (!deserialize_) return;
if (recv_buf_) { if (recv_buf_) {
if (*status) { if (*status) {
got_message = true; got_message = true;
*status = *status = deserialize_->Deserialize(recv_buf_).ok();
deserialize_->Deserialize(recv_buf_, max_receive_message_size).ok();
} else { } else {
got_message = false; got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_); g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@ -422,7 +403,7 @@ class CallOpClientSendClose {
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
} }
void FinishOp(bool* status, int max_receive_message_size) { send_ = false; } void FinishOp(bool* status) { send_ = false; }
private: private:
bool send_; bool send_;
@ -451,13 +432,14 @@ class CallOpServerSendStatus {
trailing_metadata_count_; trailing_metadata_count_;
op->data.send_status_from_server.trailing_metadata = trailing_metadata_; op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
op->data.send_status_from_server.status = send_status_code_; op->data.send_status_from_server.status = send_status_code_;
status_details_slice_ = SliceReferencingString(send_status_details_);
op->data.send_status_from_server.status_details = op->data.send_status_from_server.status_details =
send_status_details_.empty() ? nullptr : send_status_details_.c_str(); send_status_details_.empty() ? nullptr : &status_details_slice_;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
} }
void FinishOp(bool* status, int max_receive_message_size) { void FinishOp(bool* status) {
if (!send_status_available_) return; if (!send_status_available_) return;
g_core_codegen_interface->gpr_free(trailing_metadata_); g_core_codegen_interface->gpr_free(trailing_metadata_);
send_status_available_ = false; send_status_available_ = false;
@ -469,36 +451,36 @@ class CallOpServerSendStatus {
grpc::string send_status_details_; grpc::string send_status_details_;
size_t trailing_metadata_count_; size_t trailing_metadata_count_;
grpc_metadata* trailing_metadata_; grpc_metadata* trailing_metadata_;
grpc_slice status_details_slice_;
}; };
class CallOpRecvInitialMetadata { class CallOpRecvInitialMetadata {
public: public:
CallOpRecvInitialMetadata() : recv_initial_metadata_(nullptr) {} CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
void RecvInitialMetadata(ClientContext* context) { void RecvInitialMetadata(ClientContext* context) {
context->initial_metadata_received_ = true; context->initial_metadata_received_ = true;
recv_initial_metadata_ = &context->recv_initial_metadata_; metadata_map_ = &context->recv_initial_metadata_;
} }
protected: protected:
void AddOp(grpc_op* ops, size_t* nops) { void AddOp(grpc_op* ops, size_t* nops) {
if (!recv_initial_metadata_) return; if (metadata_map_ == nullptr) return;
memset(&recv_initial_metadata_arr_, 0, sizeof(recv_initial_metadata_arr_));
grpc_op* op = &ops[(*nops)++]; grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_RECV_INITIAL_METADATA; op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &recv_initial_metadata_arr_; op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr();
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
} }
void FinishOp(bool* status, int max_receive_message_size) {
if (recv_initial_metadata_ == nullptr) return; void FinishOp(bool* status) {
FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_); if (metadata_map_ == nullptr) return;
recv_initial_metadata_ = nullptr; metadata_map_->FillMap();
metadata_map_ = nullptr;
} }
private: private:
std::multimap<grpc::string_ref, grpc::string_ref>* recv_initial_metadata_; MetadataMap* metadata_map_;
grpc_metadata_array recv_initial_metadata_arr_;
}; };
class CallOpClientRecvStatus { class CallOpClientRecvStatus {
@ -506,46 +488,37 @@ class CallOpClientRecvStatus {
CallOpClientRecvStatus() : recv_status_(nullptr) {} CallOpClientRecvStatus() : recv_status_(nullptr) {}
void ClientRecvStatus(ClientContext* context, Status* status) { void ClientRecvStatus(ClientContext* context, Status* status) {
recv_trailing_metadata_ = &context->trailing_metadata_; metadata_map_ = &context->trailing_metadata_;
recv_status_ = status; recv_status_ = status;
} }
protected: protected:
void AddOp(grpc_op* ops, size_t* nops) { void AddOp(grpc_op* ops, size_t* nops) {
if (recv_status_ == nullptr) return; if (recv_status_ == nullptr) return;
memset(&recv_trailing_metadata_arr_, 0,
sizeof(recv_trailing_metadata_arr_));
status_details_ = nullptr;
status_details_capacity_ = 0;
grpc_op* op = &ops[(*nops)++]; grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
&recv_trailing_metadata_arr_;
op->data.recv_status_on_client.status = &status_code_; op->data.recv_status_on_client.status = &status_code_;
op->data.recv_status_on_client.status_details = &status_details_; op->data.recv_status_on_client.status_details = &status_details_;
op->data.recv_status_on_client.status_details_capacity =
&status_details_capacity_;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
} }
void FinishOp(bool* status, int max_receive_message_size) { void FinishOp(bool* status) {
if (recv_status_ == nullptr) return; if (recv_status_ == nullptr) return;
FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_); metadata_map_->FillMap();
*recv_status_ = Status( *recv_status_ = Status(static_cast<StatusCode>(status_code_),
static_cast<StatusCode>(status_code_), grpc::string(GRPC_SLICE_START_PTR(status_details_),
status_details_ ? grpc::string(status_details_) : grpc::string()); GRPC_SLICE_END_PTR(status_details_)));
g_core_codegen_interface->gpr_free(status_details_); g_core_codegen_interface->grpc_slice_unref(status_details_);
recv_status_ = nullptr; recv_status_ = nullptr;
} }
private: private:
std::multimap<grpc::string_ref, grpc::string_ref>* recv_trailing_metadata_; MetadataMap* metadata_map_;
Status* recv_status_; Status* recv_status_;
grpc_metadata_array recv_trailing_metadata_arr_;
grpc_status_code status_code_; grpc_status_code status_code_;
char* status_details_; grpc_slice status_details_;
size_t status_details_capacity_;
}; };
/// An abstract collection of CallOpSet's, to be used whenever /// An abstract collection of CallOpSet's, to be used whenever
@ -566,22 +539,17 @@ class CallOpSetCollectionInterface
/// API. /// API.
class CallOpSetInterface : public CompletionQueueTag { class CallOpSetInterface : public CompletionQueueTag {
public: public:
CallOpSetInterface() : max_receive_message_size_(0) {} CallOpSetInterface() {}
/// Fills in grpc_op, starting from ops[*nops] and moving /// Fills in grpc_op, starting from ops[*nops] and moving
/// upwards. /// upwards.
virtual void FillOps(grpc_op* ops, size_t* nops) = 0; virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
void set_max_receive_message_size(int max_receive_message_size) {
max_receive_message_size_ = max_receive_message_size;
}
/// Mark this as belonging to a collection if needed /// Mark this as belonging to a collection if needed
void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) { void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) {
collection_ = collection; collection_ = collection;
} }
protected: protected:
int max_receive_message_size_;
std::shared_ptr<CallOpSetCollectionInterface> collection_; std::shared_ptr<CallOpSetCollectionInterface> collection_;
}; };
@ -613,12 +581,12 @@ class CallOpSet : public CallOpSetInterface,
} }
bool FinalizeResult(void** tag, bool* status) override { bool FinalizeResult(void** tag, bool* status) override {
this->Op1::FinishOp(status, max_receive_message_size_); this->Op1::FinishOp(status);
this->Op2::FinishOp(status, max_receive_message_size_); this->Op2::FinishOp(status);
this->Op3::FinishOp(status, max_receive_message_size_); this->Op3::FinishOp(status);
this->Op4::FinishOp(status, max_receive_message_size_); this->Op4::FinishOp(status);
this->Op5::FinishOp(status, max_receive_message_size_); this->Op5::FinishOp(status);
this->Op6::FinishOp(status, max_receive_message_size_); this->Op6::FinishOp(status);
*tag = return_tag_; *tag = return_tag_;
collection_.reset(); // drop the ref at this point collection_.reset(); // drop the ref at this point
return true; return true;
@ -650,35 +618,19 @@ class Call final {
public: public:
/* call is owned by the caller */ /* call is owned by the caller */
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq) Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook), : call_hook_(call_hook), cq_(cq), call_(call) {}
cq_(cq),
call_(call),
max_receive_message_size_(-1) {}
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
int max_receive_message_size)
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_receive_message_size_(max_receive_message_size) {}
void PerformOps(CallOpSetInterface* ops) { void PerformOps(CallOpSetInterface* ops) {
if (max_receive_message_size_ > 0) {
ops->set_max_receive_message_size(max_receive_message_size_);
}
call_hook_->PerformOpsOnCall(ops, this); call_hook_->PerformOpsOnCall(ops, this);
} }
grpc_call* call() const { return call_; } grpc_call* call() const { return call_; }
CompletionQueue* cq() const { return cq_; } CompletionQueue* cq() const { return cq_; }
int max_receive_message_size() { return max_receive_message_size_; }
private: private:
CallHook* call_hook_; CallHook* call_hook_;
CompletionQueue* cq_; CompletionQueue* cq_;
grpc_call* call_; grpc_call* call_;
int max_receive_message_size_;
}; };
} // namespace grpc } // namespace grpc

@ -57,7 +57,9 @@
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h> #include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/create_auth_context.h> #include <grpc++/impl/codegen/create_auth_context.h>
#include <grpc++/impl/codegen/metadata_map.h>
#include <grpc++/impl/codegen/security/auth_context.h> #include <grpc++/impl/codegen/security/auth_context.h>
#include <grpc++/impl/codegen/slice.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/string_ref.h> #include <grpc++/impl/codegen/string_ref.h>
#include <grpc++/impl/codegen/time.h> #include <grpc++/impl/codegen/time.h>
@ -193,7 +195,7 @@ class ClientContext {
const std::multimap<grpc::string_ref, grpc::string_ref>& const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerInitialMetadata() const { GetServerInitialMetadata() const {
GPR_CODEGEN_ASSERT(initial_metadata_received_); GPR_CODEGEN_ASSERT(initial_metadata_received_);
return recv_initial_metadata_; return *recv_initial_metadata_.map();
} }
/// Return a collection of trailing metadata key-value pairs. Note that keys /// Return a collection of trailing metadata key-value pairs. Note that keys
@ -205,7 +207,7 @@ class ClientContext {
const std::multimap<grpc::string_ref, grpc::string_ref>& const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerTrailingMetadata() const { GetServerTrailingMetadata() const {
// TODO(yangg) check finished // TODO(yangg) check finished
return trailing_metadata_; return *trailing_metadata_.map();
} }
/// Set the deadline for the client call. /// Set the deadline for the client call.
@ -375,8 +377,8 @@ class ClientContext {
mutable std::shared_ptr<const AuthContext> auth_context_; mutable std::shared_ptr<const AuthContext> auth_context_;
struct census_context* census_context_; struct census_context* census_context_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_; std::multimap<grpc::string, grpc::string> send_initial_metadata_;
std::multimap<grpc::string_ref, grpc::string_ref> recv_initial_metadata_; MetadataMap recv_initial_metadata_;
std::multimap<grpc::string_ref, grpc::string_ref> trailing_metadata_; MetadataMap trailing_metadata_;
grpc_call* propagate_from_call_; grpc_call* propagate_from_call_;
PropagationOptions propagation_options_; PropagationOptions propagation_options_;

@ -69,7 +69,14 @@ Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ops.ClientSendClose(); ops.ClientSendClose();
ops.ClientRecvStatus(context, &status); ops.ClientRecvStatus(context, &status);
call.PerformOps(&ops); call.PerformOps(&ops);
GPR_CODEGEN_ASSERT((cq.Pluck(&ops) && ops.got_message) || !status.ok()); if (cq.Pluck(&ops)) {
if (!ops.got_message && status.ok()) {
return Status(StatusCode::UNIMPLEMENTED,
"No message returned for unary request");
}
} else {
GPR_CODEGEN_ASSERT(!status.ok());
}
return status; return status;
} }

@ -81,7 +81,10 @@ class CoreCodegen : public CoreCodegenInterface {
grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override; grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override;
void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override; void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override;
void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override; void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override;
grpc_slice grpc_slice_from_static_buffer(const void* buffer,
size_t length) override;
grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
size_t length) override;
void grpc_metadata_array_init(grpc_metadata_array* array) override; void grpc_metadata_array_init(grpc_metadata_array* array) override;
void grpc_metadata_array_destroy(grpc_metadata_array* array) override; void grpc_metadata_array_destroy(grpc_metadata_array* array) override;
@ -91,7 +94,8 @@ class CoreCodegen : public CoreCodegenInterface {
virtual const Status& ok() override; virtual const Status& ok() override;
virtual const Status& cancelled() override; virtual const Status& cancelled() override;
void assert_fail(const char* failed_assertion) override; void assert_fail(const char* failed_assertion, const char* file,
int line) override;
}; };
} // namespace grpc } // namespace grpc

@ -56,7 +56,8 @@ namespace grpc {
class CoreCodegenInterface { class CoreCodegenInterface {
public: public:
/// Upon a failed assertion, log the error. /// Upon a failed assertion, log the error.
virtual void assert_fail(const char* failed_assertion) = 0; virtual void assert_fail(const char* failed_assertion, const char* file,
int line) = 0;
virtual grpc_completion_queue* grpc_completion_queue_create( virtual grpc_completion_queue* grpc_completion_queue_create(
void* reserved) = 0; void* reserved) = 0;
@ -99,6 +100,10 @@ class CoreCodegenInterface {
virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb, virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb,
grpc_slice slice) = 0; grpc_slice slice) = 0;
virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0; virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0;
virtual grpc_slice grpc_slice_from_static_buffer(const void* buffer,
size_t length) = 0;
virtual grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
size_t length) = 0;
virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0; virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0;
virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0; virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0;
@ -113,11 +118,11 @@ class CoreCodegenInterface {
extern CoreCodegenInterface* g_core_codegen_interface; extern CoreCodegenInterface* g_core_codegen_interface;
/// Codegen specific version of \a GPR_ASSERT. /// Codegen specific version of \a GPR_ASSERT.
#define GPR_CODEGEN_ASSERT(x) \ #define GPR_CODEGEN_ASSERT(x) \
do { \ do { \
if (!(x)) { \ if (!(x)) { \
grpc::g_core_codegen_interface->assert_fail(#x); \ grpc::g_core_codegen_interface->assert_fail(#x, __FILE__, __LINE__); \
} \ } \
} while (0) } while (0)
} // namespace grpc } // namespace grpc

@ -0,0 +1,71 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
#define GRPCXX_IMPL_CODEGEN_METADATA_MAP_H
#include <grpc++/impl/codegen/slice.h>
namespace grpc {
class MetadataMap {
public:
MetadataMap() { memset(&arr_, 0, sizeof(arr_)); }
~MetadataMap() {
g_core_codegen_interface->grpc_metadata_array_destroy(&arr_);
}
void FillMap() {
for (size_t i = 0; i < arr_.count; i++) {
// TODO(yangg) handle duplicates?
map_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
StringRefFromSlice(&arr_.metadata[i].key),
StringRefFromSlice(&arr_.metadata[i].value)));
}
}
std::multimap<grpc::string_ref, grpc::string_ref> *map() { return &map_; }
const std::multimap<grpc::string_ref, grpc::string_ref> *map() const {
return &map_;
}
grpc_metadata_array *arr() { return &arr_; }
private:
grpc_metadata_array arr_;
std::multimap<grpc::string_ref, grpc::string_ref> map_;
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_METADATA_MAP_H

@ -52,8 +52,8 @@ class RpcMethodHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) final { void RunHandler(const HandlerParameter& param) final {
RequestType req; RequestType req;
Status status = SerializationTraits<RequestType>::Deserialize( Status status =
param.request, &req, param.max_receive_message_size); SerializationTraits<RequestType>::Deserialize(param.request, &req);
ResponseType rsp; ResponseType rsp;
if (status.ok()) { if (status.ok()) {
status = func_(service_, param.server_context, &req, &rsp); status = func_(service_, param.server_context, &req, &rsp);
@ -138,8 +138,8 @@ class ServerStreamingHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) final { void RunHandler(const HandlerParameter& param) final {
RequestType req; RequestType req;
Status status = SerializationTraits<RequestType>::Deserialize( Status status =
param.request, &req, param.max_receive_message_size); SerializationTraits<RequestType>::Deserialize(param.request, &req);
if (status.ok()) { if (status.ok()) {
ServerWriter<ResponseType> writer(param.call, param.server_context); ServerWriter<ResponseType> writer(param.call, param.server_context);

@ -203,8 +203,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
} }
static Status Deserialize(grpc_byte_buffer* buffer, static Status Deserialize(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg, grpc::protobuf::Message* msg) {
int max_receive_message_size) {
if (buffer == nullptr) { if (buffer == nullptr) {
return Status(StatusCode::INTERNAL, "No payload"); return Status(StatusCode::INTERNAL, "No payload");
} }
@ -215,10 +214,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
return reader.status(); return reader.status();
} }
::grpc::protobuf::io::CodedInputStream decoder(&reader); ::grpc::protobuf::io::CodedInputStream decoder(&reader);
if (max_receive_message_size > 0) { decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
decoder.SetTotalBytesLimit(max_receive_message_size,
max_receive_message_size);
}
if (!msg->ParseFromCodedStream(&decoder)) { if (!msg->ParseFromCodedStream(&decoder)) {
result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
} }

@ -57,17 +57,12 @@ class MethodHandler {
public: public:
virtual ~MethodHandler() {} virtual ~MethodHandler() {}
struct HandlerParameter { struct HandlerParameter {
HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req, HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req)
int max_size) : call(c), server_context(context), request(req) {}
: call(c),
server_context(context),
request(req),
max_receive_message_size(max_size) {}
Call* call; Call* call;
ServerContext* server_context; ServerContext* server_context;
// Handler required to grpc_byte_buffer_destroy this // Handler required to grpc_byte_buffer_destroy this
grpc_byte_buffer* request; grpc_byte_buffer* request;
int max_receive_message_size;
}; };
virtual void RunHandler(const HandlerParameter& param) = 0; virtual void RunHandler(const HandlerParameter& param) = 0;
}; };

@ -39,6 +39,7 @@
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/create_auth_context.h> #include <grpc++/impl/codegen/create_auth_context.h>
#include <grpc++/impl/codegen/metadata_map.h>
#include <grpc++/impl/codegen/security/auth_context.h> #include <grpc++/impl/codegen/security/auth_context.h>
#include <grpc++/impl/codegen/string_ref.h> #include <grpc++/impl/codegen/string_ref.h>
#include <grpc++/impl/codegen/time.h> #include <grpc++/impl/codegen/time.h>
@ -123,7 +124,7 @@ class ServerContext {
const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata() const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
const { const {
return client_metadata_; return *client_metadata_.map();
} }
grpc_compression_level compression_level() const { grpc_compression_level compression_level() const {
@ -223,7 +224,7 @@ class ServerContext {
CompletionQueue* cq_; CompletionQueue* cq_;
bool sent_initial_metadata_; bool sent_initial_metadata_;
mutable std::shared_ptr<const AuthContext> auth_context_; mutable std::shared_ptr<const AuthContext> auth_context_;
std::multimap<grpc::string_ref, grpc::string_ref> client_metadata_; MetadataMap client_metadata_;
std::multimap<grpc::string, grpc::string> initial_metadata_; std::multimap<grpc::string, grpc::string> initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_; std::multimap<grpc::string, grpc::string> trailing_metadata_;

@ -152,7 +152,6 @@ class ServerInterface : public CallHook {
void* const tag_; void* const tag_;
const bool delete_on_finalize_; const bool delete_on_finalize_;
grpc_call* call_; grpc_call* call_;
grpc_metadata_array initial_metadata_array_;
}; };
class RegisteredAsyncRequest : public BaseAsyncRequest { class RegisteredAsyncRequest : public BaseAsyncRequest {
@ -199,9 +198,7 @@ class ServerInterface : public CallHook {
bool FinalizeResult(void** tag, bool* status) override { bool FinalizeResult(void** tag, bool* status) override {
bool serialization_status = bool serialization_status =
*status && payload_ && *status && payload_ &&
SerializationTraits<Message>::Deserialize( SerializationTraits<Message>::Deserialize(payload_, request_).ok();
payload_, request_, server_->max_receive_message_size())
.ok();
bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status); bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
*status = serialization_status && *status; *status = serialization_status && *status;
return ret; return ret;

@ -0,0 +1,65 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_IMPL_CODEGEN_SLICE_H
#define GRPCXX_IMPL_CODEGEN_SLICE_H
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/string_ref.h>
namespace grpc {
inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) {
return grpc::string_ref(
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice)),
GRPC_SLICE_LENGTH(*slice));
}
inline grpc::string StringFromCopiedSlice(grpc_slice slice) {
return grpc::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
GRPC_SLICE_LENGTH(slice));
}
inline grpc_slice SliceReferencingString(const grpc::string& str) {
return g_core_codegen_interface->grpc_slice_from_static_buffer(str.data(),
str.length());
}
inline grpc_slice SliceFromCopiedString(const grpc::string& str) {
return g_core_codegen_interface->grpc_slice_from_copied_buffer(str.data(),
str.length());
}
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_SLICE_H

@ -160,7 +160,7 @@ class ClientReader final : public ClientReaderInterface<R> {
} }
bool NextMessageSize(uint32_t* sz) override { bool NextMessageSize(uint32_t* sz) override {
*sz = call_.max_receive_message_size(); *sz = INT_MAX;
return true; return true;
} }
@ -310,7 +310,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
} }
bool NextMessageSize(uint32_t* sz) override { bool NextMessageSize(uint32_t* sz) override {
*sz = call_.max_receive_message_size(); *sz = INT_MAX;
return true; return true;
} }
@ -382,7 +382,7 @@ class ServerReader final : public ServerReaderInterface<R> {
} }
bool NextMessageSize(uint32_t* sz) override { bool NextMessageSize(uint32_t* sz) override {
*sz = call_->max_receive_message_size(); *sz = INT_MAX;
return true; return true;
} }
@ -474,7 +474,7 @@ class ServerReaderWriterBody final {
} }
bool NextMessageSize(uint32_t* sz) { bool NextMessageSize(uint32_t* sz) {
*sz = call_->max_receive_message_size(); *sz = INT_MAX;
return true; return true;
} }

@ -95,8 +95,7 @@ class ByteBuffer final {
template <> template <>
class SerializationTraits<ByteBuffer, void> { class SerializationTraits<ByteBuffer, void> {
public: public:
static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest, static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest) {
int max_receive_message_size) {
dest->set_buffer(byte_buffer); dest->set_buffer(byte_buffer);
return Status::OK; return Status::OK;
} }

@ -34,11 +34,12 @@
#ifndef GRPC_COMPRESSION_H #ifndef GRPC_COMPRESSION_H
#define GRPC_COMPRESSION_H #define GRPC_COMPRESSION_H
#include <stdlib.h>
#include <grpc/impl/codegen/port_platform.h> #include <grpc/impl/codegen/port_platform.h>
#include <stdlib.h>
#include <grpc/impl/codegen/compression_types.h> #include <grpc/impl/codegen/compression_types.h>
#include <grpc/slice.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -48,8 +49,7 @@ extern "C" {
* grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon * grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon
* success, 0 otherwise. */ * success, 0 otherwise. */
GRPCAPI int grpc_compression_algorithm_parse( GRPCAPI int grpc_compression_algorithm_parse(
const char *name, size_t name_length, grpc_slice value, grpc_compression_algorithm *algorithm);
grpc_compression_algorithm *algorithm);
/** Updates \a name with the encoding name corresponding to a valid \a /** Updates \a name with the encoding name corresponding to a valid \a
* algorithm. Note that \a name is statically allocated and must *not* be freed. * algorithm. Note that \a name is statically allocated and must *not* be freed.

@ -178,8 +178,8 @@ GRPCAPI void grpc_channel_watch_connectivity_state(
possible values). */ possible values). */
GRPCAPI grpc_call *grpc_channel_create_call( GRPCAPI grpc_call *grpc_channel_create_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
grpc_completion_queue *completion_queue, const char *method, grpc_completion_queue *completion_queue, grpc_slice method,
const char *host, gpr_timespec deadline, void *reserved); const grpc_slice *host, gpr_timespec deadline, void *reserved);
/** Ping the channels peer (load balanced channels will select one sub-channel /** Ping the channels peer (load balanced channels will select one sub-channel
to ping); if the channel is not connected, posts a failed. */ to ping); if the channel is not connected, posts a failed. */
@ -402,14 +402,14 @@ GRPCAPI void grpc_server_destroy(grpc_server *server);
GRPCAPI int grpc_tracer_set_enabled(const char *name, int enabled); GRPCAPI int grpc_tracer_set_enabled(const char *name, int enabled);
/** Check whether a metadata key is legal (will be accepted by core) */ /** Check whether a metadata key is legal (will be accepted by core) */
GRPCAPI int grpc_header_key_is_legal(const char *key, size_t length); GRPCAPI int grpc_header_key_is_legal(grpc_slice slice);
/** Check whether a non-binary metadata value is legal (will be accepted by /** Check whether a non-binary metadata value is legal (will be accepted by
core) */ core) */
GRPCAPI int grpc_header_nonbin_value_is_legal(const char *value, size_t length); GRPCAPI int grpc_header_nonbin_value_is_legal(grpc_slice slice);
/** Check whether a metadata key corresponds to a binary value */ /** Check whether a metadata key corresponds to a binary value */
GRPCAPI int grpc_is_binary_header(const char *key, size_t length); GRPCAPI int grpc_is_binary_header(grpc_slice slice);
/** Convert grpc_call_error values to a string */ /** Convert grpc_call_error values to a string */
GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error); GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error);

@ -294,9 +294,11 @@ typedef enum grpc_call_error {
/** A single metadata element */ /** A single metadata element */
typedef struct grpc_metadata { typedef struct grpc_metadata {
const char *key; /* the key, value values are expected to line up with grpc_mdelem: if changing
const char *value; them, update metadata.h at the same time. */
size_t value_length; grpc_slice key;
grpc_slice value;
uint32_t flags; uint32_t flags;
/** The following fields are reserved for grpc internal use. /** The following fields are reserved for grpc internal use.
@ -338,10 +340,8 @@ typedef struct {
} grpc_metadata_array; } grpc_metadata_array;
typedef struct { typedef struct {
char *method; grpc_slice method;
size_t method_capacity; grpc_slice host;
char *host;
size_t host_capacity;
gpr_timespec deadline; gpr_timespec deadline;
uint32_t flags; uint32_t flags;
void *reserved; void *reserved;
@ -418,23 +418,32 @@ typedef struct grpc_op {
grpc_compression_level level; grpc_compression_level level;
} maybe_compression_level; } maybe_compression_level;
} send_initial_metadata; } send_initial_metadata;
struct grpc_byte_buffer *send_message; struct {
struct grpc_byte_buffer *send_message;
} send_message;
struct { struct {
size_t trailing_metadata_count; size_t trailing_metadata_count;
grpc_metadata *trailing_metadata; grpc_metadata *trailing_metadata;
grpc_status_code status; grpc_status_code status;
const char *status_details; /* optional: set to NULL if no details need sending, non-NULL if they do
* pointer will not be retained past the start_batch call
*/
grpc_slice *status_details;
} send_status_from_server; } send_status_from_server;
/** ownership of the array is with the caller, but ownership of the elements /** ownership of the array is with the caller, but ownership of the elements
stays with the call object (ie key, value members are owned by the call stays with the call object (ie key, value members are owned by the call
object, recv_initial_metadata->array is owned by the caller). object, recv_initial_metadata->array is owned by the caller).
After the operation completes, call grpc_metadata_array_destroy on this After the operation completes, call grpc_metadata_array_destroy on this
value, or reuse it in a future op. */ value, or reuse it in a future op. */
grpc_metadata_array *recv_initial_metadata; struct {
grpc_metadata_array *recv_initial_metadata;
} recv_initial_metadata;
/** ownership of the byte buffer is moved to the caller; the caller must /** ownership of the byte buffer is moved to the caller; the caller must
call grpc_byte_buffer_destroy on this value, or reuse it in a future op. call grpc_byte_buffer_destroy on this value, or reuse it in a future op.
*/ */
struct grpc_byte_buffer **recv_message; struct {
struct grpc_byte_buffer **recv_message;
} recv_message;
struct { struct {
/** ownership of the array is with the caller, but ownership of the /** ownership of the array is with the caller, but ownership of the
elements stays with the call object (ie key, value members are owned elements stays with the call object (ie key, value members are owned
@ -444,28 +453,7 @@ typedef struct grpc_op {
value, or reuse it in a future op. */ value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata; grpc_metadata_array *trailing_metadata;
grpc_status_code *status; grpc_status_code *status;
/** status_details is a buffer owned by the application before the op grpc_slice *status_details;
completes and after the op has completed. During the operation
status_details may be reallocated to a size larger than
*status_details_capacity, in which case *status_details_capacity will
be updated with the new array capacity.
Pre-allocating space:
size_t my_capacity = 8;
char *my_details = gpr_malloc(my_capacity);
x.status_details = &my_details;
x.status_details_capacity = &my_capacity;
Not pre-allocating space:
size_t my_capacity = 0;
char *my_details = NULL;
x.status_details = &my_details;
x.status_details_capacity = &my_capacity;
After the call:
gpr_free(my_details); */
char **status_details;
size_t *status_details_capacity;
} recv_status_on_client; } recv_status_on_client;
struct { struct {
/** out argument, set to 1 if the call failed in any way (seen as a /** out argument, set to 1 if the call failed in any way (seen as a

@ -40,6 +40,8 @@
#include <grpc/impl/codegen/exec_ctx_fwd.h> #include <grpc/impl/codegen/exec_ctx_fwd.h>
#include <grpc/impl/codegen/gpr_slice.h> #include <grpc/impl/codegen/gpr_slice.h>
typedef struct grpc_slice grpc_slice;
/* Slice API /* Slice API
A slice represents a contiguous reference counted array of bytes. A slice represents a contiguous reference counted array of bytes.
@ -53,14 +55,25 @@
reference ownership semantics (who should call unref?) and mutability reference ownership semantics (who should call unref?) and mutability
constraints (is the callee allowed to modify the slice?) */ constraints (is the callee allowed to modify the slice?) */
typedef struct grpc_slice_refcount_vtable {
void (*ref)(void *);
void (*unref)(grpc_exec_ctx *exec_ctx, void *);
int (*eq)(grpc_slice a, grpc_slice b);
uint32_t (*hash)(grpc_slice slice);
} grpc_slice_refcount_vtable;
/* Reference count container for grpc_slice. Contains function pointers to /* Reference count container for grpc_slice. Contains function pointers to
increment and decrement reference counts. Implementations should cleanup increment and decrement reference counts. Implementations should cleanup
when the reference count drops to zero. when the reference count drops to zero.
Typically client code should not touch this, and use grpc_slice_malloc, Typically client code should not touch this, and use grpc_slice_malloc,
grpc_slice_new, or grpc_slice_new_with_len instead. */ grpc_slice_new, or grpc_slice_new_with_len instead. */
typedef struct grpc_slice_refcount { typedef struct grpc_slice_refcount {
void (*ref)(void *); const grpc_slice_refcount_vtable *vtable;
void (*unref)(grpc_exec_ctx *exec_ctx, void *); /* If a subset of this slice is taken, use this pointer for the refcount.
Typically points back to the refcount itself, however iterning
implementations can use this to avoid a verification step on each hash
or equality check */
struct grpc_slice_refcount *sub_refcount;
} grpc_slice_refcount; } grpc_slice_refcount;
#define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1) #define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1)
@ -74,7 +87,7 @@ typedef struct grpc_slice_refcount {
If the slice does not have a refcount, it represents an inlined small piece If the slice does not have a refcount, it represents an inlined small piece
of data that is copied by value. */ of data that is copied by value. */
typedef struct grpc_slice { struct grpc_slice {
struct grpc_slice_refcount *refcount; struct grpc_slice_refcount *refcount;
union { union {
struct { struct {
@ -86,7 +99,7 @@ typedef struct grpc_slice {
uint8_t bytes[GRPC_SLICE_INLINED_SIZE]; uint8_t bytes[GRPC_SLICE_INLINED_SIZE];
} inlined; } inlined;
} data; } data;
} grpc_slice; };
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 #define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8

@ -76,6 +76,12 @@ GPRAPI grpc_slice grpc_slice_new_with_len(void *p, size_t len,
Aborts if malloc() fails. */ Aborts if malloc() fails. */
GPRAPI grpc_slice grpc_slice_malloc(size_t length); GPRAPI grpc_slice grpc_slice_malloc(size_t length);
/* Intern a slice:
The return value for two invocations of this function with the same sequence
of bytes is a slice which points to the same memory. */
GPRAPI grpc_slice grpc_slice_intern(grpc_slice slice);
/* Create a slice by copying a string. /* Create a slice by copying a string.
Does not preserve null terminators. Does not preserve null terminators.
Equivalent to: Equivalent to:
@ -93,6 +99,9 @@ GPRAPI grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t len);
/* Create a slice pointing to constant memory */ /* Create a slice pointing to constant memory */
GPRAPI grpc_slice grpc_slice_from_static_string(const char *source); GPRAPI grpc_slice grpc_slice_from_static_string(const char *source);
/* Create a slice pointing to constant memory */
GPRAPI grpc_slice grpc_slice_from_static_buffer(const void *source, size_t len);
/* Return a result slice derived from s, which shares a ref count with s, where /* Return a result slice derived from s, which shares a ref count with s, where
result.data==s.data+begin, and result.length==end-begin. result.data==s.data+begin, and result.length==end-begin.
The ref count of s is increased by one. The ref count of s is increased by one.
@ -113,18 +122,45 @@ GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split);
Requires s intialized, split <= s.length */ Requires s intialized, split <= s.length */
GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split); GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split);
GPRAPI grpc_slice gpr_empty_slice(void); GPRAPI grpc_slice grpc_empty_slice(void);
GPRAPI uint32_t grpc_slice_default_hash_impl(grpc_slice s);
GPRAPI int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b);
GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b);
/* Returns <0 if a < b, ==0 if a == b, >0 if a > b /* Returns <0 if a < b, ==0 if a == b, >0 if a > b
The order is arbitrary, and is not guaranteed to be stable across different The order is arbitrary, and is not guaranteed to be stable across different
versions of the API. */ versions of the API. */
GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b); GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b);
GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b); GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b);
GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen);
/* return non-zero if the first blen bytes of a are equal to b */
GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen);
/* return the index of the last instance of \a c in \a s, or -1 if not found */
GPRAPI int grpc_slice_rchr(grpc_slice s, char c);
GPRAPI int grpc_slice_chr(grpc_slice s, char c);
/* return the index of the first occurance of \a needle in \a haystack, or -1 if
* it's not found */
GPRAPI int grpc_slice_slice(grpc_slice haystack, grpc_slice needle);
GPRAPI uint32_t grpc_slice_hash(grpc_slice s);
/* Do two slices point at the same memory, with the same length /* Do two slices point at the same memory, with the same length
If a or b is inlined, actually compares data */ If a or b is inlined, actually compares data */
GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b); GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b);
/* Return a slice pointing to newly allocated memory that has the same contents
* as \a s */
GPRAPI grpc_slice grpc_slice_dup(grpc_slice a);
/* Return a copy of slice as a C string. Offers no protection against embedded
NULL's. Returned string must be freed with gpr_free. */
GPRAPI char *grpc_slice_to_c_string(grpc_slice s);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -200,6 +200,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/error.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/error.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/error_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_linux.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" />
@ -252,6 +253,7 @@
<file baseinstalldir="/" name="src/core/lib/json/json_reader.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/json/json_reader.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/json/json_writer.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/json/json_writer.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_internal.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/slice/slice_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/api_trace.h" role="src" />
@ -265,14 +267,17 @@
<file baseinstalldir="/" name="src/core/lib/surface/init.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/init.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/lame_client.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/lame_client.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/server.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/server.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/byte_stream.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/error_utils.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/http2_errors.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/service_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/status_conversion.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport_impl.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport_impl.h" role="src" />
@ -289,11 +294,9 @@
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_encoder.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_encoder.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_table.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/hpack_table.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/http2_errors.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/status_conversion.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/alpn/alpn.h" role="src" />
@ -448,6 +451,8 @@
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/slice/slice.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_intern.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/slice/slice_string_helpers.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/alarm.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/alarm.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/api_trace.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/api_trace.c" role="src" />
@ -469,12 +474,13 @@
<file baseinstalldir="/" name="src/core/lib/surface/version.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/version.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/byte_stream.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/byte_stream.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/error_utils.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/pid_controller.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/service_config.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/status_conversion.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport_op_string.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport_op_string.c" role="src" />
@ -495,7 +501,6 @@
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/incoming_metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/parsing.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/parsing.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/status_conversion.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_lists.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_lists.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/stream_map.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/varint.c" role="src" />

@ -134,29 +134,15 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
out->Outdent(); out->Outdent();
out->Print("}\n\n"); out->Print("}\n\n");
} }
void PrintServices(const FileDescriptor *file, Printer *out) {
map<grpc::string, grpc::string> vars;
vars["package"] = MessageIdentifierName(file->package());
out->Print(vars, "namespace $package$ {\n\n");
out->Indent();
for (int i = 0; i < file->service_count(); i++) {
PrintService(file->service(i), out);
}
out->Outdent();
out->Print("}\n");
}
} }
grpc::string GenerateFile(const FileDescriptor *file) { grpc::string GenerateFile(const FileDescriptor *file,
const ServiceDescriptor *service) {
grpc::string output; grpc::string output;
{ {
StringOutputStream output_stream(&output); StringOutputStream output_stream(&output);
Printer out(&output_stream, '$'); Printer out(&output_stream, '$');
if (file->service_count() == 0) {
return output;
}
out.Print("<?php\n"); out.Print("<?php\n");
out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n"); out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");
@ -166,7 +152,15 @@ grpc::string GenerateFile(const FileDescriptor *file) {
out.Print(leading_comments.c_str()); out.Print(leading_comments.c_str());
} }
PrintServices(file, &out); map<grpc::string, grpc::string> vars;
vars["package"] = MessageIdentifierName(file->package());
out.Print(vars, "namespace $package$ {\n\n");
out.Indent();
PrintService(service, &out);
out.Outdent();
out.Print("}\n");
} }
return output; return output;
} }

@ -38,7 +38,8 @@
namespace grpc_php_generator { namespace grpc_php_generator {
grpc::string GenerateFile(const grpc::protobuf::FileDescriptor *file); grpc::string GenerateFile(const grpc::protobuf::FileDescriptor *file,
const grpc::protobuf::ServiceDescriptor *service);
} // namespace grpc_php_generator } // namespace grpc_php_generator

@ -41,14 +41,23 @@
namespace grpc_php_generator { namespace grpc_php_generator {
inline grpc::string GetPHPServiceFilename(const grpc::string& filename) { inline grpc::string GetPHPServiceFilename(
return grpc_generator::StripProto(filename) + "_grpc_pb.php"; const grpc::protobuf::FileDescriptor *file,
const grpc::protobuf::ServiceDescriptor *service) {
std::vector<grpc::string> tokens =
grpc_generator::tokenize(file->package(), ".");
std::ostringstream oss;
for (unsigned int i = 0; i < tokens.size(); i++) {
oss << (i == 0 ? "" : "/")
<< grpc_generator::CapitalizeFirstLetter(tokens[i]);
}
return oss.str() + "/" + service->name() + "Client.php";
} }
// Get leading or trailing comments in a string. Comment lines start with "// ". // Get leading or trailing comments in a string. Comment lines start with "// ".
// Leading detached comments are put in in front of leading comments. // Leading detached comments are put in in front of leading comments.
template <typename DescriptorType> template <typename DescriptorType>
inline grpc::string GetPHPComments(const DescriptorType* desc, inline grpc::string GetPHPComments(const DescriptorType *desc,
grpc::string prefix) { grpc::string prefix) {
return grpc_generator::GetPrefixedComments(desc, true, prefix); return grpc_generator::GetPrefixedComments(desc, true, prefix);
} }

@ -51,18 +51,22 @@ class PHPGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
const grpc::string &parameter, const grpc::string &parameter,
grpc::protobuf::compiler::GeneratorContext *context, grpc::protobuf::compiler::GeneratorContext *context,
grpc::string *error) const { grpc::string *error) const {
grpc::string code = GenerateFile(file); if (file->service_count() == 0) {
if (code.size() == 0) {
return true; return true;
} }
// Get output file name for (int i = 0; i < file->service_count(); i++) {
grpc::string file_name = GetPHPServiceFilename(file->name()); grpc::string code = GenerateFile(file, file->service(i));
// Get output file name
grpc::string file_name = GetPHPServiceFilename(file, file->service(i));
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
context->Open(file_name));
grpc::protobuf::io::CodedOutputStream coded_out(output.get());
coded_out.WriteRaw(code.data(), code.size());
}
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
context->Open(file_name));
grpc::protobuf::io::CodedOutputStream coded_out(output.get());
coded_out.WriteRaw(code.data(), code.size());
return true; return true;
} }
}; };

@ -292,4 +292,4 @@ extern const pb_field_t google_census_Metric_fields[5];
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif #endif /* GRPC_CORE_EXT_CENSUS_GEN_CENSUS_PB_H */

@ -96,4 +96,4 @@ extern const pb_field_t google_trace_TraceContext_fields[4];
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif #endif /* GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H */

@ -67,9 +67,7 @@ static void extract_and_annotate_method_tag(grpc_metadata_batch *md,
channel_data *chand) { channel_data *chand) {
grpc_linked_mdelem *m; grpc_linked_mdelem *m;
for (m = md->list.head; m != NULL; m = m->next) { for (m = md->list.head; m != NULL; m = m->next) {
if (m->md->key == GRPC_MDSTR_PATH) { if (grpc_slice_eq(GRPC_MDKEY(m->md), GRPC_MDSTR_PATH)) {
gpr_log(GPR_DEBUG, "%s",
(const char *)GRPC_SLICE_START_PTR(m->md->value->slice));
/* Add method tag here */ /* Add method tag here */
} }
} }

@ -54,6 +54,7 @@
#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
@ -89,7 +90,7 @@ static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
gpr_free(p); gpr_free(p);
} }
static const grpc_mdstr_hash_table_vtable method_parameters_vtable = { static const grpc_slice_hash_table_vtable method_parameters_vtable = {
method_parameters_free, method_parameters_copy}; method_parameters_free, method_parameters_copy};
static void *method_parameters_create_from_json(const grpc_json *json) { static void *method_parameters_create_from_json(const grpc_json *json) {
@ -171,7 +172,7 @@ typedef struct client_channel_channel_data {
/** service config in JSON form */ /** service config in JSON form */
char *service_config_json; char *service_config_json;
/** maps method names to method_parameters structs */ /** maps method names to method_parameters structs */
grpc_mdstr_hash_table *method_params_table; grpc_slice_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */ /** incoming resolver result - set by resolver.next() */
grpc_channel_args *resolver_result; grpc_channel_args *resolver_result;
/** a list of closures that are all waiting for config to come in */ /** a list of closures that are all waiting for config to come in */
@ -273,7 +274,7 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
char *lb_policy_name = NULL; char *lb_policy_name = NULL;
grpc_lb_policy *lb_policy = NULL; grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy; grpc_lb_policy *old_lb_policy;
grpc_mdstr_hash_table *method_params_table = NULL; grpc_slice_hash_table *method_params_table = NULL;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE; grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
bool exit_idle = false; bool exit_idle = false;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy"); grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
@ -379,7 +380,7 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
chand->service_config_json = service_config_json; chand->service_config_json = service_config_json;
} }
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table); grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
} }
chand->method_params_table = method_params_table; chand->method_params_table = method_params_table;
if (lb_policy != NULL) { if (lb_policy != NULL) {
@ -579,7 +580,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
gpr_free(chand->lb_policy_name); gpr_free(chand->lb_policy_name);
gpr_free(chand->service_config_json); gpr_free(chand->service_config_json);
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table); grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
} }
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker); grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
grpc_pollset_set_destroy(chand->interested_parties); grpc_pollset_set_destroy(chand->interested_parties);
@ -614,7 +615,7 @@ typedef struct client_channel_call_data {
// to avoid this without breaking the grpc_deadline_state abstraction. // to avoid this without breaking the grpc_deadline_state abstraction.
grpc_deadline_state deadline_state; grpc_deadline_state deadline_state;
grpc_mdstr *path; // Request path. grpc_slice path; // Request path.
gpr_timespec call_start_time; gpr_timespec call_start_time;
gpr_timespec deadline; gpr_timespec deadline;
wait_for_ready_value wait_for_ready_from_service_config; wait_for_ready_value wait_for_ready_from_service_config;
@ -1018,10 +1019,10 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
// Get the method config table from channel data. // Get the method config table from channel data.
gpr_mu_lock(&chand->mu); gpr_mu_lock(&chand->mu);
grpc_mdstr_hash_table *method_params_table = NULL; grpc_slice_hash_table *method_params_table = NULL;
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
method_params_table = method_params_table =
grpc_mdstr_hash_table_ref(chand->method_params_table); grpc_slice_hash_table_ref(chand->method_params_table);
} }
gpr_mu_unlock(&chand->mu); gpr_mu_unlock(&chand->mu);
// If the method config table was present, use it. // If the method config table was present, use it.
@ -1050,7 +1051,7 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_unlock(&calld->mu); gpr_mu_unlock(&calld->mu);
} }
} }
grpc_mdstr_hash_table_unref(exec_ctx, method_params_table); grpc_slice_hash_table_unref(exec_ctx, method_params_table);
} }
} }
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config"); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
@ -1064,7 +1065,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
// Initialize data members. // Initialize data members.
grpc_deadline_state_init(exec_ctx, elem, args->call_stack); grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
calld->path = GRPC_MDSTR_REF(args->path); calld->path = grpc_slice_ref_internal(args->path);
calld->call_start_time = args->start_time; calld->call_start_time = args->start_time;
calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC); calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET; calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
@ -1088,8 +1089,8 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
// We already have a resolver result, so check for service config. // We already have a resolver result, so check for service config.
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table *method_params_table = grpc_slice_hash_table *method_params_table =
grpc_mdstr_hash_table_ref(chand->method_params_table); grpc_slice_hash_table_ref(chand->method_params_table);
gpr_mu_unlock(&chand->mu); gpr_mu_unlock(&chand->mu);
method_parameters *method_params = grpc_method_config_table_get( method_parameters *method_params = grpc_method_config_table_get(
exec_ctx, method_params_table, args->path); exec_ctx, method_params_table, args->path);
@ -1105,7 +1106,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
method_params->wait_for_ready; method_params->wait_for_ready;
} }
} }
grpc_mdstr_hash_table_unref(exec_ctx, method_params_table); grpc_slice_hash_table_unref(exec_ctx, method_params_table);
} else { } else {
gpr_mu_unlock(&chand->mu); gpr_mu_unlock(&chand->mu);
} }
@ -1134,7 +1135,7 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
void *and_free_memory) { void *and_free_memory) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_deadline_state_destroy(exec_ctx, elem); grpc_deadline_state_destroy(exec_ctx, elem);
GRPC_MDSTR_UNREF(exec_ctx, calld->path); grpc_slice_unref_internal(exec_ctx, calld->path);
GRPC_ERROR_UNREF(calld->cancel_error); GRPC_ERROR_UNREF(calld->cancel_error);
grpc_subchannel_call *call = GET_CALL(calld); grpc_subchannel_call *call = GET_CALL(calld);
if (call != NULL && call != CANCELLED_CALL) { if (call != NULL && call != CANCELLED_CALL) {

@ -49,7 +49,7 @@ void grpc_connector_connect(grpc_exec_ctx* exec_ctx, grpc_connector* connector,
connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify); connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify);
} }
void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx, void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx, grpc_connector* connector,
grpc_connector* connector) { grpc_error* why) {
connector->vtable->shutdown(exec_ctx, connector); connector->vtable->shutdown(exec_ctx, connector, why);
} }

@ -68,7 +68,8 @@ struct grpc_connector_vtable {
void (*ref)(grpc_connector *connector); void (*ref)(grpc_connector *connector);
void (*unref)(grpc_exec_ctx *exec_ctx, grpc_connector *connector); void (*unref)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
/** Implementation of grpc_connector_shutdown */ /** Implementation of grpc_connector_shutdown */
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector); void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
grpc_error *why);
/** Implementation of grpc_connector_connect */ /** Implementation of grpc_connector_connect */
void (*connect)(grpc_exec_ctx *exec_ctx, grpc_connector *connector, void (*connect)(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
const grpc_connect_in_args *in_args, const grpc_connect_in_args *in_args,
@ -83,7 +84,7 @@ void grpc_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
grpc_connect_out_args *out_args, grpc_connect_out_args *out_args,
grpc_closure *notify); grpc_closure *notify);
/** Cancel any pending connection */ /** Cancel any pending connection */
void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx, void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
grpc_connector *connector); grpc_error *why);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CONNECTOR_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CONNECTOR_H */

@ -123,7 +123,8 @@ static void handshake_failed_locked(grpc_exec_ctx* exec_ctx,
// before destroying them, even if we know that there are no // before destroying them, even if we know that there are no
// pending read/write callbacks. This should be fixed, at which // pending read/write callbacks. This should be fixed, at which
// point this can be removed. // point this can be removed.
grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint); grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint,
GRPC_ERROR_REF(error));
// Not shutting down, so the handshake failed. Clean up before // Not shutting down, so the handshake failed. Clean up before
// invoking the callback. // invoking the callback.
cleanup_args_for_failure_locked(exec_ctx, handshaker); cleanup_args_for_failure_locked(exec_ctx, handshaker);
@ -251,15 +252,18 @@ static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx,
} }
static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
grpc_handshaker* handshaker_in) { grpc_handshaker* handshaker_in,
grpc_error* why) {
http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in;
gpr_mu_lock(&handshaker->mu); gpr_mu_lock(&handshaker->mu);
if (!handshaker->shutdown) { if (!handshaker->shutdown) {
handshaker->shutdown = true; handshaker->shutdown = true;
grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint); grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint,
GRPC_ERROR_REF(why));
cleanup_args_for_failure_locked(exec_ctx, handshaker); cleanup_args_for_failure_locked(exec_ctx, handshaker);
} }
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
GRPC_ERROR_UNREF(why);
} }
static void http_connect_handshaker_do_handshake( static void http_connect_handshaker_do_handshake(

@ -273,7 +273,8 @@ static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->disconnected); GPR_ASSERT(!c->disconnected);
c->disconnected = true; c->disconnected = true;
grpc_connector_shutdown(exec_ctx, c->connector); grpc_connector_shutdown(exec_ctx, c->connector,
GRPC_ERROR_CREATE("Subchannel disconnected"));
con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
if (con != NULL) { if (con != NULL) {
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection"); GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection");
@ -637,9 +638,8 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_error *error = grpc_channel_stack_builder_finish( grpc_error *error = grpc_channel_stack_builder_finish(
exec_ctx, builder, 0, 1, connection_destroy, NULL, (void **)&con); exec_ctx, builder, 0, 1, connection_destroy, NULL, (void **)&con);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
const char *msg = grpc_error_string(error); gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", msg); grpc_error_string(error));
grpc_error_free_string(msg);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
abort(); /* TODO(ctiller): what to do here? */ abort(); /* TODO(ctiller): what to do here? */
} }
@ -704,7 +704,6 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
const char *errmsg = grpc_error_string(error); const char *errmsg = grpc_error_string(error);
gpr_log(GPR_INFO, "Connect failed: %s", errmsg); gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
grpc_error_free_string(errmsg);
maybe_start_connecting_locked(exec_ctx, c); maybe_start_connecting_locked(exec_ctx, c);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
@ -763,7 +762,7 @@ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
grpc_error *grpc_connected_subchannel_create_call( grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec start_time, grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time,
gpr_timespec deadline, grpc_subchannel_call **call) { gpr_timespec deadline, grpc_subchannel_call **call) {
grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con); grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
*call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
@ -775,7 +774,7 @@ grpc_error *grpc_connected_subchannel_create_call(
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
const char *error_string = grpc_error_string(error); const char *error_string = grpc_error_string(error);
gpr_log(GPR_ERROR, "error: %s", error_string); gpr_log(GPR_ERROR, "error: %s", error_string);
grpc_error_free_string(error_string);
gpr_free(*call); gpr_free(*call);
return error; return error;
} }

@ -114,7 +114,7 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
/** construct a subchannel call */ /** construct a subchannel call */
grpc_error *grpc_connected_subchannel_create_call( grpc_error *grpc_connected_subchannel_create_call(
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel, grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
grpc_polling_entity *pollent, grpc_mdstr *path, gpr_timespec start_time, grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time,
gpr_timespec deadline, grpc_subchannel_call **subchannel_call); gpr_timespec deadline, grpc_subchannel_call **subchannel_call);
/** process a transport level op */ /** process a transport level op */

@ -135,13 +135,13 @@ int grpc_lb_glb_trace = 0;
/* add lb_token of selected subchannel (address) to the call's initial /* add lb_token of selected subchannel (address) to the call's initial
* metadata */ * metadata */
static void initial_metadata_add_lb_token( static grpc_error *initial_metadata_add_lb_token(
grpc_metadata_batch *initial_metadata, grpc_exec_ctx *exec_ctx, grpc_metadata_batch *initial_metadata,
grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem *lb_token) { grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem lb_token) {
GPR_ASSERT(lb_token_mdelem_storage != NULL); GPR_ASSERT(lb_token_mdelem_storage != NULL);
GPR_ASSERT(lb_token != NULL); GPR_ASSERT(!GRPC_MDISNULL(lb_token));
grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage, return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata,
lb_token); lb_token_mdelem_storage, lb_token);
} }
typedef struct wrapped_rr_closure_arg { typedef struct wrapped_rr_closure_arg {
@ -161,7 +161,7 @@ typedef struct wrapped_rr_closure_arg {
grpc_connected_subchannel **target; grpc_connected_subchannel **target;
/* the LB token associated with the pick */ /* the LB token associated with the pick */
grpc_mdelem *lb_token; grpc_mdelem lb_token;
/* storage for the lb token initial metadata mdelem */ /* storage for the lb token initial metadata mdelem */
grpc_linked_mdelem *lb_token_mdelem_storage; grpc_linked_mdelem *lb_token_mdelem_storage;
@ -188,8 +188,8 @@ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
* addresses failed to connect). There won't be any user_data/token * addresses failed to connect). There won't be any user_data/token
* available */ * available */
if (*wc_arg->target != NULL) { if (*wc_arg->target != NULL) {
if (wc_arg->lb_token != NULL) { if (!GRPC_MDISNULL(wc_arg->lb_token)) {
initial_metadata_add_lb_token(wc_arg->initial_metadata, initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata,
wc_arg->lb_token_mdelem_storage, wc_arg->lb_token_mdelem_storage,
GRPC_MDELEM_REF(wc_arg->lb_token)); GRPC_MDELEM_REF(wc_arg->lb_token));
} else { } else {
@ -345,8 +345,7 @@ typedef struct glb_lb_policy {
/* call status code and details, set in lb_on_server_status_received() */ /* call status code and details, set in lb_on_server_status_received() */
grpc_status_code lb_call_status; grpc_status_code lb_call_status;
char *lb_call_status_details; grpc_slice lb_call_status_details;
size_t lb_call_status_details_capacity;
/** LB call retry backoff state */ /** LB call retry backoff state */
gpr_backoff lb_call_backoff_state; gpr_backoff lb_call_backoff_state;
@ -388,10 +387,14 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
/* vtable for LB tokens in grpc_lb_addresses. */ /* vtable for LB tokens in grpc_lb_addresses. */
static void *lb_token_copy(void *token) { static void *lb_token_copy(void *token) {
return token == NULL ? NULL : GRPC_MDELEM_REF(token); return token == NULL
? NULL
: (void *)GRPC_MDELEM_REF((grpc_mdelem){(uintptr_t)token}).payload;
} }
static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) { static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) {
if (token != NULL) GRPC_MDELEM_UNREF(exec_ctx, token); if (token != NULL) {
GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){(uintptr_t)token});
}
} }
static int lb_token_cmp(void *token1, void *token2) { static int lb_token_cmp(void *token1, void *token2) {
if (token1 > token2) return 1; if (token1 > token2) return 1;
@ -459,10 +462,11 @@ static grpc_lb_addresses *process_serverlist_locked(
GPR_ARRAY_SIZE(server->load_balance_token); GPR_ARRAY_SIZE(server->load_balance_token);
const size_t lb_token_length = const size_t lb_token_length =
strnlen(server->load_balance_token, lb_token_max_length); strnlen(server->load_balance_token, lb_token_max_length);
grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer( grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
(uint8_t *)server->load_balance_token, lb_token_length); server->load_balance_token, lb_token_length);
user_data = grpc_mdelem_from_metadata_strings( user_data = (void *)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr); lb_token_mdstr)
.payload;
} else { } else {
char *uri = grpc_sockaddr_to_uri(&addr); char *uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
@ -470,7 +474,7 @@ static grpc_lb_addresses *process_serverlist_locked(
"be used instead", "be used instead",
uri); uri);
gpr_free(uri); gpr_free(uri);
user_data = GRPC_MDELEM_LB_TOKEN_EMPTY; user_data = (void *)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
} }
grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len, grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
@ -564,7 +568,7 @@ static bool pick_from_internal_rr_locked(
GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync"); GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
/* add the load reporting initial metadata */ /* add the load reporting initial metadata */
initial_metadata_add_lb_token(pick_args->initial_metadata, initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
pick_args->lb_token_mdelem_storage, pick_args->lb_token_mdelem_storage,
GRPC_MDELEM_REF(wc_arg->lb_token)); GRPC_MDELEM_REF(wc_arg->lb_token));
@ -1103,11 +1107,12 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
/* Note the following LB call progresses every time there's activity in \a /* Note the following LB call progresses every time there's activity in \a
* glb_policy->base.interested_parties, which is comprised of the polling * glb_policy->base.interested_parties, which is comprised of the polling
* entities from \a client_channel. */ * entities from \a client_channel. */
grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name);
glb_policy->lb_call = grpc_channel_create_pollset_set_call( glb_policy->lb_call = grpc_channel_create_pollset_set_call(
exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS, exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
glb_policy->base.interested_parties, glb_policy->base.interested_parties,
"/grpc.lb.v1.LoadBalancer/BalanceLoad", glb_policy->server_name, GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
glb_policy->deadline, NULL); &host, glb_policy->deadline, NULL);
grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv); grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv); grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
@ -1120,9 +1125,6 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
grpc_slice_unref_internal(exec_ctx, request_payload_slice); grpc_slice_unref_internal(exec_ctx, request_payload_slice);
grpc_grpclb_request_destroy(request); grpc_grpclb_request_destroy(request);
glb_policy->lb_call_status_details = NULL;
glb_policy->lb_call_status_details_capacity = 0;
grpc_closure_init(&glb_policy->lb_on_server_status_received, grpc_closure_init(&glb_policy->lb_on_server_status_received,
lb_on_server_status_received, glb_policy, lb_on_server_status_received, glb_policy,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
@ -1138,7 +1140,8 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000); GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
} }
static void lb_call_destroy_locked(glb_lb_policy *glb_policy) { static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx,
glb_lb_policy *glb_policy) {
GPR_ASSERT(glb_policy->lb_call != NULL); GPR_ASSERT(glb_policy->lb_call != NULL);
grpc_call_destroy(glb_policy->lb_call); grpc_call_destroy(glb_policy->lb_call);
glb_policy->lb_call = NULL; glb_policy->lb_call = NULL;
@ -1147,7 +1150,7 @@ static void lb_call_destroy_locked(glb_lb_policy *glb_policy) {
grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv); grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
grpc_byte_buffer_destroy(glb_policy->lb_request_payload); grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
gpr_free(glb_policy->lb_call_status_details); grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details);
} }
/* /*
@ -1178,14 +1181,15 @@ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
op++; op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA; op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &glb_policy->lb_initial_metadata_recv; op->data.recv_initial_metadata.recv_initial_metadata =
&glb_policy->lb_initial_metadata_recv;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op++; op++;
GPR_ASSERT(glb_policy->lb_request_payload != NULL); GPR_ASSERT(glb_policy->lb_request_payload != NULL);
op->op = GRPC_OP_SEND_MESSAGE; op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = glb_policy->lb_request_payload; op->data.send_message.send_message = glb_policy->lb_request_payload;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op++; op++;
@ -1196,8 +1200,6 @@ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
op->data.recv_status_on_client.status = &glb_policy->lb_call_status; op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
op->data.recv_status_on_client.status_details = op->data.recv_status_on_client.status_details =
&glb_policy->lb_call_status_details; &glb_policy->lb_call_status_details;
op->data.recv_status_on_client.status_details_capacity =
&glb_policy->lb_call_status_details_capacity;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op++; op++;
@ -1211,7 +1213,7 @@ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
op = ops; op = ops;
op->op = GRPC_OP_RECV_MESSAGE; op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &glb_policy->lb_response_payload; op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op++; op++;
@ -1293,7 +1295,7 @@ static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
if (!glb_policy->shutting_down) { if (!glb_policy->shutting_down) {
/* keep listening for serverlist updates */ /* keep listening for serverlist updates */
op->op = GRPC_OP_RECV_MESSAGE; op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &glb_policy->lb_response_payload; op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op++; op++;
@ -1340,15 +1342,18 @@ static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
GPR_ASSERT(glb_policy->lb_call != NULL); GPR_ASSERT(glb_policy->lb_call != NULL);
if (grpc_lb_glb_trace) { if (grpc_lb_glb_trace) {
char *status_details =
grpc_slice_to_c_string(glb_policy->lb_call_status_details);
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"Status from LB server received. Status = %d, Details = '%s', " "Status from LB server received. Status = %d, Details = '%s', "
"(call: %p)", "(call: %p)",
glb_policy->lb_call_status, glb_policy->lb_call_status_details, glb_policy->lb_call_status, status_details,
(void *)glb_policy->lb_call); (void *)glb_policy->lb_call);
gpr_free(status_details);
} }
/* We need to performe cleanups no matter what. */ /* We need to perform cleanups no matter what. */
lb_call_destroy_locked(glb_policy); lb_call_destroy_locked(exec_ctx, glb_policy);
if (!glb_policy->shutting_down) { if (!glb_policy->shutting_down) {
/* if we aren't shutting down, restart the LB client call after some time */ /* if we aren't shutting down, restart the LB client call after some time */

@ -41,13 +41,17 @@
#include "src/core/ext/load_reporting/load_reporting_filter.h" #include "src/core/ext/load_reporting/load_reporting_filter.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
typedef struct call_data { typedef struct call_data {
intptr_t id; /**< an id unique to the call */ intptr_t id; /**< an id unique to the call */
char *trailing_md_string; bool have_trailing_md_string;
char *initial_md_string; grpc_slice trailing_md_string;
const char *service_method; bool have_initial_md_string;
grpc_slice initial_md_string;
bool have_service_method;
grpc_slice service_method;
/* stores the recv_initial_metadata op's ready closure, which we wrap with our /* stores the recv_initial_metadata op's ready closure, which we wrap with our
* own (on_initial_md_ready) in order to capture the incoming initial metadata * own (on_initial_md_ready) in order to capture the incoming initial metadata
@ -63,42 +67,28 @@ typedef struct channel_data {
intptr_t id; /**< an id unique to the channel */ intptr_t id; /**< an id unique to the channel */
} channel_data; } channel_data;
typedef struct {
grpc_call_element *elem;
grpc_exec_ctx *exec_ctx;
} recv_md_filter_args;
static grpc_mdelem *recv_md_filter(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_mdelem *md) {
recv_md_filter_args *a = user_data;
grpc_call_element *elem = a->elem;
call_data *calld = elem->call_data;
if (md->key == GRPC_MDSTR_PATH) {
calld->service_method = grpc_mdstr_as_c_string(md->value);
} else if (md->key == GRPC_MDSTR_LB_TOKEN) {
calld->initial_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value));
return NULL;
}
return md;
}
static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data, static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_error *err) { grpc_error *err) {
grpc_call_element *elem = user_data; grpc_call_element *elem = user_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
if (err == GRPC_ERROR_NONE) { if (err == GRPC_ERROR_NONE) {
recv_md_filter_args a; if (calld->recv_initial_metadata->idx.named.path != NULL) {
a.elem = elem; calld->service_method = grpc_slice_ref_internal(
a.exec_ctx = exec_ctx; GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md));
grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata, calld->have_service_method = true;
recv_md_filter, &a); } else {
if (calld->service_method == NULL) {
err = err =
grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header")); grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header"));
} }
if (calld->recv_initial_metadata->idx.named.lb_token != NULL) {
calld->initial_md_string = grpc_slice_ref_internal(
GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md));
calld->have_initial_md_string = true;
grpc_metadata_batch_remove(
exec_ctx, calld->recv_initial_metadata,
calld->recv_initial_metadata->idx.named.lb_token);
}
} else { } else {
GRPC_ERROR_REF(err); GRPC_ERROR_REF(err);
} }
@ -149,8 +139,15 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
calld->service_method}; calld->service_method};
*/ */
gpr_free(calld->initial_md_string); if (calld->have_initial_md_string) {
gpr_free(calld->trailing_md_string); grpc_slice_unref_internal(exec_ctx, calld->initial_md_string);
}
if (calld->have_trailing_md_string) {
grpc_slice_unref_internal(exec_ctx, calld->trailing_md_string);
}
if (calld->have_service_method) {
grpc_slice_unref_internal(exec_ctx, calld->service_method);
}
} }
/* Constructor for channel_data */ /* Constructor for channel_data */
@ -193,19 +190,6 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
*/ */
} }
static grpc_mdelem *lr_trailing_md_filter(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
if (md->key == GRPC_MDSTR_LB_COST_BIN) {
calld->trailing_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value));
return NULL;
}
return md;
}
static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx, static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_transport_stream_op *op) { grpc_transport_stream_op *op) {
@ -218,8 +202,14 @@ static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready; calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready;
op->recv_initial_metadata_ready = &calld->on_initial_md_ready; op->recv_initial_metadata_ready = &calld->on_initial_md_ready;
} else if (op->send_trailing_metadata) { } else if (op->send_trailing_metadata) {
grpc_metadata_batch_filter(exec_ctx, op->send_trailing_metadata, if (op->send_trailing_metadata->idx.named.lb_cost_bin != NULL) {
lr_trailing_md_filter, elem); calld->trailing_md_string = grpc_slice_ref_internal(
GRPC_MDVALUE(op->send_trailing_metadata->idx.named.lb_cost_bin->md));
calld->have_trailing_md_string = true;
grpc_metadata_batch_remove(
exec_ctx, op->send_trailing_metadata,
op->send_trailing_metadata->idx.named.lb_cost_bin);
}
} }
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(exec_ctx, elem, op);

@ -188,9 +188,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now); gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
gpr_timespec timeout = gpr_time_sub(next_try, now); gpr_timespec timeout = gpr_time_sub(next_try, now);
const char *msg = grpc_error_string(error); gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", msg); grpc_error_string(error));
grpc_error_free_string(msg);
GPR_ASSERT(!r->have_retry_timer); GPR_ASSERT(!r->have_retry_timer);
r->have_retry_timer = true; r->have_retry_timer = true;
GRPC_RESOLVER_REF(&r->base, "retry-timer"); GRPC_RESOLVER_REF(&r->base, "retry-timer");

@ -182,7 +182,7 @@ static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx,
bool errors_found = false; bool errors_found = false;
for (size_t i = 0; i < addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
grpc_uri ith_uri = *args->uri; grpc_uri ith_uri = *args->uri;
char *part_str = grpc_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII); char *part_str = grpc_slice_to_c_string(path_parts.slices[i]);
ith_uri.path = part_str; ith_uri.path = part_str;
if (!parse(&ith_uri, &addresses->addresses[i].address)) { if (!parse(&ith_uri, &addresses->addresses[i].address)) {
errors_found = true; /* GPR_TRUE */ errors_found = true; /* GPR_TRUE */

@ -92,19 +92,21 @@ static void chttp2_connector_unref(grpc_exec_ctx *exec_ctx,
} }
static void chttp2_connector_shutdown(grpc_exec_ctx *exec_ctx, static void chttp2_connector_shutdown(grpc_exec_ctx *exec_ctx,
grpc_connector *con) { grpc_connector *con, grpc_error *why) {
chttp2_connector *c = (chttp2_connector *)con; chttp2_connector *c = (chttp2_connector *)con;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
c->shutdown = true; c->shutdown = true;
if (c->handshake_mgr != NULL) { if (c->handshake_mgr != NULL) {
grpc_handshake_manager_shutdown(exec_ctx, c->handshake_mgr); grpc_handshake_manager_shutdown(exec_ctx, c->handshake_mgr,
GRPC_ERROR_REF(why));
} }
// If handshaking is not yet in progress, shutdown the endpoint. // If handshaking is not yet in progress, shutdown the endpoint.
// Otherwise, the handshaker will do this for us. // Otherwise, the handshaker will do this for us.
if (!c->connecting && c->endpoint != NULL) { if (!c->connecting && c->endpoint != NULL) {
grpc_endpoint_shutdown(exec_ctx, c->endpoint); grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(why));
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
GRPC_ERROR_UNREF(why);
} }
static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
@ -121,7 +123,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
// before destroying them, even if we know that there are no // before destroying them, even if we know that there are no
// pending read/write callbacks. This should be fixed, at which // pending read/write callbacks. This should be fixed, at which
// point this can be removed. // point this can be removed.
grpc_endpoint_shutdown(exec_ctx, args->endpoint); grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_REF(error));
grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_endpoint_destroy(exec_ctx, args->endpoint);
grpc_channel_args_destroy(exec_ctx, args->args); grpc_channel_args_destroy(exec_ctx, args->args);
grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
@ -195,7 +197,9 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_closure *notify = c->notify; grpc_closure *notify = c->notify;
c->notify = NULL; c->notify = NULL;
grpc_closure_sched(exec_ctx, notify, error); grpc_closure_sched(exec_ctx, notify, error);
if (c->endpoint != NULL) grpc_endpoint_shutdown(exec_ctx, c->endpoint); if (c->endpoint != NULL) {
grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(error));
}
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
chttp2_connector_unref(exec_ctx, arg); chttp2_connector_unref(exec_ctx, arg);
} else { } else {

@ -101,16 +101,19 @@ static void pending_handshake_manager_remove_locked(
} }
static void pending_handshake_manager_shutdown_locked(grpc_exec_ctx *exec_ctx, static void pending_handshake_manager_shutdown_locked(grpc_exec_ctx *exec_ctx,
server_state *state) { server_state *state,
grpc_error *why) {
pending_handshake_manager_node *prev_node = NULL; pending_handshake_manager_node *prev_node = NULL;
for (pending_handshake_manager_node *node = state->pending_handshake_mgrs; for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
node != NULL; node = node->next) { node != NULL; node = node->next) {
grpc_handshake_manager_shutdown(exec_ctx, node->handshake_mgr); grpc_handshake_manager_shutdown(exec_ctx, node->handshake_mgr,
GRPC_ERROR_REF(why));
gpr_free(prev_node); gpr_free(prev_node);
prev_node = node; prev_node = node;
} }
gpr_free(prev_node); gpr_free(prev_node);
state->pending_handshake_mgrs = NULL; state->pending_handshake_mgrs = NULL;
GRPC_ERROR_UNREF(why);
} }
static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
@ -121,7 +124,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) { if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) {
const char *error_str = grpc_error_string(error); const char *error_str = grpc_error_string(error);
gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
grpc_error_free_string(error_str);
if (error == GRPC_ERROR_NONE && args->endpoint != NULL) { if (error == GRPC_ERROR_NONE && args->endpoint != NULL) {
// We were shut down after handshaking completed successfully, so // We were shut down after handshaking completed successfully, so
// destroy the endpoint here. // destroy the endpoint here.
@ -129,7 +132,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
// before destroying them, even if we know that there are no // before destroying them, even if we know that there are no
// pending read/write callbacks. This should be fixed, at which // pending read/write callbacks. This should be fixed, at which
// point this can be removed. // point this can be removed.
grpc_endpoint_shutdown(exec_ctx, args->endpoint); grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE);
grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_endpoint_destroy(exec_ctx, args->endpoint);
grpc_channel_args_destroy(exec_ctx, args->args); grpc_channel_args_destroy(exec_ctx, args->args);
grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
@ -210,7 +213,8 @@ static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_lock(&state->mu); gpr_mu_lock(&state->mu);
grpc_closure *destroy_done = state->server_destroy_listener_done; grpc_closure *destroy_done = state->server_destroy_listener_done;
GPR_ASSERT(state->shutdown); GPR_ASSERT(state->shutdown);
pending_handshake_manager_shutdown_locked(exec_ctx, state); pending_handshake_manager_shutdown_locked(exec_ctx, state,
GRPC_ERROR_REF(error));
gpr_mu_unlock(&state->mu); gpr_mu_unlock(&state->mu);
// Flush queued work before destroying handshaker factory, since that // Flush queued work before destroying handshaker factory, since that
// may do a synchronous unref. // may do a synchronous unref.
@ -307,7 +311,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
const char *warning_message = grpc_error_string(err); const char *warning_message = grpc_error_string(err);
gpr_log(GPR_INFO, "WARNING: %s", warning_message); gpr_log(GPR_INFO, "WARNING: %s", warning_message);
grpc_error_free_string(warning_message);
/* we managed to bind some addresses: continue */ /* we managed to bind some addresses: continue */
} }
grpc_resolved_addresses_destroy(resolved); grpc_resolved_addresses_destroy(resolved);

@ -51,7 +51,7 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
if (err != GRPC_ERROR_NONE) { if (err != GRPC_ERROR_NONE) {
const char *msg = grpc_error_string(err); const char *msg = grpc_error_string(err);
gpr_log(GPR_ERROR, "%s", msg); gpr_log(GPR_ERROR, "%s", msg);
grpc_error_free_string(msg);
GRPC_ERROR_UNREF(err); GRPC_ERROR_UNREF(err);
} }
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);

@ -94,7 +94,7 @@ done:
if (err != GRPC_ERROR_NONE) { if (err != GRPC_ERROR_NONE) {
const char *msg = grpc_error_string(err); const char *msg = grpc_error_string(err);
gpr_log(GPR_ERROR, "%s", msg); gpr_log(GPR_ERROR, "%s", msg);
grpc_error_free_string(msg);
GRPC_ERROR_UNREF(err); GRPC_ERROR_UNREF(err);
} }
return port_num; return port_num;

@ -157,7 +157,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx,
"grpc_chttp2_base64_decode has a length of %d, which is not a " "grpc_chttp2_base64_decode has a length of %d, which is not a "
"multiple of 4.\n", "multiple of 4.\n",
(int)input_length); (int)input_length);
return gpr_empty_slice(); return grpc_empty_slice();
} }
if (input_length > 0) { if (input_length > 0) {
@ -178,11 +178,11 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx,
ctx.contains_tail = false; ctx.contains_tail = false;
if (!grpc_base64_decode_partial(&ctx)) { if (!grpc_base64_decode_partial(&ctx)) {
char *s = grpc_dump_slice(input, GPR_DUMP_ASCII); char *s = grpc_slice_to_c_string(input);
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s); gpr_free(s);
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(exec_ctx, output);
return gpr_empty_slice(); return grpc_empty_slice();
} }
GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input)); GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input));
@ -204,7 +204,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
"has a tail of 1 byte.\n", "has a tail of 1 byte.\n",
(int)input_length); (int)input_length);
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(exec_ctx, output);
return gpr_empty_slice(); return grpc_empty_slice();
} }
if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) { if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) {
@ -214,7 +214,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
(int)output_length, (int)output_length,
(int)(input_length / 4 * 3 + tail_xtra[input_length % 4])); (int)(input_length / 4 * 3 + tail_xtra[input_length % 4]));
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(exec_ctx, output);
return gpr_empty_slice(); return grpc_empty_slice();
} }
ctx.input_cur = GRPC_SLICE_START_PTR(input); ctx.input_cur = GRPC_SLICE_START_PTR(input);
@ -224,11 +224,11 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
ctx.contains_tail = true; ctx.contains_tail = true;
if (!grpc_base64_decode_partial(&ctx)) { if (!grpc_base64_decode_partial(&ctx)) {
char *s = grpc_dump_slice(input, GPR_DUMP_ASCII); char *s = grpc_slice_to_c_string(input);
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s); gpr_free(s);
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(exec_ctx, output);
return gpr_empty_slice(); return grpc_empty_slice();
} }
GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input)); GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input));

@ -177,8 +177,7 @@ static void enc_add1(huff_out *out, uint8_t a) {
enc_flush_some(out); enc_flush_some(out);
} }
grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl( grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input) {
grpc_slice input) {
size_t input_length = GRPC_SLICE_LENGTH(input); size_t input_length = GRPC_SLICE_LENGTH(input);
size_t input_triplets = input_length / 3; size_t input_triplets = input_length / 3;
size_t tail_case = input_length % 3; size_t tail_case = input_length % 3;

@ -49,7 +49,6 @@ grpc_slice grpc_chttp2_huffman_compress(grpc_slice input);
grpc_slice y = grpc_chttp2_huffman_compress(x); grpc_slice y = grpc_chttp2_huffman_compress(x);
grpc_slice_unref_internal(exec_ctx, x); grpc_slice_unref_internal(exec_ctx, x);
return y; */ return y; */
grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl( grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input);
grpc_slice input);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */

@ -31,14 +31,11 @@
* *
*/ */
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
void grpc_chttp2_plugin_init(void) { void grpc_chttp2_plugin_init(void) {
grpc_chttp2_base64_encode_and_huffman_compress =
grpc_chttp2_base64_encode_and_huffman_compress_impl;
grpc_register_tracer("http", &grpc_http_trace); grpc_register_tracer("http", &grpc_http_trace);
grpc_register_tracer("flowctl", &grpc_flowctl_trace); grpc_register_tracer("flowctl", &grpc_flowctl_trace);
} }

@ -44,9 +44,7 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
#include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/ext/transport/chttp2/transport/varint.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/http/parser.h" #include "src/core/lib/http/parser.h"
@ -55,7 +53,10 @@
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/http2_errors.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/status_conversion.h"
#include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/timeout_encoding.h"
#include "src/core/lib/transport/transport_impl.h" #include "src/core/lib/transport/transport_impl.h"
@ -409,14 +410,14 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_error_add_child(t->close_transport_on_writes_finished, error); grpc_error_add_child(t->close_transport_on_writes_finished, error);
return; return;
} }
if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { if (!grpc_error_has_clear_grpc_status(error)) {
error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_UNAVAILABLE); GRPC_STATUS_UNAVAILABLE);
} }
t->closed = 1; t->closed = 1;
connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN, connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(error), "close_transport"); GRPC_ERROR_REF(error), "close_transport");
grpc_endpoint_shutdown(exec_ctx, t->ep); grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
/* flush writable stream list to avoid dangling references */ /* flush writable stream list to avoid dangling references */
grpc_chttp2_stream *s; grpc_chttp2_stream *s;
@ -866,7 +867,6 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
(int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT), (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT),
(int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT), (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT),
desc, errstr); desc, errstr);
grpc_error_free_string(errstr);
} }
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
if (closure->error_data.error == GRPC_ERROR_NONE) { if (closure->error_data.error == GRPC_ERROR_NONE) {
@ -895,12 +895,9 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
} }
static bool contains_non_ok_status(grpc_metadata_batch *batch) { static bool contains_non_ok_status(grpc_metadata_batch *batch) {
grpc_linked_mdelem *l; if (batch->idx.named.grpc_status != NULL) {
for (l = batch->list.head; l; l = l->next) { return !grpc_mdelem_eq(batch->idx.named.grpc_status->md,
if (l->md->key == GRPC_MDSTR_GRPC_STATUS && GRPC_MDELEM_GRPC_STATUS_0);
l->md != GRPC_MDELEM_GRPC_STATUS_0) {
return true;
}
} }
return false; return false;
} }
@ -980,9 +977,12 @@ static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id,
bool is_client, bool is_initial) { bool is_client, bool is_initial) {
for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail; for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail;
md = md->next) { md = md->next) {
char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL", gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL",
is_client ? "CLI" : "SVR", grpc_mdstr_as_c_string(md->md->key), is_client ? "CLI" : "SVR", key, value);
grpc_mdstr_as_c_string(md->md->value)); gpr_free(key);
gpr_free(value);
} }
} }
@ -1025,11 +1025,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
} }
if (op->cancel_error != GRPC_ERROR_NONE) { if (op->cancel_error != GRPC_ERROR_NONE) {
grpc_chttp2_cancel_stream(exec_ctx, t, s, GRPC_ERROR_REF(op->cancel_error)); grpc_chttp2_cancel_stream(exec_ctx, t, s, op->cancel_error);
}
if (op->close_error != GRPC_ERROR_NONE) {
close_from_api(exec_ctx, t, s, GRPC_ERROR_REF(op->close_error));
} }
if (op->send_initial_metadata != NULL) { if (op->send_initial_metadata != NULL) {
@ -1080,8 +1076,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
s->send_initial_metadata = NULL; s->send_initial_metadata = NULL;
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
exec_ctx, t, s, &s->send_initial_metadata_finished, exec_ctx, t, s, &s->send_initial_metadata_finished,
GRPC_ERROR_CREATE( GRPC_ERROR_CREATE_REFERENCING(
"Attempt to send initial metadata after stream was closed"), "Attempt to send initial metadata after stream was closed",
&s->write_closed_error, 1),
"send_initial_metadata_finished"); "send_initial_metadata_finished");
} }
} }
@ -1093,7 +1090,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
if (s->write_closed) { if (s->write_closed) {
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
exec_ctx, t, s, &s->fetching_send_message_finished, exec_ctx, t, s, &s->fetching_send_message_finished,
GRPC_ERROR_CREATE("Attempt to send message after stream was closed"), GRPC_ERROR_CREATE_REFERENCING(
"Attempt to send message after stream was closed",
&s->write_closed_error, 1),
"fetching_send_message_finished"); "fetching_send_message_finished");
} else { } else {
GPR_ASSERT(s->fetching_send_message == NULL); GPR_ASSERT(s->fetching_send_message == NULL);
@ -1265,11 +1264,16 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
} }
static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_error_code error, grpc_slice data) { grpc_error *error) {
t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED;
grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)error, data, grpc_http2_error_code http_error;
&t->qbuf); const char *msg;
grpc_error_get_status(error, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL, &msg,
&http_error);
grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
grpc_slice_from_copied_string(msg), &t->qbuf);
grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent"); grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent");
GRPC_ERROR_UNREF(error);
} }
static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
@ -1285,10 +1289,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
op->on_connectivity_state_change); op->on_connectivity_state_change);
} }
if (op->send_goaway) { if (op->goaway_error) {
send_goaway(exec_ctx, t, send_goaway(exec_ctx, t, op->goaway_error);
grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
grpc_slice_ref_internal(*op->goaway_message));
} }
if (op->set_accept_stream) { if (op->set_accept_stream) {
@ -1348,8 +1350,8 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE);
} }
} }
grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[0], grpc_chttp2_incoming_metadata_buffer_publish(
s->recv_initial_metadata); exec_ctx, &s->metadata_buffer[0], s->recv_initial_metadata);
null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready, null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} }
@ -1392,8 +1394,8 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
} }
if (s->all_incoming_byte_streams_finished && if (s->all_incoming_byte_streams_finished &&
s->recv_trailing_metadata_finished != NULL) { s->recv_trailing_metadata_finished != NULL) {
grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1], grpc_chttp2_incoming_metadata_buffer_publish(
s->recv_trailing_metadata); exec_ctx, &s->metadata_buffer[1], s->recv_trailing_metadata);
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE, exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE,
"recv_trailing_metadata_finished"); "recv_trailing_metadata_finished");
@ -1441,70 +1443,37 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
maybe_start_some_streams(exec_ctx, t); maybe_start_some_streams(exec_ctx, t);
} }
static void status_codes_from_error(grpc_error *error, gpr_timespec deadline,
grpc_chttp2_error_code *http2_error,
grpc_status_code *grpc_status) {
intptr_t ip_http;
intptr_t ip_grpc;
bool have_http =
grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &ip_http);
bool have_grpc =
grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &ip_grpc);
if (have_http) {
*http2_error = (grpc_chttp2_error_code)ip_http;
} else if (have_grpc) {
*http2_error =
grpc_chttp2_grpc_status_to_http2_error((grpc_status_code)ip_grpc);
} else {
*http2_error = GRPC_CHTTP2_INTERNAL_ERROR;
}
if (have_grpc) {
*grpc_status = (grpc_status_code)ip_grpc;
} else if (have_http) {
*grpc_status = grpc_chttp2_http2_error_to_grpc_status(
(grpc_chttp2_error_code)ip_http, deadline);
} else {
*grpc_status = GRPC_STATUS_INTERNAL;
}
}
void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
grpc_error *due_to_error) { grpc_error *due_to_error) {
if (!s->read_closed || !s->write_closed) { if (!t->is_client && !s->sent_trailing_metadata &&
grpc_status_code grpc_status; grpc_error_has_clear_grpc_status(due_to_error)) {
grpc_chttp2_error_code http_error; close_from_api(exec_ctx, t, s, due_to_error);
status_codes_from_error(due_to_error, s->deadline, &http_error, return;
&grpc_status); }
if (!s->read_closed || !s->write_closed) {
if (s->id != 0) { if (s->id != 0) {
grpc_http2_error_code http_error;
grpc_error_get_status(due_to_error, s->deadline, NULL, NULL, &http_error);
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error, &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
&s->stats.outgoing)); &s->stats.outgoing));
grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream"); grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream");
} }
const char *msg =
grpc_error_get_str(due_to_error, GRPC_ERROR_STR_GRPC_MESSAGE);
bool free_msg = false;
if (msg == NULL) {
free_msg = true;
msg = grpc_error_string(due_to_error);
}
grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
if (free_msg) grpc_error_free_string(msg);
} }
if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) { if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) {
s->seen_error = true; s->seen_error = true;
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
} }
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error);
} }
void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_status_code status, grpc_chttp2_stream *s, grpc_error *error) {
grpc_slice *slice) { grpc_status_code status;
const char *msg;
grpc_error_get_status(error, s->deadline, &status, &msg, NULL);
if (status != GRPC_STATUS_OK) { if (status != GRPC_STATUS_OK) {
s->seen_error = true; s->seen_error = true;
} }
@ -1518,24 +1487,21 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
s->recv_trailing_metadata_finished != NULL) { s->recv_trailing_metadata_finished != NULL) {
char status_string[GPR_LTOA_MIN_BUFSIZE]; char status_string[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(status, status_string); gpr_ltoa(status, status_string);
grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer_replace_or_add(
&s->metadata_buffer[1], grpc_mdelem_from_metadata_strings( exec_ctx, &s->metadata_buffer[1],
exec_ctx, GRPC_MDSTR_GRPC_STATUS, grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
grpc_mdstr_from_string(status_string))); grpc_slice_from_copied_string(status_string)));
if (slice) { if (msg != NULL) {
grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer_replace_or_add(
&s->metadata_buffer[1], exec_ctx, &s->metadata_buffer[1],
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, grpc_slice_from_copied_string(msg)));
grpc_mdstr_from_slice(exec_ctx,
grpc_slice_ref_internal(*slice))));
} }
s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE; s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
} }
if (slice) {
grpc_slice_unref_internal(exec_ctx, *slice); GRPC_ERROR_UNREF(error);
}
} }
static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) { static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) {
@ -1601,36 +1567,48 @@ void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
int close_writes, grpc_error *error) { int close_writes, grpc_error *error) {
if (s->read_closed && s->write_closed) { if (s->read_closed && s->write_closed) {
/* already closed */ /* already closed */
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
return; return;
} }
bool closed_read = false;
bool became_closed = false;
if (close_reads && !s->read_closed) { if (close_reads && !s->read_closed) {
s->read_closed_error = GRPC_ERROR_REF(error); s->read_closed_error = GRPC_ERROR_REF(error);
s->read_closed = true; s->read_closed = true;
for (int i = 0; i < 2; i++) { closed_read = true;
if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) {
s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE;
}
}
decrement_active_streams_locked(exec_ctx, t, s);
grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
} }
if (close_writes && !s->write_closed) { if (close_writes && !s->write_closed) {
s->write_closed_error = GRPC_ERROR_REF(error); s->write_closed_error = GRPC_ERROR_REF(error);
s->write_closed = true; s->write_closed = true;
grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error)); grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error));
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
} }
if (s->read_closed && s->write_closed) { if (s->read_closed && s->write_closed) {
became_closed = true;
grpc_error *overall_error =
removal_error(GRPC_ERROR_REF(error), s, "Stream removed");
if (s->id != 0) { if (s->id != 0) {
remove_stream(exec_ctx, t, s->id, remove_stream(exec_ctx, t, s->id, GRPC_ERROR_REF(overall_error));
removal_error(GRPC_ERROR_REF(error), s, "Stream removed"));
} else { } else {
/* Purge streams waiting on concurrency still waiting for id assignment */ /* Purge streams waiting on concurrency still waiting for id assignment */
grpc_chttp2_list_remove_waiting_for_concurrency(t, s); grpc_chttp2_list_remove_waiting_for_concurrency(t, s);
} }
if (overall_error != GRPC_ERROR_NONE) {
grpc_chttp2_fake_status(exec_ctx, t, s, overall_error);
}
}
if (closed_read) {
for (int i = 0; i < 2; i++) {
if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) {
s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE;
}
}
decrement_active_streams_locked(exec_ctx, t, s);
grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
}
if (became_closed) {
grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2"); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2");
} }
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
@ -1644,112 +1622,92 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
uint8_t *p; uint8_t *p;
uint32_t len = 0; uint32_t len = 0;
grpc_status_code grpc_status; grpc_status_code grpc_status;
grpc_chttp2_error_code http_error; const char *msg;
status_codes_from_error(error, s->deadline, &http_error, &grpc_status); grpc_error_get_status(error, s->deadline, &grpc_status, &msg, NULL);
GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100); GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
if (s->id != 0 && !t->is_client) { /* Hand roll a header block.
/* Hand roll a header block. This is unnecessarily ugly - at some point we should find a more
This is unnecessarily ugly - at some point we should find a more elegant solution.
elegant It's complicated by the fact that our send machinery would be dead by
solution. the time we got around to sending this, so instead we ignore HPACK
It's complicated by the fact that our send machinery would be dead by compression and just write the uncompressed bytes onto the wire. */
the status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
time we got around to sending this, so instead we ignore HPACK p = GRPC_SLICE_START_PTR(status_hdr);
compression *p++ = 0x00; /* literal header, not indexed */
and just write the uncompressed bytes onto the wire. */ *p++ = 11; /* len(grpc-status) */
status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10)); *p++ = 'g';
p = GRPC_SLICE_START_PTR(status_hdr); *p++ = 'r';
*p++ = 0x40; /* literal header */ *p++ = 'p';
*p++ = 11; /* len(grpc-status) */ *p++ = 'c';
*p++ = '-';
*p++ = 's';
*p++ = 't';
*p++ = 'a';
*p++ = 't';
*p++ = 'u';
*p++ = 's';
if (grpc_status < 10) {
*p++ = 1;
*p++ = (uint8_t)('0' + grpc_status);
} else {
*p++ = 2;
*p++ = (uint8_t)('0' + (grpc_status / 10));
*p++ = (uint8_t)('0' + (grpc_status % 10));
}
GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
if (msg != NULL) {
size_t msg_len = strlen(msg);
GPR_ASSERT(msg_len <= UINT32_MAX);
uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0);
message_pfx = grpc_slice_malloc(14 + msg_len_len);
p = GRPC_SLICE_START_PTR(message_pfx);
*p++ = 0x00; /* literal header, not indexed */
*p++ = 12; /* len(grpc-message) */
*p++ = 'g'; *p++ = 'g';
*p++ = 'r'; *p++ = 'r';
*p++ = 'p'; *p++ = 'p';
*p++ = 'c'; *p++ = 'c';
*p++ = '-'; *p++ = '-';
*p++ = 'm';
*p++ = 'e';
*p++ = 's'; *p++ = 's';
*p++ = 't';
*p++ = 'a';
*p++ = 't';
*p++ = 'u';
*p++ = 's'; *p++ = 's';
if (grpc_status < 10) { *p++ = 'a';
*p++ = 1; *p++ = 'g';
*p++ = (uint8_t)('0' + grpc_status); *p++ = 'e';
} else { GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p, (uint32_t)msg_len_len);
*p++ = 2; p += msg_len_len;
*p++ = (uint8_t)('0' + (grpc_status / 10)); GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
*p++ = (uint8_t)('0' + (grpc_status % 10)); len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
} len += (uint32_t)msg_len;
GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr)); }
len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
hdr = grpc_slice_malloc(9);
const char *optional_message = p = GRPC_SLICE_START_PTR(hdr);
grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE); *p++ = (uint8_t)(len >> 16);
*p++ = (uint8_t)(len >> 8);
if (optional_message != NULL) { *p++ = (uint8_t)(len);
size_t msg_len = strlen(optional_message); *p++ = GRPC_CHTTP2_FRAME_HEADER;
GPR_ASSERT(msg_len <= UINT32_MAX); *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0); *p++ = (uint8_t)(s->id >> 24);
message_pfx = grpc_slice_malloc(14 + msg_len_len); *p++ = (uint8_t)(s->id >> 16);
p = GRPC_SLICE_START_PTR(message_pfx); *p++ = (uint8_t)(s->id >> 8);
*p++ = 0x40; *p++ = (uint8_t)(s->id);
*p++ = 12; /* len(grpc-message) */ GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
*p++ = 'g';
*p++ = 'r'; grpc_slice_buffer_add(&t->qbuf, hdr);
*p++ = 'p'; grpc_slice_buffer_add(&t->qbuf, status_hdr);
*p++ = 'c'; if (msg != NULL) {
*p++ = '-'; grpc_slice_buffer_add(&t->qbuf, message_pfx);
*p++ = 'm'; grpc_slice_buffer_add(&t->qbuf, grpc_slice_from_copied_string(msg));
*p++ = 'e'; }
*p++ = 's'; grpc_slice_buffer_add(
*p++ = 's'; &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
*p++ = 'a'; &s->stats.outgoing));
*p++ = 'g';
*p++ = 'e';
GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p,
(uint32_t)msg_len_len);
p += msg_len_len;
GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
len += (uint32_t)msg_len;
}
hdr = grpc_slice_malloc(9);
p = GRPC_SLICE_START_PTR(hdr);
*p++ = (uint8_t)(len >> 16);
*p++ = (uint8_t)(len >> 8);
*p++ = (uint8_t)(len);
*p++ = GRPC_CHTTP2_FRAME_HEADER;
*p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
*p++ = (uint8_t)(s->id >> 24);
*p++ = (uint8_t)(s->id >> 16);
*p++ = (uint8_t)(s->id >> 8);
*p++ = (uint8_t)(s->id);
GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
grpc_slice_buffer_add(&t->qbuf, hdr);
grpc_slice_buffer_add(&t->qbuf, status_hdr);
if (optional_message) {
grpc_slice_buffer_add(&t->qbuf, message_pfx);
grpc_slice_buffer_add(&t->qbuf,
grpc_slice_from_copied_string(optional_message));
}
grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR,
&s->stats.outgoing));
}
const char *msg = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
bool free_msg = false;
if (msg == NULL) {
free_msg = true;
msg = grpc_error_string(error);
}
grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
if (free_msg) grpc_error_free_string(msg);
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error);
grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api"); grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api");
@ -1827,8 +1785,10 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
if (parse_error == GRPC_ERROR_NONE && if (parse_error == GRPC_ERROR_NONE &&
(parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) { (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
error = grpc_error_set_int( error = grpc_error_set_int(
GRPC_ERROR_CREATE("Trying to connect an http1.x server"), grpc_error_set_int(
GRPC_ERROR_INT_HTTP_STATUS, response.status); GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
GRPC_ERROR_INT_HTTP_STATUS, response.status),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
} }
GRPC_ERROR_UNREF(parse_error); GRPC_ERROR_UNREF(parse_error);
@ -2089,6 +2049,8 @@ static void incoming_byte_stream_publish_error(
grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error)); grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error));
bs->on_next = NULL; bs->on_next = NULL;
GRPC_ERROR_UNREF(bs->error); GRPC_ERROR_UNREF(bs->error);
grpc_chttp2_cancel_stream(exec_ctx, bs->transport, bs->stream,
GRPC_ERROR_REF(error));
bs->error = error; bs->error = error;
} }
@ -2197,8 +2159,10 @@ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory", gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory",
t->peer_string); t->peer_string);
} }
send_goaway(exec_ctx, t, GRPC_CHTTP2_ENHANCE_YOUR_CALM, send_goaway(exec_ctx, t,
grpc_slice_from_static_string("Buffers full")); grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
GRPC_ERROR_INT_HTTP2_ERROR,
GRPC_HTTP2_ENHANCE_YOUR_CALM));
} else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) { } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) {
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
@ -2227,7 +2191,7 @@ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_chttp2_cancel_stream( grpc_chttp2_cancel_stream(
exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"), exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
GRPC_ERROR_INT_HTTP2_ERROR, GRPC_ERROR_INT_HTTP2_ERROR,
GRPC_CHTTP2_ENHANCE_YOUR_CALM)); GRPC_HTTP2_ENHANCE_YOUR_CALM));
if (n > 1) { if (n > 1) {
/* Since we cancel one stream per destructive reclamation, if /* Since we cancel one stream per destructive reclamation, if
there are more streams left, we can immediately post a new there are more streams left, we can immediately post a new

@ -39,8 +39,7 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/ext/transport/chttp2/transport/frame.h"
#include "src/core/ext/transport/chttp2/transport/http2_errors.h" #include "src/core/lib/transport/http2_errors.h"
#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
grpc_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code, grpc_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code,
grpc_transport_one_way_stats *stats) { grpc_transport_one_way_stats *stats) {
@ -109,17 +108,9 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx,
(((uint32_t)p->reason_bytes[2]) << 8) | (((uint32_t)p->reason_bytes[2]) << 8) |
(((uint32_t)p->reason_bytes[3])); (((uint32_t)p->reason_bytes[3]));
grpc_error *error = GRPC_ERROR_NONE; grpc_error *error = GRPC_ERROR_NONE;
if (reason != GRPC_CHTTP2_NO_ERROR || s->header_frames_received < 2) { if (reason != GRPC_HTTP2_NO_ERROR || s->header_frames_received < 2) {
error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"), error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"),
GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason); GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason);
grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
(grpc_chttp2_error_code)reason, s->deadline);
char *status_details;
gpr_asprintf(&status_details, "Received RST_STREAM with error code %d",
reason);
grpc_slice slice_details = grpc_slice_from_copied_string(status_details);
gpr_free(status_details);
grpc_chttp2_fake_status(exec_ctx, t, s, status_code, &slice_details);
} }
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error);
} }

@ -43,8 +43,8 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/ext/transport/chttp2/transport/frame.h"
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/transport/http2_errors.h"
#define MAX_MAX_HEADER_LIST_SIZE (1024 * 1024 * 1024) #define MAX_MAX_HEADER_LIST_SIZE (1024 * 1024 * 1024)
@ -52,21 +52,21 @@
const grpc_chttp2_setting_parameters const grpc_chttp2_setting_parameters
grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = { grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {
{NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, {NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
GRPC_CHTTP2_PROTOCOL_ERROR}, GRPC_HTTP2_PROTOCOL_ERROR},
{"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff, {"HEADER_TABLE_SIZE", 4096, 0, 0xffffffff,
GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
{"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, {"ENABLE_PUSH", 1, 0, 1, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
GRPC_CHTTP2_PROTOCOL_ERROR}, GRPC_HTTP2_PROTOCOL_ERROR},
{"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu, {"MAX_CONCURRENT_STREAMS", 0xffffffffu, 0, 0xffffffffu,
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
{"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu, {"INITIAL_WINDOW_SIZE", 65535, 0, 0x7fffffffu,
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
GRPC_CHTTP2_FLOW_CONTROL_ERROR}, GRPC_HTTP2_FLOW_CONTROL_ERROR},
{"MAX_FRAME_SIZE", 16384, 16384, 16777215, {"MAX_FRAME_SIZE", 16384, 16384, 16777215,
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_CHTTP2_PROTOCOL_ERROR}, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
{"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0, {"MAX_HEADER_LIST_SIZE", MAX_MAX_HEADER_LIST_SIZE, 0,
MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE, MAX_MAX_HEADER_LIST_SIZE, GRPC_CHTTP2_CLAMP_INVALID_VALUE,
GRPC_CHTTP2_PROTOCOL_ERROR}, GRPC_HTTP2_PROTOCOL_ERROR},
}; };
static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) { static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) {

@ -49,6 +49,7 @@
#include "src/core/ext/transport/chttp2/transport/hpack_table.h" #include "src/core/ext/transport/chttp2/transport/hpack_table.h"
#include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/ext/transport/chttp2/transport/varint.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/timeout_encoding.h"
@ -64,6 +65,10 @@
/* don't consider adding anything bigger than this to the hpack table */ /* don't consider adding anything bigger than this to the hpack table */
#define MAX_DECODER_SPACE_USAGE 512 #define MAX_DECODER_SPACE_USAGE 512
static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL};
static const grpc_slice terminal_slice = {&terminal_slice_refcount,
.data.refcounted = {0, 0}};
extern int grpc_http_trace; extern int grpc_http_trace;
typedef struct { typedef struct {
@ -185,9 +190,12 @@ static void evict_entry(grpc_chttp2_hpack_compressor *c) {
/* add an element to the decoder table */ /* add an element to the decoder table */
static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem) { grpc_mdelem elem) {
uint32_t key_hash = elem->key->hash; GPR_ASSERT(GRPC_MDELEM_IS_INTERNED(elem));
uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
uint32_t new_index = c->tail_remote_index + c->table_elems + 1; uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem); size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
@ -212,17 +220,18 @@ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
c->table_elems++; c->table_elems++;
/* Store this element into {entries,indices}_elem */ /* Store this element into {entries,indices}_elem */
if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem) { if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem)) {
/* already there: update with new index */ /* already there: update with new index */
c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
} else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem) { } else if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)],
elem)) {
/* already there (cuckoo): update with new index */ /* already there (cuckoo): update with new index */
c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
} else if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == NULL) { } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_2(elem_hash)])) {
/* not there, but a free element: add */ /* not there, but a free element: add */
c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem); c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index; c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
} else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == NULL) { } else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_3(elem_hash)])) {
/* not there (cuckoo), but a free element: add */ /* not there (cuckoo), but a free element: add */
c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem); c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index; c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
@ -241,24 +250,34 @@ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* do exactly the same for the key (so we can find by that again too) */ /* do exactly the same for the key (so we can find by that again too) */
if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key) { if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
GRPC_MDKEY(elem))) {
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) { } else if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_3(key_hash)],
GRPC_MDKEY(elem))) {
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) { } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)].refcount ==
c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key); &terminal_slice_refcount) {
c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) { } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)].refcount ==
c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key); &terminal_slice_refcount) {
c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] < } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
c->indices_keys[HASH_FRAGMENT_3(key_hash)]) { c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[HASH_FRAGMENT_2(key_hash)]); grpc_slice_unref_internal(exec_ctx,
c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key); c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else { } else {
GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[HASH_FRAGMENT_3(key_hash)]); grpc_slice_unref_internal(exec_ctx,
c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key); c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} }
} }
@ -270,20 +289,18 @@ static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
len); len);
} }
static grpc_slice get_wire_value(grpc_mdelem *elem, uint8_t *huffman_prefix) { static grpc_slice get_wire_value(grpc_mdelem elem, uint8_t *huffman_prefix) {
if (grpc_is_binary_header( if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
(const char *)GRPC_SLICE_START_PTR(elem->key->slice),
GRPC_SLICE_LENGTH(elem->key->slice))) {
*huffman_prefix = 0x80; *huffman_prefix = 0x80;
return grpc_mdstr_as_base64_encoded_and_huffman_compressed(elem->value); return grpc_chttp2_base64_encode_and_huffman_compress(GRPC_MDVALUE(elem));
} }
/* TODO(ctiller): opportunistically compress non-binary headers */ /* TODO(ctiller): opportunistically compress non-binary headers */
*huffman_prefix = 0x00; *huffman_prefix = 0x00;
return elem->value->slice; return grpc_slice_ref_internal(GRPC_MDVALUE(elem));
} }
static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
uint32_t key_index, grpc_mdelem *elem, uint32_t key_index, grpc_mdelem elem,
framer_state *st) { framer_state *st) {
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2); uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
uint8_t huffman_prefix; uint8_t huffman_prefix;
@ -296,11 +313,11 @@ static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
add_tiny_header_data(st, len_pfx), len_pfx); add_tiny_header_data(st, len_pfx), len_pfx);
GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix, GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len); add_tiny_header_data(st, len_val_len), len_val_len);
add_header_data(st, grpc_slice_ref_internal(value_slice)); add_header_data(st, value_slice);
} }
static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
uint32_t key_index, grpc_mdelem *elem, uint32_t key_index, grpc_mdelem elem,
framer_state *st) { framer_state *st) {
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4); uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
uint8_t huffman_prefix; uint8_t huffman_prefix;
@ -313,12 +330,12 @@ static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
add_tiny_header_data(st, len_pfx), len_pfx); add_tiny_header_data(st, len_pfx), len_pfx);
GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix, GRPC_CHTTP2_WRITE_VARINT((uint32_t)len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len); add_tiny_header_data(st, len_val_len), len_val_len);
add_header_data(st, grpc_slice_ref_internal(value_slice)); add_header_data(st, value_slice);
} }
static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem, framer_state *st) { grpc_mdelem elem, framer_state *st) {
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key->slice); uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
uint8_t huffman_prefix; uint8_t huffman_prefix;
grpc_slice value_slice = get_wire_value(elem, &huffman_prefix); grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice); uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@ -329,15 +346,15 @@ static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
*add_tiny_header_data(st, 1) = 0x40; *add_tiny_header_data(st, 1) = 0x40;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len); add_tiny_header_data(st, len_key_len), len_key_len);
add_header_data(st, grpc_slice_ref_internal(elem->key->slice)); add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix, GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len); add_tiny_header_data(st, len_val_len), len_val_len);
add_header_data(st, grpc_slice_ref_internal(value_slice)); add_header_data(st, value_slice);
} }
static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem, framer_state *st) { grpc_mdelem elem, framer_state *st) {
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key->slice); uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
uint8_t huffman_prefix; uint8_t huffman_prefix;
grpc_slice value_slice = get_wire_value(elem, &huffman_prefix); grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice); uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@ -348,10 +365,10 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
*add_tiny_header_data(st, 1) = 0x00; *add_tiny_header_data(st, 1) = 0x00;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00, GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len); add_tiny_header_data(st, len_key_len), len_key_len);
add_header_data(st, grpc_slice_ref_internal(elem->key->slice)); add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix, GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len); add_tiny_header_data(st, len_val_len), len_val_len);
add_header_data(st, grpc_slice_ref_internal(value_slice)); add_header_data(st, value_slice);
} }
static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c, static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
@ -369,15 +386,9 @@ static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) {
/* encode an mdelem */ /* encode an mdelem */
static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
grpc_mdelem *elem, framer_state *st) { grpc_mdelem elem, framer_state *st) {
uint32_t key_hash = elem->key->hash; GPR_ASSERT(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)) > 0);
uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash); if (GRPC_SLICE_START_PTR(GRPC_MDKEY(elem))[0] != ':') { /* regular header */
size_t decoder_space_usage;
uint32_t indices_key;
int should_add_elem;
GPR_ASSERT(GRPC_SLICE_LENGTH(elem->key->slice) > 0);
if (GRPC_SLICE_START_PTR(elem->key->slice)[0] != ':') { /* regular header */
st->seen_regular_header = 1; st->seen_regular_header = 1;
} else { } else {
GPR_ASSERT( GPR_ASSERT(
@ -385,11 +396,39 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
"Reserved header (colon-prefixed) happening after regular ones."); "Reserved header (colon-prefixed) happening after regular ones.");
} }
if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(elem)) {
char *k = grpc_slice_to_c_string(GRPC_MDKEY(elem));
char *v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
gpr_log(
GPR_DEBUG,
"Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem),
grpc_slice_is_interned(GRPC_MDKEY(elem)),
grpc_slice_is_interned(GRPC_MDVALUE(elem)));
gpr_free(k);
gpr_free(v);
}
if (!GRPC_MDELEM_IS_INTERNED(elem)) {
emit_lithdr_noidx_v(c, elem, st);
return;
}
uint32_t key_hash;
uint32_t value_hash;
uint32_t elem_hash;
size_t decoder_space_usage;
uint32_t indices_key;
int should_add_elem;
key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems); inc_filter(HASH_FRAGMENT_1(elem_hash), &c->filter_elems_sum, c->filter_elems);
/* is this elem currently in the decoders table? */ /* is this elem currently in the decoders table? */
if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem && if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) &&
c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) { c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
/* HIT: complete element (first cuckoo hash) */ /* HIT: complete element (first cuckoo hash) */
emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]), emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
@ -397,7 +436,7 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
return; return;
} }
if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem && if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) &&
c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) { c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
/* HIT: complete element (second cuckoo hash) */ /* HIT: complete element (second cuckoo hash) */
emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
@ -414,7 +453,8 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* no hits for the elem... maybe there's a key? */ /* no hits for the elem... maybe there's a key? */
indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)]; indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == elem->key && if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
GRPC_MDKEY(elem)) &&
indices_key > c->tail_remote_index) { indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */ /* HIT: key (first cuckoo hash) */
if (should_add_elem) { if (should_add_elem) {
@ -429,7 +469,8 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
} }
indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)]; indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key && if (grpc_slice_eq(c->entries_keys[HASH_FRAGMENT_3(key_hash)],
GRPC_MDKEY(elem)) &&
indices_key > c->tail_remote_index) { indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */ /* HIT: key (first cuckoo hash) */
if (should_add_elem) { if (should_add_elem) {
@ -463,11 +504,11 @@ static void deadline_enc(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
framer_state *st) { framer_state *st) {
char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
grpc_mdelem *mdelem; grpc_mdelem mdelem;
grpc_http2_encode_timeout( grpc_http2_encode_timeout(
gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str); gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
mdelem = grpc_mdelem_from_metadata_strings( mdelem = grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT,
exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str)); grpc_slice_from_copied_string(timeout_str));
hpack_enc(exec_ctx, c, mdelem, st); hpack_enc(exec_ctx, c, mdelem, st);
GRPC_MDELEM_UNREF(exec_ctx, mdelem); GRPC_MDELEM_UNREF(exec_ctx, mdelem);
} }
@ -484,14 +525,19 @@ void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c) {
gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems); gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
memset(c->table_elem_size, 0, memset(c->table_elem_size, 0,
sizeof(*c->table_elem_size) * c->cap_table_elems); sizeof(*c->table_elem_size) * c->cap_table_elems);
for (size_t i = 0; i < GPR_ARRAY_SIZE(c->entries_keys); i++) {
c->entries_keys[i] = terminal_slice;
}
} }
void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx, void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c) { grpc_chttp2_hpack_compressor *c) {
int i; int i;
for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) { for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
if (c->entries_keys[i]) GRPC_MDSTR_UNREF(exec_ctx, c->entries_keys[i]); if (c->entries_keys[i].refcount != &terminal_slice_refcount) {
if (c->entries_elems[i]) GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]); grpc_slice_unref_internal(exec_ctx, c->entries_keys[i]);
}
GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]);
} }
gpr_free(c->table_elem_size); gpr_free(c->table_elem_size);
} }

@ -74,8 +74,8 @@ typedef struct {
/* entry tables for keys & elems: these tables track values that have been /* entry tables for keys & elems: these tables track values that have been
seen and *may* be in the decompressor table */ seen and *may* be in the decompressor table */
grpc_mdstr *entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES]; grpc_slice entries_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
grpc_mdelem *entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; grpc_mdelem entries_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES]; uint32_t indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES]; uint32_t indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];

@ -50,9 +50,13 @@
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/http2_errors.h"
/* TODO(ctiller): remove before submission */
#include "src/core/lib/slice/slice_string_helpers.h"
extern int grpc_http_trace; extern int grpc_http_trace;
@ -668,8 +672,22 @@ static const uint8_t inverse_base64[256] = {
/* emission helpers */ /* emission helpers */
static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p,
grpc_mdelem *md, int add_to_table) { grpc_mdelem md, int add_to_table) {
if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(md)) {
char *k = grpc_slice_to_c_string(GRPC_MDKEY(md));
char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(
GPR_DEBUG,
"Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md),
grpc_slice_is_interned(GRPC_MDKEY(md)),
grpc_slice_is_interned(GRPC_MDVALUE(md)));
gpr_free(k);
gpr_free(v);
}
if (add_to_table) { if (add_to_table) {
GPR_ASSERT(GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_INTERNED ||
GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC);
grpc_error *err = grpc_chttp2_hptbl_add(exec_ctx, &p->table, md); grpc_error *err = grpc_chttp2_hptbl_add(exec_ctx, &p->table, md);
if (err != GRPC_ERROR_NONE) return err; if (err != GRPC_ERROR_NONE) return err;
} }
@ -681,10 +699,28 @@ static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p, static grpc_slice take_string(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser_string *str) { grpc_chttp2_hpack_parser *p,
grpc_mdstr *s = grpc_mdstr_from_buffer((uint8_t *)str->str, str->length); grpc_chttp2_hpack_parser_string *str,
str->length = 0; bool intern) {
grpc_slice s;
if (!str->copied) {
if (intern) {
s = grpc_slice_intern(str->data.referenced);
grpc_slice_unref_internal(exec_ctx, str->data.referenced);
} else {
s = str->data.referenced;
}
str->copied = true;
str->data.referenced = grpc_empty_slice();
} else if (intern) {
s = grpc_slice_intern(grpc_slice_from_static_buffer(
str->data.copied.str, str->data.copied.length));
} else {
s = grpc_slice_from_copied_buffer(str->data.copied.str,
str->data.copied.length);
}
str->data.copied.length = 0;
return s; return s;
} }
@ -771,8 +807,8 @@ static grpc_error *finish_indexed_field(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
if (md == NULL) { if (GRPC_MDISNULL(md)) {
return grpc_error_set_int( return grpc_error_set_int(
grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"), grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
GRPC_ERROR_INT_INDEX, (intptr_t)p->index), GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
@ -813,12 +849,13 @@ static grpc_error *finish_lithdr_incidx(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */ GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings( grpc_error *err = on_hdr(
exec_ctx, GRPC_MDSTR_REF(md->key), exec_ctx, p,
take_string(p, &p->value)), grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
1); take_string(exec_ctx, p, &p->value, true)),
1);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end); return parse_begin(exec_ctx, p, cur, end);
} }
@ -828,10 +865,11 @@ static grpc_error *finish_lithdr_incidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings( grpc_error *err = on_hdr(
exec_ctx, take_string(p, &p->key), exec_ctx, p,
take_string(p, &p->value)), grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
1); take_string(exec_ctx, p, &p->value, true)),
1);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end); return parse_begin(exec_ctx, p, cur, end);
} }
@ -881,12 +919,13 @@ static grpc_error *finish_lithdr_notidx(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */ GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings( grpc_error *err = on_hdr(
exec_ctx, GRPC_MDSTR_REF(md->key), exec_ctx, p,
take_string(p, &p->value)), grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
0); take_string(exec_ctx, p, &p->value, false)),
0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end); return parse_begin(exec_ctx, p, cur, end);
} }
@ -896,10 +935,11 @@ static grpc_error *finish_lithdr_notidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings( grpc_error *err = on_hdr(
exec_ctx, take_string(p, &p->key), exec_ctx, p,
take_string(p, &p->value)), grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
0); take_string(exec_ctx, p, &p->value, false)),
0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end); return parse_begin(exec_ctx, p, cur, end);
} }
@ -949,12 +989,13 @@ static grpc_error *finish_lithdr_nvridx(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */ GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings( grpc_error *err = on_hdr(
exec_ctx, GRPC_MDSTR_REF(md->key), exec_ctx, p,
take_string(p, &p->value)), grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
0); take_string(exec_ctx, p, &p->value, false)),
0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end); return parse_begin(exec_ctx, p, cur, end);
} }
@ -964,10 +1005,11 @@ static grpc_error *finish_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_error *err = on_hdr(exec_ctx, p, grpc_mdelem_from_metadata_strings( grpc_error *err = on_hdr(
exec_ctx, take_string(p, &p->key), exec_ctx, p,
take_string(p, &p->value)), grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
0); take_string(exec_ctx, p, &p->value, false)),
0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err); if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end); return parse_begin(exec_ctx, p, cur, end);
} }
@ -1261,14 +1303,15 @@ static grpc_error *parse_string_prefix(grpc_exec_ctx *exec_ctx,
static void append_bytes(grpc_chttp2_hpack_parser_string *str, static void append_bytes(grpc_chttp2_hpack_parser_string *str,
const uint8_t *data, size_t length) { const uint8_t *data, size_t length) {
if (length == 0) return; if (length == 0) return;
if (length + str->length > str->capacity) { if (length + str->data.copied.length > str->data.copied.capacity) {
GPR_ASSERT(str->length + length <= UINT32_MAX); GPR_ASSERT(str->data.copied.length + length <= UINT32_MAX);
str->capacity = (uint32_t)(str->length + length); str->data.copied.capacity = (uint32_t)(str->data.copied.length + length);
str->str = gpr_realloc(str->str, str->capacity); str->data.copied.str =
gpr_realloc(str->data.copied.str, str->data.copied.capacity);
} }
memcpy(str->str + str->length, data, length); memcpy(str->data.copied.str + str->data.copied.length, data, length);
GPR_ASSERT(length <= UINT32_MAX - str->length); GPR_ASSERT(length <= UINT32_MAX - str->data.copied.length);
str->length += (uint32_t)length; str->data.copied.length += (uint32_t)length;
} }
static grpc_error *append_string(grpc_exec_ctx *exec_ctx, static grpc_error *append_string(grpc_exec_ctx *exec_ctx,
@ -1351,11 +1394,9 @@ static grpc_error *append_string(grpc_exec_ctx *exec_ctx,
exec_ctx, p, cur, end, GRPC_ERROR_CREATE("Should never reach here"))); exec_ctx, p, cur, end, GRPC_ERROR_CREATE("Should never reach here")));
} }
/* append a null terminator to a string */
static grpc_error *finish_str(grpc_exec_ctx *exec_ctx, static grpc_error *finish_str(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, const uint8_t *cur, grpc_chttp2_hpack_parser *p, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
uint8_t terminator = 0;
uint8_t decoded[2]; uint8_t decoded[2];
uint32_t bits; uint32_t bits;
grpc_chttp2_hpack_parser_string *str = p->parsing.str; grpc_chttp2_hpack_parser_string *str = p->parsing.str;
@ -1396,8 +1437,6 @@ static grpc_error *finish_str(grpc_exec_ctx *exec_ctx,
append_bytes(str, decoded, 2); append_bytes(str, decoded, 2);
break; break;
} }
append_bytes(str, &terminator, 1);
p->parsing.str->length--; /* don't actually count the null terminator */
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -1472,8 +1511,18 @@ static grpc_error *begin_parse_string(grpc_exec_ctx *exec_ctx,
const uint8_t *cur, const uint8_t *end, const uint8_t *cur, const uint8_t *end,
uint8_t binary, uint8_t binary,
grpc_chttp2_hpack_parser_string *str) { grpc_chttp2_hpack_parser_string *str) {
if (!p->huff && binary == NOT_BINARY && (end - cur) >= (intptr_t)p->strlen &&
p->current_slice_refcount != NULL) {
str->copied = false;
str->data.referenced.refcount = p->current_slice_refcount;
str->data.referenced.data.refcounted.bytes = (uint8_t *)cur;
str->data.referenced.data.refcounted.length = p->strlen;
grpc_slice_ref_internal(str->data.referenced);
return parse_next(exec_ctx, p, cur + p->strlen, end);
}
p->strgot = 0; p->strgot = 0;
str->length = 0; str->copied = true;
str->data.copied.length = 0;
p->parsing.str = str; p->parsing.str = str;
p->huff_state = 0; p->huff_state = 0;
p->binary = binary; p->binary = binary;
@ -1490,21 +1539,22 @@ static grpc_error *parse_key_string(grpc_exec_ctx *exec_ctx,
/* check if a key represents a binary header or not */ /* check if a key represents a binary header or not */
static bool is_binary_literal_header(grpc_chttp2_hpack_parser *p) { static bool is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
return grpc_is_binary_header(p->key.str, p->key.length); return grpc_is_binary_header(
p->key.copied ? grpc_slice_from_static_buffer(p->key.data.copied.str,
p->key.data.copied.length)
: p->key.data.referenced);
} }
static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p, static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p,
bool *is) { bool *is) {
grpc_mdelem *elem = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
if (!elem) { if (GRPC_MDISNULL(elem)) {
return grpc_error_set_int( return grpc_error_set_int(
grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"), grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
GRPC_ERROR_INT_INDEX, (intptr_t)p->index), GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents); GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents);
} }
*is = grpc_is_binary_header( *is = grpc_is_binary_header(GRPC_MDKEY(elem));
(const char *)GRPC_SLICE_START_PTR(elem->key->slice),
GRPC_SLICE_LENGTH(elem->key->slice));
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -1539,12 +1589,14 @@ void grpc_chttp2_hpack_parser_init(grpc_exec_ctx *exec_ctx,
p->on_header = NULL; p->on_header = NULL;
p->on_header_user_data = NULL; p->on_header_user_data = NULL;
p->state = parse_begin; p->state = parse_begin;
p->key.str = NULL; p->key.data.referenced = grpc_empty_slice();
p->key.capacity = 0; p->key.data.copied.str = NULL;
p->key.length = 0; p->key.data.copied.capacity = 0;
p->value.str = NULL; p->key.data.copied.length = 0;
p->value.capacity = 0; p->value.data.referenced = grpc_empty_slice();
p->value.length = 0; p->value.data.copied.str = NULL;
p->value.data.copied.capacity = 0;
p->value.data.copied.length = 0;
p->dynamic_table_update_allowed = 2; p->dynamic_table_update_allowed = 2;
p->last_error = GRPC_ERROR_NONE; p->last_error = GRPC_ERROR_NONE;
grpc_chttp2_hptbl_init(exec_ctx, &p->table); grpc_chttp2_hptbl_init(exec_ctx, &p->table);
@ -1559,19 +1611,24 @@ void grpc_chttp2_hpack_parser_destroy(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p) { grpc_chttp2_hpack_parser *p) {
grpc_chttp2_hptbl_destroy(exec_ctx, &p->table); grpc_chttp2_hptbl_destroy(exec_ctx, &p->table);
GRPC_ERROR_UNREF(p->last_error); GRPC_ERROR_UNREF(p->last_error);
gpr_free(p->key.str); grpc_slice_unref_internal(exec_ctx, p->key.data.referenced);
gpr_free(p->value.str); grpc_slice_unref_internal(exec_ctx, p->value.data.referenced);
gpr_free(p->key.data.copied.str);
gpr_free(p->value.data.copied.str);
} }
grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx, grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *beg, grpc_slice slice) {
const uint8_t *end) {
/* TODO(ctiller): limit the distance of end from beg, and perform multiple /* TODO(ctiller): limit the distance of end from beg, and perform multiple
steps in the event of a large chunk of data to limit steps in the event of a large chunk of data to limit
stack space usage when no tail call optimization is stack space usage when no tail call optimization is
available */ available */
return p->state(exec_ctx, p, beg, end); p->current_slice_refcount = slice.refcount;
grpc_error *error = p->state(exec_ctx, p, GRPC_SLICE_START_PTR(slice),
GRPC_SLICE_END_PTR(slice));
p->current_slice_refcount = NULL;
return error;
} }
typedef void (*maybe_complete_func_type)(grpc_exec_ctx *exec_ctx, typedef void (*maybe_complete_func_type)(grpc_exec_ctx *exec_ctx,
@ -1587,7 +1644,7 @@ static void force_client_rst_stream(grpc_exec_ctx *exec_ctx, void *sp,
grpc_chttp2_transport *t = s->t; grpc_chttp2_transport *t = s->t;
if (!s->write_closed) { if (!s->write_closed) {
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR, &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
&s->stats.outgoing)); &s->stats.outgoing));
grpc_chttp2_initiate_write(exec_ctx, t, false, "force_rst_stream"); grpc_chttp2_initiate_write(exec_ctx, t, false, "force_rst_stream");
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, GRPC_ERROR_NONE); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, GRPC_ERROR_NONE);
@ -1605,8 +1662,7 @@ grpc_error *grpc_chttp2_header_parser_parse(grpc_exec_ctx *exec_ctx,
if (s != NULL) { if (s != NULL) {
s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice); s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice);
} }
grpc_error *error = grpc_chttp2_hpack_parser_parse( grpc_error *error = grpc_chttp2_hpack_parser_parse(exec_ctx, parser, slice);
exec_ctx, parser, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_END_PTR(slice));
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
return error; return error;

@ -49,14 +49,20 @@ typedef grpc_error *(*grpc_chttp2_hpack_parser_state)(
const uint8_t *end); const uint8_t *end);
typedef struct { typedef struct {
char *str; bool copied;
uint32_t length; struct {
uint32_t capacity; grpc_slice referenced;
struct {
char *str;
uint32_t length;
uint32_t capacity;
} copied;
} data;
} grpc_chttp2_hpack_parser_string; } grpc_chttp2_hpack_parser_string;
struct grpc_chttp2_hpack_parser { struct grpc_chttp2_hpack_parser {
/* user specified callback for each header output */ /* user specified callback for each header output */
void (*on_header)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem *md); void (*on_header)(grpc_exec_ctx *exec_ctx, void *user_data, grpc_mdelem md);
void *on_header_user_data; void *on_header_user_data;
grpc_error *last_error; grpc_error *last_error;
@ -67,6 +73,8 @@ struct grpc_chttp2_hpack_parser {
const grpc_chttp2_hpack_parser_state *next_state; const grpc_chttp2_hpack_parser_state *next_state;
/* what to do after skipping prioritization data */ /* what to do after skipping prioritization data */
grpc_chttp2_hpack_parser_state after_prioritization; grpc_chttp2_hpack_parser_state after_prioritization;
/* the refcount of the slice that we're currently parsing */
grpc_slice_refcount *current_slice_refcount;
/* the value we're currently parsing */ /* the value we're currently parsing */
union { union {
uint32_t *value; uint32_t *value;
@ -106,11 +114,9 @@ void grpc_chttp2_hpack_parser_destroy(grpc_exec_ctx *exec_ctx,
void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p); void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p);
/* returns 1 on success, 0 on error */
grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx, grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *beg, grpc_slice slice);
const uint8_t *end);
/* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for /* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
the transport */ the transport */

@ -190,8 +190,11 @@ void grpc_chttp2_hptbl_init(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries); tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries); memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
tbl->static_ents[i - 1] = grpc_mdelem_from_strings( tbl->static_ents[i - 1] = grpc_mdelem_from_slices(
exec_ctx, static_table[i].key, static_table[i].value); exec_ctx,
grpc_slice_intern(grpc_slice_from_static_string(static_table[i].key)),
grpc_slice_intern(
grpc_slice_from_static_string(static_table[i].value)));
} }
} }
@ -208,8 +211,8 @@ void grpc_chttp2_hptbl_destroy(grpc_exec_ctx *exec_ctx,
gpr_free(tbl->ents); gpr_free(tbl->ents);
} }
grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
uint32_t tbl_index) { uint32_t tbl_index) {
/* Static table comes first, just return an entry from it */ /* Static table comes first, just return an entry from it */
if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) { if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) {
return tbl->static_ents[tbl_index - 1]; return tbl->static_ents[tbl_index - 1];
@ -222,14 +225,14 @@ grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
return tbl->ents[offset]; return tbl->ents[offset];
} }
/* Invalid entry: return error */ /* Invalid entry: return error */
return NULL; return GRPC_MDNULL;
} }
/* Evict one element from the table */ /* Evict one element from the table */
static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) { static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
grpc_mdelem *first_ent = tbl->ents[tbl->first_ent]; grpc_mdelem first_ent = tbl->ents[tbl->first_ent];
size_t elem_bytes = GRPC_SLICE_LENGTH(first_ent->key->slice) + size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(first_ent)) +
GRPC_SLICE_LENGTH(first_ent->value->slice) + GRPC_SLICE_LENGTH(GRPC_MDVALUE(first_ent)) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
GPR_ASSERT(elem_bytes <= tbl->mem_used); GPR_ASSERT(elem_bytes <= tbl->mem_used);
tbl->mem_used -= (uint32_t)elem_bytes; tbl->mem_used -= (uint32_t)elem_bytes;
@ -239,7 +242,7 @@ static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
} }
static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) { static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) {
grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap); grpc_mdelem *ents = gpr_malloc(sizeof(*ents) * new_cap);
uint32_t i; uint32_t i;
for (i = 0; i < tbl->num_ents; i++) { for (i = 0; i < tbl->num_ents; i++) {
@ -301,10 +304,10 @@ grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_exec_ctx *exec_ctx,
} }
grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx, grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { grpc_chttp2_hptbl *tbl, grpc_mdelem md) {
/* determine how many bytes of buffer this entry represents */ /* determine how many bytes of buffer this entry represents */
size_t elem_bytes = GRPC_SLICE_LENGTH(md->key->slice) + size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(md)) +
GRPC_SLICE_LENGTH(md->value->slice) + GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
if (tbl->current_table_bytes > tbl->max_bytes) { if (tbl->current_table_bytes > tbl->max_bytes) {
@ -352,16 +355,16 @@ grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx,
} }
grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find( grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
const grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { const grpc_chttp2_hptbl *tbl, grpc_mdelem md) {
grpc_chttp2_hptbl_find_result r = {0, 0}; grpc_chttp2_hptbl_find_result r = {0, 0};
uint32_t i; uint32_t i;
/* See if the string is in the static table */ /* See if the string is in the static table */
for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
grpc_mdelem *ent = tbl->static_ents[i]; grpc_mdelem ent = tbl->static_ents[i];
if (md->key != ent->key) continue; if (!grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDKEY(ent))) continue;
r.index = i + 1u; r.index = i + 1u;
r.has_value = md->value == ent->value; r.has_value = grpc_slice_eq(GRPC_MDVALUE(md), GRPC_MDVALUE(ent));
if (r.has_value) return r; if (r.has_value) return r;
} }
@ -369,10 +372,10 @@ grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
for (i = 0; i < tbl->num_ents; i++) { for (i = 0; i < tbl->num_ents; i++) {
uint32_t idx = uint32_t idx =
(uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY); (uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]; grpc_mdelem ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
if (md->key != ent->key) continue; if (!grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDKEY(ent))) continue;
r.index = idx; r.index = idx;
r.has_value = md->value == ent->value; r.has_value = grpc_slice_eq(GRPC_MDVALUE(md), GRPC_MDVALUE(ent));
if (r.has_value) return r; if (r.has_value) return r;
} }

@ -79,8 +79,8 @@ typedef struct {
/* a circular buffer of headers - this is stored in the opposite order to /* a circular buffer of headers - this is stored in the opposite order to
what hpack specifies, in order to simplify table management a little... what hpack specifies, in order to simplify table management a little...
meaning lookups need to SUBTRACT from the end position */ meaning lookups need to SUBTRACT from the end position */
grpc_mdelem **ents; grpc_mdelem *ents;
grpc_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY]; grpc_mdelem static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY];
} grpc_chttp2_hptbl; } grpc_chttp2_hptbl;
/* initialize a hpack table */ /* initialize a hpack table */
@ -94,12 +94,12 @@ grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_exec_ctx *exec_ctx,
uint32_t bytes); uint32_t bytes);
/* lookup a table entry based on its hpack index */ /* lookup a table entry based on its hpack index */
grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl, grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
uint32_t index); uint32_t index);
/* add a table entry to the index */ /* add a table entry to the index */
grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx, grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hptbl *tbl, grpc_chttp2_hptbl *tbl,
grpc_mdelem *md) GRPC_MUST_USE_RESULT; grpc_mdelem md) GRPC_MUST_USE_RESULT;
/* Find a key/value pair in the table... returns the index in the table of the /* Find a key/value pair in the table... returns the index in the table of the
most similar entry, or 0 if the value was not found */ most similar entry, or 0 if the value was not found */
typedef struct { typedef struct {
@ -107,6 +107,6 @@ typedef struct {
int has_value; int has_value;
} grpc_chttp2_hptbl_find_result; } grpc_chttp2_hptbl_find_result;
grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find( grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
const grpc_chttp2_hptbl *tbl, grpc_mdelem *md); const grpc_chttp2_hptbl *tbl, grpc_mdelem md);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_TABLE_H */

@ -57,7 +57,7 @@ void grpc_chttp2_incoming_metadata_buffer_destroy(
} }
void grpc_chttp2_incoming_metadata_buffer_add( void grpc_chttp2_incoming_metadata_buffer_add(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) { grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem) {
GPR_ASSERT(!buffer->published); GPR_ASSERT(!buffer->published);
if (buffer->capacity == buffer->count) { if (buffer->capacity == buffer->count) {
buffer->capacity = GPR_MAX(8, 2 * buffer->capacity); buffer->capacity = GPR_MAX(8, 2 * buffer->capacity);
@ -68,6 +68,19 @@ void grpc_chttp2_incoming_metadata_buffer_add(
buffer->size += GRPC_MDELEM_LENGTH(elem); buffer->size += GRPC_MDELEM_LENGTH(elem);
} }
void grpc_chttp2_incoming_metadata_buffer_replace_or_add(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_mdelem elem) {
for (size_t i = 0; i < buffer->count; i++) {
if (grpc_slice_eq(GRPC_MDKEY(buffer->elems[i].md), GRPC_MDKEY(elem))) {
GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md);
buffer->elems[i].md = elem;
return;
}
}
grpc_chttp2_incoming_metadata_buffer_add(buffer, elem);
}
void grpc_chttp2_incoming_metadata_buffer_set_deadline( void grpc_chttp2_incoming_metadata_buffer_set_deadline(
grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) { grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline) {
GPR_ASSERT(!buffer->published); GPR_ASSERT(!buffer->published);
@ -75,21 +88,20 @@ void grpc_chttp2_incoming_metadata_buffer_set_deadline(
} }
void grpc_chttp2_incoming_metadata_buffer_publish( void grpc_chttp2_incoming_metadata_buffer_publish(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) { grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_metadata_batch *batch) {
GPR_ASSERT(!buffer->published); GPR_ASSERT(!buffer->published);
buffer->published = 1; buffer->published = 1;
if (buffer->count > 0) { if (buffer->count > 0) {
size_t i; size_t i;
for (i = 1; i < buffer->count; i++) { for (i = 0; i < buffer->count; i++) {
buffer->elems[i].prev = &buffer->elems[i - 1]; /* TODO(ctiller): do something better here */
} if (!GRPC_LOG_IF_ERROR("grpc_chttp2_incoming_metadata_buffer_publish",
for (i = 0; i < buffer->count - 1; i++) { grpc_metadata_batch_link_tail(
buffer->elems[i].next = &buffer->elems[i + 1]; exec_ctx, batch, &buffer->elems[i]))) {
GRPC_MDELEM_UNREF(exec_ctx, buffer->elems[i].md);
}
} }
buffer->elems[0].prev = NULL;
buffer->elems[buffer->count - 1].next = NULL;
batch->list.head = &buffer->elems[0];
batch->list.tail = &buffer->elems[buffer->count - 1];
} else { } else {
batch->list.head = batch->list.tail = NULL; batch->list.head = batch->list.tail = NULL;
} }

@ -51,10 +51,14 @@ void grpc_chttp2_incoming_metadata_buffer_init(
void grpc_chttp2_incoming_metadata_buffer_destroy( void grpc_chttp2_incoming_metadata_buffer_destroy(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer); grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer);
void grpc_chttp2_incoming_metadata_buffer_publish( void grpc_chttp2_incoming_metadata_buffer_publish(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch); grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_metadata_batch *batch);
void grpc_chttp2_incoming_metadata_buffer_add( void grpc_chttp2_incoming_metadata_buffer_add(
grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem); grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem elem);
void grpc_chttp2_incoming_metadata_buffer_replace_or_add(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_metadata_buffer *buffer,
grpc_mdelem elem);
void grpc_chttp2_incoming_metadata_buffer_set_deadline( void grpc_chttp2_incoming_metadata_buffer_set_deadline(
grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline); grpc_chttp2_incoming_metadata_buffer *buffer, gpr_timespec deadline);

@ -618,8 +618,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
uint32_t stream_id, int64_t val1, int64_t val2); uint32_t stream_id, int64_t val1, int64_t val2);
void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_stream *stream, grpc_chttp2_stream *stream, grpc_error *error);
grpc_status_code status, grpc_slice *details);
void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx, void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, int close_reads, grpc_chttp2_stream *s, int close_reads,

@ -39,10 +39,11 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/transport/http2_errors.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/status_conversion.h"
#include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/timeout_encoding.h"
static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx, static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx,
@ -200,7 +201,7 @@ grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
return err; return err;
} }
if (t->incoming_frame_size == 0) { if (t->incoming_frame_size == 0) {
err = parse_frame_slice(exec_ctx, t, gpr_empty_slice(), 1); err = parse_frame_slice(exec_ctx, t, grpc_empty_slice(), 1);
if (err != GRPC_ERROR_NONE) { if (err != GRPC_ERROR_NONE) {
return err; return err;
} }
@ -335,7 +336,7 @@ static grpc_error *skip_parser(grpc_exec_ctx *exec_ctx, void *parser,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static void skip_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem *md) { static void skip_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem md) {
GRPC_MDELEM_UNREF(exec_ctx, md); GRPC_MDELEM_UNREF(exec_ctx, md);
} }
@ -432,7 +433,7 @@ error_handler:
} }
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id, &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR, GRPC_HTTP2_PROTOCOL_ERROR,
&s->stats.outgoing)); &s->stats.outgoing));
return init_skip_frame_parser(exec_ctx, t, 0); return init_skip_frame_parser(exec_ctx, t, 0);
} else { } else {
@ -443,7 +444,7 @@ error_handler:
static void free_timeout(void *p) { gpr_free(p); } static void free_timeout(void *p) { gpr_free(p); }
static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp, static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
grpc_mdelem *md) { grpc_mdelem md) {
grpc_chttp2_transport *t = tp; grpc_chttp2_transport *t = tp;
grpc_chttp2_stream *s = t->incoming_stream; grpc_chttp2_stream *s = t->incoming_stream;
@ -451,32 +452,42 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
GPR_ASSERT(s != NULL); GPR_ASSERT(s != NULL);
GRPC_CHTTP2_IF_TRACING(gpr_log( if (grpc_http_trace) {
GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR", char *key = grpc_slice_to_c_string(GRPC_MDKEY(md));
grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value))); char *value =
grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id,
t->is_client ? "CLI" : "SVR", key, value);
gpr_free(key);
gpr_free(value);
}
if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) { if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
!grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
/* TODO(ctiller): check for a status like " 0" */ /* TODO(ctiller): check for a status like " 0" */
s->seen_error = true; s->seen_error = true;
} }
if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) { if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout); gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
if (!cached_timeout) { gpr_timespec timeout;
if (cached_timeout == NULL) {
/* not already parsed: parse it now, and store the result away */ /* not already parsed: parse it now, and store the result away */
cached_timeout = gpr_malloc(sizeof(gpr_timespec)); cached_timeout = gpr_malloc(sizeof(gpr_timespec));
if (!grpc_http2_decode_timeout(grpc_mdstr_as_c_string(md->value), if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), cached_timeout)) {
cached_timeout)) { char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
grpc_mdstr_as_c_string(md->value)); gpr_free(val);
*cached_timeout = gpr_inf_future(GPR_TIMESPAN); *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
} }
cached_timeout = timeout = *cached_timeout;
grpc_mdelem_set_user_data(md, free_timeout, cached_timeout); grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
} else {
timeout = *cached_timeout;
} }
grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer_set_deadline(
&s->metadata_buffer[0], &s->metadata_buffer[0],
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout)); gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), timeout));
GRPC_MDELEM_UNREF(exec_ctx, md); GRPC_MDELEM_UNREF(exec_ctx, md);
} else { } else {
const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md); const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
@ -505,7 +516,7 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
} }
static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp, static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
grpc_mdelem *md) { grpc_mdelem md) {
grpc_chttp2_transport *t = tp; grpc_chttp2_transport *t = tp;
grpc_chttp2_stream *s = t->incoming_stream; grpc_chttp2_stream *s = t->incoming_stream;
@ -513,11 +524,18 @@ static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
GPR_ASSERT(s != NULL); GPR_ASSERT(s != NULL);
GRPC_CHTTP2_IF_TRACING(gpr_log( if (grpc_http_trace) {
GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR", char *key = grpc_slice_to_c_string(GRPC_MDKEY(md));
grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value))); char *value =
grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id,
t->is_client ? "CLI" : "SVR", key, value);
gpr_free(key);
gpr_free(value);
}
if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) { if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
!grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
/* TODO(ctiller): check for a status like " 0" */ /* TODO(ctiller): check for a status like " 0" */
s->seen_error = true; s->seen_error = true;
} }
@ -733,14 +751,13 @@ static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx,
if (grpc_http_trace) { if (grpc_http_trace) {
const char *msg = grpc_error_string(err); const char *msg = grpc_error_string(err);
gpr_log(GPR_ERROR, "%s", msg); gpr_log(GPR_ERROR, "%s", msg);
grpc_error_free_string(msg);
} }
grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
if (s) { if (s) {
s->forced_close_error = err; s->forced_close_error = err;
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id, &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR, GRPC_HTTP2_PROTOCOL_ERROR,
&s->stats.outgoing)); &s->stats.outgoing));
} else { } else {
GRPC_ERROR_UNREF(err); GRPC_ERROR_UNREF(err);

@ -37,9 +37,9 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/http2_errors.h"
static void add_to_write_list(grpc_chttp2_write_cb **list, static void add_to_write_list(grpc_chttp2_write_cb **list,
grpc_chttp2_write_cb *cb) { grpc_chttp2_write_cb *cb) {
@ -74,6 +74,15 @@ static void update_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static bool stream_ref_if_not_destroyed(gpr_refcount *r) {
gpr_atm count;
do {
count = gpr_atm_acq_load(&r->count);
if (count == 0) return false;
} while (!gpr_atm_rel_cas(&r->count, count, count + 1));
return true;
}
bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) { grpc_chttp2_transport *t) {
grpc_chttp2_stream *s; grpc_chttp2_stream *s;
@ -101,8 +110,11 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
if (t->outgoing_window > 0) { if (t->outgoing_window > 0) {
while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) { while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) {
grpc_chttp2_become_writable(exec_ctx, t, s, false, if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s) &&
"transport.read_flow_control"); stream_ref_if_not_destroyed(&s->refcount->refs)) {
grpc_chttp2_initiate_write(exec_ctx, t, false,
"transport.read_flow_control");
}
} }
} }
@ -164,7 +176,7 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
s->sent_trailing_metadata = true; s->sent_trailing_metadata = true;
if (!t->is_client && !s->read_closed) { if (!t->is_client && !s->read_closed) {
grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_rst_stream_create( grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_rst_stream_create(
s->id, GRPC_CHTTP2_NO_ERROR, s->id, GRPC_HTTP2_NO_ERROR,
&s->stats.outgoing)); &s->stats.outgoing));
} }
} }
@ -197,7 +209,7 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
if (!t->is_client && !s->read_closed) { if (!t->is_client && !s->read_closed) {
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->outbuf, grpc_chttp2_rst_stream_create( &t->outbuf, grpc_chttp2_rst_stream_create(
s->id, GRPC_CHTTP2_NO_ERROR, &s->stats.outgoing)); s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing));
} }
now_writing = true; now_writing = true;
} }

@ -44,6 +44,8 @@
#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
#include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
@ -437,9 +439,11 @@ static void on_response_headers_received(
for (size_t i = 0; i < headers->count; i++) { for (size_t i = 0; i < headers->count; i++) {
grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer_add(
&s->state.rs.initial_metadata, &s->state.rs.initial_metadata,
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_slices(
&exec_ctx, grpc_mdstr_from_string(headers->headers[i].key), &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(
grpc_mdstr_from_string(headers->headers[i].value))); headers->headers[i].key)),
grpc_slice_intern(
grpc_slice_from_static_string(headers->headers[i].value))));
} }
s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true; s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true;
if (!(s->state.state_op_done[OP_CANCEL_ERROR] || if (!(s->state.state_op_done[OP_CANCEL_ERROR] ||
@ -534,9 +538,11 @@ static void on_response_trailers_received(
trailers->headers[i].value); trailers->headers[i].value);
grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer_add(
&s->state.rs.trailing_metadata, &s->state.rs.trailing_metadata,
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_slices(
&exec_ctx, grpc_mdstr_from_string(trailers->headers[i].key), &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(
grpc_mdstr_from_string(trailers->headers[i].value))); trailers->headers[i].key)),
grpc_slice_intern(
grpc_slice_from_static_string(trailers->headers[i].value))));
s->state.rs.trailing_metadata_valid = true; s->state.rs.trailing_metadata_valid = true;
if (0 == strcmp(trailers->headers[i].key, "grpc-status") && if (0 == strcmp(trailers->headers[i].key, "grpc-status") &&
0 != strcmp(trailers->headers[i].value, "0")) { 0 != strcmp(trailers->headers[i].value, "0")) {
@ -616,27 +622,33 @@ static void convert_metadata_to_cronet_headers(
curr = head; curr = head;
size_t num_headers = 0; size_t num_headers = 0;
while (num_headers < num_headers_available) { while (num_headers < num_headers_available) {
grpc_mdelem *mdelem = curr->md; grpc_mdelem mdelem = curr->md;
curr = curr->next; curr = curr->next;
const char *key = grpc_mdstr_as_c_string(mdelem->key); char *key = grpc_slice_to_c_string(GRPC_MDKEY(mdelem));
const char *value = grpc_mdstr_as_c_string(mdelem->value); char *value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem));
if (mdelem->key == GRPC_MDSTR_SCHEME || if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_SCHEME) ||
mdelem->key == GRPC_MDSTR_AUTHORITY) { grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_AUTHORITY)) {
/* Cronet populates these fields on its own */ /* Cronet populates these fields on its own */
gpr_free(key);
gpr_free(value);
continue; continue;
} }
if (mdelem->key == GRPC_MDSTR_METHOD) { if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_METHOD)) {
if (mdelem->value == GRPC_MDSTR_PUT) { if (grpc_slice_eq(GRPC_MDVALUE(mdelem), GRPC_MDSTR_PUT)) {
*method = "PUT"; *method = "PUT";
} else { } else {
/* POST method in default*/ /* POST method in default*/
*method = "POST"; *method = "POST";
} }
gpr_free(key);
gpr_free(value);
continue; continue;
} }
if (mdelem->key == GRPC_MDSTR_PATH) { if (grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_PATH)) {
/* Create URL by appending :path value to the hostname */ /* Create URL by appending :path value to the hostname */
gpr_asprintf(pp_url, "https://%s%s", host, value); gpr_asprintf(pp_url, "https://%s%s", host, value);
gpr_free(key);
gpr_free(value);
continue; continue;
} }
CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value); CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value);
@ -662,7 +674,7 @@ static int parse_grpc_header(const uint8_t *data) {
static bool header_has_authority(grpc_linked_mdelem *head) { static bool header_has_authority(grpc_linked_mdelem *head) {
while (head != NULL) { while (head != NULL) {
if (head->md->key == GRPC_MDSTR_AUTHORITY) { if (grpc_slice_eq(GRPC_MDKEY(head->md), GRPC_MDSTR_AUTHORITY)) {
return true; return true;
} }
head = head->next; head = head->next;
@ -843,6 +855,12 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
s->header_array.capacity = s->header_array.count; s->header_array.capacity = s->header_array.count;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url); CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url);
bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false); bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false);
unsigned int header_index;
for (header_index = 0; header_index < s->header_array.count;
header_index++) {
gpr_free((void *)s->header_array.headers[header_index].key);
gpr_free((void *)s->header_array.headers[header_index].value);
}
stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true; stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true;
result = ACTION_TAKEN_WITH_CALLBACK; result = ACTION_TAKEN_WITH_CALLBACK;
} else if (stream_op->recv_initial_metadata && } else if (stream_op->recv_initial_metadata &&
@ -857,7 +875,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} else { } else {
grpc_chttp2_incoming_metadata_buffer_publish( grpc_chttp2_incoming_metadata_buffer_publish(
&oas->s->state.rs.initial_metadata, stream_op->recv_initial_metadata); exec_ctx, &oas->s->state.rs.initial_metadata,
stream_op->recv_initial_metadata);
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready, grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} }
@ -1013,7 +1032,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas);
if (oas->s->state.rs.trailing_metadata_valid) { if (oas->s->state.rs.trailing_metadata_valid) {
grpc_chttp2_incoming_metadata_buffer_publish( grpc_chttp2_incoming_metadata_buffer_publish(
&oas->s->state.rs.trailing_metadata, exec_ctx, &oas->s->state.rs.trailing_metadata,
stream_op->recv_trailing_metadata); stream_op->recv_trailing_metadata);
stream_state->rs.trailing_metadata_valid = false; stream_state->rs.trailing_metadata_valid = false;
} }

@ -170,7 +170,7 @@ grpc_error *grpc_call_stack_init(
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
grpc_call_context_element *context, const void *transport_server_data, grpc_call_context_element *context, const void *transport_server_data,
grpc_mdstr *path, gpr_timespec start_time, gpr_timespec deadline, grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
grpc_call_stack *call_stack) { grpc_call_stack *call_stack) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
grpc_call_element_args args; grpc_call_element_args args;
@ -288,41 +288,10 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) {
sizeof(grpc_call_stack))); sizeof(grpc_call_stack)));
} }
static void destroy_op(grpc_exec_ctx *exec_ctx, void *op, grpc_error *error) { void grpc_call_element_signal_error(grpc_exec_ctx *exec_ctx,
gpr_free(op); grpc_call_element *elem,
} grpc_error *error) {
grpc_transport_stream_op *op = grpc_make_transport_stream_op(NULL);
void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx, op->cancel_error = error;
grpc_call_element *elem) {
grpc_transport_stream_op *op = gpr_malloc(sizeof(*op));
memset(op, 0, sizeof(*op));
op->cancel_error = GRPC_ERROR_CANCELLED;
op->on_complete =
grpc_closure_create(destroy_op, op, grpc_schedule_on_exec_ctx);
elem->filter->start_transport_stream_op(exec_ctx, elem, op);
}
void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_status_code status,
grpc_slice *optional_message) {
grpc_transport_stream_op *op = gpr_malloc(sizeof(*op));
memset(op, 0, sizeof(*op));
op->on_complete =
grpc_closure_create(destroy_op, op, grpc_schedule_on_exec_ctx);
grpc_transport_stream_op_add_cancellation_with_message(exec_ctx, op, status,
optional_message);
elem->filter->start_transport_stream_op(exec_ctx, elem, op);
}
void grpc_call_element_send_close_with_message(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_status_code status,
grpc_slice *optional_message) {
grpc_transport_stream_op *op = gpr_malloc(sizeof(*op));
memset(op, 0, sizeof(*op));
op->on_complete =
grpc_closure_create(destroy_op, op, grpc_schedule_on_exec_ctx);
grpc_transport_stream_op_add_close(exec_ctx, op, status, optional_message);
elem->filter->start_transport_stream_op(exec_ctx, elem, op); elem->filter->start_transport_stream_op(exec_ctx, elem, op);
} }

@ -81,7 +81,7 @@ typedef struct {
grpc_call_stack *call_stack; grpc_call_stack *call_stack;
const void *server_transport_data; const void *server_transport_data;
grpc_call_context_element *context; grpc_call_context_element *context;
grpc_mdstr *path; grpc_slice path;
gpr_timespec start_time; gpr_timespec start_time;
gpr_timespec deadline; gpr_timespec deadline;
} grpc_call_element_args; } grpc_call_element_args;
@ -238,7 +238,7 @@ grpc_error *grpc_call_stack_init(
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg,
grpc_call_context_element *context, const void *transport_server_data, grpc_call_context_element *context, const void *transport_server_data,
grpc_mdstr *path, gpr_timespec start_time, gpr_timespec deadline, grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
grpc_call_stack *call_stack); grpc_call_stack *call_stack);
/* Set a pollset or a pollset_set for a call stack: must occur before the first /* Set a pollset or a pollset_set for a call stack: must occur before the first
* op is started */ * op is started */
@ -299,18 +299,9 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem);
void grpc_call_log_op(char *file, int line, gpr_log_severity severity, void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
grpc_call_element *elem, grpc_transport_stream_op *op); grpc_call_element *elem, grpc_transport_stream_op *op);
void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx, void grpc_call_element_signal_error(grpc_exec_ctx *exec_ctx,
grpc_call_element *cur_elem); grpc_call_element *cur_elem,
grpc_error *error);
void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx,
grpc_call_element *cur_elem,
grpc_status_code status,
grpc_slice *optional_message);
void grpc_call_element_send_close_with_message(grpc_exec_ctx *exec_ctx,
grpc_call_element *cur_elem,
grpc_status_code status,
grpc_slice *optional_message);
extern int grpc_trace_channel; extern int grpc_trace_channel;

@ -45,6 +45,7 @@
#include "src/core/lib/compression/message_compress.h" #include "src/core/lib/compression/message_compress.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
@ -80,39 +81,6 @@ typedef struct channel_data {
uint32_t supported_compression_algorithms; uint32_t supported_compression_algorithms;
} channel_data; } channel_data;
/** For each \a md element from the incoming metadata, filter out the entry for
* "grpc-encoding", using its value to populate the call data's
* compression_algorithm field. */
static grpc_mdelem *compression_md_filter(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
const char *md_c_str = grpc_mdstr_as_c_string(md->value);
if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
&calld->compression_algorithm)) {
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (unknown). Ignoring.",
md_c_str);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
}
if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
calld->compression_algorithm)) {
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (previously disabled). "
"Ignoring.",
md_c_str);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
}
calld->has_compression_algorithm = 1;
return NULL;
}
return md;
}
static int skip_compression(grpc_call_element *elem, uint32_t flags) { static int skip_compression(grpc_call_element *elem, uint32_t flags) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data; channel_data *channeld = elem->channel_data;
@ -131,32 +99,65 @@ static int skip_compression(grpc_call_element *elem, uint32_t flags) {
} }
/** Filter initial metadata */ /** Filter initial metadata */
static void process_send_initial_metadata( static grpc_error *process_send_initial_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_metadata_batch *initial_metadata) GRPC_MUST_USE_RESULT;
static grpc_error *process_send_initial_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_metadata_batch *initial_metadata) { grpc_metadata_batch *initial_metadata) {
grpc_error *error;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data; channel_data *channeld = elem->channel_data;
/* Parse incoming request for compression. If any, it'll be available /* Parse incoming request for compression. If any, it'll be available
* at calld->compression_algorithm */ * at calld->compression_algorithm */
grpc_metadata_batch_filter(exec_ctx, initial_metadata, compression_md_filter, if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) {
elem); grpc_mdelem md =
if (!calld->has_compression_algorithm) { initial_metadata->idx.named.grpc_internal_encoding_request->md;
if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
&calld->compression_algorithm)) {
char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
gpr_free(val);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
}
if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
calld->compression_algorithm)) {
char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (previously disabled). "
"Ignoring.",
val);
gpr_free(val);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
}
calld->has_compression_algorithm = 1;
grpc_metadata_batch_remove(
exec_ctx, initial_metadata,
initial_metadata->idx.named.grpc_internal_encoding_request);
} else {
/* If no algorithm was found in the metadata and we aren't /* If no algorithm was found in the metadata and we aren't
* exceptionally skipping compression, fall back to the channel * exceptionally skipping compression, fall back to the channel
* default */ * default */
calld->compression_algorithm = channeld->default_compression_algorithm; calld->compression_algorithm = channeld->default_compression_algorithm;
calld->has_compression_algorithm = 1; /* GPR_TRUE */ calld->has_compression_algorithm = 1; /* GPR_TRUE */
} }
/* hint compression algorithm */ /* hint compression algorithm */
grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
initial_metadata, &calld->compression_algorithm_storage, exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
grpc_compression_encoding_mdelem(calld->compression_algorithm)); grpc_compression_encoding_mdelem(calld->compression_algorithm));
if (error != GRPC_ERROR_NONE) return error;
/* convey supported compression algorithms */ /* convey supported compression algorithms */
grpc_metadata_batch_add_tail(initial_metadata, error = grpc_metadata_batch_add_tail(
&calld->accept_encoding_storage, exec_ctx, initial_metadata, &calld->accept_encoding_storage,
GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS( GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
channeld->supported_compression_algorithms)); channeld->supported_compression_algorithms));
return error;
} }
static void continue_send_message(grpc_exec_ctx *exec_ctx, static void continue_send_message(grpc_exec_ctx *exec_ctx,
@ -247,7 +248,12 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
GPR_TIMER_BEGIN("compress_start_transport_stream_op", 0); GPR_TIMER_BEGIN("compress_start_transport_stream_op", 0);
if (op->send_initial_metadata) { if (op->send_initial_metadata) {
process_send_initial_metadata(exec_ctx, elem, op->send_initial_metadata); grpc_error *error = process_send_initial_metadata(
exec_ctx, elem, op->send_initial_metadata);
if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
return;
}
} }
if (op->send_message != NULL && if (op->send_message != NULL &&
!skip_compression(elem, op->send_message->flags)) { !skip_compression(elem, op->send_message->flags)) {

@ -56,10 +56,11 @@ static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg,
deadline_state->timer_pending = false; deadline_state->timer_pending = false;
gpr_mu_unlock(&deadline_state->timer_mu); gpr_mu_unlock(&deadline_state->timer_mu);
if (error != GRPC_ERROR_CANCELLED) { if (error != GRPC_ERROR_CANCELLED) {
grpc_slice msg = grpc_slice_from_static_string("Deadline Exceeded"); grpc_call_element_signal_error(
grpc_call_element_send_cancel_with_message( exec_ctx, elem,
exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, &msg); grpc_error_set_int(GRPC_ERROR_CREATE("Deadline Exceeded"),
grpc_slice_unref_internal(exec_ctx, msg); GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_DEADLINE_EXCEEDED));
} }
GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer");
} }
@ -196,8 +197,7 @@ void grpc_deadline_state_client_start_transport_stream_op(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
grpc_transport_stream_op* op) { grpc_transport_stream_op* op) {
grpc_deadline_state* deadline_state = elem->call_data; grpc_deadline_state* deadline_state = elem->call_data;
if (op->cancel_error != GRPC_ERROR_NONE || if (op->cancel_error != GRPC_ERROR_NONE) {
op->close_error != GRPC_ERROR_NONE) {
cancel_timer_if_needed(exec_ctx, deadline_state); cancel_timer_if_needed(exec_ctx, deadline_state);
} else { } else {
// Make sure we know when the call is complete, so that we can cancel // Make sure we know when the call is complete, so that we can cancel
@ -285,8 +285,7 @@ static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem, grpc_call_element* elem,
grpc_transport_stream_op* op) { grpc_transport_stream_op* op) {
server_call_data* calld = elem->call_data; server_call_data* calld = elem->call_data;
if (op->cancel_error != GRPC_ERROR_NONE || if (op->cancel_error != GRPC_ERROR_NONE) {
op->close_error != GRPC_ERROR_NONE) {
cancel_timer_if_needed(exec_ctx, &calld->base.deadline_state); cancel_timer_if_needed(exec_ctx, &calld->base.deadline_state);
} else { } else {
// If we're receiving initial metadata, we need to get the deadline // If we're receiving initial metadata, we need to get the deadline

@ -55,8 +55,8 @@ void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx,
} }
void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
grpc_handshaker* handshaker) { grpc_handshaker* handshaker, grpc_error* why) {
handshaker->vtable->shutdown(exec_ctx, handshaker); handshaker->vtable->shutdown(exec_ctx, handshaker, why);
} }
void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx,
@ -141,14 +141,17 @@ void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx,
} }
void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx,
grpc_handshake_manager* mgr) { grpc_handshake_manager* mgr,
grpc_error* why) {
gpr_mu_lock(&mgr->mu); gpr_mu_lock(&mgr->mu);
// Shutdown the handshaker that's currently in progress, if any. // Shutdown the handshaker that's currently in progress, if any.
if (!mgr->shutdown && mgr->index > 0) { if (!mgr->shutdown && mgr->index > 0) {
mgr->shutdown = true; mgr->shutdown = true;
grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[mgr->index - 1]); grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[mgr->index - 1],
GRPC_ERROR_REF(why));
} }
gpr_mu_unlock(&mgr->mu); gpr_mu_unlock(&mgr->mu);
GRPC_ERROR_UNREF(why);
} }
// Helper function to call either the next handshaker or the // Helper function to call either the next handshaker or the
@ -197,7 +200,8 @@ static void call_next_handshaker(grpc_exec_ctx* exec_ctx, void* arg,
static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
grpc_handshake_manager* mgr = arg; grpc_handshake_manager* mgr = arg;
if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled. if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled.
grpc_handshake_manager_shutdown(exec_ctx, mgr); grpc_handshake_manager_shutdown(exec_ctx, mgr,
GRPC_ERROR_CREATE("Handshake timed out"));
} }
grpc_handshake_manager_unref(exec_ctx, mgr); grpc_handshake_manager_unref(exec_ctx, mgr);
} }

@ -86,7 +86,8 @@ typedef struct {
/// Shuts down the handshaker (e.g., to clean up when the operation is /// Shuts down the handshaker (e.g., to clean up when the operation is
/// aborted in the middle). /// aborted in the middle).
void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker,
grpc_error* why);
/// Performs handshaking, modifying \a args as needed (e.g., to /// Performs handshaking, modifying \a args as needed (e.g., to
/// replace \a endpoint with a wrapped endpoint). /// replace \a endpoint with a wrapped endpoint).
@ -111,7 +112,7 @@ void grpc_handshaker_init(const grpc_handshaker_vtable* vtable,
void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx, void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx,
grpc_handshaker* handshaker); grpc_handshaker* handshaker);
void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
grpc_handshaker* handshaker); grpc_handshaker* handshaker, grpc_error* why);
void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx,
grpc_handshaker* handshaker, grpc_handshaker* handshaker,
grpc_tcp_server_acceptor* acceptor, grpc_tcp_server_acceptor* acceptor,
@ -141,7 +142,8 @@ void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx,
/// The caller must still call grpc_handshake_manager_destroy() after /// The caller must still call grpc_handshake_manager_destroy() after
/// calling this function. /// calling this function.
void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx,
grpc_handshake_manager* mgr); grpc_handshake_manager* mgr,
grpc_error* why);
/// Invokes handshakers in the order they were added. /// Invokes handshakers in the order they were added.
/// Takes ownership of \a endpoint, and then passes that ownership to /// Takes ownership of \a endpoint, and then passes that ownership to

@ -38,6 +38,7 @@
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/transport_impl.h" #include "src/core/lib/transport/transport_impl.h"
@ -88,77 +89,104 @@ typedef struct call_data {
} call_data; } call_data;
typedef struct channel_data { typedef struct channel_data {
grpc_mdelem *static_scheme; grpc_mdelem static_scheme;
grpc_mdelem *user_agent; grpc_mdelem user_agent;
size_t max_payload_size_for_get; size_t max_payload_size_for_get;
} channel_data; } channel_data;
static grpc_mdelem *client_recv_filter(grpc_exec_ctx *exec_ctx, void *user_data, static grpc_error *client_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
grpc_mdelem *md) { grpc_call_element *elem,
grpc_call_element *elem = user_data; grpc_metadata_batch *b) {
if (md == GRPC_MDELEM_STATUS_200) { if (b->idx.named.status != NULL) {
return NULL; if (grpc_mdelem_eq(b->idx.named.status->md, GRPC_MDELEM_STATUS_200)) {
} else if (md->key == GRPC_MDSTR_STATUS) { grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.status);
char *message_string;
gpr_asprintf(&message_string, "Received http2 header with status: %s",
grpc_mdstr_as_c_string(md->value));
grpc_slice message = grpc_slice_from_copied_string(message_string);
gpr_free(message_string);
grpc_call_element_send_close_with_message(exec_ctx, elem,
GRPC_STATUS_CANCELLED, &message);
return NULL;
} else if (md->key == GRPC_MDSTR_GRPC_MESSAGE) {
grpc_slice pct_decoded_msg =
grpc_permissive_percent_decode_slice(md->value->slice);
if (grpc_slice_is_equivalent(pct_decoded_msg, md->value->slice)) {
grpc_slice_unref_internal(exec_ctx, pct_decoded_msg);
return md;
} else { } else {
return grpc_mdelem_from_metadata_strings( char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md),
exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, GPR_DUMP_ASCII);
grpc_mdstr_from_slice(exec_ctx, pct_decoded_msg)); char *msg;
gpr_asprintf(&msg, "Received http2 header with status: %s", val);
grpc_error *e = grpc_error_set_str(
grpc_error_set_int(
grpc_error_set_str(
GRPC_ERROR_CREATE(
"Received http2 :status header with non-200 OK status"),
GRPC_ERROR_STR_VALUE, val),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED),
GRPC_ERROR_STR_GRPC_MESSAGE, msg);
gpr_free(val);
gpr_free(msg);
return e;
} }
} else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) { }
return NULL;
} else if (md->key == GRPC_MDSTR_CONTENT_TYPE) { if (b->idx.named.grpc_message != NULL) {
const char *value_str = grpc_mdstr_as_c_string(md->value); grpc_slice pct_decoded_msg = grpc_permissive_percent_decode_slice(
if (strncmp(value_str, EXPECTED_CONTENT_TYPE, GRPC_MDVALUE(b->idx.named.grpc_message->md));
EXPECTED_CONTENT_TYPE_LENGTH) == 0 && if (grpc_slice_is_equivalent(pct_decoded_msg,
(value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' || GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) { grpc_slice_unref_internal(exec_ctx, pct_decoded_msg);
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
as +proto or +json, or at least stashing them if we see them. */
/* TODO(klempner): Should we be surfacing this to application code? */
} else { } else {
/* TODO(klempner): We're currently allowing this, but we shouldn't grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message,
see it without a proxy so log for now. */ pct_decoded_msg);
gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str);
} }
return NULL;
} }
return md;
if (b->idx.named.content_type != NULL) {
if (!grpc_mdelem_eq(b->idx.named.content_type->md,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md),
EXPECTED_CONTENT_TYPE,
EXPECTED_CONTENT_TYPE_LENGTH) &&
(GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
'+' ||
GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
';')) {
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
as +proto or +json, or at least stashing them if we see them. */
/* TODO(klempner): Should we be surfacing this to application code? */
} else {
/* TODO(klempner): We're currently allowing this, but we shouldn't
see it without a proxy so log for now. */
char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md),
GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
gpr_free(val);
}
}
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type);
}
return GRPC_ERROR_NONE;
} }
static void hc_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx, static void hc_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_error *error) { void *user_data, grpc_error *error) {
grpc_call_element *elem = user_data; grpc_call_element *elem = user_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata, if (error == GRPC_ERROR_NONE) {
client_recv_filter, elem); error = client_filter_incoming_metadata(exec_ctx, elem,
grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata, calld->recv_initial_metadata);
GRPC_ERROR_REF(error)); } else {
GRPC_ERROR_REF(error);
}
grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata, error);
} }
static void hc_on_recv_trailing_metadata(grpc_exec_ctx *exec_ctx, static void hc_on_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_error *error) { void *user_data, grpc_error *error) {
grpc_call_element *elem = user_data; grpc_call_element *elem = user_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_metadata_batch_filter(exec_ctx, calld->recv_trailing_metadata, if (error == GRPC_ERROR_NONE) {
client_recv_filter, elem); error = client_filter_incoming_metadata(exec_ctx, elem,
grpc_closure_run(exec_ctx, calld->on_done_recv_trailing_metadata, calld->recv_trailing_metadata);
GRPC_ERROR_REF(error)); } else {
GRPC_ERROR_REF(error);
}
grpc_closure_run(exec_ctx, calld->on_done_recv_trailing_metadata, error);
} }
static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data, static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
@ -179,15 +207,12 @@ static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error); calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error);
} }
static grpc_mdelem *client_strip_filter(grpc_exec_ctx *exec_ctx, static void remove_if_present(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_mdelem *md) { grpc_metadata_batch *batch,
/* eat the things we'd like to set ourselves */ grpc_metadata_batch_callouts_index idx) {
if (md->key == GRPC_MDSTR_METHOD) return NULL; if (batch->idx.array[idx] != NULL) {
if (md->key == GRPC_MDSTR_SCHEME) return NULL; grpc_metadata_batch_remove(exec_ctx, batch, batch->idx.array[idx]);
if (md->key == GRPC_MDSTR_TE) return NULL; }
if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL;
if (md->key == GRPC_MDSTR_USER_AGENT) return NULL;
return md;
} }
static void continue_send_message(grpc_exec_ctx *exec_ctx, static void continue_send_message(grpc_exec_ctx *exec_ctx,
@ -226,18 +251,20 @@ static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
} }
} }
static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static grpc_error *hc_mutate_op(grpc_exec_ctx *exec_ctx,
grpc_transport_stream_op *op) { grpc_call_element *elem,
grpc_transport_stream_op *op) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data; channel_data *channeld = elem->channel_data;
grpc_error *error;
if (op->send_initial_metadata != NULL) { if (op->send_initial_metadata != NULL) {
/* Decide which HTTP VERB to use. We use GET if the request is marked /* Decide which HTTP VERB to use. We use GET if the request is marked
cacheable, and the operation contains both initial metadata and send cacheable, and the operation contains both initial metadata and send
message, and the payload is below the size threshold, and all the data message, and the payload is below the size threshold, and all the data
for this request is immediately available. */ for this request is immediately available. */
grpc_mdelem *method = GRPC_MDELEM_METHOD_POST; grpc_mdelem method = GRPC_MDELEM_METHOD_POST;
if ((op->send_initial_metadata_flags & if ((op->send_initial_metadata_flags &
GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) && GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) &&
op->send_message != NULL && op->send_message != NULL &&
@ -254,7 +281,7 @@ static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
} }
/* Attempt to read the data from send_message and create a header field. */ /* Attempt to read the data from send_message and create a header field. */
if (method == GRPC_MDELEM_METHOD_GET) { if (grpc_mdelem_eq(method, GRPC_MDELEM_METHOD_GET)) {
/* allocate memory to hold the entire payload */ /* allocate memory to hold the entire payload */
calld->payload_bytes = gpr_malloc(op->send_message->length); calld->payload_bytes = gpr_malloc(op->send_message->length);
@ -267,12 +294,14 @@ static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (calld->send_message_blocked == false) { if (calld->send_message_blocked == false) {
/* when all the send_message data is available, then create a MDELEM and /* when all the send_message data is available, then create a MDELEM and
append to headers */ append to headers */
grpc_mdelem *payload_bin = grpc_mdelem_from_metadata_strings( grpc_mdelem payload_bin = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN, exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN,
grpc_mdstr_from_buffer(calld->payload_bytes, grpc_slice_from_copied_buffer((const char *)calld->payload_bytes,
op->send_message->length)); op->send_message->length));
grpc_metadata_batch_add_tail(op->send_initial_metadata, error =
&calld->payload_bin, payload_bin); grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
&calld->payload_bin, payload_bin);
if (error != GRPC_ERROR_NONE) return error;
calld->on_complete = op->on_complete; calld->on_complete = op->on_complete;
op->on_complete = &calld->hc_on_complete; op->on_complete = &calld->hc_on_complete;
op->send_message = NULL; op->send_message = NULL;
@ -285,21 +314,35 @@ static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
} }
} }
grpc_metadata_batch_filter(exec_ctx, op->send_initial_metadata, remove_if_present(exec_ctx, op->send_initial_metadata, GRPC_BATCH_METHOD);
client_strip_filter, elem); remove_if_present(exec_ctx, op->send_initial_metadata, GRPC_BATCH_SCHEME);
remove_if_present(exec_ctx, op->send_initial_metadata, GRPC_BATCH_TE);
remove_if_present(exec_ctx, op->send_initial_metadata,
GRPC_BATCH_CONTENT_TYPE);
remove_if_present(exec_ctx, op->send_initial_metadata,
GRPC_BATCH_USER_AGENT);
/* Send : prefixed headers, which have to be before any application /* Send : prefixed headers, which have to be before any application
layer headers. */ layer headers. */
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method, error = grpc_metadata_batch_add_head(exec_ctx, op->send_initial_metadata,
method); &calld->method, method);
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme, if (error != GRPC_ERROR_NONE) return error;
channeld->static_scheme); error =
grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers, grpc_metadata_batch_add_head(exec_ctx, op->send_initial_metadata,
GRPC_MDELEM_TE_TRAILERS); &calld->scheme, channeld->static_scheme);
grpc_metadata_batch_add_tail( if (error != GRPC_ERROR_NONE) return error;
op->send_initial_metadata, &calld->content_type, error = grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
&calld->te_trailers,
GRPC_MDELEM_TE_TRAILERS);
if (error != GRPC_ERROR_NONE) return error;
error = grpc_metadata_batch_add_tail(
exec_ctx, op->send_initial_metadata, &calld->content_type,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent, if (error != GRPC_ERROR_NONE) return error;
GRPC_MDELEM_REF(channeld->user_agent)); error = grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
&calld->user_agent,
GRPC_MDELEM_REF(channeld->user_agent));
if (error != GRPC_ERROR_NONE) return error;
} }
if (op->recv_initial_metadata != NULL) { if (op->recv_initial_metadata != NULL) {
@ -315,6 +358,8 @@ static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
calld->on_done_recv_trailing_metadata = op->on_complete; calld->on_done_recv_trailing_metadata = op->on_complete;
op->on_complete = &calld->hc_on_recv_trailing_metadata; op->on_complete = &calld->hc_on_recv_trailing_metadata;
} }
return GRPC_ERROR_NONE;
} }
static void hc_start_transport_op(grpc_exec_ctx *exec_ctx, static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
@ -322,15 +367,20 @@ static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_transport_stream_op *op) { grpc_transport_stream_op *op) {
GPR_TIMER_BEGIN("hc_start_transport_op", 0); GPR_TIMER_BEGIN("hc_start_transport_op", 0);
GRPC_CALL_LOG_OP(GPR_INFO, elem, op); GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
hc_mutate_op(exec_ctx, elem, op); grpc_error *error = hc_mutate_op(exec_ctx, elem, op);
GPR_TIMER_END("hc_start_transport_op", 0); if (error != GRPC_ERROR_NONE) {
call_data *calld = elem->call_data; grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
if (op->send_message != NULL && calld->send_message_blocked) {
/* Don't forward the op. send_message contains slices that aren't ready
yet. The call will be forwarded by the op_complete of slice read call. */
} else { } else {
grpc_call_next_op(exec_ctx, elem, op); call_data *calld = elem->call_data;
if (op->send_message != NULL && calld->send_message_blocked) {
/* Don't forward the op. send_message contains slices that aren't ready
yet. The call will be forwarded by the op_complete of slice read call.
*/
} else {
grpc_call_next_op(exec_ctx, elem, op);
}
} }
GPR_TIMER_END("hc_start_transport_op", 0);
} }
/* Constructor for call_data */ /* Constructor for call_data */
@ -367,18 +417,18 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices);
} }
static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) { static grpc_mdelem scheme_from_args(const grpc_channel_args *args) {
unsigned i; unsigned i;
size_t j; size_t j;
grpc_mdelem *valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP, grpc_mdelem valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP,
GRPC_MDELEM_SCHEME_HTTPS}; GRPC_MDELEM_SCHEME_HTTPS};
if (args != NULL) { if (args != NULL) {
for (i = 0; i < args->num_args; ++i) { for (i = 0; i < args->num_args; ++i) {
if (args->args[i].type == GRPC_ARG_STRING && if (args->args[i].type == GRPC_ARG_STRING &&
strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) { strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) {
for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) { for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) {
if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value), if (0 == grpc_slice_str_cmp(GRPC_MDVALUE(valid_schemes[j]),
args->args[i].value.string)) { args->args[i].value.string)) {
return valid_schemes[j]; return valid_schemes[j];
} }
} }
@ -404,13 +454,13 @@ static size_t max_payload_size_from_args(const grpc_channel_args *args) {
return kMaxPayloadSizeForGet; return kMaxPayloadSizeForGet;
} }
static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args, static grpc_slice user_agent_from_args(const grpc_channel_args *args,
const char *transport_name) { const char *transport_name) {
gpr_strvec v; gpr_strvec v;
size_t i; size_t i;
int is_first = 1; int is_first = 1;
char *tmp; char *tmp;
grpc_mdstr *result; grpc_slice result;
gpr_strvec_init(&v); gpr_strvec_init(&v);
@ -448,7 +498,7 @@ static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args,
tmp = gpr_strvec_flatten(&v, NULL); tmp = gpr_strvec_flatten(&v, NULL);
gpr_strvec_destroy(&v); gpr_strvec_destroy(&v);
result = grpc_mdstr_from_string(tmp); result = grpc_slice_intern(grpc_slice_from_static_string(tmp));
gpr_free(tmp); gpr_free(tmp);
return result; return result;
@ -464,7 +514,7 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
chand->static_scheme = scheme_from_args(args->channel_args); chand->static_scheme = scheme_from_args(args->channel_args);
chand->max_payload_size_for_get = chand->max_payload_size_for_get =
max_payload_size_from_args(args->channel_args); max_payload_size_from_args(args->channel_args);
chand->user_agent = grpc_mdelem_from_metadata_strings( chand->user_agent = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_USER_AGENT, exec_ctx, GRPC_MDSTR_USER_AGENT,
user_agent_from_args(args->channel_args, user_agent_from_args(args->channel_args,
args->optional_transport->vtable->name)); args->optional_transport->vtable->name));

@ -39,6 +39,7 @@
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE "application/grpc"
@ -47,18 +48,13 @@
extern int grpc_http_trace; extern int grpc_http_trace;
typedef struct call_data { typedef struct call_data {
uint8_t seen_path;
uint8_t seen_method;
uint8_t sent_status;
uint8_t seen_scheme;
uint8_t seen_te_trailers;
uint8_t seen_authority;
uint8_t seen_payload_bin;
grpc_linked_mdelem status; grpc_linked_mdelem status;
grpc_linked_mdelem content_type; grpc_linked_mdelem content_type;
/* did this request come with payload-bin */
bool seen_payload_bin;
/* flag to ensure payload_bin is delivered only once */ /* flag to ensure payload_bin is delivered only once */
uint8_t payload_bin_delivered; bool payload_bin_delivered;
grpc_metadata_batch *recv_initial_metadata; grpc_metadata_batch *recv_initial_metadata;
bool *recv_idempotent_request; bool *recv_idempotent_request;
@ -83,109 +79,152 @@ typedef struct call_data {
typedef struct channel_data { uint8_t unused; } channel_data; typedef struct channel_data { uint8_t unused; } channel_data;
static grpc_mdelem *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx, static grpc_error *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_call_element *elem,
grpc_mdelem *md) { grpc_metadata_batch *b) {
if (md->key == GRPC_MDSTR_GRPC_MESSAGE) { if (b->idx.named.grpc_message != NULL) {
grpc_slice pct_encoded_msg = grpc_percent_encode_slice( grpc_slice pct_encoded_msg = grpc_percent_encode_slice(
md->value->slice, grpc_compatible_percent_encoding_unreserved_bytes); GRPC_MDVALUE(b->idx.named.grpc_message->md),
if (grpc_slice_is_equivalent(pct_encoded_msg, md->value->slice)) { grpc_compatible_percent_encoding_unreserved_bytes);
if (grpc_slice_is_equivalent(pct_encoded_msg,
GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
grpc_slice_unref_internal(exec_ctx, pct_encoded_msg); grpc_slice_unref_internal(exec_ctx, pct_encoded_msg);
return md;
} else { } else {
return grpc_mdelem_from_metadata_strings( grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message,
exec_ctx, GRPC_MDSTR_GRPC_MESSAGE, pct_encoded_msg);
grpc_mdstr_from_slice(exec_ctx, pct_encoded_msg));
} }
} else {
return md;
} }
return GRPC_ERROR_NONE;
} }
static grpc_mdelem *server_filter(grpc_exec_ctx *exec_ctx, void *user_data, static void add_error(const char *error_name, grpc_error **cumulative,
grpc_mdelem *md) { grpc_error *new) {
grpc_call_element *elem = user_data; if (new == GRPC_ERROR_NONE) return;
if (*cumulative == GRPC_ERROR_NONE) {
*cumulative = GRPC_ERROR_CREATE(error_name);
}
*cumulative = grpc_error_add_child(*cumulative, new);
}
static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_metadata_batch *b) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_error *error = GRPC_ERROR_NONE;
static const char *error_name = "Failed processing incoming headers";
/* Check if it is one of the headers we care about. */ if (b->idx.named.method != NULL) {
if (md == GRPC_MDELEM_TE_TRAILERS || md == GRPC_MDELEM_METHOD_POST || if (grpc_mdelem_eq(b->idx.named.method->md, GRPC_MDELEM_METHOD_POST)) {
md == GRPC_MDELEM_METHOD_PUT || md == GRPC_MDELEM_METHOD_GET ||
md == GRPC_MDELEM_SCHEME_HTTP || md == GRPC_MDELEM_SCHEME_HTTPS ||
md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
/* swallow it */
if (md == GRPC_MDELEM_METHOD_POST) {
calld->seen_method = 1;
*calld->recv_idempotent_request = false; *calld->recv_idempotent_request = false;
*calld->recv_cacheable_request = false; *calld->recv_cacheable_request = false;
} else if (md == GRPC_MDELEM_METHOD_PUT) { } else if (grpc_mdelem_eq(b->idx.named.method->md,
calld->seen_method = 1; GRPC_MDELEM_METHOD_PUT)) {
*calld->recv_idempotent_request = true; *calld->recv_idempotent_request = true;
} else if (md == GRPC_MDELEM_METHOD_GET) { } else if (grpc_mdelem_eq(b->idx.named.method->md,
calld->seen_method = 1; GRPC_MDELEM_METHOD_GET)) {
*calld->recv_cacheable_request = true; *calld->recv_cacheable_request = true;
} else if (md->key == GRPC_MDSTR_SCHEME) {
calld->seen_scheme = 1;
} else if (md == GRPC_MDELEM_TE_TRAILERS) {
calld->seen_te_trailers = 1;
}
/* TODO(klempner): Track that we've seen all the headers we should
require */
return NULL;
} else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
const char *value_str = grpc_mdstr_as_c_string(md->value);
if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
(value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
as +proto or +json, or at least stashing them if we see them. */
/* TODO(klempner): Should we be surfacing this to application code? */
} else { } else {
/* TODO(klempner): We're currently allowing this, but we shouldn't add_error(error_name, &error,
see it without a proxy so log for now. */ grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str); b->idx.named.method->md));
}
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.method);
} else {
add_error(error_name, &error,
grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
GRPC_ERROR_STR_KEY, ":method"));
}
if (b->idx.named.te != NULL) {
if (!grpc_mdelem_eq(b->idx.named.te->md, GRPC_MDELEM_TE_TRAILERS)) {
add_error(error_name, &error,
grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
b->idx.named.te->md));
}
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.te);
} else {
add_error(error_name, &error,
grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
GRPC_ERROR_STR_KEY, "te"));
}
if (b->idx.named.scheme != NULL) {
if (!grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTP) &&
!grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTPS) &&
!grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_GRPC)) {
add_error(error_name, &error,
grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
b->idx.named.scheme->md));
} }
return NULL; grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.scheme);
} else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD || } else {
md->key == GRPC_MDSTR_SCHEME) { add_error(error_name, &error,
gpr_log(GPR_ERROR, "Invalid %s: header: '%s'", grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)); GRPC_ERROR_STR_KEY, ":scheme"));
/* swallow it and error everything out. */ }
/* TODO(klempner): We ought to generate more descriptive error messages
on the wire here. */ if (b->idx.named.content_type != NULL) {
grpc_call_element_send_cancel(exec_ctx, elem); if (!grpc_mdelem_eq(b->idx.named.content_type->md,
return NULL; GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
} else if (md->key == GRPC_MDSTR_PATH) { if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md),
if (calld->seen_path) { EXPECTED_CONTENT_TYPE,
gpr_log(GPR_ERROR, "Received :path twice"); EXPECTED_CONTENT_TYPE_LENGTH) &&
return NULL; (GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
'+' ||
GRPC_SLICE_START_PTR(GRPC_MDVALUE(
b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
';')) {
/* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such
as +proto or +json, or at least stashing them if we see them. */
/* TODO(klempner): Should we be surfacing this to application code? */
} else {
/* TODO(klempner): We're currently allowing this, but we shouldn't
see it without a proxy so log for now. */
char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md),
GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
gpr_free(val);
}
} }
calld->seen_path = 1; grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type);
return md; }
} else if (md->key == GRPC_MDSTR_AUTHORITY) {
calld->seen_authority = 1; if (b->idx.named.path == NULL) {
return md; add_error(error_name, &error,
} else if (md->key == GRPC_MDSTR_HOST) { grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
/* translate host to :authority since :authority may be GRPC_ERROR_STR_KEY, ":path"));
omitted */ }
grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
exec_ctx, GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value)); if (b->idx.named.host != NULL) {
calld->seen_authority = 1; add_error(
return authority; error_name, &error,
} else if (md->key == GRPC_MDSTR_GRPC_PAYLOAD_BIN) { grpc_metadata_batch_substitute(
/* Retrieve the payload from the value of the 'grpc-internal-payload-bin' exec_ctx, b, b->idx.named.host,
header field */ grpc_mdelem_from_slices(
calld->seen_payload_bin = 1; exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.host->md)))));
}
if (b->idx.named.authority == NULL) {
add_error(error_name, &error,
grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
GRPC_ERROR_STR_KEY, ":authority"));
}
if (b->idx.named.grpc_payload_bin != NULL) {
calld->seen_payload_bin = true;
grpc_slice_buffer_add(&calld->read_slice_buffer, grpc_slice_buffer_add(&calld->read_slice_buffer,
grpc_slice_ref_internal(md->value->slice)); grpc_slice_ref_internal(
GRPC_MDVALUE(b->idx.named.grpc_payload_bin->md)));
grpc_slice_buffer_stream_init(&calld->read_stream, grpc_slice_buffer_stream_init(&calld->read_stream,
&calld->read_slice_buffer, 0); &calld->read_slice_buffer, 0);
return NULL; grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_payload_bin);
} else {
return md;
} }
return error;
} }
static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
@ -193,49 +232,12 @@ static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_call_element *elem = user_data; grpc_call_element *elem = user_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
if (err == GRPC_ERROR_NONE) { if (err == GRPC_ERROR_NONE) {
grpc_metadata_batch_filter(exec_ctx, calld->recv_initial_metadata, err = server_filter_incoming_metadata(exec_ctx, elem,
server_filter, elem); calld->recv_initial_metadata);
/* Have we seen the required http2 transport headers?
(:method, :scheme, content-type, with :path and :authority covered
at the channel level right now) */
if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers &&
calld->seen_path && calld->seen_authority) {
/* do nothing */
} else {
err = GRPC_ERROR_CREATE("Bad incoming HTTP headers");
if (!calld->seen_path) {
err = grpc_error_add_child(err,
GRPC_ERROR_CREATE("Missing :path header"));
}
if (!calld->seen_authority) {
err = grpc_error_add_child(
err, GRPC_ERROR_CREATE("Missing :authority header"));
}
if (!calld->seen_method) {
err = grpc_error_add_child(err,
GRPC_ERROR_CREATE("Missing :method header"));
}
if (!calld->seen_scheme) {
err = grpc_error_add_child(err,
GRPC_ERROR_CREATE("Missing :scheme header"));
}
if (!calld->seen_te_trailers) {
err = grpc_error_add_child(
err, GRPC_ERROR_CREATE("Missing te: trailers header"));
}
/* Error this call out */
if (grpc_http_trace) {
const char *error_str = grpc_error_string(err);
gpr_log(GPR_ERROR, "Invalid http2 headers: %s", error_str);
grpc_error_free_string(error_str);
}
grpc_call_element_send_cancel(exec_ctx, elem);
}
} else { } else {
GRPC_ERROR_REF(err); GRPC_ERROR_REF(err);
} }
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, err); grpc_closure_run(exec_ctx, calld->on_done_recv, err);
GRPC_ERROR_UNREF(err);
} }
static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data, static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
@ -273,13 +275,23 @@ static void hs_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
if (op->send_initial_metadata != NULL && !calld->sent_status) { if (op->send_initial_metadata != NULL) {
calld->sent_status = 1; grpc_error *error = GRPC_ERROR_NONE;
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->status, static const char *error_name = "Failed sending initial metadata";
GRPC_MDELEM_STATUS_200); add_error(error_name, &error, grpc_metadata_batch_add_head(
grpc_metadata_batch_add_tail( exec_ctx, op->send_initial_metadata,
op->send_initial_metadata, &calld->content_type, &calld->status, GRPC_MDELEM_STATUS_200));
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); add_error(error_name, &error,
grpc_metadata_batch_add_tail(
exec_ctx, op->send_initial_metadata, &calld->content_type,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC));
add_error(error_name, &error,
server_filter_outgoing_metadata(exec_ctx, elem,
op->send_initial_metadata));
if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
return;
}
} }
if (op->recv_initial_metadata) { if (op->recv_initial_metadata) {
@ -306,8 +318,12 @@ static void hs_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
} }
if (op->send_trailing_metadata) { if (op->send_trailing_metadata) {
grpc_metadata_batch_filter(exec_ctx, op->send_trailing_metadata, grpc_error *error = server_filter_outgoing_metadata(
server_filter_outgoing_metadata, elem); exec_ctx, elem, op->send_trailing_metadata);
if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
return;
}
} }
} }

@ -58,7 +58,7 @@ static void message_size_limits_free(grpc_exec_ctx* exec_ctx, void* value) {
gpr_free(value); gpr_free(value);
} }
static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = { static const grpc_slice_hash_table_vtable message_size_limits_vtable = {
message_size_limits_free, message_size_limits_copy}; message_size_limits_free, message_size_limits_copy};
static void* message_size_limits_create_from_json(const grpc_json* json) { static void* message_size_limits_create_from_json(const grpc_json* json) {
@ -68,12 +68,16 @@ static void* message_size_limits_create_from_json(const grpc_json* json) {
if (field->key == NULL) continue; if (field->key == NULL) continue;
if (strcmp(field->key, "maxRequestMessageBytes") == 0) { if (strcmp(field->key, "maxRequestMessageBytes") == 0) {
if (max_request_message_bytes >= 0) return NULL; // Duplicate. if (max_request_message_bytes >= 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL; if (field->type != GRPC_JSON_STRING && field->type != GRPC_JSON_NUMBER) {
return NULL;
}
max_request_message_bytes = gpr_parse_nonnegative_int(field->value); max_request_message_bytes = gpr_parse_nonnegative_int(field->value);
if (max_request_message_bytes == -1) return NULL; if (max_request_message_bytes == -1) return NULL;
} else if (strcmp(field->key, "maxResponseMessageBytes") == 0) { } else if (strcmp(field->key, "maxResponseMessageBytes") == 0) {
if (max_response_message_bytes >= 0) return NULL; // Duplicate. if (max_response_message_bytes >= 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL; if (field->type != GRPC_JSON_STRING && field->type != GRPC_JSON_NUMBER) {
return NULL;
}
max_response_message_bytes = gpr_parse_nonnegative_int(field->value); max_response_message_bytes = gpr_parse_nonnegative_int(field->value);
if (max_response_message_bytes == -1) return NULL; if (max_response_message_bytes == -1) return NULL;
} }
@ -101,7 +105,7 @@ typedef struct channel_data {
int max_send_size; int max_send_size;
int max_recv_size; int max_recv_size;
// Maps path names to message_size_limits structs. // Maps path names to message_size_limits structs.
grpc_mdstr_hash_table* method_limit_table; grpc_slice_hash_table* method_limit_table;
} channel_data; } channel_data;
// Callback invoked when we receive a message. Here we check the max // Callback invoked when we receive a message. Here we check the max
@ -142,10 +146,12 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx,
char* message_string; char* message_string;
gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)", gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)",
op->send_message->length, calld->max_send_size); op->send_message->length, calld->max_send_size);
grpc_slice message = grpc_slice_from_copied_string(message_string); grpc_transport_stream_op_finish_with_failure(
exec_ctx, op, grpc_error_set_int(GRPC_ERROR_CREATE(message_string),
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_INVALID_ARGUMENT));
gpr_free(message_string); gpr_free(message_string);
grpc_call_element_send_close_with_message( return;
exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message);
} }
// Inject callback for receiving a message. // Inject callback for receiving a message.
if (op->recv_message_ready != NULL) { if (op->recv_message_ready != NULL) {
@ -243,7 +249,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element* elem) { grpc_channel_element* elem) {
channel_data* chand = elem->channel_data; channel_data* chand = elem->channel_data;
grpc_mdstr_hash_table_unref(exec_ctx, chand->method_limit_table); grpc_slice_hash_table_unref(exec_ctx, chand->method_limit_table);
} }
const grpc_channel_filter grpc_message_size_filter = { const grpc_channel_filter grpc_message_size_filter = {

@ -38,16 +38,16 @@
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
/** Return compression algorithm based metadata value */ /** Return compression algorithm based metadata value */
grpc_mdstr *grpc_compression_algorithm_mdstr( grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm); grpc_compression_algorithm algorithm);
/** Return compression algorithm based metadata element (grpc-encoding: xxx) */ /** Return compression algorithm based metadata element (grpc-encoding: xxx) */
grpc_mdelem *grpc_compression_encoding_mdelem( grpc_mdelem grpc_compression_encoding_mdelem(
grpc_compression_algorithm algorithm); grpc_compression_algorithm algorithm);
/** Find compression algorithm based on passed in mdstr - returns /** Find compression algorithm based on passed in mdstr - returns
* GRPC_COMPRESS_ALGORITHM_COUNT on failure */ * GRPC_COMPRESS_ALGORITHM_COUNT on failure */
grpc_compression_algorithm grpc_compression_algorithm_from_mdstr( grpc_compression_algorithm grpc_compression_algorithm_from_slice(
grpc_mdstr *str); grpc_slice str);
#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */ #endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */

@ -41,30 +41,24 @@
#include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
int grpc_compression_algorithm_parse(const char *name, size_t name_length, int grpc_compression_algorithm_parse(grpc_slice name,
grpc_compression_algorithm *algorithm) { grpc_compression_algorithm *algorithm) {
/* we use strncmp not only because it's safer (even though in this case it /* we use strncmp not only because it's safer (even though in this case it
* doesn't matter, given that we are comparing against string literals, but * doesn't matter, given that we are comparing against string literals, but
* because this way we needn't have "name" nil-terminated (useful for slice * because this way we needn't have "name" nil-terminated (useful for slice
* data, for example) */ * data, for example) */
GRPC_API_TRACE( if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) {
"grpc_compression_algorithm_parse("
"name=%*.*s, name_length=%lu, algorithm=%p)",
5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
algorithm));
if (name_length == 0) {
return 0;
}
if (strncmp(name, "identity", name_length) == 0) {
*algorithm = GRPC_COMPRESS_NONE; *algorithm = GRPC_COMPRESS_NONE;
} else if (strncmp(name, "gzip", name_length) == 0) { return 1;
} else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) {
*algorithm = GRPC_COMPRESS_GZIP; *algorithm = GRPC_COMPRESS_GZIP;
} else if (strncmp(name, "deflate", name_length) == 0) { return 1;
} else if (grpc_slice_eq(name, GRPC_MDSTR_DEFLATE)) {
*algorithm = GRPC_COMPRESS_DEFLATE; *algorithm = GRPC_COMPRESS_DEFLATE;
return 1;
} else { } else {
return 0; return 0;
} }
return 1;
} }
int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm, int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
@ -87,15 +81,15 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
return 0; return 0;
} }
grpc_compression_algorithm grpc_compression_algorithm_from_mdstr( grpc_compression_algorithm grpc_compression_algorithm_from_slice(
grpc_mdstr *str) { grpc_slice str) {
if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE; if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE;
if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE; if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE)) return GRPC_COMPRESS_DEFLATE;
if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP; if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_COMPRESS_GZIP;
return GRPC_COMPRESS_ALGORITHMS_COUNT; return GRPC_COMPRESS_ALGORITHMS_COUNT;
} }
grpc_mdstr *grpc_compression_algorithm_mdstr( grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm) { grpc_compression_algorithm algorithm) {
switch (algorithm) { switch (algorithm) {
case GRPC_COMPRESS_NONE: case GRPC_COMPRESS_NONE:
@ -105,12 +99,12 @@ grpc_mdstr *grpc_compression_algorithm_mdstr(
case GRPC_COMPRESS_GZIP: case GRPC_COMPRESS_GZIP:
return GRPC_MDSTR_GZIP; return GRPC_MDSTR_GZIP;
case GRPC_COMPRESS_ALGORITHMS_COUNT: case GRPC_COMPRESS_ALGORITHMS_COUNT:
return NULL; return grpc_empty_slice();
} }
return NULL; return grpc_empty_slice();
} }
grpc_mdelem *grpc_compression_encoding_mdelem( grpc_mdelem grpc_compression_encoding_mdelem(
grpc_compression_algorithm algorithm) { grpc_compression_algorithm algorithm) {
switch (algorithm) { switch (algorithm) {
case GRPC_COMPRESS_NONE: case GRPC_COMPRESS_NONE:
@ -122,7 +116,7 @@ grpc_mdelem *grpc_compression_encoding_mdelem(
default: default:
break; break;
} }
return NULL; return GRPC_MDNULL;
} }
void grpc_compression_options_init(grpc_compression_options *opts) { void grpc_compression_options_init(grpc_compression_options *opts) {

@ -156,7 +156,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
const char *msg = grpc_error_string(error); const char *msg = grpc_error_string(error);
gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg); gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg);
grpc_error_free_string(msg);
c->func(exec_ctx, c->arg, NULL); c->func(exec_ctx, c->arg, NULL);
} else { } else {
grpc_channel_args_destroy(exec_ctx, args->args); grpc_channel_args_destroy(exec_ctx, args->args);

@ -34,6 +34,7 @@
#include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/closure.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"

@ -66,6 +66,7 @@ typedef struct grpc_closure_scheduler_vtable {
grpc_error *error); grpc_error *error);
void (*sched)(grpc_exec_ctx *exec_ctx, grpc_closure *closure, void (*sched)(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_error *error); grpc_error *error);
const char *name;
} grpc_closure_scheduler_vtable; } grpc_closure_scheduler_vtable;
/** Abstract type that can schedule closures for execution */ /** Abstract type that can schedule closures for execution */

@ -86,13 +86,17 @@ static void combiner_finally_exec_covered(grpc_exec_ctx *exec_ctx,
grpc_error *error); grpc_error *error);
static const grpc_closure_scheduler_vtable scheduler_uncovered = { static const grpc_closure_scheduler_vtable scheduler_uncovered = {
combiner_exec_uncovered, combiner_exec_uncovered}; combiner_exec_uncovered, combiner_exec_uncovered,
"combiner:immediately:uncovered"};
static const grpc_closure_scheduler_vtable scheduler_covered = { static const grpc_closure_scheduler_vtable scheduler_covered = {
combiner_exec_covered, combiner_exec_covered}; combiner_exec_covered, combiner_exec_covered,
"combiner:immediately:covered"};
static const grpc_closure_scheduler_vtable finally_scheduler_uncovered = { static const grpc_closure_scheduler_vtable finally_scheduler_uncovered = {
combiner_finally_exec_uncovered, combiner_finally_exec_uncovered}; combiner_finally_exec_uncovered, combiner_finally_exec_uncovered,
"combiner:finally:uncovered"};
static const grpc_closure_scheduler_vtable finally_scheduler_covered = { static const grpc_closure_scheduler_vtable finally_scheduler_covered = {
combiner_finally_exec_covered, combiner_finally_exec_covered}; combiner_finally_exec_covered, combiner_finally_exec_covered,
"combiner:finally:covered"};
static void offload(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); static void offload(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);

@ -54,8 +54,9 @@ void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx,
ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set); ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set);
} }
void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) { void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
ep->vtable->shutdown(exec_ctx, ep); grpc_error* why) {
ep->vtable->shutdown(exec_ctx, ep, why);
} }
void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) { void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {

@ -57,7 +57,7 @@ struct grpc_endpoint_vtable {
grpc_pollset *pollset); grpc_pollset *pollset);
void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset_set *pollset); grpc_pollset_set *pollset);
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why);
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
grpc_resource_user *(*get_resource_user)(grpc_endpoint *ep); grpc_resource_user *(*get_resource_user)(grpc_endpoint *ep);
char *(*get_peer)(grpc_endpoint *ep); char *(*get_peer)(grpc_endpoint *ep);
@ -96,7 +96,8 @@ void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
/* Causes any pending and future read/write callbacks to run immediately with /* Causes any pending and future read/write callbacks to run immediately with
success==0 */ success==0 */
void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_error *why);
void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
/* Add an endpoint to a pollset, so that when the pollset is polled, events from /* Add an endpoint to a pollset, so that when the pollset is polled, events from

@ -33,13 +33,10 @@
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include <inttypes.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include <grpc/status.h> #include <grpc/status.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/avl.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
@ -48,6 +45,7 @@
#include <grpc/support/log_windows.h> #include <grpc/support/log_windows.h>
#endif #endif
#include "src/core/lib/iomgr/error_internal.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
static void destroy_integer(void *key) {} static void destroy_integer(void *key) {}
@ -128,6 +126,10 @@ static const char *error_int_name(grpc_error_ints key) {
static const char *error_str_name(grpc_error_strs key) { static const char *error_str_name(grpc_error_strs key) {
switch (key) { switch (key) {
case GRPC_ERROR_STR_KEY:
return "key";
case GRPC_ERROR_STR_VALUE:
return "value";
case GRPC_ERROR_STR_DESCRIPTION: case GRPC_ERROR_STR_DESCRIPTION:
return "description"; return "description";
case GRPC_ERROR_STR_OS_ERROR: case GRPC_ERROR_STR_OS_ERROR:
@ -160,16 +162,7 @@ static const char *error_time_name(grpc_error_times key) {
GPR_UNREACHABLE_CODE(return "unknown"); GPR_UNREACHABLE_CODE(return "unknown");
} }
struct grpc_error { bool grpc_error_is_special(grpc_error *err) {
gpr_refcount refs;
gpr_avl ints;
gpr_avl strs;
gpr_avl times;
gpr_avl errs;
uintptr_t next_err;
};
static bool is_special(grpc_error *err) {
return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM || return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM ||
err == GRPC_ERROR_CANCELLED; err == GRPC_ERROR_CANCELLED;
} }
@ -177,7 +170,7 @@ static bool is_special(grpc_error *err) {
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifdef GRPC_ERROR_REFCOUNT_DEBUG
grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line, grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
const char *func) { const char *func) {
if (is_special(err)) return err; if (grpc_error_is_special(err)) return err;
gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err,
err->refs.count, err->refs.count + 1, file, line, func); err->refs.count, err->refs.count + 1, file, line, func);
gpr_ref(&err->refs); gpr_ref(&err->refs);
@ -185,25 +178,26 @@ grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
} }
#else #else
grpc_error *grpc_error_ref(grpc_error *err) { grpc_error *grpc_error_ref(grpc_error *err) {
if (is_special(err)) return err; if (grpc_error_is_special(err)) return err;
gpr_ref(&err->refs); gpr_ref(&err->refs);
return err; return err;
} }
#endif #endif
static void error_destroy(grpc_error *err) { static void error_destroy(grpc_error *err) {
GPR_ASSERT(!is_special(err)); GPR_ASSERT(!grpc_error_is_special(err));
gpr_avl_unref(err->ints); gpr_avl_unref(err->ints);
gpr_avl_unref(err->strs); gpr_avl_unref(err->strs);
gpr_avl_unref(err->errs); gpr_avl_unref(err->errs);
gpr_avl_unref(err->times); gpr_avl_unref(err->times);
gpr_free((void *)gpr_atm_acq_load(&err->error_string));
gpr_free(err); gpr_free(err);
} }
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifdef GRPC_ERROR_REFCOUNT_DEBUG
void grpc_error_unref(grpc_error *err, const char *file, int line, void grpc_error_unref(grpc_error *err, const char *file, int line,
const char *func) { const char *func) {
if (is_special(err)) return; if (grpc_error_is_special(err)) return;
gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err,
err->refs.count, err->refs.count - 1, file, line, func); err->refs.count, err->refs.count - 1, file, line, func);
if (gpr_unref(&err->refs)) { if (gpr_unref(&err->refs)) {
@ -212,7 +206,7 @@ void grpc_error_unref(grpc_error *err, const char *file, int line,
} }
#else #else
void grpc_error_unref(grpc_error *err) { void grpc_error_unref(grpc_error *err) {
if (is_special(err)) return; if (grpc_error_is_special(err)) return;
if (gpr_unref(&err->refs)) { if (gpr_unref(&err->refs)) {
error_destroy(err); error_destroy(err);
} }
@ -247,6 +241,7 @@ grpc_error *grpc_error_create(const char *file, int line, const char *desc,
err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times), err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times),
(void *)(uintptr_t)GRPC_ERROR_TIME_CREATED, (void *)(uintptr_t)GRPC_ERROR_TIME_CREATED,
box_time(gpr_now(GPR_CLOCK_REALTIME))); box_time(gpr_now(GPR_CLOCK_REALTIME)));
gpr_atm_no_barrier_store(&err->error_string, 0);
gpr_ref_init(&err->refs, 1); gpr_ref_init(&err->refs, 1);
GPR_TIMER_END("grpc_error_create", 0); GPR_TIMER_END("grpc_error_create", 0);
return err; return err;
@ -255,9 +250,10 @@ grpc_error *grpc_error_create(const char *file, int line, const char *desc,
static grpc_error *copy_error_and_unref(grpc_error *in) { static grpc_error *copy_error_and_unref(grpc_error *in) {
GPR_TIMER_BEGIN("copy_error_and_unref", 0); GPR_TIMER_BEGIN("copy_error_and_unref", 0);
grpc_error *out; grpc_error *out;
if (is_special(in)) { if (grpc_error_is_special(in)) {
if (in == GRPC_ERROR_NONE) if (in == GRPC_ERROR_NONE)
out = GRPC_ERROR_CREATE("no error"); out = grpc_error_set_int(GRPC_ERROR_CREATE("no error"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK);
else if (in == GRPC_ERROR_OOM) else if (in == GRPC_ERROR_OOM)
out = GRPC_ERROR_CREATE("oom"); out = GRPC_ERROR_CREATE("oom");
else if (in == GRPC_ERROR_CANCELLED) else if (in == GRPC_ERROR_CANCELLED)
@ -275,6 +271,7 @@ static grpc_error *copy_error_and_unref(grpc_error *in) {
out->strs = gpr_avl_ref(in->strs); out->strs = gpr_avl_ref(in->strs);
out->errs = gpr_avl_ref(in->errs); out->errs = gpr_avl_ref(in->errs);
out->times = gpr_avl_ref(in->times); out->times = gpr_avl_ref(in->times);
gpr_atm_no_barrier_store(&out->error_string, 0);
out->next_err = in->next_err; out->next_err = in->next_err;
gpr_ref_init(&out->refs, 1); gpr_ref_init(&out->refs, 1);
GRPC_ERROR_UNREF(in); GRPC_ERROR_UNREF(in);
@ -292,14 +289,29 @@ grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
return new; return new;
} }
typedef struct {
grpc_error *error;
grpc_status_code code;
const char *msg;
} special_error_status_map;
static special_error_status_map error_status_map[] = {
{GRPC_ERROR_NONE, GRPC_STATUS_OK, NULL},
{GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"},
{GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
};
bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) { bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) {
GPR_TIMER_BEGIN("grpc_error_get_int", 0); GPR_TIMER_BEGIN("grpc_error_get_int", 0);
void *pp; void *pp;
if (is_special(err)) { if (grpc_error_is_special(err)) {
if (err == GRPC_ERROR_CANCELLED && which == GRPC_ERROR_INT_GRPC_STATUS) { if (which == GRPC_ERROR_INT_GRPC_STATUS) {
*p = GRPC_STATUS_CANCELLED; for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
GPR_TIMER_END("grpc_error_get_int", 0); if (error_status_map[i].error == err) {
return true; if (p != NULL) *p = error_status_map[i].code;
GPR_TIMER_END("grpc_error_get_int", 0);
return true;
}
}
} }
GPR_TIMER_END("grpc_error_get_int", 0); GPR_TIMER_END("grpc_error_get_int", 0);
return false; return false;
@ -324,66 +336,17 @@ grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
} }
const char *grpc_error_get_str(grpc_error *err, grpc_error_strs which) { const char *grpc_error_get_str(grpc_error *err, grpc_error_strs which) {
if (is_special(err)) return NULL; if (grpc_error_is_special(err)) {
return gpr_avl_get(err->strs, (void *)(uintptr_t)which); if (which == GRPC_ERROR_STR_GRPC_MESSAGE) {
} for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
if (error_status_map[i].error == err) {
typedef struct { return error_status_map[i].msg;
grpc_error *error; }
grpc_status_code code; }
const char *msg;
} special_error_status_map;
static special_error_status_map error_status_map[] = {
{GRPC_ERROR_NONE, GRPC_STATUS_OK, ""},
{GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "RPC cancelled"},
{GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
};
static grpc_error *recursively_find_error_with_status(grpc_error *error,
intptr_t *status) {
// If the error itself has a status code, return it.
if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, status)) {
return error;
}
// Otherwise, search through its children.
intptr_t key = 0;
while (true) {
grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++);
if (child_error == NULL) break;
grpc_error *result =
recursively_find_error_with_status(child_error, status);
if (result != NULL) return result;
}
return NULL;
}
void grpc_error_get_status(grpc_error *error, grpc_status_code *code,
const char **msg) {
// Handle special errors via the static map.
for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); ++i) {
if (error == error_status_map[i].error) {
*code = error_status_map[i].code;
*msg = error_status_map[i].msg;
return;
} }
return NULL;
} }
// Populate code. return gpr_avl_get(err->strs, (void *)(uintptr_t)which);
// Start with the parent error and recurse through the tree of children
// until we find the first one that has a status code.
intptr_t status = GRPC_STATUS_UNKNOWN; // Default in case we don't find one.
grpc_error *found_error = recursively_find_error_with_status(error, &status);
*code = (grpc_status_code)status;
// Now populate msg.
// If we found an error with a status code above, use that; otherwise,
// fall back to using the parent error.
if (found_error == NULL) found_error = error;
// If the error has a status message, use it. Otherwise, fall back to
// the error description.
*msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE);
if (*msg == NULL) {
*msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION);
if (*msg == NULL) *msg = "uknown error"; // Just in case.
}
} }
grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) { grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) {
@ -535,7 +498,6 @@ static void add_errs(gpr_avl_node *n, char **s, size_t *sz, size_t *cap,
*first = false; *first = false;
const char *e = grpc_error_string(n->value); const char *e = grpc_error_string(n->value);
append_str(e, s, sz, cap); append_str(e, s, sz, cap);
grpc_error_free_string(e);
add_errs(n->right, s, sz, cap, first); add_errs(n->right, s, sz, cap, first);
} }
@ -557,7 +519,7 @@ static int cmp_kvs(const void *a, const void *b) {
return strcmp(ka->key, kb->key); return strcmp(ka->key, kb->key);
} }
static const char *finish_kvs(kv_pairs *kvs) { static char *finish_kvs(kv_pairs *kvs) {
char *s = NULL; char *s = NULL;
size_t sz = 0; size_t sz = 0;
size_t cap = 0; size_t cap = 0;
@ -578,19 +540,18 @@ static const char *finish_kvs(kv_pairs *kvs) {
return s; return s;
} }
void grpc_error_free_string(const char *str) {
if (str == no_error_string) return;
if (str == oom_error_string) return;
if (str == cancelled_error_string) return;
gpr_free((char *)str);
}
const char *grpc_error_string(grpc_error *err) { const char *grpc_error_string(grpc_error *err) {
GPR_TIMER_BEGIN("grpc_error_string", 0); GPR_TIMER_BEGIN("grpc_error_string", 0);
if (err == GRPC_ERROR_NONE) return no_error_string; if (err == GRPC_ERROR_NONE) return no_error_string;
if (err == GRPC_ERROR_OOM) return oom_error_string; if (err == GRPC_ERROR_OOM) return oom_error_string;
if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string; if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string;
void *p = (void *)gpr_atm_acq_load(&err->error_string);
if (p != NULL) {
GPR_TIMER_END("grpc_error_string", 0);
return p;
}
kv_pairs kvs; kv_pairs kvs;
memset(&kvs, 0, sizeof(kvs)); memset(&kvs, 0, sizeof(kvs));
@ -603,7 +564,13 @@ const char *grpc_error_string(grpc_error *err) {
qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs); qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs);
const char *out = finish_kvs(&kvs); char *out = finish_kvs(&kvs);
if (!gpr_atm_rel_cas(&err->error_string, 0, (gpr_atm)out)) {
gpr_free(out);
out = (char *)gpr_atm_no_barrier_load(&err->error_string);
}
GPR_TIMER_END("grpc_error_string", 0); GPR_TIMER_END("grpc_error_string", 0);
return out; return out;
} }
@ -638,7 +605,6 @@ bool grpc_log_if_error(const char *what, grpc_error *error, const char *file,
if (error == GRPC_ERROR_NONE) return true; if (error == GRPC_ERROR_NONE) return true;
const char *msg = grpc_error_string(error); const char *msg = grpc_error_string(error);
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg);
grpc_error_free_string(msg);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
return false; return false;
} }

@ -124,7 +124,11 @@ typedef enum {
/// filename that we were trying to read/write when this error occurred /// filename that we were trying to read/write when this error occurred
GRPC_ERROR_STR_FILENAME, GRPC_ERROR_STR_FILENAME,
/// which data was queued for writing when the error occurred /// which data was queued for writing when the error occurred
GRPC_ERROR_STR_QUEUED_BUFFERS GRPC_ERROR_STR_QUEUED_BUFFERS,
/// key associated with the error
GRPC_ERROR_STR_KEY,
/// value associated with the error
GRPC_ERROR_STR_VALUE,
} grpc_error_strs; } grpc_error_strs;
typedef enum { typedef enum {
@ -141,7 +145,6 @@ typedef enum {
#define GRPC_ERROR_CANCELLED ((grpc_error *)4) #define GRPC_ERROR_CANCELLED ((grpc_error *)4)
const char *grpc_error_string(grpc_error *error); const char *grpc_error_string(grpc_error *error);
void grpc_error_free_string(const char *str);
/// Create an error - but use GRPC_ERROR_CREATE instead /// Create an error - but use GRPC_ERROR_CREATE instead
grpc_error *grpc_error_create(const char *file, int line, const char *desc, grpc_error *grpc_error_create(const char *file, int line, const char *desc,
@ -189,12 +192,6 @@ grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
/// Caller does NOT own return value. /// Caller does NOT own return value.
const char *grpc_error_get_str(grpc_error *error, grpc_error_strs which); const char *grpc_error_get_str(grpc_error *error, grpc_error_strs which);
/// A utility function to get the status code and message to be returned
/// to the application. If not set in the top-level message, looks
/// through child errors until it finds the first one with these attributes.
void grpc_error_get_status(grpc_error *error, grpc_status_code *code,
const char **msg);
/// Add a child error: an error that is believed to have contributed to this /// Add a child error: an error that is believed to have contributed to this
/// error occurring. Allows root causing high level errors from lower level /// error occurring. Allows root causing high level errors from lower level
/// errors that contributed to them. /// errors that contributed to them.

@ -0,0 +1,54 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H
#define GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H
#include <inttypes.h>
#include <stdbool.h>
#include <grpc/support/avl.h>
struct grpc_error {
gpr_refcount refs;
gpr_avl ints;
gpr_avl strs;
gpr_avl times;
gpr_avl errs;
uintptr_t next_err;
gpr_atm error_string;
};
bool grpc_error_is_special(grpc_error *err);
#endif /* GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H */

@ -143,6 +143,7 @@ struct grpc_fd {
/* Indicates that the fd is shutdown and that any pending read/write closures /* Indicates that the fd is shutdown and that any pending read/write closures
should fail */ should fail */
bool shutdown; bool shutdown;
grpc_error *shutdown_error; /* reason for shutdown: set iff shutdown==true */
/* The fd is either closed or we relinquished control of it. In either cases, /* The fd is either closed or we relinquished control of it. In either cases,
this indicates that the 'fd' on this structure is no longer valid */ this indicates that the 'fd' on this structure is no longer valid */
@ -321,7 +322,7 @@ gpr_atm g_epoll_sync;
#endif /* defined(GRPC_TSAN) */ #endif /* defined(GRPC_TSAN) */
static const grpc_closure_scheduler_vtable workqueue_scheduler_vtable = { static const grpc_closure_scheduler_vtable workqueue_scheduler_vtable = {
workqueue_enqueue, workqueue_enqueue}; workqueue_enqueue, workqueue_enqueue, "workqueue"};
static void pi_add_ref(polling_island *pi); static void pi_add_ref(polling_island *pi);
static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi); static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi);
@ -907,6 +908,7 @@ static void unref_by(grpc_fd *fd, int n) {
fd->freelist_next = fd_freelist; fd->freelist_next = fd_freelist;
fd_freelist = fd; fd_freelist = fd;
grpc_iomgr_unregister_object(&fd->iomgr_object); grpc_iomgr_unregister_object(&fd->iomgr_object);
if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error);
gpr_mu_unlock(&fd_freelist_mu); gpr_mu_unlock(&fd_freelist_mu);
} else { } else {
@ -1058,11 +1060,11 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static grpc_error *fd_shutdown_error(bool shutdown) { static grpc_error *fd_shutdown_error(grpc_fd *fd) {
if (!shutdown) { if (!fd->shutdown) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} else { } else {
return GRPC_ERROR_CREATE("FD shutdown"); return GRPC_ERROR_CREATE_REFERENCING("FD shutdown", &fd->shutdown_error, 1);
} }
} }
@ -1076,7 +1078,7 @@ static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
} else if (*st == CLOSURE_READY) { } else if (*st == CLOSURE_READY) {
/* already ready ==> queue the closure to run immediately */ /* already ready ==> queue the closure to run immediately */
*st = CLOSURE_NOT_READY; *st = CLOSURE_NOT_READY;
grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown)); grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd));
} else { } else {
/* upcallptr was set to a different closure. This is an error! */ /* upcallptr was set to a different closure. This is an error! */
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
@ -1098,7 +1100,7 @@ static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
return 0; return 0;
} else { } else {
/* waiting ==> queue closure */ /* waiting ==> queue closure */
grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown)); grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd));
*st = CLOSURE_NOT_READY; *st = CLOSURE_NOT_READY;
return 1; return 1;
} }
@ -1123,17 +1125,20 @@ static bool fd_is_shutdown(grpc_fd *fd) {
} }
/* Might be called multiple times */ /* Might be called multiple times */
static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
gpr_mu_lock(&fd->po.mu); gpr_mu_lock(&fd->po.mu);
/* Do the actual shutdown only once */ /* Do the actual shutdown only once */
if (!fd->shutdown) { if (!fd->shutdown) {
fd->shutdown = true; fd->shutdown = true;
fd->shutdown_error = why;
shutdown(fd->fd, SHUT_RDWR); shutdown(fd->fd, SHUT_RDWR);
/* Flush any pending read and write closures. Since fd->shutdown is 'true' /* Flush any pending read and write closures. Since fd->shutdown is 'true'
at this point, the closures would be called with 'success = false' */ at this point, the closures would be called with 'success = false' */
set_ready_locked(exec_ctx, fd, &fd->read_closure); set_ready_locked(exec_ctx, fd, &fd->read_closure);
set_ready_locked(exec_ctx, fd, &fd->write_closure); set_ready_locked(exec_ctx, fd, &fd->write_closure);
} else {
GRPC_ERROR_UNREF(why);
} }
gpr_mu_unlock(&fd->po.mu); gpr_mu_unlock(&fd->po.mu);
} }
@ -1527,7 +1532,8 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx,
append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd), append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
err_desc); err_desc);
} else if (data_ptr == &pi->workqueue_wakeup_fd) { } else if (data_ptr == &pi->workqueue_wakeup_fd) {
append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd), append_error(error,
grpc_wakeup_fd_consume_wakeup(&pi->workqueue_wakeup_fd),
err_desc); err_desc);
maybe_do_workqueue_work(exec_ctx, pi); maybe_do_workqueue_work(exec_ctx, pi);
} else if (data_ptr == &polling_island_wakeup_fd) { } else if (data_ptr == &polling_island_wakeup_fd) {

@ -82,6 +82,7 @@ struct grpc_fd {
int shutdown; int shutdown;
int closed; int closed;
int released; int released;
grpc_error *shutdown_error;
/* The watcher list. /* The watcher list.
@ -306,6 +307,7 @@ static void unref_by(grpc_fd *fd, int n) {
if (old == n) { if (old == n) {
gpr_mu_destroy(&fd->mu); gpr_mu_destroy(&fd->mu);
grpc_iomgr_unregister_object(&fd->iomgr_object); grpc_iomgr_unregister_object(&fd->iomgr_object);
if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error);
gpr_free(fd); gpr_free(fd);
} else { } else {
GPR_ASSERT(old > n); GPR_ASSERT(old > n);
@ -444,11 +446,11 @@ static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); } static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
#endif #endif
static grpc_error *fd_shutdown_error(bool shutdown) { static grpc_error *fd_shutdown_error(grpc_fd *fd) {
if (!shutdown) { if (!fd->shutdown) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} else { } else {
return GRPC_ERROR_CREATE("FD shutdown"); return GRPC_ERROR_CREATE_REFERENCING("FD shutdown", &fd->shutdown_error, 1);
} }
} }
@ -462,7 +464,7 @@ static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
} else if (*st == CLOSURE_READY) { } else if (*st == CLOSURE_READY) {
/* already ready ==> queue the closure to run immediately */ /* already ready ==> queue the closure to run immediately */
*st = CLOSURE_NOT_READY; *st = CLOSURE_NOT_READY;
grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown)); grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd));
maybe_wake_one_watcher_locked(fd); maybe_wake_one_watcher_locked(fd);
} else { } else {
/* upcallptr was set to a different closure. This is an error! */ /* upcallptr was set to a different closure. This is an error! */
@ -485,7 +487,7 @@ static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
return 0; return 0;
} else { } else {
/* waiting ==> queue closure */ /* waiting ==> queue closure */
grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown)); grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd));
*st = CLOSURE_NOT_READY; *st = CLOSURE_NOT_READY;
return 1; return 1;
} }
@ -496,15 +498,18 @@ static void set_read_notifier_pollset_locked(
fd->read_notifier_pollset = read_notifier_pollset; fd->read_notifier_pollset = read_notifier_pollset;
} }
static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
gpr_mu_lock(&fd->mu); gpr_mu_lock(&fd->mu);
/* only shutdown once */ /* only shutdown once */
if (!fd->shutdown) { if (!fd->shutdown) {
fd->shutdown = 1; fd->shutdown = 1;
fd->shutdown_error = why;
/* signal read/write closed to OS so that future operations fail */ /* signal read/write closed to OS so that future operations fail */
shutdown(fd->fd, SHUT_RDWR); shutdown(fd->fd, SHUT_RDWR);
set_ready_locked(exec_ctx, fd, &fd->read_closure); set_ready_locked(exec_ctx, fd, &fd->read_closure);
set_ready_locked(exec_ctx, fd, &fd->write_closure); set_ready_locked(exec_ctx, fd, &fd->write_closure);
} else {
GRPC_ERROR_UNREF(why);
} }
gpr_mu_unlock(&fd->mu); gpr_mu_unlock(&fd->mu);
} }

@ -52,6 +52,8 @@
* tests */ * tests */
grpc_poll_function_type grpc_poll_function = poll; grpc_poll_function_type grpc_poll_function = poll;
grpc_wakeup_fd grpc_global_wakeup_fd;
static const grpc_event_engine_vtable *g_event_engine; static const grpc_event_engine_vtable *g_event_engine;
static const char *g_poll_strategy_name = NULL; static const char *g_poll_strategy_name = NULL;
@ -160,8 +162,8 @@ void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
g_event_engine->fd_orphan(exec_ctx, fd, on_done, release_fd, reason); g_event_engine->fd_orphan(exec_ctx, fd, on_done, release_fd, reason);
} }
void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
g_event_engine->fd_shutdown(exec_ctx, fd); g_event_engine->fd_shutdown(exec_ctx, fd, why);
} }
bool grpc_fd_is_shutdown(grpc_fd *fd) { bool grpc_fd_is_shutdown(grpc_fd *fd) {

@ -51,7 +51,7 @@ typedef struct grpc_event_engine_vtable {
int (*fd_wrapped_fd)(grpc_fd *fd); int (*fd_wrapped_fd)(grpc_fd *fd);
void (*fd_orphan)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done, void (*fd_orphan)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
int *release_fd, const char *reason); int *release_fd, const char *reason);
void (*fd_shutdown)(grpc_exec_ctx *exec_ctx, grpc_fd *fd); void (*fd_shutdown)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why);
void (*fd_notify_on_read)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, void (*fd_notify_on_read)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure); grpc_closure *closure);
void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd, void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
@ -140,7 +140,7 @@ void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
bool grpc_fd_is_shutdown(grpc_fd *fd); bool grpc_fd_is_shutdown(grpc_fd *fd);
/* Cause any current and future callbacks to fail. */ /* Cause any current and future callbacks to fail. */
void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd); void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why);
/* Register read interest, causing read_cb to be called once when fd becomes /* Register read interest, causing read_cb to be called once when fd becomes
readable, on deadline specified by deadline, or on shutdown triggered by readable, on deadline specified by deadline, or on shutdown triggered by

@ -42,11 +42,16 @@
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx) { bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx) {
if (!exec_ctx->cached_ready_to_finish) { if ((exec_ctx->flags & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) {
exec_ctx->cached_ready_to_finish = exec_ctx->check_ready_to_finish( if (exec_ctx->check_ready_to_finish(exec_ctx,
exec_ctx, exec_ctx->check_ready_to_finish_arg); exec_ctx->check_ready_to_finish_arg)) {
exec_ctx->flags |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
return true;
}
return false;
} else {
return true;
} }
return exec_ctx->cached_ready_to_finish;
} }
bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) { bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) {
@ -82,7 +87,7 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
} }
void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) { void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
exec_ctx->cached_ready_to_finish = true; exec_ctx->flags |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
grpc_exec_ctx_flush(exec_ctx); grpc_exec_ctx_flush(exec_ctx);
} }
@ -101,6 +106,6 @@ void grpc_exec_ctx_global_init(void) {}
void grpc_exec_ctx_global_shutdown(void) {} void grpc_exec_ctx_global_shutdown(void) {}
static const grpc_closure_scheduler_vtable exec_ctx_scheduler_vtable = { static const grpc_closure_scheduler_vtable exec_ctx_scheduler_vtable = {
exec_ctx_run, exec_ctx_sched}; exec_ctx_run, exec_ctx_sched, "exec_ctx"};
static grpc_closure_scheduler exec_ctx_scheduler = {&exec_ctx_scheduler_vtable}; static grpc_closure_scheduler exec_ctx_scheduler = {&exec_ctx_scheduler_vtable};
grpc_closure_scheduler *grpc_schedule_on_exec_ctx = &exec_ctx_scheduler; grpc_closure_scheduler *grpc_schedule_on_exec_ctx = &exec_ctx_scheduler;

@ -43,6 +43,13 @@
typedef struct grpc_workqueue grpc_workqueue; typedef struct grpc_workqueue grpc_workqueue;
typedef struct grpc_combiner grpc_combiner; typedef struct grpc_combiner grpc_combiner;
/* This exec_ctx is ready to return: either pre-populated, or cached as soon as
the finish_check returns true */
#define GRPC_EXEC_CTX_FLAG_IS_FINISHED 1
/* The exec_ctx's thread is (potentially) owned by a call or channel: care
should be given to not delete said call/channel from this exec_ctx */
#define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2
/** Execution context. /** Execution context.
* A bag of data that collects information along a callstack. * A bag of data that collects information along a callstack.
* Generally created at public API entry points, and passed down as * Generally created at public API entry points, and passed down as
@ -63,36 +70,26 @@ typedef struct grpc_combiner grpc_combiner;
* - Instances are always passed as the first argument to a function that * - Instances are always passed as the first argument to a function that
* takes it, and always as a pointer (grpc_exec_ctx is never copied). * takes it, and always as a pointer (grpc_exec_ctx is never copied).
*/ */
#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
struct grpc_exec_ctx { struct grpc_exec_ctx {
grpc_closure_list closure_list; grpc_closure_list closure_list;
/** currently active combiner: updated only via combiner.c */ /** currently active combiner: updated only via combiner.c */
grpc_combiner *active_combiner; grpc_combiner *active_combiner;
/** last active combiner in the active combiner list */ /** last active combiner in the active combiner list */
grpc_combiner *last_combiner; grpc_combiner *last_combiner;
bool cached_ready_to_finish; uintptr_t flags;
void *check_ready_to_finish_arg; void *check_ready_to_finish_arg;
bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg); bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg);
}; };
/* initializer for grpc_exec_ctx: /* initializer for grpc_exec_ctx:
prefer to use GRPC_EXEC_CTX_INIT whenever possible */ prefer to use GRPC_EXEC_CTX_INIT whenever possible */
#define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \ #define GRPC_EXEC_CTX_INITIALIZER(flags, finish_check, finish_check_arg) \
{ GRPC_CLOSURE_LIST_INIT, NULL, NULL, false, finish_check_arg, finish_check } { GRPC_CLOSURE_LIST_INIT, NULL, NULL, flags, finish_check_arg, finish_check }
#else
struct grpc_exec_ctx {
bool cached_ready_to_finish;
void *check_ready_to_finish_arg;
bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg);
};
#define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \
{ false, finish_check_arg, finish_check }
#endif
/* initialize an execution context at the top level of an API call into grpc /* initialize an execution context at the top level of an API call into grpc
(this is safe to use elsewhere, though possibly not as efficient) */ (this is safe to use elsewhere, though possibly not as efficient) */
#define GRPC_EXEC_CTX_INIT \ #define GRPC_EXEC_CTX_INIT \
GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(grpc_always_ready_to_finish, NULL) GRPC_EXEC_CTX_INITIALIZER(GRPC_EXEC_CTX_FLAG_IS_FINISHED, NULL, NULL)
extern grpc_closure_scheduler *grpc_schedule_on_exec_ctx; extern grpc_closure_scheduler *grpc_schedule_on_exec_ctx;

@ -158,7 +158,7 @@ void grpc_executor_shutdown(grpc_exec_ctx *exec_ctx) {
gpr_mu_destroy(&g_executor.mu); gpr_mu_destroy(&g_executor.mu);
} }
static const grpc_closure_scheduler_vtable executor_vtable = {executor_push, static const grpc_closure_scheduler_vtable executor_vtable = {
executor_push}; executor_push, executor_push, "executor"};
static grpc_closure_scheduler executor_scheduler = {&executor_vtable}; static grpc_closure_scheduler executor_scheduler = {&executor_vtable};
grpc_closure_scheduler *grpc_executor_scheduler = &executor_scheduler; grpc_closure_scheduler *grpc_executor_scheduler = &executor_scheduler;

@ -47,7 +47,7 @@ grpc_error *grpc_load_file(const char *filename, int add_null_terminator,
grpc_slice *output) { grpc_slice *output) {
unsigned char *contents = NULL; unsigned char *contents = NULL;
size_t contents_size = 0; size_t contents_size = 0;
grpc_slice result = gpr_empty_slice(); grpc_slice result = grpc_empty_slice();
FILE *file; FILE *file;
size_t bytes_read = 0; size_t bytes_read = 0;
grpc_error *error = GRPC_ERROR_NONE; grpc_error *error = GRPC_ERROR_NONE;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save