Merge branch 'master' into epoll_changes_merged

pull/6803/head
Sree Kuchibhotla 9 years ago
commit c3a9fae601
  1. 46
      BUILD
  2. 466
      Makefile
  3. 4
      binding.gyp
  4. 103
      build.yaml
  5. 4
      config.m4
  6. 6
      doc/cpp-style-guide.md
  7. 2
      examples/python/route_guide/route_guide_server.py
  8. 12
      gRPC.podspec
  9. 2
      grpc.def
  10. 8
      grpc.gemspec
  11. 2
      include/grpc++/ext/proto_server_reflection_plugin.h
  12. 2
      include/grpc++/impl/codegen/call.h
  13. 17
      include/grpc++/impl/codegen/config.h
  14. 46
      include/grpc++/impl/codegen/core_codegen.h
  15. 3
      include/grpc++/impl/server_builder_option.h
  16. 2
      include/grpc++/server_builder.h
  17. 5
      include/grpc/support/avl.h
  18. 8
      package.xml
  19. 1
      setup.py
  20. 7
      src/compiler/cpp_generator.cc
  21. 3
      src/compiler/generator_helpers.h
  22. 14
      src/compiler/node_generator.cc
  23. 6
      src/core/ext/census/grpc_filter.c
  24. 34
      src/core/ext/client_config/channel_connectivity.c
  25. 111
      src/core/ext/client_config/client_channel.c
  26. 2
      src/core/ext/client_config/connector.h
  27. 11
      src/core/ext/client_config/lb_policy.c
  28. 8
      src/core/ext/client_config/lb_policy.h
  29. 89
      src/core/ext/client_config/subchannel.c
  30. 2
      src/core/ext/client_config/subchannel.h
  31. 47
      src/core/ext/client_config/subchannel_call_holder.c
  32. 78
      src/core/ext/lb_policy/pick_first/pick_first.c
  33. 61
      src/core/ext/lb_policy/round_robin/round_robin.c
  34. 31
      src/core/ext/resolver/dns/native/dns_resolver.c
  35. 4
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  36. 513
      src/core/ext/resolver/zookeeper/zookeeper_resolver.c
  37. 8
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  38. 26
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  39. 63
      src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
  40. 91
      src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
  41. 373
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  42. 8
      src/core/ext/transport/chttp2/transport/frame.h
  43. 71
      src/core/ext/transport/chttp2/transport/frame_data.c
  44. 11
      src/core/ext/transport/chttp2/transport/frame_data.h
  45. 37
      src/core/ext/transport/chttp2/transport/frame_goaway.c
  46. 4
      src/core/ext/transport/chttp2/transport/frame_goaway.h
  47. 19
      src/core/ext/transport/chttp2/transport/frame_ping.c
  48. 6
      src/core/ext/transport/chttp2/transport/frame_ping.h
  49. 30
      src/core/ext/transport/chttp2/transport/frame_rst_stream.c
  50. 4
      src/core/ext/transport/chttp2/transport/frame_rst_stream.h
  51. 44
      src/core/ext/transport/chttp2/transport/frame_settings.c
  52. 4
      src/core/ext/transport/chttp2/transport/frame_settings.h
  53. 26
      src/core/ext/transport/chttp2/transport/frame_window_update.c
  54. 4
      src/core/ext/transport/chttp2/transport/frame_window_update.h
  55. 650
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  56. 14
      src/core/ext/transport/chttp2/transport/hpack_parser.h
  57. 44
      src/core/ext/transport/chttp2/transport/hpack_table.c
  58. 9
      src/core/ext/transport/chttp2/transport/hpack_table.h
  59. 39
      src/core/ext/transport/chttp2/transport/internal.h
  60. 437
      src/core/ext/transport/chttp2/transport/parsing.c
  61. 17
      src/core/ext/transport/chttp2/transport/writing.c
  62. 4
      src/core/ext/transport/cronet/transport/cronet_transport.c
  63. 3
      src/core/lib/channel/channel_args.c
  64. 6
      src/core/lib/channel/compress_filter.c
  65. 5
      src/core/lib/channel/http_client_filter.c
  66. 27
      src/core/lib/channel/http_server_filter.c
  67. 123
      src/core/lib/http/httpcli.c
  68. 21
      src/core/lib/http/httpcli.h
  69. 6
      src/core/lib/http/httpcli_security_connector.c
  70. 246
      src/core/lib/http/parser.c
  71. 357
      src/core/lib/http/parser.c.orig
  72. 17
      src/core/lib/http/parser.h
  73. 36
      src/core/lib/iomgr/closure.c
  74. 34
      src/core/lib/iomgr/closure.h
  75. 2
      src/core/lib/iomgr/endpoint.h
  76. 4
      src/core/lib/iomgr/endpoint_pair_posix.c
  77. 535
      src/core/lib/iomgr/error.c
  78. 192
      src/core/lib/iomgr/error.h
  79. 205
      src/core/lib/iomgr/ev_poll_and_epoll_posix.c
  80. 149
      src/core/lib/iomgr/ev_poll_posix.c
  81. 20
      src/core/lib/iomgr/ev_posix.c
  82. 18
      src/core/lib/iomgr/ev_posix.h
  83. 15
      src/core/lib/iomgr/exec_ctx.c
  84. 6
      src/core/lib/iomgr/exec_ctx.h
  85. 4
      src/core/lib/iomgr/executor.c
  86. 2
      src/core/lib/iomgr/executor.h
  87. 41
      src/core/lib/iomgr/iocp_windows.c
  88. 8
      src/core/lib/iomgr/iocp_windows.h
  89. 32
      src/core/lib/iomgr/load_file.c
  90. 15
      src/core/lib/iomgr/load_file.h
  91. 11
      src/core/lib/iomgr/pollset.h
  92. 16
      src/core/lib/iomgr/pollset_windows.c
  93. 14
      src/core/lib/iomgr/resolve_address.h
  94. 93
      src/core/lib/iomgr/resolve_address_posix.c
  95. 86
      src/core/lib/iomgr/resolve_address_windows.c
  96. 135
      src/core/lib/iomgr/socket_utils_common_posix.c
  97. 35
      src/core/lib/iomgr/socket_utils_posix.h
  98. 61
      src/core/lib/iomgr/socket_windows.c
  99. 13
      src/core/lib/iomgr/socket_windows.h
  100. 93
      src/core/lib/iomgr/tcp_client_posix.c
  101. Some files were not shown because too many files have changed in this diff Show More

46
BUILD

@ -49,7 +49,6 @@ cc_library(
"src/core/lib/support/backoff.h",
"src/core/lib/support/block_annotate.h",
"src/core/lib/support/env.h",
"src/core/lib/support/load_file.h",
"src/core/lib/support/murmur_hash.h",
"src/core/lib/support/stack_lockfree.h",
"src/core/lib/support/string.h",
@ -72,7 +71,6 @@ cc_library(
"src/core/lib/support/env_windows.c",
"src/core/lib/support/histogram.c",
"src/core/lib/support/host_port.c",
"src/core/lib/support/load_file.c",
"src/core/lib/support/log.c",
"src/core/lib/support/log_android.c",
"src/core/lib/support/log_linux.c",
@ -178,6 +176,7 @@ cc_library(
"src/core/lib/iomgr/closure.h",
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/ev_epoll_linux.h",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
"src/core/lib/iomgr/ev_poll_posix.h",
@ -188,6 +187,7 @@ cc_library(
"src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_internal.h",
"src/core/lib/iomgr/iomgr_posix.h",
"src/core/lib/iomgr/load_file.h",
"src/core/lib/iomgr/polling_entity.h",
"src/core/lib/iomgr/pollset.h",
"src/core/lib/iomgr/pollset_set.h",
@ -275,6 +275,7 @@ cc_library(
"src/core/lib/security/transport/handshake.h",
"src/core/lib/security/transport/secure_endpoint.h",
"src/core/lib/security/transport/security_connector.h",
"src/core/lib/security/transport/tsi_error.h",
"src/core/lib/security/util/b64.h",
"src/core/lib/security/util/json_util.h",
"src/core/lib/tsi/fake_transport_security.h",
@ -327,6 +328,7 @@ cc_library(
"src/core/lib/iomgr/endpoint.c",
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll_linux.c",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
"src/core/lib/iomgr/ev_poll_posix.c",
@ -337,6 +339,7 @@ cc_library(
"src/core/lib/iomgr/iomgr.c",
"src/core/lib/iomgr/iomgr_posix.c",
"src/core/lib/iomgr/iomgr_windows.c",
"src/core/lib/iomgr/load_file.c",
"src/core/lib/iomgr/polling_entity.c",
"src/core/lib/iomgr/pollset_set_windows.c",
"src/core/lib/iomgr/pollset_windows.c",
@ -439,6 +442,7 @@ cc_library(
"src/core/lib/security/transport/secure_endpoint.c",
"src/core/lib/security/transport/security_connector.c",
"src/core/lib/security/transport/server_auth_filter.c",
"src/core/lib/security/transport/tsi_error.c",
"src/core/lib/security/util/b64.c",
"src/core/lib/security/util/json_util.c",
"src/core/lib/surface/init_secure.c",
@ -558,6 +562,7 @@ cc_library(
"src/core/lib/iomgr/closure.h",
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/ev_epoll_linux.h",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
"src/core/lib/iomgr/ev_poll_posix.h",
@ -568,6 +573,7 @@ cc_library(
"src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_internal.h",
"src/core/lib/iomgr/iomgr_posix.h",
"src/core/lib/iomgr/load_file.h",
"src/core/lib/iomgr/polling_entity.h",
"src/core/lib/iomgr/pollset.h",
"src/core/lib/iomgr/pollset_set.h",
@ -672,6 +678,7 @@ cc_library(
"src/core/lib/security/transport/handshake.h",
"src/core/lib/security/transport/secure_endpoint.h",
"src/core/lib/security/transport/security_connector.h",
"src/core/lib/security/transport/tsi_error.h",
"src/core/lib/security/util/b64.h",
"src/core/lib/security/util/json_util.h",
"src/core/lib/tsi/fake_transport_security.h",
@ -697,6 +704,7 @@ cc_library(
"src/core/lib/iomgr/endpoint.c",
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll_linux.c",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
"src/core/lib/iomgr/ev_poll_posix.c",
@ -707,6 +715,7 @@ cc_library(
"src/core/lib/iomgr/iomgr.c",
"src/core/lib/iomgr/iomgr_posix.c",
"src/core/lib/iomgr/iomgr_windows.c",
"src/core/lib/iomgr/load_file.c",
"src/core/lib/iomgr/polling_entity.c",
"src/core/lib/iomgr/pollset_set_windows.c",
"src/core/lib/iomgr/pollset_windows.c",
@ -831,6 +840,7 @@ cc_library(
"src/core/lib/security/transport/secure_endpoint.c",
"src/core/lib/security/transport/security_connector.c",
"src/core/lib/security/transport/server_auth_filter.c",
"src/core/lib/security/transport/tsi_error.c",
"src/core/lib/security/util/b64.c",
"src/core/lib/security/util/json_util.c",
"src/core/lib/surface/init_secure.c",
@ -903,6 +913,7 @@ cc_library(
"src/core/lib/iomgr/closure.h",
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/ev_epoll_linux.h",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
"src/core/lib/iomgr/ev_poll_posix.h",
@ -913,6 +924,7 @@ cc_library(
"src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_internal.h",
"src/core/lib/iomgr/iomgr_posix.h",
"src/core/lib/iomgr/load_file.h",
"src/core/lib/iomgr/polling_entity.h",
"src/core/lib/iomgr/pollset.h",
"src/core/lib/iomgr/pollset_set.h",
@ -1030,6 +1042,7 @@ cc_library(
"src/core/lib/iomgr/endpoint.c",
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll_linux.c",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
"src/core/lib/iomgr/ev_poll_posix.c",
@ -1040,6 +1053,7 @@ cc_library(
"src/core/lib/iomgr/iomgr.c",
"src/core/lib/iomgr/iomgr_posix.c",
"src/core/lib/iomgr/iomgr_windows.c",
"src/core/lib/iomgr/load_file.c",
"src/core/lib/iomgr/polling_entity.c",
"src/core/lib/iomgr/pollset_set_windows.c",
"src/core/lib/iomgr/pollset_windows.c",
@ -1208,26 +1222,6 @@ cc_library(
cc_library(
name = "grpc_zookeeper",
srcs = [
"src/core/ext/resolver/zookeeper/zookeeper_resolver.c",
],
hdrs = [
"include/grpc/grpc_zookeeper.h",
],
includes = [
"include",
".",
],
deps = [
":gpr",
":grpc",
],
)
cc_library(
name = "grpc++",
srcs = [
@ -1689,7 +1683,6 @@ objc_library(
"src/core/lib/support/env_windows.c",
"src/core/lib/support/histogram.c",
"src/core/lib/support/host_port.c",
"src/core/lib/support/load_file.c",
"src/core/lib/support/log.c",
"src/core/lib/support/log_android.c",
"src/core/lib/support/log_linux.c",
@ -1768,7 +1761,6 @@ objc_library(
"src/core/lib/support/backoff.h",
"src/core/lib/support/block_annotate.h",
"src/core/lib/support/env.h",
"src/core/lib/support/load_file.h",
"src/core/lib/support/murmur_hash.h",
"src/core/lib/support/stack_lockfree.h",
"src/core/lib/support/string.h",
@ -1808,6 +1800,7 @@ objc_library(
"src/core/lib/iomgr/endpoint.c",
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll_linux.c",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
"src/core/lib/iomgr/ev_poll_posix.c",
@ -1818,6 +1811,7 @@ objc_library(
"src/core/lib/iomgr/iomgr.c",
"src/core/lib/iomgr/iomgr_posix.c",
"src/core/lib/iomgr/iomgr_windows.c",
"src/core/lib/iomgr/load_file.c",
"src/core/lib/iomgr/polling_entity.c",
"src/core/lib/iomgr/pollset_set_windows.c",
"src/core/lib/iomgr/pollset_windows.c",
@ -1920,6 +1914,7 @@ objc_library(
"src/core/lib/security/transport/secure_endpoint.c",
"src/core/lib/security/transport/security_connector.c",
"src/core/lib/security/transport/server_auth_filter.c",
"src/core/lib/security/transport/tsi_error.c",
"src/core/lib/security/util/b64.c",
"src/core/lib/security/util/json_util.c",
"src/core/lib/surface/init_secure.c",
@ -2018,6 +2013,7 @@ objc_library(
"src/core/lib/iomgr/closure.h",
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/ev_epoll_linux.h",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
"src/core/lib/iomgr/ev_poll_posix.h",
@ -2028,6 +2024,7 @@ objc_library(
"src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_internal.h",
"src/core/lib/iomgr/iomgr_posix.h",
"src/core/lib/iomgr/load_file.h",
"src/core/lib/iomgr/polling_entity.h",
"src/core/lib/iomgr/pollset.h",
"src/core/lib/iomgr/pollset_set.h",
@ -2115,6 +2112,7 @@ objc_library(
"src/core/lib/security/transport/handshake.h",
"src/core/lib/security/transport/secure_endpoint.h",
"src/core/lib/security/transport/security_connector.h",
"src/core/lib/security/transport/tsi_error.h",
"src/core/lib/security/util/b64.h",
"src/core/lib/security/util/json_util.h",
"src/core/lib/tsi/fake_transport_security.h",

@ -922,7 +922,6 @@ gpr_cpu_test: $(BINDIR)/$(CONFIG)/gpr_cpu_test
gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test
gpr_histogram_test: $(BINDIR)/$(CONFIG)/gpr_histogram_test
gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test
gpr_load_file_test: $(BINDIR)/$(CONFIG)/gpr_load_file_test
gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test
gpr_slice_buffer_test: $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test
gpr_slice_test: $(BINDIR)/$(CONFIG)/gpr_slice_test
@ -951,8 +950,9 @@ grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt
hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test
hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test
hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test
http_fuzzer_test: $(BINDIR)/$(CONFIG)/http_fuzzer_test
http_parser_test: $(BINDIR)/$(CONFIG)/http_parser_test
http_request_fuzzer_test: $(BINDIR)/$(CONFIG)/http_request_fuzzer_test
http_response_fuzzer_test: $(BINDIR)/$(CONFIG)/http_response_fuzzer_test
httpcli_format_request_test: $(BINDIR)/$(CONFIG)/httpcli_format_request_test
httpcli_test: $(BINDIR)/$(CONFIG)/httpcli_test
httpscli_test: $(BINDIR)/$(CONFIG)/httpscli_test
@ -968,6 +968,7 @@ json_stream_error_test: $(BINDIR)/$(CONFIG)/json_stream_error_test
json_test: $(BINDIR)/$(CONFIG)/json_test
lame_client_test: $(BINDIR)/$(CONFIG)/lame_client_test
lb_policies_test: $(BINDIR)/$(CONFIG)/lb_policies_test
load_file_test: $(BINDIR)/$(CONFIG)/load_file_test
low_level_ping_pong_benchmark: $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark
message_compress_test: $(BINDIR)/$(CONFIG)/message_compress_test
mlog_test: $(BINDIR)/$(CONFIG)/mlog_test
@ -979,6 +980,7 @@ no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test
secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test
secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test
sequential_connectivity_test: $(BINDIR)/$(CONFIG)/sequential_connectivity_test
server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
server_fuzzer: $(BINDIR)/$(CONFIG)/server_fuzzer
server_test: $(BINDIR)/$(CONFIG)/server_test
@ -1050,7 +1052,6 @@ status_test: $(BINDIR)/$(CONFIG)/status_test
streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test
stress_test: $(BINDIR)/$(CONFIG)/stress_test
thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
zookeeper_test: $(BINDIR)/$(CONFIG)/zookeeper_test
public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89
boringssl_aes_test: $(BINDIR)/$(CONFIG)/boringssl_aes_test
boringssl_asn1_test: $(BINDIR)/$(CONFIG)/boringssl_asn1_test
@ -1136,7 +1137,8 @@ h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test
api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry
hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry
http_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry
http_request_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry
http_response_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry
json_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry
nanopb_fuzzer_response_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry
nanopb_fuzzer_serverlist_test_one_entry: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry
@ -1182,8 +1184,8 @@ shared_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)
shared_csharp: shared_c $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT)
ifeq ($(HAS_ZOOKEEPER),true)
static_zookeeper_libs: $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
shared_zookeeper_libs: $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)
static_zookeeper_libs:
shared_zookeeper_libs:
else
static_zookeeper_libs:
@ -1213,7 +1215,12 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc
pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
ifeq ($(EMBED_OPENSSL),true)
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a
else
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a
endif
ifeq ($(HAS_ZOOKEEPER),true)
privatelibs_zookeeper:
@ -1258,7 +1265,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/gpr_env_test \
$(BINDIR)/$(CONFIG)/gpr_histogram_test \
$(BINDIR)/$(CONFIG)/gpr_host_port_test \
$(BINDIR)/$(CONFIG)/gpr_load_file_test \
$(BINDIR)/$(CONFIG)/gpr_log_test \
$(BINDIR)/$(CONFIG)/gpr_slice_buffer_test \
$(BINDIR)/$(CONFIG)/gpr_slice_test \
@ -1297,6 +1303,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/json_test \
$(BINDIR)/$(CONFIG)/lame_client_test \
$(BINDIR)/$(CONFIG)/lb_policies_test \
$(BINDIR)/$(CONFIG)/load_file_test \
$(BINDIR)/$(CONFIG)/message_compress_test \
$(BINDIR)/$(CONFIG)/mlog_test \
$(BINDIR)/$(CONFIG)/multiple_server_queues_test \
@ -1305,6 +1312,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/resolve_address_test \
$(BINDIR)/$(CONFIG)/secure_channel_create_test \
$(BINDIR)/$(CONFIG)/secure_endpoint_test \
$(BINDIR)/$(CONFIG)/sequential_connectivity_test \
$(BINDIR)/$(CONFIG)/server_chttp2_test \
$(BINDIR)/$(CONFIG)/server_test \
$(BINDIR)/$(CONFIG)/set_initial_connect_string_test \
@ -1372,7 +1380,8 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/api_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \
$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry \
$(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry \
$(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry \
$(BINDIR)/$(CONFIG)/json_fuzzer_test_one_entry \
$(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test_one_entry \
$(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test_one_entry \
@ -1380,6 +1389,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry \
ifeq ($(EMBED_OPENSSL),true)
buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \
@ -1463,10 +1473,57 @@ buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
$(BINDIR)/$(CONFIG)/boringssl_pqueue_test \
$(BINDIR)/$(CONFIG)/boringssl_ssl_test \
else
buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/cli_call_test \
$(BINDIR)/$(CONFIG)/client_crash_test \
$(BINDIR)/$(CONFIG)/client_crash_test_server \
$(BINDIR)/$(CONFIG)/codegen_test_full \
$(BINDIR)/$(CONFIG)/codegen_test_minimal \
$(BINDIR)/$(CONFIG)/credentials_test \
$(BINDIR)/$(CONFIG)/cxx_byte_buffer_test \
$(BINDIR)/$(CONFIG)/cxx_slice_test \
$(BINDIR)/$(CONFIG)/cxx_string_ref_test \
$(BINDIR)/$(CONFIG)/cxx_time_test \
$(BINDIR)/$(CONFIG)/end2end_test \
$(BINDIR)/$(CONFIG)/generic_end2end_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
$(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/hybrid_end2end_test \
$(BINDIR)/$(CONFIG)/interop_client \
$(BINDIR)/$(CONFIG)/interop_server \
$(BINDIR)/$(CONFIG)/interop_test \
$(BINDIR)/$(CONFIG)/json_run_localhost \
$(BINDIR)/$(CONFIG)/metrics_client \
$(BINDIR)/$(CONFIG)/mock_test \
$(BINDIR)/$(CONFIG)/proto_server_reflection_test \
$(BINDIR)/$(CONFIG)/qps_interarrival_test \
$(BINDIR)/$(CONFIG)/qps_json_driver \
$(BINDIR)/$(CONFIG)/qps_openloop_test \
$(BINDIR)/$(CONFIG)/qps_worker \
$(BINDIR)/$(CONFIG)/reconnect_interop_client \
$(BINDIR)/$(CONFIG)/reconnect_interop_server \
$(BINDIR)/$(CONFIG)/secure_auth_context_test \
$(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \
$(BINDIR)/$(CONFIG)/server_builder_plugin_test \
$(BINDIR)/$(CONFIG)/server_crash_test \
$(BINDIR)/$(CONFIG)/server_crash_test_client \
$(BINDIR)/$(CONFIG)/shutdown_test \
$(BINDIR)/$(CONFIG)/status_test \
$(BINDIR)/$(CONFIG)/streaming_throughput_test \
$(BINDIR)/$(CONFIG)/stress_test \
$(BINDIR)/$(CONFIG)/thread_stress_test \
endif
ifeq ($(HAS_ZOOKEEPER),true)
buildtests_zookeeper: privatelibs_zookeeper \
$(BINDIR)/$(CONFIG)/zookeeper_test \
else
buildtests_zookeeper:
@ -1540,8 +1597,6 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/gpr_histogram_test || ( echo test gpr_histogram_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_host_port_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_host_port_test || ( echo test gpr_host_port_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_load_file_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_load_file_test || ( echo test gpr_load_file_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_log_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_log_test || ( echo test gpr_log_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_slice_buffer_test"
@ -1608,6 +1663,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/json_test || ( echo test json_test failed ; exit 1 )
$(E) "[RUN] Testing lame_client_test"
$(Q) $(BINDIR)/$(CONFIG)/lame_client_test || ( echo test lame_client_test failed ; exit 1 )
$(E) "[RUN] Testing load_file_test"
$(Q) $(BINDIR)/$(CONFIG)/load_file_test || ( echo test load_file_test failed ; exit 1 )
$(E) "[RUN] Testing message_compress_test"
$(Q) $(BINDIR)/$(CONFIG)/message_compress_test || ( echo test message_compress_test failed ; exit 1 )
$(E) "[RUN] Testing multiple_server_queues_test"
@ -1622,6 +1679,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/secure_channel_create_test || ( echo test secure_channel_create_test failed ; exit 1 )
$(E) "[RUN] Testing secure_endpoint_test"
$(Q) $(BINDIR)/$(CONFIG)/secure_endpoint_test || ( echo test secure_endpoint_test failed ; exit 1 )
$(E) "[RUN] Testing sequential_connectivity_test"
$(Q) $(BINDIR)/$(CONFIG)/sequential_connectivity_test || ( echo test sequential_connectivity_test failed ; exit 1 )
$(E) "[RUN] Testing server_chttp2_test"
$(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 )
$(E) "[RUN] Testing server_test"
@ -1813,8 +1872,6 @@ ifeq ($(CONFIG),opt)
$(E) "[STRIP] Stripping libgrpc_unsecure.a"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a
ifeq ($(HAS_ZOOKEEPER),true)
$(E) "[STRIP] Stripping libgrpc_zookeeper.a"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
endif
endif
@ -1839,8 +1896,6 @@ ifeq ($(CONFIG),opt)
$(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT)
ifeq ($(HAS_ZOOKEEPER),true)
$(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)
endif
endif
@ -1896,12 +1951,12 @@ else
$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -1911,12 +1966,12 @@ else
$(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -1926,12 +1981,12 @@ else
$(GENDIR)/src/proto/grpc/testing/control.pb.cc: src/proto/grpc/testing/control.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: src/proto/grpc/testing/control.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -1941,12 +1996,12 @@ else
$(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc: src/proto/grpc/testing/duplicate/echo_duplicate.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc: src/proto/grpc/testing/duplicate/echo_duplicate.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -1956,12 +2011,12 @@ else
$(GENDIR)/src/proto/grpc/testing/echo.pb.cc: src/proto/grpc/testing/echo.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc: src/proto/grpc/testing/echo.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -1971,12 +2026,12 @@ else
$(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc: src/proto/grpc/testing/echo_messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc: src/proto/grpc/testing/echo_messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -1986,12 +2041,12 @@ else
$(GENDIR)/src/proto/grpc/testing/empty.pb.cc: src/proto/grpc/testing/empty.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc: src/proto/grpc/testing/empty.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -2001,12 +2056,12 @@ else
$(GENDIR)/src/proto/grpc/testing/messages.pb.cc: src/proto/grpc/testing/messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc: src/proto/grpc/testing/messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -2016,12 +2071,12 @@ else
$(GENDIR)/src/proto/grpc/testing/metrics.pb.cc: src/proto/grpc/testing/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc: src/proto/grpc/testing/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -2031,12 +2086,12 @@ else
$(GENDIR)/src/proto/grpc/testing/payloads.pb.cc: src/proto/grpc/testing/payloads.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc: src/proto/grpc/testing/payloads.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -2046,12 +2101,12 @@ else
$(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -2061,12 +2116,12 @@ else
$(GENDIR)/src/proto/grpc/testing/stats.pb.cc: src/proto/grpc/testing/stats.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc: src/proto/grpc/testing/stats.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true)
@ -2076,12 +2131,12 @@ else
$(GENDIR)/src/proto/grpc/testing/test.pb.cc: src/proto/grpc/testing/test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc: src/proto/grpc/testing/test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
@ -2155,9 +2210,6 @@ install-static_c: static_c strip-static_c install-pkg-config_c
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(prefix)/lib/libgrpc_unsecure.a
ifeq ($(HAS_ZOOKEEPER),true)
$(E) "[INSTALL] Installing libgrpc_zookeeper.a"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(prefix)/lib/libgrpc_zookeeper.a
endif
install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx
@ -2211,15 +2263,6 @@ else ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc_unsecure.so
endif
ifeq ($(HAS_ZOOKEEPER),true)
$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/$(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT)
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper-imp.a $(prefix)/lib/libgrpc_zookeeper-imp.a
else ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc_zookeeper.so.0
$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc_zookeeper.so
endif
endif
ifneq ($(SYSTEM),MINGW32)
ifneq ($(SYSTEM),Darwin)
@ -2369,7 +2412,6 @@ LIBGPR_SRC = \
src/core/lib/support/env_windows.c \
src/core/lib/support/histogram.c \
src/core/lib/support/host_port.c \
src/core/lib/support/load_file.c \
src/core/lib/support/log.c \
src/core/lib/support/log_android.c \
src/core/lib/support/log_linux.c \
@ -2526,6 +2568,7 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll_linux.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -2536,6 +2579,7 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_windows.c \
@ -2638,6 +2682,7 @@ LIBGRPC_SRC = \
src/core/lib/security/transport/secure_endpoint.c \
src/core/lib/security/transport/security_connector.c \
src/core/lib/security/transport/server_auth_filter.c \
src/core/lib/security/transport/tsi_error.c \
src/core/lib/security/util/b64.c \
src/core/lib/security/util/json_util.c \
src/core/lib/surface/init_secure.c \
@ -2794,6 +2839,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll_linux.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -2804,6 +2850,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_windows.c \
@ -2928,6 +2975,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/security/transport/secure_endpoint.c \
src/core/lib/security/transport/security_connector.c \
src/core/lib/security/transport/server_auth_filter.c \
src/core/lib/security/transport/tsi_error.c \
src/core/lib/security/util/b64.c \
src/core/lib/security/util/json_util.c \
src/core/lib/surface/init_secure.c \
@ -3131,6 +3179,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll_linux.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -3141,6 +3190,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_windows.c \
@ -3334,49 +3384,6 @@ ifneq ($(NO_DEPS),true)
endif
LIBGRPC_ZOOKEEPER_SRC = \
src/core/ext/resolver/zookeeper/zookeeper_resolver.c \
PUBLIC_HEADERS_C += \
include/grpc/grpc_zookeeper.h \
LIBGRPC_ZOOKEEPER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_ZOOKEEPER_SRC))))
$(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a: $(ZLIB_DEP) $(LIBGRPC_ZOOKEEPER_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBGRPC_ZOOKEEPER_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a
endif
ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC_ZOOKEEPER_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc_zookeeper.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_zookeeper$(SHARED_VERSION).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC_ZOOKEEPER_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) -lgpr-imp -lgrpc-imp
else
$(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC_ZOOKEEPER_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin)
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC_ZOOKEEPER_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) -lgpr -lgrpc -lzookeeper_mt
else
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_zookeeper.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC_ZOOKEEPER_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) -lgpr -lgrpc -lzookeeper_mt
$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).so.0
$(Q) ln -sf $(SHARED_PREFIX)grpc_zookeeper$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper$(SHARED_VERSION).so
endif
endif
ifneq ($(NO_DEPS),true)
-include $(LIBGRPC_ZOOKEEPER_OBJS:.o=.dep)
endif
LIBRECONNECT_SERVER_SRC = \
test/core/util/reconnect_server.c \
@ -7678,38 +7685,6 @@ endif
endif
GPR_LOAD_FILE_TEST_SRC = \
test/core/support/load_file_test.c \
GPR_LOAD_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_LOAD_FILE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/gpr_load_file_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/gpr_load_file_test: $(GPR_LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(GPR_LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_load_file_test
endif
$(OBJDIR)/$(CONFIG)/test/core/support/load_file_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_gpr_load_file_test: $(GPR_LOAD_FILE_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(GPR_LOAD_FILE_TEST_OBJS:.o=.dep)
endif
endif
GPR_LOG_TEST_SRC = \
test/core/support/log_test.c \
@ -8606,66 +8581,98 @@ endif
endif
HTTP_FUZZER_TEST_SRC = \
test/core/http/fuzzer.c \
HTTP_PARSER_TEST_SRC = \
test/core/http/parser_test.c \
HTTP_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_FUZZER_TEST_SRC))))
HTTP_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_PARSER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/http_fuzzer_test: openssl_dep_error
$(BINDIR)/$(CONFIG)/http_parser_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/http_fuzzer_test: $(HTTP_FUZZER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(BINDIR)/$(CONFIG)/http_parser_test: $(HTTP_PARSER_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) $(LDXX) $(LDFLAGS) $(HTTP_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_fuzzer_test
$(Q) $(LD) $(LDFLAGS) $(HTTP_PARSER_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)/http_parser_test
endif
$(OBJDIR)/$(CONFIG)/test/core/http/fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/core/http/parser_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_http_fuzzer_test: $(HTTP_FUZZER_TEST_OBJS:.o=.dep)
deps_http_parser_test: $(HTTP_PARSER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(HTTP_FUZZER_TEST_OBJS:.o=.dep)
-include $(HTTP_PARSER_TEST_OBJS:.o=.dep)
endif
endif
HTTP_PARSER_TEST_SRC = \
test/core/http/parser_test.c \
HTTP_REQUEST_FUZZER_TEST_SRC = \
test/core/http/request_fuzzer.c \
HTTP_PARSER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_PARSER_TEST_SRC))))
HTTP_REQUEST_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/http_parser_test: openssl_dep_error
$(BINDIR)/$(CONFIG)/http_request_fuzzer_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/http_parser_test: $(HTTP_PARSER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(BINDIR)/$(CONFIG)/http_request_fuzzer_test: $(HTTP_REQUEST_FUZZER_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) $(HTTP_PARSER_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)/http_parser_test
$(Q) $(LDXX) $(LDFLAGS) $(HTTP_REQUEST_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_request_fuzzer_test
endif
$(OBJDIR)/$(CONFIG)/test/core/http/parser_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/core/http/request_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_http_parser_test: $(HTTP_PARSER_TEST_OBJS:.o=.dep)
deps_http_request_fuzzer_test: $(HTTP_REQUEST_FUZZER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(HTTP_PARSER_TEST_OBJS:.o=.dep)
-include $(HTTP_REQUEST_FUZZER_TEST_OBJS:.o=.dep)
endif
endif
HTTP_RESPONSE_FUZZER_TEST_SRC = \
test/core/http/response_fuzzer.c \
HTTP_RESPONSE_FUZZER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/http_response_fuzzer_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/http_response_fuzzer_test: $(HTTP_RESPONSE_FUZZER_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) $(LDXX) $(LDFLAGS) $(HTTP_RESPONSE_FUZZER_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) -lFuzzer -o $(BINDIR)/$(CONFIG)/http_response_fuzzer_test
endif
$(OBJDIR)/$(CONFIG)/test/core/http/response_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_http_response_fuzzer_test: $(HTTP_RESPONSE_FUZZER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(HTTP_RESPONSE_FUZZER_TEST_OBJS:.o=.dep)
endif
endif
@ -9150,6 +9157,38 @@ endif
endif
LOAD_FILE_TEST_SRC = \
test/core/iomgr/load_file_test.c \
LOAD_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LOAD_FILE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/load_file_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/load_file_test: $(LOAD_FILE_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) $(LOAD_FILE_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)/load_file_test
endif
$(OBJDIR)/$(CONFIG)/test/core/iomgr/load_file_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_load_file_test: $(LOAD_FILE_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(LOAD_FILE_TEST_OBJS:.o=.dep)
endif
endif
LOW_LEVEL_PING_PONG_BENCHMARK_SRC = \
test/core/network_benchmarks/low_level_ping_pong.c \
@ -9502,6 +9541,38 @@ endif
endif
SEQUENTIAL_CONNECTIVITY_TEST_SRC = \
test/core/surface/sequential_connectivity_test.c \
SEQUENTIAL_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SEQUENTIAL_CONNECTIVITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/sequential_connectivity_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_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) $(SEQUENTIAL_CONNECTIVITY_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)/sequential_connectivity_test
endif
$(OBJDIR)/$(CONFIG)/test/core/surface/sequential_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_sequential_connectivity_test: $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SEQUENTIAL_CONNECTIVITY_TEST_OBJS:.o=.dep)
endif
endif
SERVER_CHTTP2_TEST_SRC = \
test/core/surface/server_chttp2_test.c \
@ -12313,53 +12384,6 @@ endif
endif
ZOOKEEPER_TEST_SRC = \
$(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \
test/cpp/end2end/zookeeper_test.cc \
ZOOKEEPER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ZOOKEEPER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/zookeeper_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/zookeeper_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/zookeeper_test: $(PROTOBUF_DEP) $(ZOOKEEPER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(ZOOKEEPER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -lzookeeper_mt $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/zookeeper_test
endif
endif
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/cpp/end2end/zookeeper_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc_zookeeper.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_zookeeper_test: $(ZOOKEEPER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(ZOOKEEPER_TEST_OBJS:.o=.dep)
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/end2end/zookeeper_test.o: $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc
PUBLIC_HEADERS_MUST_BE_C89_SRC = \
test/core/surface/public_headers_must_be_c89.c \
@ -14639,37 +14663,72 @@ endif
endif
HTTP_FUZZER_TEST_ONE_ENTRY_SRC = \
test/core/http/fuzzer.c \
HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC = \
test/core/http/request_fuzzer.c \
test/core/util/one_corpus_entry_fuzzer.c \
HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/http_request_fuzzer_test_one_entry: $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_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) $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_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)/http_request_fuzzer_test_one_entry
endif
$(OBJDIR)/$(CONFIG)/test/core/http/request_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_http_request_fuzzer_test_one_entry: $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(HTTP_REQUEST_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
endif
endif
HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC = \
test/core/http/response_fuzzer.c \
test/core/util/one_corpus_entry_fuzzer.c \
HTTP_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_FUZZER_TEST_ONE_ENTRY_SRC))))
HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry: openssl_dep_error
$(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry: $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(BINDIR)/$(CONFIG)/http_response_fuzzer_test_one_entry: $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_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) $(HTTP_FUZZER_TEST_ONE_ENTRY_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)/http_fuzzer_test_one_entry
$(Q) $(LD) $(LDFLAGS) $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_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)/http_response_fuzzer_test_one_entry
endif
$(OBJDIR)/$(CONFIG)/test/core/http/fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/core/http/response_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_http_fuzzer_test_one_entry: $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
deps_http_response_fuzzer_test_one_entry: $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(HTTP_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
-include $(HTTP_RESPONSE_FUZZER_TEST_ONE_ENTRY_OBJS:.o=.dep)
endif
endif
@ -14883,6 +14942,7 @@ src/core/lib/security/transport/handshake.c: $(OPENSSL_DEP)
src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP)
src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP)
src/core/lib/security/transport/server_auth_filter.c: $(OPENSSL_DEP)
src/core/lib/security/transport/tsi_error.c: $(OPENSSL_DEP)
src/core/lib/security/util/b64.c: $(OPENSSL_DEP)
src/core/lib/security/util/json_util.c: $(OPENSSL_DEP)
src/core/lib/surface/init_secure.c: $(OPENSSL_DEP)

@ -510,7 +510,6 @@
'src/core/lib/support/env_windows.c',
'src/core/lib/support/histogram.c',
'src/core/lib/support/host_port.c',
'src/core/lib/support/load_file.c',
'src/core/lib/support/log.c',
'src/core/lib/support/log_android.c',
'src/core/lib/support/log_linux.c',
@ -581,6 +580,7 @@
'src/core/lib/iomgr/endpoint.c',
'src/core/lib/iomgr/endpoint_pair_posix.c',
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll_linux.c',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
'src/core/lib/iomgr/ev_poll_posix.c',
@ -591,6 +591,7 @@
'src/core/lib/iomgr/iomgr.c',
'src/core/lib/iomgr/iomgr_posix.c',
'src/core/lib/iomgr/iomgr_windows.c',
'src/core/lib/iomgr/load_file.c',
'src/core/lib/iomgr/polling_entity.c',
'src/core/lib/iomgr/pollset_set_windows.c',
'src/core/lib/iomgr/pollset_windows.c',
@ -693,6 +694,7 @@
'src/core/lib/security/transport/secure_endpoint.c',
'src/core/lib/security/transport/security_connector.c',
'src/core/lib/security/transport/server_auth_filter.c',
'src/core/lib/security/transport/tsi_error.c',
'src/core/lib/security/util/b64.c',
'src/core/lib/security/util/json_util.c',
'src/core/lib/surface/init_secure.c',

@ -70,7 +70,6 @@ filegroups:
- src/core/lib/support/backoff.h
- src/core/lib/support/block_annotate.h
- src/core/lib/support/env.h
- src/core/lib/support/load_file.h
- src/core/lib/support/murmur_hash.h
- src/core/lib/support/stack_lockfree.h
- src/core/lib/support/string.h
@ -94,7 +93,6 @@ filegroups:
- src/core/lib/support/env_windows.c
- src/core/lib/support/histogram.c
- src/core/lib/support/host_port.c
- src/core/lib/support/load_file.c
- src/core/lib/support/log.c
- src/core/lib/support/log_android.c
- src/core/lib/support/log_linux.c
@ -174,6 +172,7 @@ filegroups:
- src/core/lib/iomgr/closure.h
- src/core/lib/iomgr/endpoint.h
- src/core/lib/iomgr/endpoint_pair.h
- src/core/lib/iomgr/error.h
- src/core/lib/iomgr/ev_epoll_linux.h
- src/core/lib/iomgr/ev_poll_and_epoll_posix.h
- src/core/lib/iomgr/ev_poll_posix.h
@ -184,6 +183,7 @@ filegroups:
- src/core/lib/iomgr/iomgr.h
- src/core/lib/iomgr/iomgr_internal.h
- src/core/lib/iomgr/iomgr_posix.h
- src/core/lib/iomgr/load_file.h
- src/core/lib/iomgr/polling_entity.h
- src/core/lib/iomgr/pollset.h
- src/core/lib/iomgr/pollset_set.h
@ -251,6 +251,7 @@ filegroups:
- src/core/lib/iomgr/endpoint.c
- src/core/lib/iomgr/endpoint_pair_posix.c
- src/core/lib/iomgr/endpoint_pair_windows.c
- src/core/lib/iomgr/error.c
- src/core/lib/iomgr/ev_epoll_linux.c
- src/core/lib/iomgr/ev_poll_and_epoll_posix.c
- src/core/lib/iomgr/ev_poll_posix.c
@ -261,6 +262,7 @@ filegroups:
- src/core/lib/iomgr/iomgr.c
- src/core/lib/iomgr/iomgr_posix.c
- src/core/lib/iomgr/iomgr_windows.c
- src/core/lib/iomgr/load_file.c
- src/core/lib/iomgr/polling_entity.c
- src/core/lib/iomgr/pollset_set_windows.c
- src/core/lib/iomgr/pollset_windows.c
@ -444,6 +446,7 @@ filegroups:
- src/core/lib/security/transport/handshake.h
- src/core/lib/security/transport/secure_endpoint.h
- src/core/lib/security/transport/security_connector.h
- src/core/lib/security/transport/tsi_error.h
- src/core/lib/security/util/b64.h
- src/core/lib/security/util/json_util.h
src:
@ -468,6 +471,7 @@ filegroups:
- src/core/lib/security/transport/secure_endpoint.c
- src/core/lib/security/transport/security_connector.c
- src/core/lib/security/transport/server_auth_filter.c
- src/core/lib/security/transport/tsi_error.c
- src/core/lib/security/util/b64.c
- src/core/lib/security/util/json_util.c
- src/core/lib/surface/init_secure.c
@ -899,21 +903,6 @@ libs:
generate_plugin_registry: true
secure: false
vs_project_guid: '{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}'
- name: grpc_zookeeper
build: all
language: c
public_headers:
- include/grpc/grpc_zookeeper.h
src:
- src/core/ext/resolver/zookeeper/zookeeper_resolver.c
deps:
- gpr
- grpc
external_deps:
- zookeeper
platforms:
- linux
secure: false
- name: reconnect_server
build: private
language: c
@ -1470,7 +1459,7 @@ targets:
- gpr_test_util
- gpr
- name: fling_stream_test
cpu_cost: 2
cpu_cost: 1.5
build: test
language: c
src:
@ -1485,7 +1474,7 @@ targets:
- linux
- posix
- name: fling_test
cpu_cost: 2
cpu_cost: 1.5
build: test
language: c
src:
@ -1584,14 +1573,6 @@ targets:
deps:
- gpr_test_util
- gpr
- name: gpr_load_file_test
build: test
language: c
src:
- test/core/support/load_file_test.c
deps:
- gpr_test_util
- gpr
- name: gpr_log_test
build: test
language: c
@ -1617,7 +1598,7 @@ targets:
- gpr_test_util
- gpr
- name: gpr_stack_lockfree_test
cpu_cost: 10
cpu_cost: 7
build: test
language: c
src:
@ -1863,11 +1844,21 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: http_fuzzer_test
- name: http_parser_test
build: test
language: c
src:
- test/core/http/parser_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: http_request_fuzzer_test
build: fuzzer
language: c
src:
- test/core/http/fuzzer.c
- test/core/http/request_fuzzer.c
deps:
- grpc_test_util
- grpc
@ -1876,16 +1867,19 @@ targets:
corpus_dirs:
- test/core/http/corpus
maxlen: 2048
- name: http_parser_test
build: test
- name: http_response_fuzzer_test
build: fuzzer
language: c
src:
- test/core/http/parser_test.c
- test/core/http/response_fuzzer.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
corpus_dirs:
- test/core/http/corpus
maxlen: 2048
- name: httpcli_format_request_test
build: test
language: c
@ -1968,6 +1962,7 @@ targets:
- gpr_test_util
- gpr
- name: invalid_call_argument_test
cpu_cost: 0.1
build: test
language: c
src:
@ -2051,6 +2046,16 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: load_file_test
build: test
language: c
src:
- test/core/iomgr/load_file_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: low_level_ping_pong_benchmark
build: benchmark
language: c
@ -2171,6 +2176,16 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: sequential_connectivity_test
build: test
language: c
src:
- test/core/surface/sequential_connectivity_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: server_chttp2_test
build: test
language: c
@ -2267,7 +2282,7 @@ targets:
- linux
- posix
- name: tcp_posix_test
cpu_cost: 0.5
cpu_cost: 0.2
build: test
language: c
src:
@ -3118,26 +3133,6 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: zookeeper_test
gtest: true
build: test
run: false
language: c++
src:
- src/proto/grpc/testing/echo.proto
- test/cpp/end2end/zookeeper_test.cc
deps:
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc_zookeeper
- grpc
- gpr_test_util
- gpr
external_deps:
- zookeeper
platforms:
- linux
- name: public_headers_must_be_c89
build: test
language: c89

@ -51,7 +51,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/support/env_windows.c \
src/core/lib/support/histogram.c \
src/core/lib/support/host_port.c \
src/core/lib/support/load_file.c \
src/core/lib/support/log.c \
src/core/lib/support/log_android.c \
src/core/lib/support/log_linux.c \
@ -100,6 +99,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll_linux.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
@ -110,6 +110,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_windows.c \
@ -212,6 +213,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/transport/secure_endpoint.c \
src/core/lib/security/transport/security_connector.c \
src/core/lib/security/transport/server_auth_filter.c \
src/core/lib/security/transport/tsi_error.c \
src/core/lib/security/util/b64.c \
src/core/lib/security/util/json_util.c \
src/core/lib/surface/init_secure.c \

@ -53,6 +53,12 @@ default capture). Other C++ functional features such as
(../include/grpc++/impl/codegen/config.h). Instead, pointers should
be checked for validity using their implicit conversion to `bool`.
In other words, use `if (p)` rather than `if (p != nullptr)`
- Do not initialize global/static pointer variables to `nullptr`. Just let
the compiler implicitly initialize them to `nullptr` (which it will
definitely do). The reason is that `nullptr` is an actual object in
our implementation rather than just a constant pointer value, so
static/global constructors will be called in a potentially
undesirable sequence.
- Do not use `final` or `override` as these are not supported by some
compilers. Instead use `GRPC_FINAL` and `GRPC_OVERRIDE` . These
compile down to the traditional C++ forms for compilers that support

@ -51,7 +51,7 @@ def get_distance(start, end):
coord_factor = 10000000.0
lat_1 = start.latitude / coord_factor
lat_2 = end.latitude / coord_factor
lon_1 = start.latitude / coord_factor
lon_1 = start.longitude / coord_factor
lon_2 = end.longitude / coord_factor
lat_rad_1 = math.radians(lat_1)
lat_rad_2 = math.radians(lat_2)

@ -68,7 +68,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/backoff.h',
'src/core/lib/support/block_annotate.h',
'src/core/lib/support/env.h',
'src/core/lib/support/load_file.h',
'src/core/lib/support/murmur_hash.h',
'src/core/lib/support/stack_lockfree.h',
'src/core/lib/support/string.h',
@ -133,7 +132,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/env_windows.c',
'src/core/lib/support/histogram.c',
'src/core/lib/support/host_port.c',
'src/core/lib/support/load_file.c',
'src/core/lib/support/log.c',
'src/core/lib/support/log_android.c',
'src/core/lib/support/log_linux.c',
@ -181,6 +179,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/closure.h',
'src/core/lib/iomgr/endpoint.h',
'src/core/lib/iomgr/endpoint_pair.h',
'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/ev_epoll_linux.h',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
'src/core/lib/iomgr/ev_poll_posix.h',
@ -191,6 +190,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/iomgr.h',
'src/core/lib/iomgr/iomgr_internal.h',
'src/core/lib/iomgr/iomgr_posix.h',
'src/core/lib/iomgr/load_file.h',
'src/core/lib/iomgr/polling_entity.h',
'src/core/lib/iomgr/pollset.h',
'src/core/lib/iomgr/pollset_set.h',
@ -278,6 +278,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/handshake.h',
'src/core/lib/security/transport/secure_endpoint.h',
'src/core/lib/security/transport/security_connector.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/b64.h',
'src/core/lib/security/util/json_util.h',
'src/core/lib/tsi/fake_transport_security.h',
@ -364,6 +365,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/endpoint.c',
'src/core/lib/iomgr/endpoint_pair_posix.c',
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll_linux.c',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
'src/core/lib/iomgr/ev_poll_posix.c',
@ -374,6 +376,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/iomgr.c',
'src/core/lib/iomgr/iomgr_posix.c',
'src/core/lib/iomgr/iomgr_windows.c',
'src/core/lib/iomgr/load_file.c',
'src/core/lib/iomgr/polling_entity.c',
'src/core/lib/iomgr/pollset_set_windows.c',
'src/core/lib/iomgr/pollset_windows.c',
@ -476,6 +479,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/secure_endpoint.c',
'src/core/lib/security/transport/security_connector.c',
'src/core/lib/security/transport/server_auth_filter.c',
'src/core/lib/security/transport/tsi_error.c',
'src/core/lib/security/util/b64.c',
'src/core/lib/security/util/json_util.c',
'src/core/lib/surface/init_secure.c',
@ -533,7 +537,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/backoff.h',
'src/core/lib/support/block_annotate.h',
'src/core/lib/support/env.h',
'src/core/lib/support/load_file.h',
'src/core/lib/support/murmur_hash.h',
'src/core/lib/support/stack_lockfree.h',
'src/core/lib/support/string.h',
@ -558,6 +561,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/closure.h',
'src/core/lib/iomgr/endpoint.h',
'src/core/lib/iomgr/endpoint_pair.h',
'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/ev_epoll_linux.h',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
'src/core/lib/iomgr/ev_poll_posix.h',
@ -568,6 +572,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/iomgr.h',
'src/core/lib/iomgr/iomgr_internal.h',
'src/core/lib/iomgr/iomgr_posix.h',
'src/core/lib/iomgr/load_file.h',
'src/core/lib/iomgr/polling_entity.h',
'src/core/lib/iomgr/pollset.h',
'src/core/lib/iomgr/pollset_set.h',
@ -655,6 +660,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/handshake.h',
'src/core/lib/security/transport/secure_endpoint.h',
'src/core/lib/security/transport/security_connector.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/b64.h',
'src/core/lib/security/util/json_util.h',
'src/core/lib/tsi/fake_transport_security.h',

@ -223,6 +223,8 @@ EXPORTS
gpr_avl_add
gpr_avl_remove
gpr_avl_get
gpr_avl_maybe_get
gpr_avl_is_empty
gpr_cmdline_create
gpr_cmdline_add_int
gpr_cmdline_add_flag

@ -89,7 +89,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/backoff.h )
s.files += %w( src/core/lib/support/block_annotate.h )
s.files += %w( src/core/lib/support/env.h )
s.files += %w( src/core/lib/support/load_file.h )
s.files += %w( src/core/lib/support/murmur_hash.h )
s.files += %w( src/core/lib/support/stack_lockfree.h )
s.files += %w( src/core/lib/support/string.h )
@ -112,7 +111,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/env_windows.c )
s.files += %w( src/core/lib/support/histogram.c )
s.files += %w( src/core/lib/support/host_port.c )
s.files += %w( src/core/lib/support/load_file.c )
s.files += %w( src/core/lib/support/log.c )
s.files += %w( src/core/lib/support/log_android.c )
s.files += %w( src/core/lib/support/log_linux.c )
@ -190,6 +188,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/closure.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/error.h )
s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h )
s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
@ -200,6 +199,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/iomgr.h )
s.files += %w( src/core/lib/iomgr/iomgr_internal.h )
s.files += %w( src/core/lib/iomgr/iomgr_posix.h )
s.files += %w( src/core/lib/iomgr/load_file.h )
s.files += %w( src/core/lib/iomgr/polling_entity.h )
s.files += %w( src/core/lib/iomgr/pollset.h )
s.files += %w( src/core/lib/iomgr/pollset_set.h )
@ -287,6 +287,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/transport/handshake.h )
s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
s.files += %w( src/core/lib/security/transport/security_connector.h )
s.files += %w( src/core/lib/security/transport/tsi_error.h )
s.files += %w( src/core/lib/security/util/b64.h )
s.files += %w( src/core/lib/security/util/json_util.h )
s.files += %w( src/core/lib/tsi/fake_transport_security.h )
@ -343,6 +344,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/endpoint.c )
s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c )
s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c )
s.files += %w( src/core/lib/iomgr/error.c )
s.files += %w( src/core/lib/iomgr/ev_epoll_linux.c )
s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.c )
@ -353,6 +355,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/iomgr.c )
s.files += %w( src/core/lib/iomgr/iomgr_posix.c )
s.files += %w( src/core/lib/iomgr/iomgr_windows.c )
s.files += %w( src/core/lib/iomgr/load_file.c )
s.files += %w( src/core/lib/iomgr/polling_entity.c )
s.files += %w( src/core/lib/iomgr/pollset_set_windows.c )
s.files += %w( src/core/lib/iomgr/pollset_windows.c )
@ -455,6 +458,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/transport/secure_endpoint.c )
s.files += %w( src/core/lib/security/transport/security_connector.c )
s.files += %w( src/core/lib/security/transport/server_auth_filter.c )
s.files += %w( src/core/lib/security/transport/tsi_error.c )
s.files += %w( src/core/lib/security/util/b64.c )
s.files += %w( src/core/lib/security/util/json_util.c )
s.files += %w( src/core/lib/surface/init_secure.c )

@ -56,7 +56,7 @@ class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin {
bool has_sync_methods() const GRPC_OVERRIDE;
private:
std::shared_ptr<::grpc::ProtoServerReflection> reflection_service_;
std::shared_ptr<grpc::ProtoServerReflection> reflection_service_;
};
// Add proto reflection plugin to ServerBuilder. This function should be called

@ -337,7 +337,7 @@ class DeserializeFuncType GRPC_FINAL : public DeserializeFunc {
return SerializationTraits<R>::Deserialize(buf, message_, max_message_size);
}
~DeserializeFuncType() override {}
~DeserializeFuncType() GRPC_OVERRIDE {}
private:
R* message_; // Not a managed pointer because management is external to this

@ -54,6 +54,7 @@
// nullptr was added in gcc 4.6
#if (__GNUC__ * 100 + __GNUC_MINOR__ < 406)
#define GRPC_CXX0X_NO_NULLPTR 1
#define GRPC_CXX0X_LIMITED_TOSTRING 1
#endif
// final and override were added in gcc 4.7
#if (__GNUC__ * 100 + __GNUC_MINOR__ < 407)
@ -78,6 +79,7 @@
#endif
#ifdef GRPC_CXX0X_NO_NULLPTR
#include <functional>
#include <memory>
namespace grpc {
const class {
@ -95,6 +97,10 @@ const class {
return std::shared_ptr<T>(static_cast<T *>(0));
}
operator bool() const { return false; }
template <class F>
operator std::function<F>() const {
return std::function<F>();
}
private:
void operator&() const = delete;
@ -111,6 +117,17 @@ namespace grpc {
typedef GRPC_CUSTOM_STRING string;
#ifdef GRPC_CXX0X_LIMITED_TOSTRING
inline grpc::string to_string(const int x) {
return std::to_string(static_cast<const long long int>(x));
}
inline grpc::string to_string(const unsigned int x) {
return std::to_string(static_cast<const long long unsigned int>(x));
}
#else
using std::to_string;
#endif
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_CONFIG_H

@ -42,42 +42,44 @@ namespace grpc {
/// Implementation of the core codegen interface.
class CoreCodegen : public CoreCodegenInterface {
private:
grpc_completion_queue* grpc_completion_queue_create(void* reserved) override;
void grpc_completion_queue_destroy(grpc_completion_queue* cq) override;
grpc_completion_queue* grpc_completion_queue_create(void* reserved)
GRPC_OVERRIDE;
void grpc_completion_queue_destroy(grpc_completion_queue* cq) GRPC_OVERRIDE;
grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag,
gpr_timespec deadline,
void* reserved) override;
void* reserved) GRPC_OVERRIDE;
void* gpr_malloc(size_t size) override;
void gpr_free(void* p) override;
void* gpr_malloc(size_t size) GRPC_OVERRIDE;
void gpr_free(void* p) GRPC_OVERRIDE;
void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override;
void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) GRPC_OVERRIDE;
void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
grpc_byte_buffer* buffer) override;
void grpc_byte_buffer_reader_destroy(
grpc_byte_buffer_reader* reader) override;
grpc_byte_buffer* buffer) GRPC_OVERRIDE;
void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader* reader)
GRPC_OVERRIDE;
int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader,
gpr_slice* slice) override;
gpr_slice* slice) GRPC_OVERRIDE;
grpc_byte_buffer* grpc_raw_byte_buffer_create(gpr_slice* slice,
size_t nslices) override;
size_t nslices) GRPC_OVERRIDE;
gpr_slice gpr_slice_malloc(size_t length) override;
void gpr_slice_unref(gpr_slice slice) override;
gpr_slice gpr_slice_split_tail(gpr_slice* s, size_t split) override;
void gpr_slice_buffer_add(gpr_slice_buffer* sb, gpr_slice slice) override;
void gpr_slice_buffer_pop(gpr_slice_buffer* sb) override;
gpr_slice gpr_slice_malloc(size_t length) GRPC_OVERRIDE;
void gpr_slice_unref(gpr_slice slice) GRPC_OVERRIDE;
gpr_slice gpr_slice_split_tail(gpr_slice* s, size_t split) GRPC_OVERRIDE;
void gpr_slice_buffer_add(gpr_slice_buffer* sb,
gpr_slice slice) GRPC_OVERRIDE;
void gpr_slice_buffer_pop(gpr_slice_buffer* sb) GRPC_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_init(grpc_metadata_array* array) GRPC_OVERRIDE;
void grpc_metadata_array_destroy(grpc_metadata_array* array) GRPC_OVERRIDE;
gpr_timespec gpr_inf_future(gpr_clock_type type) override;
gpr_timespec gpr_inf_future(gpr_clock_type type) GRPC_OVERRIDE;
virtual const Status& ok() override;
virtual const Status& cancelled() override;
virtual const Status& ok() GRPC_OVERRIDE;
virtual const Status& cancelled() GRPC_OVERRIDE;
void assert_fail(const char* failed_assertion) override;
void assert_fail(const char* failed_assertion) GRPC_OVERRIDE;
};
} // namespace grpc

@ -50,8 +50,7 @@ class ServerBuilderOption {
virtual void UpdateArguments(ChannelArguments* args) = 0;
/// Alter the ServerBuilderPlugin map that will be added into ServerBuilder.
virtual void UpdatePlugins(
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin> >*
plugins) = 0;
std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) = 0;
};
} // namespace grpc

@ -174,7 +174,7 @@ class ServerBuilder {
std::vector<Port> ports_;
std::vector<ServerCompletionQueue*> cqs_;
std::shared_ptr<ServerCredentials> creds_;
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>> plugins_;
std::vector<std::unique_ptr<ServerBuilderPlugin>> plugins_;
AsyncGenericService* generic_service_;
struct {
bool is_set;

@ -88,5 +88,10 @@ GPRAPI gpr_avl gpr_avl_remove(gpr_avl avl, void *key);
does not mutate avl.
returns NULL if key is not found. */
GPRAPI void *gpr_avl_get(gpr_avl avl, void *key);
/** Return 1 if avl contains key, 0 otherwise; if it has the key, sets *value to
its value*/
GPRAPI int gpr_avl_maybe_get(gpr_avl avl, void *key, void **value);
/** Return 1 if avl is empty, 0 otherwise */
GPRAPI int gpr_avl_is_empty(gpr_avl avl);
#endif /* GRPC_SUPPORT_AVL_H */

@ -96,7 +96,6 @@
<file baseinstalldir="/" name="src/core/lib/support/backoff.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/block_annotate.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/env.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/load_file.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/murmur_hash.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" />
@ -119,7 +118,6 @@
<file baseinstalldir="/" name="src/core/lib/support/env_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/histogram.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/host_port.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/load_file.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/log.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/log_android.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/log_linux.c" role="src" />
@ -197,6 +195,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/closure.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/error.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_and_epoll_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
@ -207,6 +206,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/load_file.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/polling_entity.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset_set.h" role="src" />
@ -294,6 +294,7 @@
<file baseinstalldir="/" name="src/core/lib/security/transport/handshake.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/b64.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.h" role="src" />
@ -350,6 +351,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/error.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_linux.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_and_epoll_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.c" role="src" />
@ -360,6 +362,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/load_file.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/polling_entity.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset_set_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset_windows.c" role="src" />
@ -462,6 +465,7 @@
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/server_auth_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/b64.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/init_secure.c" role="src" />

@ -246,7 +246,6 @@ setuptools.setup(
ext_modules=CYTHON_EXTENSION_MODULES,
packages=list(PACKAGES),
package_dir=PACKAGE_DIRECTORIES,
namespace_packages=['grpc'],
package_data=PACKAGE_DATA,
install_requires=INSTALL_REQUIRES,
setup_requires=SETUP_REQUIRES,

@ -73,9 +73,10 @@ void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, c
vars["l"] = params.use_system_headers ? '<' : '"';
vars["r"] = params.use_system_headers ? '>' : '"';
if (!params.grpc_search_path.empty()) {
vars["l"] += params.grpc_search_path;
if (params.grpc_search_path.back() != '/') {
auto& s = params.grpc_search_path;
if (!s.empty()) {
vars["l"] += s;
if (s[s.size()-1] != '/') {
vars["l"] += '/';
}
}

@ -253,7 +253,8 @@ inline void GetComment(const grpc::protobuf::FileDescriptor *desc,
inline grpc::string GenerateCommentsWithPrefix(
const std::vector<grpc::string> &in, const grpc::string &prefix) {
std::ostringstream oss;
for (const grpc::string &elem : in) {
for (auto it = in.begin(); it != in.end(); it++) {
const grpc::string& elem = *it;
if (elem.empty()) {
oss << prefix << "\n";
} else if (elem[0] == ' ') {

@ -74,8 +74,16 @@ grpc::string GetJSMessageFilename(const grpc::string& filename) {
// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& filename) {
size_t slashes = std::count(filename.begin(), filename.end(), '/');
grpc::string GetRootPath(const grpc::string& from_filename,
const grpc::string& to_filename) {
if (to_filename.find("google/protobuf") == 0) {
// Well-known types (.proto files in the google/protobuf directory) are
// assumed to come from the 'google-protobuf' npm package. We may want to
// generalize this exception later by letting others put generated code in
// their own npm packages.
return "google-protobuf/";
}
size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
if (slashes == 0) {
return "./";
}
@ -90,7 +98,7 @@ grpc::string GetRootPath(const grpc::string& filename) {
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
const grpc::string& to_file) {
return GetRootPath(from_file) + to_file;
return GetRootPath(from_file, to_file) + to_file;
}
/* Finds all message types used in all services in the file, and returns them

@ -91,14 +91,14 @@ static void client_start_transport_op(grpc_exec_ctx *exec_ctx,
}
static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
bool success) {
grpc_error *error) {
grpc_call_element *elem = ptr;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
if (success) {
if (error == GRPC_ERROR_NONE) {
extract_and_annotate_method_tag(calld->recv_initial_metadata, calld, chand);
}
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error);
}
static void server_mutate_op(grpc_call_element *elem,

@ -75,7 +75,6 @@ typedef enum {
typedef struct {
gpr_mu mu;
callback_phase phase;
int success;
grpc_closure on_complete;
grpc_timer alarm;
grpc_connectivity_state state;
@ -122,7 +121,7 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
}
static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
int due_to_completion) {
bool due_to_completion, grpc_error *error) {
int delete = 0;
if (due_to_completion) {
@ -130,14 +129,26 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
}
gpr_mu_lock(&w->mu);
if (due_to_completion) {
w->success = 1;
if (grpc_trace_operation_failures) {
GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error));
}
GRPC_ERROR_UNREF(error);
error = GRPC_ERROR_NONE;
} else {
if (error == GRPC_ERROR_NONE) {
error =
GRPC_ERROR_CREATE("Timed out waiting for connection state change");
} else if (error == GRPC_ERROR_CANCELLED) {
error = GRPC_ERROR_NONE;
}
}
switch (w->phase) {
case WAITING:
w->phase = CALLING_BACK;
grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->success, finished_completion,
w, &w->completion_storage);
grpc_cq_end_op(exec_ctx, w->cq, w->tag, GRPC_ERROR_REF(error),
finished_completion, w, &w->completion_storage);
break;
case CALLING_BACK:
w->phase = CALLING_BACK_AND_FINISHED;
@ -153,14 +164,18 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
if (delete) {
delete_state_watcher(exec_ctx, w);
}
GRPC_ERROR_UNREF(error);
}
static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
partly_done(exec_ctx, pw, 1);
static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw,
grpc_error *error) {
partly_done(exec_ctx, pw, true, GRPC_ERROR_REF(error));
}
static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw, bool success) {
partly_done(exec_ctx, pw, 0);
static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw,
grpc_error *error) {
partly_done(exec_ctx, pw, false, GRPC_ERROR_REF(error));
}
void grpc_channel_watch_connectivity_state(
@ -185,7 +200,6 @@ void grpc_channel_watch_connectivity_state(
grpc_closure_init(&w->on_complete, watch_complete, w);
w->phase = WAITING;
w->state = last_observed_state;
w->success = 0;
w->cq = cq;
w->tag = tag;
w->channel = channel;

@ -117,6 +117,7 @@ static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
channel_data *chand,
grpc_connectivity_state state,
grpc_error *error,
const char *reason) {
if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
state == GRPC_CHANNEL_SHUTDOWN) &&
@ -127,11 +128,13 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
/* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY,
/* check= */ 0);
}
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, reason);
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
reason);
}
static void on_lb_policy_state_changed_locked(
grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
lb_policy_connectivity_watcher *w,
grpc_error *error) {
grpc_connectivity_state publish_state = w->state;
/* check if the notification is for a stale policy */
if (w->lb_policy != w->chand->lb_policy) return;
@ -143,18 +146,18 @@ static void on_lb_policy_state_changed_locked(
w->chand->lb_policy = NULL;
}
set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
"lb_changed");
GRPC_ERROR_REF(error), "lb_changed");
if (w->state != GRPC_CHANNEL_SHUTDOWN) {
watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
}
}
static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_error *error) {
lb_policy_connectivity_watcher *w = arg;
gpr_mu_lock(&w->chand->mu_config);
on_lb_policy_state_changed_locked(exec_ctx, w);
on_lb_policy_state_changed_locked(exec_ctx, w, error);
gpr_mu_unlock(&w->chand->mu_config);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
@ -176,19 +179,22 @@ static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
}
static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_error *error) {
channel_data *chand = arg;
grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
int exit_idle = 0;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
if (chand->incoming_configuration != NULL) {
lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
if (lb_policy != NULL) {
GRPC_LB_POLICY_REF(lb_policy, "channel");
GRPC_LB_POLICY_REF(lb_policy, "config_change");
state = grpc_lb_policy_check_connectivity(exec_ctx, lb_policy);
GRPC_ERROR_UNREF(state_error);
state =
grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
}
grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
@ -208,7 +214,9 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
NULL);
} else if (chand->resolver == NULL /* disconnected */) {
grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
grpc_closure_list_fail_all(
&chand->waiting_for_config_closures,
GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
NULL);
}
@ -218,9 +226,9 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
chand->exit_idle_when_lb_policy_arrives = 0;
}
if (iomgr_success && chand->resolver) {
set_channel_connectivity_state_locked(exec_ctx, chand, state,
"new_lb+resolver");
if (error == GRPC_ERROR_NONE && chand->resolver) {
set_channel_connectivity_state_locked(
exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
if (lb_policy != NULL) {
watch_lb_policy(exec_ctx, chand, lb_policy, state);
}
@ -235,8 +243,12 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
}
grpc_error *refs[] = {error, state_error};
set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN, "resolver_gone");
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
GPR_ARRAY_SIZE(refs)),
"resolver_gone");
gpr_mu_unlock(&chand->mu_config);
}
@ -256,6 +268,7 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
}
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
GRPC_ERROR_UNREF(state_error);
}
static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
@ -263,7 +276,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_transport_op *op) {
channel_data *chand = elem->channel_data;
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
GPR_ASSERT(op->set_accept_stream == false);
if (op->bind_pollset != NULL) {
@ -282,7 +295,9 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
if (op->send_ping != NULL) {
if (chand->lb_policy == NULL) {
grpc_exec_ctx_enqueue(exec_ctx, op->send_ping, false, NULL);
grpc_exec_ctx_sched(exec_ctx, op->send_ping,
GRPC_ERROR_CREATE("Ping with no load balancing"),
NULL);
} else {
grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
op->bind_pollset = NULL;
@ -290,24 +305,29 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
op->send_ping = NULL;
}
if (op->disconnect && chand->resolver != NULL) {
set_channel_connectivity_state_locked(exec_ctx, chand,
GRPC_CHANNEL_SHUTDOWN, "disconnect");
grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
if (!chand->started_resolving) {
grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
NULL);
}
if (chand->lb_policy != NULL) {
grpc_pollset_set_del_pollset_set(exec_ctx,
chand->lb_policy->interested_parties,
chand->interested_parties);
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
chand->lb_policy = NULL;
if (op->disconnect_with_error != GRPC_ERROR_NONE) {
if (chand->resolver != NULL) {
set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
if (!chand->started_resolving) {
grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
GRPC_ERROR_REF(op->disconnect_with_error));
grpc_exec_ctx_enqueue_list(exec_ctx,
&chand->waiting_for_config_closures, NULL);
}
if (chand->lb_policy != NULL) {
grpc_pollset_set_del_pollset_set(exec_ctx,
chand->lb_policy->interested_parties,
chand->interested_parties);
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
chand->lb_policy = NULL;
}
}
GRPC_ERROR_UNREF(op->disconnect_with_error);
}
gpr_mu_unlock(&chand->mu_config);
}
@ -327,16 +347,17 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
grpc_connected_subchannel **connected_subchannel,
grpc_closure *on_ready);
static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
continue_picking_args *cpa = arg;
if (cpa->connected_subchannel == NULL) {
/* cancelled, do nothing */
} else if (!success) {
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
} else if (error != GRPC_ERROR_NONE) {
grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error), NULL);
} else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
cpa->initial_metadata_flags,
cpa->connected_subchannel, cpa->on_ready)) {
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, true, NULL);
grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE, NULL);
}
gpr_free(cpa);
}
@ -361,11 +382,12 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
connected_subchannel);
}
for (closure = chand->waiting_for_config_closures.head; closure != NULL;
closure = grpc_closure_next(closure)) {
closure = closure->next_data.next) {
cpa = closure->cb_arg;
if (cpa->connected_subchannel == connected_subchannel) {
cpa->connected_subchannel = NULL;
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
grpc_exec_ctx_sched(exec_ctx, cpa->on_ready,
GRPC_ERROR_CREATE("Pick cancelled"), NULL);
}
}
gpr_mu_unlock(&chand->mu_config);
@ -397,10 +419,11 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
cpa->on_ready = on_ready;
cpa->elem = elem;
grpc_closure_init(&cpa->closure, continue_picking, cpa);
grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure,
1);
grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
GRPC_ERROR_NONE);
} else {
grpc_exec_ctx_enqueue(exec_ctx, on_ready, false, NULL);
grpc_exec_ctx_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"),
NULL);
}
gpr_mu_unlock(&chand->mu_config);
return 0;
@ -507,7 +530,7 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
channel_data *chand = elem->channel_data;
grpc_connectivity_state out;
gpr_mu_lock(&chand->mu_config);
out = grpc_connectivity_state_check(&chand->state_tracker);
out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
if (chand->lb_policy != NULL) {
grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
@ -534,7 +557,7 @@ typedef struct {
} external_connectivity_watcher;
static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_error *error) {
external_connectivity_watcher *w = arg;
grpc_closure *follow_up = w->on_complete;
grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
@ -542,7 +565,7 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
"external_connectivity_watcher");
gpr_free(w);
follow_up->cb(exec_ctx, follow_up->cb_arg, iomgr_success);
follow_up->cb(exec_ctx, follow_up->cb_arg, error);
}
void grpc_client_channel_watch_connectivity_state(

@ -64,7 +64,7 @@ typedef struct {
grpc_transport *transport;
/** channel arguments (to be passed to the filters) */
const grpc_channel_args *channel_args;
grpc_channel_args *channel_args;
} grpc_connect_out_args;
struct grpc_connector_vtable {

@ -60,8 +60,9 @@ static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta,
: gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"LB_POLICY: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
old_val + delta, reason);
"LB_POLICY: 0x%" PRIxPTR " %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR
" [%s]",
(intptr_t)c, purpose, old_val, old_val + delta, reason);
#endif
return old_val;
}
@ -138,6 +139,8 @@ void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
}
grpc_connectivity_state grpc_lb_policy_check_connectivity(
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
return policy->vtable->check_connectivity(exec_ctx, policy);
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_error **connectivity_error) {
return policy->vtable->check_connectivity(exec_ctx, policy,
connectivity_error);
}

@ -77,8 +77,9 @@ struct grpc_lb_policy_vtable {
void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** check the current connectivity of the lb_policy */
grpc_connectivity_state (*check_connectivity)(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy);
grpc_connectivity_state (*check_connectivity)(
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_error **connectivity_error);
/** call notify when the connectivity state of a channel changes from *state.
Updates *state with the new state of the policy */
@ -154,6 +155,7 @@ void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_closure *closure);
grpc_connectivity_state grpc_lb_policy_check_connectivity(
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_error **connectivity_error);
#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_LB_POLICY_H */

@ -54,7 +54,7 @@
#define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
#define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20
#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 2
#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
#define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
#define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
@ -147,7 +147,7 @@ struct grpc_subchannel_call {
(((grpc_subchannel_call *)(callstack)) - 1)
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
bool iomgr_success);
grpc_error *error);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
#define REF_REASON reason
@ -177,7 +177,7 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
*/
static void connection_destroy(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
grpc_error *error) {
grpc_connected_subchannel *c = arg;
grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c));
gpr_free(c);
@ -200,7 +200,7 @@ void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
*/
static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
grpc_error *error) {
grpc_subchannel *c = arg;
gpr_free((void *)c->filters);
grpc_channel_args_destroy(c->args);
@ -290,8 +290,8 @@ void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
gpr_atm old_refs;
old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
if (old_refs == 1) {
grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(subchannel_destroy, c),
true, NULL);
grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(subchannel_destroy, c),
GRPC_ERROR_NONE, NULL);
}
}
@ -382,7 +382,8 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
args.initial_connect_string = c->initial_connect_string;
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
GRPC_CHANNEL_CONNECTING, "state_change");
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
"state_change");
grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
&c->connected);
}
@ -393,16 +394,17 @@ static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
continue_connect(exec_ctx, c);
}
grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c) {
grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c,
grpc_error **error) {
grpc_connectivity_state state;
gpr_mu_lock(&c->mu);
state = grpc_connectivity_state_check(&c->state_tracker);
state = grpc_connectivity_state_check(&c->state_tracker, error);
gpr_mu_unlock(&c->mu);
return state;
}
static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
grpc_error *error) {
external_state_watcher *w = arg;
grpc_closure *follow_up = w->notify;
if (w->pollset_set != NULL) {
@ -415,7 +417,7 @@ static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_unlock(&w->subchannel->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
gpr_free(w);
follow_up->cb(exec_ctx, follow_up->cb_arg, success);
follow_up->cb(exec_ctx, follow_up->cb_arg, error);
}
void grpc_subchannel_notify_on_state_change(
@ -469,7 +471,7 @@ void grpc_connected_subchannel_process_transport_op(
}
static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
bool iomgr_success) {
grpc_error *error) {
state_watcher *sw = p;
grpc_subchannel *c = sw->subchannel;
gpr_mu *mu = &c->mu;
@ -477,20 +479,19 @@ static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
gpr_mu_lock(mu);
/* if we failed just leave this closure */
if (iomgr_success) {
if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
/* any errors on a subchannel ==> we're done, create a new one */
sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
}
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
sw->connectivity_state, "reflect_child");
if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
grpc_connected_subchannel_notify_on_state_change(
exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
&sw->connectivity_state, &sw->closure);
GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
sw = NULL;
}
if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
/* any errors on a subchannel ==> we're done, create a new one */
sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
}
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
sw->connectivity_state, GRPC_ERROR_REF(error),
"reflect_child");
if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
grpc_connected_subchannel_notify_on_state_change(
exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
&sw->connectivity_state, &sw->closure);
GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
sw = NULL;
}
gpr_mu_unlock(mu);
@ -592,17 +593,20 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
/* signal completion */
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
"connected");
GRPC_ERROR_NONE, "connected");
}
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
c->have_alarm = 0;
if (c->disconnected) {
iomgr_success = 0;
error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1);
} else {
GRPC_ERROR_REF(error);
}
if (iomgr_success) {
if (error == GRPC_ERROR_NONE) {
gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
c->next_attempt =
gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
@ -611,11 +615,13 @@ static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
GRPC_ERROR_UNREF(error);
}
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_error *error) {
grpc_subchannel *c = arg;
grpc_channel_args *delete_channel_args = c->connecting_result.channel_args;
GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
gpr_mu_lock(&c->mu);
@ -627,13 +633,26 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
GPR_ASSERT(!c->have_alarm);
c->have_alarm = 1;
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connect_failed");
grpc_connectivity_state_set(
exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1),
"connect_failed");
gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now);
const char *errmsg = grpc_error_string(error);
gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <=
0) {
gpr_log(GPR_INFO, "Retry immediately");
} else {
gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds",
time_til_next.tv_sec, time_til_next.tv_nsec);
}
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
grpc_error_free_string(errmsg);
}
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
grpc_channel_args_destroy(delete_channel_args);
}
/*
@ -641,7 +660,7 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
*/
static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
bool success) {
grpc_error *error) {
grpc_subchannel_call *c = call;
GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
grpc_connected_subchannel *connection = c->connection;

@ -119,7 +119,7 @@ void grpc_connected_subchannel_process_transport_op(
/** poll the current connectivity state of a channel */
grpc_connectivity_state grpc_subchannel_check_connectivity(
grpc_subchannel *channel);
grpc_subchannel *channel, grpc_error **error);
/** call notify when the connectivity state of a channel changes from *state.
Updates *state with the new state of the channel */

@ -43,14 +43,14 @@
#define CANCELLED_CALL ((grpc_subchannel_call *)1)
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *holder,
bool success);
grpc_error *error);
static void retry_ops(grpc_exec_ctx *exec_ctx, void *retry_ops_args,
bool success);
grpc_error *error);
static void add_waiting_locked(grpc_subchannel_call_holder *holder,
grpc_transport_stream_op *op);
static void fail_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call_holder *holder);
grpc_subchannel_call_holder *holder, grpc_error *error);
static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call_holder *holder);
@ -91,7 +91,8 @@ void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *call = GET_CALL(holder);
GPR_TIMER_BEGIN("grpc_subchannel_call_holder_perform_op", 0);
if (call == CANCELLED_CALL) {
grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
GRPC_ERROR_CANCELLED);
GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
return;
}
@ -107,7 +108,8 @@ retry:
call = GET_CALL(holder);
if (call == CANCELLED_CALL) {
gpr_mu_unlock(&holder->mu);
grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
GRPC_ERROR_CANCELLED);
GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
return;
}
@ -124,7 +126,10 @@ retry:
} else {
switch (holder->creation_phase) {
case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
fail_locked(exec_ctx, holder);
fail_locked(exec_ctx, holder,
grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
GRPC_ERROR_INT_GRPC_STATUS,
op->cancel_with_status));
break;
case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL,
@ -132,7 +137,8 @@ retry:
break;
}
gpr_mu_unlock(&holder->mu);
grpc_transport_stream_op_finish_with_failure(exec_ctx, op);
grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
GRPC_ERROR_CANCELLED);
GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
return;
}
@ -168,7 +174,8 @@ retry:
GPR_TIMER_END("grpc_subchannel_call_holder_perform_op", 0);
}
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_subchannel_call_holder *holder = arg;
gpr_mu_lock(&holder->mu);
GPR_ASSERT(holder->creation_phase ==
@ -176,10 +183,14 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
if (holder->connected_subchannel == NULL) {
gpr_atm_no_barrier_store(&holder->subchannel_call, 1);
fail_locked(exec_ctx, holder);
fail_locked(exec_ctx, holder,
GRPC_ERROR_CREATE_REFERENCING("Failed to create subchannel",
&error, 1));
} else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
/* already cancelled before subchannel became ready */
fail_locked(exec_ctx, holder);
fail_locked(exec_ctx, holder,
GRPC_ERROR_CREATE_REFERENCING(
"Cancelled before creating subchannel", &error, 1));
} else {
gpr_atm_rel_store(
&holder->subchannel_call,
@ -205,18 +216,18 @@ static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
a->call = GET_CALL(holder);
if (a->call == CANCELLED_CALL) {
gpr_free(a);
fail_locked(exec_ctx, holder);
fail_locked(exec_ctx, holder, GRPC_ERROR_CANCELLED);
return;
}
holder->waiting_ops = NULL;
holder->waiting_ops_count = 0;
holder->waiting_ops_capacity = 0;
GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(retry_ops, a), true,
NULL);
grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(retry_ops, a),
GRPC_ERROR_NONE, NULL);
}
static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, bool success) {
static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
retry_ops_args *a = args;
size_t i;
for (i = 0; i < a->nops; i++) {
@ -241,13 +252,15 @@ static void add_waiting_locked(grpc_subchannel_call_holder *holder,
}
static void fail_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call_holder *holder) {
grpc_subchannel_call_holder *holder,
grpc_error *error) {
size_t i;
for (i = 0; i < holder->waiting_ops_count; i++) {
grpc_transport_stream_op_finish_with_failure(exec_ctx,
&holder->waiting_ops[i]);
grpc_transport_stream_op_finish_with_failure(
exec_ctx, &holder->waiting_ops[i], GRPC_ERROR_REF(error));
}
holder->waiting_ops_count = 0;
GRPC_ERROR_UNREF(error);
}
char *grpc_subchannel_call_holder_get_peer(

@ -103,8 +103,9 @@ static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
p->shutdown = 1;
pp = p->pending_picks;
p->pending_picks = NULL;
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_SHUTDOWN, "shutdown");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE("Channel shutdown"), "shutdown");
/* cancel subscription */
if (selected != NULL) {
grpc_connected_subchannel_notify_on_state_change(
@ -120,7 +121,7 @@ static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
*pp->target = NULL;
grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
p->base.interested_parties);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
gpr_free(pp);
pp = next;
}
@ -139,7 +140,8 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
p->base.interested_parties);
*target = NULL;
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete,
GRPC_ERROR_CREATE("Pick Cancelled"), NULL);
gpr_free(pp);
} else {
pp->next = p->pending_picks;
@ -164,7 +166,8 @@ static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
initial_metadata_flags_eq) {
grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
p->base.interested_parties);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete,
GRPC_ERROR_CREATE("Pick Cancelled"), NULL);
gpr_free(pp);
} else {
pp->next = p->pending_picks;
@ -237,7 +240,7 @@ static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_error *error) {
pick_first_lb_policy *p = arg;
size_t i;
size_t num_subchannels = p->num_subchannels;
@ -258,12 +261,14 @@ static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
}
static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_error *error) {
pick_first_lb_policy *p = arg;
grpc_subchannel *selected_subchannel;
pending_pick *pp;
grpc_connected_subchannel *selected;
GRPC_ERROR_REF(error);
gpr_mu_lock(&p->mu);
selected = GET_SELECTED(p);
@ -271,6 +276,7 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
if (p->shutdown) {
gpr_mu_unlock(&p->mu);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
GRPC_ERROR_UNREF(error);
return;
} else if (selected != NULL) {
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@ -278,7 +284,8 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN;
}
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
p->checking_connectivity, "selected_changed");
p->checking_connectivity, GRPC_ERROR_REF(error),
"selected_changed");
if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) {
grpc_connected_subchannel_notify_on_state_change(
exec_ctx, selected, p->base.interested_parties,
@ -291,7 +298,8 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
switch (p->checking_connectivity) {
case GRPC_CHANNEL_READY:
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_READY, "connecting_ready");
GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
"connecting_ready");
selected_subchannel = p->subchannels[p->checking_subchannel];
selected =
grpc_subchannel_get_connected_subchannel(selected_subchannel);
@ -300,15 +308,16 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
/* drop the pick list: we are connected now */
GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
grpc_exec_ctx_enqueue(
exec_ctx, grpc_closure_create(destroy_subchannels, p), true, NULL);
grpc_exec_ctx_sched(exec_ctx,
grpc_closure_create(destroy_subchannels, p),
GRPC_ERROR_NONE, NULL);
/* update any calls that were waiting for a pick */
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = selected;
grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
p->base.interested_parties);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
gpr_free(pp);
}
grpc_connected_subchannel_notify_on_state_change(
@ -320,12 +329,13 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
(p->checking_subchannel + 1) % p->num_subchannels;
if (p->checking_subchannel == 0) {
/* only trigger transient failure when we've tried all alternatives */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connecting_transient_failure");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "connecting_transient_failure");
}
GRPC_ERROR_UNREF(error);
p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]);
p->subchannels[p->checking_subchannel], &error);
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
grpc_subchannel_notify_on_state_change(
exec_ctx, p->subchannels[p->checking_subchannel],
@ -337,9 +347,9 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
break;
case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE:
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_CONNECTING,
"connecting_changed");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING,
GRPC_ERROR_REF(error), "connecting_changed");
grpc_subchannel_notify_on_state_change(
exec_ctx, p->subchannels[p->checking_subchannel],
p->base.interested_parties, &p->checking_connectivity,
@ -352,38 +362,45 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
"pick_first");
if (p->num_subchannels == 0) {
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_SHUTDOWN,
"no_more_channels");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE_REFERENCING("Pick first exhausted channels",
&error, 1),
"no_more_channels");
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE,
NULL);
gpr_free(pp);
}
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
"pick_first_connectivity");
} else {
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"subchannel_failed");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "subchannel_failed");
p->checking_subchannel %= p->num_subchannels;
GRPC_ERROR_UNREF(error);
p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]);
p->subchannels[p->checking_subchannel], &error);
goto loop;
}
}
}
gpr_mu_unlock(&p->mu);
GRPC_ERROR_UNREF(error);
}
static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *pol) {
grpc_lb_policy *pol,
grpc_error **error) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
grpc_connectivity_state st;
gpr_mu_lock(&p->mu);
st = grpc_connectivity_state_check(&p->state_tracker);
st = grpc_connectivity_state_check(&p->state_tracker, error);
gpr_mu_unlock(&p->mu);
return st;
}
@ -406,7 +423,8 @@ static void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
if (selected) {
grpc_connected_subchannel_ping(exec_ctx, selected, closure);
} else {
grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CREATE("Not connected"),
NULL);
}
}

@ -265,11 +265,13 @@ static void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete,
GRPC_ERROR_CREATE("Channel Shutdown"), NULL);
gpr_free(pp);
}
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_SHUTDOWN, "shutdown");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE("Channel Shutdown"), "shutdown");
for (i = 0; i < p->num_subchannels; i++) {
subchannel_data *sd = p->subchannels[i];
grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL,
@ -291,7 +293,8 @@ static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
p->base.interested_parties);
*target = NULL;
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CANCELLED,
NULL);
gpr_free(pp);
} else {
pp->next = p->pending_picks;
@ -317,7 +320,8 @@ static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
p->base.interested_parties);
*pp->target = NULL;
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CANCELLED,
NULL);
gpr_free(pp);
} else {
pp->next = p->pending_picks;
@ -396,7 +400,7 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_error *error) {
subchannel_data *sd = arg;
round_robin_lb_policy *p = sd->policy;
pending_pick *pp;
@ -404,6 +408,7 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
int unref = 0;
GRPC_ERROR_REF(error);
gpr_mu_lock(&p->mu);
if (p->shutdown) {
@ -412,7 +417,8 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
switch (sd->connectivity_state) {
case GRPC_CHANNEL_READY:
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_READY, "connecting_ready");
GRPC_CHANNEL_READY, GRPC_ERROR_REF(error),
"connecting_ready");
/* add the newly connected subchannel to the list of connected ones.
* Note that it goes to the "end of the line". */
sd->ready_list_node = add_connected_sc_locked(p, sd->subchannel);
@ -436,7 +442,7 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
}
grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
p->base.interested_parties);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
gpr_free(pp);
}
grpc_subchannel_notify_on_state_change(
@ -445,9 +451,9 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
break;
case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE:
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
sd->connectivity_state,
"connecting_changed");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, sd->connectivity_state,
GRPC_ERROR_REF(error), "connecting_changed");
grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, p->base.interested_parties,
&sd->connectivity_state, &sd->connectivity_changed_closure);
@ -463,9 +469,9 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
remove_disconnected_sc_locked(p, sd->ready_list_node);
sd->ready_list_node = NULL;
}
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connecting_transient_failure");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "connecting_transient_failure");
break;
case GRPC_CHANNEL_SHUTDOWN:
if (sd->ready_list_node != NULL) {
@ -482,19 +488,22 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
unref = 1;
if (p->num_subchannels == 0) {
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_SHUTDOWN,
"no_more_channels");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE_REFERENCING("Round Robin Channels Exhausted",
&error, 1),
"no_more_channels");
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE,
NULL);
gpr_free(pp);
}
} else {
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"subchannel_failed");
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "subchannel_failed");
}
} /* switch */
} /* !unref */
@ -504,14 +513,17 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
if (unref) {
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "round_robin_connectivity");
}
GRPC_ERROR_UNREF(error);
}
static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *pol) {
grpc_lb_policy *pol,
grpc_error **error) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
grpc_connectivity_state st;
gpr_mu_lock(&p->mu);
st = grpc_connectivity_state_check(&p->state_tracker);
st = grpc_connectivity_state_check(&p->state_tracker, error);
gpr_mu_unlock(&p->mu);
return st;
}
@ -539,7 +551,8 @@ static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_connected_subchannel_ping(exec_ctx, target, closure);
} else {
gpr_mu_unlock(&p->mu);
grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
grpc_exec_ctx_sched(exec_ctx, closure,
GRPC_ERROR_CREATE("Round Robin not connected"), NULL);
}
}

@ -82,6 +82,9 @@ typedef struct {
grpc_timer retry_timer;
/** retry backoff state */
gpr_backoff backoff_state;
/** currently resolving addresses */
grpc_resolved_addresses *addresses;
} dns_resolver;
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@ -108,7 +111,8 @@ static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
}
if (r->next_completion != NULL) {
*r->target_config = NULL;
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
grpc_exec_ctx_sched(exec_ctx, r->next_completion,
GRPC_ERROR_CREATE("Resolver Shutdown"), NULL);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
@ -143,12 +147,12 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
}
static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
grpc_error *error) {
dns_resolver *r = arg;
gpr_mu_lock(&r->mu);
r->have_retry_timer = false;
if (success) {
if (error == GRPC_ERROR_NONE) {
if (!r->resolving) {
dns_start_resolving_locked(exec_ctx, r);
}
@ -159,13 +163,14 @@ static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
}
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
grpc_error *error) {
dns_resolver *r = arg;
grpc_client_config *config = NULL;
grpc_lb_policy *lb_policy;
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = 0;
grpc_resolved_addresses *addresses = r->addresses;
if (addresses != NULL) {
grpc_lb_policy_args lb_policy_args;
config = grpc_client_config_create();
@ -183,12 +188,18 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
gpr_timespec timeout = gpr_time_sub(next_try, now);
gpr_log(GPR_DEBUG,
"dns resolution failed: retrying in %" PRId64 ".%09d seconds",
timeout.tv_sec, timeout.tv_nsec);
const char *msg = grpc_error_string(error);
gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg);
grpc_error_free_string(msg);
GPR_ASSERT(!r->have_retry_timer);
r->have_retry_timer = true;
GRPC_RESOLVER_REF(&r->base, "retry-timer");
if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) <= 0) {
gpr_log(GPR_DEBUG, "retrying in %" PRId64 ".%09d seconds", timeout.tv_sec,
timeout.tv_nsec);
} else {
gpr_log(GPR_DEBUG, "retrying immediately");
}
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
now);
}
@ -208,7 +219,9 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
GRPC_RESOLVER_REF(&r->base, "dns-resolving");
GPR_ASSERT(!r->resolving);
r->resolving = 1;
grpc_resolve_address(exec_ctx, r->name, r->default_port, dns_on_resolved, r);
r->addresses = NULL;
grpc_resolve_address(exec_ctx, r->name, r->default_port,
grpc_closure_create(dns_on_resolved, r), &r->addresses);
}
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@ -219,7 +232,7 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
if (r->resolved_config) {
grpc_client_config_ref(r->resolved_config);
}
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL;
r->published_version = r->resolved_version;
}

@ -92,7 +92,7 @@ static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
@ -133,7 +133,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
r->published = 1;
*r->target_config = cfg;
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL;
}
}

@ -1,513 +0,0 @@
/*
*
* 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.
*
*/
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include <grpc/grpc_zookeeper.h>
#include <zookeeper/zookeeper.h>
#include "src/core/ext/client_config/lb_policy_registry.h"
#include "src/core/ext/client_config/resolver_registry.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/json/json.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/api_trace.h"
/** Zookeeper session expiration time in milliseconds */
#define GRPC_ZOOKEEPER_SESSION_TIMEOUT 15000
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** refcount */
gpr_refcount refs;
/** name to resolve */
char *name;
/** subchannel factory */
grpc_client_channel_factory *client_channel_factory;
/** load balancing policy name */
char *lb_policy_name;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** are we currently resolving? */
int resolving;
/** which version of resolved_config have we published? */
int published_version;
/** which version of resolved_config is current? */
int resolved_version;
/** pending next completion, or NULL */
grpc_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
/** current (fully resolved) config */
grpc_client_config *resolved_config;
/** zookeeper handle */
zhandle_t *zookeeper_handle;
/** zookeeper resolved addresses */
grpc_resolved_addresses *resolved_addrs;
/** total number of addresses to be resolved */
int resolved_total;
/** number of addresses resolved */
int resolved_num;
} zookeeper_resolver;
static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void zookeeper_start_resolving_locked(zookeeper_resolver *r);
static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
zookeeper_resolver *r);
static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *r);
static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_client_config **target_config,
grpc_closure *on_complete);
static const grpc_resolver_vtable zookeeper_resolver_vtable = {
zookeeper_destroy, zookeeper_shutdown, zookeeper_channel_saw_error,
zookeeper_next};
static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
grpc_closure *call = NULL;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
call = r->next_completion;
r->next_completion = NULL;
}
zookeeper_close(r->zookeeper_handle);
gpr_mu_unlock(&r->mu);
if (call != NULL) {
call->cb(exec_ctx, call->cb_arg, 1);
}
}
static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->resolving == 0) {
zookeeper_start_resolving_locked(r);
}
gpr_mu_unlock(&r->mu);
}
static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_closure *on_complete) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->next_completion == NULL);
r->next_completion = on_complete;
r->target_config = target_config;
if (r->resolved_version == 0 && r->resolving == 0) {
zookeeper_start_resolving_locked(r);
} else {
zookeeper_maybe_finish_next_locked(exec_ctx, r);
}
gpr_mu_unlock(&r->mu);
}
/** Zookeeper global watcher for connection management
TODO: better connection management besides logs */
static void zookeeper_global_watcher(zhandle_t *zookeeper_handle, int type,
int state, const char *path,
void *watcher_ctx) {
if (type == ZOO_SESSION_EVENT) {
if (state == ZOO_EXPIRED_SESSION_STATE) {
gpr_log(GPR_ERROR, "Zookeeper session expired");
} else if (state == ZOO_AUTH_FAILED_STATE) {
gpr_log(GPR_ERROR, "Zookeeper authentication failed");
}
}
}
/** Zookeeper watcher triggered by changes to watched nodes
Once triggered, it tries to resolve again to get updated addresses */
static void zookeeper_watcher(zhandle_t *zookeeper_handle, int type, int state,
const char *path, void *watcher_ctx) {
if (watcher_ctx != NULL) {
zookeeper_resolver *r = (zookeeper_resolver *)watcher_ctx;
if (state == ZOO_CONNECTED_STATE) {
gpr_mu_lock(&r->mu);
if (r->resolving == 0) {
zookeeper_start_resolving_locked(r);
}
gpr_mu_unlock(&r->mu);
}
}
}
/** Callback function after getting all resolved addresses
Creates a subchannel for each address */
static void zookeeper_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
zookeeper_resolver *r = arg;
grpc_client_config *config = NULL;
grpc_lb_policy *lb_policy;
if (addresses != NULL) {
grpc_lb_policy_args lb_policy_args;
config = grpc_client_config_create();
lb_policy_args.addresses = addresses;
lb_policy_args.client_channel_factory = r->client_channel_factory;
lb_policy =
grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) {
grpc_client_config_set_lb_policy(config, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
}
grpc_resolved_addresses_destroy(addresses);
}
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving == 1);
r->resolving = 0;
if (r->resolved_config != NULL) {
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
r->resolved_config = config;
r->resolved_version++;
zookeeper_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "zookeeper-resolving");
}
/** Callback function for each DNS resolved address */
static void zookeeper_dns_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
size_t i;
zookeeper_resolver *r = arg;
int resolve_done = 0;
gpr_mu_lock(&r->mu);
r->resolved_num++;
r->resolved_addrs->addrs =
gpr_realloc(r->resolved_addrs->addrs,
sizeof(grpc_resolved_address) *
(r->resolved_addrs->naddrs + addresses->naddrs));
for (i = 0; i < addresses->naddrs; i++) {
memcpy(r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].addr,
addresses->addrs[i].addr, addresses->addrs[i].len);
r->resolved_addrs->addrs[i + r->resolved_addrs->naddrs].len =
addresses->addrs[i].len;
}
r->resolved_addrs->naddrs += addresses->naddrs;
grpc_resolved_addresses_destroy(addresses);
/** Wait for all addresses to be resolved */
resolve_done = (r->resolved_num == r->resolved_total);
gpr_mu_unlock(&r->mu);
if (resolve_done) {
zookeeper_on_resolved(exec_ctx, r, r->resolved_addrs);
}
}
/** Parses JSON format address of a zookeeper node */
static char *zookeeper_parse_address(const char *value, size_t value_len) {
grpc_json *json;
grpc_json *cur;
const char *host;
const char *port;
char *buffer;
char *address = NULL;
buffer = gpr_malloc(value_len);
memcpy(buffer, value, value_len);
json = grpc_json_parse_string_with_len(buffer, value_len);
if (json != NULL) {
host = NULL;
port = NULL;
for (cur = json->child; cur != NULL; cur = cur->next) {
if (!strcmp(cur->key, "host")) {
host = cur->value;
if (port != NULL) {
break;
}
} else if (!strcmp(cur->key, "port")) {
port = cur->value;
if (host != NULL) {
break;
}
}
}
if (host != NULL && port != NULL) {
gpr_asprintf(&address, "%s:%s", host, port);
}
grpc_json_destroy(json);
}
gpr_free(buffer);
return address;
}
static void zookeeper_get_children_node_completion(int rc, const char *value,
int value_len,
const struct Stat *stat,
const void *arg) {
char *address = NULL;
zookeeper_resolver *r = (zookeeper_resolver *)arg;
int resolve_done = 0;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
if (rc != 0) {
gpr_log(GPR_ERROR, "Error in getting a child node of %s", r->name);
grpc_exec_ctx_finish(&exec_ctx);
return;
}
address = zookeeper_parse_address(value, (size_t)value_len);
if (address != NULL) {
/** Further resolves address by DNS */
grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
gpr_free(address);
} else {
gpr_log(GPR_ERROR, "Error in resolving a child node of %s", r->name);
gpr_mu_lock(&r->mu);
r->resolved_total--;
resolve_done = (r->resolved_num == r->resolved_total);
gpr_mu_unlock(&r->mu);
if (resolve_done) {
zookeeper_on_resolved(&exec_ctx, r, r->resolved_addrs);
}
}
grpc_exec_ctx_finish(&exec_ctx);
}
static void zookeeper_get_children_completion(
int rc, const struct String_vector *children, const void *arg) {
char *path;
int status;
int i;
zookeeper_resolver *r = (zookeeper_resolver *)arg;
if (rc != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
return;
}
if (children->count == 0) {
gpr_log(GPR_ERROR, "Error in resolving zookeeper address %s", r->name);
return;
}
r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
r->resolved_addrs->addrs = NULL;
r->resolved_addrs->naddrs = 0;
r->resolved_total = children->count;
/** TODO: Replace expensive heap allocation with stack
if we can get maximum length of zookeeper path */
for (i = 0; i < children->count; i++) {
gpr_asprintf(&path, "%s/%s", r->name, children->data[i]);
status = zoo_awget(r->zookeeper_handle, path, zookeeper_watcher, r,
zookeeper_get_children_node_completion, r);
gpr_free(path);
if (status != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", path);
}
}
}
static void zookeeper_get_node_completion(int rc, const char *value,
int value_len,
const struct Stat *stat,
const void *arg) {
int status;
char *address = NULL;
zookeeper_resolver *r = (zookeeper_resolver *)arg;
r->resolved_addrs = NULL;
r->resolved_total = 0;
r->resolved_num = 0;
if (rc != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
return;
}
/** If zookeeper node of path r->name does not have address
(i.e. service node), get its children */
address = zookeeper_parse_address(value, (size_t)value_len);
if (address != NULL) {
r->resolved_addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
r->resolved_addrs->addrs = NULL;
r->resolved_addrs->naddrs = 0;
r->resolved_total = 1;
/** Further resolves address by DNS */
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
gpr_free(address);
grpc_exec_ctx_finish(&exec_ctx);
return;
}
status = zoo_awget_children(r->zookeeper_handle, r->name, zookeeper_watcher,
r, zookeeper_get_children_completion, r);
if (status != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper children of %s", r->name);
}
}
static void zookeeper_resolve_address(zookeeper_resolver *r) {
int status;
status = zoo_awget(r->zookeeper_handle, r->name, zookeeper_watcher, r,
zookeeper_get_node_completion, r);
if (status != 0) {
gpr_log(GPR_ERROR, "Error in getting zookeeper node %s", r->name);
}
}
static void zookeeper_start_resolving_locked(zookeeper_resolver *r) {
GRPC_RESOLVER_REF(&r->base, "zookeeper-resolving");
GPR_ASSERT(r->resolving == 0);
r->resolving = 1;
zookeeper_resolve_address(r);
}
static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
zookeeper_resolver *r) {
if (r->next_completion != NULL &&
r->resolved_version != r->published_version) {
*r->target_config = r->resolved_config;
if (r->resolved_config != NULL) {
grpc_client_config_ref(r->resolved_config);
}
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
r->next_completion = NULL;
r->published_version = r->resolved_version;
}
}
static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
zookeeper_resolver *r = (zookeeper_resolver *)gr;
gpr_mu_destroy(&r->mu);
if (r->resolved_config != NULL) {
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
gpr_free(r->name);
gpr_free(r->lb_policy_name);
gpr_free(r);
}
static grpc_resolver *zookeeper_create(grpc_resolver_args *args,
const char *lb_policy_name) {
zookeeper_resolver *r;
size_t length;
char *path = args->uri->path;
if (0 == strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "No authority specified in zookeeper uri");
return NULL;
}
/** Removes the trailing slash if exists */
length = strlen(path);
if (length > 1 && path[length - 1] == '/') {
path[length - 1] = 0;
}
r = gpr_malloc(sizeof(zookeeper_resolver));
memset(r, 0, sizeof(*r));
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &zookeeper_resolver_vtable);
r->name = gpr_strdup(path);
r->client_channel_factory = args->client_channel_factory;
grpc_client_channel_factory_ref(r->client_channel_factory);
r->lb_policy_name = gpr_strdup(lb_policy_name);
/** Initializes zookeeper client */
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
r->zookeeper_handle =
zookeeper_init(args->uri->authority, zookeeper_global_watcher,
GRPC_ZOOKEEPER_SESSION_TIMEOUT, 0, 0, 0);
if (r->zookeeper_handle == NULL) {
gpr_log(GPR_ERROR, "Unable to connect to zookeeper server");
return NULL;
}
return &r->base;
}
/*
* FACTORY
*/
static void zookeeper_factory_ref(grpc_resolver_factory *factory) {}
static void zookeeper_factory_unref(grpc_resolver_factory *factory) {}
static char *zookeeper_factory_get_default_hostname(
grpc_resolver_factory *factory, grpc_uri *uri) {
return NULL;
}
static grpc_resolver *zookeeper_factory_create_resolver(
grpc_resolver_factory *factory, grpc_resolver_args *args) {
return zookeeper_create(args, "pick_first");
}
static const grpc_resolver_factory_vtable zookeeper_factory_vtable = {
zookeeper_factory_ref, zookeeper_factory_unref,
zookeeper_factory_create_resolver, zookeeper_factory_get_default_hostname,
"zookeeper"};
static grpc_resolver_factory zookeeper_resolver_factory = {
&zookeeper_factory_vtable};
static grpc_resolver_factory *zookeeper_resolver_factory_create() {
return &zookeeper_resolver_factory;
}
static void zookeeper_plugin_init() {
grpc_register_resolver_type(zookeeper_resolver_factory_create());
}
void grpc_zookeeper_register() {
GRPC_API_TRACE("grpc_zookeeper_register(void)", 0, ());
grpc_register_plugin(zookeeper_plugin_init, NULL);
}

@ -79,11 +79,11 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
}
static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
grpc_error *error) {
connector_unref(exec_ctx, arg);
}
static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector *c = arg;
grpc_closure *notify;
grpc_endpoint *tcp = c->tcp;
@ -103,13 +103,13 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
0);
GPR_ASSERT(c->result->transport);
c->result->channel_args = c->args.channel_args;
c->result->channel_args = grpc_channel_args_copy(c->args.channel_args);
} else {
memset(c->result, 0, sizeof(*c->result));
}
notify = c->notify;
c->notify = NULL;
notify->cb(exec_ctx, notify->cb_arg, 1);
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}

@ -90,7 +90,6 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_auth_context *auth_context) {
connector *c = arg;
grpc_closure *notify;
grpc_channel_args *args_copy = NULL;
gpr_mu_lock(&c->mu);
if (c->connecting_endpoint == NULL) {
memset(c->result, 0, sizeof(*c->result));
@ -109,26 +108,23 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
0);
auth_context_arg = grpc_auth_context_to_arg(auth_context);
args_copy = grpc_channel_args_copy_and_add(c->args.channel_args,
&auth_context_arg, 1);
c->result->channel_args = args_copy;
c->result->channel_args = grpc_channel_args_copy_and_add(
c->args.channel_args, &auth_context_arg, 1);
}
notify = c->notify;
c->notify = NULL;
/* look at c->args which are connector args. */
notify->cb(exec_ctx, notify->cb_arg, 1);
if (args_copy != NULL) grpc_channel_args_destroy(args_copy);
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_NONE, NULL);
}
static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
grpc_error *error) {
connector *c = arg;
grpc_channel_security_connector_do_handshake(exec_ctx, c->security_connector,
c->connecting_endpoint,
on_secure_handshake_done, c);
grpc_channel_security_connector_do_handshake(
exec_ctx, c->security_connector, c->connecting_endpoint, c->args.deadline,
on_secure_handshake_done, c);
}
static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector *c = arg;
grpc_closure *notify;
grpc_endpoint *tcp = c->newly_connecting_endpoint;
@ -147,13 +143,14 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
&c->initial_string_sent);
} else {
grpc_channel_security_connector_do_handshake(
exec_ctx, c->security_connector, tcp, on_secure_handshake_done, c);
exec_ctx, c->security_connector, tcp, c->args.deadline,
on_secure_handshake_done, c);
}
} else {
memset(c->result, 0, sizeof(*c->result));
notify = c->notify;
c->notify = NULL;
notify->cb(exec_ctx, notify->cb_arg, 1);
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
}
@ -175,7 +172,6 @@ static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
grpc_closure *notify) {
connector *c = (connector *)con;
GPR_ASSERT(c->notify == NULL);
GPR_ASSERT(notify->cb);
c->notify = notify;
c->args = *args;
c->result = result;

@ -35,6 +35,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/http_server_filter.h"
@ -74,34 +75,40 @@ static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
grpc_closure *destroy_done) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_unref(exec_ctx, tcp);
grpc_exec_ctx_enqueue(exec_ctx, destroy_done, true, NULL);
grpc_exec_ctx_sched(exec_ctx, destroy_done, GRPC_ERROR_NONE, NULL);
}
int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
grpc_resolved_addresses *resolved = NULL;
grpc_tcp_server *tcp = NULL;
size_t i;
unsigned count = 0;
size_t count = 0;
int port_num = -1;
int port_temp;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_error *err = GRPC_ERROR_NONE;
GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2,
(server, addr));
resolved = grpc_blocking_resolve_address(addr, "http");
if (!resolved) {
grpc_error **errors = NULL;
err = grpc_blocking_resolve_address(addr, "https", &resolved);
if (err != GRPC_ERROR_NONE) {
goto error;
}
tcp = grpc_tcp_server_create(NULL);
GPR_ASSERT(tcp);
err = grpc_tcp_server_create(NULL, &tcp);
if (err != GRPC_ERROR_NONE) {
goto error;
}
for (i = 0; i < resolved->naddrs; i++) {
port_temp = grpc_tcp_server_add_port(
const size_t naddrs = resolved->naddrs;
errors = gpr_malloc(sizeof(*errors) * naddrs);
for (i = 0; i < naddrs; i++) {
errors[i] = grpc_tcp_server_add_port(
tcp, (struct sockaddr *)&resolved->addrs[i].addr,
resolved->addrs[i].len);
if (port_temp > 0) {
resolved->addrs[i].len, &port_temp);
if (errors[i] == GRPC_ERROR_NONE) {
if (port_num == -1) {
port_num = port_temp;
} else {
@ -111,14 +118,24 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
}
}
if (count == 0) {
gpr_log(GPR_ERROR, "No address added out of total %" PRIuPTR " resolved",
resolved->naddrs);
char *msg;
gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
naddrs);
err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
gpr_free(msg);
goto error;
}
if (count != resolved->naddrs) {
gpr_log(GPR_ERROR,
"Only %d addresses added out of total %" PRIuPTR " resolved", count,
resolved->naddrs);
} else if (count != naddrs) {
char *msg;
gpr_asprintf(&msg, "Only %" PRIuPTR
" addresses added out of total %" PRIuPTR " resolved",
count, naddrs);
err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
gpr_free(msg);
const char *warning_message = grpc_error_string(err);
gpr_log(GPR_INFO, "WARNING: %s", warning_message);
grpc_error_free_string(warning_message);
/* we managed to bind some addresses: continue */
}
grpc_resolved_addresses_destroy(resolved);
@ -128,6 +145,7 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
/* Error path: cleanup and return */
error:
GPR_ASSERT(err != GRPC_ERROR_NONE);
if (resolved) {
grpc_resolved_addresses_destroy(resolved);
}
@ -136,7 +154,18 @@ error:
}
port_num = 0;
const char *msg = grpc_error_string(err);
gpr_log(GPR_ERROR, "%s", msg);
grpc_error_free_string(msg);
GRPC_ERROR_UNREF(err);
done:
grpc_exec_ctx_finish(&exec_ctx);
if (errors != NULL) {
for (i = 0; i < naddrs; i++) {
GRPC_ERROR_UNREF(errors[i]);
}
}
gpr_free(errors);
return port_num;
}

@ -37,6 +37,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
@ -128,9 +129,11 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
state->state = statep;
state_ref(state->state);
state->accepting_pollset = accepting_pollset;
grpc_server_security_connector_do_handshake(exec_ctx, state->state->sc,
acceptor, tcp,
on_secure_handshake_done, state);
grpc_server_security_connector_do_handshake(
exec_ctx, state->state->sc, acceptor, tcp,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(120, GPR_TIMESPAN)),
on_secure_handshake_done, state);
}
/* Server callback: start listening on our ports */
@ -141,11 +144,12 @@ static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
on_accept, state);
}
static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, bool success) {
static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep,
grpc_error *error) {
server_secure_state *state = statep;
if (state->destroy_callback != NULL) {
state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
success);
GRPC_ERROR_REF(error));
}
grpc_server_security_connector_shutdown(exec_ctx, state->sc);
state_unref(state);
@ -171,12 +175,14 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
grpc_tcp_server *tcp = NULL;
server_secure_state *state = NULL;
size_t i;
unsigned count = 0;
size_t count = 0;
int port_num = -1;
int port_temp;
grpc_security_status status = GRPC_SECURITY_ERROR;
grpc_server_security_connector *sc = NULL;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_error *err = GRPC_ERROR_NONE;
grpc_error **errors = NULL;
GRPC_API_TRACE(
"grpc_server_add_secure_http2_port("
@ -184,26 +190,34 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
3, (server, addr, creds));
/* create security context */
if (creds == NULL) goto error;
if (creds == NULL) {
err = GRPC_ERROR_CREATE(
"No credentials specified for secure server port (creds==NULL)");
goto error;
}
status = grpc_server_credentials_create_security_connector(creds, &sc);
if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR,
"Unable to create secure server with credentials of type %s.",
creds->type);
char *msg;
gpr_asprintf(&msg,
"Unable to create secure server with credentials of type %s.",
creds->type);
err = grpc_error_set_int(GRPC_ERROR_CREATE(msg),
GRPC_ERROR_INT_SECURITY_STATUS, status);
gpr_free(msg);
goto error;
}
sc->channel_args = grpc_server_get_channel_args(server);
/* resolve address */
resolved = grpc_blocking_resolve_address(addr, "https");
if (!resolved) {
err = grpc_blocking_resolve_address(addr, "https", &resolved);
if (err != GRPC_ERROR_NONE) {
goto error;
}
state = gpr_malloc(sizeof(*state));
memset(state, 0, sizeof(*state));
grpc_closure_init(&state->destroy_closure, destroy_done, state);
tcp = grpc_tcp_server_create(&state->destroy_closure);
if (!tcp) {
err = grpc_tcp_server_create(&state->destroy_closure, &tcp);
if (err != GRPC_ERROR_NONE) {
goto error;
}
@ -215,11 +229,12 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
gpr_mu_init(&state->mu);
gpr_ref_init(&state->refcount, 1);
errors = gpr_malloc(sizeof(*errors) * resolved->naddrs);
for (i = 0; i < resolved->naddrs; i++) {
port_temp = grpc_tcp_server_add_port(
errors[i] = grpc_tcp_server_add_port(
tcp, (struct sockaddr *)&resolved->addrs[i].addr,
resolved->addrs[i].len);
if (port_temp > 0) {
resolved->addrs[i].len, &port_temp);
if (errors[i] == GRPC_ERROR_NONE) {
if (port_num == -1) {
port_num = port_temp;
} else {
@ -229,16 +244,31 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
}
}
if (count == 0) {
gpr_log(GPR_ERROR, "No address added out of total %" PRIuPTR " resolved",
resolved->naddrs);
char *msg;
gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
resolved->naddrs);
err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
gpr_free(msg);
goto error;
} else if (count != resolved->naddrs) {
char *msg;
gpr_asprintf(&msg, "Only %" PRIuPTR
" addresses added out of total %" PRIuPTR " resolved",
count, resolved->naddrs);
err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
gpr_free(msg);
const char *warning_message = grpc_error_string(err);
gpr_log(GPR_INFO, "WARNING: %s", warning_message);
grpc_error_free_string(warning_message);
/* we managed to bind some addresses: continue */
} else {
for (i = 0; i < resolved->naddrs; i++) {
GRPC_ERROR_UNREF(errors[i]);
}
}
if (count != resolved->naddrs) {
gpr_log(GPR_ERROR,
"Only %d addresses added out of total %" PRIuPTR " resolved", count,
resolved->naddrs);
/* if it's an error, don't we want to goto error; here ? */
}
gpr_free(errors);
errors = NULL;
grpc_resolved_addresses_destroy(resolved);
/* Register with the server only upon success */
@ -249,6 +279,13 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
/* Error path: cleanup and return */
error:
GPR_ASSERT(err != GRPC_ERROR_NONE);
if (errors != NULL) {
for (i = 0; i < resolved->naddrs; i++) {
GRPC_ERROR_UNREF(errors[i]);
}
gpr_free(errors);
}
if (resolved) {
grpc_resolved_addresses_destroy(resolved);
}
@ -263,5 +300,9 @@ error:
}
}
grpc_exec_ctx_finish(&exec_ctx);
const char *msg = grpc_error_string(err);
GRPC_ERROR_UNREF(err);
gpr_log(GPR_ERROR, "%s", msg);
grpc_error_free_string(msg);
return 0;
}

@ -85,19 +85,17 @@ int grpc_flowctl_trace = 0;
static const grpc_transport_vtable vtable;
/* forward declarations of various callbacks that we'll build closures around */
static void writing_action(grpc_exec_ctx *exec_ctx, void *t,
bool iomgr_success_ignored);
static void reading_action(grpc_exec_ctx *exec_ctx, void *t,
bool iomgr_success_ignored);
static void parsing_action(grpc_exec_ctx *exec_ctx, void *t,
bool iomgr_success_ignored);
static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
/** Set a transport level setting, and push it to our peer */
static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
uint32_t value);
/** Start disconnection chain */
static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_error *error);
/** Perform a transport_op */
static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
@ -135,7 +133,7 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
static void connectivity_state_set(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_connectivity_state state, const char *reason);
grpc_connectivity_state state, grpc_error *error, const char *reason);
static void check_read_ops(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global);
@ -149,7 +147,9 @@ static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream *s,
void *byte_stream);
static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global);
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global,
grpc_error *error);
/*******************************************************************************
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
@ -194,7 +194,8 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
and maybe they hold resources that need to be freed */
while (t->global.pings.next != &t->global.pings) {
grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, false, NULL);
grpc_exec_ctx_sched(exec_ctx, ping->on_recv,
GRPC_ERROR_CREATE("Transport closed"), NULL);
ping->next->prev = ping->prev;
ping->prev->next = ping->next;
gpr_free(ping);
@ -409,7 +410,7 @@ static void destroy_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream *s_ignored,
void *arg_ignored) {
t->destroying = 1;
drop_connection(exec_ctx, t);
drop_connection(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
}
static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
@ -445,12 +446,11 @@ static void destroy_endpoint(grpc_exec_ctx *exec_ctx,
static void close_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s_ignored,
void *arg_ignored) {
grpc_error *error) {
if (!t->closed) {
t->closed = 1;
connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN,
"close_transport");
GRPC_ERROR_REF(error), "close_transport");
if (t->ep) {
allow_endpoint_shutdown_locked(exec_ctx, t);
}
@ -463,6 +463,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
}
}
GRPC_ERROR_UNREF(error);
}
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
@ -551,7 +552,9 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx,
s->global.id == 0);
GPR_ASSERT(!s->global.in_stream_map);
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
close_transport_locked(exec_ctx, t, NULL, NULL);
close_transport_locked(
exec_ctx, t,
GRPC_ERROR_CREATE("Last stream closed after sending goaway"));
}
if (!t->executor.parsing_active && s->global.id) {
GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
@ -645,7 +648,7 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
t->executor.writing_active = 1;
REF_TRANSPORT(t, "writing");
prevent_endpoint_shutdown(t);
grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, true, NULL);
grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL);
}
check_read_ops(exec_ctx, &t->global);
@ -756,12 +759,12 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s_ignored,
void *a) {
bool success = (bool)(uintptr_t)a;
grpc_error *error = a;
allow_endpoint_shutdown_locked(exec_ctx, t);
if (!success) {
drop_connection(exec_ctx, t);
if (error != GRPC_ERROR_NONE) {
drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
}
grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
@ -769,7 +772,8 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global;
while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
&stream_global)) {
fail_pending_writes(exec_ctx, stream_global);
fail_pending_writes(exec_ctx, &t->global, stream_global,
GRPC_ERROR_REF(error));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
}
@ -782,18 +786,18 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
}
UNREF_TRANSPORT(exec_ctx, t, "writing");
GRPC_ERROR_UNREF(error);
}
void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
void *transport_writing, bool success) {
void *transport_writing, grpc_error *error) {
grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL,
terminate_writing_with_lock,
(void *)(uintptr_t)success, 0);
grpc_chttp2_run_with_global_lock(
exec_ctx, t, NULL, terminate_writing_with_lock, GRPC_ERROR_REF(error), 0);
}
static void writing_action(grpc_exec_ctx *exec_ctx, void *gt,
bool iomgr_success_ignored) {
grpc_error *error) {
grpc_chttp2_transport *t = gt;
GPR_TIMER_BEGIN("writing_action", 0);
grpc_chttp2_perform_writes(exec_ctx, &t->writing, t->ep);
@ -806,13 +810,19 @@ void grpc_chttp2_add_incoming_goaway(
char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg));
gpr_free(msg);
gpr_slice_unref(goaway_text);
transport_global->seen_goaway = 1;
/* lie: use transient failure from the transport to indicate goaway has been
* received */
connectivity_state_set(exec_ctx, transport_global,
GRPC_CHANNEL_TRANSIENT_FAILURE, "got_goaway");
connectivity_state_set(
exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
grpc_error_set_str(
grpc_error_set_int(GRPC_ERROR_CREATE("GOAWAY received"),
GRPC_ERROR_INT_HTTP2_ERROR,
(intptr_t)goaway_error),
GRPC_ERROR_STR_RAW_BYTES, msg),
"got_goaway");
gpr_free(msg);
}
static void maybe_start_some_streams(
@ -841,9 +851,9 @@ static void maybe_start_some_streams(
transport_global->next_stream_id += 2;
if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
connectivity_state_set(exec_ctx, transport_global,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"no_more_stream_ids");
connectivity_state_set(
exec_ctx, transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_CREATE("Stream IDs exhausted"), "no_more_stream_ids");
}
stream_global->outgoing_window =
@ -871,34 +881,40 @@ static void maybe_start_some_streams(
}
#define CLOSURE_BARRIER_STATS_BIT (1 << 0)
#define CLOSURE_BARRIER_FAILURE_BIT (1 << 1)
#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
static grpc_closure *add_closure_barrier(grpc_closure *closure) {
closure->final_data += CLOSURE_BARRIER_FIRST_REF_BIT;
closure->next_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT;
return closure;
}
void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global,
grpc_closure **pclosure, int success) {
void grpc_chttp2_complete_closure_step(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure,
grpc_error *error) {
grpc_closure *closure = *pclosure;
if (closure == NULL) {
GRPC_ERROR_UNREF(error);
return;
}
closure->final_data -= CLOSURE_BARRIER_FIRST_REF_BIT;
if (!success) {
closure->final_data |= CLOSURE_BARRIER_FAILURE_BIT;
closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
if (error != GRPC_ERROR_NONE) {
if (closure->error == GRPC_ERROR_NONE) {
closure->error =
GRPC_ERROR_CREATE("Error in HTTP transport completing operation");
closure->error = grpc_error_set_str(
closure->error, GRPC_ERROR_STR_TARGET_ADDRESS,
TRANSPORT_FROM_GLOBAL(transport_global)->peer_string);
}
closure->error = grpc_error_add_child(closure->error, error);
}
if (closure->final_data < CLOSURE_BARRIER_FIRST_REF_BIT) {
if (closure->final_data & CLOSURE_BARRIER_STATS_BIT) {
if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
grpc_transport_move_stats(&stream_global->stats,
stream_global->collecting_stats);
stream_global->collecting_stats = NULL;
}
grpc_exec_ctx_enqueue(
exec_ctx, closure,
(closure->final_data & CLOSURE_BARRIER_FAILURE_BIT) == 0, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, closure->error, NULL);
}
*pclosure = NULL;
}
@ -916,7 +932,7 @@ static int contains_non_ok_status(
return 0;
}
static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, bool success) {}
static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
@ -933,12 +949,13 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
}
/* use final_data as a barrier until enqueue time; the inital counter is
dropped at the end of this function */
on_complete->final_data = CLOSURE_BARRIER_FIRST_REF_BIT;
on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
on_complete->error = GRPC_ERROR_NONE;
if (op->collect_stats != NULL) {
GPR_ASSERT(stream_global->collecting_stats == NULL);
stream_global->collecting_stats = op->collect_stats;
on_complete->final_data |= CLOSURE_BARRIER_STATS_BIT;
on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
}
if (op->cancel_with_status != GRPC_STATUS_OK) {
@ -985,8 +1002,10 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
}
} else {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_initial_metadata_finished, 0);
exec_ctx, transport_global, stream_global,
&stream_global->send_initial_metadata_finished,
GRPC_ERROR_CREATE(
"Attempt to send initial metadata after stream was closed"));
}
}
}
@ -997,7 +1016,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
stream_global->send_message_finished = add_closure_barrier(on_complete);
if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_message_finished, 0);
exec_ctx, transport_global, stream_global,
&stream_global->send_message_finished,
GRPC_ERROR_CREATE("Attempt to send message after stream was closed"));
} else {
stream_global->send_message = op->send_message;
if (stream_global->id != 0) {
@ -1031,9 +1052,12 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
}
if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
exec_ctx, transport_global, stream_global,
&stream_global->send_trailing_metadata_finished,
grpc_metadata_batch_is_empty(op->send_trailing_metadata));
grpc_metadata_batch_is_empty(op->send_trailing_metadata)
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE("Attempt to send trailing metadata after "
"stream was closed"));
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
@ -1072,7 +1096,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
grpc_chttp2_complete_closure_step(exec_ctx, stream_global, &on_complete, 1);
grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
&on_complete, GRPC_ERROR_NONE);
GPR_TIMER_END("perform_stream_op_locked", 0);
}
@ -1109,7 +1134,7 @@ static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
for (ping = transport_global->pings.next; ping != &transport_global->pings;
ping = ping->next) {
if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
grpc_exec_ctx_enqueue(exec_ctx, ping->on_recv, true, NULL);
grpc_exec_ctx_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE, NULL);
ping->next->prev = ping->prev;
ping->prev->next = ping->next;
gpr_free(ping);
@ -1131,7 +1156,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream *s_unused,
void *stream_op) {
grpc_transport_op *op = stream_op;
bool close_transport = op->disconnect;
grpc_error *close_transport = op->disconnect_with_error;
/* If there's a set_accept_stream ensure that we're not parsing
to avoid changing things out from underneath */
@ -1142,7 +1167,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
return;
}
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
if (op->on_connectivity_state_change != NULL) {
grpc_connectivity_state_notify_on_state_change(
@ -1156,7 +1181,9 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
t->global.last_incoming_stream_id,
(uint32_t)grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
close_transport = !grpc_chttp2_has_streams(t);
close_transport = grpc_chttp2_has_streams(t)
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE("GOAWAY sent");
}
if (op->set_accept_stream) {
@ -1177,8 +1204,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
send_ping_locked(t, op->send_ping);
}
if (close_transport) {
close_transport_locked(exec_ctx, t, NULL, NULL);
if (close_transport != GRPC_ERROR_NONE) {
close_transport_locked(exec_ctx, t, close_transport);
}
}
@ -1214,8 +1241,8 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
grpc_chttp2_incoming_metadata_buffer_publish(
&stream_global->received_initial_metadata,
stream_global->recv_initial_metadata);
grpc_exec_ctx_enqueue(
exec_ctx, stream_global->recv_initial_metadata_ready, true, NULL);
grpc_exec_ctx_sched(exec_ctx, stream_global->recv_initial_metadata_ready,
GRPC_ERROR_NONE, NULL);
stream_global->recv_initial_metadata_ready = NULL;
}
if (stream_global->recv_message_ready != NULL) {
@ -1228,13 +1255,13 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
*stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
&stream_global->incoming_frames);
GPR_ASSERT(*stream_global->recv_message != NULL);
grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
NULL);
grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
GRPC_ERROR_NONE, NULL);
stream_global->recv_message_ready = NULL;
} else if (stream_global->published_trailing_metadata) {
*stream_global->recv_message = NULL;
grpc_exec_ctx_enqueue(exec_ctx, stream_global->recv_message_ready, true,
NULL);
grpc_exec_ctx_sched(exec_ctx, stream_global->recv_message_ready,
GRPC_ERROR_NONE, NULL);
stream_global->recv_message_ready = NULL;
}
}
@ -1255,8 +1282,8 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
&stream_global->received_trailing_metadata,
stream_global->recv_trailing_metadata);
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->recv_trailing_metadata_finished, 1);
exec_ctx, transport_global, stream_global,
&stream_global->recv_trailing_metadata_finished, GRPC_ERROR_NONE);
}
}
}
@ -1272,7 +1299,7 @@ static void decrement_active_streams_locked(
}
static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
uint32_t id) {
uint32_t id, grpc_error *error) {
size_t new_stream_count;
grpc_chttp2_stream *s =
grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
@ -1287,12 +1314,15 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
}
if (s->parsing.data_parser.parsing_frame != NULL) {
grpc_chttp2_incoming_byte_stream_finished(
exec_ctx, s->parsing.data_parser.parsing_frame, 0, 0);
exec_ctx, s->parsing.data_parser.parsing_frame,
GRPC_ERROR_CREATE_REFERENCING("Stream removed", &error, 1), 0);
s->parsing.data_parser.parsing_frame = NULL;
}
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
close_transport_locked(exec_ctx, t, NULL, NULL);
close_transport_locked(
exec_ctx, t,
GRPC_ERROR_CREATE("Last stream closed after sending GOAWAY"));
}
if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
@ -1305,6 +1335,7 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->global.concurrent_stream_count = (uint32_t)new_stream_count;
maybe_start_some_streams(exec_ctx, &t->global);
}
GRPC_ERROR_UNREF(error);
}
static void cancel_from_api(grpc_exec_ctx *exec_ctx,
@ -1332,8 +1363,10 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
stream_global->seen_error = true;
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1);
grpc_chttp2_mark_stream_closed(
exec_ctx, transport_global, stream_global, 1, 1,
grpc_error_set_int(GRPC_ERROR_CREATE("Cancelled"),
GRPC_ERROR_INT_GRPC_STATUS, status));
}
void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
@ -1374,23 +1407,27 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
}
static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global) {
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global,
grpc_error *error) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_initial_metadata_finished,
0);
exec_ctx, transport_global, stream_global,
&stream_global->send_initial_metadata_finished, GRPC_ERROR_REF(error));
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_trailing_metadata_finished,
0);
grpc_chttp2_complete_closure_step(exec_ctx, stream_global,
&stream_global->send_message_finished, 0);
exec_ctx, transport_global, stream_global,
&stream_global->send_trailing_metadata_finished, GRPC_ERROR_REF(error));
grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global,
&stream_global->send_message_finished,
error);
}
void grpc_chttp2_mark_stream_closed(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, int close_reads,
int close_writes) {
grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
grpc_error *error) {
if (stream_global->read_closed && stream_global->write_closed) {
/* already closed */
GRPC_ERROR_UNREF(error);
return;
}
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
@ -1407,7 +1444,8 @@ void grpc_chttp2_mark_stream_closed(
grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
stream_global);
} else {
fail_pending_writes(exec_ctx, stream_global);
fail_pending_writes(exec_ctx, transport_global, stream_global,
GRPC_ERROR_REF(error));
}
}
if (stream_global->read_closed && stream_global->write_closed) {
@ -1418,11 +1456,12 @@ void grpc_chttp2_mark_stream_closed(
} else {
if (stream_global->id != 0) {
remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
stream_global->id);
stream_global->id, GRPC_ERROR_REF(error));
}
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
}
}
GRPC_ERROR_UNREF(error);
}
static void close_from_api(grpc_exec_ctx *exec_ctx,
@ -1529,8 +1568,16 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
optional_message);
grpc_error *err = GRPC_ERROR_CREATE("Stream closed");
err = grpc_error_set_int(err, GRPC_ERROR_INT_GRPC_STATUS, status);
if (optional_message) {
char *str =
gpr_dump_slice(*optional_message, GPR_DUMP_HEX | GPR_DUMP_ASCII);
err = grpc_error_set_str(err, GRPC_ERROR_STR_GRPC_MESSAGE, str);
gpr_free(str);
}
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1);
1, err);
}
static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
@ -1549,8 +1596,9 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
grpc_chttp2_for_all_streams(&t->global, exec_ctx, cancel_stream_cb);
}
static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
close_transport_locked(exec_ctx, t, NULL, NULL);
static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_error *error) {
close_transport_locked(exec_ctx, t, error);
end_all_the_calls(exec_ctx, t);
}
@ -1581,20 +1629,22 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
static void reading_action_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s_unused, void *arg);
static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success);
static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error);
static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s_unused, void *arg);
static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_stream *s_unused, void *arg);
static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
static void reading_action(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error) {
/* Control flow:
reading_action_locked ->
(parse_unlocked -> post_parse_locked)? ->
post_reading_action_locked */
grpc_chttp2_run_with_global_lock(exec_ctx, tp, NULL, reading_action_locked,
(void *)(uintptr_t)success, 0);
GRPC_ERROR_REF(error), 0);
}
static void reading_action_locked(grpc_exec_ctx *exec_ctx,
@ -1602,7 +1652,7 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream *s_unused, void *arg) {
grpc_chttp2_transport_global *transport_global = &t->global;
grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
bool success = (bool)(uintptr_t)arg;
grpc_error *error = arg;
GPR_ASSERT(!t->executor.parsing_active);
if (!t->closed) {
@ -1611,48 +1661,54 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_map_move_into(&t->new_stream_map,
&t->parsing_stream_map);
grpc_chttp2_prepare_to_read(transport_global, transport_parsing);
grpc_exec_ctx_enqueue(exec_ctx, &t->parsing_action, success, NULL);
grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL);
} else {
post_reading_action_locked(exec_ctx, t, s_unused, arg);
}
}
static bool try_http_parsing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) {
static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) {
grpc_http_parser parser;
size_t i = 0;
bool success = false;
grpc_error *error = GRPC_ERROR_NONE;
grpc_http_response response;
memset(&response, 0, sizeof(response));
grpc_http_parser_init(&parser);
grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
for (; i < t->read_buffer.count &&
grpc_http_parser_parse(&parser, t->read_buffer.slices[i]);
i++)
;
if (grpc_http_parser_eof(&parser) && parser.type == GRPC_HTTP_RESPONSE) {
success = true;
GRPC_CHTTP2_IF_TRACING(gpr_log(
GPR_DEBUG, "Trying to connect an http1.x server, received status:%d",
parser.http.response.status));
grpc_error *parse_error = GRPC_ERROR_NONE;
for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) {
parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i]);
}
if (parse_error == GRPC_ERROR_NONE &&
(parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
error = grpc_error_set_int(
GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
GRPC_ERROR_INT_HTTP_STATUS, response.status);
}
GRPC_ERROR_UNREF(parse_error);
grpc_http_parser_destroy(&parser);
return success;
grpc_http_response_destroy(&response);
return error;
}
static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_chttp2_transport *t = arg;
GPR_TIMER_BEGIN("reading_action.parse", 0);
size_t i = 0;
for (; i < t->read_buffer.count &&
grpc_chttp2_perform_read(exec_ctx, &t->parsing,
t->read_buffer.slices[i]);
i++)
;
grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
GRPC_ERROR_NONE};
for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing,
t->read_buffer.slices[i]);
};
if (i != t->read_buffer.count) {
success = false;
gpr_slice_unref(t->optional_drop_message);
if (try_http_parsing(exec_ctx, t)) {
errors[2] = try_http_parsing(exec_ctx, t);
if (errors[2] != GRPC_ERROR_NONE) {
t->optional_drop_message = gpr_slice_from_copied_string(
"Connection dropped: received http1.x response");
} else {
@ -1660,9 +1716,18 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
"Connection dropped: received unparseable response");
}
}
grpc_error *err =
errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE &&
errors[2] == GRPC_ERROR_NONE
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
GPR_ARRAY_SIZE(errors));
for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
GRPC_ERROR_UNREF(errors[i]);
}
GPR_TIMER_END("reading_action.parse", 0);
grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked,
(void *)(uintptr_t)success, 0);
grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, err,
0);
}
static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@ -1699,7 +1764,8 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GPR_ASSERT(stream_global->in_stream_map);
GPR_ASSERT(stream_global->write_closed);
GPR_ASSERT(stream_global->read_closed);
remove_stream(exec_ctx, t, stream_global->id);
remove_stream(exec_ctx, t, stream_global->id,
GRPC_ERROR_CREATE("Stream removed"));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
}
@ -1710,10 +1776,13 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s_unused,
void *arg) {
bool success = (bool)(uintptr_t)arg;
grpc_error *error = arg;
bool keep_reading = false;
if (!success || t->closed) {
drop_connection(exec_ctx, t);
if (error == GRPC_ERROR_NONE && t->closed) {
error = GRPC_ERROR_CREATE("Transport closed");
}
if (error != GRPC_ERROR_NONE) {
drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
t->endpoint_reading = 0;
if (!t->executor.writing_active && t->ep) {
grpc_endpoint_destroy(exec_ctx, t->ep);
@ -1735,6 +1804,8 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
} else {
UNREF_TRANSPORT(exec_ctx, t, "reading_action");
}
GRPC_ERROR_UNREF(error);
}
/*******************************************************************************
@ -1743,13 +1814,13 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
static void connectivity_state_set(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_connectivity_state state, const char *reason) {
grpc_connectivity_state state, grpc_error *error, const char *reason) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
grpc_connectivity_state_set(
exec_ctx,
&TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker,
state, reason);
state, error, reason);
}
/*******************************************************************************
@ -1795,6 +1866,7 @@ static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
grpc_chttp2_incoming_byte_stream *bs) {
if (gpr_unref(&bs->refs)) {
GRPC_ERROR_UNREF(bs->error);
gpr_slice_buffer_destroy(&bs->slices);
gpr_free(bs);
}
@ -1863,9 +1935,10 @@ static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx,
}
if (bs->slices.count > 0) {
*arg->slice = gpr_slice_buffer_take_first(&bs->slices);
grpc_exec_ctx_enqueue(exec_ctx, arg->on_complete, true, NULL);
} else if (bs->failed) {
grpc_exec_ctx_enqueue(exec_ctx, arg->on_complete, false, NULL);
grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_NONE, NULL);
} else if (bs->error != GRPC_ERROR_NONE) {
grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_REF(bs->error),
NULL);
} else {
bs->on_next = arg->on_complete;
bs->next = arg->slice;
@ -1922,7 +1995,7 @@ static void incoming_byte_stream_push_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_incoming_byte_stream *bs = arg->byte_stream;
if (bs->on_next != NULL) {
*bs->next = arg->slice;
grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, true, NULL);
grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE, NULL);
bs->on_next = NULL;
} else {
gpr_slice_buffer_add(&bs->slices, arg->slice);
@ -1940,13 +2013,30 @@ void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
sizeof(arg));
}
typedef struct {
grpc_chttp2_incoming_byte_stream *bs;
grpc_error *error;
} bs_fail_args;
static bs_fail_args *make_bs_fail_args(grpc_chttp2_incoming_byte_stream *bs,
grpc_error *error) {
bs_fail_args *a = gpr_malloc(sizeof(*a));
a->bs = bs;
a->error = error;
return a;
}
static void incoming_byte_stream_finished_failed_locked(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
void *argp) {
grpc_chttp2_incoming_byte_stream *bs = argp;
grpc_exec_ctx_enqueue(exec_ctx, bs->on_next, false, NULL);
bs_fail_args *a = argp;
grpc_chttp2_incoming_byte_stream *bs = a->bs;
grpc_error *error = a->error;
gpr_free(a);
grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL);
bs->on_next = NULL;
bs->failed = 1;
GRPC_ERROR_UNREF(bs->error);
bs->error = error;
incoming_byte_stream_unref(exec_ctx, bs);
}
@ -1959,25 +2049,26 @@ static void incoming_byte_stream_finished_ok_locked(grpc_exec_ctx *exec_ctx,
}
void grpc_chttp2_incoming_byte_stream_finished(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
int from_parsing_thread) {
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
grpc_error *error, int from_parsing_thread) {
if (from_parsing_thread) {
if (success) {
if (error == GRPC_ERROR_NONE) {
grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream,
incoming_byte_stream_finished_ok_locked,
bs, 0);
} else {
incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport,
bs->stream, bs);
}
} else {
if (success) {
grpc_chttp2_run_with_global_lock(
exec_ctx, bs->transport, bs->stream,
incoming_byte_stream_finished_failed_locked, bs, 0);
incoming_byte_stream_finished_failed_locked,
make_bs_fail_args(bs, error), 0);
}
} else {
if (error == GRPC_ERROR_NONE) {
incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport,
bs->stream, bs);
} else {
incoming_byte_stream_finished_failed_locked(exec_ctx, bs->transport,
bs->stream, bs);
incoming_byte_stream_finished_failed_locked(
exec_ctx, bs->transport, bs->stream, make_bs_fail_args(bs, error));
}
}
}
@ -2000,7 +2091,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
gpr_slice_buffer_init(&incoming_byte_stream->slices);
incoming_byte_stream->on_next = NULL;
incoming_byte_stream->is_tail = 1;
incoming_byte_stream->failed = 0;
incoming_byte_stream->error = GRPC_ERROR_NONE;
if (add_to_queue->head == NULL) {
add_to_queue->head = incoming_byte_stream;
} else {
@ -2141,5 +2232,5 @@ void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
REF_TRANSPORT(t, "reading_action"); /* matches unref inside reading_action */
gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
reading_action(exec_ctx, t, 1);
reading_action(exec_ctx, t, GRPC_ERROR_NONE);
}

@ -37,13 +37,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
/* Common definitions for frame handling in the chttp2 transport */
typedef enum {
GRPC_CHTTP2_PARSE_OK,
GRPC_CHTTP2_STREAM_ERROR,
GRPC_CHTTP2_CONNECTION_ERROR
} grpc_chttp2_parse_error;
#include "src/core/lib/iomgr/error.h"
/* defined in internal.h */
typedef struct grpc_chttp2_stream_parsing grpc_chttp2_stream_parsing;

@ -37,24 +37,25 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/transport.h"
grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
grpc_chttp2_data_parser *parser) {
grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser) {
parser->state = GRPC_CHTTP2_DATA_FH_0;
parser->parsing_frame = NULL;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
grpc_chttp2_data_parser *parser) {
grpc_byte_stream *bs;
if (parser->parsing_frame) {
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame,
0, 1);
grpc_chttp2_incoming_byte_stream_finished(
exec_ctx, parser->parsing_frame, GRPC_ERROR_CREATE("Parser destroyed"),
1);
}
while (
(bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
@ -62,11 +63,16 @@ void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
}
}
grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
grpc_chttp2_data_parser *parser, uint8_t flags) {
grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser,
uint8_t flags,
uint32_t stream_id) {
if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
gpr_log(GPR_ERROR, "unsupported data flags: 0x%02x", flags);
return GRPC_CHTTP2_STREAM_ERROR;
char *msg;
gpr_asprintf(&msg, "unsupported data flags: 0x%02x", flags);
grpc_error *err = grpc_error_set_int(
GRPC_ERROR_CREATE(msg), GRPC_ERROR_INT_STREAM_ID, (intptr_t)stream_id);
gpr_free(msg);
return err;
}
if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
@ -75,7 +81,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
parser->is_last_frame = 0;
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
void grpc_chttp2_incoming_frame_queue_merge(
@ -139,7 +145,7 @@ void grpc_chttp2_encode_data(uint32_t id, gpr_slice_buffer *inbuf,
stats->data_bytes += write_bytes;
}
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_error *grpc_chttp2_data_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -149,19 +155,20 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_chttp2_data_parser *p = parser;
uint32_t message_flags;
grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
char *msg;
if (is_last && p->is_last_frame) {
stream_parsing->received_close = 1;
}
if (cur == end) {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
switch (p->state) {
case GRPC_CHTTP2_DATA_ERROR:
p->state = GRPC_CHTTP2_DATA_ERROR;
return GRPC_CHTTP2_STREAM_ERROR;
return GRPC_ERROR_REF(p->error);
fh_0:
case GRPC_CHTTP2_DATA_FH_0:
stream_parsing->stats.incoming.framing_bytes++;
@ -174,13 +181,23 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->is_frame_compressed = 1; /* GPR_TRUE */
break;
default:
gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type);
p->error = GRPC_ERROR_CREATE(msg);
p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID,
(intptr_t)stream_parsing->id);
gpr_free(msg);
msg = gpr_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
p->error =
grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES, msg);
gpr_free(msg);
p->error =
grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
p->state = GRPC_CHTTP2_DATA_ERROR;
return GRPC_CHTTP2_STREAM_ERROR;
return GRPC_ERROR_REF(p->error);
}
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_1:
@ -188,7 +205,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_size = ((uint32_t)*cur) << 24;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_2:
@ -196,7 +213,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_size |= ((uint32_t)*cur) << 16;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_3:
@ -204,7 +221,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_size |= ((uint32_t)*cur) << 8;
if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_4;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_CHTTP2_DATA_FH_4:
@ -225,7 +242,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
if (cur == end) {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
uint32_t remaining = (uint32_t)(end - cur);
if (remaining == p->frame_size) {
@ -233,19 +250,19 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_chttp2_incoming_byte_stream_push(
exec_ctx, p->parsing_frame,
gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
1);
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
GRPC_ERROR_NONE, 1);
p->parsing_frame = NULL;
p->state = GRPC_CHTTP2_DATA_FH_0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
} else if (remaining > p->frame_size) {
stream_parsing->stats.incoming.data_bytes += p->frame_size;
grpc_chttp2_incoming_byte_stream_push(
exec_ctx, p->parsing_frame,
gpr_slice_sub(slice, (size_t)(cur - beg),
(size_t)(cur + p->frame_size - beg)));
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
1);
grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
GRPC_ERROR_NONE, 1);
p->parsing_frame = NULL;
cur += p->frame_size;
goto fh_0; /* loop */
@ -256,9 +273,9 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
p->frame_size -= remaining;
stream_parsing->stats.incoming.data_bytes += remaining;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
}
GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}

@ -66,6 +66,7 @@ typedef struct {
uint8_t is_last_frame;
uint8_t frame_type;
uint32_t frame_size;
grpc_error *error;
int is_frame_compressed;
grpc_chttp2_incoming_frame_queue incoming_frames;
@ -79,19 +80,19 @@ grpc_byte_stream *grpc_chttp2_incoming_frame_queue_pop(
grpc_chttp2_incoming_frame_queue *q);
/* initialize per-stream state for data frame parsing */
grpc_chttp2_parse_error grpc_chttp2_data_parser_init(
grpc_chttp2_data_parser *parser);
grpc_error *grpc_chttp2_data_parser_init(grpc_chttp2_data_parser *parser);
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
grpc_chttp2_data_parser *parser);
/* start processing a new data frame */
grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
grpc_chttp2_data_parser *parser, uint8_t flags);
grpc_error *grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser *parser,
uint8_t flags,
uint32_t stream_id);
/* handle a slice of a data frame - is_last indicates the last slice of a
frame */
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
grpc_error *grpc_chttp2_data_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p) {
p->debug_data = NULL;
@ -47,11 +48,15 @@ void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p) {
gpr_free(p->debug_data);
}
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_goaway_parser *p, uint32_t length, uint8_t flags) {
grpc_error *grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser *p,
uint32_t length,
uint8_t flags) {
if (length < 8) {
gpr_log(GPR_ERROR, "goaway frame too short (%d bytes)", length);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "goaway frame too short (%d bytes)", length);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
gpr_free(p->debug_data);
@ -59,10 +64,10 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
p->debug_data = gpr_malloc(p->debug_length);
p->debug_pos = 0;
p->state = GRPC_CHTTP2_GOAWAY_LSI0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
grpc_error *grpc_chttp2_goaway_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -75,7 +80,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI0:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id = ((uint32_t)*cur) << 24;
++cur;
@ -83,7 +88,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI1:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id |= ((uint32_t)*cur) << 16;
++cur;
@ -91,7 +96,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI2:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id |= ((uint32_t)*cur) << 8;
++cur;
@ -99,7 +104,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_LSI3:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_LSI3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->last_stream_id |= ((uint32_t)*cur);
++cur;
@ -107,7 +112,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR0:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code = ((uint32_t)*cur) << 24;
++cur;
@ -115,7 +120,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR1:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code |= ((uint32_t)*cur) << 16;
++cur;
@ -123,7 +128,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR2:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code |= ((uint32_t)*cur) << 8;
++cur;
@ -131,7 +136,7 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
case GRPC_CHTTP2_GOAWAY_ERR3:
if (cur == end) {
p->state = GRPC_CHTTP2_GOAWAY_ERR3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
p->error_code |= ((uint32_t)*cur);
++cur;
@ -151,9 +156,9 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
gpr_slice_new(p->debug_data, p->debug_length, gpr_free);
p->debug_data = NULL;
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code,

@ -63,9 +63,9 @@ typedef struct {
void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser *p);
void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser *p);
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_error *grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_goaway_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
grpc_error *grpc_chttp2_goaway_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
gpr_slice slice = gpr_slice_malloc(9 + 8);
@ -57,18 +58,22 @@ gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
return slice;
}
grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags) {
grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
uint32_t length,
uint8_t flags) {
if (flags & 0xfe || length != 8) {
gpr_log(GPR_ERROR, "invalid ping: length=%d, flags=%02x", length, flags);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid ping: length=%d, flags=%02x", length, flags);
grpc_error *error = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return error;
}
parser->byte = 0;
parser->is_ack = flags;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
grpc_error *grpc_chttp2_ping_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -93,5 +98,5 @@ grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
}
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}

@ -46,9 +46,9 @@ typedef struct {
gpr_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
grpc_chttp2_ping_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
uint32_t length, uint8_t flags);
grpc_error *grpc_chttp2_ping_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -34,7 +34,9 @@
#include "src/core/ext/transport/chttp2/transport/frame_rst_stream.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/transport/chttp2/transport/frame.h"
@ -67,18 +69,21 @@ gpr_slice grpc_chttp2_rst_stream_create(uint32_t id, uint32_t code,
return slice;
}
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_error *grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags) {
if (length != 4) {
gpr_log(GPR_ERROR, "invalid rst_stream: length=%d, flags=%02x", length,
flags);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid rst_stream: length=%d, flags=%02x", length,
flags);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
parser->byte = 0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
grpc_error *grpc_chttp2_rst_stream_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -97,12 +102,13 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
if (p->byte == 4) {
GPR_ASSERT(is_last);
stream_parsing->received_close = 1;
stream_parsing->saw_rst_stream = 1;
stream_parsing->rst_stream_reason = (((uint32_t)p->reason_bytes[0]) << 24) |
(((uint32_t)p->reason_bytes[1]) << 16) |
(((uint32_t)p->reason_bytes[2]) << 8) |
(((uint32_t)p->reason_bytes[3]));
stream_parsing->forced_close_error = grpc_error_set_int(
GRPC_ERROR_CREATE("RST_STREAM"), GRPC_ERROR_INT_HTTP2_ERROR,
(intptr_t)((((uint32_t)p->reason_bytes[0]) << 24) |
(((uint32_t)p->reason_bytes[1]) << 16) |
(((uint32_t)p->reason_bytes[2]) << 8) |
(((uint32_t)p->reason_bytes[3]))));
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}

@ -47,9 +47,9 @@ typedef struct {
gpr_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code,
grpc_transport_one_way_stats *stats);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_error *grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
grpc_error *grpc_chttp2_rst_stream_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -36,7 +36,9 @@
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
@ -118,7 +120,7 @@ gpr_slice grpc_chttp2_settings_ack_create(void) {
return output;
}
grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
grpc_error *grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
uint32_t *settings) {
parser->target_settings = settings;
@ -129,31 +131,29 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
if (flags == GRPC_CHTTP2_FLAG_ACK) {
parser->is_ack = 1;
if (length != 0) {
gpr_log(GPR_ERROR, "non-empty settings ack frame received");
return GRPC_CHTTP2_CONNECTION_ERROR;
return GRPC_ERROR_CREATE("non-empty settings ack frame received");
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
} else if (flags != 0) {
gpr_log(GPR_ERROR, "invalid flags on settings frame");
return GRPC_CHTTP2_CONNECTION_ERROR;
return GRPC_ERROR_CREATE("invalid flags on settings frame");
} else if (length % 6 != 0) {
gpr_log(GPR_ERROR, "settings frames must be a multiple of six bytes");
return GRPC_CHTTP2_CONNECTION_ERROR;
return GRPC_ERROR_CREATE("settings frames must be a multiple of six bytes");
} else {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
}
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
grpc_error *grpc_chttp2_settings_parser_parse(
grpc_exec_ctx *exec_ctx, void *p,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_settings_parser *parser = p;
const uint8_t *cur = GPR_SLICE_START_PTR(slice);
const uint8_t *end = GPR_SLICE_END_PTR(slice);
char *msg;
if (parser->is_ack) {
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
for (;;) {
@ -168,7 +168,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
gpr_slice_buffer_add(&transport_parsing->qbuf,
grpc_chttp2_settings_ack_create());
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->id = (uint16_t)(((uint16_t)*cur) << 8);
cur++;
@ -176,7 +176,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_ID1:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_ID1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->id = (uint16_t)(parser->id | (*cur));
cur++;
@ -184,7 +184,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL0:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->value = ((uint32_t)*cur) << 24;
cur++;
@ -192,7 +192,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL1:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL1;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->value |= ((uint32_t)*cur) << 16;
cur++;
@ -200,7 +200,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL2:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL2;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
parser->value |= ((uint32_t)*cur) << 8;
cur++;
@ -208,7 +208,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
case GRPC_CHTTP2_SPS_VAL3:
if (cur == end) {
parser->state = GRPC_CHTTP2_SPS_VAL3;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
} else {
parser->state = GRPC_CHTTP2_SPS_ID0;
}
@ -229,9 +229,11 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
transport_parsing->last_incoming_stream_id, sp->error_value,
gpr_slice_from_static_string("HTTP2 settings error"),
&transport_parsing->qbuf);
gpr_log(GPR_ERROR, "invalid value %u passed for %s",
parser->value, sp->name);
return GRPC_CHTTP2_CONNECTION_ERROR;
gpr_asprintf(&msg, "invalid value %u passed for %s",
parser->value, sp->name);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
}
if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
@ -249,7 +251,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
transport_parsing->is_client ? "CLI" : "SVR", parser->id,
parser->value);
}
} else {
} else if (grpc_http_trace) {
gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",
parser->id, parser->value);
}

@ -92,10 +92,10 @@ gpr_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
/* Create an ack settings frame */
gpr_slice grpc_chttp2_settings_ack_create(void);
grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
grpc_error *grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_settings_parser *parser, uint32_t length, uint8_t flags,
uint32_t *settings);
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
grpc_error *grpc_chttp2_settings_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -34,7 +34,9 @@
#include "src/core/ext/transport/chttp2/transport/frame_window_update.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
gpr_slice grpc_chttp2_window_update_create(
uint32_t id, uint32_t window_update, grpc_transport_one_way_stats *stats) {
@ -62,19 +64,22 @@ gpr_slice grpc_chttp2_window_update_create(
return slice;
}
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
grpc_error *grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags) {
if (flags || length != 4) {
gpr_log(GPR_ERROR, "invalid window update: length=%d, flags=%02x", length,
flags);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid window update: length=%d, flags=%02x", length,
flags);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
parser->byte = 0;
parser->amount = 0;
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
grpc_error *grpc_chttp2_window_update_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
@ -96,8 +101,11 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
if (p->byte == 4) {
uint32_t received_update = p->amount;
if (received_update == 0 || (received_update & 0x80000000u)) {
gpr_log(GPR_ERROR, "invalid window update bytes: %d", p->amount);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "invalid window update bytes: %d", p->amount);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
GPR_ASSERT(is_last);
@ -115,5 +123,5 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
}
}
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}

@ -48,9 +48,9 @@ typedef struct {
gpr_slice grpc_chttp2_window_update_create(uint32_t id, uint32_t window_delta,
grpc_transport_one_way_stats *stats);
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
grpc_error *grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_window_update_parser *parser, uint32_t length, uint8_t flags);
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
grpc_error *grpc_chttp2_window_update_parser_parse(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

File diff suppressed because it is too large Load Diff

@ -44,9 +44,8 @@
typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser;
typedef int (*grpc_chttp2_hpack_parser_state)(grpc_chttp2_hpack_parser *p,
const uint8_t *beg,
const uint8_t *end);
typedef grpc_error *(*grpc_chttp2_hpack_parser_state)(
grpc_chttp2_hpack_parser *p, const uint8_t *beg, const uint8_t *end);
typedef struct {
char *str;
@ -59,6 +58,8 @@ struct grpc_chttp2_hpack_parser {
void (*on_header)(void *user_data, grpc_mdelem *md);
void *on_header_user_data;
grpc_error *last_error;
/* current parse state - or a function that implements it */
grpc_chttp2_hpack_parser_state state;
/* future states dependent on the opening op code */
@ -103,12 +104,13 @@ void grpc_chttp2_hpack_parser_destroy(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 */
int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
const uint8_t *beg, const uint8_t *end);
grpc_error *grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
const uint8_t *beg,
const uint8_t *end);
/* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for
the transport */
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
grpc_error *grpc_chttp2_header_parser_parse(
grpc_exec_ctx *exec_ctx, void *hpack_parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/support/murmur_hash.h"
@ -262,18 +263,19 @@ void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
tbl->max_bytes = max_bytes;
}
int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes) {
grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes) {
if (tbl->current_table_bytes == bytes) {
return 1;
return GRPC_ERROR_NONE;
}
if (bytes > tbl->max_bytes) {
if (grpc_http_trace) {
gpr_log(GPR_ERROR,
"Attempt to make hpack table %d bytes when max is %d bytes",
bytes, tbl->max_bytes);
}
return 0;
char *msg;
gpr_asprintf(&msg,
"Attempt to make hpack table %d bytes when max is %d bytes",
bytes, tbl->max_bytes);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
@ -291,23 +293,25 @@ int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
rebuild_ents(tbl, new_cap);
}
}
return 1;
return GRPC_ERROR_NONE;
}
int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
grpc_error *grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
/* determine how many bytes of buffer this entry represents */
size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) +
GPR_SLICE_LENGTH(md->value->slice) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
if (tbl->current_table_bytes > tbl->max_bytes) {
if (grpc_http_trace) {
gpr_log(GPR_ERROR,
"HPACK max table size reduced to %d but not reflected by hpack "
"stream (still at %d)",
tbl->max_bytes, tbl->current_table_bytes);
}
return 0;
char *msg;
gpr_asprintf(
&msg,
"HPACK max table size reduced to %d but not reflected by hpack "
"stream (still at %d)",
tbl->max_bytes, tbl->current_table_bytes);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
/* we can't add elements bigger than the max table size */
@ -324,7 +328,7 @@ int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
while (tbl->num_ents) {
evict1(tbl);
}
return 1;
return GRPC_ERROR_NONE;
}
/* evict entries to ensure no overflow */
@ -339,7 +343,7 @@ int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
/* update accounting values */
tbl->num_ents++;
tbl->mem_used += (uint32_t)elem_bytes;
return 1;
return GRPC_ERROR_NONE;
}
grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(

@ -36,6 +36,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/transport/metadata.h"
/* HPACK header table */
@ -87,15 +88,15 @@ void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl);
void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl);
void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
uint32_t max_bytes);
int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes);
grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
uint32_t bytes);
/* lookup a table entry based on its hpack index */
grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
uint32_t index);
/* add a table entry to the index */
int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
grpc_mdelem *md) GRPC_MUST_USE_RESULT;
grpc_error *grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
grpc_mdelem *md) GRPC_MUST_USE_RESULT;
/* 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 */
typedef struct {

@ -156,7 +156,7 @@ struct grpc_chttp2_incoming_byte_stream {
grpc_byte_stream base;
gpr_refcount refs;
struct grpc_chttp2_incoming_byte_stream *next_message;
int failed;
grpc_error *error;
grpc_chttp2_transport *transport;
grpc_chttp2_stream *stream;
@ -275,10 +275,10 @@ struct grpc_chttp2_transport_parsing {
/* active parser */
void *parser_data;
grpc_chttp2_stream_parsing *incoming_stream;
grpc_chttp2_parse_error (*parser)(
grpc_exec_ctx *exec_ctx, void *parser_user_data,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_error *(*parser)(grpc_exec_ctx *exec_ctx, void *parser_user_data,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing,
gpr_slice slice, int is_last);
/* received settings */
uint32_t settings[GRPC_CHTTP2_NUM_SETTINGS];
@ -471,12 +471,12 @@ typedef struct {
} grpc_chttp2_stream_writing;
struct grpc_chttp2_stream_parsing {
/** saw some stream level error */
grpc_error *forced_close_error;
/** HTTP2 stream id for this stream, or zero if one has not been assigned */
uint32_t id;
/** has this stream received a close */
uint8_t received_close;
/** saw a rst_stream */
uint8_t saw_rst_stream;
/** how many header frames have we received? */
uint8_t header_frames_received;
/** which metadata did we get (on this parse) */
@ -488,8 +488,6 @@ struct grpc_chttp2_stream_parsing {
int64_t incoming_window;
/** parsing state for data frames */
grpc_chttp2_data_parser data_parser;
/** reason give to rst_stream */
uint32_t rst_stream_reason;
/** amount of window given */
int64_t outgoing_window;
/** number of bytes received - reset at end of parse thread execution */
@ -532,7 +530,7 @@ void grpc_chttp2_perform_writes(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
grpc_endpoint *endpoint);
void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
void *transport_writing, bool success);
void *transport_writing, grpc_error *error);
void grpc_chttp2_cleanup_writing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *global,
grpc_chttp2_transport_writing *writing);
@ -541,9 +539,9 @@ void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
/** Process one slice of incoming data; return 1 if the connection is still
viable after reading, or 0 if the connection should be torn down */
int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice);
grpc_error *grpc_chttp2_perform_read(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice);
void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
@ -673,9 +671,10 @@ void grpc_chttp2_for_all_streams(
void grpc_chttp2_parsing_become_skip_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global,
grpc_closure **pclosure, int success);
void grpc_chttp2_complete_closure_step(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure,
grpc_error *error);
void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *transport,
@ -778,8 +777,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
grpc_status_code status, gpr_slice *details);
void grpc_chttp2_mark_stream_closed(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, int close_reads,
int close_writes);
grpc_chttp2_stream_global *stream_global, int close_reads, int close_writes,
grpc_error *error);
void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global);
@ -811,8 +810,8 @@ void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx,
grpc_chttp2_incoming_byte_stream *bs,
gpr_slice slice);
void grpc_chttp2_incoming_byte_stream_finished(
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, int success,
int from_parsing_thread);
grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
grpc_error *error, int from_parsing_thread);
void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *parsing,

@ -49,30 +49,30 @@
((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \
parsing)))
static int init_frame_parser(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing);
static int init_header_frame_parser(
static grpc_error *init_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
static grpc_error *init_header_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
int is_continuation);
static int init_data_frame_parser(
static grpc_error *init_data_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
static grpc_error *init_rst_stream_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
static grpc_error *init_settings_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
static int init_rst_stream_parser(
static grpc_error *init_window_update_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
static int init_settings_frame_parser(
static grpc_error *init_ping_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
static int init_window_update_frame_parser(
static grpc_error *init_goaway_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing);
static int init_ping_parser(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing);
static int init_goaway_parser(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing);
static int init_skip_frame_parser(
static grpc_error *init_skip_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
int is_header);
static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last);
static grpc_error *parse_frame_slice(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last);
void grpc_chttp2_prepare_to_read(
grpc_chttp2_transport_global *transport_global,
@ -230,38 +230,42 @@ void grpc_chttp2_publish_reads(
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
if (stream_parsing->saw_rst_stream) {
if (stream_parsing->rst_stream_reason != GRPC_CHTTP2_NO_ERROR) {
grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status(
(grpc_chttp2_error_code)stream_parsing->rst_stream_reason);
char *status_details;
gpr_slice slice_details;
gpr_asprintf(&status_details, "Received RST_STREAM err=%d",
stream_parsing->rst_stream_reason);
slice_details = gpr_slice_from_copied_string(status_details);
gpr_free(status_details);
if (stream_parsing->forced_close_error != GRPC_ERROR_NONE) {
intptr_t reason;
bool has_reason = grpc_error_get_int(stream_parsing->forced_close_error,
GRPC_ERROR_INT_HTTP2_ERROR, &reason);
if (has_reason && reason != GRPC_CHTTP2_NO_ERROR) {
grpc_status_code status_code =
has_reason ? grpc_chttp2_http2_error_to_grpc_status(
(grpc_chttp2_error_code)reason)
: GRPC_STATUS_INTERNAL;
const char *status_details =
grpc_error_string(stream_parsing->forced_close_error);
gpr_slice slice_details = gpr_slice_from_copied_string(status_details);
grpc_error_free_string(status_details);
grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global,
status_code, &slice_details);
}
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
1, 1);
1, 1, stream_parsing->forced_close_error);
}
if (stream_parsing->received_close) {
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
1, 0);
1, 0, GRPC_ERROR_NONE);
}
}
}
int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice) {
grpc_error *grpc_chttp2_perform_read(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice) {
uint8_t *beg = GPR_SLICE_START_PTR(slice);
uint8_t *end = GPR_SLICE_END_PTR(slice);
uint8_t *cur = beg;
grpc_error *err;
if (cur == end) return 1;
if (cur == end) return GRPC_ERROR_NONE;
switch (transport_parsing->deframe_state) {
case GRPC_DTS_CLIENT_PREFIX_0:
@ -291,21 +295,25 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
->deframe_state]) {
gpr_log(GPR_INFO,
"Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
"at byte %d",
GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
->deframe_state],
(int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
[transport_parsing->deframe_state],
*cur, (int)*cur, transport_parsing->deframe_state);
return 0;
char *msg;
gpr_asprintf(
&msg,
"Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
"at byte %d",
GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
->deframe_state],
(int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING
[transport_parsing->deframe_state],
*cur, (int)*cur, transport_parsing->deframe_state);
err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
++cur;
++transport_parsing->deframe_state;
}
if (cur == end) {
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
dts_fh_0:
@ -314,7 +322,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_1;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_1:
@ -322,7 +330,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_2;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_2:
@ -330,7 +338,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_frame_size |= *cur;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_3;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_3:
@ -338,7 +346,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_frame_type = *cur;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_4;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_4:
@ -346,7 +354,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_frame_flags = *cur;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_5;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_5:
@ -354,7 +362,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_6;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_6:
@ -362,7 +370,7 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_7;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_7:
@ -370,15 +378,16 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_8;
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FH_8:
GPR_ASSERT(cur < end);
transport_parsing->incoming_stream_id |= ((uint32_t)*cur);
transport_parsing->deframe_state = GRPC_DTS_FRAME;
if (!init_frame_parser(exec_ctx, transport_parsing)) {
return 0;
err = init_frame_parser(exec_ctx, transport_parsing);
if (err != GRPC_ERROR_NONE) {
return err;
}
if (transport_parsing->incoming_stream_id != 0 &&
transport_parsing->incoming_stream_id >
@ -387,62 +396,69 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
transport_parsing->incoming_stream_id;
}
if (transport_parsing->incoming_frame_size == 0) {
if (!parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
1)) {
return 0;
err = parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(),
1);
if (err != GRPC_ERROR_NONE) {
return err;
}
transport_parsing->incoming_stream = NULL;
if (++cur == end) {
transport_parsing->deframe_state = GRPC_DTS_FH_0;
return 1;
return GRPC_ERROR_NONE;
}
goto dts_fh_0; /* loop */
} else if (transport_parsing->incoming_frame_size >
transport_parsing->max_frame_size) {
gpr_log(GPR_DEBUG, "Frame size %d is larger than max frame size %d",
transport_parsing->incoming_frame_size,
transport_parsing->max_frame_size);
return 0;
char *msg;
gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d",
transport_parsing->incoming_frame_size,
transport_parsing->max_frame_size);
err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
if (++cur == end) {
return 1;
return GRPC_ERROR_NONE;
}
/* fallthrough */
case GRPC_DTS_FRAME:
GPR_ASSERT(cur < end);
if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) {
if (!parse_frame_slice(exec_ctx, transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)),
1)) {
return 0;
err = parse_frame_slice(exec_ctx, transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)),
1);
if (err != GRPC_ERROR_NONE) {
return err;
}
transport_parsing->deframe_state = GRPC_DTS_FH_0;
transport_parsing->incoming_stream = NULL;
return 1;
return GRPC_ERROR_NONE;
} else if ((uint32_t)(end - cur) >
transport_parsing->incoming_frame_size) {
size_t cur_offset = (size_t)(cur - beg);
if (!parse_frame_slice(
exec_ctx, transport_parsing,
gpr_slice_sub_no_ref(
slice, cur_offset,
cur_offset + transport_parsing->incoming_frame_size),
1)) {
return 0;
err = parse_frame_slice(
exec_ctx, transport_parsing,
gpr_slice_sub_no_ref(
slice, cur_offset,
cur_offset + transport_parsing->incoming_frame_size),
1);
if (err != GRPC_ERROR_NONE) {
return err;
}
cur += transport_parsing->incoming_frame_size;
transport_parsing->incoming_stream = NULL;
goto dts_fh_0; /* loop */
} else {
if (!parse_frame_slice(exec_ctx, transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)),
0)) {
return 0;
err = parse_frame_slice(exec_ctx, transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)),
0);
if (err != GRPC_ERROR_NONE) {
return err;
}
transport_parsing->incoming_frame_size -= (uint32_t)(end - cur);
return 1;
return GRPC_ERROR_NONE;
}
GPR_UNREACHABLE_CODE(return 0);
}
@ -450,23 +466,30 @@ int grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
GPR_UNREACHABLE_CODE(return 0);
}
static int init_frame_parser(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing) {
static grpc_error *init_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
if (transport_parsing->expect_continuation_stream_id != 0) {
if (transport_parsing->incoming_frame_type !=
GRPC_CHTTP2_FRAME_CONTINUATION) {
gpr_log(GPR_ERROR, "Expected CONTINUATION frame, got frame type %02x",
transport_parsing->incoming_frame_type);
return 0;
char *msg;
gpr_asprintf(&msg, "Expected CONTINUATION frame, got frame type %02x",
transport_parsing->incoming_frame_type);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
if (transport_parsing->expect_continuation_stream_id !=
transport_parsing->incoming_stream_id) {
gpr_log(GPR_ERROR,
"Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
"grpc_chttp2_stream %08x",
transport_parsing->expect_continuation_stream_id,
transport_parsing->incoming_stream_id);
return 0;
char *msg;
gpr_asprintf(
&msg,
"Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
"grpc_chttp2_stream %08x",
transport_parsing->expect_continuation_stream_id,
transport_parsing->incoming_stream_id);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
return init_header_frame_parser(exec_ctx, transport_parsing, 1);
}
@ -476,8 +499,7 @@ static int init_frame_parser(grpc_exec_ctx *exec_ctx,
case GRPC_CHTTP2_FRAME_HEADER:
return init_header_frame_parser(exec_ctx, transport_parsing, 0);
case GRPC_CHTTP2_FRAME_CONTINUATION:
gpr_log(GPR_ERROR, "Unexpected CONTINUATION frame");
return 0;
return GRPC_ERROR_CREATE("Unexpected CONTINUATION frame");
case GRPC_CHTTP2_FRAME_RST_STREAM:
return init_rst_stream_parser(exec_ctx, transport_parsing);
case GRPC_CHTTP2_FRAME_SETTINGS:
@ -489,22 +511,24 @@ static int init_frame_parser(grpc_exec_ctx *exec_ctx,
case GRPC_CHTTP2_FRAME_GOAWAY:
return init_goaway_parser(exec_ctx, transport_parsing);
default:
gpr_log(GPR_ERROR, "Unknown frame type %02x",
transport_parsing->incoming_frame_type);
if (grpc_http_trace) {
gpr_log(GPR_ERROR, "Unknown frame type %02x",
transport_parsing->incoming_frame_type);
}
return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
}
}
static grpc_chttp2_parse_error skip_parser(
grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
return GRPC_CHTTP2_PARSE_OK;
static grpc_error *skip_parser(grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing,
gpr_slice slice, int is_last) {
return GRPC_ERROR_NONE;
}
static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
static int init_skip_frame_parser(
static grpc_error *init_skip_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
int is_header) {
if (is_header) {
@ -519,7 +543,7 @@ static int init_skip_frame_parser(
} else {
transport_parsing->parser = skip_parser;
}
return 1;
return GRPC_ERROR_NONE;
}
void grpc_chttp2_parsing_become_skip_parser(
@ -529,22 +553,28 @@ void grpc_chttp2_parsing_become_skip_parser(
transport_parsing->parser == grpc_chttp2_header_parser_parse);
}
static grpc_chttp2_parse_error update_incoming_window(
static grpc_error *update_incoming_window(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing) {
uint32_t incoming_frame_size = transport_parsing->incoming_frame_size;
if (incoming_frame_size > transport_parsing->incoming_window) {
gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %" PRId64,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_window);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_window);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
if (incoming_frame_size > stream_parsing->incoming_window) {
gpr_log(GPR_ERROR, "frame of size %d overflows incoming window of %" PRId64,
transport_parsing->incoming_frame_size,
stream_parsing->incoming_window);
return GRPC_CHTTP2_CONNECTION_ERROR;
char *msg;
gpr_asprintf(&msg, "frame of size %d overflows incoming window of %" PRId64,
transport_parsing->incoming_frame_size,
stream_parsing->incoming_window);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", transport_parsing, incoming_window,
@ -555,15 +585,15 @@ static grpc_chttp2_parse_error update_incoming_window(
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
return GRPC_CHTTP2_PARSE_OK;
return GRPC_ERROR_NONE;
}
static int init_data_frame_parser(
static grpc_error *init_data_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
grpc_chttp2_stream_parsing *stream_parsing =
grpc_chttp2_parsing_lookup_stream(transport_parsing,
transport_parsing->incoming_stream_id);
grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
grpc_error *err = GRPC_ERROR_NONE;
if (stream_parsing == NULL) {
return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
}
@ -571,33 +601,32 @@ static int init_data_frame_parser(
if (stream_parsing->received_close) {
return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
}
if (err == GRPC_CHTTP2_PARSE_OK) {
if (err == GRPC_ERROR_NONE) {
err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
}
if (err == GRPC_CHTTP2_PARSE_OK) {
if (err == GRPC_ERROR_NONE) {
err = grpc_chttp2_data_parser_begin_frame(
&stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
}
switch (err) {
case GRPC_CHTTP2_PARSE_OK:
transport_parsing->incoming_stream = stream_parsing;
transport_parsing->parser = grpc_chttp2_data_parser_parse;
transport_parsing->parser_data = &stream_parsing->data_parser;
return 1;
case GRPC_CHTTP2_STREAM_ERROR:
stream_parsing->received_close = 1;
stream_parsing->saw_rst_stream = 1;
stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
gpr_slice_buffer_add(
&transport_parsing->qbuf,
grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR,
&stream_parsing->stats.outgoing));
return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
case GRPC_CHTTP2_CONNECTION_ERROR:
return 0;
&stream_parsing->data_parser, transport_parsing->incoming_frame_flags,
stream_parsing->id);
}
if (err == GRPC_ERROR_NONE) {
transport_parsing->incoming_stream = stream_parsing;
transport_parsing->parser = grpc_chttp2_data_parser_parse;
transport_parsing->parser_data = &stream_parsing->data_parser;
return GRPC_ERROR_NONE;
} else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
/* handle stream errors by closing the stream */
stream_parsing->received_close = 1;
stream_parsing->forced_close_error = err;
gpr_slice_buffer_add(
&transport_parsing->qbuf,
grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR,
&stream_parsing->stats.outgoing));
return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
} else {
return err;
}
GPR_UNREACHABLE_CODE(return 0);
}
static void free_timeout(void *p) { gpr_free(p); }
@ -713,7 +742,7 @@ static void on_trailing_header(void *tp, grpc_mdelem *md) {
GPR_TIMER_END("on_trailing_header", 0);
}
static int init_header_frame_parser(
static grpc_error *init_header_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
int is_continuation) {
uint8_t is_eoh = (transport_parsing->incoming_frame_flags &
@ -808,15 +837,16 @@ static int init_header_frame_parser(
GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
}
return 1;
return GRPC_ERROR_NONE;
}
static int init_window_update_frame_parser(
static grpc_error *init_window_update_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
&transport_parsing->simple.window_update,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
grpc_error *err = grpc_chttp2_window_update_parser_begin_frame(
&transport_parsing->simple.window_update,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
if (err != GRPC_ERROR_NONE) return err;
if (transport_parsing->incoming_stream_id != 0) {
grpc_chttp2_stream_parsing *stream_parsing =
transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
@ -828,26 +858,27 @@ static int init_window_update_frame_parser(
}
transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.window_update;
return ok;
return GRPC_ERROR_NONE;
}
static int init_ping_parser(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_ping_parser_begin_frame(
&transport_parsing->simple.ping,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
static grpc_error *init_ping_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
grpc_error *err = grpc_chttp2_ping_parser_begin_frame(
&transport_parsing->simple.ping, transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
if (err != GRPC_ERROR_NONE) return err;
transport_parsing->parser = grpc_chttp2_ping_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.ping;
return ok;
return GRPC_ERROR_NONE;
}
static int init_rst_stream_parser(
static grpc_error *init_rst_stream_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
&transport_parsing->simple.rst_stream,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
grpc_error *err = grpc_chttp2_rst_stream_parser_begin_frame(
&transport_parsing->simple.rst_stream,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
if (err != GRPC_ERROR_NONE) return err;
grpc_chttp2_stream_parsing *stream_parsing =
transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
transport_parsing, transport_parsing->incoming_stream_id);
@ -857,37 +888,32 @@ static int init_rst_stream_parser(
stream_parsing->stats.incoming.framing_bytes += 9;
transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
return ok;
return GRPC_ERROR_NONE;
}
static int init_goaway_parser(
static grpc_error *init_goaway_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_goaway_parser_begin_frame(
&transport_parsing->goaway_parser,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
grpc_error *err = grpc_chttp2_goaway_parser_begin_frame(
&transport_parsing->goaway_parser, transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags);
if (err != GRPC_ERROR_NONE) return err;
transport_parsing->parser = grpc_chttp2_goaway_parser_parse;
transport_parsing->parser_data = &transport_parsing->goaway_parser;
return ok;
return GRPC_ERROR_NONE;
}
static int init_settings_frame_parser(
static grpc_error *init_settings_frame_parser(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
int ok;
if (transport_parsing->incoming_stream_id != 0) {
gpr_log(GPR_ERROR, "settings frame received for grpc_chttp2_stream %d",
transport_parsing->incoming_stream_id);
return 0;
return GRPC_ERROR_CREATE("Settings frame received for grpc_chttp2_stream");
}
ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_settings_parser_begin_frame(
&transport_parsing->simple.settings,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags,
transport_parsing->settings);
if (!ok) {
return 0;
grpc_error *err = grpc_chttp2_settings_parser_begin_frame(
&transport_parsing->simple.settings,
transport_parsing->incoming_frame_size,
transport_parsing->incoming_frame_flags, transport_parsing->settings);
if (err != GRPC_ERROR_NONE) {
return err;
}
if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
transport_parsing->settings_ack_received = 1;
@ -901,7 +927,7 @@ static int init_settings_frame_parser(
}
transport_parsing->parser = grpc_chttp2_settings_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.settings;
return ok;
return GRPC_ERROR_NONE;
}
/*
@ -910,34 +936,37 @@ static int is_window_update_legal(int64_t window_update, int64_t window) {
}
*/
static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last) {
static grpc_error *parse_frame_slice(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing =
transport_parsing->incoming_stream;
switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
transport_parsing, stream_parsing, slice,
is_last)) {
case GRPC_CHTTP2_PARSE_OK:
if (stream_parsing) {
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
}
return 1;
case GRPC_CHTTP2_STREAM_ERROR:
grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
if (stream_parsing) {
stream_parsing->saw_rst_stream = 1;
stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
gpr_slice_buffer_add(
&transport_parsing->qbuf,
grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR,
&stream_parsing->stats.outgoing));
}
return 1;
case GRPC_CHTTP2_CONNECTION_ERROR:
return 0;
grpc_error *err = transport_parsing->parser(
exec_ctx, transport_parsing->parser_data, transport_parsing,
stream_parsing, slice, is_last);
if (err == GRPC_ERROR_NONE) {
if (stream_parsing) {
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
stream_parsing);
}
return GRPC_ERROR_NONE;
} else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
if (grpc_http_trace) {
const char *msg = grpc_error_string(err);
gpr_log(GPR_ERROR, "%s", msg);
grpc_error_free_string(msg);
}
grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
if (stream_parsing) {
stream_parsing->forced_close_error = err;
gpr_slice_buffer_add(
&transport_parsing->qbuf,
grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
GRPC_CHTTP2_PROTOCOL_ERROR,
&stream_parsing->stats.outgoing));
} else {
GRPC_ERROR_UNREF(err);
}
}
GPR_UNREACHABLE_CODE(return 0);
return err;
}

@ -187,7 +187,8 @@ void grpc_chttp2_perform_writes(
grpc_endpoint_write(exec_ctx, endpoint, &transport_writing->outbuf,
&transport_writing->done_cb);
} else {
grpc_exec_ctx_enqueue(exec_ctx, &transport_writing->done_cb, true, NULL);
grpc_exec_ctx_sched(exec_ctx, &transport_writing->done_cb, GRPC_ERROR_NONE,
NULL);
}
}
@ -334,25 +335,27 @@ void grpc_chttp2_cleanup_writing(
transport_global, transport_writing, &stream_global, &stream_writing)) {
if (stream_writing->sent_initial_metadata) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_initial_metadata_finished, 1);
exec_ctx, transport_global, stream_global,
&stream_global->send_initial_metadata_finished, GRPC_ERROR_NONE);
}
grpc_transport_move_one_way_stats(&stream_writing->stats,
&stream_global->stats.outgoing);
if (stream_writing->sent_message) {
GPR_ASSERT(stream_writing->send_message == NULL);
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global, &stream_global->send_message_finished, 1);
exec_ctx, transport_global, stream_global,
&stream_global->send_message_finished, GRPC_ERROR_NONE);
stream_writing->sent_message = 0;
}
if (stream_writing->sent_trailing_metadata) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_trailing_metadata_finished, 1);
exec_ctx, transport_global, stream_global,
&stream_global->send_trailing_metadata_finished, GRPC_ERROR_NONE);
}
if (stream_writing->sent_trailing_metadata) {
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global,
!transport_global->is_client, 1);
!transport_global->is_client, 1,
GRPC_ERROR_NONE);
}
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
}

@ -159,11 +159,11 @@ static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx,
static void enqueue_callbacks(grpc_closure *callback_list[]) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
if (callback_list[0]) {
grpc_exec_ctx_enqueue(&exec_ctx, callback_list[0], true, NULL);
grpc_exec_ctx_sched(&exec_ctx, callback_list[0], GRPC_ERROR_NONE, NULL);
callback_list[0] = NULL;
}
if (callback_list[1]) {
grpc_exec_ctx_enqueue(&exec_ctx, callback_list[1], true, NULL);
grpc_exec_ctx_sched(&exec_ctx, callback_list[1], GRPC_ERROR_NONE, NULL);
callback_list[1] = NULL;
}
grpc_exec_ctx_finish(&exec_ctx);

@ -149,6 +149,7 @@ grpc_channel_args *grpc_channel_args_normalize(const grpc_channel_args *a) {
void grpc_channel_args_destroy(grpc_channel_args *a) {
size_t i;
if (!a) return;
for (i = 0; i < a->num_args; i++) {
switch (a->args[i].type) {
case GRPC_ARG_STRING:
@ -212,7 +213,7 @@ static int find_compression_algorithm_states_bitset(const grpc_channel_args *a,
grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
grpc_channel_args **a, grpc_compression_algorithm algorithm, int state) {
int *states_arg;
int *states_arg = NULL;
grpc_channel_args *result = *a;
const int states_arg_found =
find_compression_algorithm_states_bitset(*a, &states_arg);

@ -154,11 +154,11 @@ static void process_send_initial_metadata(
static void continue_send_message(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem);
static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
static void send_done(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
grpc_call_element *elem = elemp;
call_data *calld = elem->call_data;
gpr_slice_buffer_reset_and_unref(&calld->slices);
calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, success);
calld->post_send->cb(exec_ctx, calld->post_send->cb_arg, error);
}
static void finish_send_message(grpc_exec_ctx *exec_ctx,
@ -206,7 +206,7 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
grpc_call_next_op(exec_ctx, elem, &calld->send_op);
}
static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, bool success) {
static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) {
grpc_call_element *elem = elemp;
call_data *calld = elem->call_data;
gpr_slice_buffer_add(&calld->slices, calld->incoming_slice);

@ -101,7 +101,8 @@ static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
return md;
}
static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_error *error) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
client_recv_filter_args a;
@ -109,7 +110,7 @@ static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
a.exec_ctx = exec_ctx;
grpc_metadata_batch_filter(calld->recv_initial_metadata, client_recv_filter,
&a);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error);
}
static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {

@ -142,10 +142,11 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
}
}
static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_error *err) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
if (success) {
if (err == GRPC_ERROR_NONE) {
server_filter_args a;
a.elem = elem;
a.exec_ctx = exec_ctx;
@ -157,27 +158,35 @@ static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
calld->seen_path && calld->seen_authority) {
/* do nothing */
} else {
err = GRPC_ERROR_CREATE("Bad incoming HTTP headers");
if (!calld->seen_path) {
gpr_log(GPR_ERROR, "Missing :path header");
err = grpc_error_add_child(err,
GRPC_ERROR_CREATE("Missing :path header"));
}
if (!calld->seen_authority) {
gpr_log(GPR_ERROR, "Missing :authority header");
err = grpc_error_add_child(
err, GRPC_ERROR_CREATE("Missing :authority header"));
}
if (!calld->seen_method) {
gpr_log(GPR_ERROR, "Missing :method header");
err = grpc_error_add_child(err,
GRPC_ERROR_CREATE("Missing :method header"));
}
if (!calld->seen_scheme) {
gpr_log(GPR_ERROR, "Missing :scheme header");
err = grpc_error_add_child(err,
GRPC_ERROR_CREATE("Missing :scheme header"));
}
if (!calld->seen_te_trailers) {
gpr_log(GPR_ERROR, "Missing te trailers header");
err = grpc_error_add_child(
err, GRPC_ERROR_CREATE("Missing te: trailers header"));
}
/* Error this call out */
success = 0;
grpc_call_element_send_cancel(exec_ctx, elem);
}
} else {
GRPC_ERROR_REF(err);
}
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, err);
GRPC_ERROR_UNREF(err);
}
static void hs_mutate_op(grpc_call_element *elem,

@ -39,12 +39,14 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/lib/http/format_request.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/support/string.h"
@ -59,8 +61,7 @@ typedef struct {
gpr_timespec deadline;
int have_read_byte;
const grpc_httpcli_handshaker *handshaker;
grpc_httpcli_response_cb on_response;
void *user_data;
grpc_closure *on_done;
grpc_httpcli_context *context;
grpc_polling_entity *pollent;
grpc_iomgr_object iomgr_obj;
@ -69,6 +70,7 @@ typedef struct {
grpc_closure on_read;
grpc_closure done_write;
grpc_closure connected;
grpc_error *overall_error;
} internal_request;
static grpc_httpcli_get_override g_get_override = NULL;
@ -76,6 +78,7 @@ static grpc_httpcli_post_override g_post_override = NULL;
static void plaintext_handshake(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint, const char *host,
gpr_timespec deadline,
void (*on_done)(grpc_exec_ctx *exec_ctx,
void *arg,
grpc_endpoint *endpoint)) {
@ -93,14 +96,14 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
grpc_pollset_set_destroy(context->pollset_set);
}
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
grpc_error *due_to_error);
static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
int success) {
grpc_error *error) {
grpc_polling_entity_del_from_pollset_set(exec_ctx, req->pollent,
req->context->pollset_set);
req->on_response(exec_ctx, req->user_data,
success ? &req->parser.http.response : NULL);
grpc_exec_ctx_sched(exec_ctx, req->on_done, error, NULL);
grpc_http_parser_destroy(&req->parser);
if (req->addresses != NULL) {
grpc_resolved_addresses_destroy(req->addresses);
@ -114,39 +117,49 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
grpc_iomgr_unregister_object(&req->iomgr_obj);
gpr_slice_buffer_destroy(&req->incoming);
gpr_slice_buffer_destroy(&req->outgoing);
GRPC_ERROR_UNREF(req->overall_error);
gpr_free(req);
}
static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success);
static void append_error(internal_request *req, grpc_error *error) {
if (req->overall_error == GRPC_ERROR_NONE) {
req->overall_error = GRPC_ERROR_CREATE("Failed HTTP/1 client request");
}
grpc_resolved_address *addr = &req->addresses->addrs[req->next_address - 1];
char *addr_text = grpc_sockaddr_to_uri((struct sockaddr *)addr->addr);
req->overall_error = grpc_error_add_child(
req->overall_error,
grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, addr_text));
gpr_free(addr_text);
}
static void do_read(grpc_exec_ctx *exec_ctx, internal_request *req) {
grpc_endpoint_read(exec_ctx, req->ep, &req->incoming, &req->on_read);
}
static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
static void on_read(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_error *error) {
internal_request *req = user_data;
size_t i;
for (i = 0; i < req->incoming.count; i++) {
if (GPR_SLICE_LENGTH(req->incoming.slices[i])) {
req->have_read_byte = 1;
if (!grpc_http_parser_parse(&req->parser, req->incoming.slices[i])) {
finish(exec_ctx, req, 0);
grpc_error *err =
grpc_http_parser_parse(&req->parser, req->incoming.slices[i]);
if (err != GRPC_ERROR_NONE) {
finish(exec_ctx, req, err);
return;
}
}
}
if (success) {
if (error == GRPC_ERROR_NONE) {
do_read(exec_ctx, req);
} else if (!req->have_read_byte) {
next_address(exec_ctx, req);
next_address(exec_ctx, req, GRPC_ERROR_REF(error));
} else {
int parse_success = grpc_http_parser_eof(&req->parser);
if (parse_success && (req->parser.type != GRPC_HTTP_RESPONSE)) {
parse_success = 0;
}
finish(exec_ctx, req, parse_success);
finish(exec_ctx, req, grpc_http_parser_eof(&req->parser));
}
}
@ -154,12 +167,12 @@ static void on_written(grpc_exec_ctx *exec_ctx, internal_request *req) {
do_read(exec_ctx, req);
}
static void done_write(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
internal_request *req = arg;
if (success) {
if (error == GRPC_ERROR_NONE) {
on_written(exec_ctx, req);
} else {
next_address(exec_ctx, req);
next_address(exec_ctx, req, GRPC_ERROR_REF(error));
}
}
@ -174,7 +187,8 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
internal_request *req = arg;
if (!ep) {
next_address(exec_ctx, req);
next_address(exec_ctx, req,
GRPC_ERROR_CREATE("Unexplained handshake failure"));
return;
}
@ -182,23 +196,30 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
start_write(exec_ctx, req);
}
static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void on_connected(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
internal_request *req = arg;
if (!req->ep) {
next_address(exec_ctx, req);
next_address(exec_ctx, req, GRPC_ERROR_REF(error));
return;
}
req->handshaker->handshake(
exec_ctx, req, req->ep,
req->ssl_host_override ? req->ssl_host_override : req->host,
on_handshake_done);
req->deadline, on_handshake_done);
}
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
grpc_error *error) {
grpc_resolved_address *addr;
if (error != GRPC_ERROR_NONE) {
append_error(req, error);
}
if (req->next_address == req->addresses->naddrs) {
finish(exec_ctx, req, 0);
finish(exec_ctx, req,
GRPC_ERROR_CREATE_REFERENCING("Failed HTTP requests to all targets",
&req->overall_error, 1));
return;
}
addr = &req->addresses->addrs[req->next_address++];
@ -208,34 +229,34 @@ static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
(struct sockaddr *)&addr->addr, addr->len, req->deadline);
}
static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
internal_request *req = arg;
if (!addresses) {
finish(exec_ctx, req, 0);
if (error != GRPC_ERROR_NONE) {
finish(exec_ctx, req, error);
return;
}
req->addresses = addresses;
req->next_address = 0;
next_address(exec_ctx, req);
next_address(exec_ctx, req, GRPC_ERROR_NONE);
}
static void internal_request_begin(
grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_polling_entity *pollent, const grpc_httpcli_request *request,
gpr_timespec deadline, grpc_httpcli_response_cb on_response,
void *user_data, const char *name, gpr_slice request_text) {
static void internal_request_begin(grpc_exec_ctx *exec_ctx,
grpc_httpcli_context *context,
grpc_polling_entity *pollent,
const grpc_httpcli_request *request,
gpr_timespec deadline, grpc_closure *on_done,
grpc_httpcli_response *response,
const char *name, gpr_slice request_text) {
internal_request *req = gpr_malloc(sizeof(internal_request));
memset(req, 0, sizeof(*req));
req->request_text = request_text;
grpc_http_parser_init(&req->parser);
req->on_response = on_response;
req->user_data = user_data;
grpc_http_parser_init(&req->parser, GRPC_HTTP_RESPONSE, response);
req->on_done = on_done;
req->deadline = deadline;
req->handshaker =
request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
req->context = context;
req->pollent = pollent;
req->overall_error = GRPC_ERROR_NONE;
grpc_closure_init(&req->on_read, on_read, req);
grpc_closure_init(&req->done_write, done_write, req);
gpr_slice_buffer_init(&req->incoming);
@ -248,22 +269,22 @@ static void internal_request_begin(
grpc_polling_entity_add_to_pollset_set(exec_ctx, req->pollent,
req->context->pollset_set);
grpc_resolve_address(exec_ctx, request->host, req->handshaker->default_port,
on_resolved, req);
grpc_closure_create(on_resolved, req), &req->addresses);
}
void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_polling_entity *pollent,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
gpr_timespec deadline, grpc_closure *on_done,
grpc_httpcli_response *response) {
char *name;
if (g_get_override &&
g_get_override(exec_ctx, request, deadline, on_response, user_data)) {
g_get_override(exec_ctx, request, deadline, on_done, response)) {
return;
}
gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->http.path);
internal_request_begin(exec_ctx, context, pollent, request, deadline,
on_response, user_data, name,
internal_request_begin(exec_ctx, context, pollent, request, deadline, on_done,
response, name,
grpc_httpcli_format_get_request(request));
gpr_free(name);
}
@ -272,18 +293,18 @@ void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_polling_entity *pollent,
const grpc_httpcli_request *request,
const char *body_bytes, size_t body_size,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
gpr_timespec deadline, grpc_closure *on_done,
grpc_httpcli_response *response) {
char *name;
if (g_post_override &&
g_post_override(exec_ctx, request, body_bytes, body_size, deadline,
on_response, user_data)) {
on_done, response)) {
return;
}
gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->http.path);
internal_request_begin(
exec_ctx, context, pollent, request, deadline, on_response, user_data,
name, grpc_httpcli_format_post_request(request, body_bytes, body_size));
exec_ctx, context, pollent, request, deadline, on_done, response, name,
grpc_httpcli_format_post_request(request, body_bytes, body_size));
gpr_free(name);
}

@ -57,7 +57,7 @@ typedef struct grpc_httpcli_context {
typedef struct {
const char *default_port;
void (*handshake)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint,
const char *host,
const char *host, gpr_timespec deadline,
void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint));
} grpc_httpcli_handshaker;
@ -82,11 +82,6 @@ typedef struct grpc_httpcli_request {
/* Expose the parser response type as a httpcli response too */
typedef struct grpc_http_response grpc_httpcli_response;
/* Callback for grpc_httpcli_get and grpc_httpcli_post. */
typedef void (*grpc_httpcli_response_cb)(grpc_exec_ctx *exec_ctx,
void *user_data,
const grpc_http_response *response);
void grpc_httpcli_context_init(grpc_httpcli_context *context);
void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
@ -103,8 +98,8 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_polling_entity *pollent,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data);
gpr_timespec deadline, grpc_closure *on_complete,
grpc_httpcli_response *response);
/* Asynchronously perform a HTTP POST.
'context' specifies the http context under which to do the post
@ -125,19 +120,19 @@ void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_polling_entity *pollent,
const grpc_httpcli_request *request,
const char *body_bytes, size_t body_size,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data);
gpr_timespec deadline, grpc_closure *on_complete,
grpc_httpcli_response *response);
/* override functions return 1 if they handled the request, 0 otherwise */
typedef int (*grpc_httpcli_get_override)(grpc_exec_ctx *exec_ctx,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data);
grpc_closure *on_complete,
grpc_httpcli_response *response);
typedef int (*grpc_httpcli_post_override)(
grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
const char *body_bytes, size_t body_size, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data);
grpc_closure *on_complete, grpc_httpcli_response *response);
void grpc_httpcli_set_override(grpc_httpcli_get_override get,
grpc_httpcli_post_override post);

@ -61,6 +61,7 @@ static void httpcli_ssl_destroy(grpc_security_connector *sc) {
static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
grpc_endpoint *nonsecure_endpoint,
gpr_timespec deadline,
grpc_security_handshake_done_cb cb,
void *user_data) {
grpc_httpcli_ssl_channel_security_connector *c =
@ -79,7 +80,7 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
} else {
grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
nonsecure_endpoint, cb, user_data);
nonsecure_endpoint, deadline, cb, user_data);
}
}
@ -163,6 +164,7 @@ static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *tcp, const char *host,
gpr_timespec deadline,
void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint)) {
grpc_channel_security_connector *sc = NULL;
@ -181,7 +183,7 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
pem_root_certs, pem_root_certs_size, host, &sc) ==
GRPC_SECURITY_OK);
grpc_channel_security_connector_do_handshake(
exec_ctx, sc, tcp, on_secure_transport_setup_done, c);
exec_ctx, sc, tcp, deadline, on_secure_transport_setup_done, c);
GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
}

@ -48,37 +48,38 @@ static char *buf2str(void *buffer, size_t length) {
return out;
}
static int handle_response_line(grpc_http_parser *parser) {
static grpc_error *handle_response_line(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
if (cur == end || *cur++ != 'H') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'P') goto error;
if (cur == end || *cur++ != '/') goto error;
if (cur == end || *cur++ != '1') goto error;
if (cur == end || *cur++ != '.') goto error;
if (cur == end || *cur < '0' || *cur++ > '1') goto error;
if (cur == end || *cur++ != ' ') goto error;
if (cur == end || *cur < '1' || *cur++ > '9') goto error;
if (cur == end || *cur < '0' || *cur++ > '9') goto error;
if (cur == end || *cur < '0' || *cur++ > '9') goto error;
parser->http.response.status =
if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
if (cur == end || *cur++ != '1') return GRPC_ERROR_CREATE("Expected '1'");
if (cur == end || *cur++ != '.') return GRPC_ERROR_CREATE("Expected '.'");
if (cur == end || *cur < '0' || *cur++ > '1') {
return GRPC_ERROR_CREATE("Expected HTTP/1.0 or HTTP/1.1");
}
if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
if (cur == end || *cur < '1' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
if (cur == end || *cur < '0' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
if (cur == end || *cur < '0' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
parser->http.response->status =
(cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0');
if (cur == end || *cur++ != ' ') goto error;
if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
/* we don't really care about the status code message */
return 1;
error:
if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing response line");
return 0;
return GRPC_ERROR_NONE;
}
static int handle_request_line(grpc_http_parser *parser) {
static grpc_error *handle_request_line(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
@ -87,84 +88,81 @@ static int handle_request_line(grpc_http_parser *parser) {
while (cur != end && *cur++ != ' ')
;
if (cur == end) goto error;
parser->http.request.method = buf2str(beg, (size_t)(cur - beg - 1));
if (cur == end) return GRPC_ERROR_CREATE("No method on HTTP request line");
parser->http.request->method = buf2str(beg, (size_t)(cur - beg - 1));
beg = cur;
while (cur != end && *cur++ != ' ')
;
if (cur == end) goto error;
parser->http.request.path = buf2str(beg, (size_t)(cur - beg - 1));
if (cur == end || *cur++ != 'H') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'P') goto error;
if (cur == end || *cur++ != '/') goto error;
if (cur == end) return GRPC_ERROR_CREATE("No path on HTTP request line");
parser->http.request->path = buf2str(beg, (size_t)(cur - beg - 1));
if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
vers_major = (uint8_t)(*cur++ - '1' + 1);
++cur;
if (cur == end) goto error;
if (cur == end)
return GRPC_ERROR_CREATE("End of line in HTTP version string");
vers_minor = (uint8_t)(*cur++ - '1' + 1);
if (vers_major == 1) {
if (vers_minor == 0) {
parser->http.request.version = GRPC_HTTP_HTTP10;
parser->http.request->version = GRPC_HTTP_HTTP10;
} else if (vers_minor == 1) {
parser->http.request.version = GRPC_HTTP_HTTP11;
parser->http.request->version = GRPC_HTTP_HTTP11;
} else {
goto error;
return GRPC_ERROR_CREATE(
"Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
} else if (vers_major == 2) {
if (vers_minor == 0) {
parser->http.request.version = GRPC_HTTP_HTTP20;
parser->http.request->version = GRPC_HTTP_HTTP20;
} else {
goto error;
return GRPC_ERROR_CREATE(
"Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
} else {
goto error;
return GRPC_ERROR_CREATE("Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
return 1;
error:
if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing request line");
return 0;
return GRPC_ERROR_NONE;
}
static int handle_first_line(grpc_http_parser *parser) {
if (parser->cur_line[0] == 'H') {
parser->type = GRPC_HTTP_RESPONSE;
return handle_response_line(parser);
} else {
parser->type = GRPC_HTTP_REQUEST;
return handle_request_line(parser);
static grpc_error *handle_first_line(grpc_http_parser *parser) {
switch (parser->type) {
case GRPC_HTTP_REQUEST:
return handle_request_line(parser);
case GRPC_HTTP_RESPONSE:
return handle_response_line(parser);
}
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
static int add_header(grpc_http_parser *parser) {
static grpc_error *add_header(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
size_t *hdr_count = NULL;
grpc_http_header **hdrs = NULL;
grpc_http_header hdr = {NULL, NULL};
grpc_error *error = GRPC_ERROR_NONE;
GPR_ASSERT(cur != end);
if (*cur == ' ' || *cur == '\t') {
if (grpc_http1_trace)
gpr_log(GPR_ERROR, "Continued header lines not supported yet");
goto error;
error = GRPC_ERROR_CREATE("Continued header lines not supported yet");
goto done;
}
while (cur != end && *cur != ':') {
cur++;
}
if (cur == end) {
if (grpc_http1_trace) {
gpr_log(GPR_ERROR, "Didn't find ':' in header string");
}
goto error;
error = GRPC_ERROR_CREATE("Didn't find ':' in header string");
goto done;
}
GPR_ASSERT(cur >= beg);
hdr.key = buf2str(beg, (size_t)(cur - beg));
@ -176,14 +174,15 @@ static int add_header(grpc_http_parser *parser) {
GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length);
hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length);
if (parser->type == GRPC_HTTP_RESPONSE) {
hdr_count = &parser->http.response.hdr_count;
hdrs = &parser->http.response.hdrs;
} else if (parser->type == GRPC_HTTP_REQUEST) {
hdr_count = &parser->http.request.hdr_count;
hdrs = &parser->http.request.hdrs;
} else {
return 0;
switch (parser->type) {
case GRPC_HTTP_RESPONSE:
hdr_count = &parser->http.response->hdr_count;
hdrs = &parser->http.response->hdrs;
break;
case GRPC_HTTP_REQUEST:
hdr_count = &parser->http.request->hdr_count;
hdrs = &parser->http.request->hdrs;
break;
}
if (*hdr_count == parser->hdr_capacity) {
@ -192,20 +191,21 @@ static int add_header(grpc_http_parser *parser) {
*hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs));
}
(*hdrs)[(*hdr_count)++] = hdr;
return 1;
error:
gpr_free(hdr.key);
gpr_free(hdr.value);
return 0;
done:
if (error != GRPC_ERROR_NONE) {
gpr_free(hdr.key);
gpr_free(hdr.value);
}
return error;
}
static int finish_line(grpc_http_parser *parser) {
static grpc_error *finish_line(grpc_http_parser *parser) {
grpc_error *err;
switch (parser->state) {
case GRPC_HTTP_FIRST_LINE:
if (!handle_first_line(parser)) {
return 0;
}
err = handle_first_line(parser);
if (err != GRPC_ERROR_NONE) return err;
parser->state = GRPC_HTTP_HEADERS;
break;
case GRPC_HTTP_HEADERS:
@ -213,30 +213,31 @@ static int finish_line(grpc_http_parser *parser) {
parser->state = GRPC_HTTP_BODY;
break;
}
if (!add_header(parser)) {
return 0;
err = add_header(parser);
if (err != GRPC_ERROR_NONE) {
return err;
}
break;
case GRPC_HTTP_BODY:
GPR_UNREACHABLE_CODE(return 0);
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
parser->cur_line_length = 0;
return 1;
return GRPC_ERROR_NONE;
}
static int addbyte_body(grpc_http_parser *parser, uint8_t byte) {
static grpc_error *addbyte_body(grpc_http_parser *parser, uint8_t byte) {
size_t *body_length = NULL;
char **body = NULL;
if (parser->type == GRPC_HTTP_RESPONSE) {
body_length = &parser->http.response.body_length;
body = &parser->http.response.body;
body_length = &parser->http.response->body_length;
body = &parser->http.response->body;
} else if (parser->type == GRPC_HTTP_REQUEST) {
body_length = &parser->http.request.body_length;
body = &parser->http.request.body;
body_length = &parser->http.request->body_length;
body = &parser->http.request->body;
} else {
return 0;
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
if (*body_length == parser->body_capacity) {
@ -246,34 +247,34 @@ static int addbyte_body(grpc_http_parser *parser, uint8_t byte) {
(*body)[*body_length] = (char)byte;
(*body_length)++;
return 1;
return GRPC_ERROR_NONE;
}
static int check_line(grpc_http_parser *parser) {
static bool check_line(grpc_http_parser *parser) {
if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\r' &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
return 1;
return true;
}
// HTTP request with \n\r line termiantors.
else if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\n' &&
parser->cur_line[parser->cur_line_length - 1] == '\r') {
return 1;
return true;
}
// HTTP request with only \n line terminators.
else if (parser->cur_line_length >= 1 &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
parser->cur_line_end_length = 1;
return 1;
return true;
}
return 0;
return false;
}
static int addbyte(grpc_http_parser *parser, uint8_t byte) {
static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) {
switch (parser->state) {
case GRPC_HTTP_FIRST_LINE:
case GRPC_HTTP_HEADERS:
@ -288,7 +289,7 @@ static int addbyte(grpc_http_parser *parser, uint8_t byte) {
if (check_line(parser)) {
return finish_line(parser);
} else {
return 1;
return GRPC_ERROR_NONE;
}
GPR_UNREACHABLE_CODE(return 0);
case GRPC_HTTP_BODY:
@ -297,46 +298,53 @@ static int addbyte(grpc_http_parser *parser, uint8_t byte) {
GPR_UNREACHABLE_CODE(return 0);
}
void grpc_http_parser_init(grpc_http_parser *parser) {
void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
void *request_or_response) {
memset(parser, 0, sizeof(*parser));
parser->state = GRPC_HTTP_FIRST_LINE;
parser->type = GRPC_HTTP_UNKNOWN;
parser->type = type;
parser->http.request_or_response = request_or_response;
parser->cur_line_end_length = 2;
}
void grpc_http_parser_destroy(grpc_http_parser *parser) {
void grpc_http_parser_destroy(grpc_http_parser *parser) {}
void grpc_http_request_destroy(grpc_http_request *request) {
size_t i;
if (parser->type == GRPC_HTTP_RESPONSE) {
gpr_free(parser->http.response.body);
for (i = 0; i < parser->http.response.hdr_count; i++) {
gpr_free(parser->http.response.hdrs[i].key);
gpr_free(parser->http.response.hdrs[i].value);
}
gpr_free(parser->http.response.hdrs);
} else if (parser->type == GRPC_HTTP_REQUEST) {
gpr_free(parser->http.request.body);
for (i = 0; i < parser->http.request.hdr_count; i++) {
gpr_free(parser->http.request.hdrs[i].key);
gpr_free(parser->http.request.hdrs[i].value);
}
gpr_free(parser->http.request.hdrs);
gpr_free(parser->http.request.method);
gpr_free(parser->http.request.path);
gpr_free(request->body);
for (i = 0; i < request->hdr_count; i++) {
gpr_free(request->hdrs[i].key);
gpr_free(request->hdrs[i].value);
}
gpr_free(request->hdrs);
gpr_free(request->method);
gpr_free(request->path);
}
int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
void grpc_http_response_destroy(grpc_http_response *response) {
size_t i;
gpr_free(response->body);
for (i = 0; i < response->hdr_count; i++) {
gpr_free(response->hdrs[i].key);
gpr_free(response->hdrs[i].value);
}
gpr_free(response->hdrs);
}
grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
size_t i;
for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) {
if (!addbyte(parser, GPR_SLICE_START_PTR(slice)[i])) {
return 0;
}
grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i]);
if (err != GRPC_ERROR_NONE) return err;
}
return 1;
return GRPC_ERROR_NONE;
}
int grpc_http_parser_eof(grpc_http_parser *parser) {
return parser->state == GRPC_HTTP_BODY;
grpc_error *grpc_http_parser_eof(grpc_http_parser *parser) {
if (parser->state != GRPC_HTTP_BODY) {
return GRPC_ERROR_CREATE("Did not finish headers");
}
return GRPC_ERROR_NONE;
}

@ -0,0 +1,357 @@
/*
*
* 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.
*
*/
#include "src/core/lib/http/parser.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
int grpc_http1_trace = 0;
static char *buf2str(void *buffer, size_t length) {
char *out = gpr_malloc(length + 1);
memcpy(out, buffer, length);
out[length] = 0;
return out;
}
static grpc_error *handle_response_line(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
if (cur == end || *cur++ != '1') return GRPC_ERROR_CREATE("Expected '1'");
if (cur == end || *cur++ != '.') return GRPC_ERROR_CREATE("Expected '.'");
if (cur == end || *cur < '0' || *cur++ > '1') {
return GRPC_ERROR_CREATE("Expected HTTP/1.0 or HTTP/1.1");
}
if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
if (cur == end || *cur < '1' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
if (cur == end || *cur < '0' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
if (cur == end || *cur < '0' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
parser->http.response->status =
(cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0');
if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
/* we don't really care about the status code message */
return GRPC_ERROR_NONE;
}
static grpc_error *handle_request_line(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
uint8_t vers_major = 0;
uint8_t vers_minor = 0;
while (cur != end && *cur++ != ' ')
;
if (cur == end) return GRPC_ERROR_CREATE("No method on HTTP request line");
parser->http.request->method = buf2str(beg, (size_t)(cur - beg - 1));
beg = cur;
while (cur != end && *cur++ != ' ')
;
if (cur == end) return GRPC_ERROR_CREATE("No path on HTTP request line");
parser->http.request->path = buf2str(beg, (size_t)(cur - beg - 1));
if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
vers_major = (uint8_t)(*cur++ - '1' + 1);
++cur;
if (cur == end)
return GRPC_ERROR_CREATE("End of line in HTTP version string");
vers_minor = (uint8_t)(*cur++ - '1' + 1);
if (vers_major == 1) {
if (vers_minor == 0) {
parser->http.request->version = GRPC_HTTP_HTTP10;
} else if (vers_minor == 1) {
parser->http.request->version = GRPC_HTTP_HTTP11;
} else {
return GRPC_ERROR_CREATE(
"Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
} else if (vers_major == 2) {
if (vers_minor == 0) {
parser->http.request->version = GRPC_HTTP_HTTP20;
} else {
return GRPC_ERROR_CREATE(
"Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
} else {
return GRPC_ERROR_CREATE("Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
return GRPC_ERROR_NONE;
}
static grpc_error *handle_first_line(grpc_http_parser *parser) {
switch (parser->type) {
case GRPC_HTTP_REQUEST:
return handle_request_line(parser);
case GRPC_HTTP_RESPONSE:
return handle_response_line(parser);
}
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
static grpc_error *add_header(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
size_t *hdr_count = NULL;
grpc_http_header **hdrs = NULL;
grpc_http_header hdr = {NULL, NULL};
grpc_error *error = GRPC_ERROR_NONE;
GPR_ASSERT(cur != end);
if (*cur == ' ' || *cur == '\t') {
error = GRPC_ERROR_CREATE("Continued header lines not supported yet");
goto done;
}
while (cur != end && *cur != ':') {
cur++;
}
if (cur == end) {
<<<<<<< HEAD
error = GRPC_ERROR_CREATE("Didn't find ':' in header string");
goto done;
=======
if (grpc_http1_trace) {
gpr_log(GPR_ERROR, "Didn't find ':' in header string");
}
goto error;
>>>>>>> a709afe241d8b264a1c326315f757b4a8d330207
}
GPR_ASSERT(cur >= beg);
hdr.key = buf2str(beg, (size_t)(cur - beg));
cur++; /* skip : */
while (cur != end && (*cur == ' ' || *cur == '\t')) {
cur++;
}
GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length);
hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length);
switch (parser->type) {
case GRPC_HTTP_RESPONSE:
hdr_count = &parser->http.response->hdr_count;
hdrs = &parser->http.response->hdrs;
break;
case GRPC_HTTP_REQUEST:
hdr_count = &parser->http.request->hdr_count;
hdrs = &parser->http.request->hdrs;
break;
}
if (*hdr_count == parser->hdr_capacity) {
parser->hdr_capacity =
GPR_MAX(parser->hdr_capacity + 1, parser->hdr_capacity * 3 / 2);
*hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs));
}
(*hdrs)[(*hdr_count)++] = hdr;
done:
if (error != GRPC_ERROR_NONE) {
gpr_free(hdr.key);
gpr_free(hdr.value);
}
return error;
}
static grpc_error *finish_line(grpc_http_parser *parser) {
grpc_error *err;
switch (parser->state) {
case GRPC_HTTP_FIRST_LINE:
err = handle_first_line(parser);
if (err != GRPC_ERROR_NONE) return err;
parser->state = GRPC_HTTP_HEADERS;
break;
case GRPC_HTTP_HEADERS:
if (parser->cur_line_length == parser->cur_line_end_length) {
parser->state = GRPC_HTTP_BODY;
break;
}
err = add_header(parser);
if (err != GRPC_ERROR_NONE) {
return err;
}
break;
case GRPC_HTTP_BODY:
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
parser->cur_line_length = 0;
return GRPC_ERROR_NONE;
}
static grpc_error *addbyte_body(grpc_http_parser *parser, uint8_t byte) {
size_t *body_length = NULL;
char **body = NULL;
if (parser->type == GRPC_HTTP_RESPONSE) {
body_length = &parser->http.response->body_length;
body = &parser->http.response->body;
} else if (parser->type == GRPC_HTTP_REQUEST) {
body_length = &parser->http.request->body_length;
body = &parser->http.request->body;
} else {
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
if (*body_length == parser->body_capacity) {
parser->body_capacity = GPR_MAX(8, parser->body_capacity * 3 / 2);
*body = gpr_realloc((void *)*body, parser->body_capacity);
}
(*body)[*body_length] = (char)byte;
(*body_length)++;
return GRPC_ERROR_NONE;
}
static bool check_line(grpc_http_parser *parser) {
if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\r' &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
return true;
}
// HTTP request with \n\r line termiantors.
else if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\n' &&
parser->cur_line[parser->cur_line_length - 1] == '\r') {
return true;
}
// HTTP request with only \n line terminators.
else if (parser->cur_line_length >= 1 &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
parser->cur_line_end_length = 1;
return true;
}
return false;
}
static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) {
switch (parser->state) {
case GRPC_HTTP_FIRST_LINE:
case GRPC_HTTP_HEADERS:
if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) {
if (grpc_http1_trace)
gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded",
GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
return 0;
}
parser->cur_line[parser->cur_line_length] = byte;
parser->cur_line_length++;
if (check_line(parser)) {
return finish_line(parser);
} else {
return GRPC_ERROR_NONE;
}
GPR_UNREACHABLE_CODE(return 0);
case GRPC_HTTP_BODY:
return addbyte_body(parser, byte);
}
GPR_UNREACHABLE_CODE(return 0);
}
void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
void *request_or_response) {
memset(parser, 0, sizeof(*parser));
parser->state = GRPC_HTTP_FIRST_LINE;
parser->type = type;
parser->http.request_or_response = request_or_response;
parser->cur_line_end_length = 2;
}
void grpc_http_parser_destroy(grpc_http_parser *parser) {}
void grpc_http_request_destroy(grpc_http_request *request) {
size_t i;
gpr_free(request->body);
for (i = 0; i < request->hdr_count; i++) {
gpr_free(request->hdrs[i].key);
gpr_free(request->hdrs[i].value);
}
gpr_free(request->hdrs);
gpr_free(request->method);
gpr_free(request->path);
}
void grpc_http_response_destroy(grpc_http_response *response) {
size_t i;
gpr_free(response->body);
for (i = 0; i < response->hdr_count; i++) {
gpr_free(response->hdrs[i].key);
gpr_free(response->hdrs[i].value);
}
gpr_free(response->hdrs);
}
grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
size_t i;
for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) {
grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i]);
if (err != GRPC_ERROR_NONE) return err;
}
return GRPC_ERROR_NONE;
}
grpc_error *grpc_http_parser_eof(grpc_http_parser *parser) {
if (parser->state != GRPC_HTTP_BODY) {
return GRPC_ERROR_CREATE("Did not finish headers");
}
return GRPC_ERROR_NONE;
}

@ -36,6 +36,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include "src/core/lib/iomgr/error.h"
/* Maximum length of a header string of the form 'Key: Value\r\n' */
#define GRPC_HTTP_PARSER_MAX_HEADER_LENGTH 4096
@ -61,7 +62,6 @@ typedef enum {
typedef enum {
GRPC_HTTP_RESPONSE,
GRPC_HTTP_REQUEST,
GRPC_HTTP_UNKNOWN
} grpc_http_type;
/* A request */
@ -97,8 +97,9 @@ typedef struct {
grpc_http_type type;
union {
grpc_http_response response;
grpc_http_request request;
grpc_http_response *response;
grpc_http_request *request;
void *request_or_response;
} http;
size_t body_capacity;
size_t hdr_capacity;
@ -108,11 +109,15 @@ typedef struct {
size_t cur_line_end_length;
} grpc_http_parser;
void grpc_http_parser_init(grpc_http_parser *parser);
void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
void *request_or_response);
void grpc_http_parser_destroy(grpc_http_parser *parser);
int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
int grpc_http_parser_eof(grpc_http_parser *parser);
grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
grpc_error *grpc_http_parser_eof(grpc_http_parser *parser);
void grpc_http_request_destroy(grpc_http_request *request);
void grpc_http_response_destroy(grpc_http_response *response);
extern int grpc_http1_trace;

@ -39,25 +39,32 @@ void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg) {
closure->cb = cb;
closure->cb_arg = cb_arg;
closure->final_data = 0;
}
void grpc_closure_list_add(grpc_closure_list *closure_list,
grpc_closure *closure, bool success) {
if (closure == NULL) return;
closure->final_data = (success != 0);
void grpc_closure_list_append(grpc_closure_list *closure_list,
grpc_closure *closure, grpc_error *error) {
if (closure == NULL) {
GRPC_ERROR_UNREF(error);
return;
}
closure->error = error;
closure->next_data.next = NULL;
if (closure_list->head == NULL) {
closure_list->head = closure;
} else {
closure_list->tail->final_data |= (uintptr_t)closure;
closure_list->tail->next_data.next = closure;
}
closure_list->tail = closure;
}
void grpc_closure_list_fail_all(grpc_closure_list *list) {
for (grpc_closure *c = list->head; c != NULL; c = grpc_closure_next(c)) {
c->final_data &= ~(uintptr_t)1;
void grpc_closure_list_fail_all(grpc_closure_list *list,
grpc_error *forced_failure) {
for (grpc_closure *c = list->head; c != NULL; c = c->next_data.next) {
if (c->error == GRPC_ERROR_NONE) {
c->error = GRPC_ERROR_REF(forced_failure);
}
}
GRPC_ERROR_UNREF(forced_failure);
}
bool grpc_closure_list_empty(grpc_closure_list closure_list) {
@ -71,7 +78,7 @@ void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst) {
if (dst->head == NULL) {
*dst = *src;
} else {
dst->tail->final_data |= (uintptr_t)src->head;
dst->tail->next_data.next = src->head;
dst->tail = src->tail;
}
src->head = src->tail = NULL;
@ -83,12 +90,13 @@ typedef struct {
grpc_closure wrapper;
} wrapped_closure;
static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
wrapped_closure *wc = arg;
grpc_iomgr_cb_func cb = wc->cb;
void *cb_arg = wc->cb_arg;
gpr_free(wc);
cb(exec_ctx, cb_arg, success);
cb(exec_ctx, cb_arg, error);
}
grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg) {
@ -98,7 +106,3 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg) {
grpc_closure_init(&wc->wrapper, closure_wrapper, wc);
return &wc->wrapper;
}
grpc_closure *grpc_closure_next(grpc_closure *closure) {
return (grpc_closure *)(closure->final_data & ~(uintptr_t)1);
}

@ -36,6 +36,7 @@
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include "src/core/lib/iomgr/error.h"
struct grpc_closure;
typedef struct grpc_closure grpc_closure;
@ -52,10 +53,10 @@ typedef struct grpc_closure_list {
/** gRPC Callback definition.
*
* \param arg Arbitrary input.
* \param success An indication on the state of the iomgr. On false, cleanup
* actions should be taken (eg, shutdown). */
* \param error GRPC_ERROR_NONE if no error occurred, otherwise some grpc_error
* describing what went wrong */
typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg,
bool success);
grpc_error *error);
/** A closure over a grpc_iomgr_cb_func. */
struct grpc_closure {
@ -65,10 +66,15 @@ struct grpc_closure {
/** Arguments to be passed to "cb". */
void *cb_arg;
/** Once enqueued, contains in the lower bit the success of the closure,
and in the upper bits the pointer to the next closure in the list.
Before enqueing for execution, this is usable for scratch data. */
uintptr_t final_data;
/** Once queued, the result of the closure. Before then: scratch space */
grpc_error *error;
/** Once queued, next indicates the next queued closure; before then, scratch
* space */
union {
grpc_closure *next;
uintptr_t scratch;
} next_data;
};
/** Initializes \a closure with \a cb and \a cb_arg. */
@ -81,13 +87,14 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg);
#define GRPC_CLOSURE_LIST_INIT \
{ NULL, NULL }
/** add \a closure to the end of \a list and set \a closure's success to \a
* success */
void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure,
bool success);
/** add \a closure to the end of \a list
and set \a closure's result to \a error */
void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
grpc_error *error);
/** force all success bits in \a list to false */
void grpc_closure_list_fail_all(grpc_closure_list *list);
void grpc_closure_list_fail_all(grpc_closure_list *list,
grpc_error *forced_failure);
/** append all closures from \a src to \a dst and empty \a src. */
void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst);
@ -95,7 +102,4 @@ void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst);
/** return whether \a list is empty. */
bool grpc_closure_list_empty(grpc_closure_list list);
/** return the next pointer for a queued closure list */
grpc_closure *grpc_closure_next(grpc_closure *closure);
#endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */

@ -82,7 +82,7 @@ char *grpc_endpoint_get_peer(grpc_endpoint *ep);
void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *slices, grpc_closure *cb);
/* Causes any pending read/write callbacks to run immediately with
/* Causes any pending and future read/write callbacks to run immediately with
success==0 */
void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);

@ -58,8 +58,8 @@ static void create_sockets(int sv[2]) {
GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
flags = fcntl(sv[1], F_GETFL, 0);
GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]));
GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]));
GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == GRPC_ERROR_NONE);
GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == GRPC_ERROR_NONE);
}
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,

@ -0,0 +1,535 @@
/*
*
* 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.
*
*/
#include "src/core/lib/iomgr/error.h"
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/avl.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#ifdef GPR_WINDOWS
#include <grpc/support/log_windows.h>
#endif
static void destroy_integer(void *key) {}
static void *copy_integer(void *key) { return key; }
static long compare_integers(void *key1, void *key2) {
return GPR_ICMP((uintptr_t)key1, (uintptr_t)key2);
}
static void destroy_string(void *str) { gpr_free(str); }
static void *copy_string(void *str) { return gpr_strdup(str); }
static void destroy_err(void *err) { GRPC_ERROR_UNREF(err); }
static void *copy_err(void *err) { return GRPC_ERROR_REF(err); }
static void destroy_time(void *tm) { gpr_free(tm); }
static gpr_timespec *box_time(gpr_timespec tm) {
gpr_timespec *out = gpr_malloc(sizeof(*out));
*out = tm;
return out;
}
static void *copy_time(void *tm) { return box_time(*(gpr_timespec *)tm); }
static const gpr_avl_vtable avl_vtable_ints = {destroy_integer, copy_integer,
compare_integers,
destroy_integer, copy_integer};
static const gpr_avl_vtable avl_vtable_strs = {destroy_integer, copy_integer,
compare_integers, destroy_string,
copy_string};
static const gpr_avl_vtable avl_vtable_times = {
destroy_integer, copy_integer, compare_integers, destroy_time, copy_time};
static const gpr_avl_vtable avl_vtable_errs = {
destroy_integer, copy_integer, compare_integers, destroy_err, copy_err};
static const char *error_int_name(grpc_error_ints key) {
switch (key) {
case GRPC_ERROR_INT_ERRNO:
return "errno";
case GRPC_ERROR_INT_FILE_LINE:
return "file_line";
case GRPC_ERROR_INT_STREAM_ID:
return "stream_id";
case GRPC_ERROR_INT_GRPC_STATUS:
return "grpc_status";
case GRPC_ERROR_INT_OFFSET:
return "offset";
case GRPC_ERROR_INT_INDEX:
return "index";
case GRPC_ERROR_INT_SIZE:
return "size";
case GRPC_ERROR_INT_HTTP2_ERROR:
return "http2_error";
case GRPC_ERROR_INT_TSI_CODE:
return "tsi_code";
case GRPC_ERROR_INT_SECURITY_STATUS:
return "security_status";
case GRPC_ERROR_INT_FD:
return "fd";
case GRPC_ERROR_INT_WSA_ERROR:
return "wsa_error";
case GRPC_ERROR_INT_HTTP_STATUS:
return "http_status";
}
GPR_UNREACHABLE_CODE(return "unknown");
}
static const char *error_str_name(grpc_error_strs key) {
switch (key) {
case GRPC_ERROR_STR_DESCRIPTION:
return "description";
case GRPC_ERROR_STR_OS_ERROR:
return "os_error";
case GRPC_ERROR_STR_TARGET_ADDRESS:
return "target_address";
case GRPC_ERROR_STR_SYSCALL:
return "syscall";
case GRPC_ERROR_STR_FILE:
return "file";
case GRPC_ERROR_STR_GRPC_MESSAGE:
return "grpc_message";
case GRPC_ERROR_STR_RAW_BYTES:
return "raw_bytes";
case GRPC_ERROR_STR_TSI_ERROR:
return "tsi_error";
case GRPC_ERROR_STR_FILENAME:
return "filename";
}
GPR_UNREACHABLE_CODE(return "unknown");
}
static const char *error_time_name(grpc_error_times key) {
switch (key) {
case GRPC_ERROR_TIME_CREATED:
return "created";
}
GPR_UNREACHABLE_CODE(return "unknown");
}
struct grpc_error {
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 ||
err == GRPC_ERROR_CANCELLED;
}
#ifdef GRPC_ERROR_REFCOUNT_DEBUG
grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
const char *func) {
if (is_special(err)) return err;
gpr_log(GPR_DEBUG, "%p: %d -> %d [%s:%d %s]", err, err->refs.count,
err->refs.count + 1, file, line, func);
gpr_ref(&err->refs);
return err;
}
#else
grpc_error *grpc_error_ref(grpc_error *err) {
if (is_special(err)) return err;
gpr_ref(&err->refs);
return err;
}
#endif
static void error_destroy(grpc_error *err) {
GPR_ASSERT(!is_special(err));
gpr_avl_unref(err->ints);
gpr_avl_unref(err->strs);
gpr_avl_unref(err->errs);
gpr_avl_unref(err->times);
gpr_free(err);
}
#ifdef GRPC_ERROR_REFCOUNT_DEBUG
void grpc_error_unref(grpc_error *err, const char *file, int line,
const char *func) {
if (is_special(err)) return;
gpr_log(GPR_DEBUG, "%p: %d -> %d [%s:%d %s]", err, err->refs.count,
err->refs.count - 1, file, line, func);
if (gpr_unref(&err->refs)) {
error_destroy(err);
}
}
#else
void grpc_error_unref(grpc_error *err) {
if (is_special(err)) return;
if (gpr_unref(&err->refs)) {
error_destroy(err);
}
}
#endif
grpc_error *grpc_error_create(const char *file, int line, const char *desc,
grpc_error **referencing,
size_t num_referencing) {
grpc_error *err = gpr_malloc(sizeof(*err));
if (err == NULL) { // TODO(ctiller): make gpr_malloc return NULL
return GRPC_ERROR_OOM;
}
#ifdef GRPC_ERROR_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line);
#endif
err->ints = gpr_avl_add(gpr_avl_create(&avl_vtable_ints),
(void *)(uintptr_t)GRPC_ERROR_INT_FILE_LINE,
(void *)(uintptr_t)line);
err->strs = gpr_avl_add(
gpr_avl_add(gpr_avl_create(&avl_vtable_strs),
(void *)(uintptr_t)GRPC_ERROR_STR_FILE, gpr_strdup(file)),
(void *)(uintptr_t)GRPC_ERROR_STR_DESCRIPTION, gpr_strdup(desc));
err->errs = gpr_avl_create(&avl_vtable_errs);
err->next_err = 0;
for (size_t i = 0; i < num_referencing; i++) {
if (referencing[i] == GRPC_ERROR_NONE) continue;
err->errs = gpr_avl_add(err->errs, (void *)(err->next_err++),
GRPC_ERROR_REF(referencing[i]));
}
err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times),
(void *)(uintptr_t)GRPC_ERROR_TIME_CREATED,
box_time(gpr_now(GPR_CLOCK_REALTIME)));
gpr_ref_init(&err->refs, 1);
return err;
}
static grpc_error *copy_error_and_unref(grpc_error *in) {
if (is_special(in)) {
if (in == GRPC_ERROR_NONE) return GRPC_ERROR_CREATE("no error");
if (in == GRPC_ERROR_OOM) return GRPC_ERROR_CREATE("oom");
if (in == GRPC_ERROR_CANCELLED) return GRPC_ERROR_CREATE("cancelled");
return GRPC_ERROR_CREATE("unknown");
}
grpc_error *out = gpr_malloc(sizeof(*out));
#ifdef GRPC_ERROR_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "%p create copying", out);
#endif
out->ints = gpr_avl_ref(in->ints);
out->strs = gpr_avl_ref(in->strs);
out->errs = gpr_avl_ref(in->errs);
out->times = gpr_avl_ref(in->times);
out->next_err = in->next_err;
gpr_ref_init(&out->refs, 1);
GRPC_ERROR_UNREF(in);
return out;
}
grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
intptr_t value) {
grpc_error *new = copy_error_and_unref(src);
new->ints = gpr_avl_add(new->ints, (void *)(uintptr_t)which, (void *)value);
return new;
}
bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) {
void *pp;
if (gpr_avl_maybe_get(err->ints, (void *)(uintptr_t)which, &pp)) {
if (p != NULL) *p = (intptr_t)pp;
return true;
}
return false;
}
grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
const char *value) {
grpc_error *new = copy_error_and_unref(src);
new->strs =
gpr_avl_add(new->strs, (void *)(uintptr_t)which, gpr_strdup(value));
return new;
}
grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) {
grpc_error *new = copy_error_and_unref(src);
new->errs = gpr_avl_add(new->errs, (void *)(new->next_err++), child);
return new;
}
static const char *no_error_string = "null";
static const char *oom_error_string = "\"Out of memory\"";
static const char *cancelled_error_string = "\"Cancelled\"";
typedef struct {
char *key;
char *value;
} kv_pair;
typedef struct {
kv_pair *kvs;
size_t num_kvs;
size_t cap_kvs;
} kv_pairs;
static void append_kv(kv_pairs *kvs, char *key, char *value) {
if (kvs->num_kvs == kvs->cap_kvs) {
kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4);
kvs->kvs = gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs);
}
kvs->kvs[kvs->num_kvs].key = key;
kvs->kvs[kvs->num_kvs].value = value;
kvs->num_kvs++;
}
static void collect_kvs(gpr_avl_node *node, char *key(void *k),
char *fmt(void *v), kv_pairs *kvs) {
if (node == NULL) return;
append_kv(kvs, key(node->key), fmt(node->value));
collect_kvs(node->left, key, fmt, kvs);
collect_kvs(node->right, key, fmt, kvs);
}
static char *key_int(void *p) {
return gpr_strdup(error_int_name((grpc_error_ints)(uintptr_t)p));
}
static char *key_str(void *p) {
return gpr_strdup(error_str_name((grpc_error_strs)(uintptr_t)p));
}
static char *key_time(void *p) {
return gpr_strdup(error_time_name((grpc_error_times)(uintptr_t)p));
}
static char *fmt_int(void *p) {
char *s;
gpr_asprintf(&s, "%" PRIdPTR, (intptr_t)p);
return s;
}
static void append_chr(char c, char **s, size_t *sz, size_t *cap) {
if (*sz == *cap) {
*cap = GPR_MAX(8, 3 * *cap / 2);
*s = gpr_realloc(*s, *cap);
}
(*s)[(*sz)++] = c;
}
static void append_str(const char *str, char **s, size_t *sz, size_t *cap) {
for (const char *c = str; *c; c++) {
append_chr(*c, s, sz, cap);
}
}
static void append_esc_str(const char *str, char **s, size_t *sz, size_t *cap) {
static const char *hex = "0123456789abcdef";
append_chr('"', s, sz, cap);
for (const uint8_t *c = (const uint8_t *)str; *c; c++) {
if (*c < 32 || *c >= 127) {
append_chr('\\', s, sz, cap);
switch (*c) {
case '\b':
append_chr('b', s, sz, cap);
break;
case '\f':
append_chr('f', s, sz, cap);
break;
case '\n':
append_chr('n', s, sz, cap);
break;
case '\r':
append_chr('r', s, sz, cap);
break;
case '\t':
append_chr('t', s, sz, cap);
break;
default:
append_chr('u', s, sz, cap);
append_chr('0', s, sz, cap);
append_chr('0', s, sz, cap);
append_chr(hex[*c >> 4], s, sz, cap);
append_chr(hex[*c & 0x0f], s, sz, cap);
break;
}
} else {
append_chr((char)*c, s, sz, cap);
}
}
append_chr('"', s, sz, cap);
}
static char *fmt_str(void *p) {
char *s = NULL;
size_t sz = 0;
size_t cap = 0;
append_esc_str(p, &s, &sz, &cap);
append_chr(0, &s, &sz, &cap);
return s;
}
static char *fmt_time(void *p) {
gpr_timespec tm = *(gpr_timespec *)p;
char *out;
char *pfx = "!!";
switch (tm.clock_type) {
case GPR_CLOCK_MONOTONIC:
pfx = "@monotonic:";
break;
case GPR_CLOCK_REALTIME:
pfx = "@";
break;
case GPR_CLOCK_PRECISE:
pfx = "@precise:";
break;
case GPR_TIMESPAN:
pfx = "";
break;
}
gpr_asprintf(&out, "\"%s%" PRId64 ".%09d\"", pfx, tm.tv_sec, tm.tv_nsec);
return out;
}
static void add_errs(gpr_avl_node *n, char **s, size_t *sz, size_t *cap) {
if (n == NULL) return;
add_errs(n->left, s, sz, cap);
const char *e = grpc_error_string(n->value);
append_str(e, s, sz, cap);
grpc_error_free_string(e);
add_errs(n->right, s, sz, cap);
}
static char *errs_string(grpc_error *err) {
char *s = NULL;
size_t sz = 0;
size_t cap = 0;
append_chr('[', &s, &sz, &cap);
add_errs(err->errs.root, &s, &sz, &cap);
append_chr(']', &s, &sz, &cap);
append_chr(0, &s, &sz, &cap);
return s;
}
static int cmp_kvs(const void *a, const void *b) {
const kv_pair *ka = a;
const kv_pair *kb = b;
return strcmp(ka->key, kb->key);
}
static const char *finish_kvs(kv_pairs *kvs) {
char *s = NULL;
size_t sz = 0;
size_t cap = 0;
append_chr('{', &s, &sz, &cap);
for (size_t i = 0; i < kvs->num_kvs; i++) {
if (i != 0) append_chr(',', &s, &sz, &cap);
append_esc_str(kvs->kvs[i].key, &s, &sz, &cap);
gpr_free(kvs->kvs[i].key);
append_chr(':', &s, &sz, &cap);
append_str(kvs->kvs[i].value, &s, &sz, &cap);
gpr_free(kvs->kvs[i].value);
}
append_chr('}', &s, &sz, &cap);
append_chr(0, &s, &sz, &cap);
gpr_free(kvs->kvs);
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) {
if (err == GRPC_ERROR_NONE) return no_error_string;
if (err == GRPC_ERROR_OOM) return oom_error_string;
if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string;
kv_pairs kvs;
memset(&kvs, 0, sizeof(kvs));
collect_kvs(err->ints.root, key_int, fmt_int, &kvs);
collect_kvs(err->strs.root, key_str, fmt_str, &kvs);
collect_kvs(err->times.root, key_time, fmt_time, &kvs);
if (!gpr_avl_is_empty(err->errs)) {
append_kv(&kvs, gpr_strdup("referenced_errors"), errs_string(err));
}
qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs);
return finish_kvs(&kvs);
}
grpc_error *grpc_os_error(const char *file, int line, int err,
const char *call_name) {
return grpc_error_set_str(
grpc_error_set_str(
grpc_error_set_int(grpc_error_create(file, line, "OS Error", NULL, 0),
GRPC_ERROR_INT_ERRNO, err),
GRPC_ERROR_STR_OS_ERROR, strerror(err)),
GRPC_ERROR_STR_SYSCALL, call_name);
}
#ifdef GPR_WINDOWS
grpc_error *grpc_wsa_error(const char *file, int line, int err,
const char *call_name) {
char *utf8_message = gpr_format_message(err);
grpc_error *error = grpc_error_set_str(
grpc_error_set_str(
grpc_error_set_int(grpc_error_create(file, line, "OS Error", NULL, 0),
GRPC_ERROR_INT_WSA_ERROR, err),
GRPC_ERROR_STR_OS_ERROR, utf8_message),
GRPC_ERROR_STR_SYSCALL, call_name);
gpr_free(utf8_message);
return error;
}
#endif
bool grpc_log_if_error(const char *what, grpc_error *error, const char *file,
int line) {
if (error == GRPC_ERROR_NONE) return true;
const char *msg = grpc_error_string(error);
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg);
grpc_error_free_string(msg);
GRPC_ERROR_UNREF(error);
return false;
}

@ -0,0 +1,192 @@
/*
*
* 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_H
#define GRPC_CORE_LIB_IOMGR_ERROR_H
#include <stdbool.h>
#include <stdint.h>
#include <grpc/support/time.h>
/// Opaque representation of an error.
/// Errors are refcounted objects that represent the result of an operation.
/// Ownership laws:
/// if a grpc_error is returned by a function, the caller owns a ref to that
/// instance
/// if a grpc_error is passed to a grpc_closure callback function (functions
/// with the signature:
/// void (*f)(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error))
/// then those functions do not automatically own a ref to error
/// if a grpc_error is passed to *ANY OTHER FUNCTION* then that function takes
/// ownership of the error
/// Errors have:
/// a set of ints, strings, and timestamps that describe the error
/// always present are:
/// GRPC_ERROR_STR_FILE, GRPC_ERROR_INT_FILE_LINE - source location the error
/// was generated
/// GRPC_ERROR_STR_DESCRIPTION - a human readable description of the error
/// GRPC_ERROR_TIME_CREATED - a timestamp indicating when the error happened
/// an error can also have children; these are other errors that are believed
/// to have contributed to this one. By accumulating children, we can begin
/// to root cause high level failures from low level failures, without having
/// to derive execution paths from log lines
typedef struct grpc_error grpc_error;
typedef enum {
/// 'errno' from the operating system
GRPC_ERROR_INT_ERRNO,
/// __LINE__ from the call site creating the error
GRPC_ERROR_INT_FILE_LINE,
/// stream identifier: for errors that are associated with an individual
/// wire stream
GRPC_ERROR_INT_STREAM_ID,
/// grpc status code representing this error
GRPC_ERROR_INT_GRPC_STATUS,
/// offset into some binary blob (usually represented by
/// GRPC_ERROR_STR_RAW_BYTES) where the error occurred
GRPC_ERROR_INT_OFFSET,
/// context sensitive index associated with the error
GRPC_ERROR_INT_INDEX,
/// context sensitive size associated with the error
GRPC_ERROR_INT_SIZE,
/// http2 error code associated with the error (see the HTTP2 RFC)
GRPC_ERROR_INT_HTTP2_ERROR,
/// TSI status code associated with the error
GRPC_ERROR_INT_TSI_CODE,
/// grpc_security_status associated with the error
GRPC_ERROR_INT_SECURITY_STATUS,
/// WSAGetLastError() reported when this error occurred
GRPC_ERROR_INT_WSA_ERROR,
/// File descriptor associated with this error
GRPC_ERROR_INT_FD,
/// HTTP status (i.e. 404)
GRPC_ERROR_INT_HTTP_STATUS,
} grpc_error_ints;
typedef enum {
/// top-level textual description of this error
GRPC_ERROR_STR_DESCRIPTION,
/// source file in which this error occurred
GRPC_ERROR_STR_FILE,
/// operating system description of this error
GRPC_ERROR_STR_OS_ERROR,
/// syscall that generated this error
GRPC_ERROR_STR_SYSCALL,
/// peer that we were trying to communicate when this error occurred
GRPC_ERROR_STR_TARGET_ADDRESS,
/// grpc status message associated with this error
GRPC_ERROR_STR_GRPC_MESSAGE,
/// hex dump (or similar) with the data that generated this error
GRPC_ERROR_STR_RAW_BYTES,
/// tsi error string associated with this error
GRPC_ERROR_STR_TSI_ERROR,
/// filename that we were trying to read/write when this error occurred
GRPC_ERROR_STR_FILENAME,
} grpc_error_strs;
typedef enum {
/// timestamp of error creation
GRPC_ERROR_TIME_CREATED,
} grpc_error_times;
#define GRPC_ERROR_NONE ((grpc_error *)NULL)
#define GRPC_ERROR_OOM ((grpc_error *)1)
#define GRPC_ERROR_CANCELLED ((grpc_error *)2)
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
grpc_error *grpc_error_create(const char *file, int line, const char *desc,
grpc_error **referencing, size_t num_referencing);
/// Create an error (this is the preferred way of generating an error that is
/// not due to a system call - for system calls, use GRPC_OS_ERROR or
/// GRPC_WSA_ERROR as appropriate)
/// \a referencing is an array of num_referencing elements indicating one or
/// more errors that are believed to have contributed to this one
/// err = grpc_error_create(x, y, z, r, nr) is equivalent to:
/// err = grpc_error_create(x, y, z, NULL, 0);
/// for (i=0; i<nr; i++) err = grpc_error_add_child(err, r[i]);
#define GRPC_ERROR_CREATE(desc) \
grpc_error_create(__FILE__, __LINE__, desc, NULL, 0)
// Create an error that references some other errors. This function adds a
// reference to each error in errs - it does not consume an existing reference
#define GRPC_ERROR_CREATE_REFERENCING(desc, errs, count) \
grpc_error_create(__FILE__, __LINE__, desc, errs, count)
//#define GRPC_ERROR_REFCOUNT_DEBUG
#ifdef GRPC_ERROR_REFCOUNT_DEBUG
grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
const char *func);
void grpc_error_unref(grpc_error *err, const char *file, int line,
const char *func);
#define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__, __func__)
#define GRPC_ERROR_UNREF(err) \
grpc_error_unref(err, __FILE__, __LINE__, __func__)
#else
grpc_error *grpc_error_ref(grpc_error *err);
void grpc_error_unref(grpc_error *err);
#define GRPC_ERROR_REF(err) grpc_error_ref(err)
#define GRPC_ERROR_UNREF(err) grpc_error_unref(err)
#endif
grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
intptr_t value);
bool grpc_error_get_int(grpc_error *error, grpc_error_ints which, intptr_t *p);
grpc_error *grpc_error_set_time(grpc_error *src, grpc_error_times which,
gpr_timespec value);
grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
const char *value);
/// 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
/// errors that contributed to them.
grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child);
grpc_error *grpc_os_error(const char *file, int line, int err,
const char *call_name);
/// create an error associated with errno!=0 (an 'operating system' error)
#define GRPC_OS_ERROR(err, call_name) \
grpc_os_error(__FILE__, __LINE__, err, call_name)
grpc_error *grpc_wsa_error(const char *file, int line, int err,
const char *call_name);
/// windows only: create an error associated with WSAGetLastError()!=0
#define GRPC_WSA_ERROR(err, call_name) \
grpc_wsa_error(__FILE__, __LINE__, err, call_name)
bool grpc_log_if_error(const char *what, grpc_error *error, const char *file,
int line);
#define GRPC_LOG_IF_ERROR(what, error) \
grpc_log_if_error((what), (error), __FILE__, __LINE__)
#endif /* GRPC_CORE_LIB_IOMGR_ERROR_H */

@ -221,9 +221,10 @@ struct grpc_pollset {
struct grpc_pollset_vtable {
void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
struct grpc_fd *fd, int and_unlock_pollset);
void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now);
grpc_error *(*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now);
void (*finish_shutdown)(grpc_pollset *pollset);
void (*destroy)(grpc_pollset *pollset);
};
@ -251,9 +252,9 @@ static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
#define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2
/* As per pollset_kick, with an extended set of flags (defined above)
-- mostly for fd_posix's use. */
static void pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags);
static grpc_error *pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags) GRPC_MUST_USE_RESULT;
/* turn a pollset into a multipoller: platform specific */
typedef void (*platform_become_multipoller_type)(grpc_exec_ctx *exec_ctx,
@ -420,12 +421,13 @@ static bool fd_is_orphaned(grpc_fd *fd) {
return (gpr_atm_acq_load(&fd->refst) & 1) == 0;
}
static void pollset_kick_locked(grpc_fd_watcher *watcher) {
static grpc_error *pollset_kick_locked(grpc_fd_watcher *watcher) {
gpr_mu_lock(&watcher->pollset->mu);
GPR_ASSERT(watcher->worker);
pollset_kick_ext(watcher->pollset, watcher->worker,
GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
grpc_error *err = pollset_kick_ext(watcher->pollset, watcher->worker,
GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
gpr_mu_unlock(&watcher->pollset->mu);
return err;
}
static void maybe_wake_one_watcher_locked(grpc_fd *fd) {
@ -464,7 +466,7 @@ static void close_fd_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
} else {
remove_fd_from_all_epoll_sets(fd->fd);
}
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL);
grpc_exec_ctx_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_NONE, NULL);
}
static int fd_wrapped_fd(grpc_fd *fd) {
@ -513,15 +515,27 @@ static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
#endif
static grpc_error *fd_shutdown_error(bool shutdown) {
if (!shutdown) {
return GRPC_ERROR_NONE;
} else {
return GRPC_ERROR_CREATE("FD shutdown");
}
}
static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure **st, grpc_closure *closure) {
if (*st == CLOSURE_NOT_READY) {
if (fd->shutdown) {
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CREATE("FD shutdown"),
NULL);
} else if (*st == CLOSURE_NOT_READY) {
/* not ready ==> switch to a waiting state by setting the closure */
*st = closure;
} else if (*st == CLOSURE_READY) {
/* already ready ==> queue the closure to run immediately */
*st = CLOSURE_NOT_READY;
grpc_exec_ctx_enqueue(exec_ctx, closure, !fd->shutdown, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown),
NULL);
maybe_wake_one_watcher_locked(fd);
} else {
/* upcallptr was set to a different closure. This is an error! */
@ -544,7 +558,7 @@ static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
return 0;
} else {
/* waiting ==> queue closure */
grpc_exec_ctx_enqueue(exec_ctx, *st, !fd->shutdown, NULL);
grpc_exec_ctx_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown), NULL);
*st = CLOSURE_NOT_READY;
return 1;
}
@ -557,11 +571,22 @@ static void set_read_notifier_pollset_locked(
static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
gpr_mu_lock(&fd->mu);
GPR_ASSERT(!fd->shutdown);
fd->shutdown = 1;
set_ready_locked(exec_ctx, fd, &fd->read_closure);
set_ready_locked(exec_ctx, fd, &fd->write_closure);
/* only shutdown once */
if (!fd->shutdown) {
fd->shutdown = 1;
/* signal read/write closed to OS so that future operations fail */
shutdown(fd->fd, SHUT_RDWR);
set_ready_locked(exec_ctx, fd, &fd->read_closure);
set_ready_locked(exec_ctx, fd, &fd->write_closure);
}
gpr_mu_unlock(&fd->mu);
}
static bool fd_is_shutdown(grpc_fd *fd) {
gpr_mu_lock(&fd->mu);
bool r = fd->shutdown;
gpr_mu_unlock(&fd->mu);
return r;
}
static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
@ -744,10 +769,19 @@ static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
worker->prev->next = worker->next->prev = worker;
}
static void pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags) {
static void kick_append_error(grpc_error **composite, grpc_error *error) {
if (error == GRPC_ERROR_NONE) return;
if (*composite == GRPC_ERROR_NONE) {
*composite = GRPC_ERROR_CREATE("Kick Failure");
}
*composite = grpc_error_add_child(*composite, error);
}
static grpc_error *pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags) {
GPR_TIMER_BEGIN("pollset_kick_ext", 0);
grpc_error *error = GRPC_ERROR_NONE;
/* pollset->mu already held */
if (specific_worker != NULL) {
@ -757,25 +791,28 @@ static void pollset_kick_ext(grpc_pollset *p,
for (specific_worker = p->root_worker.next;
specific_worker != &p->root_worker;
specific_worker = specific_worker->next) {
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
kick_append_error(
&error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
}
p->kicked_without_pollers = 1;
p->kicked_without_pollers = true;
GPR_TIMER_END("pollset_kick_ext.broadcast", 0);
} else if (gpr_tls_get(&g_current_thread_worker) !=
(intptr_t)specific_worker) {
GPR_TIMER_MARK("different_thread_worker", 0);
if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
specific_worker->reevaluate_polling_on_wakeup = 1;
specific_worker->reevaluate_polling_on_wakeup = true;
}
specific_worker->kicked_specifically = 1;
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
specific_worker->kicked_specifically = true;
kick_append_error(&error,
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
} else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) {
GPR_TIMER_MARK("kick_yoself", 0);
if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
specific_worker->reevaluate_polling_on_wakeup = 1;
specific_worker->reevaluate_polling_on_wakeup = true;
}
specific_worker->kicked_specifically = 1;
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
specific_worker->kicked_specifically = true;
kick_append_error(&error,
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
}
} else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) {
GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
@ -783,14 +820,9 @@ static void pollset_kick_ext(grpc_pollset *p,
specific_worker = pop_front_worker(p);
if (specific_worker != NULL) {
if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) {
/* Prefer not to kick self. Push the worker to the end of the list and
* pop the one from front */
GPR_TIMER_MARK("kick_anonymous_not_self", 0);
push_back_worker(p, specific_worker);
specific_worker = pop_front_worker(p);
/* If there was only one worker on the pollset, we would get the same
* worker we pushed (the one set on current thread local) back. If so,
* kick it only if GRPC_POLLSET_CAN_KICK_SELF flag is set */
if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 &&
gpr_tls_get(&g_current_thread_worker) ==
(intptr_t)specific_worker) {
@ -801,28 +833,30 @@ static void pollset_kick_ext(grpc_pollset *p,
if (specific_worker != NULL) {
GPR_TIMER_MARK("finally_kick", 0);
push_back_worker(p, specific_worker);
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
kick_append_error(
&error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
}
} else {
GPR_TIMER_MARK("kicked_no_pollers", 0);
p->kicked_without_pollers = 1;
p->kicked_without_pollers = true;
}
}
GPR_TIMER_END("pollset_kick_ext", 0);
return error;
}
static void pollset_kick(grpc_pollset *p,
grpc_pollset_worker *specific_worker) {
pollset_kick_ext(p, specific_worker, 0);
static grpc_error *pollset_kick(grpc_pollset *p,
grpc_pollset_worker *specific_worker) {
return pollset_kick_ext(p, specific_worker, 0);
}
/* global state management */
static void pollset_global_init(void) {
static grpc_error *pollset_global_init(void) {
gpr_tls_init(&g_current_thread_poller);
gpr_tls_init(&g_current_thread_worker);
grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
return grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
}
static void pollset_global_shutdown(void) {
@ -831,7 +865,9 @@ static void pollset_global_shutdown(void) {
gpr_tls_destroy(&g_current_thread_worker);
}
static void kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); }
static grpc_error *kick_poller(void) {
return grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd);
}
/* main interface */
@ -894,14 +930,23 @@ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
GPR_ASSERT(grpc_closure_list_empty(pollset->idle_jobs));
pollset->vtable->finish_shutdown(pollset);
grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE, NULL);
}
static void work_combine_error(grpc_error **composite, grpc_error *error) {
if (error == GRPC_ERROR_NONE) return;
if (*composite == GRPC_ERROR_NONE) {
*composite = GRPC_ERROR_CREATE("pollset_work");
}
*composite = grpc_error_add_child(*composite, error);
}
static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl, gpr_timespec now,
gpr_timespec deadline) {
static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl,
gpr_timespec now, gpr_timespec deadline) {
grpc_pollset_worker worker;
*worker_hdl = &worker;
grpc_error *error = GRPC_ERROR_NONE;
/* pollset->mu already held */
int added_worker = 0;
@ -917,7 +962,10 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
pollset->local_wakeup_cache = worker.wakeup_fd->next;
} else {
worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd));
grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
if (error != GRPC_ERROR_NONE) {
return error;
}
}
worker.kicked_specifically = 0;
/* If there's work waiting for the pollset to be idle, and the
@ -954,8 +1002,9 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
}
gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset);
GPR_TIMER_BEGIN("maybe_work_and_unlock", 0);
pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, &worker,
deadline, now);
work_combine_error(&error,
pollset->vtable->maybe_work_and_unlock(
exec_ctx, pollset, &worker, deadline, now));
GPR_TIMER_END("maybe_work_and_unlock", 0);
locked = 0;
gpr_tls_set(&g_current_thread_poller, 0);
@ -1017,6 +1066,7 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
}
*worker_hdl = NULL;
GPR_TIMER_END("pollset_work", 0);
return error;
}
static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@ -1065,7 +1115,7 @@ typedef struct grpc_unary_promote_args {
} grpc_unary_promote_args;
static void basic_do_promote(grpc_exec_ctx *exec_ctx, void *args,
bool success) {
grpc_error *error) {
grpc_unary_promote_args *up_args = args;
const grpc_pollset_vtable *original_vtable = up_args->original_vtable;
grpc_pollset *pollset = up_args->pollset;
@ -1167,7 +1217,8 @@ static void basic_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
up_args->promotion_closure.cb = basic_do_promote;
up_args->promotion_closure.cb_arg = up_args;
grpc_closure_list_add(&pollset->idle_jobs, &up_args->promotion_closure, 1);
grpc_closure_list_append(&pollset->idle_jobs, &up_args->promotion_closure,
GRPC_ERROR_NONE);
pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
exit:
@ -1176,11 +1227,9 @@ exit:
}
}
static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
grpc_pollset_worker *worker,
gpr_timespec deadline,
gpr_timespec now) {
static grpc_error *basic_pollset_maybe_work_and_unlock(
grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now) {
#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR)
#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR)
@ -1190,6 +1239,7 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
int timeout;
int r;
nfds_t nfds;
grpc_error *error = GRPC_ERROR_NONE;
fd = pollset->data.ptr;
if (fd && fd_is_orphaned(fd)) {
@ -1230,7 +1280,7 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
if (r < 0) {
if (errno != EINTR) {
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
}
if (fd) {
fd_end_poll(exec_ctx, &fd_watcher, 0, 0, NULL);
@ -1241,10 +1291,12 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
}
} else {
if (pfd[0].revents & POLLIN_CHECK) {
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
work_combine_error(&error,
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd));
}
if (pfd[1].revents & POLLIN_CHECK) {
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
work_combine_error(&error,
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd));
}
if (nfds > 2) {
fd_end_poll(exec_ctx, &fd_watcher, pfd[2].revents & POLLIN_CHECK,
@ -1257,6 +1309,8 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
if (fd) {
GRPC_FD_UNREF(fd, "basicpoll_begin");
}
return error;
}
static void basic_pollset_destroy(grpc_pollset *pollset) {
@ -1317,7 +1371,7 @@ exit:
}
}
static void multipoll_with_poll_pollset_maybe_work_and_unlock(
static grpc_error *multipoll_with_poll_pollset_maybe_work_and_unlock(
grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now) {
#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR)
@ -1331,6 +1385,7 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
/* TODO(ctiller): inline some elements to avoid an allocation */
grpc_fd_watcher *watchers;
struct pollfd *pfds;
grpc_error *error = GRPC_ERROR_NONE;
h = pollset->data.ptr;
timeout = poll_deadline_to_millis_timeout(deadline, now);
@ -1383,7 +1438,7 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
if (r < 0) {
if (errno != EINTR) {
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
}
for (i = 2; i < pfd_count; i++) {
fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL);
@ -1394,10 +1449,12 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
}
} else {
if (pfds[0].revents & POLLIN_CHECK) {
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
work_combine_error(&error,
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd));
}
if (pfds[1].revents & POLLIN_CHECK) {
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
work_combine_error(&error,
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd));
}
for (i = 2; i < pfd_count; i++) {
if (watchers[i].fd == NULL) {
@ -1411,6 +1468,8 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
gpr_free(pfds);
gpr_free(watchers);
return error;
}
static void multipoll_with_poll_pollset_finish_shutdown(grpc_pollset *pollset) {
@ -1601,7 +1660,7 @@ static void finally_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
}
static void perform_delayed_add(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_status) {
grpc_error *error) {
delayed_add *da = arg;
if (!fd_is_orphaned(da->fd)) {
@ -1614,7 +1673,8 @@ static void perform_delayed_add(grpc_exec_ctx *exec_ctx, void *arg,
/* We don't care about this pollset anymore. */
if (da->pollset->in_flight_cbs == 0 && !da->pollset->called_shutdown) {
da->pollset->called_shutdown = 1;
grpc_exec_ctx_enqueue(exec_ctx, da->pollset->shutdown_done, true, NULL);
grpc_exec_ctx_sched(exec_ctx, da->pollset->shutdown_done, GRPC_ERROR_NONE,
NULL);
}
}
gpr_mu_unlock(&da->pollset->mu);
@ -1638,14 +1698,14 @@ static void multipoll_with_epoll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
GRPC_FD_REF(fd, "delayed_add");
grpc_closure_init(&da->closure, perform_delayed_add, da);
pollset->in_flight_cbs++;
grpc_exec_ctx_enqueue(exec_ctx, &da->closure, true, NULL);
grpc_exec_ctx_sched(exec_ctx, &da->closure, GRPC_ERROR_NONE, NULL);
}
}
/* TODO(klempner): We probably want to turn this down a bit */
#define GRPC_EPOLL_MAX_EVENTS 1000
static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
static grpc_error *multipoll_with_epoll_pollset_maybe_work_and_unlock(
grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now) {
struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS];
@ -1654,6 +1714,7 @@ static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
epoll_hdr *h = pollset->data.ptr;
int timeout_ms;
struct pollfd pfds[2];
grpc_error *error = GRPC_ERROR_NONE;
/* If you want to ignore epoll's ability to sanely handle parallel pollers,
* for a more apples-to-apples performance comparison with poll, add a
@ -1682,13 +1743,14 @@ static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
if (poll_rv < 0) {
if (errno != EINTR) {
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
}
} else if (poll_rv == 0) {
/* do nothing */
} else {
if (pfds[0].revents) {
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd);
work_combine_error(&error,
grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd));
}
if (pfds[1].revents) {
do {
@ -1696,7 +1758,7 @@ static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0);
if (ep_rv < 0) {
if (errno != EINTR) {
gpr_log(GPR_ERROR, "epoll_wait() failed: %s", strerror(errno));
work_combine_error(&error, GRPC_OS_ERROR(errno, "epoll_wait"));
}
} else {
int i;
@ -1708,7 +1770,8 @@ static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI);
int write_ev = ep_ev[i].events & EPOLLOUT;
if (fd == NULL) {
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
work_combine_error(&error, grpc_wakeup_fd_consume_wakeup(
&grpc_global_wakeup_fd));
} else {
if (read_ev || cancel) {
fd_become_readable(exec_ctx, fd, pollset);
@ -1722,6 +1785,7 @@ static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
} while (ep_rv == GRPC_EPOLL_MAX_EVENTS);
}
}
return error;
}
static void multipoll_with_epoll_pollset_finish_shutdown(
@ -1938,6 +2002,7 @@ static const grpc_event_engine_vtable vtable = {
.fd_wrapped_fd = fd_wrapped_fd,
.fd_orphan = fd_orphan,
.fd_shutdown = fd_shutdown,
.fd_is_shutdown = fd_is_shutdown,
.fd_notify_on_read = fd_notify_on_read,
.fd_notify_on_write = fd_notify_on_write,
.fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -217,9 +217,9 @@ static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
#define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2
/* As per pollset_kick, with an extended set of flags (defined above)
-- mostly for fd_posix's use. */
static void pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags);
static grpc_error *pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags) GRPC_MUST_USE_RESULT;
/* Return 1 if the pollset has active threads in pollset_work (pollset must
* be locked) */
@ -328,12 +328,13 @@ static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
return notifier;
}
static void pollset_kick_locked(grpc_fd_watcher *watcher) {
static grpc_error *pollset_kick_locked(grpc_fd_watcher *watcher) {
gpr_mu_lock(&watcher->pollset->mu);
GPR_ASSERT(watcher->worker);
pollset_kick_ext(watcher->pollset, watcher->worker,
GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
grpc_error *err = pollset_kick_ext(watcher->pollset, watcher->worker,
GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
gpr_mu_unlock(&watcher->pollset->mu);
return err;
}
static void maybe_wake_one_watcher_locked(grpc_fd *fd) {
@ -370,7 +371,7 @@ static void close_fd_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
if (!fd->released) {
close(fd->fd);
}
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL);
grpc_exec_ctx_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_NONE, NULL);
}
static int fd_wrapped_fd(grpc_fd *fd) {
@ -419,15 +420,27 @@ static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
#endif
static grpc_error *fd_shutdown_error(bool shutdown) {
if (!shutdown) {
return GRPC_ERROR_NONE;
} else {
return GRPC_ERROR_CREATE("FD shutdown");
}
}
static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure **st, grpc_closure *closure) {
if (*st == CLOSURE_NOT_READY) {
if (fd->shutdown) {
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CREATE("FD shutdown"),
NULL);
} else if (*st == CLOSURE_NOT_READY) {
/* not ready ==> switch to a waiting state by setting the closure */
*st = closure;
} else if (*st == CLOSURE_READY) {
/* already ready ==> queue the closure to run immediately */
*st = CLOSURE_NOT_READY;
grpc_exec_ctx_enqueue(exec_ctx, closure, !fd->shutdown, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown),
NULL);
maybe_wake_one_watcher_locked(fd);
} else {
/* upcallptr was set to a different closure. This is an error! */
@ -450,7 +463,7 @@ static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
return 0;
} else {
/* waiting ==> queue closure */
grpc_exec_ctx_enqueue(exec_ctx, *st, !fd->shutdown, NULL);
grpc_exec_ctx_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown), NULL);
*st = CLOSURE_NOT_READY;
return 1;
}
@ -463,13 +476,24 @@ static void set_read_notifier_pollset_locked(
static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
gpr_mu_lock(&fd->mu);
GPR_ASSERT(!fd->shutdown);
fd->shutdown = 1;
set_ready_locked(exec_ctx, fd, &fd->read_closure);
set_ready_locked(exec_ctx, fd, &fd->write_closure);
/* only shutdown once */
if (!fd->shutdown) {
fd->shutdown = 1;
/* signal read/write closed to OS so that future operations fail */
shutdown(fd->fd, SHUT_RDWR);
set_ready_locked(exec_ctx, fd, &fd->read_closure);
set_ready_locked(exec_ctx, fd, &fd->write_closure);
}
gpr_mu_unlock(&fd->mu);
}
static bool fd_is_shutdown(grpc_fd *fd) {
gpr_mu_lock(&fd->mu);
bool r = fd->shutdown;
gpr_mu_unlock(&fd->mu);
return r;
}
static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure) {
gpr_mu_lock(&fd->mu);
@ -631,10 +655,19 @@ static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
worker->prev->next = worker->next->prev = worker;
}
static void pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags) {
static void kick_append_error(grpc_error **composite, grpc_error *error) {
if (error == GRPC_ERROR_NONE) return;
if (*composite == GRPC_ERROR_NONE) {
*composite = GRPC_ERROR_CREATE("Kick Failure");
}
*composite = grpc_error_add_child(*composite, error);
}
static grpc_error *pollset_kick_ext(grpc_pollset *p,
grpc_pollset_worker *specific_worker,
uint32_t flags) {
GPR_TIMER_BEGIN("pollset_kick_ext", 0);
grpc_error *error = GRPC_ERROR_NONE;
/* pollset->mu already held */
if (specific_worker != NULL) {
@ -644,25 +677,28 @@ static void pollset_kick_ext(grpc_pollset *p,
for (specific_worker = p->root_worker.next;
specific_worker != &p->root_worker;
specific_worker = specific_worker->next) {
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
kick_append_error(
&error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
}
p->kicked_without_pollers = 1;
p->kicked_without_pollers = true;
GPR_TIMER_END("pollset_kick_ext.broadcast", 0);
} else if (gpr_tls_get(&g_current_thread_worker) !=
(intptr_t)specific_worker) {
GPR_TIMER_MARK("different_thread_worker", 0);
if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
specific_worker->reevaluate_polling_on_wakeup = 1;
specific_worker->reevaluate_polling_on_wakeup = true;
}
specific_worker->kicked_specifically = 1;
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
specific_worker->kicked_specifically = true;
kick_append_error(&error,
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
} else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) {
GPR_TIMER_MARK("kick_yoself", 0);
if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) {
specific_worker->reevaluate_polling_on_wakeup = 1;
specific_worker->reevaluate_polling_on_wakeup = true;
}
specific_worker->kicked_specifically = 1;
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
specific_worker->kicked_specifically = true;
kick_append_error(&error,
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
}
} else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) {
GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0);
@ -683,28 +719,31 @@ static void pollset_kick_ext(grpc_pollset *p,
if (specific_worker != NULL) {
GPR_TIMER_MARK("finally_kick", 0);
push_back_worker(p, specific_worker);
grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd);
kick_append_error(
&error, grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd));
}
} else {
GPR_TIMER_MARK("kicked_no_pollers", 0);
p->kicked_without_pollers = 1;
p->kicked_without_pollers = true;
}
}
GPR_TIMER_END("pollset_kick_ext", 0);
GRPC_LOG_IF_ERROR("pollset_kick_ext", GRPC_ERROR_REF(error));
return error;
}
static void pollset_kick(grpc_pollset *p,
grpc_pollset_worker *specific_worker) {
pollset_kick_ext(p, specific_worker, 0);
static grpc_error *pollset_kick(grpc_pollset *p,
grpc_pollset_worker *specific_worker) {
return pollset_kick_ext(p, specific_worker, 0);
}
/* global state management */
static void pollset_global_init(void) {
static grpc_error *pollset_global_init(void) {
gpr_tls_init(&g_current_thread_poller);
gpr_tls_init(&g_current_thread_worker);
grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
return grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
}
static void pollset_global_shutdown(void) {
@ -713,7 +752,9 @@ static void pollset_global_shutdown(void) {
gpr_tls_destroy(&g_current_thread_worker);
}
static void kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); }
static grpc_error *kick_poller(void) {
return grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd);
}
/* main interface */
@ -783,14 +824,23 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
GRPC_FD_UNREF(pollset->fds[i], "multipoller");
}
pollset->fd_count = 0;
grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE, NULL);
}
static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl, gpr_timespec now,
gpr_timespec deadline) {
static void work_combine_error(grpc_error **composite, grpc_error *error) {
if (error == GRPC_ERROR_NONE) return;
if (*composite == GRPC_ERROR_NONE) {
*composite = GRPC_ERROR_CREATE("pollset_work");
}
*composite = grpc_error_add_child(*composite, error);
}
static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl,
gpr_timespec now, gpr_timespec deadline) {
grpc_pollset_worker worker;
*worker_hdl = &worker;
grpc_error *error = GRPC_ERROR_NONE;
/* pollset->mu already held */
int added_worker = 0;
@ -806,7 +856,11 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
pollset->local_wakeup_cache = worker.wakeup_fd->next;
} else {
worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd));
grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
error = grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
if (error != GRPC_ERROR_NONE) {
GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error));
return error;
}
}
worker.kicked_specifically = 0;
/* If there's work waiting for the pollset to be idle, and the
@ -890,7 +944,7 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
if (r < 0) {
if (errno != EINTR) {
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
work_combine_error(&error, GRPC_OS_ERROR(errno, "poll"));
}
for (i = 2; i < pfd_count; i++) {
fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL);
@ -901,10 +955,12 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
}
} else {
if (pfds[0].revents & POLLIN_CHECK) {
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd);
work_combine_error(
&error, grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd));
}
if (pfds[1].revents & POLLIN_CHECK) {
grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd);
work_combine_error(
&error, grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd));
}
for (i = 2; i < pfd_count; i++) {
if (watchers[i].fd == NULL) {
@ -937,7 +993,7 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
/* If we're forced to re-evaluate polling (via pollset_kick with
GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force
a loop */
if (worker.reevaluate_polling_on_wakeup) {
if (worker.reevaluate_polling_on_wakeup && error == GRPC_ERROR_NONE) {
worker.reevaluate_polling_on_wakeup = 0;
pollset->kicked_without_pollers = 0;
if (queued_work || worker.kicked_specifically) {
@ -982,6 +1038,8 @@ static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
}
*worker_hdl = NULL;
GPR_TIMER_END("pollset_work", 0);
GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error));
return error;
}
static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@ -1172,6 +1230,7 @@ static const grpc_event_engine_vtable vtable = {
.fd_wrapped_fd = fd_wrapped_fd,
.fd_orphan = fd_orphan,
.fd_shutdown = fd_shutdown,
.fd_is_shutdown = fd_is_shutdown,
.fd_notify_on_read = fd_notify_on_read,
.fd_notify_on_write = fd_notify_on_write,
.fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
@ -1199,7 +1258,9 @@ static const grpc_event_engine_vtable vtable = {
};
const grpc_event_engine_vtable *grpc_init_poll_posix(void) {
pollset_global_init();
if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
return NULL;
}
return &vtable;
}

@ -163,6 +163,10 @@ void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
g_event_engine->fd_shutdown(exec_ctx, fd);
}
bool grpc_fd_is_shutdown(grpc_fd *fd) {
return g_event_engine->fd_is_shutdown(fd);
}
void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure) {
g_event_engine->fd_notify_on_read(exec_ctx, fd, closure);
@ -192,15 +196,15 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
g_event_engine->pollset_destroy(pollset);
}
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now,
gpr_timespec deadline) {
g_event_engine->pollset_work(exec_ctx, pollset, worker, now, deadline);
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now,
gpr_timespec deadline) {
return g_event_engine->pollset_work(exec_ctx, pollset, worker, now, deadline);
}
void grpc_pollset_kick(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker) {
g_event_engine->pollset_kick(pollset, specific_worker);
grpc_error *grpc_pollset_kick(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker) {
return g_event_engine->pollset_kick(pollset, specific_worker);
}
void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@ -250,6 +254,6 @@ void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
g_event_engine->pollset_set_del_fd(exec_ctx, pollset_set, fd);
}
void grpc_kick_poller(void) { g_event_engine->kick_poller(); }
grpc_error *grpc_kick_poller(void) { return g_event_engine->kick_poller(); }
#endif // GPR_POSIX_SOCKET

@ -55,6 +55,7 @@ typedef struct grpc_event_engine_vtable {
grpc_closure *closure);
void (*fd_notify_on_write)(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure);
bool (*fd_is_shutdown)(grpc_fd *fd);
grpc_pollset *(*fd_get_read_notifier_pollset)(grpc_exec_ctx *exec_ctx,
grpc_fd *fd);
@ -63,11 +64,11 @@ typedef struct grpc_event_engine_vtable {
grpc_closure *closure);
void (*pollset_reset)(grpc_pollset *pollset);
void (*pollset_destroy)(grpc_pollset *pollset);
void (*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now,
gpr_timespec deadline);
void (*pollset_kick)(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker);
grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now,
gpr_timespec deadline);
grpc_error *(*pollset_kick)(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker);
void (*pollset_add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
struct grpc_fd *fd);
@ -90,7 +91,7 @@ typedef struct grpc_event_engine_vtable {
void (*pollset_set_del_fd)(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_fd *fd);
void (*kick_poller)(void);
grpc_error *(*kick_poller)(void);
void (*shutdown_engine)(void);
} grpc_event_engine_vtable;
@ -119,7 +120,10 @@ int grpc_fd_wrapped_fd(grpc_fd *fd);
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
int *release_fd, const char *reason);
/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */
/* Has grpc_fd_shutdown been called on an fd? */
bool grpc_fd_is_shutdown(grpc_fd *fd);
/* Cause any current and future callbacks to fail. */
void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
/* Register read interest, causing read_cb to be called once when fd becomes

@ -63,11 +63,12 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
grpc_closure *c = exec_ctx->closure_list.head;
exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
while (c != NULL) {
bool success = (bool)(c->final_data & 1);
grpc_closure *next = (grpc_closure *)(c->final_data & ~(uintptr_t)1);
grpc_closure *next = c->next_data.next;
grpc_error *error = c->error;
did_something = true;
GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
c->cb(exec_ctx, c->cb_arg, success);
c->cb(exec_ctx, c->cb_arg, error);
GRPC_ERROR_UNREF(error);
GPR_TIMER_END("grpc_exec_ctx_flush.cb", 0);
c = next;
}
@ -81,11 +82,11 @@ void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
grpc_exec_ctx_flush(exec_ctx);
}
void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
bool success,
grpc_workqueue *offload_target_or_null) {
void grpc_exec_ctx_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_error *error,
grpc_workqueue *offload_target_or_null) {
GPR_ASSERT(offload_target_or_null == NULL);
grpc_closure_list_add(&exec_ctx->closure_list, closure, success);
grpc_closure_list_append(&exec_ctx->closure_list, closure, error);
}
void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,

@ -94,9 +94,9 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx);
* the instance is destroyed, or work may be lost. */
void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx);
/** Add a closure to be executed at the next flush/finish point */
void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
bool success,
grpc_workqueue *offload_target_or_null);
void grpc_exec_ctx_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_error *error,
grpc_workqueue *offload_target_or_null);
/** Returns true if we'd like to leave this execution context as soon as
possible: useful for deciding whether to do something more or not depending
on outside context */

@ -112,10 +112,10 @@ static void maybe_spawn_locked() {
g_executor.pending_join = 1;
}
void grpc_executor_enqueue(grpc_closure *closure, bool success) {
void grpc_executor_push(grpc_closure *closure, grpc_error *error) {
gpr_mu_lock(&g_executor.mu);
if (g_executor.shutting_down == 0) {
grpc_closure_list_add(&g_executor.closures, closure, success);
grpc_closure_list_append(&g_executor.closures, closure, error);
maybe_spawn_locked();
}
gpr_mu_unlock(&g_executor.mu);

@ -45,7 +45,7 @@ void grpc_executor_init();
/** Enqueue \a closure for its eventual execution of \a f(arg) on a separate
* thread */
void grpc_executor_enqueue(grpc_closure *closure, bool success);
void grpc_executor_push(grpc_closure *closure, grpc_error *error);
/** Shutdown the executor, running all pending work as part of the call */
void grpc_executor_shutdown();

@ -104,7 +104,6 @@ grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
} else if (overlapped == &socket->read_info.overlapped) {
info = &socket->read_info;
} else {
gpr_log(GPR_ERROR, "Unknown IOCP operation");
abort();
}
success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
@ -112,16 +111,7 @@ grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
info->bytes_transfered = bytes;
info->wsa_error = success ? 0 : WSAGetLastError();
GPR_ASSERT(overlapped == &info->overlapped);
GPR_ASSERT(!info->has_pending_iocp);
gpr_mu_lock(&socket->state_mu);
if (info->closure) {
closure = info->closure;
info->closure = NULL;
} else {
info->has_pending_iocp = 1;
}
gpr_mu_unlock(&socket->state_mu);
grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
grpc_socket_become_ready(exec_ctx, socket, info);
return GRPC_IOCP_WORK_WORK;
}
@ -176,33 +166,4 @@ void grpc_iocp_add_socket(grpc_winsocket *socket) {
GPR_ASSERT(ret == g_iocp);
}
/* Calling notify_on_read or write means either of two things:
-) The IOCP already completed in the background, and we need to call
the callback now.
-) The IOCP hasn't completed yet, and we're queuing it for later. */
static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx,
grpc_winsocket *socket, grpc_closure *closure,
grpc_winsocket_callback_info *info) {
GPR_ASSERT(info->closure == NULL);
gpr_mu_lock(&socket->state_mu);
if (info->has_pending_iocp) {
info->has_pending_iocp = 0;
grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
} else {
info->closure = closure;
}
gpr_mu_unlock(&socket->state_mu);
}
void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
grpc_winsocket *socket,
grpc_closure *closure) {
socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info);
}
void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
grpc_closure *closure) {
socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info);
}
#endif /* GPR_WINSOCK_SOCKET */

@ -52,12 +52,4 @@ void grpc_iocp_flush(void);
void grpc_iocp_shutdown(void);
void grpc_iocp_add_socket(grpc_winsocket *);
void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
grpc_winsocket *winsocket,
grpc_closure *closure);
void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx,
grpc_winsocket *winsocket,
grpc_closure *closure);
#endif /* GRPC_CORE_LIB_IOMGR_IOCP_WINDOWS_H */

@ -31,7 +31,7 @@
*
*/
#include "src/core/lib/support/load_file.h"
#include "src/core/lib/iomgr/load_file.h"
#include <errno.h>
#include <string.h>
@ -43,21 +43,19 @@
#include "src/core/lib/support/block_annotate.h"
#include "src/core/lib/support/string.h"
gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
int *success) {
grpc_error *grpc_load_file(const char *filename, int add_null_terminator,
gpr_slice *output) {
unsigned char *contents = NULL;
size_t contents_size = 0;
char *error_msg = NULL;
gpr_slice result = gpr_empty_slice();
FILE *file;
size_t bytes_read = 0;
grpc_error *error = GRPC_ERROR_NONE;
GRPC_SCHEDULING_START_BLOCKING_REGION;
file = fopen(filename, "rb");
if (file == NULL) {
gpr_asprintf(&error_msg, "Could not open file %s (error = %s).", filename,
strerror(errno));
GPR_ASSERT(error_msg != NULL);
error = GRPC_OS_ERROR(errno, "fopen");
goto end;
}
fseek(file, 0, SEEK_END);
@ -67,25 +65,25 @@ gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0));
bytes_read = fread(contents, 1, contents_size, file);
if (bytes_read < contents_size) {
error = GRPC_OS_ERROR(errno, "fread");
GPR_ASSERT(ferror(file));
gpr_asprintf(&error_msg, "Error %s occured while reading file %s.",
strerror(errno), filename);
GPR_ASSERT(error_msg != NULL);
goto end;
}
if (success != NULL) *success = 1;
if (add_null_terminator) {
contents[contents_size++] = 0;
}
result = gpr_slice_new(contents, contents_size, gpr_free);
end:
if (error_msg != NULL) {
gpr_log(GPR_ERROR, "%s", error_msg);
gpr_free(error_msg);
if (success != NULL) *success = 0;
}
*output = result;
if (file != NULL) fclose(file);
if (error != GRPC_ERROR_NONE) {
grpc_error *error_out = grpc_error_set_str(
GRPC_ERROR_CREATE_REFERENCING("Failed to load file", &error, 1),
GRPC_ERROR_STR_FILENAME, filename);
GRPC_ERROR_UNREF(error);
error = error_out;
}
GRPC_SCHEDULING_END_BLOCKING_REGION;
return result;
return error;
}

@ -31,25 +31,26 @@
*
*/
#ifndef GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H
#define GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H
#ifndef GRPC_CORE_LIB_IOMGR_LOAD_FILE_H
#define GRPC_CORE_LIB_IOMGR_LOAD_FILE_H
#include <stdio.h>
#include <grpc/support/slice.h>
#include "src/core/lib/iomgr/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Loads the content of a file into a slice. add_null_terminator will add
a NULL terminator if non-zero. The success parameter, if not NULL,
will be set to 1 in case of success and 0 in case of failure. */
gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
int *success);
a NULL terminator if non-zero. */
grpc_error *grpc_load_file(const char *filename, int add_null_terminator,
gpr_slice *slice);
#ifdef __cplusplus
}
#endif
#endif /* GRPC_CORE_LIB_SUPPORT_LOAD_FILE_H */
#endif /* GRPC_CORE_LIB_IOMGR_LOAD_FILE_H */

@ -81,14 +81,15 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
May call grpc_closure_list_run on grpc_closure_list, without holding the
pollset
lock */
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now,
gpr_timespec deadline);
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now,
gpr_timespec deadline) GRPC_MUST_USE_RESULT;
/* Break one polling thread out of polling work for this pollset.
If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers.
Otherwise, if specific_worker is non-NULL, then kick that worker. */
void grpc_pollset_kick(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker);
grpc_error *grpc_pollset_kick(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker)
GRPC_MUST_USE_RESULT;
#endif /* GRPC_CORE_LIB_IOMGR_POLLSET_H */

@ -109,7 +109,7 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
pollset->shutting_down = 1;
grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
if (!pollset->is_iocp_worker) {
grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
} else {
pollset->on_shutdown = closure;
}
@ -127,9 +127,9 @@ void grpc_pollset_reset(grpc_pollset *pollset) {
pollset->on_shutdown = NULL;
}
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl, gpr_timespec now,
gpr_timespec deadline) {
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl,
gpr_timespec now, gpr_timespec deadline) {
grpc_pollset_worker worker;
*worker_hdl = &worker;
@ -167,7 +167,8 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
}
if (pollset->shutting_down && pollset->on_shutdown != NULL) {
grpc_exec_ctx_enqueue(exec_ctx, pollset->on_shutdown, true, NULL);
grpc_exec_ctx_sched(exec_ctx, pollset->on_shutdown, GRPC_ERROR_NONE,
NULL);
pollset->on_shutdown = NULL;
}
goto done;
@ -197,9 +198,11 @@ done:
}
gpr_cv_destroy(&worker.cv);
*worker_hdl = NULL;
return GRPC_ERROR_NONE;
}
void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
grpc_error *grpc_pollset_kick(grpc_pollset *p,
grpc_pollset_worker *specific_worker) {
if (specific_worker != NULL) {
if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) {
for (specific_worker =
@ -233,6 +236,7 @@ void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
p->kicked_without_pollers = 1;
}
}
return GRPC_ERROR_NONE;
}
void grpc_kick_poller(void) { grpc_iocp_kick(); }

@ -50,24 +50,20 @@ typedef struct {
grpc_resolved_address *addrs;
} grpc_resolved_addresses;
/* Async result callback:
On success: addresses is the result, and the callee must call
grpc_resolved_addresses_destroy when it's done with them
On failure: addresses is NULL */
typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses);
/* Asynchronously resolve addr. Use default_port if a port isn't designated
in addr, otherwise use the port in addr. */
/* TODO(ctiller): add a timeout here */
extern void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr,
const char *default_port,
grpc_resolve_cb cb, void *arg);
grpc_closure *on_done,
grpc_resolved_addresses **addresses);
/* Destroy resolved addresses */
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
/* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
result must be freed with grpc_resolved_addresses_destroy. */
extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port);
extern grpc_error *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses);
#endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */

@ -54,38 +54,33 @@
#include "src/core/lib/support/block_annotate.h"
#include "src/core/lib/support/string.h"
typedef struct {
char *name;
char *default_port;
grpc_resolve_cb cb;
grpc_closure request_closure;
void *arg;
} request;
static grpc_resolved_addresses *blocking_resolve_address_impl(
const char *name, const char *default_port) {
static grpc_error *blocking_resolve_address_impl(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses) {
struct addrinfo hints;
struct addrinfo *result = NULL, *resp;
char *host;
char *port;
int s;
size_t i;
grpc_resolved_addresses *addrs = NULL;
grpc_error *err;
if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
name[4] == ':' && name[5] != 0) {
return grpc_resolve_unix_domain_address(name + 5);
return grpc_resolve_unix_domain_address(name + 5, addresses);
}
/* parse name, splitting it into host and port parts */
gpr_split_host_port(name, &host, &port);
if (host == NULL) {
gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
err = grpc_error_set_str(GRPC_ERROR_CREATE("unparseable host:port"),
GRPC_ERROR_STR_TARGET_ADDRESS, name);
goto done;
}
if (port == NULL) {
if (default_port == NULL) {
gpr_log(GPR_ERROR, "no port in name '%s'", name);
err = grpc_error_set_str(GRPC_ERROR_CREATE("no port in name"),
GRPC_ERROR_STR_TARGET_ADDRESS, name);
goto done;
}
port = gpr_strdup(default_port);
@ -115,23 +110,31 @@ static grpc_resolved_addresses *blocking_resolve_address_impl(
}
if (s != 0) {
gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
err = grpc_error_set_str(
grpc_error_set_str(
grpc_error_set_str(grpc_error_set_int(GRPC_ERROR_CREATE("OS Error"),
GRPC_ERROR_INT_ERRNO, s),
GRPC_ERROR_STR_OS_ERROR, gai_strerror(s)),
GRPC_ERROR_STR_SYSCALL, "getaddrinfo"),
GRPC_ERROR_STR_TARGET_ADDRESS, name);
goto done;
}
/* Success path: set addrs non-NULL, fill it in */
addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
addrs->naddrs = 0;
*addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
(*addresses)->naddrs = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
addrs->naddrs++;
(*addresses)->naddrs++;
}
addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
(*addresses)->addrs =
gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
i = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
addrs->addrs[i].len = resp->ai_addrlen;
memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
(*addresses)->addrs[i].len = resp->ai_addrlen;
i++;
}
err = GRPC_ERROR_NONE;
done:
gpr_free(host);
@ -139,45 +142,59 @@ done:
if (result) {
freeaddrinfo(result);
}
return addrs;
return err;
}
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port) = blocking_resolve_address_impl;
grpc_error *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses) = blocking_resolve_address_impl;
typedef struct {
char *name;
char *default_port;
grpc_closure *on_done;
grpc_resolved_addresses **addrs_out;
grpc_closure request_closure;
void *arg;
} request;
/* Callback to be passed to grpc_executor to asynch-ify
* grpc_blocking_resolve_address */
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp,
grpc_error *error) {
request *r = rp;
grpc_resolved_addresses *resolved =
grpc_blocking_resolve_address(r->name, r->default_port);
void *arg = r->arg;
grpc_resolve_cb cb = r->cb;
grpc_exec_ctx_sched(
exec_ctx, r->on_done,
grpc_blocking_resolve_address(r->name, r->default_port, r->addrs_out),
NULL);
gpr_free(r->name);
gpr_free(r->default_port);
cb(exec_ctx, arg, resolved);
gpr_free(r);
}
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
gpr_free(addrs->addrs);
if (addrs != NULL) {
gpr_free(addrs->addrs);
}
gpr_free(addrs);
}
static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) {
const char *default_port,
grpc_closure *on_done,
grpc_resolved_addresses **addrs) {
request *r = gpr_malloc(sizeof(request));
grpc_closure_init(&r->request_closure, do_request_thread, r);
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->cb = cb;
r->arg = arg;
grpc_executor_enqueue(&r->request_closure, 1);
r->on_done = on_done;
r->addrs_out = addrs;
grpc_executor_push(&r->request_closure, GRPC_ERROR_NONE);
}
void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) = resolve_address_impl;
const char *default_port, grpc_closure *on_done,
grpc_resolved_addresses **addrs) =
resolve_address_impl;
#endif

@ -56,30 +56,37 @@
typedef struct {
char *name;
char *default_port;
grpc_resolve_cb cb;
grpc_closure request_closure;
void *arg;
grpc_closure *on_done;
grpc_resolved_addresses **addresses;
} request;
static grpc_resolved_addresses *blocking_resolve_address_impl(
const char *name, const char *default_port) {
static grpc_error *blocking_resolve_address_impl(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses) {
struct addrinfo hints;
struct addrinfo *result = NULL, *resp;
char *host;
char *port;
int s;
size_t i;
grpc_resolved_addresses *addrs = NULL;
grpc_error *error = GRPC_ERROR_NONE;
/* parse name, splitting it into host and port parts */
gpr_split_host_port(name, &host, &port);
if (host == NULL) {
gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
char *msg;
gpr_asprintf(&msg, "unparseable host:port: '%s'", name);
error = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
goto done;
}
if (port == NULL) {
if (default_port == NULL) {
gpr_log(GPR_ERROR, "no port in name '%s'", name);
char *msg;
gpr_asprintf(&msg, "no port in name '%s'", name);
error = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
goto done;
}
port = gpr_strdup(default_port);
@ -95,31 +102,30 @@ static grpc_resolved_addresses *blocking_resolve_address_impl(
s = getaddrinfo(host, port, &hints, &result);
GRPC_SCHEDULING_END_BLOCKING_REGION;
if (s != 0) {
char *error_message = gpr_format_message(s);
gpr_log(GPR_ERROR, "getaddrinfo: %s", error_message);
gpr_free(error_message);
error = GRPC_WSA_ERROR(WSAGetLastError(), "getaddrinfo");
goto done;
}
/* Success path: set addrs non-NULL, fill it in */
addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
addrs->naddrs = 0;
(*addresses) = gpr_malloc(sizeof(grpc_resolved_addresses));
(*addresses)->naddrs = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
addrs->naddrs++;
(*addresses)->naddrs++;
}
addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
(*addresses)->addrs =
gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
i = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
addrs->addrs[i].len = resp->ai_addrlen;
memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
(*addresses)->addrs[i].len = resp->ai_addrlen;
i++;
}
{
for (i = 0; i < addrs->naddrs; i++) {
for (i = 0; i < (*addresses)->naddrs; i++) {
char *buf;
grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr,
0);
grpc_sockaddr_to_string(
&buf, (struct sockaddr *)&(*addresses)->addrs[i].addr, 0);
gpr_free(buf);
}
}
@ -130,45 +136,53 @@ done:
if (result) {
freeaddrinfo(result);
}
return addrs;
return error;
}
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port) = blocking_resolve_address_impl;
grpc_error *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses) = blocking_resolve_address_impl;
/* Callback to be passed to grpc_executor to asynch-ify
* grpc_blocking_resolve_address */
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp,
grpc_error *error) {
request *r = rp;
grpc_resolved_addresses *resolved =
grpc_blocking_resolve_address(r->name, r->default_port);
void *arg = r->arg;
grpc_resolve_cb cb = r->cb;
if (error == GRPC_ERROR_NONE) {
error =
grpc_blocking_resolve_address(r->name, r->default_port, r->addresses);
} else {
GRPC_ERROR_REF(error);
}
grpc_exec_ctx_sched(exec_ctx, r->on_done, error, NULL);
gpr_free(r->name);
gpr_free(r->default_port);
cb(exec_ctx, arg, resolved);
gpr_free(r);
}
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
gpr_free(addrs->addrs);
if (addrs != NULL) {
gpr_free(addrs->addrs);
}
gpr_free(addrs);
}
static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) {
const char *default_port,
grpc_closure *on_done,
grpc_resolved_addresses **addresses) {
request *r = gpr_malloc(sizeof(request));
grpc_closure_init(&r->request_closure, do_request_thread, r);
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->cb = cb;
r->arg = arg;
grpc_executor_enqueue(&r->request_closure, 1);
r->on_done = on_done;
r->addresses = addresses;
grpc_executor_push(&r->request_closure, GRPC_ERROR_NONE);
}
void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) = resolve_address_impl;
const char *default_port, grpc_closure *on_done,
grpc_resolved_addresses **addresses) =
resolve_address_impl;
#endif

@ -49,6 +49,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
@ -57,10 +58,10 @@
#include "src/core/lib/support/string.h"
/* set a socket to non blocking mode */
int grpc_set_socket_nonblocking(int fd, int non_blocking) {
grpc_error *grpc_set_socket_nonblocking(int fd, int non_blocking) {
int oldflags = fcntl(fd, F_GETFL, 0);
if (oldflags < 0) {
return 0;
return GRPC_OS_ERROR(errno, "fcntl");
}
if (non_blocking) {
@ -70,62 +71,71 @@ int grpc_set_socket_nonblocking(int fd, int non_blocking) {
}
if (fcntl(fd, F_SETFL, oldflags) != 0) {
return 0;
return GRPC_OS_ERROR(errno, "fcntl");
}
return 1;
return GRPC_ERROR_NONE;
}
int grpc_set_socket_no_sigpipe_if_possible(int fd) {
grpc_error *grpc_set_socket_no_sigpipe_if_possible(int fd) {
#ifdef GPR_HAVE_SO_NOSIGPIPE
int val = 1;
int newval;
socklen_t intlen = sizeof(newval);
return 0 == setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val)) &&
0 == getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen) &&
(newval != 0) == val;
#else
return 1;
if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val))) {
return GRPC_OS_ERROR(errno, "setsockopt(SO_NOSIGPIPE)");
}
if (0 != getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen)) {
return GRPC_OS_ERROR(errno, "getsockopt(SO_NOSIGPIPE)");
}
if ((newval != 0) != (val != 0)) {
return GRPC_ERROR_CREATE("Failed to set SO_NOSIGPIPE");
}
#endif
return GRPC_ERROR_NONE;
}
int grpc_set_socket_ip_pktinfo_if_possible(int fd) {
grpc_error *grpc_set_socket_ip_pktinfo_if_possible(int fd) {
#ifdef GPR_HAVE_IP_PKTINFO
int get_local_ip = 1;
return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
sizeof(get_local_ip));
#else
(void)fd;
return 1;
if (0 != setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
sizeof(get_local_ip))) {
return GRPC_OS_ERROR(errno, "setsockopt(IP_PKTINFO)");
}
#endif
return GRPC_ERROR_NONE;
}
int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) {
grpc_error *grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) {
#ifdef GPR_HAVE_IPV6_RECVPKTINFO
int get_local_ip = 1;
return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
sizeof(get_local_ip));
#else
(void)fd;
return 1;
if (0 != setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
sizeof(get_local_ip))) {
return GRPC_OS_ERROR(errno, "setsockopt(IPV6_RECVPKTINFO)");
}
#endif
return GRPC_ERROR_NONE;
}
int grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) {
grpc_error *grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) {
return 0 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes,
sizeof(buffer_size_bytes));
sizeof(buffer_size_bytes))
? GRPC_ERROR_NONE
: GRPC_OS_ERROR(errno, "setsockopt(SO_SNDBUF)");
}
int grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) {
grpc_error *grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) {
return 0 == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes,
sizeof(buffer_size_bytes));
sizeof(buffer_size_bytes))
? GRPC_ERROR_NONE
: GRPC_OS_ERROR(errno, "setsockopt(SO_RCVBUF)");
}
/* set a socket to close on exec */
int grpc_set_socket_cloexec(int fd, int close_on_exec) {
grpc_error *grpc_set_socket_cloexec(int fd, int close_on_exec) {
int oldflags = fcntl(fd, F_GETFD, 0);
if (oldflags < 0) {
return 0;
return GRPC_OS_ERROR(errno, "fcntl");
}
if (close_on_exec) {
@ -135,30 +145,45 @@ int grpc_set_socket_cloexec(int fd, int close_on_exec) {
}
if (fcntl(fd, F_SETFD, oldflags) != 0) {
return 0;
return GRPC_OS_ERROR(errno, "fcntl");
}
return 1;
return GRPC_ERROR_NONE;
}
/* set a socket to reuse old addresses */
int grpc_set_socket_reuse_addr(int fd, int reuse) {
grpc_error *grpc_set_socket_reuse_addr(int fd, int reuse) {
int val = (reuse != 0);
int newval;
socklen_t intlen = sizeof(newval);
return 0 == setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) &&
0 == getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen) &&
(newval != 0) == val;
if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEADDR)");
}
if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEADDR)");
}
if ((newval != 0) != val) {
return GRPC_ERROR_CREATE("Failed to set SO_REUSEADDR");
}
return GRPC_ERROR_NONE;
}
/* disable nagle */
int grpc_set_socket_low_latency(int fd, int low_latency) {
grpc_error *grpc_set_socket_low_latency(int fd, int low_latency) {
int val = (low_latency != 0);
int newval;
socklen_t intlen = sizeof(newval);
return 0 == setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) &&
0 == getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen) &&
(newval != 0) == val;
if (0 != setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val))) {
return GRPC_OS_ERROR(errno, "setsockopt(TCP_NODELAY)");
}
if (0 != getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen)) {
return GRPC_OS_ERROR(errno, "getsockopt(TCP_NODELAY)");
}
if ((newval != 0) != val) {
return GRPC_ERROR_CREATE("Failed to set TCP_NODELAY");
}
return GRPC_ERROR_NONE;
}
static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
@ -206,35 +231,47 @@ static int set_socket_dualstack(int fd) {
}
}
int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
int protocol, grpc_dualstack_mode *dsmode) {
static grpc_error *error_for_fd(int fd, const struct sockaddr *addr) {
if (fd >= 0) return GRPC_ERROR_NONE;
char *addr_str;
grpc_sockaddr_to_string(&addr_str, addr, 0);
grpc_error *err = grpc_error_set_str(GRPC_OS_ERROR(errno, "socket"),
GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
gpr_free(addr_str);
return err;
}
grpc_error *grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
int protocol,
grpc_dualstack_mode *dsmode,
int *newfd) {
int family = addr->sa_family;
if (family == AF_INET6) {
int fd;
if (grpc_ipv6_loopback_available()) {
fd = socket(family, type, protocol);
*newfd = socket(family, type, protocol);
} else {
fd = -1;
*newfd = -1;
errno = EAFNOSUPPORT;
}
/* Check if we've got a valid dualstack socket. */
if (fd >= 0 && set_socket_dualstack(fd)) {
if (*newfd >= 0 && set_socket_dualstack(*newfd)) {
*dsmode = GRPC_DSMODE_DUALSTACK;
return fd;
return GRPC_ERROR_NONE;
}
/* If this isn't an IPv4 address, then return whatever we've got. */
if (!grpc_sockaddr_is_v4mapped(addr, NULL)) {
*dsmode = GRPC_DSMODE_IPV6;
return fd;
return error_for_fd(*newfd, addr);
}
/* Fall back to AF_INET. */
if (fd >= 0) {
close(fd);
if (*newfd >= 0) {
close(*newfd);
}
family = AF_INET;
}
*dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
return socket(family, type, protocol);
*newfd = socket(family, type, protocol);
return error_for_fd(*newfd, addr);
}
#endif

@ -37,21 +37,23 @@
#include <sys/socket.h>
#include <unistd.h>
#include "src/core/lib/iomgr/error.h"
/* a wrapper for accept or accept4 */
int grpc_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
int nonblock, int cloexec);
/* set a socket to non blocking mode */
int grpc_set_socket_nonblocking(int fd, int non_blocking);
grpc_error *grpc_set_socket_nonblocking(int fd, int non_blocking);
/* set a socket to close on exec */
int grpc_set_socket_cloexec(int fd, int close_on_exec);
grpc_error *grpc_set_socket_cloexec(int fd, int close_on_exec);
/* set a socket to reuse old addresses */
int grpc_set_socket_reuse_addr(int fd, int reuse);
grpc_error *grpc_set_socket_reuse_addr(int fd, int reuse);
/* disable nagle */
int grpc_set_socket_low_latency(int fd, int low_latency);
grpc_error *grpc_set_socket_low_latency(int fd, int low_latency);
/* Returns true if this system can create AF_INET6 sockets bound to ::1.
The value is probed once, and cached for the life of the process.
@ -64,27 +66,22 @@ int grpc_set_socket_low_latency(int fd, int low_latency);
int grpc_ipv6_loopback_available(void);
/* Tries to set SO_NOSIGPIPE if available on this platform.
Returns 1 on success, 0 on failure.
If SO_NO_SIGPIPE is not available, returns 1. */
int grpc_set_socket_no_sigpipe_if_possible(int fd);
grpc_error *grpc_set_socket_no_sigpipe_if_possible(int fd);
/* Tries to set IP_PKTINFO if available on this platform.
Returns 1 on success, 0 on failure.
If IP_PKTINFO is not available, returns 1. */
int grpc_set_socket_ip_pktinfo_if_possible(int fd);
grpc_error *grpc_set_socket_ip_pktinfo_if_possible(int fd);
/* Tries to set IPV6_RECVPKTINFO if available on this platform.
Returns 1 on success, 0 on failure.
If IPV6_RECVPKTINFO is not available, returns 1. */
int grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd);
grpc_error *grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd);
/* Tries to set the socket's send buffer to given size.
Returns 1 on success, 0 on failure. */
int grpc_set_socket_sndbuf(int fd, int buffer_size_bytes);
/* Tries to set the socket's send buffer to given size. */
grpc_error *grpc_set_socket_sndbuf(int fd, int buffer_size_bytes);
/* Tries to set the socket's receive buffer to given size.
Returns 1 on success, 0 on failure. */
int grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes);
/* Tries to set the socket's receive buffer to given size. */
grpc_error *grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes);
/* An enum to keep track of IPv4/IPv6 socket modes.
@ -125,7 +122,9 @@ extern int grpc_forbid_dualstack_sockets_for_testing;
IPv4, so that bind() or connect() see the correct family.
Also, it's important to distinguish between DUALSTACK and IPV6 when
listening on the [::] wildcard address. */
int grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
int protocol, grpc_dualstack_mode *dsmode);
grpc_error *grpc_create_dualstack_socket(const struct sockaddr *addr, int type,
int protocol,
grpc_dualstack_mode *dsmode,
int *newfd);
#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H */

@ -91,10 +91,69 @@ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
closesocket(winsocket->socket);
}
void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
static void destroy(grpc_winsocket *winsocket) {
grpc_iomgr_unregister_object(&winsocket->iomgr_object);
gpr_mu_destroy(&winsocket->state_mu);
gpr_free(winsocket);
}
static bool check_destroyable(grpc_winsocket *winsocket) {
return winsocket->destroy_called == true &&
winsocket->write_info.closure == NULL &&
winsocket->read_info.closure == NULL;
}
void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
gpr_mu_lock(&winsocket->state_mu);
GPR_ASSERT(!winsocket->destroy_called);
winsocket->destroy_called = true;
bool should_destroy = check_destroyable(winsocket);
gpr_mu_unlock(&winsocket->state_mu);
if (should_destroy) destroy(winsocket);
}
/* Calling notify_on_read or write means either of two things:
-) The IOCP already completed in the background, and we need to call
the callback now.
-) The IOCP hasn't completed yet, and we're queuing it for later. */
static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx,
grpc_winsocket *socket, grpc_closure *closure,
grpc_winsocket_callback_info *info) {
GPR_ASSERT(info->closure == NULL);
gpr_mu_lock(&socket->state_mu);
if (info->has_pending_iocp) {
info->has_pending_iocp = 0;
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
} else {
info->closure = closure;
}
gpr_mu_unlock(&socket->state_mu);
}
void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
grpc_winsocket *socket,
grpc_closure *closure) {
socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info);
}
void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
grpc_closure *closure) {
socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info);
}
void grpc_socket_become_ready(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
grpc_winsocket_callback_info *info) {
GPR_ASSERT(!info->has_pending_iocp);
gpr_mu_lock(&socket->state_mu);
if (info->closure) {
grpc_exec_ctx_sched(exec_ctx, info->closure, GRPC_ERROR_NONE, NULL);
info->closure = NULL;
} else {
info->has_pending_iocp = 1;
}
bool should_destroy = check_destroyable(socket);
gpr_mu_unlock(&socket->state_mu);
if (should_destroy) destroy(socket);
}
#endif /* GPR_WINSOCK_SOCKET */

@ -81,6 +81,7 @@ typedef struct grpc_winsocket_callback_info {
is closer to what happens in posix world. */
typedef struct grpc_winsocket {
SOCKET socket;
bool destroy_called;
grpc_winsocket_callback_info write_info;
grpc_winsocket_callback_info read_info;
@ -108,4 +109,16 @@ void grpc_winsocket_shutdown(grpc_winsocket *socket);
/* Destroy a socket. Should only be called if there's no pending operation. */
void grpc_winsocket_destroy(grpc_winsocket *socket);
void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
grpc_winsocket *winsocket,
grpc_closure *closure);
void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx,
grpc_winsocket *winsocket,
grpc_closure *closure);
void grpc_socket_become_ready(grpc_exec_ctx *exec_ctx,
grpc_winsocket *winsocket,
grpc_winsocket_callback_info *ci);
#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H */

@ -71,33 +71,39 @@ typedef struct {
grpc_closure *closure;
} async_connect;
static int prepare_socket(const struct sockaddr *addr, int fd) {
if (fd < 0) {
goto error;
static grpc_error *prepare_socket(const struct sockaddr *addr, int fd) {
grpc_error *err = GRPC_ERROR_NONE;
GPR_ASSERT(fd >= 0);
err = grpc_set_socket_nonblocking(fd, 1);
if (err != GRPC_ERROR_NONE) goto error;
err = grpc_set_socket_cloexec(fd, 1);
if (err != GRPC_ERROR_NONE) goto error;
if (!grpc_is_unix_socket(addr)) {
err = grpc_set_socket_low_latency(fd, 1);
if (err != GRPC_ERROR_NONE) goto error;
}
if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
(!grpc_is_unix_socket(addr) && !grpc_set_socket_low_latency(fd, 1)) ||
!grpc_set_socket_no_sigpipe_if_possible(fd)) {
gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
strerror(errno));
goto error;
}
return 1;
err = grpc_set_socket_no_sigpipe_if_possible(fd);
if (err != GRPC_ERROR_NONE) goto error;
goto done;
error:
if (fd >= 0) {
close(fd);
}
return 0;
done:
return err;
}
static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
int done;
async_connect *ac = acp;
if (grpc_tcp_trace) {
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: success=%d", ac->addr_str,
success);
const char *str = grpc_error_string(error);
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
str);
grpc_error_free_string(str);
}
gpr_mu_lock(&ac->mu);
if (ac->fd != NULL) {
@ -112,7 +118,7 @@ static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
}
}
static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
async_connect *ac = acp;
int so_error = 0;
socklen_t so_error_size;
@ -122,9 +128,13 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
grpc_closure *closure = ac->closure;
grpc_fd *fd;
GRPC_ERROR_REF(error);
if (grpc_tcp_trace) {
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: success=%d",
ac->addr_str, success);
const char *str = grpc_error_string(error);
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
ac->addr_str, str);
grpc_error_free_string(str);
}
gpr_mu_lock(&ac->mu);
@ -136,15 +146,14 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
grpc_timer_cancel(exec_ctx, &ac->alarm);
gpr_mu_lock(&ac->mu);
if (success) {
if (error == GRPC_ERROR_NONE) {
do {
so_error_size = sizeof(so_error);
err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error,
&so_error_size);
} while (err < 0 && errno == EINTR);
if (err < 0) {
gpr_log(GPR_ERROR, "failed to connect to '%s': getsockopt(ERROR): %s",
ac->addr_str, strerror(errno));
error = GRPC_OS_ERROR(errno, "getsockopt");
goto finish;
} else if (so_error != 0) {
if (so_error == ENOBUFS) {
@ -169,14 +178,12 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
} else {
switch (so_error) {
case ECONNREFUSED:
gpr_log(
GPR_ERROR,
"failed to connect to '%s': socket error: connection refused",
ac->addr_str);
error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errno);
error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
"Connection refused");
break;
default:
gpr_log(GPR_ERROR, "failed to connect to '%s': socket error: %d",
ac->addr_str, so_error);
error = GRPC_OS_ERROR(errno, "getsockopt(SO_ERROR)");
break;
}
goto finish;
@ -188,8 +195,8 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
goto finish;
}
} else {
gpr_log(GPR_ERROR, "failed to connect to '%s': timeout occurred",
ac->addr_str);
error =
grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred");
goto finish;
}
@ -203,12 +210,18 @@ finish:
}
done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu);
if (error != GRPC_ERROR_NONE) {
error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION,
"Failed to connect to remote host");
error =
grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str);
}
if (done) {
gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_str);
gpr_free(ac);
}
grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
}
static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
@ -225,6 +238,7 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
grpc_fd *fdobj;
char *name;
char *addr_str;
grpc_error *error;
*ep = NULL;
@ -234,9 +248,10 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
addr_len = sizeof(addr6_v4mapped);
}
fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
if (fd < 0) {
gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
error = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
if (error != GRPC_ERROR_NONE) {
grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
return;
}
if (dsmode == GRPC_DSMODE_IPV4) {
/* If we got an AF_INET socket, map the address back to IPv4. */
@ -244,8 +259,8 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
addr = (struct sockaddr *)&addr4_copy;
addr_len = sizeof(addr4_copy);
}
if (!prepare_socket(addr, fd)) {
grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
if ((error = prepare_socket(addr, fd)) != GRPC_ERROR_NONE) {
grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
return;
}
@ -261,14 +276,14 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
if (err >= 0) {
*ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
goto done;
}
if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_OS_ERROR(errno, "connect"),
NULL);
goto done;
}

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

Loading…
Cancel
Save