Merge branch 'master' of https://github.com/grpc/grpc into more-bm-diff

pull/11034/head
ncteisen 8 years ago
commit bb8cc8814b
  1. 7
      BUILD
  2. 404
      CMakeLists.txt
  3. 106
      CONTRIBUTING.md
  4. 441
      Makefile
  5. 1
      Rakefile
  6. 1
      binding.gyp
  7. 31
      build.yaml
  8. 1
      config.m4
  9. 643
      config.w32
  10. 6
      doc/PROTOCOL-WEB.md
  11. 7
      gRPC-Core.podspec
  12. 2
      gRPC-ProtoRPC.podspec
  13. 2
      gRPC-RxLibrary.podspec
  14. 2
      gRPC.podspec
  15. 2
      grpc.def
  16. 3
      grpc.gemspec
  17. 14
      include/grpc++/create_channel.h
  18. 4
      include/grpc++/create_channel_posix.h
  19. 2
      include/grpc++/ext/health_check_service_server_builder_option.h
  20. 4
      include/grpc++/ext/proto_server_reflection_plugin.h
  21. 9
      include/grpc++/grpc++.h
  22. 2
      include/grpc++/health_check_service_interface.h
  23. 7
      include/grpc++/impl/codegen/client_context.h
  24. 5
      include/grpc++/impl/server_builder_plugin.h
  25. 15
      include/grpc++/resource_quota.h
  26. 5
      include/grpc++/security/auth_metadata_processor.h
  27. 2
      include/grpc++/security/credentials.h
  28. 11
      include/grpc++/security/server_credentials.h
  29. 46
      include/grpc++/server.h
  30. 45
      include/grpc++/server_builder.h
  31. 5
      include/grpc++/server_posix.h
  32. 12
      include/grpc++/support/channel_arguments.h
  33. 10
      include/grpc++/support/error_details.h
  34. 2
      include/grpc++/support/slice.h
  35. 4
      include/grpc++/test/server_context_test_spouse.h
  36. 6
      include/grpc/grpc.h
  37. 2
      include/grpc/support/log.h
  38. 2
      package.json
  39. 44
      package.xml
  40. 21
      src/compiler/php_generator.cc
  41. 320
      src/core/ext/census/intrusive_hash_map.c
  42. 167
      src/core/ext/census/intrusive_hash_map.h
  43. 63
      src/core/ext/census/intrusive_hash_map_internal.h
  44. 77
      src/core/ext/filters/client_channel/channel_connectivity.c
  45. 115
      src/core/ext/filters/client_channel/client_channel.c
  46. 6
      src/core/ext/filters/client_channel/client_channel.h
  47. 459
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
  48. 129
      src/core/ext/filters/client_channel/parse_address.c
  49. 6
      src/core/ext/filters/client_channel/parse_address.h
  50. 18
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
  51. 73
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
  52. 6
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
  53. 1
      src/core/ext/transport/chttp2/server/chttp2_server.c
  54. 4
      src/core/lib/http/httpcli.c
  55. 4
      src/core/lib/http/httpcli_security_connector.c
  56. 19
      src/core/lib/security/transport/security_connector.c
  57. 220
      src/core/lib/security/transport/security_handshaker.c
  58. 2
      src/cpp/common/version_cc.cc
  59. 4
      src/cpp/server/server_builder.cc
  60. 7
      src/csharp/.editorconfig
  61. 6
      src/csharp/Grpc.Auth/Grpc.Auth.csproj
  62. 8
      src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj
  63. 41
      src/csharp/Grpc.Core/Channel.cs
  64. 4
      src/csharp/Grpc.Core/Grpc.Core.csproj
  65. 5
      src/csharp/Grpc.Core/Internal/CallError.cs
  66. 11
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  67. 10
      src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
  68. 4
      src/csharp/Grpc.Core/Internal/NativeMethods.cs
  69. 6
      src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
  70. 2
      src/csharp/Grpc.Core/Version.csproj.include
  71. 4
      src/csharp/Grpc.Core/VersionInfo.cs
  72. 6
      src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
  73. 28
      src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
  74. 57
      src/csharp/Grpc.IntegrationTesting/Histogram.cs
  75. 26
      src/csharp/Grpc.IntegrationTesting/HistogramTest.cs
  76. 2
      src/csharp/Grpc.Microbenchmarks/.gitignore
  77. 28
      src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj
  78. 55
      src/csharp/Grpc.Microbenchmarks/Program.cs
  79. 106
      src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs
  80. 79
      src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs
  81. 6
      src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
  82. 8
      src/csharp/Grpc.sln
  83. 12
      src/csharp/build_packages_dotnetcli.bat
  84. 16
      src/csharp/build_packages_dotnetcli.sh
  85. 86
      src/csharp/ext/grpc_csharp_ext.c
  86. 64
      src/node/README.md
  87. 37
      src/node/ext/call.cc
  88. 1
      src/node/ext/call.h
  89. 4
      src/node/health_check/package.json
  90. 138
      src/node/index.js
  91. 266
      src/node/src/client.js
  92. 64
      src/node/src/common.js
  93. 24
      src/node/src/constants.js
  94. 63
      src/node/src/credentials.js
  95. 4
      src/node/src/grpc_extension.js
  96. 15
      src/node/src/metadata.js
  97. 9
      src/node/src/protobuf_js_5_common.js
  98. 9
      src/node/src/protobuf_js_6_common.js
  99. 445
      src/node/src/server.js
  100. 1
      src/node/test/common_test.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -51,9 +51,9 @@ load(
# This should be updated along with build.yaml
g_stands_for = "gregarious"
core_version = "3.0.0-dev"
core_version = "4.0.0-dev"
version = "1.4.0-dev"
version = "1.5.0-dev"
grpc_cc_library(
name = "gpr",
@ -282,6 +282,7 @@ grpc_cc_library(
"src/core/ext/census/grpc_filter.c",
"src/core/ext/census/grpc_plugin.c",
"src/core/ext/census/initialize.c",
"src/core/ext/census/intrusive_hash_map.c",
"src/core/ext/census/mlog.c",
"src/core/ext/census/operation.c",
"src/core/ext/census/placeholders.c",
@ -297,6 +298,8 @@ grpc_cc_library(
"src/core/ext/census/gen/census.pb.h",
"src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h",
"src/core/ext/census/intrusive_hash_map.h",
"src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",

@ -39,7 +39,7 @@
cmake_minimum_required(VERSION 2.8)
set(PACKAGE_NAME "grpc")
set(PACKAGE_VERSION "1.4.0-dev")
set(PACKAGE_VERSION "1.5.0-dev")
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
@ -375,6 +375,7 @@ add_dependencies(buildtests_c bdp_estimator_test)
add_dependencies(buildtests_c bin_decoder_test)
add_dependencies(buildtests_c bin_encoder_test)
add_dependencies(buildtests_c census_context_test)
add_dependencies(buildtests_c census_intrusive_hash_map_test)
add_dependencies(buildtests_c census_resource_test)
add_dependencies(buildtests_c census_trace_context_test)
add_dependencies(buildtests_c channel_create_test)
@ -481,6 +482,7 @@ add_dependencies(buildtests_c mlog_test)
add_dependencies(buildtests_c multiple_server_queues_test)
add_dependencies(buildtests_c murmur_hash_test)
add_dependencies(buildtests_c no_server_test)
add_dependencies(buildtests_c num_external_connectivity_watchers_test)
add_dependencies(buildtests_c parse_address_test)
add_dependencies(buildtests_c percent_encoding_test)
if(_gRPC_PLATFORM_LINUX)
@ -1157,6 +1159,7 @@ add_library(grpc
src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c
src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
@ -2048,6 +2051,7 @@ add_library(grpc_unsecure
src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c
src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
@ -2273,133 +2277,6 @@ add_library(grpc++
src/cpp/util/status.cc
src/cpp/util/string_ref.cc
src/cpp/util/time_cc.cc
src/core/lib/channel/channel_args.c
src/core/lib/channel/channel_stack.c
src/core/lib/channel/channel_stack_builder.c
src/core/lib/channel/connected_channel.c
src/core/lib/channel/handshaker.c
src/core/lib/channel/handshaker_factory.c
src/core/lib/channel/handshaker_registry.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/http/format_request.c
src/core/lib/http/httpcli.c
src/core/lib/http/parser.c
src/core/lib/iomgr/closure.c
src/core/lib/iomgr/combiner.c
src/core/lib/iomgr/endpoint.c
src/core/lib/iomgr/endpoint_pair_posix.c
src/core/lib/iomgr/endpoint_pair_uv.c
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
src/core/lib/iomgr/iomgr.c
src/core/lib/iomgr/iomgr_posix.c
src/core/lib/iomgr/iomgr_uv.c
src/core/lib/iomgr/iomgr_windows.c
src/core/lib/iomgr/is_epollexclusive_available.c
src/core/lib/iomgr/load_file.c
src/core/lib/iomgr/lockfree_event.c
src/core/lib/iomgr/network_status_tracker.c
src/core/lib/iomgr/polling_entity.c
src/core/lib/iomgr/pollset_set_uv.c
src/core/lib/iomgr/pollset_set_windows.c
src/core/lib/iomgr/pollset_uv.c
src/core/lib/iomgr/pollset_windows.c
src/core/lib/iomgr/resolve_address_posix.c
src/core/lib/iomgr/resolve_address_uv.c
src/core/lib/iomgr/resolve_address_windows.c
src/core/lib/iomgr/resource_quota.c
src/core/lib/iomgr/sockaddr_utils.c
src/core/lib/iomgr/socket_factory_posix.c
src/core/lib/iomgr/socket_mutator.c
src/core/lib/iomgr/socket_utils_common_posix.c
src/core/lib/iomgr/socket_utils_linux.c
src/core/lib/iomgr/socket_utils_posix.c
src/core/lib/iomgr/socket_utils_uv.c
src/core/lib/iomgr/socket_utils_windows.c
src/core/lib/iomgr/socket_windows.c
src/core/lib/iomgr/tcp_client_posix.c
src/core/lib/iomgr/tcp_client_uv.c
src/core/lib/iomgr/tcp_client_windows.c
src/core/lib/iomgr/tcp_posix.c
src/core/lib/iomgr/tcp_server_posix.c
src/core/lib/iomgr/tcp_server_utils_posix_common.c
src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c
src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c
src/core/lib/iomgr/tcp_server_uv.c
src/core/lib/iomgr/tcp_server_windows.c
src/core/lib/iomgr/tcp_uv.c
src/core/lib/iomgr/tcp_windows.c
src/core/lib/iomgr/time_averaged_stats.c
src/core/lib/iomgr/timer_generic.c
src/core/lib/iomgr/timer_heap.c
src/core/lib/iomgr/timer_manager.c
src/core/lib/iomgr/timer_uv.c
src/core/lib/iomgr/udp_server.c
src/core/lib/iomgr/unix_sockets_posix.c
src/core/lib/iomgr/unix_sockets_posix_noop.c
src/core/lib/iomgr/wakeup_fd_cv.c
src/core/lib/iomgr/wakeup_fd_eventfd.c
src/core/lib/iomgr/wakeup_fd_nospecial.c
src/core/lib/iomgr/wakeup_fd_pipe.c
src/core/lib/iomgr/wakeup_fd_posix.c
src/core/lib/iomgr/workqueue_uv.c
src/core/lib/iomgr/workqueue_windows.c
src/core/lib/json/json.c
src/core/lib/json/json_reader.c
src/core/lib/json/json_string.c
src/core/lib/json/json_writer.c
src/core/lib/slice/b64.c
src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c
src/core/lib/surface/byte_buffer.c
src/core/lib/surface/byte_buffer_reader.c
src/core/lib/surface/call.c
src/core/lib/surface/call_details.c
src/core/lib/surface/call_log_batch.c
src/core/lib/surface/channel.c
src/core/lib/surface/channel_init.c
src/core/lib/surface/channel_ping.c
src/core/lib/surface/channel_stack_type.c
src/core/lib/surface/completion_queue.c
src/core/lib/surface/completion_queue_factory.c
src/core/lib/surface/event_string.c
src/core/lib/surface/lame_client.cc
src/core/lib/surface/metadata_array.c
src/core/lib/surface/server.c
src/core/lib/surface/validate_metadata.c
src/core/lib/surface/version.c
src/core/lib/transport/bdp_estimator.c
src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c
src/core/lib/transport/error_utils.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/status_conversion.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c
src/core/lib/debug/trace.c
third_party/nanopb/pb_common.c
third_party/nanopb/pb_decode.c
third_party/nanopb/pb_encode.c
@ -2440,7 +2317,6 @@ target_link_libraries(grpc++
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc
gpr
)
foreach(_hdr
@ -2537,17 +2413,6 @@ foreach(_hdr
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
include/grpc/byte_buffer.h
include/grpc/byte_buffer_reader.h
include/grpc/compression.h
include/grpc/grpc.h
include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h
include/grpc/load_reporting.h
include/grpc/slice.h
include/grpc/slice_buffer.h
include/grpc/status.h
include/grpc/support/workaround_list.h
include/grpc++/impl/codegen/proto_utils.h
include/grpc++/impl/codegen/config_protobuf.h
)
@ -2606,6 +2471,34 @@ add_library(grpc++_cronet
src/cpp/util/status.cc
src/cpp/util/string_ref.cc
src/cpp/util/time_cc.cc
third_party/nanopb/pb_common.c
third_party/nanopb/pb_decode.c
third_party/nanopb/pb_encode.c
src/cpp/codegen/codegen_init.cc
src/core/ext/transport/chttp2/client/insecure/channel_create.c
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
src/core/ext/transport/chttp2/client/chttp2_connector.c
src/core/ext/transport/chttp2/transport/bin_decoder.c
src/core/ext/transport/chttp2/transport/bin_encoder.c
src/core/ext/transport/chttp2/transport/chttp2_plugin.c
src/core/ext/transport/chttp2/transport/chttp2_transport.c
src/core/ext/transport/chttp2/transport/frame_data.c
src/core/ext/transport/chttp2/transport/frame_goaway.c
src/core/ext/transport/chttp2/transport/frame_ping.c
src/core/ext/transport/chttp2/transport/frame_rst_stream.c
src/core/ext/transport/chttp2/transport/frame_settings.c
src/core/ext/transport/chttp2/transport/frame_window_update.c
src/core/ext/transport/chttp2/transport/hpack_encoder.c
src/core/ext/transport/chttp2/transport/hpack_parser.c
src/core/ext/transport/chttp2/transport/hpack_table.c
src/core/ext/transport/chttp2/transport/http2_settings.c
src/core/ext/transport/chttp2/transport/huffsyms.c
src/core/ext/transport/chttp2/transport/incoming_metadata.c
src/core/ext/transport/chttp2/transport/parsing.c
src/core/ext/transport/chttp2/transport/stream_lists.c
src/core/ext/transport/chttp2/transport/stream_map.c
src/core/ext/transport/chttp2/transport/varint.c
src/core/ext/transport/chttp2/transport/writing.c
src/core/lib/channel/channel_args.c
src/core/lib/channel/channel_stack.c
src/core/lib/channel/channel_stack_builder.c
@ -2733,34 +2626,6 @@ add_library(grpc++_cronet
src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c
src/core/lib/debug/trace.c
third_party/nanopb/pb_common.c
third_party/nanopb/pb_decode.c
third_party/nanopb/pb_encode.c
src/cpp/codegen/codegen_init.cc
src/core/ext/transport/chttp2/client/insecure/channel_create.c
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
src/core/ext/transport/chttp2/client/chttp2_connector.c
src/core/ext/transport/chttp2/transport/bin_decoder.c
src/core/ext/transport/chttp2/transport/bin_encoder.c
src/core/ext/transport/chttp2/transport/chttp2_plugin.c
src/core/ext/transport/chttp2/transport/chttp2_transport.c
src/core/ext/transport/chttp2/transport/frame_data.c
src/core/ext/transport/chttp2/transport/frame_goaway.c
src/core/ext/transport/chttp2/transport/frame_ping.c
src/core/ext/transport/chttp2/transport/frame_rst_stream.c
src/core/ext/transport/chttp2/transport/frame_settings.c
src/core/ext/transport/chttp2/transport/frame_window_update.c
src/core/ext/transport/chttp2/transport/hpack_encoder.c
src/core/ext/transport/chttp2/transport/hpack_parser.c
src/core/ext/transport/chttp2/transport/hpack_table.c
src/core/ext/transport/chttp2/transport/http2_settings.c
src/core/ext/transport/chttp2/transport/huffsyms.c
src/core/ext/transport/chttp2/transport/incoming_metadata.c
src/core/ext/transport/chttp2/transport/parsing.c
src/core/ext/transport/chttp2/transport/stream_lists.c
src/core/ext/transport/chttp2/transport/stream_map.c
src/core/ext/transport/chttp2/transport/varint.c
src/core/ext/transport/chttp2/transport/writing.c
src/core/ext/transport/chttp2/alpn/alpn.c
src/core/ext/filters/http/client/http_client_filter.c
src/core/ext/filters/http/http_filters_plugin.c
@ -2798,6 +2663,7 @@ add_library(grpc++_cronet
src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c
src/core/ext/census/intrusive_hash_map.c
src/core/ext/census/mlog.c
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
@ -2841,6 +2707,7 @@ target_link_libraries(grpc++_cronet
${_gRPC_ALLTARGETS_LIBRARIES}
gpr
grpc_cronet
grpc
)
foreach(_hdr
@ -3383,133 +3250,6 @@ add_library(grpc++_unsecure
src/cpp/util/status.cc
src/cpp/util/string_ref.cc
src/cpp/util/time_cc.cc
src/core/lib/channel/channel_args.c
src/core/lib/channel/channel_stack.c
src/core/lib/channel/channel_stack_builder.c
src/core/lib/channel/connected_channel.c
src/core/lib/channel/handshaker.c
src/core/lib/channel/handshaker_factory.c
src/core/lib/channel/handshaker_registry.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/http/format_request.c
src/core/lib/http/httpcli.c
src/core/lib/http/parser.c
src/core/lib/iomgr/closure.c
src/core/lib/iomgr/combiner.c
src/core/lib/iomgr/endpoint.c
src/core/lib/iomgr/endpoint_pair_posix.c
src/core/lib/iomgr/endpoint_pair_uv.c
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll1_linux.c
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
src/core/lib/iomgr/ev_epollex_linux.c
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
src/core/lib/iomgr/iomgr.c
src/core/lib/iomgr/iomgr_posix.c
src/core/lib/iomgr/iomgr_uv.c
src/core/lib/iomgr/iomgr_windows.c
src/core/lib/iomgr/is_epollexclusive_available.c
src/core/lib/iomgr/load_file.c
src/core/lib/iomgr/lockfree_event.c
src/core/lib/iomgr/network_status_tracker.c
src/core/lib/iomgr/polling_entity.c
src/core/lib/iomgr/pollset_set_uv.c
src/core/lib/iomgr/pollset_set_windows.c
src/core/lib/iomgr/pollset_uv.c
src/core/lib/iomgr/pollset_windows.c
src/core/lib/iomgr/resolve_address_posix.c
src/core/lib/iomgr/resolve_address_uv.c
src/core/lib/iomgr/resolve_address_windows.c
src/core/lib/iomgr/resource_quota.c
src/core/lib/iomgr/sockaddr_utils.c
src/core/lib/iomgr/socket_factory_posix.c
src/core/lib/iomgr/socket_mutator.c
src/core/lib/iomgr/socket_utils_common_posix.c
src/core/lib/iomgr/socket_utils_linux.c
src/core/lib/iomgr/socket_utils_posix.c
src/core/lib/iomgr/socket_utils_uv.c
src/core/lib/iomgr/socket_utils_windows.c
src/core/lib/iomgr/socket_windows.c
src/core/lib/iomgr/tcp_client_posix.c
src/core/lib/iomgr/tcp_client_uv.c
src/core/lib/iomgr/tcp_client_windows.c
src/core/lib/iomgr/tcp_posix.c
src/core/lib/iomgr/tcp_server_posix.c
src/core/lib/iomgr/tcp_server_utils_posix_common.c
src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c
src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c
src/core/lib/iomgr/tcp_server_uv.c
src/core/lib/iomgr/tcp_server_windows.c
src/core/lib/iomgr/tcp_uv.c
src/core/lib/iomgr/tcp_windows.c
src/core/lib/iomgr/time_averaged_stats.c
src/core/lib/iomgr/timer_generic.c
src/core/lib/iomgr/timer_heap.c
src/core/lib/iomgr/timer_manager.c
src/core/lib/iomgr/timer_uv.c
src/core/lib/iomgr/udp_server.c
src/core/lib/iomgr/unix_sockets_posix.c
src/core/lib/iomgr/unix_sockets_posix_noop.c
src/core/lib/iomgr/wakeup_fd_cv.c
src/core/lib/iomgr/wakeup_fd_eventfd.c
src/core/lib/iomgr/wakeup_fd_nospecial.c
src/core/lib/iomgr/wakeup_fd_pipe.c
src/core/lib/iomgr/wakeup_fd_posix.c
src/core/lib/iomgr/workqueue_uv.c
src/core/lib/iomgr/workqueue_windows.c
src/core/lib/json/json.c
src/core/lib/json/json_reader.c
src/core/lib/json/json_string.c
src/core/lib/json/json_writer.c
src/core/lib/slice/b64.c
src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_hash_table.c
src/core/lib/slice/slice_intern.c
src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c
src/core/lib/surface/byte_buffer.c
src/core/lib/surface/byte_buffer_reader.c
src/core/lib/surface/call.c
src/core/lib/surface/call_details.c
src/core/lib/surface/call_log_batch.c
src/core/lib/surface/channel.c
src/core/lib/surface/channel_init.c
src/core/lib/surface/channel_ping.c
src/core/lib/surface/channel_stack_type.c
src/core/lib/surface/completion_queue.c
src/core/lib/surface/completion_queue_factory.c
src/core/lib/surface/event_string.c
src/core/lib/surface/lame_client.cc
src/core/lib/surface/metadata_array.c
src/core/lib/surface/server.c
src/core/lib/surface/validate_metadata.c
src/core/lib/surface/version.c
src/core/lib/transport/bdp_estimator.c
src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c
src/core/lib/transport/error_utils.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/status_conversion.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c
src/core/lib/debug/trace.c
third_party/nanopb/pb_common.c
third_party/nanopb/pb_decode.c
third_party/nanopb/pb_encode.c
@ -3550,6 +3290,7 @@ target_link_libraries(grpc++_unsecure
${_gRPC_ALLTARGETS_LIBRARIES}
gpr
grpc_unsecure
grpc
)
foreach(_hdr
@ -3646,17 +3387,6 @@ foreach(_hdr
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
include/grpc/byte_buffer.h
include/grpc/byte_buffer_reader.h
include/grpc/compression.h
include/grpc/grpc.h
include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h
include/grpc/load_reporting.h
include/grpc/slice.h
include/grpc/slice_buffer.h
include/grpc/status.h
include/grpc/support/workaround_list.h
)
string(REPLACE "include/" "" _path ${_hdr})
get_filename_component(_path ${_path} PATH)
@ -5044,6 +4774,37 @@ target_link_libraries(census_context_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(census_intrusive_hash_map_test
test/core/census/intrusive_hash_map_test.c
)
target_include_directories(census_intrusive_hash_map_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(census_intrusive_hash_map_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(census_resource_test
test/core/census/resource_test.c
)
@ -7763,6 +7524,37 @@ target_link_libraries(no_server_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(num_external_connectivity_watchers_test
test/core/surface/num_external_connectivity_watchers_test.c
)
target_include_directories(num_external_connectivity_watchers_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(num_external_connectivity_watchers_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(parse_address_test
test/core/client_channel/parse_address_test.c
)

@ -1,74 +1,54 @@
# How to contribute
We definitely welcome patches and contribution to grpc! Here is some guideline
and information about how to do so.
We definitely welcome your patches and contributions to gRPC!
## Getting started
If you are new to github, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/)
### Legal requirements
## Legal requirements
In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).
### Technical requirements
## Running tests
Use `tools/run_tests/run_tests.py` script to run the unit tests.
See [tools/run_tests](tools/run_tests) for how to run tests for a given language.
Prerequisites for building and running tests are listed in [INSTALL.md](INSTALL.md)
and in `src/YOUR-LANGUAGE` (e.g. `src/csharp`)
## Generated project files
To ease maintenance of language- and platform- specific build systems,
many projects files are generated using templates and should not be edited
by hand.
Run `tools/buildgen/generate_projects.sh` to regenerate.
See [templates](templates) for details.
As a rule of thumb, if you see the "sanity tests" failing you've most likely edited generated files or you didn't regenerate the projects properly (or your code formatting doesn't match our code style).
## Guidelines for Pull Requests
How to get your contributions merged smoothly and quickly.
- Create **small PRs** that are narrowly focused on **addressing a single concern**. We often times receive PRs that are trying to fix several things at a time, but only one fix is considered acceptable, nothing gets merged and both author's & review's time is wasted. Create more PRs to address different concerns and everyone will be happy.
- For speculative changes, consider opening an issue and discussing it first. If you are suggesting a behavioral or API change, consider starting with a [gRFC proposal](https://github.com/grpc/proposal).
- Provide a good **PR description** as a record of **what** change is being made and **why** it was made. Link to a github issue if it exists.
- Don't fix code style and formatting unless you are already changing that line to address an issue. PRs with irrelevant changes won't be merged. If you do want to fix formatting or style, do that in a separate PR.
- Unless your PR is trivial, you should expect there will be reviewer comments that you'll need to address before merging. We expect you to be reasonably responsive to those comments, otherwise the PR will be closed after 2-3 weeks of inactivity.
- Maintain **clean commit history** and use **meaningful commit messages**. PRs with messy commit history are difficult to review and won't be merged. Use `rebase -i upstream/master` to curate your commit history and/or to bring in latest changes from master (but avoid rebasing in the middle of a code review).
- Keep your PR up to date with upstream/master (if there are merge conflicts, we can't really merge your change).
- if you are regenerating the projects using `tools/buildgen/generate_projects.sh`, make changes to generated files a separate commit with commit message `regenerate projects`. Mixing changes to generated and hand-written files make your PR difficult to review.
- **All tests need to be passing** before your change can be merged. We recommend you **run tests locally** before creating your PR to catch breakages early on (see [tools/run_tests](tools/run_tests). Ultimately, the green signal will be provided by our testing infrastructure. The reviewer will help you if there are test failures that seem not related to the change you are making.
- Exceptions to the rules can be made if there's a compelling reason for doing so.
You will need several tools to work with this repository. In addition to all of
the packages described in the [INSTALL](INSTALL.md) file, you will also need
python, and the mako template renderer. To install the latter, using pip, one
should simply be able to do `pip install mako`.
In order to run all of the tests we provide, you will need valgrind and clang.
More specifically, under debian, you will need the package libc++-dev to
properly run all the tests.
Compiling and running grpc C++ tests depend on protobuf 3.0.0, gtest and gflags.
Although gflags is provided in third_party, you will need to manually install
that dependency on your system to run these tests. Under a Debian or Ubuntu
system, you can install the gtests and gflags packages using apt-get:
```sh
$ [sudo] apt-get install libgflags-dev libgtest-dev
```
If you are planning to work on any of the languages other than C and C++, you
will also need their appropriate development environments.
If you want to work under Windows, we recommend the use of Visual Studio 2013.
The [Community or Express editions](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx)
are free and suitable for developing with grpc. Note however that our test
environment and tools are available for Unix environments only at the moment.
## Testing your changes
We provide a tool to help run the suite of tests in various environments.
In order to run most of the available tests, one would need to run:
`./tools/run_tests/run_tests.py`
If you want to run tests for any of the languages {c, c++, csharp, node, objc, php, python, ruby}, do this:
`./tools/run_tests/run_tests.py -l <lang>`
To know about the list of available commands, do this:
`./tools/run_tests/run_tests.py -h`
If you are running tests for ObjC on osx, follow these steps before running tests:
* install Xcode command-line tools by running
`sudo xcode-select --install`
* install macports from https://www.macports.org/install.php
* install autoconf, automake, libtool, gflags, cmake using macports
* restart your terminal window or run source ~/.bash_profile to pick up the new PATH changes.
## Adding or removing source code
Each language uses its own build system to work. Currently, the root's Makefile
and the Visual Studio project files are building only the C and C++ source code.
In order to ease the maintenance of these files, we have a
template system. Please do not contribute manual changes to any of the generated
files. Instead, modify the template files, or the build.yaml file, and
re-generate the project files using the following command:
`./tools/buildgen/generate_projects.sh`
You'll find more information about this in the [templates](templates) folder.

@ -423,8 +423,8 @@ Q = @
endif
CORE_VERSION = 4.0.0-dev
CPP_VERSION = 1.4.0-dev
CSHARP_VERSION = 1.4.0-dev
CPP_VERSION = 1.5.0-dev
CSHARP_VERSION = 1.5.0-dev
CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@ -967,6 +967,7 @@ bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
census_intrusive_hash_map_test: $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test
census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
@ -1062,6 +1063,7 @@ murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test
nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test
nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test
no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
num_external_connectivity_watchers_test: $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test
parse_address_test: $(BINDIR)/$(CONFIG)/parse_address_test
percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer
@ -1360,6 +1362,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/bin_decoder_test \
$(BINDIR)/$(CONFIG)/bin_encoder_test \
$(BINDIR)/$(CONFIG)/census_context_test \
$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test \
$(BINDIR)/$(CONFIG)/census_resource_test \
$(BINDIR)/$(CONFIG)/census_trace_context_test \
$(BINDIR)/$(CONFIG)/channel_create_test \
@ -1440,6 +1443,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/multiple_server_queues_test \
$(BINDIR)/$(CONFIG)/murmur_hash_test \
$(BINDIR)/$(CONFIG)/no_server_test \
$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test \
$(BINDIR)/$(CONFIG)/parse_address_test \
$(BINDIR)/$(CONFIG)/percent_encoding_test \
$(BINDIR)/$(CONFIG)/pollset_set_test \
@ -1763,6 +1767,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
$(E) "[RUN] Testing census_context_test"
$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
$(E) "[RUN] Testing census_intrusive_hash_map_test"
$(Q) $(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test || ( echo test census_intrusive_hash_map_test failed ; exit 1 )
$(E) "[RUN] Testing census_resource_test"
$(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 )
$(E) "[RUN] Testing census_trace_context_test"
@ -1907,6 +1913,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/murmur_hash_test || ( echo test murmur_hash_test failed ; exit 1 )
$(E) "[RUN] Testing no_server_test"
$(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 )
$(E) "[RUN] Testing num_external_connectivity_watchers_test"
$(Q) $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test || ( echo test num_external_connectivity_watchers_test failed ; exit 1 )
$(E) "[RUN] Testing parse_address_test"
$(Q) $(BINDIR)/$(CONFIG)/parse_address_test || ( echo test parse_address_test failed ; exit 1 )
$(E) "[RUN] Testing percent_encoding_test"
@ -3134,6 +3142,7 @@ LIBGRPC_SRC = \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
@ -3994,6 +4003,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
@ -4196,133 +4206,6 @@ LIBGRPC++_SRC = \
src/cpp/util/status.cc \
src/cpp/util/string_ref.cc \
src/cpp/util/time_cc.cc \
src/core/lib/channel/channel_args.c \
src/core/lib/channel/channel_stack.c \
src/core/lib/channel/channel_stack_builder.c \
src/core/lib/channel/connected_channel.c \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/handshaker_factory.c \
src/core/lib/channel/handshaker_registry.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/http/format_request.c \
src/core/lib/http/httpcli.c \
src/core/lib/http/parser.c \
src/core/lib/iomgr/closure.c \
src/core/lib/iomgr/combiner.c \
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_uv.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_uv.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/is_epollexclusive_available.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/lockfree_event.c \
src/core/lib/iomgr/network_status_tracker.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_uv.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_uv.c \
src/core/lib/iomgr/pollset_windows.c \
src/core/lib/iomgr/resolve_address_posix.c \
src/core/lib/iomgr/resolve_address_uv.c \
src/core/lib/iomgr/resolve_address_windows.c \
src/core/lib/iomgr/resource_quota.c \
src/core/lib/iomgr/sockaddr_utils.c \
src/core/lib/iomgr/socket_factory_posix.c \
src/core/lib/iomgr/socket_mutator.c \
src/core/lib/iomgr/socket_utils_common_posix.c \
src/core/lib/iomgr/socket_utils_linux.c \
src/core/lib/iomgr/socket_utils_posix.c \
src/core/lib/iomgr/socket_utils_uv.c \
src/core/lib/iomgr/socket_utils_windows.c \
src/core/lib/iomgr/socket_windows.c \
src/core/lib/iomgr/tcp_client_posix.c \
src/core/lib/iomgr/tcp_client_uv.c \
src/core/lib/iomgr/tcp_client_windows.c \
src/core/lib/iomgr/tcp_posix.c \
src/core/lib/iomgr/tcp_server_posix.c \
src/core/lib/iomgr/tcp_server_utils_posix_common.c \
src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \
src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \
src/core/lib/iomgr/tcp_server_uv.c \
src/core/lib/iomgr/tcp_server_windows.c \
src/core/lib/iomgr/tcp_uv.c \
src/core/lib/iomgr/tcp_windows.c \
src/core/lib/iomgr/time_averaged_stats.c \
src/core/lib/iomgr/timer_generic.c \
src/core/lib/iomgr/timer_heap.c \
src/core/lib/iomgr/timer_manager.c \
src/core/lib/iomgr/timer_uv.c \
src/core/lib/iomgr/udp_server.c \
src/core/lib/iomgr/unix_sockets_posix.c \
src/core/lib/iomgr/unix_sockets_posix_noop.c \
src/core/lib/iomgr/wakeup_fd_cv.c \
src/core/lib/iomgr/wakeup_fd_eventfd.c \
src/core/lib/iomgr/wakeup_fd_nospecial.c \
src/core/lib/iomgr/wakeup_fd_pipe.c \
src/core/lib/iomgr/wakeup_fd_posix.c \
src/core/lib/iomgr/workqueue_uv.c \
src/core/lib/iomgr/workqueue_windows.c \
src/core/lib/json/json.c \
src/core/lib/json/json_reader.c \
src/core/lib/json/json_string.c \
src/core/lib/json/json_writer.c \
src/core/lib/slice/b64.c \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \
src/core/lib/surface/byte_buffer.c \
src/core/lib/surface/byte_buffer_reader.c \
src/core/lib/surface/call.c \
src/core/lib/surface/call_details.c \
src/core/lib/surface/call_log_batch.c \
src/core/lib/surface/channel.c \
src/core/lib/surface/channel_init.c \
src/core/lib/surface/channel_ping.c \
src/core/lib/surface/channel_stack_type.c \
src/core/lib/surface/completion_queue.c \
src/core/lib/surface/completion_queue_factory.c \
src/core/lib/surface/event_string.c \
src/core/lib/surface/lame_client.cc \
src/core/lib/surface/metadata_array.c \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \
src/core/lib/debug/trace.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
@ -4422,17 +4305,6 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
include/grpc/byte_buffer.h \
include/grpc/byte_buffer_reader.h \
include/grpc/compression.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \
include/grpc/slice_buffer.h \
include/grpc/status.h \
include/grpc/support/workaround_list.h \
include/grpc++/impl/codegen/proto_utils.h \
include/grpc++/impl/codegen/config_protobuf.h \
@ -4471,18 +4343,18 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll -lgpr$(SHARED_VERSION_CORE)-dll
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll
else
$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
endif
@ -4537,6 +4409,34 @@ LIBGRPC++_CRONET_SRC = \
src/cpp/util/status.cc \
src/cpp/util/string_ref.cc \
src/cpp/util/time_cc.cc \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
src/cpp/codegen/codegen_init.cc \
src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
src/core/ext/transport/chttp2/client/chttp2_connector.c \
src/core/ext/transport/chttp2/transport/bin_decoder.c \
src/core/ext/transport/chttp2/transport/bin_encoder.c \
src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
src/core/ext/transport/chttp2/transport/chttp2_transport.c \
src/core/ext/transport/chttp2/transport/frame_data.c \
src/core/ext/transport/chttp2/transport/frame_goaway.c \
src/core/ext/transport/chttp2/transport/frame_ping.c \
src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
src/core/ext/transport/chttp2/transport/frame_settings.c \
src/core/ext/transport/chttp2/transport/frame_window_update.c \
src/core/ext/transport/chttp2/transport/hpack_encoder.c \
src/core/ext/transport/chttp2/transport/hpack_parser.c \
src/core/ext/transport/chttp2/transport/hpack_table.c \
src/core/ext/transport/chttp2/transport/http2_settings.c \
src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \
src/core/ext/transport/chttp2/transport/writing.c \
src/core/lib/channel/channel_args.c \
src/core/lib/channel/channel_stack.c \
src/core/lib/channel/channel_stack_builder.c \
@ -4664,34 +4564,6 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \
src/core/lib/debug/trace.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
src/cpp/codegen/codegen_init.cc \
src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
src/core/ext/transport/chttp2/client/chttp2_connector.c \
src/core/ext/transport/chttp2/transport/bin_decoder.c \
src/core/ext/transport/chttp2/transport/bin_encoder.c \
src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
src/core/ext/transport/chttp2/transport/chttp2_transport.c \
src/core/ext/transport/chttp2/transport/frame_data.c \
src/core/ext/transport/chttp2/transport/frame_goaway.c \
src/core/ext/transport/chttp2/transport/frame_ping.c \
src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
src/core/ext/transport/chttp2/transport/frame_settings.c \
src/core/ext/transport/chttp2/transport/frame_window_update.c \
src/core/ext/transport/chttp2/transport/hpack_encoder.c \
src/core/ext/transport/chttp2/transport/hpack_parser.c \
src/core/ext/transport/chttp2/transport/hpack_table.c \
src/core/ext/transport/chttp2/transport/http2_settings.c \
src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \
src/core/ext/transport/chttp2/transport/writing.c \
src/core/ext/transport/chttp2/alpn/alpn.c \
src/core/ext/filters/http/client/http_client_filter.c \
src/core/ext/filters/http/http_filters_plugin.c \
@ -4729,6 +4601,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
@ -4878,18 +4751,18 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll -lgrpc$(SHARED_VERSION_CORE)-dll
else
$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet -lgrpc
else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet -lgrpc
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
endif
@ -5304,133 +5177,6 @@ LIBGRPC++_UNSECURE_SRC = \
src/cpp/util/status.cc \
src/cpp/util/string_ref.cc \
src/cpp/util/time_cc.cc \
src/core/lib/channel/channel_args.c \
src/core/lib/channel/channel_stack.c \
src/core/lib/channel/channel_stack_builder.c \
src/core/lib/channel/connected_channel.c \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/handshaker_factory.c \
src/core/lib/channel/handshaker_registry.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/http/format_request.c \
src/core/lib/http/httpcli.c \
src/core/lib/http/parser.c \
src/core/lib/iomgr/closure.c \
src/core/lib/iomgr/combiner.c \
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_uv.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll1_linux.c \
src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
src/core/lib/iomgr/ev_epollex_linux.c \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_uv.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/is_epollexclusive_available.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/lockfree_event.c \
src/core/lib/iomgr/network_status_tracker.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_uv.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_uv.c \
src/core/lib/iomgr/pollset_windows.c \
src/core/lib/iomgr/resolve_address_posix.c \
src/core/lib/iomgr/resolve_address_uv.c \
src/core/lib/iomgr/resolve_address_windows.c \
src/core/lib/iomgr/resource_quota.c \
src/core/lib/iomgr/sockaddr_utils.c \
src/core/lib/iomgr/socket_factory_posix.c \
src/core/lib/iomgr/socket_mutator.c \
src/core/lib/iomgr/socket_utils_common_posix.c \
src/core/lib/iomgr/socket_utils_linux.c \
src/core/lib/iomgr/socket_utils_posix.c \
src/core/lib/iomgr/socket_utils_uv.c \
src/core/lib/iomgr/socket_utils_windows.c \
src/core/lib/iomgr/socket_windows.c \
src/core/lib/iomgr/tcp_client_posix.c \
src/core/lib/iomgr/tcp_client_uv.c \
src/core/lib/iomgr/tcp_client_windows.c \
src/core/lib/iomgr/tcp_posix.c \
src/core/lib/iomgr/tcp_server_posix.c \
src/core/lib/iomgr/tcp_server_utils_posix_common.c \
src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \
src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \
src/core/lib/iomgr/tcp_server_uv.c \
src/core/lib/iomgr/tcp_server_windows.c \
src/core/lib/iomgr/tcp_uv.c \
src/core/lib/iomgr/tcp_windows.c \
src/core/lib/iomgr/time_averaged_stats.c \
src/core/lib/iomgr/timer_generic.c \
src/core/lib/iomgr/timer_heap.c \
src/core/lib/iomgr/timer_manager.c \
src/core/lib/iomgr/timer_uv.c \
src/core/lib/iomgr/udp_server.c \
src/core/lib/iomgr/unix_sockets_posix.c \
src/core/lib/iomgr/unix_sockets_posix_noop.c \
src/core/lib/iomgr/wakeup_fd_cv.c \
src/core/lib/iomgr/wakeup_fd_eventfd.c \
src/core/lib/iomgr/wakeup_fd_nospecial.c \
src/core/lib/iomgr/wakeup_fd_pipe.c \
src/core/lib/iomgr/wakeup_fd_posix.c \
src/core/lib/iomgr/workqueue_uv.c \
src/core/lib/iomgr/workqueue_windows.c \
src/core/lib/json/json.c \
src/core/lib/json/json_reader.c \
src/core/lib/json/json_string.c \
src/core/lib/json/json_writer.c \
src/core/lib/slice/b64.c \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_hash_table.c \
src/core/lib/slice/slice_intern.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \
src/core/lib/surface/byte_buffer.c \
src/core/lib/surface/byte_buffer_reader.c \
src/core/lib/surface/call.c \
src/core/lib/surface/call_details.c \
src/core/lib/surface/call_log_batch.c \
src/core/lib/surface/channel.c \
src/core/lib/surface/channel_init.c \
src/core/lib/surface/channel_ping.c \
src/core/lib/surface/channel_stack_type.c \
src/core/lib/surface/completion_queue.c \
src/core/lib/surface/completion_queue_factory.c \
src/core/lib/surface/event_string.c \
src/core/lib/surface/lame_client.cc \
src/core/lib/surface/metadata_array.c \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/status_conversion.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \
src/core/lib/debug/trace.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
@ -5530,17 +5276,6 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
include/grpc/byte_buffer.h \
include/grpc/byte_buffer_reader.h \
include/grpc/compression.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \
include/grpc/slice_buffer.h \
include/grpc/status.h \
include/grpc/support/workaround_list.h \
LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC))))
@ -5567,18 +5302,18 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll -lgrpc$(SHARED_VERSION_CORE)-dll
else
$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE)
$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure -lgrpc
else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure -lgrpc
$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
endif
@ -8963,6 +8698,38 @@ endif
endif
CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC = \
test/core/census/intrusive_hash_map_test.c \
CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_INTRUSIVE_HASH_MAP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/census_intrusive_hash_map_test: $(CENSUS_INTRUSIVE_HASH_MAP_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) $(CENSUS_INTRUSIVE_HASH_MAP_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)/census_intrusive_hash_map_test
endif
$(OBJDIR)/$(CONFIG)/test/core/census/intrusive_hash_map_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_census_intrusive_hash_map_test: $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CENSUS_INTRUSIVE_HASH_MAP_TEST_OBJS:.o=.dep)
endif
endif
CENSUS_RESOURCE_TEST_SRC = \
test/core/census/resource_test.c \
@ -12003,6 +11770,38 @@ endif
endif
NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC = \
test/core/surface/num_external_connectivity_watchers_test.c \
NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_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) $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_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)/num_external_connectivity_watchers_test
endif
$(OBJDIR)/$(CONFIG)/test/core/surface/num_external_connectivity_watchers_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS:.o=.dep)
endif
endif
PARSE_ADDRESS_TEST_SRC = \
test/core/client_channel/parse_address_test.c \

@ -93,6 +93,7 @@ task 'dlls' do
[ w64, w32 ].each do |opt|
env_comp = "CC=#{opt[:cross]}-gcc "
env_comp += "CXX=#{opt[:cross]}-g++ "
env_comp += "LD=#{opt[:cross]}-gcc "
docker_for_windows "gem update --system && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}"
end

@ -890,6 +890,7 @@
'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c',
'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',

@ -14,7 +14,7 @@ settings:
'#10': See the expand_version.py for all the quirks here
core_version: 4.0.0-dev
g_stands_for: gregarious
version: 1.4.0-dev
version: 1.5.0-dev
filegroups:
- name: census
public_headers:
@ -27,6 +27,8 @@ filegroups:
- src/core/ext/census/gen/census.pb.h
- src/core/ext/census/gen/trace_context.pb.h
- src/core/ext/census/grpc_filter.h
- src/core/ext/census/intrusive_hash_map.h
- src/core/ext/census/intrusive_hash_map_internal.h
- src/core/ext/census/mlog.h
- src/core/ext/census/resource.h
- src/core/ext/census/rpc_metric_id.h
@ -45,6 +47,7 @@ filegroups:
- src/core/ext/census/grpc_filter.c
- src/core/ext/census/grpc_plugin.c
- src/core/ext/census/initialize.c
- src/core/ext/census/intrusive_hash_map.c
- src/core/ext/census/mlog.c
- src/core/ext/census/operation.c
- src/core/ext/census/placeholders.c
@ -960,9 +963,10 @@ filegroups:
- src/cpp/util/status.cc
- src/cpp/util/string_ref.cc
- src/cpp/util/time_cc.cc
deps:
- grpc
uses:
- grpc++_codegen_base
- grpc_base
- nanopb
- name: grpc++_codegen_base
language: c++
@ -1675,6 +1679,16 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: census_intrusive_hash_map_test
build: test
language: c
src:
- test/core/census/intrusive_hash_map_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: census_resource_test
build: test
language: c
@ -2693,6 +2707,18 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: num_external_connectivity_watchers_test
build: test
language: c
src:
- test/core/surface/num_external_connectivity_watchers_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
exclude_iomgrs:
- uv
- name: parse_address_test
build: test
language: c
@ -4629,6 +4655,7 @@ php_config_m4:
- grpc
- gpr
- boringssl
- z
headers:
- src/php/ext/grpc/byte_buffer.h
- src/php/ext/grpc/call.h

@ -322,6 +322,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \

@ -0,0 +1,643 @@
// $Id$
// vim:ft=javascript
ARG_WITH("grpc", "grpc support", "no");
if (PHP_GRPC != "no") {
grpc_source =
"src\\php\\ext\\grpc\\byte_buffer.c " +
"src\\php\\ext\\grpc\\call.c " +
"src\\php\\ext\\grpc\\call_credentials.c " +
"src\\php\\ext\\grpc\\channel.c " +
"src\\php\\ext\\grpc\\channel_credentials.c " +
"src\\php\\ext\\grpc\\completion_queue.c " +
"src\\php\\ext\\grpc\\php_grpc.c " +
"src\\php\\ext\\grpc\\server.c " +
"src\\php\\ext\\grpc\\server_credentials.c " +
"src\\php\\ext\\grpc\\timeval.c " +
"src\\core\\lib\\profiling\\basic_timers.c " +
"src\\core\\lib\\profiling\\stap_timers.c " +
"src\\core\\lib\\support\\alloc.c " +
"src\\core\\lib\\support\\arena.c " +
"src\\core\\lib\\support\\atm.c " +
"src\\core\\lib\\support\\avl.c " +
"src\\core\\lib\\support\\backoff.c " +
"src\\core\\lib\\support\\cmdline.c " +
"src\\core\\lib\\support\\cpu_iphone.c " +
"src\\core\\lib\\support\\cpu_linux.c " +
"src\\core\\lib\\support\\cpu_posix.c " +
"src\\core\\lib\\support\\cpu_windows.c " +
"src\\core\\lib\\support\\env_linux.c " +
"src\\core\\lib\\support\\env_posix.c " +
"src\\core\\lib\\support\\env_windows.c " +
"src\\core\\lib\\support\\histogram.c " +
"src\\core\\lib\\support\\host_port.c " +
"src\\core\\lib\\support\\log.c " +
"src\\core\\lib\\support\\log_android.c " +
"src\\core\\lib\\support\\log_linux.c " +
"src\\core\\lib\\support\\log_posix.c " +
"src\\core\\lib\\support\\log_windows.c " +
"src\\core\\lib\\support\\mpscq.c " +
"src\\core\\lib\\support\\murmur_hash.c " +
"src\\core\\lib\\support\\stack_lockfree.c " +
"src\\core\\lib\\support\\string.c " +
"src\\core\\lib\\support\\string_posix.c " +
"src\\core\\lib\\support\\string_util_windows.c " +
"src\\core\\lib\\support\\string_windows.c " +
"src\\core\\lib\\support\\subprocess_posix.c " +
"src\\core\\lib\\support\\subprocess_windows.c " +
"src\\core\\lib\\support\\sync.c " +
"src\\core\\lib\\support\\sync_posix.c " +
"src\\core\\lib\\support\\sync_windows.c " +
"src\\core\\lib\\support\\thd.c " +
"src\\core\\lib\\support\\thd_posix.c " +
"src\\core\\lib\\support\\thd_windows.c " +
"src\\core\\lib\\support\\time.c " +
"src\\core\\lib\\support\\time_posix.c " +
"src\\core\\lib\\support\\time_precise.c " +
"src\\core\\lib\\support\\time_windows.c " +
"src\\core\\lib\\support\\tls_pthread.c " +
"src\\core\\lib\\support\\tmpfile_msys.c " +
"src\\core\\lib\\support\\tmpfile_posix.c " +
"src\\core\\lib\\support\\tmpfile_windows.c " +
"src\\core\\lib\\support\\wrap_memcpy.c " +
"src\\core\\lib\\surface\\init.c " +
"src\\core\\lib\\channel\\channel_args.c " +
"src\\core\\lib\\channel\\channel_stack.c " +
"src\\core\\lib\\channel\\channel_stack_builder.c " +
"src\\core\\lib\\channel\\connected_channel.c " +
"src\\core\\lib\\channel\\handshaker.c " +
"src\\core\\lib\\channel\\handshaker_factory.c " +
"src\\core\\lib\\channel\\handshaker_registry.c " +
"src\\core\\lib\\compression\\compression.c " +
"src\\core\\lib\\compression\\message_compress.c " +
"src\\core\\lib\\http\\format_request.c " +
"src\\core\\lib\\http\\httpcli.c " +
"src\\core\\lib\\http\\parser.c " +
"src\\core\\lib\\iomgr\\closure.c " +
"src\\core\\lib\\iomgr\\combiner.c " +
"src\\core\\lib\\iomgr\\endpoint.c " +
"src\\core\\lib\\iomgr\\endpoint_pair_posix.c " +
"src\\core\\lib\\iomgr\\endpoint_pair_uv.c " +
"src\\core\\lib\\iomgr\\endpoint_pair_windows.c " +
"src\\core\\lib\\iomgr\\error.c " +
"src\\core\\lib\\iomgr\\ev_epoll1_linux.c " +
"src\\core\\lib\\iomgr\\ev_epoll_limited_pollers_linux.c " +
"src\\core\\lib\\iomgr\\ev_epoll_thread_pool_linux.c " +
"src\\core\\lib\\iomgr\\ev_epollex_linux.c " +
"src\\core\\lib\\iomgr\\ev_epollsig_linux.c " +
"src\\core\\lib\\iomgr\\ev_poll_posix.c " +
"src\\core\\lib\\iomgr\\ev_posix.c " +
"src\\core\\lib\\iomgr\\ev_windows.c " +
"src\\core\\lib\\iomgr\\exec_ctx.c " +
"src\\core\\lib\\iomgr\\executor.c " +
"src\\core\\lib\\iomgr\\iocp_windows.c " +
"src\\core\\lib\\iomgr\\iomgr.c " +
"src\\core\\lib\\iomgr\\iomgr_posix.c " +
"src\\core\\lib\\iomgr\\iomgr_uv.c " +
"src\\core\\lib\\iomgr\\iomgr_windows.c " +
"src\\core\\lib\\iomgr\\is_epollexclusive_available.c " +
"src\\core\\lib\\iomgr\\load_file.c " +
"src\\core\\lib\\iomgr\\lockfree_event.c " +
"src\\core\\lib\\iomgr\\network_status_tracker.c " +
"src\\core\\lib\\iomgr\\polling_entity.c " +
"src\\core\\lib\\iomgr\\pollset_set_uv.c " +
"src\\core\\lib\\iomgr\\pollset_set_windows.c " +
"src\\core\\lib\\iomgr\\pollset_uv.c " +
"src\\core\\lib\\iomgr\\pollset_windows.c " +
"src\\core\\lib\\iomgr\\resolve_address_posix.c " +
"src\\core\\lib\\iomgr\\resolve_address_uv.c " +
"src\\core\\lib\\iomgr\\resolve_address_windows.c " +
"src\\core\\lib\\iomgr\\resource_quota.c " +
"src\\core\\lib\\iomgr\\sockaddr_utils.c " +
"src\\core\\lib\\iomgr\\socket_factory_posix.c " +
"src\\core\\lib\\iomgr\\socket_mutator.c " +
"src\\core\\lib\\iomgr\\socket_utils_common_posix.c " +
"src\\core\\lib\\iomgr\\socket_utils_linux.c " +
"src\\core\\lib\\iomgr\\socket_utils_posix.c " +
"src\\core\\lib\\iomgr\\socket_utils_uv.c " +
"src\\core\\lib\\iomgr\\socket_utils_windows.c " +
"src\\core\\lib\\iomgr\\socket_windows.c " +
"src\\core\\lib\\iomgr\\tcp_client_posix.c " +
"src\\core\\lib\\iomgr\\tcp_client_uv.c " +
"src\\core\\lib\\iomgr\\tcp_client_windows.c " +
"src\\core\\lib\\iomgr\\tcp_posix.c " +
"src\\core\\lib\\iomgr\\tcp_server_posix.c " +
"src\\core\\lib\\iomgr\\tcp_server_utils_posix_common.c " +
"src\\core\\lib\\iomgr\\tcp_server_utils_posix_ifaddrs.c " +
"src\\core\\lib\\iomgr\\tcp_server_utils_posix_noifaddrs.c " +
"src\\core\\lib\\iomgr\\tcp_server_uv.c " +
"src\\core\\lib\\iomgr\\tcp_server_windows.c " +
"src\\core\\lib\\iomgr\\tcp_uv.c " +
"src\\core\\lib\\iomgr\\tcp_windows.c " +
"src\\core\\lib\\iomgr\\time_averaged_stats.c " +
"src\\core\\lib\\iomgr\\timer_generic.c " +
"src\\core\\lib\\iomgr\\timer_heap.c " +
"src\\core\\lib\\iomgr\\timer_manager.c " +
"src\\core\\lib\\iomgr\\timer_uv.c " +
"src\\core\\lib\\iomgr\\udp_server.c " +
"src\\core\\lib\\iomgr\\unix_sockets_posix.c " +
"src\\core\\lib\\iomgr\\unix_sockets_posix_noop.c " +
"src\\core\\lib\\iomgr\\wakeup_fd_cv.c " +
"src\\core\\lib\\iomgr\\wakeup_fd_eventfd.c " +
"src\\core\\lib\\iomgr\\wakeup_fd_nospecial.c " +
"src\\core\\lib\\iomgr\\wakeup_fd_pipe.c " +
"src\\core\\lib\\iomgr\\wakeup_fd_posix.c " +
"src\\core\\lib\\iomgr\\workqueue_uv.c " +
"src\\core\\lib\\iomgr\\workqueue_windows.c " +
"src\\core\\lib\\json\\json.c " +
"src\\core\\lib\\json\\json_reader.c " +
"src\\core\\lib\\json\\json_string.c " +
"src\\core\\lib\\json\\json_writer.c " +
"src\\core\\lib\\slice\\b64.c " +
"src\\core\\lib\\slice\\percent_encoding.c " +
"src\\core\\lib\\slice\\slice.c " +
"src\\core\\lib\\slice\\slice_buffer.c " +
"src\\core\\lib\\slice\\slice_hash_table.c " +
"src\\core\\lib\\slice\\slice_intern.c " +
"src\\core\\lib\\slice\\slice_string_helpers.c " +
"src\\core\\lib\\surface\\alarm.c " +
"src\\core\\lib\\surface\\api_trace.c " +
"src\\core\\lib\\surface\\byte_buffer.c " +
"src\\core\\lib\\surface\\byte_buffer_reader.c " +
"src\\core\\lib\\surface\\call.c " +
"src\\core\\lib\\surface\\call_details.c " +
"src\\core\\lib\\surface\\call_log_batch.c " +
"src\\core\\lib\\surface\\channel.c " +
"src\\core\\lib\\surface\\channel_init.c " +
"src\\core\\lib\\surface\\channel_ping.c " +
"src\\core\\lib\\surface\\channel_stack_type.c " +
"src\\core\\lib\\surface\\completion_queue.c " +
"src\\core\\lib\\surface\\completion_queue_factory.c " +
"src\\core\\lib\\surface\\event_string.c " +
"src\\core\\lib\\surface\\lame_client.cc " +
"src\\core\\lib\\surface\\metadata_array.c " +
"src\\core\\lib\\surface\\server.c " +
"src\\core\\lib\\surface\\validate_metadata.c " +
"src\\core\\lib\\surface\\version.c " +
"src\\core\\lib\\transport\\bdp_estimator.c " +
"src\\core\\lib\\transport\\byte_stream.c " +
"src\\core\\lib\\transport\\connectivity_state.c " +
"src\\core\\lib\\transport\\error_utils.c " +
"src\\core\\lib\\transport\\metadata.c " +
"src\\core\\lib\\transport\\metadata_batch.c " +
"src\\core\\lib\\transport\\pid_controller.c " +
"src\\core\\lib\\transport\\service_config.c " +
"src\\core\\lib\\transport\\static_metadata.c " +
"src\\core\\lib\\transport\\status_conversion.c " +
"src\\core\\lib\\transport\\timeout_encoding.c " +
"src\\core\\lib\\transport\\transport.c " +
"src\\core\\lib\\transport\\transport_op_string.c " +
"src\\core\\lib\\debug\\trace.c " +
"src\\core\\ext\\transport\\chttp2\\server\\secure\\server_secure_chttp2.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\bin_decoder.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\bin_encoder.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\chttp2_plugin.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\chttp2_transport.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\frame_data.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\frame_goaway.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\frame_ping.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\frame_rst_stream.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\frame_settings.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\frame_window_update.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\hpack_encoder.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\hpack_parser.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\hpack_table.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\http2_settings.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\huffsyms.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\incoming_metadata.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\parsing.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\stream_lists.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\stream_map.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\varint.c " +
"src\\core\\ext\\transport\\chttp2\\transport\\writing.c " +
"src\\core\\ext\\transport\\chttp2\\alpn\\alpn.c " +
"src\\core\\ext\\filters\\http\\client\\http_client_filter.c " +
"src\\core\\ext\\filters\\http\\http_filters_plugin.c " +
"src\\core\\ext\\filters\\http\\message_compress\\message_compress_filter.c " +
"src\\core\\ext\\filters\\http\\server\\http_server_filter.c " +
"src\\core\\lib\\http\\httpcli_security_connector.c " +
"src\\core\\lib\\security\\context\\security_context.c " +
"src\\core\\lib\\security\\credentials\\composite\\composite_credentials.c " +
"src\\core\\lib\\security\\credentials\\credentials.c " +
"src\\core\\lib\\security\\credentials\\credentials_metadata.c " +
"src\\core\\lib\\security\\credentials\\fake\\fake_credentials.c " +
"src\\core\\lib\\security\\credentials\\google_default\\credentials_generic.c " +
"src\\core\\lib\\security\\credentials\\google_default\\google_default_credentials.c " +
"src\\core\\lib\\security\\credentials\\iam\\iam_credentials.c " +
"src\\core\\lib\\security\\credentials\\jwt\\json_token.c " +
"src\\core\\lib\\security\\credentials\\jwt\\jwt_credentials.c " +
"src\\core\\lib\\security\\credentials\\jwt\\jwt_verifier.c " +
"src\\core\\lib\\security\\credentials\\oauth2\\oauth2_credentials.c " +
"src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.c " +
"src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.c " +
"src\\core\\lib\\security\\transport\\client_auth_filter.c " +
"src\\core\\lib\\security\\transport\\lb_targets_info.c " +
"src\\core\\lib\\security\\transport\\secure_endpoint.c " +
"src\\core\\lib\\security\\transport\\security_connector.c " +
"src\\core\\lib\\security\\transport\\security_handshaker.c " +
"src\\core\\lib\\security\\transport\\server_auth_filter.c " +
"src\\core\\lib\\security\\transport\\tsi_error.c " +
"src\\core\\lib\\security\\util\\json_util.c " +
"src\\core\\lib\\surface\\init_secure.c " +
"src\\core\\tsi\\fake_transport_security.c " +
"src\\core\\tsi\\ssl_transport_security.c " +
"src\\core\\tsi\\transport_security.c " +
"src\\core\\tsi\\transport_security_adapter.c " +
"src\\core\\ext\\transport\\chttp2\\server\\chttp2_server.c " +
"src\\core\\ext\\transport\\chttp2\\client\\secure\\secure_channel_create.c " +
"src\\core\\ext\\filters\\client_channel\\channel_connectivity.c " +
"src\\core\\ext\\filters\\client_channel\\client_channel.c " +
"src\\core\\ext\\filters\\client_channel\\client_channel_factory.c " +
"src\\core\\ext\\filters\\client_channel\\client_channel_plugin.c " +
"src\\core\\ext\\filters\\client_channel\\connector.c " +
"src\\core\\ext\\filters\\client_channel\\http_connect_handshaker.c " +
"src\\core\\ext\\filters\\client_channel\\http_proxy.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy_factory.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy_registry.c " +
"src\\core\\ext\\filters\\client_channel\\parse_address.c " +
"src\\core\\ext\\filters\\client_channel\\proxy_mapper.c " +
"src\\core\\ext\\filters\\client_channel\\proxy_mapper_registry.c " +
"src\\core\\ext\\filters\\client_channel\\resolver.c " +
"src\\core\\ext\\filters\\client_channel\\resolver_factory.c " +
"src\\core\\ext\\filters\\client_channel\\resolver_registry.c " +
"src\\core\\ext\\filters\\client_channel\\retry_throttle.c " +
"src\\core\\ext\\filters\\client_channel\\subchannel.c " +
"src\\core\\ext\\filters\\client_channel\\subchannel_index.c " +
"src\\core\\ext\\filters\\client_channel\\uri_parser.c " +
"src\\core\\ext\\filters\\deadline\\deadline_filter.c " +
"src\\core\\ext\\transport\\chttp2\\client\\chttp2_connector.c " +
"src\\core\\ext\\transport\\chttp2\\server\\insecure\\server_chttp2.c " +
"src\\core\\ext\\transport\\chttp2\\server\\insecure\\server_chttp2_posix.c " +
"src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create.c " +
"src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create_posix.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\client_load_reporting_filter.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb_channel_secure.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb_client_stats.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\load_balancer_api.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\load_balancer.pb.c " +
"third_party\\nanopb\\pb_common.c " +
"third_party\\nanopb\\pb_decode.c " +
"third_party\\nanopb\\pb_encode.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first\\pick_first.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin\\round_robin.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native\\dns_resolver.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\sockaddr\\sockaddr_resolver.c " +
"src\\core\\ext\\filters\\load_reporting\\load_reporting.c " +
"src\\core\\ext\\filters\\load_reporting\\load_reporting_filter.c " +
"src\\core\\ext\\census\\base_resources.c " +
"src\\core\\ext\\census\\context.c " +
"src\\core\\ext\\census\\gen\\census.pb.c " +
"src\\core\\ext\\census\\gen\\trace_context.pb.c " +
"src\\core\\ext\\census\\grpc_context.c " +
"src\\core\\ext\\census\\grpc_filter.c " +
"src\\core\\ext\\census\\grpc_plugin.c " +
"src\\core\\ext\\census\\initialize.c " +
"src\\core\\ext\\census\\intrusive_hash_map.c " +
"src\\core\\ext\\census\\mlog.c " +
"src\\core\\ext\\census\\operation.c " +
"src\\core\\ext\\census\\placeholders.c " +
"src\\core\\ext\\census\\resource.c " +
"src\\core\\ext\\census\\trace_context.c " +
"src\\core\\ext\\census\\tracing.c " +
"src\\core\\ext\\filters\\max_age\\max_age_filter.c " +
"src\\core\\ext\\filters\\message_size\\message_size_filter.c " +
"src\\core\\ext\\filters\\workarounds\\workaround_cronet_compression_filter.c " +
"src\\core\\ext\\filters\\workarounds\\workaround_utils.c " +
"src\\core\\plugin_registry\\grpc_plugin_registry.c " +
"src\\boringssl\\err_data.c " +
"third_party\\boringssl\\crypto\\aes\\aes.c " +
"third_party\\boringssl\\crypto\\aes\\mode_wrappers.c " +
"third_party\\boringssl\\crypto\\asn1\\a_bitstr.c " +
"third_party\\boringssl\\crypto\\asn1\\a_bool.c " +
"third_party\\boringssl\\crypto\\asn1\\a_d2i_fp.c " +
"third_party\\boringssl\\crypto\\asn1\\a_dup.c " +
"third_party\\boringssl\\crypto\\asn1\\a_enum.c " +
"third_party\\boringssl\\crypto\\asn1\\a_gentm.c " +
"third_party\\boringssl\\crypto\\asn1\\a_i2d_fp.c " +
"third_party\\boringssl\\crypto\\asn1\\a_int.c " +
"third_party\\boringssl\\crypto\\asn1\\a_mbstr.c " +
"third_party\\boringssl\\crypto\\asn1\\a_object.c " +
"third_party\\boringssl\\crypto\\asn1\\a_octet.c " +
"third_party\\boringssl\\crypto\\asn1\\a_print.c " +
"third_party\\boringssl\\crypto\\asn1\\a_strnid.c " +
"third_party\\boringssl\\crypto\\asn1\\a_time.c " +
"third_party\\boringssl\\crypto\\asn1\\a_type.c " +
"third_party\\boringssl\\crypto\\asn1\\a_utctm.c " +
"third_party\\boringssl\\crypto\\asn1\\a_utf8.c " +
"third_party\\boringssl\\crypto\\asn1\\asn1_lib.c " +
"third_party\\boringssl\\crypto\\asn1\\asn1_par.c " +
"third_party\\boringssl\\crypto\\asn1\\asn_pack.c " +
"third_party\\boringssl\\crypto\\asn1\\f_enum.c " +
"third_party\\boringssl\\crypto\\asn1\\f_int.c " +
"third_party\\boringssl\\crypto\\asn1\\f_string.c " +
"third_party\\boringssl\\crypto\\asn1\\t_bitst.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_dec.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_enc.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_fre.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_new.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_typ.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_utl.c " +
"third_party\\boringssl\\crypto\\asn1\\x_bignum.c " +
"third_party\\boringssl\\crypto\\asn1\\x_long.c " +
"third_party\\boringssl\\crypto\\base64\\base64.c " +
"third_party\\boringssl\\crypto\\bio\\bio.c " +
"third_party\\boringssl\\crypto\\bio\\bio_mem.c " +
"third_party\\boringssl\\crypto\\bio\\buffer.c " +
"third_party\\boringssl\\crypto\\bio\\connect.c " +
"third_party\\boringssl\\crypto\\bio\\fd.c " +
"third_party\\boringssl\\crypto\\bio\\file.c " +
"third_party\\boringssl\\crypto\\bio\\hexdump.c " +
"third_party\\boringssl\\crypto\\bio\\pair.c " +
"third_party\\boringssl\\crypto\\bio\\printf.c " +
"third_party\\boringssl\\crypto\\bio\\socket.c " +
"third_party\\boringssl\\crypto\\bio\\socket_helper.c " +
"third_party\\boringssl\\crypto\\bn\\add.c " +
"third_party\\boringssl\\crypto\\bn\\asm\\x86_64-gcc.c " +
"third_party\\boringssl\\crypto\\bn\\bn.c " +
"third_party\\boringssl\\crypto\\bn\\bn_asn1.c " +
"third_party\\boringssl\\crypto\\bn\\cmp.c " +
"third_party\\boringssl\\crypto\\bn\\convert.c " +
"third_party\\boringssl\\crypto\\bn\\ctx.c " +
"third_party\\boringssl\\crypto\\bn\\div.c " +
"third_party\\boringssl\\crypto\\bn\\exponentiation.c " +
"third_party\\boringssl\\crypto\\bn\\gcd.c " +
"third_party\\boringssl\\crypto\\bn\\generic.c " +
"third_party\\boringssl\\crypto\\bn\\kronecker.c " +
"third_party\\boringssl\\crypto\\bn\\montgomery.c " +
"third_party\\boringssl\\crypto\\bn\\montgomery_inv.c " +
"third_party\\boringssl\\crypto\\bn\\mul.c " +
"third_party\\boringssl\\crypto\\bn\\prime.c " +
"third_party\\boringssl\\crypto\\bn\\random.c " +
"third_party\\boringssl\\crypto\\bn\\rsaz_exp.c " +
"third_party\\boringssl\\crypto\\bn\\shift.c " +
"third_party\\boringssl\\crypto\\bn\\sqrt.c " +
"third_party\\boringssl\\crypto\\buf\\buf.c " +
"third_party\\boringssl\\crypto\\bytestring\\asn1_compat.c " +
"third_party\\boringssl\\crypto\\bytestring\\ber.c " +
"third_party\\boringssl\\crypto\\bytestring\\cbb.c " +
"third_party\\boringssl\\crypto\\bytestring\\cbs.c " +
"third_party\\boringssl\\crypto\\chacha\\chacha.c " +
"third_party\\boringssl\\crypto\\cipher\\aead.c " +
"third_party\\boringssl\\crypto\\cipher\\cipher.c " +
"third_party\\boringssl\\crypto\\cipher\\derive_key.c " +
"third_party\\boringssl\\crypto\\cipher\\e_aes.c " +
"third_party\\boringssl\\crypto\\cipher\\e_chacha20poly1305.c " +
"third_party\\boringssl\\crypto\\cipher\\e_des.c " +
"third_party\\boringssl\\crypto\\cipher\\e_null.c " +
"third_party\\boringssl\\crypto\\cipher\\e_rc2.c " +
"third_party\\boringssl\\crypto\\cipher\\e_rc4.c " +
"third_party\\boringssl\\crypto\\cipher\\e_ssl3.c " +
"third_party\\boringssl\\crypto\\cipher\\e_tls.c " +
"third_party\\boringssl\\crypto\\cipher\\tls_cbc.c " +
"third_party\\boringssl\\crypto\\cmac\\cmac.c " +
"third_party\\boringssl\\crypto\\conf\\conf.c " +
"third_party\\boringssl\\crypto\\cpu-aarch64-linux.c " +
"third_party\\boringssl\\crypto\\cpu-arm-linux.c " +
"third_party\\boringssl\\crypto\\cpu-arm.c " +
"third_party\\boringssl\\crypto\\cpu-intel.c " +
"third_party\\boringssl\\crypto\\cpu-ppc64le.c " +
"third_party\\boringssl\\crypto\\crypto.c " +
"third_party\\boringssl\\crypto\\curve25519\\curve25519.c " +
"third_party\\boringssl\\crypto\\curve25519\\spake25519.c " +
"third_party\\boringssl\\crypto\\curve25519\\x25519-x86_64.c " +
"third_party\\boringssl\\crypto\\des\\des.c " +
"third_party\\boringssl\\crypto\\dh\\check.c " +
"third_party\\boringssl\\crypto\\dh\\dh.c " +
"third_party\\boringssl\\crypto\\dh\\dh_asn1.c " +
"third_party\\boringssl\\crypto\\dh\\params.c " +
"third_party\\boringssl\\crypto\\digest\\digest.c " +
"third_party\\boringssl\\crypto\\digest\\digests.c " +
"third_party\\boringssl\\crypto\\dsa\\dsa.c " +
"third_party\\boringssl\\crypto\\dsa\\dsa_asn1.c " +
"third_party\\boringssl\\crypto\\ec\\ec.c " +
"third_party\\boringssl\\crypto\\ec\\ec_asn1.c " +
"third_party\\boringssl\\crypto\\ec\\ec_key.c " +
"third_party\\boringssl\\crypto\\ec\\ec_montgomery.c " +
"third_party\\boringssl\\crypto\\ec\\oct.c " +
"third_party\\boringssl\\crypto\\ec\\p224-64.c " +
"third_party\\boringssl\\crypto\\ec\\p256-64.c " +
"third_party\\boringssl\\crypto\\ec\\p256-x86_64.c " +
"third_party\\boringssl\\crypto\\ec\\simple.c " +
"third_party\\boringssl\\crypto\\ec\\util-64.c " +
"third_party\\boringssl\\crypto\\ec\\wnaf.c " +
"third_party\\boringssl\\crypto\\ecdh\\ecdh.c " +
"third_party\\boringssl\\crypto\\ecdsa\\ecdsa.c " +
"third_party\\boringssl\\crypto\\ecdsa\\ecdsa_asn1.c " +
"third_party\\boringssl\\crypto\\engine\\engine.c " +
"third_party\\boringssl\\crypto\\err\\err.c " +
"third_party\\boringssl\\crypto\\evp\\digestsign.c " +
"third_party\\boringssl\\crypto\\evp\\evp.c " +
"third_party\\boringssl\\crypto\\evp\\evp_asn1.c " +
"third_party\\boringssl\\crypto\\evp\\evp_ctx.c " +
"third_party\\boringssl\\crypto\\evp\\p_dsa_asn1.c " +
"third_party\\boringssl\\crypto\\evp\\p_ec.c " +
"third_party\\boringssl\\crypto\\evp\\p_ec_asn1.c " +
"third_party\\boringssl\\crypto\\evp\\p_rsa.c " +
"third_party\\boringssl\\crypto\\evp\\p_rsa_asn1.c " +
"third_party\\boringssl\\crypto\\evp\\pbkdf.c " +
"third_party\\boringssl\\crypto\\evp\\print.c " +
"third_party\\boringssl\\crypto\\evp\\sign.c " +
"third_party\\boringssl\\crypto\\ex_data.c " +
"third_party\\boringssl\\crypto\\hkdf\\hkdf.c " +
"third_party\\boringssl\\crypto\\hmac\\hmac.c " +
"third_party\\boringssl\\crypto\\lhash\\lhash.c " +
"third_party\\boringssl\\crypto\\md4\\md4.c " +
"third_party\\boringssl\\crypto\\md5\\md5.c " +
"third_party\\boringssl\\crypto\\mem.c " +
"third_party\\boringssl\\crypto\\modes\\cbc.c " +
"third_party\\boringssl\\crypto\\modes\\cfb.c " +
"third_party\\boringssl\\crypto\\modes\\ctr.c " +
"third_party\\boringssl\\crypto\\modes\\gcm.c " +
"third_party\\boringssl\\crypto\\modes\\ofb.c " +
"third_party\\boringssl\\crypto\\newhope\\error_correction.c " +
"third_party\\boringssl\\crypto\\newhope\\newhope.c " +
"third_party\\boringssl\\crypto\\newhope\\ntt.c " +
"third_party\\boringssl\\crypto\\newhope\\poly.c " +
"third_party\\boringssl\\crypto\\newhope\\precomp.c " +
"third_party\\boringssl\\crypto\\newhope\\reduce.c " +
"third_party\\boringssl\\crypto\\obj\\obj.c " +
"third_party\\boringssl\\crypto\\obj\\obj_xref.c " +
"third_party\\boringssl\\crypto\\pem\\pem_all.c " +
"third_party\\boringssl\\crypto\\pem\\pem_info.c " +
"third_party\\boringssl\\crypto\\pem\\pem_lib.c " +
"third_party\\boringssl\\crypto\\pem\\pem_oth.c " +
"third_party\\boringssl\\crypto\\pem\\pem_pk8.c " +
"third_party\\boringssl\\crypto\\pem\\pem_pkey.c " +
"third_party\\boringssl\\crypto\\pem\\pem_x509.c " +
"third_party\\boringssl\\crypto\\pem\\pem_xaux.c " +
"third_party\\boringssl\\crypto\\pkcs8\\p5_pbe.c " +
"third_party\\boringssl\\crypto\\pkcs8\\p5_pbev2.c " +
"third_party\\boringssl\\crypto\\pkcs8\\p8_pkey.c " +
"third_party\\boringssl\\crypto\\pkcs8\\pkcs8.c " +
"third_party\\boringssl\\crypto\\poly1305\\poly1305.c " +
"third_party\\boringssl\\crypto\\poly1305\\poly1305_arm.c " +
"third_party\\boringssl\\crypto\\poly1305\\poly1305_vec.c " +
"third_party\\boringssl\\crypto\\rand\\deterministic.c " +
"third_party\\boringssl\\crypto\\rand\\rand.c " +
"third_party\\boringssl\\crypto\\rand\\urandom.c " +
"third_party\\boringssl\\crypto\\rand\\windows.c " +
"third_party\\boringssl\\crypto\\rc4\\rc4.c " +
"third_party\\boringssl\\crypto\\refcount_c11.c " +
"third_party\\boringssl\\crypto\\refcount_lock.c " +
"third_party\\boringssl\\crypto\\rsa\\blinding.c " +
"third_party\\boringssl\\crypto\\rsa\\padding.c " +
"third_party\\boringssl\\crypto\\rsa\\rsa.c " +
"third_party\\boringssl\\crypto\\rsa\\rsa_asn1.c " +
"third_party\\boringssl\\crypto\\rsa\\rsa_impl.c " +
"third_party\\boringssl\\crypto\\sha\\sha1.c " +
"third_party\\boringssl\\crypto\\sha\\sha256.c " +
"third_party\\boringssl\\crypto\\sha\\sha512.c " +
"third_party\\boringssl\\crypto\\stack\\stack.c " +
"third_party\\boringssl\\crypto\\thread.c " +
"third_party\\boringssl\\crypto\\thread_none.c " +
"third_party\\boringssl\\crypto\\thread_pthread.c " +
"third_party\\boringssl\\crypto\\thread_win.c " +
"third_party\\boringssl\\crypto\\time_support.c " +
"third_party\\boringssl\\crypto\\x509\\a_digest.c " +
"third_party\\boringssl\\crypto\\x509\\a_sign.c " +
"third_party\\boringssl\\crypto\\x509\\a_strex.c " +
"third_party\\boringssl\\crypto\\x509\\a_verify.c " +
"third_party\\boringssl\\crypto\\x509\\algorithm.c " +
"third_party\\boringssl\\crypto\\x509\\asn1_gen.c " +
"third_party\\boringssl\\crypto\\x509\\by_dir.c " +
"third_party\\boringssl\\crypto\\x509\\by_file.c " +
"third_party\\boringssl\\crypto\\x509\\i2d_pr.c " +
"third_party\\boringssl\\crypto\\x509\\pkcs7.c " +
"third_party\\boringssl\\crypto\\x509\\rsa_pss.c " +
"third_party\\boringssl\\crypto\\x509\\t_crl.c " +
"third_party\\boringssl\\crypto\\x509\\t_req.c " +
"third_party\\boringssl\\crypto\\x509\\t_x509.c " +
"third_party\\boringssl\\crypto\\x509\\t_x509a.c " +
"third_party\\boringssl\\crypto\\x509\\x509.c " +
"third_party\\boringssl\\crypto\\x509\\x509_att.c " +
"third_party\\boringssl\\crypto\\x509\\x509_cmp.c " +
"third_party\\boringssl\\crypto\\x509\\x509_d2.c " +
"third_party\\boringssl\\crypto\\x509\\x509_def.c " +
"third_party\\boringssl\\crypto\\x509\\x509_ext.c " +
"third_party\\boringssl\\crypto\\x509\\x509_lu.c " +
"third_party\\boringssl\\crypto\\x509\\x509_obj.c " +
"third_party\\boringssl\\crypto\\x509\\x509_r2x.c " +
"third_party\\boringssl\\crypto\\x509\\x509_req.c " +
"third_party\\boringssl\\crypto\\x509\\x509_set.c " +
"third_party\\boringssl\\crypto\\x509\\x509_trs.c " +
"third_party\\boringssl\\crypto\\x509\\x509_txt.c " +
"third_party\\boringssl\\crypto\\x509\\x509_v3.c " +
"third_party\\boringssl\\crypto\\x509\\x509_vfy.c " +
"third_party\\boringssl\\crypto\\x509\\x509_vpm.c " +
"third_party\\boringssl\\crypto\\x509\\x509cset.c " +
"third_party\\boringssl\\crypto\\x509\\x509name.c " +
"third_party\\boringssl\\crypto\\x509\\x509rset.c " +
"third_party\\boringssl\\crypto\\x509\\x509spki.c " +
"third_party\\boringssl\\crypto\\x509\\x509type.c " +
"third_party\\boringssl\\crypto\\x509\\x_algor.c " +
"third_party\\boringssl\\crypto\\x509\\x_all.c " +
"third_party\\boringssl\\crypto\\x509\\x_attrib.c " +
"third_party\\boringssl\\crypto\\x509\\x_crl.c " +
"third_party\\boringssl\\crypto\\x509\\x_exten.c " +
"third_party\\boringssl\\crypto\\x509\\x_info.c " +
"third_party\\boringssl\\crypto\\x509\\x_name.c " +
"third_party\\boringssl\\crypto\\x509\\x_pkey.c " +
"third_party\\boringssl\\crypto\\x509\\x_pubkey.c " +
"third_party\\boringssl\\crypto\\x509\\x_req.c " +
"third_party\\boringssl\\crypto\\x509\\x_sig.c " +
"third_party\\boringssl\\crypto\\x509\\x_spki.c " +
"third_party\\boringssl\\crypto\\x509\\x_val.c " +
"third_party\\boringssl\\crypto\\x509\\x_x509.c " +
"third_party\\boringssl\\crypto\\x509\\x_x509a.c " +
"third_party\\boringssl\\crypto\\x509v3\\pcy_cache.c " +
"third_party\\boringssl\\crypto\\x509v3\\pcy_data.c " +
"third_party\\boringssl\\crypto\\x509v3\\pcy_lib.c " +
"third_party\\boringssl\\crypto\\x509v3\\pcy_map.c " +
"third_party\\boringssl\\crypto\\x509v3\\pcy_node.c " +
"third_party\\boringssl\\crypto\\x509v3\\pcy_tree.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_akey.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_akeya.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_alt.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_bcons.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_bitst.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_conf.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_cpols.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_crld.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_enum.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_extku.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_genn.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_ia5.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_info.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_int.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_lib.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_ncons.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_pci.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_pcia.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_pcons.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_pku.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_pmaps.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_prn.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_purp.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_skey.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_sxnet.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_utl.c " +
"third_party\\boringssl\\ssl\\custom_extensions.c " +
"third_party\\boringssl\\ssl\\d1_both.c " +
"third_party\\boringssl\\ssl\\d1_lib.c " +
"third_party\\boringssl\\ssl\\d1_pkt.c " +
"third_party\\boringssl\\ssl\\d1_srtp.c " +
"third_party\\boringssl\\ssl\\dtls_method.c " +
"third_party\\boringssl\\ssl\\dtls_record.c " +
"third_party\\boringssl\\ssl\\handshake_client.c " +
"third_party\\boringssl\\ssl\\handshake_server.c " +
"third_party\\boringssl\\ssl\\s3_both.c " +
"third_party\\boringssl\\ssl\\s3_enc.c " +
"third_party\\boringssl\\ssl\\s3_lib.c " +
"third_party\\boringssl\\ssl\\s3_pkt.c " +
"third_party\\boringssl\\ssl\\ssl_aead_ctx.c " +
"third_party\\boringssl\\ssl\\ssl_asn1.c " +
"third_party\\boringssl\\ssl\\ssl_buffer.c " +
"third_party\\boringssl\\ssl\\ssl_cert.c " +
"third_party\\boringssl\\ssl\\ssl_cipher.c " +
"third_party\\boringssl\\ssl\\ssl_ecdh.c " +
"third_party\\boringssl\\ssl\\ssl_file.c " +
"third_party\\boringssl\\ssl\\ssl_lib.c " +
"third_party\\boringssl\\ssl\\ssl_rsa.c " +
"third_party\\boringssl\\ssl\\ssl_session.c " +
"third_party\\boringssl\\ssl\\ssl_stat.c " +
"third_party\\boringssl\\ssl\\t1_enc.c " +
"third_party\\boringssl\\ssl\\t1_lib.c " +
"third_party\\boringssl\\ssl\\tls13_both.c " +
"third_party\\boringssl\\ssl\\tls13_client.c " +
"third_party\\boringssl\\ssl\\tls13_enc.c " +
"third_party\\boringssl\\ssl\\tls13_server.c " +
"third_party\\boringssl\\ssl\\tls_method.c " +
"third_party\\boringssl\\ssl\\tls_record.c " +
"third_party\\zlib\\adler32.c " +
"third_party\\zlib\\compress.c " +
"third_party\\zlib\\crc32.c " +
"third_party\\zlib\\deflate.c " +
"third_party\\zlib\\gzclose.c " +
"third_party\\zlib\\gzlib.c " +
"third_party\\zlib\\gzread.c " +
"third_party\\zlib\\gzwrite.c " +
"third_party\\zlib\\infback.c " +
"third_party\\zlib\\inffast.c " +
"third_party\\zlib\\inflate.c " +
"third_party\\zlib\\inftrees.c " +
"third_party\\zlib\\trees.c " +
"third_party\\zlib\\uncompr.c " +
"third_party\\zlib\\zutil.c " +
"";
EXTENSION("grpc", grpc_source, null,
"/DOPENSSL_NO_ASM /D_GNU_SOURCE /DWIN32_LEAN_AND_MEAN "+
"/D_HAS_EXCEPTIONS=0 /DNOMINMAX /DGRPC_ARES=0 /D_WIN32_WINNT=0x600 "+
"/I"+configure_module_dirname+" "+
"/I"+configure_module_dirname+"\\include "+
"/I"+configure_module_dirname+"\\src\\php\\ext\\grpc "+
"/I"+configure_module_dirname+"\\third_party\\boringssl\\include "+
"/I"+configure_module_dirname+"\\third_party\\zlib");
}

@ -37,6 +37,8 @@ Content-Type
1. application/grpc-web
* e.g. application/grpc-web+[proto, json, thrift]
* the sender should always specify the message format, e.g. +proto, +json
* the receiver should assume the default is "+proto" when the message format is missing in Content-Type (as "application/grpc-web")
2. application/grpc-web-text
* text-encoded streams of “application/grpc-web”
* e.g. application/grpc-web-text+[proto, thrift]
@ -101,10 +103,6 @@ to security policies with XHR
* While the server runtime will always base64-encode and flush gRPC messages
atomically the client library should not assume base64 padding always
happens at the boundary of message frames. That is, the implementation may send base64-encoded "chunks" with potential padding whenever the runtime needs to flush a byte buffer.
3. For binary trailers, when the content-type is set to
application/grpc-web-text, the extra base64 encoding specified
in [gRPC over HTTP2](http://www.grpc.io/docs/guides/wire.html)
for binary custom metadata is skipped.
# Other features

@ -37,7 +37,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
version = '1.4.0-dev'
version = '1.5.0-dev'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'http://www.grpc.io'
@ -463,6 +463,8 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/census.pb.h',
'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h',
'src/core/ext/census/intrusive_hash_map.h',
'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h',
@ -713,6 +715,7 @@ Pod::Spec.new do |s|
'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c',
'src/core/ext/census/initialize.c',
'src/core/ext/census/intrusive_hash_map.c',
'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
@ -946,6 +949,8 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/census.pb.h',
'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h',
'src/core/ext/census/intrusive_hash_map.h',
'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h',

@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
version = '1.4.0-dev'
version = '1.5.0-dev'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'http://www.grpc.io'

@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
version = '1.4.0-dev'
version = '1.5.0-dev'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'http://www.grpc.io'

@ -35,7 +35,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
version = '1.4.0-dev'
version = '1.5.0-dev'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'

@ -65,6 +65,7 @@ EXPORTS
grpc_alarm_cancel
grpc_alarm_destroy
grpc_channel_check_connectivity_state
grpc_channel_num_external_connectivity_watchers
grpc_channel_watch_connectivity_state
grpc_channel_create_call
grpc_channel_ping
@ -232,6 +233,7 @@ EXPORTS
gpr_histogram_merge_contents
gpr_join_host_port
gpr_split_host_port
gpr_log_severity_string
gpr_log
gpr_log_message
gpr_set_log_verbosity

@ -379,6 +379,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/gen/census.pb.h )
s.files += %w( src/core/ext/census/gen/trace_context.pb.h )
s.files += %w( src/core/ext/census/grpc_filter.h )
s.files += %w( src/core/ext/census/intrusive_hash_map.h )
s.files += %w( src/core/ext/census/intrusive_hash_map_internal.h )
s.files += %w( src/core/ext/census/mlog.h )
s.files += %w( src/core/ext/census/resource.h )
s.files += %w( src/core/ext/census/rpc_metric_id.h )
@ -629,6 +631,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/grpc_filter.c )
s.files += %w( src/core/ext/census/grpc_plugin.c )
s.files += %w( src/core/ext/census/initialize.c )
s.files += %w( src/core/ext/census/intrusive_hash_map.c )
s.files += %w( src/core/ext/census/mlog.c )
s.files += %w( src/core/ext/census/operation.c )
s.files += %w( src/core/ext/census/placeholders.c )

@ -43,23 +43,25 @@
namespace grpc {
/// Create a new \a Channel pointing to \a target
/// Create a new \a Channel pointing to \a target.
///
/// \param target The URI of the endpoint to connect to.
/// \param creds Credentials to use for the created channel. If it does not hold
/// an object or is invalid, a lame channel is returned.
/// \param creds Credentials to use for the created channel. If it does not
/// hold an object or is invalid, a lame channel (one on which all operations
/// fail) is returned.
std::shared_ptr<Channel> CreateChannel(
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds);
/// Create a new \em custom \a Channel pointing to \a target
/// Create a new \em custom \a Channel pointing to \a target.
///
/// \warning For advanced use and testing ONLY. Override default channel
/// arguments only if necessary.
///
/// \param target The URI of the endpoint to connect to.
/// \param creds Credentials to use for the created channel. If it does not hold
/// an object or is invalid, a lame channel is returned.
/// \param creds Credentials to use for the created channel. If it does not
/// hold an object or is invalid, a lame channel (one on which all operations
/// fail) is returned.
/// \param args Options for channel creation.
std::shared_ptr<Channel> CreateCustomChannel(
const grpc::string& target,

@ -44,7 +44,7 @@ namespace grpc {
#ifdef GPR_SUPPORT_CHANNELS_FROM_FD
/// Create a new \a Channel communicating over given file descriptor
/// Create a new \a Channel communicating over the given file descriptor.
///
/// \param target The name of the target.
/// \param fd The file descriptor representing a socket.
@ -52,7 +52,7 @@ std::shared_ptr<Channel> CreateInsecureChannelFromFd(const grpc::string& target,
int fd);
/// Create a new \a Channel communicating over given file descriptor with custom
/// channel arguments
/// channel arguments.
///
/// \param target The name of the target.
/// \param fd The file descriptor representing a socket.

@ -44,7 +44,7 @@ namespace grpc {
class HealthCheckServiceServerBuilderOption : public ServerBuilderOption {
public:
/// The ownership of hc will be taken and transferred to the grpc server.
/// The ownership of \a hc will be taken and transferred to the grpc server.
/// To explicitly disable default service, pass in a nullptr.
explicit HealthCheckServiceServerBuilderOption(
std::unique_ptr<HealthCheckServiceInterface> hc);

@ -59,8 +59,8 @@ class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin {
std::shared_ptr<grpc::ProtoServerReflection> reflection_service_;
};
/// Add proto reflection plugin to ServerBuilder. This function should be called
/// at the static initialization time.
/// Add proto reflection plugin to \a ServerBuilder.
/// This function should be called at the static initialization time.
void InitProtoReflectionServerBuilderPlugin();
} // namespace reflection

@ -34,18 +34,18 @@
/// \mainpage gRPC C++ API
///
/// The gRPC C++ API mainly consists of the following classes:
//
/// <br>
/// - grpc::Channel, which represents the connection to an endpoint. See [the
/// gRPC Concepts page](http://www.grpc.io/docs/guides/concepts.html) for more
/// details. Channels are created by the factory function grpc::CreateChannel.
//
///
/// - grpc::CompletionQueue, the producer-consumer queue used for all
/// asynchronous communication with the gRPC runtime.
//
///
/// - grpc::ClientContext and grpc::ServerContext, where optional configuration
/// for an RPC can be set, such as setting custom metadata to be conveyed to the
/// peer, compression settings, authentication, etc.
//
///
/// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder.
///
/// Streaming calls are handled with the streaming classes in
@ -76,6 +76,7 @@
// IWYU pragma: end_exports
namespace grpc {
/// Return gRPC library version.
grpc::string Version();
} // namespace grpc

@ -47,7 +47,7 @@ class HealthCheckServiceInterface {
public:
virtual ~HealthCheckServiceInterface() {}
/// Set or change the serving status of the given service_name.
/// Set or change the serving status of the given \a service_name.
virtual void SetServingStatus(const grpc::string& service_name,
bool serving) = 0;
/// Apply to all registered service names.

@ -307,7 +307,7 @@ class ClientContext {
/// Flag whether the initial metadata should be \a corked
///
/// If \a corked is true, then the initial metadata will be colasced with the
/// If \a corked is true, then the initial metadata will be coalesced with the
/// write of first message in the stream.
///
/// \param corked The flag indicating whether the initial metadata is to be
@ -331,8 +331,9 @@ class ClientContext {
return census_context_;
}
/// Send a best-effort out-of-band cancel. The call could be in any stage.
/// e.g. if it is already finished, it may still return success.
/// Send a best-effort out-of-band cancel on the call associated with
/// this client context. The call could be in any stage; e.g., if it is
/// already finished, it may still return success.
///
/// There is no guarantee the call will be cancelled.
void TryCancel();

@ -40,6 +40,7 @@
namespace grpc {
class ServerBuilder;
class ServerInitializer;
class ChannelArguments;
@ -51,6 +52,10 @@ class ServerBuilderPlugin {
virtual ~ServerBuilderPlugin() {}
virtual grpc::string name() = 0;
/// UpdateServerBuilder will be called at the beginning of
/// \a ServerBuilder::BuildAndStart().
virtual void UpdateServerBuilder(ServerBuilder* builder) {}
/// InitServer will be called in ServerBuilder::BuildAndStart(), after the
/// Server instance is created.
virtual void InitServer(ServerInitializer* si) = 0;

@ -42,9 +42,10 @@ struct grpc_resource_quota;
namespace grpc {
/// ResourceQuota represents a bound on memory usage by the gRPC library.
/// A ResourceQuota can be attached to a server (via ServerBuilder), or a client
/// channel (via ChannelArguments). gRPC will attempt to keep memory used by
/// all attached entities below the ResourceQuota bound.
/// A ResourceQuota can be attached to a server (via \a ServerBuilder),
/// or a client channel (via \a ChannelArguments).
/// gRPC will attempt to keep memory used by all attached entities
/// below the ResourceQuota bound.
class ResourceQuota final : private GrpcLibraryCodegen {
public:
/// \param name - a unique name for this ResourceQuota.
@ -52,10 +53,10 @@ class ResourceQuota final : private GrpcLibraryCodegen {
ResourceQuota();
~ResourceQuota();
/// Resize this ResourceQuota to a new size. If new_size is smaller than the
/// current size of the pool, memory usage will be monotonically decreased
/// until it falls under new_size. No time bound is given for this to occur
/// however.
/// Resize this \a ResourceQuota to a new size. If \a new_size is smaller
/// than the current size of the pool, memory usage will be monotonically
/// decreased until it falls under \a new_size.
/// No time bound is given for this to occur however.
ResourceQuota& Resize(size_t new_size);
grpc_resource_quota* c_resource_quota() const { return impl_; }

@ -42,6 +42,9 @@
namespace grpc {
/// Interface allowing custom server-side authorization based on credentials
/// encoded in metadata. Objects of this type can be passed to
/// \a ServerCredentials::SetAuthMetadataProcessor().
class AuthMetadataProcessor {
public:
typedef std::multimap<grpc::string_ref, grpc::string_ref> InputMetadata;
@ -49,7 +52,7 @@ class AuthMetadataProcessor {
virtual ~AuthMetadataProcessor() {}
/// If this method returns true, the Process function will be scheduled in
/// If this method returns true, the \a Process function will be scheduled in
/// a different thread from the one processing the call.
virtual bool IsBlocking() const { return true; }

@ -151,7 +151,7 @@ std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials();
/// json_key is the JSON key string containing the client's private key.
/// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
/// (JWT) created with this credentials. It should not exceed
/// grpc_max_auth_token_lifetime or will be cropped to this value.
/// \a grpc_max_auth_token_lifetime or will be cropped to this value.
std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds);

@ -70,7 +70,7 @@ class ServerCredentials {
/// Options to create ServerCredentials with SSL
struct SslServerCredentialsOptions {
/// Deprecated
/// \warning Deprecated
SslServerCredentialsOptions()
: force_client_auth(false),
client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {}
@ -84,12 +84,13 @@ struct SslServerCredentialsOptions {
};
grpc::string pem_root_certs;
std::vector<PemKeyCertPair> pem_key_cert_pairs;
/// Deprecated
/// \warning Deprecated
bool force_client_auth;
/// If both force_client_auth and client_certificate_request fields are set,
/// force_client_auth takes effect i.e
/// REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY will be enforced.
/// If both \a force_client_auth and \a client_certificate_request
/// fields are set, \a force_client_auth takes effect, i.e.
/// \a REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
/// will be enforced.
grpc_ssl_client_certificate_request_type client_certificate_request;
};

@ -60,23 +60,26 @@ class HealthCheckServiceInterface;
class ServerContext;
class ServerInitializer;
/// Models a gRPC server.
/// Represents a gRPC server.
///
/// Servers are configured and started via \a grpc::ServerBuilder.
/// Use a \a grpc::ServerBuilder to create, configure, and start
/// \a Server instances.
class Server final : public ServerInterface, private GrpcLibraryCodegen {
public:
~Server();
/// Block waiting for all work to complete.
/// Block until the server shuts down.
///
/// \warning The server must be either shutting down or some other thread must
/// call \a Shutdown for this function to ever return.
void Wait() override;
/// Global Callbacks
///
/// Can be set exactly once per application to install hooks whenever
/// a server event occurs
/// Global callbacks are a set of hooks that are called when server
/// events occur. \a SetGlobalCallbacks method is used to register
/// the hooks with gRPC. Note that
/// the \a GlobalCallbacks instance will be shared among all
/// \a Server instances in an application and can be set exactly
/// once per application.
class GlobalCallbacks {
public:
virtual ~GlobalCallbacks() {}
@ -92,12 +95,14 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
virtual void AddPort(Server* server, const grpc::string& addr,
ServerCredentials* creds, int port) {}
};
/// Set the global callback object. Can only be called once. Does not take
/// ownership of callbacks, and expects the pointed to object to be alive
/// until all server objects in the process have been destroyed.
/// Set the global callback object. Can only be called once per application.
/// Does not take ownership of callbacks, and expects the pointed to object
/// to be alive until all server objects in the process have been destroyed.
/// The same \a GlobalCallbacks object will be used throughout the
/// application and is shared among all \a Server objects.
static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
// Returns a \em raw pointer to the underlying grpc_server instance.
// Returns a \em raw pointer to the underlying \a grpc_server instance.
grpc_server* c_server();
/// Returns the health check service.
@ -158,17 +163,19 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
/// service. The service must exist for the lifetime of the Server instance.
void RegisterAsyncGenericService(AsyncGenericService* service) override;
/// Tries to bind \a server to the given \a addr.
/// Try binding the server to the given \a addr endpoint
/// (port, and optionally including IP address to bind to).
///
/// It can be invoked multiple times.
/// It can be invoked multiple times. Should be used before
/// starting the server.
///
/// \param addr The address to try to bind to the server (eg, localhost:1234,
/// 192.168.1.1:31416, [::1]:27182, etc.).
/// \params creds The credentials associated with the server.
///
/// \return bound port number on sucess, 0 on failure.
/// \return bound port number on success, 0 on failure.
///
/// \warning It's an error to call this method on an already started server.
/// \warning It is an error to call this method on an already started server.
int AddListeningPort(const grpc::string& addr,
ServerCredentials* creds) override;
@ -194,13 +201,14 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
const int max_receive_message_size_;
/// The following completion queues are ONLY used in case of Sync API i.e if
/// the server has any services with sync methods. The server uses these
/// completion queues to poll for new RPCs
/// The following completion queues are ONLY used in case of Sync API
/// i.e. if the server has any services with sync methods. The server uses
/// these completion queues to poll for new RPCs
std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
sync_server_cqs_;
/// List of ThreadManager instances (one for each cq in the sync_server_cqs)
/// List of \a ThreadManager instances (one for each cq in
/// the \a sync_server_cqs)
std::vector<std::unique_ptr<SyncRequestThreadManager>> sync_req_mgrs_;
// Sever status

@ -71,7 +71,13 @@ class ServerBuilder {
ServerBuilder();
~ServerBuilder();
enum SyncServerOption { NUM_CQS, MIN_POLLERS, MAX_POLLERS, CQ_TIMEOUT_MSEC };
/// Options for synchronous servers.
enum SyncServerOption {
NUM_CQS, ///< Number of completion queues.
MIN_POLLERS, ///< Minimum number of polling threads.
MAX_POLLERS, ///< Maximum number of polling threads.
CQ_TIMEOUT_MSEC ///< Completion queue timeout in milliseconds.
};
/// Register a service. This call does not take ownership of the service.
/// The service must exist for the lifetime of the \a Server instance returned
@ -85,7 +91,7 @@ class ServerBuilder {
/// Register a service. This call does not take ownership of the service.
/// The service must exist for the lifetime of the \a Server instance returned
/// by BuildAndStart().
/// by \a BuildAndStart().
/// Only matches requests with :authority \a host
ServerBuilder& RegisterService(const grpc::string& host, Service* service);
@ -110,7 +116,7 @@ class ServerBuilder {
/// enabled by default.
///
/// Incoming calls compressed with an unsupported algorithm will fail with
/// GRPC_STATUS_UNIMPLEMENTED.
/// \a GRPC_STATUS_UNIMPLEMENTED.
ServerBuilder& SetCompressionAlgorithmSupportStatus(
grpc_compression_algorithm algorithm, bool enabled);
@ -139,15 +145,17 @@ class ServerBuilder {
return SetOption(MakeChannelArgumentOption(arg, value));
}
/// Tries to bind \a server to the given \a addr.
/// Enlists an endpoint \a addr (port with an optional IP address) to
/// bind the \a grpc::Server object to be created to.
///
/// It can be invoked multiple times.
///
/// \param addr The address to try to bind to the server (eg, localhost:1234,
/// 192.168.1.1:31416, [::1]:27182, etc.).
/// \params creds The credentials associated with the server.
/// \param selected_port[out] Upon success, updated to contain the port
/// number. \a nullptr otherwise.
/// \param selected_port[out] If not `nullptr`, gets populated with the port
/// number bound to the \a grpc::Server for the corresponding endpoint after
/// it is successfully bound, 0 otherwise.
///
// TODO(dgq): the "port" part seems to be a misnomer.
ServerBuilder& AddListeningPort(const grpc::string& addr,
@ -169,12 +177,13 @@ class ServerBuilder {
/// server_->Shutdown();
/// cq_->Shutdown(); // Always *after* the associated server's Shutdown()!
///
/// \param is_frequently_polled This is an optional parameter to inform GRPC
/// \param is_frequently_polled This is an optional parameter to inform gRPC
/// library about whether this completion queue would be frequently polled
/// (i.e by calling Next() or AsyncNext()). The default value is 'true' and is
/// the recommended setting. Setting this to 'false' (i.e not polling the
/// completion queue frequently) will have a significantly negative
/// performance impact and hence should not be used in production use cases.
/// (i.e. by calling \a Next() or \a AsyncNext()). The default value is
/// 'true' and is the recommended setting. Setting this to 'false' (i.e.
/// not polling the completion queue frequently) will have a significantly
/// negative performance impact and hence should not be used in production
/// use cases.
std::unique_ptr<ServerCompletionQueue> AddCompletionQueue(
bool is_frequently_polled = true);
@ -206,18 +215,18 @@ class ServerBuilder {
max_pollers(2),
cq_timeout_msec(10000) {}
// Number of server completion queues to create to listen to incoming RPCs.
/// Number of server completion queues to create to listen to incoming RPCs.
int num_cqs;
// Minimum number of threads per completion queue that should be listening
// to incoming RPCs.
/// Minimum number of threads per completion queue that should be listening
/// to incoming RPCs.
int min_pollers;
// Maximum number of threads per completion queue that can be listening to
// incoming RPCs.
/// Maximum number of threads per completion queue that can be listening to
/// incoming RPCs.
int max_pollers;
// The timeout for server completion queue's AsyncNext call.
/// The timeout for server completion queue's AsyncNext call.
int cq_timeout_msec;
};
@ -238,7 +247,7 @@ class ServerBuilder {
SyncServerSettings sync_server_settings_;
// List of completion queues added via AddCompletionQueue() method
/// List of completion queues added via \a AddCompletionQueue method.
std::vector<ServerCompletionQueue*> cqs_;
std::shared_ptr<ServerCredentials> creds_;

@ -43,9 +43,10 @@ namespace grpc {
#ifdef GPR_SUPPORT_CHANNELS_FROM_FD
/// Adds new client to a \a Server communicating over given file descriptor
/// Add a new client to a \a Server communicating over the given
/// file descriptor.
///
/// \param server The server to add a client to.
/// \param server The server to add the client to.
/// \param fd The file descriptor representing a socket.
void AddInsecureChannelFromFd(Server* server, int fd);

@ -49,7 +49,7 @@ class ChannelArgumentsTest;
class ResourceQuota;
/// Options for channel creation. The user can use generic setters to pass
/// key value pairs down to c channel creation code. For grpc related options,
/// key value pairs down to C channel creation code. For gRPC related options,
/// concrete setters are provided.
class ChannelArguments {
public:
@ -82,13 +82,13 @@ class ChannelArguments {
/// Set the socket mutator for the channel.
void SetSocketMutator(grpc_socket_mutator* mutator);
/// The given string will be sent at the front of the user agent string.
/// Set the string to prepend to the user agent.
void SetUserAgentPrefix(const grpc::string& user_agent_prefix);
/// The given buffer pool will be attached to the constructed channel
/// Set the buffer pool to be attached to the constructed channel.
void SetResourceQuota(const ResourceQuota& resource_quota);
/// Sets the max receive and send message sizes.
/// Set the max receive and send message sizes.
void SetMaxReceiveMessageSize(int size);
void SetMaxSendMessageSize(int size);
@ -115,8 +115,8 @@ class ChannelArguments {
/// Set a textual argument \a value under \a key.
void SetString(const grpc::string& key, const grpc::string& value);
/// Return (by value) a c grpc_channel_args structure which points to
/// arguments owned by this ChannelArguments instance
/// Return (by value) a C \a grpc_channel_args structure which points to
/// arguments owned by this \a ChannelArguments instance
grpc_channel_args c_channel_args() const {
grpc_channel_args out;
out.num_args = args_.size();

@ -44,16 +44,16 @@ class Status;
namespace grpc {
/// Maps a grpc::Status to a google::rpc::Status.
/// Map a \a grpc::Status to a \a google::rpc::Status.
/// The given \a to object will be cleared.
/// On success, returns status with OK.
/// Returns status with INVALID_ARGUMENT, if failed to deserialize.
/// Returns status with FAILED_PRECONDITION, if \a to is nullptr.
/// Returns status with \a INVALID_ARGUMENT, if failed to deserialize.
/// Returns status with \a FAILED_PRECONDITION, if \a to is nullptr.
Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to);
/// Maps google::rpc::Status to a grpc::Status.
/// Map \a google::rpc::Status to a \a grpc::Status.
/// Returns OK on success.
/// Returns status with FAILED_PRECONDITION if \a to is nullptr.
/// Returns status with \a FAILED_PRECONDITION if \a to is nullptr.
Status SetErrorDetails(const ::google::rpc::Status& from, Status* to);
} // namespace grpc

@ -48,7 +48,7 @@ class Slice final {
public:
/// Construct an empty slice.
Slice();
// Destructor - drops one reference.
/// Destructor - drops one reference.
~Slice();
enum AddRef { ADD_REF };

@ -47,7 +47,7 @@ class ServerContextTestSpouse {
explicit ServerContextTestSpouse(ServerContext* ctx) : ctx_(ctx) {}
/// Inject client metadata to the ServerContext for the test. The test spouse
/// must be alive when ServerContext::client_metadata is called.
/// must be alive when \a ServerContext::client_metadata is called.
void AddClientMetadata(const grpc::string& key, const grpc::string& value) {
client_metadata_storage_.insert(
std::pair<grpc::string, grpc::string>(key, value));
@ -70,7 +70,7 @@ class ServerContextTestSpouse {
}
private:
ServerContext* ctx_; /// not owned
ServerContext* ctx_; // not owned
std::multimap<grpc::string, grpc::string> client_metadata_storage_;
};

@ -178,6 +178,12 @@ GRPCAPI void grpc_alarm_destroy(grpc_alarm *alarm);
GRPCAPI grpc_connectivity_state grpc_channel_check_connectivity_state(
grpc_channel *channel, int try_to_connect);
/** Number of active "external connectivity state watchers" attached to a
* channel.
* Useful for testing. **/
GRPCAPI int grpc_channel_num_external_connectivity_watchers(
grpc_channel *channel);
/** Watch for a change in connectivity state.
Once the channel connectivity state is different from last_observed_state,
tag will be enqueued on cq with success=1.

@ -65,7 +65,7 @@ typedef enum gpr_log_severity {
#define GPR_LOG_VERBOSITY_UNSET -1
/** Returns a string representation of the log severity */
const char *gpr_log_severity_string(gpr_log_severity severity);
GPRAPI const char *gpr_log_severity_string(gpr_log_severity severity);
/** Macros to build log contexts at various severity levels */
#define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG

@ -1,6 +1,6 @@
{
"name": "grpc",
"version": "1.4.0-dev",
"version": "1.5.0-dev",
"author": "Google Inc.",
"description": "gRPC Library for Node",
"homepage": "http://www.grpc.io/",

@ -10,11 +10,11 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
<date>2017-05-05</date>
<date>2017-05-22</date>
<time>16:06:07</time>
<version>
<release>1.4.0dev</release>
<api>1.4.0dev</api>
<release>1.5.0dev</release>
<api>1.5.0dev</api>
</version>
<stability>
<release>beta</release>
@ -23,13 +23,18 @@
<license>BSD</license>
<notes>
- Fixed some memory leaks #9559, #10996
- Disabled cares dependency from gRPC C Core #10940
- De-coupled protobuf dependency #11112
- Fixed extension reported version #10842
- Added config.w32 for Windows support #8161
- Fixed PHP distrib test after cc files were added #11193
- Fixed protoc plugin comment escape bug #11025
</notes>
<contents>
<dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="config.m4" role="src" />
<file baseinstalldir="/" name="config.w32" role="src" />
<file baseinstalldir="/" name="src/php/README.md" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/byte_buffer.c" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/call.c" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/call_credentials.c" role="src" />
@ -388,6 +393,8 @@
<file baseinstalldir="/" name="src/core/ext/census/gen/census.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/gen/trace_context.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
@ -638,6 +645,7 @@
<file baseinstalldir="/" name="src/core/ext/census/grpc_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_plugin.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/initialize.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/mlog.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" />
@ -1057,6 +1065,32 @@
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls13_server.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls_method.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls_record.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/crc32.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/deflate.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/gzguts.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/inffast.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/inffixed.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/inflate.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/inftrees.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/trees.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/zconf.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/zlib.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/zutil.h" role="src" />
<file baseinstalldir="/" name="third_party/zlib/adler32.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/compress.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/crc32.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/deflate.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/gzclose.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/gzlib.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/gzread.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/gzwrite.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/infback.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/inffast.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/inflate.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/inftrees.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/trees.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/uncompr.c" role="src" />
<file baseinstalldir="/" name="third_party/zlib/zutil.c" role="src" />
<file name="LICENSE" role="doc" />
</dir>
</contents>

@ -67,12 +67,11 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
out->Print("/**\n");
out->Print(GetPHPComments(method, " *").c_str());
out->Print(GetPHPComments(method, " //").c_str());
if (method->client_streaming()) {
out->Print(vars,
" * @param array $$metadata metadata\n"
" * @param array $$options call options\n */\n"
" // @param array $$metadata metadata\n"
" // @param array $$options call options\n"
"public function $name$($$metadata = [], "
"$$options = []) {\n");
out->Indent();
@ -87,9 +86,9 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
"$$metadata, $$options);\n");
} else {
out->Print(vars,
" * @param \\$input_type_id$ $$argument input argument\n"
" * @param array $$metadata metadata\n"
" * @param array $$options call options\n */\n"
" // @param \\$input_type_id$ $$argument input argument\n"
" // @param array $$metadata metadata\n"
" // @param array $$options call options\n"
"public function $name$(\\$input_type_id$ $$argument,\n"
" $$metadata = [], $$options = []) {\n");
out->Indent();
@ -116,10 +115,10 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n");
out->Indent();
out->Print(
"/**\n * @param string $$hostname hostname\n"
" * @param array $$opts channel options\n"
" * @param \\Grpc\\Channel $$channel (optional) re-use channel "
"object\n */\n"
" // @param string $$hostname hostname\n"
" // @param array $$opts channel options\n"
" // @param \\Grpc\\Channel $$channel (optional) re-use channel "
"object\n"
"public function __construct($$hostname, $$opts, "
"$$channel = null) {\n");
out->Indent();

@ -0,0 +1,320 @@
/*
*
* Copyright 2017, 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/ext/census/intrusive_hash_map.h"
#include <string.h>
extern bool hm_index_compare(const hm_index *A, const hm_index *B);
/* Simple hashing function that takes lower 32 bits. */
static __inline uint32_t chunked_vector_hasher(uint64_t key) {
return (uint32_t)key;
}
/* Vector chunks are 1MiB divided by pointer size. */
static const size_t VECTOR_CHUNK_SIZE = (1 << 20) / sizeof(void *);
/* Helper functions which return buckets from the chunked vector. */
static __inline void **get_mutable_bucket(const chunked_vector *buckets,
uint32_t index) {
if (index < VECTOR_CHUNK_SIZE) {
return &buckets->first_[index];
}
size_t rest_index = (index - VECTOR_CHUNK_SIZE) / VECTOR_CHUNK_SIZE;
return &buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE];
}
static __inline void *get_bucket(const chunked_vector *buckets,
uint32_t index) {
if (index < VECTOR_CHUNK_SIZE) {
return buckets->first_[index];
}
size_t rest_index = (index - VECTOR_CHUNK_SIZE) / VECTOR_CHUNK_SIZE;
return buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE];
}
/* Helper function. */
static __inline size_t RestSize(const chunked_vector *vec) {
return (vec->size_ <= VECTOR_CHUNK_SIZE)
? 0
: (vec->size_ - VECTOR_CHUNK_SIZE - 1) / VECTOR_CHUNK_SIZE + 1;
}
/* Initialize chunked vector to size of 0. */
static void chunked_vector_init(chunked_vector *vec) {
vec->size_ = 0;
vec->first_ = NULL;
vec->rest_ = NULL;
}
/* Clear chunked vector and free all memory that has been allocated then
initialize chunked vector. */
static void chunked_vector_clear(chunked_vector *vec) {
if (vec->first_ != NULL) {
gpr_free(vec->first_);
}
if (vec->rest_ != NULL) {
size_t rest_size = RestSize(vec);
for (size_t i = 0; i < rest_size; ++i) {
if (vec->rest_[i] != NULL) {
gpr_free(vec->rest_[i]);
}
}
gpr_free(vec->rest_);
}
chunked_vector_init(vec);
}
/* Clear chunked vector and then resize it to n entries. Allow the first 1MB to
be read w/o an extra cache miss. The rest of the elements are stored in an
array of arrays to avoid large mallocs. */
static void chunked_vector_reset(chunked_vector *vec, size_t n) {
chunked_vector_clear(vec);
vec->size_ = n;
if (n <= VECTOR_CHUNK_SIZE) {
vec->first_ = (void **)gpr_malloc(sizeof(void *) * n);
memset(vec->first_, 0, sizeof(void *) * n);
} else {
vec->first_ = (void **)gpr_malloc(sizeof(void *) * VECTOR_CHUNK_SIZE);
memset(vec->first_, 0, sizeof(void *) * VECTOR_CHUNK_SIZE);
size_t rest_size = RestSize(vec);
vec->rest_ = (void ***)gpr_malloc(sizeof(void **) * rest_size);
memset(vec->rest_, 0, sizeof(void **) * rest_size);
int i = 0;
n -= VECTOR_CHUNK_SIZE;
while (n > 0) {
size_t this_size = GPR_MIN(n, VECTOR_CHUNK_SIZE);
vec->rest_[i] = (void **)gpr_malloc(sizeof(void *) * this_size);
memset(vec->rest_[i], 0, sizeof(void *) * this_size);
n -= this_size;
++i;
}
}
}
void intrusive_hash_map_init(intrusive_hash_map *hash_map,
uint32_t initial_log2_table_size) {
hash_map->log2_num_buckets = initial_log2_table_size;
hash_map->num_items = 0;
uint32_t num_buckets = (uint32_t)1 << hash_map->log2_num_buckets;
hash_map->extend_threshold = num_buckets >> 1;
chunked_vector_init(&hash_map->buckets);
chunked_vector_reset(&hash_map->buckets, num_buckets);
hash_map->hash_mask = num_buckets - 1;
}
bool intrusive_hash_map_empty(const intrusive_hash_map *hash_map) {
return hash_map->num_items == 0;
}
size_t intrusive_hash_map_size(const intrusive_hash_map *hash_map) {
return hash_map->num_items;
}
void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx) {
idx->bucket_index = (uint32_t)hash_map->buckets.size_;
GPR_ASSERT(idx->bucket_index <= UINT32_MAX);
idx->item = NULL;
}
void intrusive_hash_map_next(const intrusive_hash_map *hash_map,
hm_index *idx) {
idx->item = idx->item->hash_link;
while (idx->item == NULL) {
idx->bucket_index++;
if (idx->bucket_index >= hash_map->buckets.size_) {
/* Reached end of table. */
idx->item = NULL;
return;
}
idx->item = (hm_item *)get_bucket(&hash_map->buckets, idx->bucket_index);
}
}
void intrusive_hash_map_begin(const intrusive_hash_map *hash_map,
hm_index *idx) {
for (uint32_t i = 0; i < hash_map->buckets.size_; ++i) {
if (get_bucket(&hash_map->buckets, i) != NULL) {
idx->bucket_index = i;
idx->item = (hm_item *)get_bucket(&hash_map->buckets, i);
return;
}
}
intrusive_hash_map_end(hash_map, idx);
}
hm_item *intrusive_hash_map_find(const intrusive_hash_map *hash_map,
uint64_t key) {
uint32_t index = chunked_vector_hasher(key) & hash_map->hash_mask;
hm_item *p = (hm_item *)get_bucket(&hash_map->buckets, index);
while (p != NULL) {
if (key == p->key) {
return p;
}
p = p->hash_link;
}
return NULL;
}
hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key) {
uint32_t index = chunked_vector_hasher(key) & hash_map->hash_mask;
hm_item **slot = (hm_item **)get_mutable_bucket(&hash_map->buckets, index);
hm_item *p = *slot;
if (p == NULL) {
return NULL;
}
if (key == p->key) {
*slot = p->hash_link;
p->hash_link = NULL;
hash_map->num_items--;
return p;
}
hm_item *prev = p;
p = p->hash_link;
while (p) {
if (key == p->key) {
prev->hash_link = p->hash_link;
p->hash_link = NULL;
hash_map->num_items--;
return p;
}
prev = p;
p = p->hash_link;
}
return NULL;
}
/* Insert an hm_item* into the underlying chunked vector. hash_mask is
* array_size-1. Returns true if it is a new hm_item and false if the hm_item
* already existed.
*/
static __inline bool intrusive_hash_map_internal_insert(chunked_vector *buckets,
uint32_t hash_mask,
hm_item *item) {
const uint64_t key = item->key;
uint32_t index = chunked_vector_hasher(key) & hash_mask;
hm_item **slot = (hm_item **)get_mutable_bucket(buckets, index);
hm_item *p = *slot;
item->hash_link = p;
/* Check to see if key already exists. */
while (p) {
if (p->key == key) {
return false;
}
p = p->hash_link;
}
/* Otherwise add new entry. */
*slot = item;
return true;
}
/* Extend the allocated number of elements in the hash map by a factor of 2. */
void intrusive_hash_map_extend(intrusive_hash_map *hash_map) {
uint32_t new_log2_num_buckets = 1 + hash_map->log2_num_buckets;
uint32_t new_num_buckets = (uint32_t)1 << new_log2_num_buckets;
GPR_ASSERT(new_num_buckets <= UINT32_MAX && new_num_buckets > 0);
chunked_vector new_buckets;
chunked_vector_init(&new_buckets);
chunked_vector_reset(&new_buckets, new_num_buckets);
uint32_t new_hash_mask = new_num_buckets - 1;
hm_index cur_idx;
hm_index end_idx;
intrusive_hash_map_end(hash_map, &end_idx);
intrusive_hash_map_begin(hash_map, &cur_idx);
while (!hm_index_compare(&cur_idx, &end_idx)) {
hm_item *new_item = cur_idx.item;
intrusive_hash_map_next(hash_map, &cur_idx);
intrusive_hash_map_internal_insert(&new_buckets, new_hash_mask, new_item);
}
/* Set values for new chunked_vector. extend_threshold is set to half of
* new_num_buckets. */
hash_map->log2_num_buckets = new_log2_num_buckets;
chunked_vector_clear(&hash_map->buckets);
hash_map->buckets = new_buckets;
hash_map->hash_mask = new_hash_mask;
hash_map->extend_threshold = new_num_buckets >> 1;
}
/* Insert a hm_item. The hm_item must remain live until it is removed from the
table. This object does not take the ownership of hm_item. The caller must
remove this hm_item from the table and delete it before this table is
deleted. If hm_item exists already num_items is not changed. */
bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item) {
if (hash_map->num_items >= hash_map->extend_threshold) {
intrusive_hash_map_extend(hash_map);
}
if (intrusive_hash_map_internal_insert(&hash_map->buckets,
hash_map->hash_mask, item)) {
hash_map->num_items++;
return true;
}
return false;
}
void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
void (*free_object)(void *)) {
hm_index cur;
hm_index end;
intrusive_hash_map_end(hash_map, &end);
intrusive_hash_map_begin(hash_map, &cur);
while (!hm_index_compare(&cur, &end)) {
hm_index next = cur;
intrusive_hash_map_next(hash_map, &next);
if (cur.item != NULL) {
hm_item *item = intrusive_hash_map_erase(hash_map, cur.item->key);
(*free_object)((void *)item);
gpr_free(item);
}
cur = next;
}
}
void intrusive_hash_map_free(intrusive_hash_map *hash_map,
void (*free_object)(void *)) {
intrusive_hash_map_clear(hash_map, (*free_object));
hash_map->num_items = 0;
hash_map->extend_threshold = 0;
hash_map->log2_num_buckets = 0;
hash_map->hash_mask = 0;
chunked_vector_clear(&hash_map->buckets);
}

@ -0,0 +1,167 @@
/*
*
* Copyright 2017, 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_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
#include "src/core/ext/census/intrusive_hash_map_internal.h"
/* intrusive_hash_map is a fast chained hash table. This hash map is faster than
* a dense hash map when the application calls insert and erase more often than
* find. When the workload is dominated by find() a dense hash map may be
* faster.
*
* intrusive_hash_map uses an intrusive header placed within a user defined
* struct. The header field IHM_key MUST be set to a valid value before
* insertion into the hash map or undefined behavior may occur. The header field
* IHM_hash_link MUST to be set to NULL initially.
*
* EXAMPLE USAGE:
*
* typedef struct string_item {
* INTRUSIVE_HASH_MAP_HEADER;
* // User data.
* char *str_buf;
* uint16_t len;
* } string_item;
*
* static string_item *make_string_item(uint64_t key, const char *buf,
* uint16_t len) {
* string_item *item = (string_item *)gpr_malloc(sizeof(string_item));
* item->IHM_key = key;
* item->IHM_hash_link = NULL;
* item->len = len;
* item->str_buf = (char *)malloc(len);
* memcpy(item->str_buf, buf, len);
* return item;
* }
*
* intrusive_hash_map hash_map;
* intrusive_hash_map_init(&hash_map, 4);
* string_item *new_item1 = make_string_item(10, "test1", 5);
* bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1);
*
* string_item *item1 =
* (string_item *)intrusive_hash_map_find(&hash_map, 10);
*/
/* Hash map item. Stores key and a pointer to the actual object. A user defined
* version of this can be passed in provided the first 2 entries (key and
* hash_link) are the same. These entries must be first in the user defined
* struct. Pointer to struct will need to be cast as (hm_item *) when passed to
* hash map. This allows it to be intrusive. */
typedef struct hm_item {
uint64_t key;
struct hm_item *hash_link;
/* Optional user defined data after this. */
} hm_item;
/* Macro provided for ease of use. This must be first in the user defined
* struct (i.e. uint64_t key and hm_item * must be the first two elements in
* that order). */
#define INTRUSIVE_HASH_MAP_HEADER \
uint64_t IHM_key; \
struct hm_item *IHM_hash_link
/* Index struct which acts as a pseudo-iterator within the hash map. */
typedef struct hm_index {
uint32_t bucket_index; // hash map bucket index.
hm_item *item; // Pointer to hm_item within the hash map.
} hm_index;
/* Returns true if two hm_indices point to the same object within the hash map
* and false otherwise. */
__inline bool hm_index_compare(const hm_index *A, const hm_index *B) {
return (A->item == B->item && A->bucket_index == B->bucket_index);
}
/*
* Helper functions for iterating over the hash map.
*/
/* On return idx will contain an invalid index which is always equal to
* hash_map->buckets.size_ */
void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx);
/* Iterates index to the next valid entry in the hash map and stores the
* index within idx. If end of table is reached, idx will contain the same
* values as if intrusive_hash_map_end() was called. */
void intrusive_hash_map_next(const intrusive_hash_map *hash_map, hm_index *idx);
/* On return, idx will contain the index of the first non-null entry in the hash
* map. If the hash map is empty, idx will contain the same values as if
* intrusive_hash_map_end() was called. */
void intrusive_hash_map_begin(const intrusive_hash_map *hash_map,
hm_index *idx);
/* Initialize intrusive hash map data structure. This must be called before
* the hash map can be used. The initial size of an intrusive hash map will be
* 2^initial_log2_map_size (valid range is [0, 31]). */
void intrusive_hash_map_init(intrusive_hash_map *hash_map,
uint32_t initial_log2_map_size);
/* Returns true if the hash map is empty and false otherwise. */
bool intrusive_hash_map_empty(const intrusive_hash_map *hash_map);
/* Returns the number of elements currently in the hash map. */
size_t intrusive_hash_map_size(const intrusive_hash_map *hash_map);
/* Find a hm_item within the hash map by key. Returns NULL if item was not
* found. */
hm_item *intrusive_hash_map_find(const intrusive_hash_map *hash_map,
uint64_t key);
/* Erase the hm_item that corresponds with key. If the hm_item is found, return
* the pointer to the hm_item. Else returns NULL. */
hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key);
/* Attempts to insert a new hm_item into the hash map. If an element with the
* same key already exists, it will not insert the new item and return false.
* Otherwise, it will insert the new item and return true. */
bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item);
/* Clears entire contents of the hash map, but leaves internal data structure
* untouched. Second argument takes a function pointer to a function that will
* free the object designated by the user and pointed to by hash_map->value. */
void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
void (*free_object)(void *));
/* Erase all contents of hash map and free the memory. Hash map is invalid
* after calling this function and cannot be used until it has been
* reinitialized (intrusive_hash_map_init()). This function takes a function
* pointer to a function that will free the object designated by the user and
* pointed to by hash_map->value. */
void intrusive_hash_map_free(intrusive_hash_map *hash_map,
void (*free_object)(void *));
#endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H */

@ -0,0 +1,63 @@
/*
*
* Copyright 2017, 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_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#include <stdbool.h>
/* The chunked vector is a data structure that allocates buckets for use in the
* hash map. ChunkedVector is logically equivalent to T*[N] (cast void* as
* T*). It's internally implemented as an array of 1MB arrays to avoid
* allocating large consecutive memory chunks. This is an internal data
* structure that should never be accessed directly. */
typedef struct chunked_vector {
size_t size_;
void **first_;
void ***rest_;
} chunked_vector;
/* Core intrusive hash map data structure. All internal elements are managed by
* functions and should not be altered manually. */
typedef struct intrusive_hash_map {
uint32_t num_items;
uint32_t extend_threshold;
uint32_t log2_num_buckets;
uint32_t hash_mask;
chunked_vector buckets;
} intrusive_hash_map;
#endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H */

@ -67,9 +67,8 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
typedef enum {
WAITING,
CALLING_BACK,
READY_TO_CALL_BACK,
CALLING_BACK_AND_FINISHED,
CALLED_BACK
} callback_phase;
typedef struct {
@ -77,11 +76,13 @@ typedef struct {
callback_phase phase;
grpc_closure on_complete;
grpc_closure on_timeout;
grpc_closure watcher_timer_init;
grpc_timer alarm;
grpc_connectivity_state state;
grpc_completion_queue *cq;
grpc_cq_completion completion_storage;
grpc_channel *channel;
grpc_error *error;
void *tag;
} state_watcher;
@ -105,11 +106,8 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
gpr_mu_lock(&w->mu);
switch (w->phase) {
case WAITING:
case CALLED_BACK:
case READY_TO_CALL_BACK:
GPR_UNREACHABLE_CODE(return );
case CALLING_BACK:
w->phase = CALLED_BACK;
break;
case CALLING_BACK_AND_FINISHED:
delete = 1;
break;
@ -123,10 +121,14 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
bool due_to_completion, grpc_error *error) {
int delete = 0;
if (due_to_completion) {
grpc_timer_cancel(exec_ctx, &w->alarm);
} else {
grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
grpc_channel_get_channel_stack(w->channel));
grpc_client_channel_watch_connectivity_state(exec_ctx, client_channel_elem,
grpc_cq_pollset(w->cq), NULL,
&w->on_complete, NULL);
}
gpr_mu_lock(&w->mu);
@ -147,25 +149,27 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
}
switch (w->phase) {
case WAITING:
w->phase = CALLING_BACK;
grpc_cq_end_op(exec_ctx, w->cq, w->tag, GRPC_ERROR_REF(error),
finished_completion, w, &w->completion_storage);
GRPC_ERROR_REF(error);
w->error = error;
w->phase = READY_TO_CALL_BACK;
break;
case CALLING_BACK:
case READY_TO_CALL_BACK:
if (error != GRPC_ERROR_NONE) {
GPR_ASSERT(!due_to_completion);
GRPC_ERROR_UNREF(w->error);
GRPC_ERROR_REF(error);
w->error = error;
}
w->phase = CALLING_BACK_AND_FINISHED;
grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->error, finished_completion, w,
&w->completion_storage);
break;
case CALLING_BACK_AND_FINISHED:
GPR_UNREACHABLE_CODE(return );
case CALLED_BACK:
delete = 1;
break;
}
gpr_mu_unlock(&w->mu);
if (delete) {
delete_state_watcher(exec_ctx, w);
}
GRPC_ERROR_UNREF(error);
}
@ -179,6 +183,28 @@ static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw,
partly_done(exec_ctx, pw, false, GRPC_ERROR_REF(error));
}
int grpc_channel_num_external_connectivity_watchers(grpc_channel *channel) {
grpc_channel_element *client_channel_elem =
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
return grpc_client_channel_num_external_connectivity_watchers(
client_channel_elem);
}
typedef struct watcher_timer_init_arg {
state_watcher *w;
gpr_timespec deadline;
} watcher_timer_init_arg;
static void watcher_timer_init(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error_ignored) {
watcher_timer_init_arg *wa = (watcher_timer_init_arg *)arg;
grpc_timer_init(exec_ctx, &wa->w->alarm,
gpr_convert_clock_type(wa->deadline, GPR_CLOCK_MONOTONIC),
&wa->w->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC));
gpr_free(wa);
}
void grpc_channel_watch_connectivity_state(
grpc_channel *channel, grpc_connectivity_state last_observed_state,
gpr_timespec deadline, grpc_completion_queue *cq, void *tag) {
@ -208,16 +234,19 @@ void grpc_channel_watch_connectivity_state(
w->cq = cq;
w->tag = tag;
w->channel = channel;
w->error = NULL;
grpc_timer_init(&exec_ctx, &w->alarm,
gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
&w->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC));
watcher_timer_init_arg *wa = gpr_malloc(sizeof(watcher_timer_init_arg));
wa->w = w;
wa->deadline = deadline;
grpc_closure_init(&w->watcher_timer_init, watcher_timer_init, wa,
grpc_schedule_on_exec_ctx);
if (client_channel_elem->filter == &grpc_client_channel_filter) {
GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity");
grpc_client_channel_watch_connectivity_state(&exec_ctx, client_channel_elem,
grpc_cq_pollset(cq), &w->state,
&w->on_complete);
grpc_client_channel_watch_connectivity_state(
&exec_ctx, client_channel_elem, grpc_cq_pollset(cq), &w->state,
&w->on_complete, &w->watcher_timer_init);
} else {
abort();
}

@ -167,6 +167,8 @@ static void *method_parameters_create_from_json(const grpc_json *json) {
return value;
}
struct external_connectivity_watcher;
/*************************************************************************
* CHANNEL-WIDE FUNCTIONS
*/
@ -204,6 +206,11 @@ typedef struct client_channel_channel_data {
/** interested parties (owned) */
grpc_pollset_set *interested_parties;
/* external_connectivity_watcher_list head is guarded by its own mutex, since
* counts need to be grabbed immediately without polling on a cq */
gpr_mu external_connectivity_watcher_list_mu;
struct external_connectivity_watcher *external_connectivity_watcher_list_head;
/* the following properties are guarded by a mutex since API's require them
to be instantaneously available */
gpr_mu info_mu;
@ -661,6 +668,12 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
// Initialize data members.
chand->combiner = grpc_combiner_create(NULL);
gpr_mu_init(&chand->info_mu);
gpr_mu_init(&chand->external_connectivity_watcher_list_mu);
gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
chand->external_connectivity_watcher_list_head = NULL;
gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
chand->owning_stack = args->channel_stack;
grpc_closure_init(&chand->on_resolver_result_changed,
on_resolver_result_changed_locked, chand,
@ -749,6 +762,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
gpr_mu_destroy(&chand->info_mu);
gpr_mu_destroy(&chand->external_connectivity_watcher_list_mu);
}
/*************************************************************************
@ -1431,14 +1445,79 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
return out;
}
typedef struct {
typedef struct external_connectivity_watcher {
channel_data *chand;
grpc_pollset *pollset;
grpc_closure *on_complete;
grpc_closure *watcher_timer_init;
grpc_connectivity_state *state;
grpc_closure my_closure;
struct external_connectivity_watcher *next;
} external_connectivity_watcher;
static external_connectivity_watcher *lookup_external_connectivity_watcher(
channel_data *chand, grpc_closure *on_complete) {
gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
external_connectivity_watcher *w =
chand->external_connectivity_watcher_list_head;
while (w != NULL && w->on_complete != on_complete) {
w = w->next;
}
gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
return w;
}
static void external_connectivity_watcher_list_append(
channel_data *chand, external_connectivity_watcher *w) {
GPR_ASSERT(!lookup_external_connectivity_watcher(chand, w->on_complete));
gpr_mu_lock(&w->chand->external_connectivity_watcher_list_mu);
GPR_ASSERT(!w->next);
w->next = chand->external_connectivity_watcher_list_head;
chand->external_connectivity_watcher_list_head = w;
gpr_mu_unlock(&w->chand->external_connectivity_watcher_list_mu);
}
static void external_connectivity_watcher_list_remove(
channel_data *chand, external_connectivity_watcher *too_remove) {
GPR_ASSERT(
lookup_external_connectivity_watcher(chand, too_remove->on_complete));
gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
if (too_remove == chand->external_connectivity_watcher_list_head) {
chand->external_connectivity_watcher_list_head = too_remove->next;
gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
return;
}
external_connectivity_watcher *w =
chand->external_connectivity_watcher_list_head;
while (w != NULL) {
if (w->next == too_remove) {
w->next = w->next->next;
gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
return;
}
w = w->next;
}
GPR_UNREACHABLE_CODE(return );
}
int grpc_client_channel_num_external_connectivity_watchers(
grpc_channel_element *elem) {
channel_data *chand = elem->channel_data;
int count = 0;
gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
external_connectivity_watcher *w =
chand->external_connectivity_watcher_list_head;
while (w != NULL) {
count++;
w = w->next;
}
gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
return count;
}
static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
external_connectivity_watcher *w = arg;
@ -1447,6 +1526,7 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
w->pollset);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
"external_connectivity_watcher");
external_connectivity_watcher_list_remove(w->chand, w);
gpr_free(w);
grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
}
@ -1454,21 +1534,42 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error_ignored) {
external_connectivity_watcher *w = arg;
grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
grpc_schedule_on_exec_ctx);
grpc_connectivity_state_notify_on_state_change(
exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
external_connectivity_watcher *found = NULL;
if (w->state != NULL) {
external_connectivity_watcher_list_append(w->chand, w);
grpc_closure_run(exec_ctx, w->watcher_timer_init, GRPC_ERROR_NONE);
grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
grpc_schedule_on_exec_ctx);
grpc_connectivity_state_notify_on_state_change(
exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
} else {
GPR_ASSERT(w->watcher_timer_init == NULL);
found = lookup_external_connectivity_watcher(w->chand, w->on_complete);
if (found) {
GPR_ASSERT(found->on_complete == w->on_complete);
grpc_connectivity_state_notify_on_state_change(
exec_ctx, &found->chand->state_tracker, NULL, &found->my_closure);
}
grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
w->pollset);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
"external_connectivity_watcher");
gpr_free(w);
}
}
void grpc_client_channel_watch_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
grpc_connectivity_state *state, grpc_closure *closure) {
grpc_connectivity_state *state, grpc_closure *closure,
grpc_closure *watcher_timer_init) {
channel_data *chand = elem->channel_data;
external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
external_connectivity_watcher *w = gpr_zalloc(sizeof(*w));
w->chand = chand;
w->pollset = pollset;
w->on_complete = closure;
w->state = state;
w->watcher_timer_init = watcher_timer_init;
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
"external_connectivity_watcher");

@ -53,9 +53,13 @@ extern const grpc_channel_filter grpc_client_channel_filter;
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
int grpc_client_channel_num_external_connectivity_watchers(
grpc_channel_element *elem);
void grpc_client_channel_watch_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
grpc_connectivity_state *state, grpc_closure *on_complete);
grpc_connectivity_state *state, grpc_closure *on_complete,
grpc_closure *watcher_timer_init);
/* Debug helper: pull the subchannel call from a call stack element */
grpc_subchannel_call *grpc_client_channel_get_subchannel_call(

@ -99,26 +99,13 @@ typedef struct pending_pick {
grpc_closure *on_complete;
} pending_pick;
/** List of subchannels in a connectivity READY state */
typedef struct ready_list {
grpc_subchannel *subchannel;
/* references namesake entry in subchannel_data */
void *user_data;
struct ready_list *next;
struct ready_list *prev;
} ready_list;
typedef struct {
/** index within policy->subchannels */
size_t index;
/** backpointer to owning policy */
round_robin_lb_policy *policy;
/** subchannel itself */
grpc_subchannel *subchannel;
/** notification that connectivity has changed on subchannel */
grpc_closure connectivity_changed_closure;
/** this subchannels current position in subchannel->ready_list */
ready_list *ready_list_node;
/** last observed connectivity. Not updated by
* \a grpc_subchannel_notify_on_state_change. Used to determine the previous
* state while processing the new state in \a rr_connectivity_changed */
@ -126,6 +113,10 @@ typedef struct {
/** current connectivity state. Updated by \a
* grpc_subchannel_notify_on_state_change */
grpc_connectivity_state curr_connectivity_state;
/** connectivity state to be updated by the watcher, not guarded by
* the combiner. Will be moved to curr_connectivity_state inside of
* the combiner by rr_connectivity_changed_locked(). */
grpc_connectivity_state pending_connectivity_state_unsafe;
/** the subchannel's target user data */
void *user_data;
/** vtable to operate over \a user_data */
@ -141,182 +132,106 @@ struct round_robin_lb_policy {
/** all our subchannels */
size_t num_subchannels;
subchannel_data **subchannels;
subchannel_data *subchannels;
/** how many subchannels are in TRANSIENT_FAILURE */
/** how many subchannels are in state READY */
size_t num_ready;
/** how many subchannels are in state TRANSIENT_FAILURE */
size_t num_transient_failures;
/** how many subchannels are IDLE */
/** how many subchannels are in state IDLE */
size_t num_idle;
/** have we started picking? */
int started_picking;
bool started_picking;
/** are we shutting down? */
int shutdown;
bool shutdown;
/** List of picks that are waiting on connectivity */
pending_pick *pending_picks;
/** our connectivity state tracker */
grpc_connectivity_state_tracker state_tracker;
/** (Dummy) root of the doubly linked list containing READY subchannels */
ready_list ready_list;
/** Last pick from the ready list. */
ready_list *ready_list_last_pick;
// Index into subchannels for last pick.
size_t last_ready_subchannel_index;
};
/** Returns the next subchannel from the connected list or NULL if the list is
* empty.
/** Returns the index into p->subchannels of the next subchannel in
* READY state, or p->num_subchannels if no subchannel is READY.
*
* Note that this function does *not* advance p->ready_list_last_pick. Use \a
* advance_last_picked_locked() for that. */
static ready_list *peek_next_connected_locked(const round_robin_lb_policy *p) {
ready_list *selected;
selected = p->ready_list_last_pick->next;
while (selected != NULL) {
if (selected == &p->ready_list) {
GPR_ASSERT(selected->subchannel == NULL);
/* skip dummy root */
selected = selected->next;
} else {
GPR_ASSERT(selected->subchannel != NULL);
return selected;
}
* Note that this function does *not* update p->last_ready_subchannel_index.
* The caller must do that if it returns a pick. */
static size_t get_next_ready_subchannel_index_locked(
const round_robin_lb_policy *p) {
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO,
"[RR: %p] getting next ready subchannel, "
"last_ready_subchannel_index=%lu",
p, (unsigned long)p->last_ready_subchannel_index);
}
return NULL;
}
/** Advance the \a ready_list picking head. */
static void advance_last_picked_locked(round_robin_lb_policy *p) {
if (p->ready_list_last_pick->next != NULL) { /* non-empty list */
p->ready_list_last_pick = p->ready_list_last_pick->next;
if (p->ready_list_last_pick == &p->ready_list) {
/* skip dummy root */
p->ready_list_last_pick = p->ready_list_last_pick->next;
for (size_t i = 0; i < p->num_subchannels; ++i) {
const size_t index =
(i + p->last_ready_subchannel_index + 1) % p->num_subchannels;
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG, "[RR %p] checking index %lu: state=%d", p,
(unsigned long)index,
p->subchannels[index].curr_connectivity_state);
}
if (p->subchannels[index].curr_connectivity_state == GRPC_CHANNEL_READY) {
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG, "[RR %p] found next ready subchannel at index %lu",
p, (unsigned long)index);
}
return index;
}
} else { /* should be an empty list */
GPR_ASSERT(p->ready_list_last_pick == &p->ready_list);
}
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG,
"[READYLIST, RR: %p] ADVANCED LAST PICK. NOW AT NODE %p (SC %p, "
"CSC %p)",
(void *)p, (void *)p->ready_list_last_pick,
(void *)p->ready_list_last_pick->subchannel,
(void *)grpc_subchannel_get_connected_subchannel(
p->ready_list_last_pick->subchannel));
gpr_log(GPR_DEBUG, "[RR %p] no subchannels in ready state", p);
}
return p->num_subchannels;
}
/** Prepends (relative to the root at p->ready_list) the connected subchannel \a
* csc to the list of ready subchannels. */
static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
subchannel_data *sd) {
ready_list *new_elem = gpr_zalloc(sizeof(ready_list));
new_elem->subchannel = sd->subchannel;
new_elem->user_data = sd->user_data;
if (p->ready_list.prev == NULL) {
/* first element */
new_elem->next = &p->ready_list;
new_elem->prev = &p->ready_list;
p->ready_list.next = new_elem;
p->ready_list.prev = new_elem;
} else {
new_elem->next = &p->ready_list;
new_elem->prev = p->ready_list.prev;
p->ready_list.prev->next = new_elem;
p->ready_list.prev = new_elem;
}
// Sets p->last_ready_subchannel_index to last_ready_index.
static void update_last_ready_subchannel_index_locked(round_robin_lb_policy *p,
size_t last_ready_index) {
GPR_ASSERT(last_ready_index < p->num_subchannels);
p->last_ready_subchannel_index = last_ready_index;
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (Conn. SC %p)",
(void *)new_elem, (void *)sd->subchannel);
}
return new_elem;
}
/** Removes \a node from the list of connected subchannels */
static void remove_disconnected_sc_locked(round_robin_lb_policy *p,
ready_list *node) {
if (node == NULL) {
return;
}
if (node == p->ready_list_last_pick) {
p->ready_list_last_pick = p->ready_list_last_pick->prev;
}
/* removing last item */
if (node->next == &p->ready_list && node->prev == &p->ready_list) {
GPR_ASSERT(p->ready_list.next == node);
GPR_ASSERT(p->ready_list.prev == node);
p->ready_list.next = NULL;
p->ready_list.prev = NULL;
} else {
node->prev->next = node->next;
node->next->prev = node->prev;
}
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG, "[READYLIST] REMOVED NODE %p (SC %p)", (void *)node,
(void *)node->subchannel);
gpr_log(GPR_DEBUG,
"[RR: %p] setting last_ready_subchannel_index=%lu (SC %p, CSC %p)",
(void *)p, (unsigned long)last_ready_index,
(void *)p->subchannels[last_ready_index].subchannel,
(void *)grpc_subchannel_get_connected_subchannel(
p->subchannels[last_ready_index].subchannel));
}
node->next = NULL;
node->prev = NULL;
node->subchannel = NULL;
gpr_free(node);
}
static bool is_ready_list_empty(round_robin_lb_policy *p) {
return p->ready_list.prev == NULL;
}
static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
ready_list *elem;
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG, "Destroying Round Robin policy at %p", (void *)pol);
}
for (size_t i = 0; i < p->num_subchannels; i++) {
subchannel_data *sd = p->subchannels[i];
GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "rr_destroy");
if (sd->user_data != NULL) {
GPR_ASSERT(sd->user_data_vtable != NULL);
sd->user_data_vtable->destroy(exec_ctx, sd->user_data);
subchannel_data *sd = &p->subchannels[i];
if (sd->subchannel != NULL) {
GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "rr_destroy");
if (sd->user_data != NULL) {
GPR_ASSERT(sd->user_data_vtable != NULL);
sd->user_data_vtable->destroy(exec_ctx, sd->user_data);
}
}
gpr_free(sd);
}
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
gpr_free(p->subchannels);
elem = p->ready_list.next;
while (elem != NULL && elem != &p->ready_list) {
ready_list *tmp;
tmp = elem->next;
elem->next = NULL;
elem->prev = NULL;
elem->subchannel = NULL;
gpr_free(elem);
elem = tmp;
}
gpr_free(p);
}
static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
size_t i;
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG, "Shutting down Round Robin policy at %p", (void *)pol);
}
p->shutdown = 1;
p->shutdown = true;
pending_pick *pp;
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
@ -328,10 +243,13 @@ static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "rr_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,
&sd->connectivity_changed_closure);
for (size_t i = 0; i < p->num_subchannels; i++) {
subchannel_data *sd = &p->subchannels[i];
if (sd->subchannel != NULL) {
grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL,
NULL,
&sd->connectivity_changed_closure);
}
}
}
@ -339,8 +257,7 @@ static void rr_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_connected_subchannel **target,
grpc_error *error) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
pp = p->pending_picks;
pending_pick *pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
pending_pick *next = pp->next;
@ -364,8 +281,7 @@ static void rr_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
uint32_t initial_metadata_flags_eq,
grpc_error *error) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
pp = p->pending_picks;
pending_pick *pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
pending_pick *next = pp->next;
@ -387,21 +303,16 @@ static void rr_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
static void start_picking_locked(grpc_exec_ctx *exec_ctx,
round_robin_lb_policy *p) {
size_t i;
p->started_picking = 1;
for (i = 0; i < p->num_subchannels; i++) {
subchannel_data *sd = p->subchannels[i];
/* use some sentinel value outside of the range of grpc_connectivity_state
* to signal an undefined previous state. We won't be referring to this
* value again and it'll be overwritten after the first call to
* rr_connectivity_changed */
sd->prev_connectivity_state = GRPC_CHANNEL_INIT;
sd->curr_connectivity_state = GRPC_CHANNEL_IDLE;
GRPC_LB_POLICY_WEAK_REF(&p->base, "rr_connectivity");
grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, p->base.interested_parties,
&sd->curr_connectivity_state, &sd->connectivity_changed_closure);
p->started_picking = true;
for (size_t i = 0; i < p->num_subchannels; i++) {
subchannel_data *sd = &p->subchannels[i];
if (sd->subchannel != NULL) {
GRPC_LB_POLICY_WEAK_REF(&p->base, "rr_connectivity");
grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, p->base.interested_parties,
&sd->pending_connectivity_state_unsafe,
&sd->connectivity_changed_closure);
}
}
}
@ -418,36 +329,32 @@ static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_call_context_element *context, void **user_data,
grpc_closure *on_complete) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
ready_list *selected;
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO, "Round Robin %p trying to pick", (void *)pol);
}
if ((selected = peek_next_connected_locked(p))) {
const size_t next_ready_index = get_next_ready_subchannel_index_locked(p);
if (next_ready_index < p->num_subchannels) {
/* readily available, report right away */
subchannel_data *sd = &p->subchannels[next_ready_index];
*target = GRPC_CONNECTED_SUBCHANNEL_REF(
grpc_subchannel_get_connected_subchannel(selected->subchannel),
"rr_picked");
grpc_subchannel_get_connected_subchannel(sd->subchannel), "rr_picked");
if (user_data != NULL) {
*user_data = selected->user_data;
*user_data = sd->user_data;
}
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG,
"[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (NODE %p)",
(void *)*target, (void *)selected);
"[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (INDEX %lu)",
(void *)*target, (unsigned long)next_ready_index);
}
/* only advance the last picked pointer if the selection was used */
advance_last_picked_locked(p);
update_last_ready_subchannel_index_locked(p, next_ready_index);
return 1;
} else {
/* no pick currently available. Save for later in list of pending picks */
if (!p->started_picking) {
start_picking_locked(exec_ctx, p);
}
pp = gpr_malloc(sizeof(*pp));
pending_pick *pp = gpr_malloc(sizeof(*pp));
pp->next = p->pending_picks;
pp->target = target;
pp->on_complete = on_complete;
@ -458,25 +365,31 @@ static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
}
static void update_state_counters(subchannel_data *sd) {
static void update_state_counters_locked(subchannel_data *sd) {
round_robin_lb_policy *p = sd->policy;
/* update p->num_transient_failures (resp. p->num_idle): if the previous
* state was TRANSIENT_FAILURE (resp. IDLE), decrement
* p->num_transient_failures (resp. p->num_idle). */
if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
if (sd->prev_connectivity_state == GRPC_CHANNEL_READY) {
GPR_ASSERT(p->num_ready > 0);
--p->num_ready;
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
GPR_ASSERT(p->num_transient_failures > 0);
--p->num_transient_failures;
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
GPR_ASSERT(p->num_idle > 0);
--p->num_idle;
}
if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) {
++p->num_ready;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
++p->num_transient_failures;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_IDLE) {
++p->num_idle;
}
}
/* sd is the subchannel_data associted with the updated subchannel.
* shutdown_error will only be used upon policy transition to TRANSIENT_FAILURE
* or SHUTDOWN */
static grpc_connectivity_state update_lb_connectivity_status(
static grpc_connectivity_state update_lb_connectivity_status_locked(
grpc_exec_ctx *exec_ctx, subchannel_data *sd, grpc_error *error) {
/* In priority order. The first rule to match terminates the search (ie, if we
* are on rule n, all previous rules were unfulfilled).
@ -498,7 +411,7 @@ static grpc_connectivity_state update_lb_connectivity_status(
* CHECK: p->num_idle == p->num_subchannels.
*/
round_robin_lb_policy *p = sd->policy;
if (!is_ready_list_empty(p)) { /* 1) READY */
if (p->num_ready > 0) { /* 1) READY */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY,
GRPC_ERROR_NONE, "rr_ready");
return GRPC_CHANNEL_READY;
@ -532,32 +445,62 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
subchannel_data *sd = arg;
round_robin_lb_policy *p = sd->policy;
pending_pick *pp;
GRPC_ERROR_REF(error);
// Now that we're inside the combiner, copy the pending connectivity
// state (which was set by the connectivity state watcher) to
// curr_connectivity_state, which is what we use inside of the combiner.
sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe;
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG,
"[RR %p] connectivity changed for subchannel %p: "
"prev_state=%d new_state=%d",
p, sd->subchannel, sd->prev_connectivity_state,
sd->curr_connectivity_state);
}
// If we're shutting down, unref and return.
if (p->shutdown) {
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
GRPC_ERROR_UNREF(error);
return;
}
switch (sd->curr_connectivity_state) {
case GRPC_CHANNEL_INIT:
GPR_UNREACHABLE_CODE(return );
case GRPC_CHANNEL_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);
// Update state counters and determine new overall state.
update_state_counters_locked(sd);
sd->prev_connectivity_state = sd->curr_connectivity_state;
grpc_connectivity_state new_connectivity_state =
update_lb_connectivity_status_locked(exec_ctx, sd, GRPC_ERROR_REF(error));
// If the new state is SHUTDOWN, unref the subchannel, and if the new
// overall state is SHUTDOWN, clean up.
if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "rr_subchannel_shutdown");
sd->subchannel = NULL;
if (sd->user_data != NULL) {
GPR_ASSERT(sd->user_data_vtable != NULL);
sd->user_data_vtable->destroy(exec_ctx, sd->user_data);
}
if (new_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
/* the policy is shutting down. Flush all the pending picks... */
pending_pick *pp;
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
gpr_free(pp);
}
}
/* unref the "rr_connectivity" weak ref from start_picking */
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
} else {
if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) {
/* at this point we know there's at least one suitable subchannel. Go
* ahead and pick one and notify the pending suitors in
* p->pending_picks. This preemtively replicates rr_pick()'s actions. */
ready_list *selected = peek_next_connected_locked(p);
GPR_ASSERT(selected != NULL);
const size_t next_ready_index = get_next_ready_subchannel_index_locked(p);
GPR_ASSERT(next_ready_index < p->num_subchannels);
subchannel_data *selected = &p->subchannels[next_ready_index];
if (p->pending_picks != NULL) {
/* if the selected subchannel is going to be used for the pending
* picks, update the last picked pointer */
advance_last_picked_locked(p);
update_last_ready_subchannel_index_locked(p, next_ready_index);
}
pending_pick *pp;
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(
@ -568,72 +511,20 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
}
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_DEBUG,
"[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)",
(void *)selected->subchannel, (void *)selected);
"[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (INDEX %lu)",
(void *)selected->subchannel,
(unsigned long)next_ready_index);
}
grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
gpr_free(pp);
}
update_lb_connectivity_status(exec_ctx, sd, error);
sd->prev_connectivity_state = sd->curr_connectivity_state;
/* renew notification: reuses the "rr_connectivity" weak ref */
grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, p->base.interested_parties,
&sd->curr_connectivity_state, &sd->connectivity_changed_closure);
break;
case GRPC_CHANNEL_IDLE:
++p->num_idle;
/* fallthrough */
case GRPC_CHANNEL_CONNECTING:
update_state_counters(sd);
update_lb_connectivity_status(exec_ctx, sd, error);
sd->prev_connectivity_state = sd->curr_connectivity_state;
/* renew notification: reuses the "rr_connectivity" weak ref */
grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, p->base.interested_parties,
&sd->curr_connectivity_state, &sd->connectivity_changed_closure);
break;
case GRPC_CHANNEL_TRANSIENT_FAILURE:
++p->num_transient_failures;
/* remove from ready list if still present */
if (sd->ready_list_node != NULL) {
remove_disconnected_sc_locked(p, sd->ready_list_node);
sd->ready_list_node = NULL;
}
update_lb_connectivity_status(exec_ctx, sd, error);
sd->prev_connectivity_state = sd->curr_connectivity_state;
/* renew notification: reuses the "rr_connectivity" weak ref */
grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, p->base.interested_parties,
&sd->curr_connectivity_state, &sd->connectivity_changed_closure);
break;
case GRPC_CHANNEL_SHUTDOWN:
update_state_counters(sd);
if (sd->ready_list_node != NULL) {
remove_disconnected_sc_locked(p, sd->ready_list_node);
sd->ready_list_node = NULL;
}
--p->num_subchannels;
GPR_SWAP(subchannel_data *, p->subchannels[sd->index],
p->subchannels[p->num_subchannels]);
GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "rr_subchannel_shutdown");
p->subchannels[sd->index]->index = sd->index;
if (update_lb_connectivity_status(exec_ctx, sd, error) ==
GRPC_CHANNEL_SHUTDOWN) {
/* the policy is shutting down. Flush all the pending picks... */
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
gpr_free(pp);
}
}
gpr_free(sd);
/* unref the "rr_connectivity" weak ref from start_picking */
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
break;
}
/* renew notification: reuses the "rr_connectivity" weak ref */
grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, p->base.interested_parties,
&sd->pending_connectivity_state_unsafe,
&sd->connectivity_changed_closure);
}
GRPC_ERROR_UNREF(error);
}
static grpc_connectivity_state rr_check_connectivity_locked(
@ -654,10 +545,10 @@ static void rr_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
static void rr_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_closure *closure) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
ready_list *selected;
grpc_connected_subchannel *target;
if ((selected = peek_next_connected_locked(p))) {
target = GRPC_CONNECTED_SUBCHANNEL_REF(
const size_t next_ready_index = get_next_ready_subchannel_index_locked(p);
if (next_ready_index < p->num_subchannels) {
subchannel_data *selected = &p->subchannels[next_ready_index];
grpc_connected_subchannel *target = GRPC_CONNECTED_SUBCHANNEL_REF(
grpc_subchannel_get_connected_subchannel(selected->subchannel),
"rr_picked");
grpc_connected_subchannel_ping(exec_ctx, target, closure);
@ -708,7 +599,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
p->subchannels = gpr_zalloc(sizeof(*p->subchannels) * num_addrs);
grpc_subchannel_args sc_args;
size_t subchannel_idx = 0;
size_t subchannel_index = 0;
for (size_t i = 0; i < addresses->num_addresses; i++) {
/* Skip balancer addresses, since we only know how to handle backends. */
if (addresses->addresses[i].is_balancer) continue;
@ -727,42 +618,44 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
char *address_uri =
grpc_sockaddr_to_uri(&addresses->addresses[i].address);
gpr_log(GPR_DEBUG, "Created subchannel %p for address uri %s",
(void *)subchannel, address_uri);
gpr_log(GPR_DEBUG, "index %lu: Created subchannel %p for address uri %s",
(unsigned long)subchannel_index, (void *)subchannel, address_uri);
gpr_free(address_uri);
}
grpc_channel_args_destroy(exec_ctx, new_args);
if (subchannel != NULL) {
subchannel_data *sd = gpr_zalloc(sizeof(*sd));
p->subchannels[subchannel_idx] = sd;
subchannel_data *sd = &p->subchannels[subchannel_index];
sd->policy = p;
sd->index = subchannel_idx;
sd->subchannel = subchannel;
/* use some sentinel value outside of the range of grpc_connectivity_state
* to signal an undefined previous state. We won't be referring to this
* value again and it'll be overwritten after the first call to
* rr_connectivity_changed */
sd->prev_connectivity_state = GRPC_CHANNEL_INIT;
sd->curr_connectivity_state = GRPC_CHANNEL_IDLE;
sd->user_data_vtable = addresses->user_data_vtable;
if (sd->user_data_vtable != NULL) {
sd->user_data =
sd->user_data_vtable->copy(addresses->addresses[i].user_data);
}
++subchannel_idx;
grpc_closure_init(&sd->connectivity_changed_closure,
rr_connectivity_changed_locked, sd,
grpc_combiner_scheduler(args->combiner, false));
++subchannel_index;
}
}
if (subchannel_idx == 0) {
if (subchannel_index == 0) {
/* couldn't create any subchannel. Bail out */
gpr_free(p->subchannels);
gpr_free(p);
return NULL;
}
p->num_subchannels = subchannel_idx;
p->num_subchannels = subchannel_index;
/* The (dummy node) root of the ready list */
p->ready_list.subchannel = NULL;
p->ready_list.prev = NULL;
p->ready_list.next = NULL;
p->ready_list_last_pick = &p->ready_list;
// Initialize the last pick index to the last subchannel, so that the
// first pick will start at the beginning of the list.
p->last_ready_subchannel_index = subchannel_index - 1;
grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner);
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,

@ -57,11 +57,11 @@ bool grpc_parse_unix(const grpc_uri *uri,
struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
const size_t maxlen = sizeof(un->sun_path);
const size_t path_len = strnlen(uri->path, maxlen);
if (path_len == maxlen) return 0;
if (path_len == maxlen) return false;
un->sun_family = AF_UNIX;
strcpy(un->sun_path, uri->path);
resolved_addr->len = sizeof(*un);
return 1;
return true;
}
#else /* GRPC_HAVE_UNIX_SOCKET */
@ -73,74 +73,65 @@ bool grpc_parse_unix(const grpc_uri *uri,
#endif /* GRPC_HAVE_UNIX_SOCKET */
bool grpc_parse_ipv4(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
if (strcmp("ipv4", uri->scheme) != 0) {
gpr_log(GPR_ERROR, "Expected 'ipv4' scheme, got '%s'", uri->scheme);
return false;
}
const char *host_port = uri->path;
bool grpc_parse_ipv4_hostport(const char *hostport, grpc_resolved_address *addr,
bool log_errors) {
bool success = false;
// Split host and port.
char *host;
char *port;
int port_num;
bool result = false;
struct sockaddr_in *in = (struct sockaddr_in *)resolved_addr->addr;
if (*host_port == '/') ++host_port;
if (!gpr_split_host_port(host_port, &host, &port)) {
return false;
}
memset(resolved_addr, 0, sizeof(grpc_resolved_address));
resolved_addr->len = sizeof(struct sockaddr_in);
if (!gpr_split_host_port(hostport, &host, &port)) return false;
// Parse IP address.
memset(addr, 0, sizeof(*addr));
addr->len = sizeof(struct sockaddr_in);
struct sockaddr_in *in = (struct sockaddr_in *)addr->addr;
in->sin_family = AF_INET;
if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
goto done;
}
if (port != NULL) {
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
goto done;
}
in->sin_port = htons((uint16_t)port_num);
} else {
gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
// Parse port.
if (port == NULL) {
if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
goto done;
}
result = true;
int port_num;
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) {
if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
goto done;
}
in->sin_port = htons((uint16_t)port_num);
success = true;
done:
gpr_free(host);
gpr_free(port);
return result;
return success;
}
bool grpc_parse_ipv6(const grpc_uri *uri,
bool grpc_parse_ipv4(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
if (strcmp("ipv6", uri->scheme) != 0) {
gpr_log(GPR_ERROR, "Expected 'ipv6' scheme, got '%s'", uri->scheme);
if (strcmp("ipv4", uri->scheme) != 0) {
gpr_log(GPR_ERROR, "Expected 'ipv4' scheme, got '%s'", uri->scheme);
return false;
}
const char *host_port = uri->path;
char *host;
char *port;
int port_num;
int result = 0;
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)resolved_addr->addr;
if (*host_port == '/') ++host_port;
if (!gpr_split_host_port(host_port, &host, &port)) {
return 0;
}
return grpc_parse_ipv4_hostport(host_port, resolved_addr,
true /* log_errors */);
}
memset(in6, 0, sizeof(*in6));
resolved_addr->len = sizeof(*in6);
bool grpc_parse_ipv6_hostport(const char *hostport, grpc_resolved_address *addr,
bool log_errors) {
bool success = false;
// Split host and port.
char *host;
char *port;
if (!gpr_split_host_port(hostport, &host, &port)) return false;
// Parse IP address.
memset(addr, 0, sizeof(*addr));
addr->len = sizeof(struct sockaddr_in6);
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr->addr;
in6->sin6_family = AF_INET6;
/* Handle the RFC6874 syntax for IPv6 zone identifiers. */
// Handle the RFC6874 syntax for IPv6 zone identifiers.
char *host_end = (char *)gpr_memrchr(host, '%', strlen(host));
if (host_end != NULL) {
GPR_ASSERT(host_end >= host);
@ -159,7 +150,7 @@ bool grpc_parse_ipv6(const grpc_uri *uri,
gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1);
goto done;
}
// Handle "sin6_scope_id" being type "u_long". See grpc issue ##10027.
// Handle "sin6_scope_id" being type "u_long". See grpc issue #10027.
in6->sin6_scope_id = sin6_scope_id;
} else {
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
@ -167,24 +158,34 @@ bool grpc_parse_ipv6(const grpc_uri *uri,
goto done;
}
}
if (port != NULL) {
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
goto done;
}
in6->sin6_port = htons((uint16_t)port_num);
} else {
gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
// Parse port.
if (port == NULL) {
if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
goto done;
}
result = 1;
int port_num;
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) {
if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
goto done;
}
in6->sin6_port = htons((uint16_t)port_num);
success = true;
done:
gpr_free(host);
gpr_free(port);
return result;
return success;
}
bool grpc_parse_ipv6(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
if (strcmp("ipv6", uri->scheme) != 0) {
gpr_log(GPR_ERROR, "Expected 'ipv6' scheme, got '%s'", uri->scheme);
return false;
}
const char *host_port = uri->path;
if (*host_port == '/') ++host_port;
return grpc_parse_ipv6_hostport(host_port, resolved_addr,
true /* log_errors */);
}
bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr) {

@ -54,4 +54,10 @@ bool grpc_parse_ipv6(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
/** Populate \a resolved_addr from \a uri. Returns true upon success. */
bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
/** Parse bare IPv4 or IPv6 "IP:port" strings. */
bool grpc_parse_ipv4_hostport(const char *hostport, grpc_resolved_address *addr,
bool log_errors);
bool grpc_parse_ipv6_hostport(const char *hostport, grpc_resolved_address *addr,
bool log_errors);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */

@ -61,6 +61,8 @@
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** DNS server to use (if not system default) */
char *dns_server;
/** name to resolve (usually the same as target_name) */
char *name_to_resolve;
/** default port to use */
@ -172,6 +174,8 @@ static void dns_ares_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses_destroy(r->addresses);
grpc_lb_addresses_destroy(exec_ctx, addresses);
} else {
const char *msg = grpc_error_string(error);
gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg);
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);
@ -221,9 +225,9 @@ static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(!r->resolving);
r->resolving = true;
r->addresses = NULL;
grpc_resolve_address(exec_ctx, r->name_to_resolve, r->default_port,
r->interested_parties, &r->dns_ares_on_resolved_locked,
&r->addresses);
grpc_dns_lookup_ares(exec_ctx, r->dns_server, r->name_to_resolve,
r->default_port, r->interested_parties,
&r->dns_ares_on_resolved_locked, &r->addresses);
}
static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@ -246,6 +250,7 @@ static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result);
}
grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
gpr_free(r->dns_server);
gpr_free(r->name_to_resolve);
gpr_free(r->default_port);
grpc_channel_args_destroy(exec_ctx, r->channel_args);
@ -257,14 +262,13 @@ static grpc_resolver *dns_ares_create(grpc_exec_ctx *exec_ctx,
const char *default_port) {
// Get name from args.
const char *path = args->uri->path;
if (0 != strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based dns uri's not supported");
return NULL;
}
if (path[0] == '/') ++path;
// Create resolver.
ares_dns_resolver *r = gpr_zalloc(sizeof(ares_dns_resolver));
grpc_resolver_init(&r->base, &dns_ares_resolver_vtable, args->combiner);
if (0 != strcmp(args->uri->authority, "")) {
r->dns_server = gpr_strdup(args->uri->authority);
}
r->name_to_resolve = gpr_strdup(path);
r->default_port = gpr_strdup(default_port);
r->channel_args = grpc_channel_args_copy(args->args);

@ -48,7 +48,10 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@ -58,6 +61,8 @@ static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu;
typedef struct grpc_ares_request {
/** indicates the DNS server to use, if specified */
struct ares_addr_port_node dns_server_addr;
/** following members are set in grpc_resolve_address_ares_impl */
/** host to resolve, parsed from the name to resolve */
char *host;
@ -192,11 +197,12 @@ static void on_done_cb(void *arg, int status, int timeouts,
grpc_ares_request_unref(NULL, r);
}
void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port,
grpc_pollset_set *interested_parties,
grpc_closure *on_done,
grpc_resolved_addresses **addrs) {
void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
const char *name, const char *default_port,
grpc_pollset_set *interested_parties,
grpc_closure *on_done,
grpc_resolved_addresses **addrs) {
grpc_error *error = GRPC_ERROR_NONE;
/* TODO(zyc): Enable tracing after #9603 is checked in */
/* if (grpc_dns_trace) {
gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s",
@ -208,28 +214,23 @@ void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
char *port;
gpr_split_host_port(name, &host, &port);
if (host == NULL) {
grpc_error *err = grpc_error_set_str(
error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
grpc_closure_sched(exec_ctx, on_done, err);
goto error_cleanup;
} else if (port == NULL) {
if (default_port == NULL) {
grpc_error *err = grpc_error_set_str(
error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
grpc_closure_sched(exec_ctx, on_done, err);
goto error_cleanup;
}
port = gpr_strdup(default_port);
}
grpc_ares_ev_driver *ev_driver;
grpc_error *err = grpc_ares_ev_driver_create(&ev_driver, interested_parties);
if (err != GRPC_ERROR_NONE) {
GRPC_LOG_IF_ERROR("grpc_ares_ev_driver_create() failed", err);
goto error_cleanup;
}
error = grpc_ares_ev_driver_create(&ev_driver, interested_parties);
if (error != GRPC_ERROR_NONE) goto error_cleanup;
grpc_ares_request *r = gpr_malloc(sizeof(grpc_ares_request));
gpr_mu_init(&r->mu);
@ -242,6 +243,40 @@ void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
r->success = false;
r->error = GRPC_ERROR_NONE;
ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
// If dns_server is specified, use it.
if (dns_server != NULL) {
gpr_log(GPR_INFO, "Using DNS server %s", dns_server);
grpc_resolved_address addr;
if (grpc_parse_ipv4_hostport(dns_server, &addr, false /* log_errors */)) {
r->dns_server_addr.family = AF_INET;
memcpy(&r->dns_server_addr.addr.addr4, addr.addr, addr.len);
r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
} else if (grpc_parse_ipv6_hostport(dns_server, &addr,
false /* log_errors */)) {
r->dns_server_addr.family = AF_INET6;
memcpy(&r->dns_server_addr.addr.addr6, addr.addr, addr.len);
r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
} else {
error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
goto error_cleanup;
}
int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
if (status != ARES_SUCCESS) {
char *error_msg;
gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
ares_strerror(status));
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg);
goto error_cleanup;
}
}
// An extra reference is put here to avoid destroying the request in
// on_done_cb before calling grpc_ares_ev_driver_start.
gpr_ref_init(&r->pending_queries, 2);
if (grpc_ipv6_loopback_available()) {
gpr_ref(&r->pending_queries);
@ -254,10 +289,20 @@ void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
return;
error_cleanup:
grpc_closure_sched(exec_ctx, on_done, error);
gpr_free(host);
gpr_free(port);
}
void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port,
grpc_pollset_set *interested_parties,
grpc_closure *on_done,
grpc_resolved_addresses **addrs) {
grpc_dns_lookup_ares(exec_ctx, NULL /* dns_server */, name, default_port,
interested_parties, on_done, addrs);
}
void (*grpc_resolve_address_ares)(
grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
grpc_pollset_set *interested_parties, grpc_closure *on_done,

@ -51,6 +51,12 @@ extern void (*grpc_resolve_address_ares)(grpc_exec_ctx *exec_ctx,
grpc_closure *on_done,
grpc_resolved_addresses **addresses);
void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
const char *addr, const char *default_port,
grpc_pollset_set *interested_parties,
grpc_closure *on_done,
grpc_resolved_addresses **addresses);
/* Initialize gRPC ares wrapper. Must be called at least once before
grpc_resolve_address_ares(). */
grpc_error *grpc_ares_init(void);

@ -127,6 +127,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
gpr_mu_lock(&state->mu);
if (state->shutdown) {
gpr_mu_unlock(&state->mu);
grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_NONE);
grpc_endpoint_destroy(exec_ctx, tcp);
gpr_free(acceptor);
return;

@ -105,7 +105,7 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
grpc_error *error) {
grpc_polling_entity_del_from_pollset_set(exec_ctx, req->pollent,
req->context->pollset_set);
grpc_closure_sched(exec_ctx, req->on_done, GRPC_ERROR_REF(error));
grpc_closure_sched(exec_ctx, req->on_done, error);
grpc_http_parser_destroy(&req->parser);
if (req->addresses != NULL) {
grpc_resolved_addresses_destroy(req->addresses);
@ -244,7 +244,7 @@ static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
internal_request *req = arg;
if (error != GRPC_ERROR_NONE) {
finish(exec_ctx, req, error);
finish(exec_ctx, req, GRPC_ERROR_REF(error));
return;
}
req->next_address = 0;

@ -44,6 +44,7 @@
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_adapter.h"
typedef struct {
grpc_channel_security_connector base;
@ -78,7 +79,8 @@ static void httpcli_ssl_add_handshakers(grpc_exec_ctx *exec_ctx,
}
grpc_handshake_manager_add(
handshake_mgr,
grpc_security_handshaker_create(exec_ctx, handshaker, &sc->base));
grpc_security_handshaker_create(
exec_ctx, tsi_create_adapter_handshaker(handshaker), &sc->base));
}
static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,

@ -56,6 +56,7 @@
#include "src/core/lib/support/string.h"
#include "src/core/tsi/fake_transport_security.h"
#include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_adapter.h"
/* -- Constants. -- */
@ -390,7 +391,8 @@ static void fake_channel_add_handshakers(
grpc_handshake_manager_add(
handshake_mgr,
grpc_security_handshaker_create(
exec_ctx, tsi_create_fake_handshaker(true /* is_client */),
exec_ctx, tsi_create_adapter_handshaker(
tsi_create_fake_handshaker(true /* is_client */)),
&sc->base));
}
@ -400,7 +402,8 @@ static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx,
grpc_handshake_manager_add(
handshake_mgr,
grpc_security_handshaker_create(
exec_ctx, tsi_create_fake_handshaker(false /* is_client */),
exec_ctx, tsi_create_adapter_handshaker(
tsi_create_fake_handshaker(false /* is_client */)),
&sc->base));
}
@ -495,8 +498,10 @@ static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx,
}
// Create handshakers.
grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
exec_ctx, tsi_hs, &sc->base));
grpc_handshake_manager_add(
handshake_mgr,
grpc_security_handshaker_create(
exec_ctx, tsi_create_adapter_handshaker(tsi_hs), &sc->base));
}
static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx,
@ -515,8 +520,10 @@ static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx,
}
// Create handshakers.
grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create(
exec_ctx, tsi_hs, &sc->base));
grpc_handshake_manager_add(
handshake_mgr,
grpc_security_handshaker_create(
exec_ctx, tsi_create_adapter_handshaker(tsi_hs), &sc->base));
}
static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) {

@ -71,12 +71,12 @@ typedef struct {
unsigned char *handshake_buffer;
size_t handshake_buffer_size;
grpc_slice_buffer left_overs;
grpc_slice_buffer outgoing;
grpc_closure on_handshake_data_sent_to_peer;
grpc_closure on_handshake_data_received_from_peer;
grpc_closure on_peer_checked;
grpc_auth_context *auth_context;
tsi_handshaker_result *handshaker_result;
} security_handshaker;
static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
@ -84,6 +84,7 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
if (gpr_unref(&h->refs)) {
gpr_mu_destroy(&h->mu);
tsi_handshaker_destroy(h->handshaker);
tsi_handshaker_result_destroy(h->handshaker_result);
if (h->endpoint_to_destroy != NULL) {
grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy);
}
@ -92,7 +93,6 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
gpr_free(h->read_buffer_to_destroy);
}
gpr_free(h->handshake_buffer);
grpc_slice_buffer_destroy_internal(exec_ctx, &h->left_overs);
grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing);
GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake");
@ -150,10 +150,10 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error));
goto done;
}
// Get frame protector.
// Create frame protector.
tsi_frame_protector *protector;
tsi_result result =
tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
tsi_result result = tsi_handshaker_result_create_frame_protector(
h->handshaker_result, NULL, &protector);
if (result != TSI_OK) {
error = grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Frame protector creation failed"),
@ -161,14 +161,25 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
security_handshake_failed_locked(exec_ctx, h, error);
goto done;
}
// Success.
// Get unused bytes.
unsigned char *unused_bytes = NULL;
size_t unused_bytes_size = 0;
result = tsi_handshaker_result_get_unused_bytes(
h->handshaker_result, &unused_bytes, &unused_bytes_size);
// Create secure endpoint.
h->args->endpoint = grpc_secure_endpoint_create(
protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count);
h->left_overs.count = 0;
h->left_overs.length = 0;
// Clear out the read buffer before it gets passed to the transport,
// since any excess bytes were already copied to h->left_overs.
if (unused_bytes_size > 0) {
grpc_slice slice =
grpc_slice_from_copied_buffer((char *)unused_bytes, unused_bytes_size);
h->args->endpoint =
grpc_secure_endpoint_create(protector, h->args->endpoint, &slice, 1);
grpc_slice_unref_internal(exec_ctx, slice);
} else {
h->args->endpoint =
grpc_secure_endpoint_create(protector, h->args->endpoint, NULL, 0);
}
tsi_handshaker_result_destroy(h->handshaker_result);
h->handshaker_result = NULL;
// Clear out the read buffer before it gets passed to the transport.
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer);
// Add auth context to channel args.
grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context);
@ -189,7 +200,8 @@ done:
static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
security_handshaker *h) {
tsi_peer peer;
tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
tsi_result result =
tsi_handshaker_result_extract_peer(h->handshaker_result, &peer);
if (result != TSI_OK) {
return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result);
@ -199,34 +211,87 @@ static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_NONE;
}
static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx,
security_handshaker *h) {
// Get data to send.
tsi_result result = TSI_OK;
size_t offset = 0;
do {
size_t to_send_size = h->handshake_buffer_size - offset;
result = tsi_handshaker_get_bytes_to_send_to_peer(
h->handshaker, h->handshake_buffer + offset, &to_send_size);
offset += to_send_size;
if (result == TSI_INCOMPLETE_DATA) {
h->handshake_buffer_size *= 2;
h->handshake_buffer =
gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
}
} while (result == TSI_INCOMPLETE_DATA);
static grpc_error *on_handshake_next_done_locked(
grpc_exec_ctx *exec_ctx, security_handshaker *h, tsi_result result,
const unsigned char *bytes_to_send, size_t bytes_to_send_size,
tsi_handshaker_result *handshaker_result) {
grpc_error *error = GRPC_ERROR_NONE;
// Read more if we need to.
if (result == TSI_INCOMPLETE_DATA) {
GPR_ASSERT(bytes_to_send_size == 0);
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer);
return error;
}
if (result != TSI_OK) {
return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result);
}
// Send data.
grpc_slice to_send =
grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
grpc_slice_buffer_add(&h->outgoing, to_send);
grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
&h->on_handshake_data_sent_to_peer);
return GRPC_ERROR_NONE;
// Update handshaker result.
if (handshaker_result != NULL) {
GPR_ASSERT(h->handshaker_result == NULL);
h->handshaker_result = handshaker_result;
}
if (bytes_to_send_size > 0) {
// Send data to peer, if needed.
grpc_slice to_send = grpc_slice_from_copied_buffer(
(const char *)bytes_to_send, bytes_to_send_size);
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
grpc_slice_buffer_add(&h->outgoing, to_send);
grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
&h->on_handshake_data_sent_to_peer);
} else if (handshaker_result == NULL) {
// There is nothing to send, but need to read from peer.
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer);
} else {
// Handshake has finished, check peer and so on.
error = check_peer_locked(exec_ctx, h);
}
return error;
}
static void on_handshake_next_done_grpc_wrapper(
tsi_result result, void *user_data, const unsigned char *bytes_to_send,
size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) {
security_handshaker *h = user_data;
// This callback will be invoked by TSI in a non-grpc thread, so it's
// safe to create our own exec_ctx here.
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_mu_lock(&h->mu);
grpc_error *error =
on_handshake_next_done_locked(&exec_ctx, h, result, bytes_to_send,
bytes_to_send_size, handshaker_result);
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(&exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
security_handshaker_unref(&exec_ctx, h);
} else {
gpr_mu_unlock(&h->mu);
}
grpc_exec_ctx_finish(&exec_ctx);
}
static grpc_error *do_handshaker_next_locked(
grpc_exec_ctx *exec_ctx, security_handshaker *h,
const unsigned char *bytes_received, size_t bytes_received_size) {
// Invoke TSI handshaker.
unsigned char *bytes_to_send = NULL;
size_t bytes_to_send_size = 0;
tsi_handshaker_result *handshaker_result = NULL;
tsi_result result = tsi_handshaker_next(
h->handshaker, bytes_received, bytes_received_size, &bytes_to_send,
&bytes_to_send_size, &handshaker_result,
&on_handshake_next_done_grpc_wrapper, h);
if (result == TSI_ASYNC) {
// Handshaker operating asynchronously. Nothing else to do here;
// callback will be invoked in a TSI thread.
return GRPC_ERROR_NONE;
}
// Handshaker returned synchronously. Invoke callback directly in
// this thread with our existing exec_ctx.
return on_handshake_next_done_locked(exec_ctx, h, result, bytes_to_send,
bytes_to_send_size, handshaker_result);
}
static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
@ -241,72 +306,34 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
security_handshaker_unref(exec_ctx, h);
return;
}
// Process received data.
tsi_result result = TSI_OK;
size_t consumed_slice_size = 0;
// Copy all slices received.
size_t i;
size_t bytes_received_size = 0;
for (i = 0; i < h->args->read_buffer->count; i++) {
consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
result = tsi_handshaker_process_bytes_from_peer(
h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]),
&consumed_slice_size);
if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
bytes_received_size += GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
}
if (tsi_handshaker_is_in_progress(h->handshaker)) {
/* We may need more data. */
if (result == TSI_INCOMPLETE_DATA) {
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer);
goto done;
} else {
error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
security_handshaker_unref(exec_ctx, h);
return;
}
goto done;
}
if (bytes_received_size > h->handshake_buffer_size) {
h->handshake_buffer = gpr_realloc(h->handshake_buffer, bytes_received_size);
h->handshake_buffer_size = bytes_received_size;
}
if (result != TSI_OK) {
security_handshake_failed_locked(
exec_ctx, h,
grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result));
gpr_mu_unlock(&h->mu);
security_handshaker_unref(exec_ctx, h);
return;
}
/* Handshake is done and successful this point. */
bool has_left_overs_in_current_slice =
(consumed_slice_size <
GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]));
size_t num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) +
h->args->read_buffer->count - i - 1;
if (num_left_overs > 0) {
/* Put the leftovers in our buffer (ownership transfered). */
if (has_left_overs_in_current_slice) {
grpc_slice tail = grpc_slice_split_tail(&h->args->read_buffer->slices[i],
consumed_slice_size);
grpc_slice_buffer_add(&h->left_overs, tail);
/* split_tail above increments refcount. */
grpc_slice_unref_internal(exec_ctx, tail);
}
grpc_slice_buffer_addn(
&h->left_overs, &h->args->read_buffer->slices[i + 1],
num_left_overs - (size_t)has_left_overs_in_current_slice);
size_t offset = 0;
for (i = 0; i < h->args->read_buffer->count; i++) {
size_t slice_size = GPR_SLICE_LENGTH(h->args->read_buffer->slices[i]);
memcpy(h->handshake_buffer + offset,
GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), slice_size);
offset += slice_size;
}
// Check peer.
error = check_peer_locked(exec_ctx, h);
// Call TSI handshaker.
error = do_handshaker_next_locked(exec_ctx, h, h->handshake_buffer,
bytes_received_size);
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
security_handshaker_unref(exec_ctx, h);
return;
} else {
gpr_mu_unlock(&h->mu);
}
done:
gpr_mu_unlock(&h->mu);
}
static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
@ -321,8 +348,8 @@ static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
security_handshaker_unref(exec_ctx, h);
return;
}
/* We may be done. */
if (tsi_handshaker_is_in_progress(h->handshaker)) {
// We may be done.
if (h->handshaker_result == NULL) {
grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
&h->on_handshake_data_received_from_peer);
} else {
@ -371,7 +398,7 @@ static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
h->args = args;
h->on_handshake_done = on_handshake_done;
gpr_ref(&h->refs);
grpc_error *error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
grpc_error *error = do_handshaker_next_locked(exec_ctx, h, NULL, 0);
if (error != GRPC_ERROR_NONE) {
security_handshake_failed_locked(exec_ctx, h, error);
gpr_mu_unlock(&h->mu);
@ -404,7 +431,6 @@ static grpc_handshaker *security_handshaker_create(
grpc_schedule_on_exec_ctx);
grpc_closure_init(&h->on_peer_checked, on_peer_checked, h,
grpc_schedule_on_exec_ctx);
grpc_slice_buffer_init(&h->left_overs);
grpc_slice_buffer_init(&h->outgoing);
return &h->base;
}

@ -37,5 +37,5 @@
#include <grpc++/grpc++.h>
namespace grpc {
grpc::string Version() { return "1.4.0-dev"; }
grpc::string Version() { return "1.5.0-dev"; }
}

@ -180,6 +180,10 @@ ServerBuilder& ServerBuilder::AddListeningPort(
}
std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin)->UpdateServerBuilder(this);
}
ChannelArguments args;
for (auto option = options_.begin(); option != options_.end(); ++option) {
(*option)->UpdateArguments(&args);

@ -0,0 +1,7 @@
root = true
[**]
end_of_line = LF
indent_style = space
indent_size = 4
insert_final_newline = true
tab_width = 4

@ -16,6 +16,8 @@
<PackageProjectUrl>https://github.com/grpc/grpc</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</PackageLicenseUrl>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.5' ">1.6.0</NetStandardImplicitPackageVersion>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSource>true</IncludeSource>
</PropertyGroup>
<ItemGroup>
@ -23,7 +25,9 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj" />
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj">
<PrivateAssets>None</PrivateAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup>

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\Grpc.Core\Version.csproj.include" />
<Import Project="..\Grpc.Core\Common.csproj.include" />
@ -16,6 +16,8 @@
<PackageProjectUrl>https://github.com/grpc/grpc</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</PackageLicenseUrl>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.5' ">1.6.0</NetStandardImplicitPackageVersion>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSource>true</IncludeSource>
</PropertyGroup>
<ItemGroup>
@ -23,7 +25,9 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj" />
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj">
<PrivateAssets>None</PrivateAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">

@ -59,6 +59,8 @@ namespace Grpc.Core
readonly ChannelSafeHandle handle;
readonly Dictionary<string, ChannelOption> options;
readonly Task connectivityWatcherTask;
bool shutdownRequested;
/// <summary>
@ -99,6 +101,9 @@ namespace Grpc.Core
this.handle = ChannelSafeHandle.CreateInsecure(target, nativeChannelArgs);
}
}
// TODO(jtattermusch): Workaround for https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/822.
// Remove once retries are supported in C core
this.connectivityWatcherTask = RunConnectivityWatcherAsync();
GrpcEnvironment.RegisterChannel(this);
}
@ -244,7 +249,7 @@ namespace Grpc.Core
handle.Dispose();
await GrpcEnvironment.ReleaseAsync().ConfigureAwait(false);
await Task.WhenAll(GrpcEnvironment.ReleaseAsync(), connectivityWatcherTask).ConfigureAwait(false);
}
internal ChannelSafeHandle Handle
@ -299,6 +304,40 @@ namespace Grpc.Core
}
}
/// <summary>
/// Constantly Watches channel connectivity status to work around https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/822
/// </summary>
private async Task RunConnectivityWatcherAsync()
{
try
{
var lastState = State;
while (lastState != ChannelState.Shutdown)
{
lock (myLock)
{
if (shutdownRequested)
{
break;
}
}
try
{
await WaitForStateChangedAsync(lastState, DateTime.UtcNow.AddSeconds(1)).ConfigureAwait(false);
}
catch (TaskCanceledException)
{
// ignore timeout
}
lastState = State;
}
}
catch (ObjectDisposedException) {
// during shutdown, channel is going to be disposed.
}
}
private static void EnsureUserAgentChannelOption(Dictionary<string, ChannelOption> options)
{
var key = ChannelOptions.PrimaryUserAgentString;

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="Version.csproj.include" />
<Import Project="Common.csproj.include" />
@ -15,6 +15,8 @@
<PackageProjectUrl>https://github.com/grpc/grpc</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</PackageLicenseUrl>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.5' ">1.6.0</NetStandardImplicitPackageVersion>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSource>true</IncludeSource>
</PropertyGroup>
<ItemGroup>

@ -72,7 +72,10 @@ namespace Grpc.Core.Internal
/// </summary>
public static void CheckOk(this CallError callError)
{
GrpcPreconditions.CheckState(callError == CallError.OK, "Call error: " + callError);
if (callError != CallError.OK)
{
throw new InvalidOperationException("Call error: " + callError);
}
}
}
}

@ -218,5 +218,16 @@ namespace Grpc.Core.Internal
{
return buffered ? 0 : GRPC_WRITE_BUFFER_HINT;
}
/// <summary>
/// Only for testing.
/// </summary>
public static CallSafeHandle CreateFake(IntPtr ptr, CompletionQueueSafeHandle cq)
{
var call = new CallSafeHandle();
call.SetHandle(ptr);
call.Initialize(cq);
return call;
}
}
}

@ -52,6 +52,7 @@ namespace Grpc.Core.Internal
readonly GrpcEnvironment environment;
readonly ConcurrentDictionary<IntPtr, OpCompletionDelegate> dict = new ConcurrentDictionary<IntPtr, OpCompletionDelegate>(new IntPtrComparer());
IntPtr lastRegisteredKey; // only for testing
public CompletionRegistry(GrpcEnvironment environment)
{
@ -62,6 +63,7 @@ namespace Grpc.Core.Internal
{
environment.DebugStats.PendingBatchCompletions.Increment();
GrpcPreconditions.CheckState(dict.TryAdd(key, callback));
this.lastRegisteredKey = key;
}
public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback)
@ -84,6 +86,14 @@ namespace Grpc.Core.Internal
return value;
}
/// <summary>
/// For testing purposes only.
/// </summary>
public IntPtr LastRegisteredKey
{
get { return this.lastRegisteredKey; }
}
private static void HandleBatchCompletion(bool success, BatchContextSafeHandle ctx, BatchCompletionDelegate callback)
{
try

@ -164,6 +164,8 @@ namespace Grpc.Core.Internal
public readonly Delegates.grpcsharp_test_callback_delegate grpcsharp_test_callback;
public readonly Delegates.grpcsharp_test_nop_delegate grpcsharp_test_nop;
public readonly Delegates.grpcsharp_test_override_method_delegate grpcsharp_test_override_method;
#endregion
public NativeMethods(UnmanagedLibrary library)
@ -278,6 +280,7 @@ namespace Grpc.Core.Internal
this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library);
this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library);
this.grpcsharp_test_override_method = GetMethodDelegate<Delegates.grpcsharp_test_override_method_delegate>(library);
}
/// <summary>
@ -434,6 +437,7 @@ namespace Grpc.Core.Internal
public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback);
public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr);
public delegate void grpcsharp_test_override_method_delegate(string methodName, string variant);
}
}
}

@ -59,8 +59,14 @@ using System.Runtime.CompilerServices;
"0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
"27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
"71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
[assembly: InternalsVisibleTo("Grpc.Microbenchmarks,PublicKey=" +
"00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" +
"0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
"27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
"71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
#else
[assembly: InternalsVisibleTo("Grpc.Core.Tests")]
[assembly: InternalsVisibleTo("Grpc.Core.Testing")]
[assembly: InternalsVisibleTo("Grpc.IntegrationTesting")]
[assembly: InternalsVisibleTo("Grpc.Microbenchmarks")]
#endif

@ -1,7 +1,7 @@
<!-- This file is generated -->
<Project>
<PropertyGroup>
<GrpcCsharpVersion>1.4.0-dev</GrpcCsharpVersion>
<GrpcCsharpVersion>1.5.0-dev</GrpcCsharpVersion>
<GoogleProtobufVersion>3.3.0</GoogleProtobufVersion>
</PropertyGroup>
</Project>

@ -48,11 +48,11 @@ namespace Grpc.Core
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
public const string CurrentAssemblyFileVersion = "1.4.0.0";
public const string CurrentAssemblyFileVersion = "1.5.0.0";
/// <summary>
/// Current version of gRPC C#
/// </summary>
public const string CurrentVersion = "1.4.0-dev";
public const string CurrentVersion = "1.5.0-dev";
}
}

@ -15,6 +15,8 @@
<PackageProjectUrl>https://github.com/grpc/grpc</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</PackageLicenseUrl>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.5' ">1.6.0</NetStandardImplicitPackageVersion>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSource>true</IncludeSource>
</PropertyGroup>
<ItemGroup>
@ -22,7 +24,9 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj" />
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj">
<PrivateAssets>None</PrivateAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup>

@ -140,7 +140,8 @@ namespace Grpc.IntegrationTesting
readonly ClientType clientType;
readonly RpcType rpcType;
readonly PayloadConfig payloadConfig;
readonly Histogram histogram;
readonly Lazy<byte[]> cachedByteBufferRequest;
readonly ThreadLocal<Histogram> threadLocalHistogram;
readonly List<Task> runnerTasks;
readonly CancellationTokenSource stoppedCts = new CancellationTokenSource();
@ -155,7 +156,8 @@ namespace Grpc.IntegrationTesting
this.clientType = clientType;
this.rpcType = rpcType;
this.payloadConfig = payloadConfig;
this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible);
this.cachedByteBufferRequest = new Lazy<byte[]>(() => new byte[payloadConfig.BytebufParams.ReqSize]);
this.threadLocalHistogram = new ThreadLocal<Histogram>(() => new Histogram(histogramParams.Resolution, histogramParams.MaxPossible), true);
this.runnerTasks = new List<Task>();
foreach (var channel in this.channels)
@ -171,7 +173,12 @@ namespace Grpc.IntegrationTesting
public ClientStats GetStats(bool reset)
{
var histogramData = histogram.GetSnapshot(reset);
var histogramData = new HistogramData();
foreach (var hist in threadLocalHistogram.Values)
{
hist.GetSnapshot(histogramData, reset);
}
var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
if (reset)
@ -232,7 +239,7 @@ namespace Grpc.IntegrationTesting
stopwatch.Stop();
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
timer.WaitForNext();
}
@ -251,7 +258,7 @@ namespace Grpc.IntegrationTesting
stopwatch.Stop();
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
await timer.WaitForNextAsync();
}
@ -273,7 +280,7 @@ namespace Grpc.IntegrationTesting
stopwatch.Stop();
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
await timer.WaitForNextAsync();
}
@ -286,7 +293,7 @@ namespace Grpc.IntegrationTesting
private async Task RunGenericStreamingAsync(Channel channel, IInterarrivalTimer timer)
{
var request = CreateByteBufferRequest();
var request = cachedByteBufferRequest.Value;
var stopwatch = new Stopwatch();
var callDetails = new CallInvocationDetails<byte[], byte[]>(channel, GenericService.StreamingCallMethod, new CallOptions());
@ -301,7 +308,7 @@ namespace Grpc.IntegrationTesting
stopwatch.Stop();
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
await timer.WaitForNextAsync();
}
@ -351,11 +358,6 @@ namespace Grpc.IntegrationTesting
};
}
private byte[] CreateByteBufferRequest()
{
return new byte[payloadConfig.BytebufParams.ReqSize];
}
private static Payload CreateZerosPayload(int size)
{
return new Payload { Body = ByteString.CopyFrom(new byte[size]) };

@ -84,15 +84,27 @@ namespace Grpc.IntegrationTesting
}
}
/// <summary>
/// Gets snapshot of stats and reset
/// Gets snapshot of stats and optionally resets the histogram.
/// </summary>
public HistogramData GetSnapshot(bool reset = false)
{
lock (myLock)
{
return GetSnapshotUnsafe(reset);
var histogramData = new HistogramData();
GetSnapshotUnsafe(histogramData, reset);
return histogramData;
}
}
/// <summary>
/// Merges snapshot of stats into <c>mergeTo</c> and optionally resets the histogram.
/// </summary>
public void GetSnapshot(HistogramData mergeTo, bool reset)
{
lock (myLock)
{
GetSnapshotUnsafe(mergeTo, reset);
}
}
@ -117,24 +129,39 @@ namespace Grpc.IntegrationTesting
this.buckets[FindBucket(value)]++;
}
private HistogramData GetSnapshotUnsafe(bool reset)
private void GetSnapshotUnsafe(HistogramData mergeTo, bool reset)
{
var data = new HistogramData
GrpcPreconditions.CheckArgument(mergeTo.Bucket.Count == 0 || mergeTo.Bucket.Count == buckets.Length);
if (mergeTo.Count == 0)
{
Count = count,
Sum = sum,
SumOfSquares = sumOfSquares,
MinSeen = min,
MaxSeen = max,
Bucket = { buckets }
};
mergeTo.MinSeen = min;
mergeTo.MaxSeen = max;
}
else
{
mergeTo.MinSeen = Math.Min(mergeTo.MinSeen, min);
mergeTo.MaxSeen = Math.Max(mergeTo.MaxSeen, max);
}
mergeTo.Count += count;
mergeTo.Sum += sum;
mergeTo.SumOfSquares += sumOfSquares;
if (reset)
if (mergeTo.Bucket.Count == 0)
{
ResetUnsafe();
mergeTo.Bucket.AddRange(buckets);
}
else
{
for (int i = 0; i < buckets.Length; i++)
{
mergeTo.Bucket[i] += buckets[i];
}
}
return data;
if (reset)
{
ResetUnsafe();
}
}
private void ResetUnsafe()

@ -73,13 +73,37 @@ namespace Grpc.IntegrationTesting
{
var hist = new Histogram(0.01, 60e9);
hist.AddObservation(-0.5); // should be in the first bucket
hist.AddObservation(1e12); // should be in the last bucket
hist.AddObservation(1e12); // should be in the last bucket
var data = hist.GetSnapshot();
Assert.AreEqual(1, data.Bucket[0]);
Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]);
}
[Test]
public void MergeSnapshots()
{
var data = new HistogramData();
var hist1 = new Histogram(0.01, 60e9);
hist1.AddObservation(-0.5); // should be in the first bucket
hist1.AddObservation(1e12); // should be in the last bucket
hist1.GetSnapshot(data, false);
var hist2 = new Histogram(0.01, 60e9);
hist2.AddObservation(10000);
hist2.AddObservation(11000);
hist2.GetSnapshot(data, false);
Assert.AreEqual(4, data.Count);
Assert.AreEqual(-0.5, data.MinSeen);
Assert.AreEqual(1e12, data.MaxSeen);
Assert.AreEqual(1, data.Bucket[0]);
Assert.AreEqual(1, data.Bucket[925]);
Assert.AreEqual(1, data.Bucket[935]);
Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]);
}
[Test]
public void Reset()
{

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\Grpc.Core\Version.csproj.include" />
<Import Project="..\Grpc.Core\Common.csproj.include" />
<PropertyGroup>
<TargetFrameworks>net45;netcoreapp1.0</TargetFrameworks>
<AssemblyName>Grpc.Microbenchmarks</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>Grpc.Microbenchmarks</PackageId>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);portable-net45</PackageTargetFallback>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">1.0.4</RuntimeFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs" />
</ItemGroup>
</Project>

@ -0,0 +1,55 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Logging;
namespace Grpc.Microbenchmarks
{
class Program
{
public static void Main(string[] args)
{
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
var benchmark = new SendMessageBenchmark();
benchmark.Init();
foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12})
{
benchmark.Run(threadCount, 4 * 1000 * 1000, 0);
}
benchmark.Cleanup();
}
}
}

@ -0,0 +1,106 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Threading;
using Grpc.Core;
using Grpc.Core.Internal;
using System.Collections.Generic;
using System.Diagnostics;
namespace Grpc.Microbenchmarks
{
public class SendMessageBenchmark
{
static readonly NativeMethods Native = NativeMethods.Get();
GrpcEnvironment environment;
public void Init()
{
Native.grpcsharp_test_override_method("grpcsharp_call_start_batch", "nop");
environment = GrpcEnvironment.AddRef();
}
public void Cleanup()
{
GrpcEnvironment.ReleaseAsync().Wait();
// TODO(jtattermusch): track GC stats
}
public void Run(int threadCount, int iterations, int payloadSize)
{
Console.WriteLine(string.Format("SendMessageBenchmark: threads={0}, iterations={1}, payloadSize={2}", threadCount, iterations, payloadSize));
var threadedBenchmark = new ThreadedBenchmark(threadCount, () => ThreadBody(iterations, payloadSize));
threadedBenchmark.Run();
}
private void ThreadBody(int iterations, int payloadSize)
{
// TODO(jtattermusch): parametrize by number of pending completions.
// TODO(jtattermusch): parametrize by cached/non-cached BatchContextSafeHandle
var completionRegistry = new CompletionRegistry(environment);
var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry);
var call = CreateFakeCall(cq);
var sendCompletionHandler = new SendCompletionHandler((success) => { });
var payload = new byte[payloadSize];
var writeFlags = default(WriteFlags);
var stopwatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
call.StartSendMessage(sendCompletionHandler, payload, writeFlags, false);
var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey);
callback(true);
}
stopwatch.Stop();
Console.WriteLine("Elapsed millis: " + stopwatch.ElapsedMilliseconds);
cq.Dispose();
}
private static CallSafeHandle CreateFakeCall(CompletionQueueSafeHandle cq)
{
var call = CallSafeHandle.CreateFake(new IntPtr(0xdead), cq);
bool success = false;
while (!success)
{
// avoid calling destroy on a nonexistent grpc_call pointer
call.DangerousAddRef(ref success);
}
return call;
}
}
}

@ -0,0 +1,79 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Threading;
using Grpc.Core;
using Grpc.Core.Internal;
using System.Collections.Generic;
using System.Diagnostics;
namespace Grpc.Microbenchmarks
{
public class ThreadedBenchmark
{
List<ThreadStart> runners;
public ThreadedBenchmark(IEnumerable<ThreadStart> runners)
{
this.runners = new List<ThreadStart>(runners);
}
public ThreadedBenchmark(int threadCount, Action threadBody)
{
this.runners = new List<ThreadStart>();
for (int i = 0; i < threadCount; i++)
{
this.runners.Add(new ThreadStart(() => threadBody()));
}
}
public void Run()
{
Console.WriteLine("Running threads.");
var threads = new List<Thread>();
for (int i = 0; i < runners.Count; i++)
{
var thread = new Thread(runners[i]);
thread.Start();
threads.Add(thread);
}
foreach (var thread in threads)
{
thread.Join();
}
Console.WriteLine("All threads finished.");
}
}
}

@ -15,6 +15,8 @@
<PackageProjectUrl>https://github.com/grpc/grpc</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</PackageLicenseUrl>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.5' ">1.6.0</NetStandardImplicitPackageVersion>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSource>true</IncludeSource>
</PropertyGroup>
<ItemGroup>
@ -22,7 +24,9 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj" />
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj">
<PrivateAssets>None</PrivateAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup>

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
VisualStudioVersion = 15.0.26430.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core", "Grpc.Core\Grpc.Core.csproj", "{BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}"
EndProject
@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection", "Grpc.Ref
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{335AD0A2-F2CC-4C2E-853C-26174206BEE7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Microbenchmarks", "Grpc.Microbenchmarks\Grpc.Microbenchmarks.csproj", "{84C17746-4727-4290-8E8B-A380793DAE1E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -111,6 +113,10 @@ Global
{335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.Build.0 = Release|Any CPU
{84C17746-4727-4290-8E8B-A380793DAE1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84C17746-4727-4290-8E8B-A380793DAE1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84C17746-4727-4290-8E8B-A380793DAE1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84C17746-4727-4290-8E8B-A380793DAE1E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -28,7 +28,7 @@
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Current package versions
set VERSION=1.4.0-dev
set VERSION=1.5.0-dev
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe
@ -51,11 +51,11 @@ powershell -Command "cp -r ..\..\platform=*\artifacts\protoc_* protoc_plugins"
@rem To be able to build, we also need to put grpc_csharp_ext to its normal location
xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\
%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Auth --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error
%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts

@ -48,13 +48,13 @@ dotnet restore Grpc.sln
mkdir -p ../../libs/opt
cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
dotnet pack --configuration Release --include-symbols --include-source Grpc.Core --output ../../../artifacts
dotnet pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ../../../artifacts
dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth --output ../../../artifacts
dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts
dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts
nuget pack Grpc.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.Tools.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
dotnet pack --configuration Release Grpc.Core --output ../../../artifacts
dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts
dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts
dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
nuget pack Grpc.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.Tools.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts
(cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)

@ -529,6 +529,38 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) {
grpc_call_unref(call);
}
typedef grpc_call_error (*grpcsharp_call_start_batch_func)(grpc_call *call,
const grpc_op *ops,
size_t nops,
void *tag,
void *reserved);
/* Only for testing */
static grpc_call_error grpcsharp_call_start_batch_nop(grpc_call *call,
const grpc_op *ops,
size_t nops, void *tag,
void *reserved) {
return GRPC_CALL_OK;
}
static grpc_call_error grpcsharp_call_start_batch_default(grpc_call *call,
const grpc_op *ops,
size_t nops,
void *tag,
void *reserved) {
return grpc_call_start_batch(call, ops, nops, tag, reserved);
}
static grpcsharp_call_start_batch_func g_call_start_batch_func =
grpcsharp_call_start_batch_default;
static grpc_call_error grpcsharp_call_start_batch(grpc_call *call,
const grpc_op *ops,
size_t nops, void *tag,
void *reserved) {
return g_call_start_batch_func(call, ops, nops, tag, reserved);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer,
size_t send_buffer_len, uint32_t write_flags,
@ -576,8 +608,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
ops[5].flags = 0;
ops[5].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
@ -616,8 +648,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
ops[3].flags = 0;
ops[3].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
@ -656,8 +688,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
ops[3].flags = 0;
ops[3].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(
@ -685,8 +717,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(
ops[1].flags = 0;
ops[1].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata(
@ -699,8 +731,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata(
ops[0].flags = 0;
ops[0].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(
@ -720,7 +752,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(
ops[1].flags = 0;
ops[1].reserved = NULL;
return grpc_call_start_batch(call, ops, nops, ctx, NULL);
return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client(
@ -731,8 +763,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client(
ops[0].flags = 0;
ops[0].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
@ -773,7 +805,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
ops[nops].reserved = NULL;
nops++;
}
return grpc_call_start_batch(call, ops, nops, ctx, NULL);
return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE
@ -784,8 +816,8 @@ grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) {
ops[0].data.recv_message.recv_message = &(ctx->recv_message);
ops[0].flags = 0;
ops[0].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE
@ -798,8 +830,8 @@ grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) {
ops[0].flags = 0;
ops[0].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata(
@ -817,8 +849,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata(
ops[0].flags = 0;
ops[0].reserved = NULL;
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
NULL);
return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
ctx, NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE
@ -1092,3 +1124,17 @@ GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; }
GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) {
return sizeof(grpc_event);
}
/* Override a method for testing */
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_test_override_method(const char *method_name, const char *variant) {
if (strcmp("grpcsharp_call_start_batch", method_name) == 0) {
if (strcmp("nop", variant) == 0) {
g_call_start_batch_func = grpcsharp_call_start_batch_nop;
} else {
GPR_ASSERT(0);
}
} else {
GPR_ASSERT(0);
}
}

@ -2,9 +2,9 @@
# Node.js gRPC Library
## PREREQUISITES
- `node`: This requires `node` to be installed, version `0.12` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
- `node`: This requires `node` to be installed, version `4.0` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
- **Note:** If you installed `node` via a package manager and the version is still less than `0.12`, try directly installing it from [nodejs.org](https://nodejs.org).
- **Note:** If you installed `node` via a package manager and the version is still less than `4.0`, try directly installing it from [nodejs.org](https://nodejs.org).
## INSTALLATION
@ -16,7 +16,7 @@ npm install grpc
## BUILD FROM SOURCE
1. Clone [the grpc Git Repository](https://github.com/grpc/grpc).
2. Run `npm install` from the repository root.
2. Run `npm install --build-from-source` from the repository root.
- **Note:** On Windows, this might fail due to [nodejs issue #4932](https://github.com/nodejs/node/issues/4932) in which case, you will see something like the following in `npm install`'s output (towards the very beginning):
@ -34,61 +34,3 @@ npm install grpc
## TESTING
To run the test suite, simply run `npm test` in the install location.
## API
This library internally uses [ProtoBuf.js](https://github.com/dcodeIO/ProtoBuf.js), and some structures it exports match those exported by that library.
If you require this module, you will get an object with the following members
```javascript
function load(filename)
```
Takes a filename of a [Protocol Buffer](https://developers.google.com/protocol-buffers/) file, and returns an object representing the structure of the protocol buffer in the following way:
- Namespaces become maps from the names of their direct members to those member objects
- Service definitions become client constructors for clients for that service. They also have a `service` member that can be used for constructing servers.
- Message definitions become Message constructors like those that ProtoBuf.js would create
- Enum definitions become Enum objects like those that ProtoBuf.js would create
- Anything else becomes the relevant reflection object that ProtoBuf.js would create
```javascript
function loadObject(reflectionObject)
```
Returns the same structure that `load` returns, but takes a reflection object from `ProtoBuf.js` instead of a file name.
```javascript
function Server([serverOptions])
```
Constructs a server to which service/implementation pairs can be added.
```javascript
status
```
An object mapping status names to status code numbers.
```javascript
callError
```
An object mapping call error names to codes. This is primarily useful for tracking down certain kinds of internal errors.
```javascript
Credentials
```
An object with factory methods for creating credential objects for clients.
```javascript
ServerCredentials
```
An object with factory methods for creating credential objects for servers.

@ -508,9 +508,14 @@ void Call::DestroyCall() {
}
Call::Call(grpc_call *call)
: wrapped_call(call), pending_batches(0), has_final_op_completed(false) {}
: wrapped_call(call), pending_batches(0), has_final_op_completed(false) {
peer = grpc_call_get_peer(call);
}
Call::~Call() { DestroyCall(); }
Call::~Call() {
DestroyCall();
gpr_free(peer);
}
void Call::Init(Local<Object> exports) {
HandleScope scope;
@ -662,6 +667,16 @@ NAN_METHOD(Call::StartBatch) {
}
Local<Function> callback_func = info[1].As<Function>();
Call *call = ObjectWrap::Unwrap<Call>(info.This());
if (call->wrapped_call == NULL) {
/* This implies that the call has completed and has been destroyed. To
* emulate
* previous behavior, we should call the callback immediately with an error,
* as though the batch had failed in core */
Local<Value> argv[] = {
Nan::Error("The async function failed because the call has completed")};
Nan::Call(callback_func, Nan::New<Object>(), 1, argv);
return;
}
Local<Object> obj = Nan::To<Object>(info[0]).ToLocalChecked();
Local<Array> keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked();
size_t nops = keys->Length();
@ -727,6 +742,11 @@ NAN_METHOD(Call::Cancel) {
return Nan::ThrowTypeError("cancel can only be called on Call objects");
}
Call *call = ObjectWrap::Unwrap<Call>(info.This());
if (call->wrapped_call == NULL) {
/* Cancel is supposed to be idempotent. If the call has already finished,
* cancel should just complete silently */
return;
}
grpc_call_error error = grpc_call_cancel(call->wrapped_call, NULL);
if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("cancel failed", error));
@ -747,6 +767,11 @@ NAN_METHOD(Call::CancelWithStatus) {
"cancelWithStatus's second argument must be a string");
}
Call *call = ObjectWrap::Unwrap<Call>(info.This());
if (call->wrapped_call == NULL) {
/* Cancel is supposed to be idempotent. If the call has already finished,
* cancel should just complete silently */
return;
}
grpc_status_code code =
static_cast<grpc_status_code>(Nan::To<uint32_t>(info[0]).FromJust());
if (code == GRPC_STATUS_OK) {
@ -763,9 +788,7 @@ NAN_METHOD(Call::GetPeer) {
return Nan::ThrowTypeError("getPeer can only be called on Call objects");
}
Call *call = ObjectWrap::Unwrap<Call>(info.This());
char *peer = grpc_call_get_peer(call->wrapped_call);
Local<Value> peer_value = Nan::New(peer).ToLocalChecked();
gpr_free(peer);
Local<Value> peer_value = Nan::New(call->peer).ToLocalChecked();
info.GetReturnValue().Set(peer_value);
}
@ -780,6 +803,10 @@ NAN_METHOD(Call::SetCredentials) {
"setCredentials' first argument must be a CallCredentials");
}
Call *call = ObjectWrap::Unwrap<Call>(info.This());
if (call->wrapped_call == NULL) {
return Nan::ThrowError(
"Cannot set credentials on a call that has already started");
}
CallCredentials *creds_object = ObjectWrap::Unwrap<CallCredentials>(
Nan::To<Object>(info[0]).ToLocalChecked());
grpc_call_credentials *creds = creds_object->GetWrappedCredentials();

@ -96,6 +96,7 @@ class Call : public Nan::ObjectWrap {
call, this is GRPC_OP_RECV_STATUS_ON_CLIENT and for a server call, this
is GRPC_OP_SEND_STATUS_FROM_SERVER */
bool has_final_op_completed;
char *peer;
};
class Op {

@ -1,6 +1,6 @@
{
"name": "grpc-health-check",
"version": "1.4.0-dev",
"version": "1.5.0-dev",
"author": "Google Inc.",
"description": "Health check service for use with gRPC",
"repository": {
@ -15,7 +15,7 @@
}
],
"dependencies": {
"grpc": "^1.4.0-dev",
"grpc": "^1.5.0-dev",
"lodash": "^3.9.3",
"google-protobuf": "^3.0.0"
},

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@ -31,10 +31,6 @@
*
*/
/**
* @module
*/
'use strict';
var path = require('path');
@ -64,24 +60,30 @@ var constants = require('./src/constants.js');
grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii'));
/**
* Load a ProtoBuf.js object as a gRPC object. The options object can provide
* the following options:
* - binaryAsBase64: deserialize bytes values as base64 strings instead of
* Buffers. Defaults to false
* - longsAsStrings: deserialize long values as strings instead of objects.
* Defaults to true
* - deprecatedArgumentOrder: Use the beta method argument order for client
* methods, with optional arguments after the callback. Defaults to false.
* This option is only a temporary stopgap measure to smooth an API breakage.
* It is deprecated, and new code should not use it.
* - protobufjsVersion: Available values are 5, 6, and 'detect'. 5 and 6
* respectively indicate that an object from the corresponding version of
* ProtoBuf.js is provided in the value argument. If the option is 'detect',
* gRPC will guess what the version is based on the structure of the value.
* Defaults to 'detect'.
* @namespace grpc
*/
/**
* Load a ProtoBuf.js object as a gRPC object.
* @memberof grpc
* @alias grpc.loadObject
* @param {Object} value The ProtoBuf.js reflection object to load
* @param {Object=} options Options to apply to the loaded file
* @return {Object<string, *>} The resulting gRPC object
* @param {bool=} [options.binaryAsBase64=false] deserialize bytes values as
* base64 strings instead of Buffers
* @param {bool=} [options.longsAsStrings=true] deserialize long values as
* strings instead of objects
* @param {bool=} [options.enumsAsStrings=true] deserialize enum values as
* strings instead of numbers. Only works with Protobuf.js 6 values.
* @param {bool=} [options.deprecatedArgumentOrder=false] use the beta method
* argument order for client methods, with optional arguments after the
* callback. This option is only a temporary stopgap measure to smooth an
* API breakage. It is deprecated, and new code should not use it.
* @param {(number|string)=} [options.protobufjsVersion='detect'] 5 and 6
* respectively indicate that an object from the corresponding version of
* Protobuf.js is provided in the value argument. If the option is 'detect',
* gRPC wll guess what the version is based on the structure of the value.
* @return {Object<string, *>} The resulting gRPC object.
*/
exports.loadObject = function loadObject(value, options) {
options = _.defaults(options, common.defaultGrpcOptions);
@ -112,22 +114,23 @@ exports.loadObject = function loadObject(value, options) {
var loadObject = exports.loadObject;
/**
* Load a gRPC object from a .proto file. The options object can provide the
* following options:
* - convertFieldsToCamelCase: Load this file with field names in camel case
* instead of their original case
* - binaryAsBase64: deserialize bytes values as base64 strings instead of
* Buffers. Defaults to false
* - longsAsStrings: deserialize long values as strings instead of objects.
* Defaults to true
* - deprecatedArgumentOrder: Use the beta method argument order for client
* methods, with optional arguments after the callback. Defaults to false.
* This option is only a temporary stopgap measure to smooth an API breakage.
* It is deprecated, and new code should not use it.
* Load a gRPC object from a .proto file.
* @memberof grpc
* @alias grpc.load
* @param {string|{root: string, file: string}} filename The file to load
* @param {string=} format The file format to expect. Must be either 'proto' or
* 'json'. Defaults to 'proto'
* @param {Object=} options Options to apply to the loaded file
* @param {bool=} [options.convertFieldsToCamelCase=false] Load this file with
* field names in camel case instead of their original case
* @param {bool=} [options.binaryAsBase64=false] deserialize bytes values as
* base64 strings instead of Buffers
* @param {bool=} [options.longsAsStrings=true] deserialize long values as
* strings instead of objects
* @param {bool=} [options.deprecatedArgumentOrder=false] use the beta method
* argument order for client methods, with optional arguments after the
* callback. This option is only a temporary stopgap measure to smooth an
* API breakage. It is deprecated, and new code should not use it.
* @return {Object<string, *>} The resulting gRPC object
*/
exports.load = function load(filename, format, options) {
@ -168,6 +171,8 @@ var log_template = _.template(
* called. Note: the output format here is intended to be informational, and
* is not guaranteed to stay the same in the future.
* Logs will be directed to logger.error.
* @memberof grpc
* @alias grpc.setLogger
* @param {Console} logger A Console-like object.
*/
exports.setLogger = function setLogger(logger) {
@ -187,6 +192,8 @@ exports.setLogger = function setLogger(logger) {
/**
* Sets the logger verbosity for gRPC module logging. The options are members
* of the grpc.logVerbosity map.
* @memberof grpc
* @alias grpc.setLogVerbosity
* @param {Number} verbosity The minimum severity to log
*/
exports.setLogVerbosity = function setLogVerbosity(verbosity) {
@ -194,71 +201,70 @@ exports.setLogVerbosity = function setLogVerbosity(verbosity) {
grpc.setLogVerbosity(verbosity);
};
/**
* @see module:src/server.Server
*/
exports.Server = server.Server;
/**
* @see module:src/metadata
*/
exports.Metadata = Metadata;
/**
* Status name to code number mapping
*/
exports.status = constants.status;
/**
* Propagate flag name to number mapping
*/
exports.propagate = constants.propagate;
/**
* Call error name to code number mapping
*/
exports.callError = constants.callError;
/**
* Write flag name to code number mapping
*/
exports.writeFlags = constants.writeFlags;
/**
* Log verbosity setting name to code number mapping
*/
exports.logVerbosity = constants.logVerbosity;
/**
* Credentials factories
*/
exports.credentials = require('./src/credentials.js');
/**
* ServerCredentials factories
* @constructor ServerCredentials
* @memberof grpc
*/
exports.ServerCredentials = grpc.ServerCredentials;
/**
* @see module:src/client.makeClientConstructor
* Create insecure server credentials
* @name grpc.ServerCredentials.createInsecure
* @kind function
* @return grpc.ServerCredentials
*/
exports.makeGenericClientConstructor = client.makeClientConstructor;
/**
* @see module:src/client.getClientChannel
* A private key and certificate pair
* @typedef {Object} grpc.ServerCredentials~keyCertPair
* @property {Buffer} privateKey The server's private key
* @property {Buffer} certChain The server's certificate chain
*/
exports.getClientChannel = client.getClientChannel;
/**
* @see module:src/client.waitForClientReady
* Create SSL server credentials
* @name grpc.ServerCredentials.createInsecure
* @kind function
* @param {?Buffer} rootCerts Root CA certificates for validating client
* certificates
* @param {Array<grpc.ServerCredentials~keyCertPair>} keyCertPairs A list of
* private key and certificate chain pairs to be used for authenticating
* the server
* @param {boolean} [checkClientCertificate=false] Indicates that the server
* should request and verify the client's certificates
* @return grpc.ServerCredentials
*/
exports.makeGenericClientConstructor = client.makeClientConstructor;
exports.getClientChannel = client.getClientChannel;
exports.waitForClientReady = client.waitForClientReady;
/**
* @memberof grpc
* @alias grpc.closeClient
* @param {grpc.Client} client_obj The client to close
*/
exports.closeClient = function closeClient(client_obj) {
client.Client.prototype.close.apply(client_obj);
};
/**
* @see module:src/client.Client
*/
exports.Client = client.Client;

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@ -43,8 +43,6 @@
* var Client = proto_obj.package.subpackage.ServiceName;
* var client = new Client(server_address, client_credentials);
* var call = client.unaryMethod(arguments, callback);
*
* @module
*/
'use strict';
@ -70,13 +68,26 @@ var Duplex = stream.Duplex;
var util = require('util');
var version = require('../../../package.json').version;
/**
* Initial response metadata sent by the server when it starts processing the
* call
* @event grpc~ClientUnaryCall#metadata
* @type {grpc.Metadata}
*/
/**
* Status of the call when it has completed.
* @event grpc~ClientUnaryCall#status
* @type grpc~StatusObject
*/
util.inherits(ClientUnaryCall, EventEmitter);
/**
* An EventEmitter. Used for unary calls
* @constructor
* An EventEmitter. Used for unary calls.
* @constructor grpc~ClientUnaryCall
* @extends external:EventEmitter
* @param {grpc.Call} call The call object associated with the request
* @param {grpc.internal~Call} call The call object associated with the request
*/
function ClientUnaryCall(call) {
EventEmitter.call(this);
@ -88,14 +99,16 @@ util.inherits(ClientWritableStream, Writable);
/**
* A stream that the client can write to. Used for calls that are streaming from
* the client side.
* @constructor
* @constructor grpc~ClientWritableStream
* @extends external:Writable
* @borrows module:src/client~ClientUnaryCall#cancel as
* module:src/client~ClientWritableStream#cancel
* @borrows module:src/client~ClientUnaryCall#getPeer as
* module:src/client~ClientWritableStream#getPeer
* @param {grpc.Call} call The call object to send data with
* @param {module:src/common~serialize=} [serialize=identity] Serialization
* @borrows grpc~ClientUnaryCall#cancel as grpc~ClientWritableStream#cancel
* @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientWritableStream#getPeer
* @borrows grpc~ClientUnaryCall#event:metadata as
* grpc~ClientWritableStream#metadata
* @borrows grpc~ClientUnaryCall#event:status as
* grpc~ClientWritableStream#status
* @param {grpc.internal~Call} call The call object to send data with
* @param {grpc~serialize=} [serialize=identity] Serialization
* function for writes.
*/
function ClientWritableStream(call, serialize) {
@ -109,18 +122,37 @@ function ClientWritableStream(call, serialize) {
});
}
/**
* Write a message to the request stream. If serializing the argument fails,
* the call will be cancelled and the stream will end with an error.
* @name grpc~ClientWritableStream#write
* @kind function
* @override
* @param {*} message The message to write. Must be a valid argument to the
* serialize function of the corresponding method
* @param {grpc.writeFlags} flags Flags to modify how the message is written
* @param {Function} callback Callback for when this chunk of data is flushed
* @return {boolean} As defined for [Writable]{@link external:Writable}
*/
/**
* Attempt to write the given chunk. Calls the callback when done. This is an
* implementation of a method needed for implementing stream.Writable.
* @access private
* @param {Buffer} chunk The chunk to write
* @param {string} encoding Used to pass write flags
* @private
* @param {*} chunk The chunk to write
* @param {grpc.writeFlags} encoding Used to pass write flags
* @param {function(Error=)} callback Called when the write is complete
*/
function _write(chunk, encoding, callback) {
/* jshint validthis: true */
var batch = {};
var message;
var self = this;
if (this.writeFailed) {
/* Once a write fails, just call the callback immediately to let the caller
flush any pending writes. */
setImmediate(callback);
}
try {
message = this.serialize(chunk);
} catch (e) {
@ -141,8 +173,10 @@ function _write(chunk, encoding, callback) {
batch[grpc.opType.SEND_MESSAGE] = message;
this.call.startBatch(batch, function(err, event) {
if (err) {
// Something has gone wrong. Stop writing by failing to call callback
return;
/* Assume that the call is complete and that writing failed because a
status was received. In that case, set a flag to discard all future
writes */
self.writeFailed = true;
}
callback();
});
@ -155,14 +189,16 @@ util.inherits(ClientReadableStream, Readable);
/**
* A stream that the client can read from. Used for calls that are streaming
* from the server side.
* @constructor
* @constructor grpc~ClientReadableStream
* @extends external:Readable
* @borrows module:src/client~ClientUnaryCall#cancel as
* module:src/client~ClientReadableStream#cancel
* @borrows module:src/client~ClientUnaryCall#getPeer as
* module:src/client~ClientReadableStream#getPeer
* @param {grpc.Call} call The call object to read data with
* @param {module:src/common~deserialize=} [deserialize=identity]
* @borrows grpc~ClientUnaryCall#cancel as grpc~ClientReadableStream#cancel
* @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientReadableStream#getPeer
* @borrows grpc~ClientUnaryCall#event:metadata as
* grpc~ClientReadableStream#metadata
* @borrows grpc~ClientUnaryCall#event:status as
* grpc~ClientReadableStream#status
* @param {grpc.internal~Call} call The call object to read data with
* @param {grpc~deserialize=} [deserialize=identity]
* Deserialization function for reads
*/
function ClientReadableStream(call, deserialize) {
@ -183,7 +219,7 @@ function ClientReadableStream(call, deserialize) {
* parameter indicates that the call should end with that status. status
* defaults to OK if not provided.
* @param {Object!} status The status that the call should end with
* @access private
* @private
*/
function _readsDone(status) {
/* jshint validthis: true */
@ -202,7 +238,7 @@ ClientReadableStream.prototype._readsDone = _readsDone;
/**
* Called to indicate that we have received a status from the server.
* @access private
* @private
*/
function _receiveStatus(status) {
/* jshint validthis: true */
@ -215,7 +251,7 @@ ClientReadableStream.prototype._receiveStatus = _receiveStatus;
/**
* If we have both processed all incoming messages and received the status from
* the server, emit the status. Otherwise, do nothing.
* @access private
* @private
*/
function _emitStatusIfDone() {
/* jshint validthis: true */
@ -242,7 +278,7 @@ ClientReadableStream.prototype._emitStatusIfDone = _emitStatusIfDone;
/**
* Read the next object from the stream.
* @access private
* @private
* @param {*} size Ignored because we use objectMode=true
*/
function _read(size) {
@ -300,16 +336,19 @@ util.inherits(ClientDuplexStream, Duplex);
/**
* A stream that the client can read from or write to. Used for calls with
* duplex streaming.
* @constructor
* @constructor grpc~ClientDuplexStream
* @extends external:Duplex
* @borrows module:src/client~ClientUnaryCall#cancel as
* module:src/client~ClientDuplexStream#cancel
* @borrows module:src/client~ClientUnaryCall#getPeer as
* module:src/client~ClientDuplexStream#getPeer
* @param {grpc.Call} call Call object to proxy
* @param {module:src/common~serialize=} [serialize=identity] Serialization
* @borrows grpc~ClientUnaryCall#cancel as grpc~ClientDuplexStream#cancel
* @borrows grpc~ClientUnaryCall#getPeer as grpc~ClientDuplexStream#getPeer
* @borrows grpc~ClientWritableStream#write as grpc~ClientDuplexStream#write
* @borrows grpc~ClientUnaryCall#event:metadata as
* grpc~ClientDuplexStream#metadata
* @borrows grpc~ClientUnaryCall#event:status as
* grpc~ClientDuplexStream#status
* @param {grpc.internal~Call} call Call object to proxy
* @param {grpc~serialize=} [serialize=identity] Serialization
* function for requests
* @param {module:src/common~deserialize=} [deserialize=identity]
* @param {grpc~deserialize=} [deserialize=identity]
* Deserialization function for responses
*/
function ClientDuplexStream(call, serialize, deserialize) {
@ -336,8 +375,9 @@ ClientDuplexStream.prototype._read = _read;
ClientDuplexStream.prototype._write = _write;
/**
* Cancel the ongoing call
* @alias module:src/client~ClientUnaryCall#cancel
* Cancel the ongoing call. Results in the call ending with a CANCELLED status,
* unless it has already ended with some other status.
* @alias grpc~ClientUnaryCall#cancel
*/
function cancel() {
/* jshint validthis: true */
@ -352,7 +392,7 @@ ClientDuplexStream.prototype.cancel = cancel;
/**
* Get the endpoint this call/stream is connected to.
* @return {string} The URI of the endpoint
* @alias module:src/client~ClientUnaryCall#getPeer
* @alias grpc~ClientUnaryCall#getPeer
*/
function getPeer() {
/* jshint validthis: true */
@ -368,33 +408,31 @@ ClientDuplexStream.prototype.getPeer = getPeer;
* Any client call type
* @typedef {(ClientUnaryCall|ClientReadableStream|
* ClientWritableStream|ClientDuplexStream)}
* module:src/client~Call
* grpc.Client~Call
*/
/**
* Options that can be set on a call.
* @typedef {Object} module:src/client~CallOptions
* @property {(date|number)} deadline The deadline for the entire call to
* complete. A value of Infinity indicates that no deadline should be set.
* @property {(string)} host Server hostname to set on the call. Only meaningful
* @typedef {Object} grpc.Client~CallOptions
* @property {grpc~Deadline} deadline The deadline for the entire call to
* complete.
* @property {string} host Server hostname to set on the call. Only meaningful
* if different from the server address used to construct the client.
* @property {module:src/client~Call} parent Parent call. Used in servers when
* @property {grpc.Client~Call} parent Parent call. Used in servers when
* making a call as part of the process of handling a call. Used to
* propagate some information automatically, as specified by
* propagate_flags.
* @property {number} propagate_flags Indicates which properties of a parent
* call should propagate to this call. Bitwise combination of flags in
* [grpc.propagate]{@link module:index.propagate}.
* @property {module:src/credentials~CallCredentials} credentials The
* credentials that should be used to make this particular call.
* {@link grpc.propagate}.
* @property {grpc.credentials~CallCredentials} credentials The credentials that
* should be used to make this particular call.
*/
/**
* Get a call object built with the provided options. Keys for options are
* 'deadline', which takes a date or number, and 'host', which takes a string
* and overrides the hostname to connect to.
* Get a call object built with the provided options.
* @access private
* @param {module:src/client~CallOptions=} options Options object.
* @param {grpc.Client~CallOptions=} options Options object.
*/
function getCall(channel, method, options) {
var deadline;
@ -422,14 +460,14 @@ function getCall(channel, method, options) {
/**
* A generic gRPC client. Primarily useful as a base class for generated clients
* @alias module:src/client.Client
* @memberof grpc
* @constructor
* @param {string} address Server address to connect to
* @param {module:src/credentials~ChannelCredentials} credentials Credentials to
* use to connect to the server
* @param {grpc~ChannelCredentials} credentials Credentials to use to connect to
* the server
* @param {Object} options Options to apply to channel creation
*/
var Client = exports.Client = function Client(address, credentials, options) {
function Client(address, credentials, options) {
if (!options) {
options = {};
}
@ -445,19 +483,13 @@ var Client = exports.Client = function Client(address, credentials, options) {
/* Private fields use $ as a prefix instead of _ because it is an invalid
* prefix of a method name */
this.$channel = new grpc.Channel(address, credentials, options);
};
}
/**
* @typedef {Error} module:src/client.Client~ServiceError
* @property {number} code The error code, a key of
* [grpc.status]{@link module:src/client.status}
* @property {module:metadata.Metadata} metadata Metadata sent with the status
* by the server, if any
*/
exports.Client = Client;
/**
* @callback module:src/client.Client~requestCallback
* @param {?module:src/client.Client~ServiceError} error The error, if the call
* @callback grpc.Client~requestCallback
* @param {?grpc~ServiceError} error The error, if the call
* failed
* @param {*} value The response value, if the call succeeded
*/
@ -466,17 +498,17 @@ var Client = exports.Client = function Client(address, credentials, options) {
* Make a unary request to the given method, using the given serialize
* and deserialize functions, with the given argument.
* @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for
* @param {grpc~serialize} serialize The serialization function for
* inputs
* @param {module:src/common~deserialize} deserialize The deserialization
* @param {grpc~deserialize} deserialize The deserialization
* function for outputs
* @param {*} argument The argument to the call. Should be serializable with
* serialize
* @param {module:src/metadata.Metadata=} metadata Metadata to add to the call
* @param {module:src/client~CallOptions=} options Options map
* @param {module:src/client.Client~requestCallback} callback The callback to
* @param {grpc.Metadata=} metadata Metadata to add to the call
* @param {grpc.Client~CallOptions=} options Options map
* @param {grpc.Client~requestCallback} callback The callback to
* for when the response is received
* @return {EventEmitter} An event emitter for stream related events
* @return {grpc~ClientUnaryCall} An event emitter for stream related events
*/
Client.prototype.makeUnaryRequest = function(method, serialize, deserialize,
argument, metadata, options,
@ -548,17 +580,17 @@ Client.prototype.makeUnaryRequest = function(method, serialize, deserialize,
* Make a client stream request to the given method, using the given serialize
* and deserialize functions, with the given argument.
* @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for
* @param {grpc~serialize} serialize The serialization function for
* inputs
* @param {module:src/common~deserialize} deserialize The deserialization
* @param {grpc~deserialize} deserialize The deserialization
* function for outputs
* @param {module:src/metadata.Metadata=} metadata Array of metadata key/value
* pairs to add to the call
* @param {module:src/client~CallOptions=} options Options map
* @param {Client~requestCallback} callback The callback to for when the
* @param {grpc.Metadata=} metadata Array of metadata key/value pairs to add to
* the call
* @param {grpc.Client~CallOptions=} options Options map
* @param {grpc.Client~requestCallback} callback The callback to for when the
* response is received
* @return {module:src/client~ClientWritableStream} An event emitter for stream
* related events
* @return {grpc~ClientWritableStream} An event emitter for stream related
* events
*/
Client.prototype.makeClientStreamRequest = function(method, serialize,
deserialize, metadata,
@ -631,17 +663,16 @@ Client.prototype.makeClientStreamRequest = function(method, serialize,
* Make a server stream request to the given method, with the given serialize
* and deserialize function, using the given argument
* @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for
* inputs
* @param {module:src/common~deserialize} deserialize The deserialization
* @param {grpc~serialize} serialize The serialization function for inputs
* @param {grpc~deserialize} deserialize The deserialization
* function for outputs
* @param {*} argument The argument to the call. Should be serializable with
* serialize
* @param {module:src/metadata.Metadata=} metadata Array of metadata key/value
* pairs to add to the call
* @param {module:src/client~CallOptions=} options Options map
* @return {module:src/client~ClientReadableStream} An event emitter for stream
* related events
* @param {grpc.Metadata=} metadata Array of metadata key/value pairs to add to
* the call
* @param {grpc.Client~CallOptions=} options Options map
* @return {grpc~ClientReadableStream} An event emitter for stream related
* events
*/
Client.prototype.makeServerStreamRequest = function(method, serialize,
deserialize, argument,
@ -693,15 +724,13 @@ Client.prototype.makeServerStreamRequest = function(method, serialize,
/**
* Make a bidirectional stream request with this method on the given channel.
* @param {string} method The name of the method to request
* @param {module:src/common~serialize} serialize The serialization function for
* inputs
* @param {module:src/common~deserialize} deserialize The deserialization
* @param {grpc~serialize} serialize The serialization function for inputs
* @param {grpc~deserialize} deserialize The deserialization
* function for outputs
* @param {module:src/metadata.Metadata=} metadata Array of metadata key/value
* @param {grpc.Metadata=} metadata Array of metadata key/value
* pairs to add to the call
* @param {module:src/client~CallOptions=} options Options map
* @return {module:src/client~ClientDuplexStream} An event emitter for stream
* related events
* @param {grpc.Client~CallOptions=} options Options map
* @return {grpc~ClientDuplexStream} An event emitter for stream related events
*/
Client.prototype.makeBidiStreamRequest = function(method, serialize,
deserialize, metadata,
@ -743,6 +772,9 @@ Client.prototype.makeBidiStreamRequest = function(method, serialize,
return stream;
};
/**
* Close this client.
*/
Client.prototype.close = function() {
this.$channel.close();
};
@ -761,8 +793,7 @@ Client.prototype.getChannel = function() {
* with an error if the attempt to connect to the server has unrecoverablly
* failed or if the deadline expires. This function will make the channel
* start connecting if it has not already done so.
* @param {(Date|Number)} deadline When to stop waiting for a connection. Pass
* Infinity to wait forever.
* @param {grpc~Deadline} deadline When to stop waiting for a connection.
* @param {function(Error)} callback The callback to call when done attempting
* to connect.
*/
@ -788,7 +819,7 @@ Client.prototype.waitForReady = function(deadline, callback) {
/**
* Map with short names for each of the requester maker functions. Used in
* makeClientConstructor
* @access private
* @private
*/
var requester_funcs = {
unary: Client.prototype.makeUnaryRequest,
@ -834,9 +865,15 @@ var deprecated_request_wrap = {
/**
* Creates a constructor for a client with the given methods, as specified in
* the methods argument.
* @param {module:src/common~ServiceDefinition} methods An object mapping
* method names to method attributes
* the methods argument. The resulting class will have an instance method for
* each method in the service, which is a partial application of one of the
* [Client]{@link grpc.Client} request methods, depending on `requestSerialize`
* and `responseSerialize`, with the `method`, `serialize`, and `deserialize`
* arguments predefined.
* @memberof grpc
* @alias grpc~makeGenericClientConstructor
* @param {grpc~ServiceDefinition} methods An object mapping method names to
* method attributes
* @param {string} serviceName The fully qualified name of the service
* @param {Object} class_options An options object.
* @param {boolean=} [class_options.deprecatedArgumentOrder=false] Indicates
@ -844,9 +881,8 @@ var deprecated_request_wrap = {
* arguments at the end instead of the callback at the end. This option
* is only a temporary stopgap measure to smooth an API breakage.
* It is deprecated, and new code should not use it.
* @return {function(string, Object)} New client constructor, which is a
* subclass of [grpc.Client]{@link module:src/client.Client}, and has the
* same arguments as that constructor.
* @return {function} New client constructor, which is a subclass of
* {@link grpc.Client}, and has the same arguments as that constructor.
*/
exports.makeClientConstructor = function(methods, serviceName,
class_options) {
@ -898,8 +934,11 @@ exports.makeClientConstructor = function(methods, serviceName,
/**
* Return the underlying channel object for the specified client
* @memberof grpc
* @alias grpc~getClientChannel
* @param {Client} client
* @return {Channel} The channel
* @see grpc.Client#getChannel
*/
exports.getClientChannel = function(client) {
return Client.prototype.getChannel.call(client);
@ -911,22 +950,15 @@ exports.getClientChannel = function(client) {
* with an error if the attempt to connect to the server has unrecoverablly
* failed or if the deadline expires. This function will make the channel
* start connecting if it has not already done so.
* @memberof grpc
* @alias grpc~waitForClientReady
* @param {Client} client The client to wait on
* @param {(Date|Number)} deadline When to stop waiting for a connection. Pass
* @param {grpc~Deadline} deadline When to stop waiting for a connection. Pass
* Infinity to wait forever.
* @param {function(Error)} callback The callback to call when done attempting
* to connect.
* @see grpc.Client#waitForReady
*/
exports.waitForClientReady = function(client, deadline, callback) {
Client.prototype.waitForReady.call(client, deadline, callback);
};
/**
* Map of status code names to status codes
*/
exports.status = constants.status;
/**
* See docs for client.callError
*/
exports.callError = grpc.callError;

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@ -31,12 +31,6 @@
*
*/
/**
* This module contains functions that are common to client and server
* code. None of them should be used directly by gRPC users.
* @module
*/
'use strict';
var _ = require('lodash');
@ -62,16 +56,19 @@ exports.wrapIgnoreNull = function wrapIgnoreNull(func) {
/**
* The logger object for the gRPC module. Defaults to console.
* @private
*/
exports.logger = console;
/**
* The current logging verbosity. 0 corresponds to logging everything
* @private
*/
exports.logVerbosity = 0;
/**
* Log a message if the severity is at least as high as the current verbosity
* @private
* @param {Number} severity A value of the grpc.logVerbosity map
* @param {String} message The message to log
*/
@ -83,6 +80,7 @@ exports.log = function log(severity, message) {
/**
* Default options for loading proto files into gRPC
* @alias grpc~defaultLoadOptions
*/
exports.defaultGrpcOptions = {
convertFieldsToCamelCase: false,
@ -94,6 +92,30 @@ exports.defaultGrpcOptions = {
// JSDoc definitions that are used in multiple other modules
/**
* Represents the status of a completed request. If `code` is
* {@link grpc.status}.OK, then the request has completed successfully.
* Otherwise, the request has failed, `details` will contain a description of
* the error. Either way, `metadata` contains the trailing response metadata
* sent by the server when it finishes processing the call.
* @typedef {object} grpc~StatusObject
* @property {number} code The error code, a key of {@link grpc.status}
* @property {string} details Human-readable description of the status
* @property {grpc.Metadata} metadata Trailing metadata sent with the status,
* if applicable
*/
/**
* Describes how a request has failed. The member `message` will be the same as
* `details` in {@link grpc~StatusObject}, and `code` and `metadata` are the
* same as in that object.
* @typedef {Error} grpc~ServiceError
* @property {number} code The error code, a key of {@link grpc.status} that is
* not `grpc.status.OK`
* @property {grpc.Metadata} metadata Trailing metadata sent with the status,
* if applicable
*/
/**
* The EventEmitter class in the event standard module
* @external EventEmitter
@ -120,38 +142,46 @@ exports.defaultGrpcOptions = {
/**
* A serialization function
* @callback module:src/common~serialize
* @callback grpc~serialize
* @param {*} value The value to serialize
* @return {Buffer} The value serialized as a byte sequence
*/
/**
* A deserialization function
* @callback module:src/common~deserialize
* @callback grpc~deserialize
* @param {Buffer} data The byte sequence to deserialize
* @return {*} The data deserialized as a value
*/
/**
* The deadline of an operation. If it is a date, the deadline is reached at
* the date and time specified. If it is a finite number, it is treated as
* a number of milliseconds since the Unix Epoch. If it is Infinity, the
* deadline will never be reached. If it is -Infinity, the deadline has already
* passed.
* @typedef {(number|date)} grpc~Deadline
*/
/**
* An object that completely defines a service method signature.
* @typedef {Object} module:src/common~MethodDefinition
* @typedef {Object} grpc~MethodDefinition
* @property {string} path The method's URL path
* @property {boolean} requestStream Indicates whether the method accepts
* a stream of requests
* @property {boolean} responseStream Indicates whether the method returns
* a stream of responses
* @property {module:src/common~serialize} requestSerialize Serialization
* @property {grpc~serialize} requestSerialize Serialization
* function for request values
* @property {module:src/common~serialize} responseSerialize Serialization
* @property {grpc~serialize} responseSerialize Serialization
* function for response values
* @property {module:src/common~deserialize} requestDeserialize Deserialization
* @property {grpc~deserialize} requestDeserialize Deserialization
* function for request data
* @property {module:src/common~deserialize} responseDeserialize Deserialization
* @property {grpc~deserialize} responseDeserialize Deserialization
* function for repsonse data
*/
/**
* An object that completely defines a service.
* @typedef {Object.<string, module:src/common~MethodDefinition>}
* module:src/common~ServiceDefinition
* @typedef {Object.<string, grpc~MethodDefinition>} grpc~ServiceDefinition
*/

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2017, Google Inc.
* All rights reserved.
*
@ -31,16 +31,14 @@
*
*/
/**
* @module
*/
/* The comments about status codes are copied verbatim (with some formatting
* modifications) from include/grpc/impl/codegen/status.h, for the purpose of
* including them in generated documentation.
*/
/**
* Enum of status codes that gRPC can return
* @memberof grpc
* @alias grpc.status
* @readonly
* @enum {number}
*/
@ -178,6 +176,8 @@ exports.status = {
* Users are encouraged to write propagation masks as deltas from the default.
* i.e. write `grpc.propagate.DEFAULTS & ~grpc.propagate.DEADLINE` to disable
* deadline propagation.
* @memberof grpc
* @alias grpc.propagate
* @enum {number}
*/
exports.propagate = {
@ -194,9 +194,11 @@ exports.propagate = {
/**
* Call error constants. Call errors almost always indicate bugs in the gRPC
* library, and these error codes are mainly useful for finding those bugs.
* @memberof grpc
* @readonly
* @enum {number}
*/
exports.callError = {
const callError = {
OK: 0,
ERROR: 1,
NOT_ON_SERVER: 2,
@ -213,9 +215,14 @@ exports.callError = {
PAYLOAD_TYPE_MISMATCH: 14
};
exports.callError = callError;
/**
* Write flags: these can be bitwise or-ed to form write options that modify
* how data is written.
* @memberof grpc
* @alias grpc.writeFlags
* @readonly
* @enum {number}
*/
exports.writeFlags = {
@ -232,6 +239,9 @@ exports.writeFlags = {
};
/**
* @memberof grpc
* @alias grpc.logVerbosity
* @readonly
* @enum {number}
*/
exports.logVerbosity = {

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@ -48,6 +48,7 @@
* For example, to create a client secured with SSL that uses Google
* default application credentials to authenticate:
*
* @example
* var channel_creds = credentials.createSsl(root_certs);
* (new GoogleAuth()).getApplicationDefault(function(err, credential) {
* var call_creds = credentials.createFromGoogleCredential(credential);
@ -56,15 +57,25 @@
* var client = new Client(address, combined_creds);
* });
*
* @module
* @namespace grpc.credentials
*/
'use strict';
var grpc = require('./grpc_extension');
/**
* This cannot be constructed directly. Instead, instances of this class should
* be created using the factory functions in {@link grpc.credentials}
* @constructor grpc.credentials~CallCredentials
*/
var CallCredentials = grpc.CallCredentials;
/**
* This cannot be constructed directly. Instead, instances of this class should
* be created using the factory functions in {@link grpc.credentials}
* @constructor grpc.credentials~ChannelCredentials
*/
var ChannelCredentials = grpc.ChannelCredentials;
var Metadata = require('./metadata.js');
@ -75,25 +86,49 @@ var constants = require('./constants');
var _ = require('lodash');
/**
* @external GoogleCredential
* @see https://github.com/google/google-auth-library-nodejs
*/
/**
* Create an SSL Credentials object. If using a client-side certificate, both
* the second and third arguments must be passed.
* @memberof grpc.credentials
* @alias grpc.credentials.createSsl
* @kind function
* @param {Buffer} root_certs The root certificate data
* @param {Buffer=} private_key The client certificate private key, if
* applicable
* @param {Buffer=} cert_chain The client certificate cert chain, if applicable
* @return {ChannelCredentials} The SSL Credentials object
* @return {grpc.credentials.ChannelCredentials} The SSL Credentials object
*/
exports.createSsl = ChannelCredentials.createSsl;
/**
* @callback grpc.credentials~metadataCallback
* @param {Error} error The error, if getting metadata failed
* @param {grpc.Metadata} metadata The metadata
*/
/**
* @callback grpc.credentials~generateMetadata
* @param {Object} params Parameters that can modify metadata generation
* @param {string} params.service_url The URL of the service that the call is
* going to
* @param {grpc.credentials~metadataCallback} callback
*/
/**
* Create a gRPC credentials object from a metadata generation function. This
* function gets the service URL and a callback as parameters. The error
* passed to the callback can optionally have a 'code' value attached to it,
* which corresponds to a status code that this library uses.
* @param {function(String, function(Error, Metadata))} metadata_generator The
* function that generates metadata
* @return {CallCredentials} The credentials object
* @memberof grpc.credentials
* @alias grpc.credentials.createFromMetadataGenerator
* @param {grpc.credentials~generateMetadata} metadata_generator The function
* that generates metadata
* @return {grpc.credentials.CallCredentials} The credentials object
*/
exports.createFromMetadataGenerator = function(metadata_generator) {
return CallCredentials.createFromPlugin(function(service_url, cb_data,
@ -119,8 +154,11 @@ exports.createFromMetadataGenerator = function(metadata_generator) {
/**
* Create a gRPC credential from a Google credential object.
* @param {Object} google_credential The Google credential object to use
* @return {CallCredentials} The resulting credentials object
* @memberof grpc.credentials
* @alias grpc.credentials.createFromGoogleCredential
* @param {external:GoogleCredential} google_credential The Google credential
* object to use
* @return {grpc.credentials.CallCredentials} The resulting credentials object
*/
exports.createFromGoogleCredential = function(google_credential) {
return exports.createFromMetadataGenerator(function(auth_context, callback) {
@ -141,6 +179,8 @@ exports.createFromGoogleCredential = function(google_credential) {
/**
* Combine a ChannelCredentials with any number of CallCredentials into a single
* ChannelCredentials object.
* @memberof grpc.credentials
* @alias grpc.credentials.combineChannelCredentials
* @param {ChannelCredentials} channel_credential The ChannelCredentials to
* start with
* @param {...CallCredentials} credentials The CallCredentials to compose
@ -157,6 +197,8 @@ exports.combineChannelCredentials = function(channel_credential) {
/**
* Combine any number of CallCredentials into a single CallCredentials object
* @memberof grpc.credentials
* @alias grpc.credentials.combineCallCredentials
* @param {...CallCredentials} credentials the CallCredentials to compose
* @return CallCredentials A credentials object that combines all of the input
* credentials
@ -172,6 +214,9 @@ exports.combineCallCredentials = function() {
/**
* Create an insecure credentials object. This is used to create a channel that
* does not use SSL. This cannot be composed with anything.
* @memberof grpc.credentials
* @alias grpc.credentials.createInsecure
* @kind function
* @return {ChannelCredentials} The insecure credentials object
*/
exports.createInsecure = ChannelCredentials.createInsecure;

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2016, Google Inc.
* All rights reserved.
*

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@ -31,15 +31,6 @@
*
*/
/**
* Metadata module
*
* This module defines the Metadata class, which represents header and trailer
* metadata for gRPC calls.
*
* @module
*/
'use strict';
var _ = require('lodash');
@ -48,8 +39,8 @@ var grpc = require('./grpc_extension');
/**
* Class for storing metadata. Keys are normalized to lowercase ASCII.
* @memberof grpc
* @constructor
* @alias module:src/metadata.Metadata
* @example
* var metadata = new metadata_module.Metadata();
* metadata.set('key1', 'value1');

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2017, Google Inc.
* All rights reserved.
*
@ -31,6 +31,11 @@
*
*/
/**
* @module
* @private
*/
'use strict';
var _ = require('lodash');

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2017, Google Inc.
* All rights reserved.
*
@ -31,6 +31,11 @@
*
*/
/**
* @module
* @private
*/
'use strict';
var _ = require('lodash');

@ -1,5 +1,5 @@
/*
*
/**
* @license
* Copyright 2015, Google Inc.
* All rights reserved.
*
@ -31,22 +31,6 @@
*
*/
/**
* Server module
*
* This module contains all the server code for Node gRPC: both the Server
* class itself and the method handler code for all types of methods.
*
* For example, to create a Server, add a service, and start it:
*
* var server = new server_module.Server();
* server.addProtoService(protobuf_service_descriptor, service_implementation);
* server.bind('address:port', server_credential);
* server.start();
*
* @module
*/
'use strict';
var _ = require('lodash');
@ -70,9 +54,9 @@ var EventEmitter = require('events').EventEmitter;
/**
* Handle an error on a call by sending it as a status
* @access private
* @param {grpc.Call} call The call to send the error on
* @param {Object} error The error object
* @private
* @param {grpc.internal~Call} call The call to send the error on
* @param {(Object|Error)} error The error object
*/
function handleError(call, error) {
var statusMetadata = new Metadata();
@ -104,14 +88,14 @@ function handleError(call, error) {
/**
* Send a response to a unary or client streaming call.
* @access private
* @private
* @param {grpc.Call} call The call to respond on
* @param {*} value The value to respond with
* @param {function(*):Buffer=} serialize Serialization function for the
* @param {grpc~serialize} serialize Serialization function for the
* response
* @param {Metadata=} metadata Optional trailing metadata to send with status
* @param {number=} flags Flags for modifying how the message is sent.
* Defaults to 0.
* @param {grpc.Metadata=} metadata Optional trailing metadata to send with
* status
* @param {number=} [flags=0] Flags for modifying how the message is sent.
*/
function sendUnaryResponse(call, value, serialize, metadata, flags) {
var end_batch = {};
@ -146,7 +130,7 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) {
/**
* Initialize a writable stream. This is used for both the writable and duplex
* stream constructors.
* @access private
* @private
* @param {Writable} stream The stream to set up
* @param {function(*):Buffer=} Serialization function for responses
*/
@ -225,9 +209,9 @@ function setUpWritable(stream, serialize) {
/**
* Initialize a readable stream. This is used for both the readable and duplex
* stream constructors.
* @access private
* @private
* @param {Readable} stream The stream to initialize
* @param {function(Buffer):*=} deserialize Deserialization function for
* @param {grpc~deserialize} deserialize Deserialization function for
* incoming data.
*/
function setUpReadable(stream, deserialize) {
@ -245,34 +229,88 @@ function setUpReadable(stream, deserialize) {
});
}
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerUnaryCall~cancelled
*/
util.inherits(ServerUnaryCall, EventEmitter);
function ServerUnaryCall(call) {
/**
* An EventEmitter. Used for unary calls.
* @constructor grpc~ServerUnaryCall
* @extends external:EventEmitter
* @param {grpc.internal~Call} call The call object associated with the request
* @param {grpc.Metadata} metadata The request metadata from the client
*/
function ServerUnaryCall(call, metadata) {
EventEmitter.call(this);
this.call = call;
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerUnaryCall#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerUnaryCall#metadata
*/
this.metadata = metadata;
/**
* The request message from the client
* @member {*} grpc~ServerUnaryCall#request
*/
this.request = undefined;
}
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerWritableStream~cancelled
*/
util.inherits(ServerWritableStream, Writable);
/**
* A stream that the server can write to. Used for calls that are streaming from
* the server side.
* @constructor
* @param {grpc.Call} call The call object to send data with
* @param {function(*):Buffer=} serialize Serialization function for writes
* @constructor grpc~ServerWritableStream
* @extends external:Writable
* @borrows grpc~ServerUnaryCall#sendMetadata as
* grpc~ServerWritableStream#sendMetadata
* @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerWritableStream#getPeer
* @param {grpc.internal~Call} call The call object to send data with
* @param {grpc.Metadata} metadata The request metadata from the client
* @param {grpc~serialize} serialize Serialization function for writes
*/
function ServerWritableStream(call, serialize) {
function ServerWritableStream(call, metadata, serialize) {
Writable.call(this, {objectMode: true});
this.call = call;
this.finished = false;
setUpWritable(this, serialize);
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerWritableStream#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerWritableStream#metadata
*/
this.metadata = metadata;
/**
* The request message from the client
* @member {*} grpc~ServerWritableStream#request
*/
this.request = undefined;
}
/**
* Start writing a chunk of data. This is an implementation of a method required
* for implementing stream.Writable.
* @access private
* @private
* @param {Buffer} chunk The chunk of data to write
* @param {string} encoding Used to pass write flags
* @param {function(Error=)} callback Callback to indicate that the write is
@ -312,19 +350,40 @@ function _write(chunk, encoding, callback) {
ServerWritableStream.prototype._write = _write;
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerReadableStream~cancelled
*/
util.inherits(ServerReadableStream, Readable);
/**
* A stream that the server can read from. Used for calls that are streaming
* from the client side.
* @constructor
* @param {grpc.Call} call The call object to read data with
* @param {function(Buffer):*=} deserialize Deserialization function for reads
* @constructor grpc~ServerReadableStream
* @extends external:Readable
* @borrows grpc~ServerUnaryCall#sendMetadata as
* grpc~ServerReadableStream#sendMetadata
* @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerReadableStream#getPeer
* @param {grpc.internal~Call} call The call object to read data with
* @param {grpc.Metadata} metadata The request metadata from the client
* @param {grpc~deserialize} deserialize Deserialization function for reads
*/
function ServerReadableStream(call, deserialize) {
function ServerReadableStream(call, metadata, deserialize) {
Readable.call(this, {objectMode: true});
this.call = call;
setUpReadable(this, deserialize);
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerReadableStream#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerReadableStream#metadata
*/
this.metadata = metadata;
}
/**
@ -381,22 +440,43 @@ function _read(size) {
ServerReadableStream.prototype._read = _read;
/**
* Emitted when the call has been cancelled. After this has been emitted, the
* call's `cancelled` property will be set to `true`.
* @event grpc~ServerDuplexStream~cancelled
*/
util.inherits(ServerDuplexStream, Duplex);
/**
* A stream that the server can read from or write to. Used for calls with
* duplex streaming.
* @constructor
* @param {grpc.Call} call Call object to proxy
* @param {function(*):Buffer=} serialize Serialization function for requests
* @param {function(Buffer):*=} deserialize Deserialization function for
* @constructor grpc~ServerDuplexStream
* @extends external:Duplex
* @borrows grpc~ServerUnaryCall#sendMetadata as
* grpc~ServerDuplexStream#sendMetadata
* @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerDuplexStream#getPeer
* @param {grpc.internal~Call} call Call object to proxy
* @param {grpc.Metadata} metadata The request metadata from the client
* @param {grpc~serialize} serialize Serialization function for requests
* @param {grpc~deserialize} deserialize Deserialization function for
* responses
*/
function ServerDuplexStream(call, serialize, deserialize) {
function ServerDuplexStream(call, metadata, serialize, deserialize) {
Duplex.call(this, {objectMode: true});
this.call = call;
setUpWritable(this, serialize);
setUpReadable(this, deserialize);
/**
* Indicates if the call has been cancelled
* @member {boolean} grpc~ServerReadableStream#cancelled
*/
this.cancelled = false;
/**
* The request metadata from the client
* @member {grpc.Metadata} grpc~ServerReadableStream#metadata
*/
this.metadata = metadata;
}
ServerDuplexStream.prototype._read = _read;
@ -404,6 +484,7 @@ ServerDuplexStream.prototype._write = _write;
/**
* Send the initial metadata for a writable stream.
* @alias grpc~ServerUnaryCall#sendMetadata
* @param {Metadata} responseMetadata Metadata to send
*/
function sendMetadata(responseMetadata) {
@ -430,6 +511,7 @@ ServerDuplexStream.prototype.sendMetadata = sendMetadata;
/**
* Get the endpoint this call/stream is connected to.
* @alias grpc~ServerUnaryCall#getPeer
* @return {string} The URI of the endpoint
*/
function getPeer() {
@ -445,6 +527,7 @@ ServerDuplexStream.prototype.getPeer = getPeer;
/**
* Wait for the client to close, then emit a cancelled event if the client
* cancelled.
* @private
*/
function waitForCancel() {
/* jshint validthis: true */
@ -467,19 +550,42 @@ ServerReadableStream.prototype.waitForCancel = waitForCancel;
ServerWritableStream.prototype.waitForCancel = waitForCancel;
ServerDuplexStream.prototype.waitForCancel = waitForCancel;
/**
* Callback function passed to server handlers that handle methods with unary
* responses.
* @callback grpc.Server~sendUnaryData
* @param {grpc~ServiceError} error An error, if the call failed
* @param {*} value The response value. Must be a valid argument to the
* `responseSerialize` method of the method that is being handled
* @param {grpc.Metadata=} trailer Trailing metadata to send, if applicable
* @param {grpc.writeFlags=} flags Flags to modify writing the response
*/
/**
* User-provided method to handle unary requests on a server
* @callback grpc.Server~handleUnaryCall
* @param {grpc~ServerUnaryCall} call The call object
* @param {grpc.Server~sendUnaryData} callback The callback to call to respond
* to the request
*/
/**
* Fully handle a unary call
* @access private
* @param {grpc.Call} call The call to handle
* @private
* @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
* @param {Metadata} metadata Metadata from the client
* @param {grpc~Server.handleUnaryCall} handler.func The handler function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {grpc.Metadata} metadata Metadata from the client
*/
function handleUnary(call, handler, metadata) {
var emitter = new ServerUnaryCall(call);
var emitter = new ServerUnaryCall(call, metadata);
emitter.on('error', function(error) {
handleError(call, error);
});
emitter.metadata = metadata;
emitter.waitForCancel();
var batch = {};
batch[grpc.opType.RECV_MESSAGE] = true;
@ -511,17 +617,28 @@ function handleUnary(call, handler, metadata) {
});
}
/**
* User provided method to handle server streaming methods on the server.
* @callback grpc.Server~handleServerStreamingCall
* @param {grpc~ServerWritableStream} call The call object
*/
/**
* Fully handle a server streaming call
* @access private
* @param {grpc.Call} call The call to handle
* @private
* @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
* @param {Metadata} metadata Metadata from the client
* @param {grpc~Server.handleServerStreamingCall} handler.func The handler
* function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {grpc.Metadata} metadata Metadata from the client
*/
function handleServerStreaming(call, handler, metadata) {
var stream = new ServerWritableStream(call, handler.serialize);
var stream = new ServerWritableStream(call, metadata, handler.serialize);
stream.waitForCancel();
stream.metadata = metadata;
var batch = {};
batch[grpc.opType.RECV_MESSAGE] = true;
call.startBatch(batch, function(err, result) {
@ -540,20 +657,33 @@ function handleServerStreaming(call, handler, metadata) {
});
}
/**
* User provided method to handle client streaming methods on the server.
* @callback grpc.Server~handleClientStreamingCall
* @param {grpc~ServerReadableStream} call The call object
* @param {grpc.Server~sendUnaryData} callback The callback to call to respond
* to the request
*/
/**
* Fully handle a client streaming call
* @access private
* @param {grpc.Call} call The call to handle
* @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
* @param {Metadata} metadata Metadata from the client
* @param {grpc~Server.handleClientStreamingCall} handler.func The handler
* function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {grpc.Metadata} metadata Metadata from the client
*/
function handleClientStreaming(call, handler, metadata) {
var stream = new ServerReadableStream(call, handler.deserialize);
var stream = new ServerReadableStream(call, metadata, handler.deserialize);
stream.on('error', function(error) {
handleError(call, error);
});
stream.waitForCancel();
stream.metadata = metadata;
handler.func(stream, function(err, value, trailer, flags) {
stream.terminate();
if (err) {
@ -567,18 +697,29 @@ function handleClientStreaming(call, handler, metadata) {
});
}
/**
* User provided method to handle bidirectional streaming calls on the server.
* @callback grpc.Server~handleBidiStreamingCall
* @param {grpc~ServerDuplexStream} call The call object
*/
/**
* Fully handle a bidirectional streaming call
* @access private
* @param {grpc.Call} call The call to handle
* @private
* @param {grpc.internal~Call} call The call to handle
* @param {Object} handler Request handler object for the method that was called
* @param {grpc~Server.handleBidiStreamingCall} handler.func The handler
* function
* @param {grpc~deserialize} handler.deserialize The deserialization function
* for request data
* @param {grpc~serialize} handler.serialize The serialization function for
* response data
* @param {Metadata} metadata Metadata from the client
*/
function handleBidiStreaming(call, handler, metadata) {
var stream = new ServerDuplexStream(call, handler.serialize,
var stream = new ServerDuplexStream(call, metadata, handler.serialize,
handler.deserialize);
stream.waitForCancel();
stream.metadata = metadata;
handler.func(stream);
}
@ -592,96 +733,90 @@ var streamHandlers = {
/**
* Constructs a server object that stores request handlers and delegates
* incoming requests to those handlers
* @memberof grpc
* @constructor
* @param {Object=} options Options that should be passed to the internal server
* implementation
* @example
* var server = new grpc.Server();
* server.addProtoService(protobuf_service_descriptor, service_implementation);
* server.bind('address:port', server_credential);
* server.start();
*/
function Server(options) {
this.handlers = {};
var handlers = this.handlers;
var server = new grpc.Server(options);
this._server = server;
this.started = false;
}
/**
* Start the server and begin handling requests
*/
Server.prototype.start = function() {
if (this.started) {
throw new Error('Server is already running');
}
var self = this;
this.started = true;
this._server.start();
/**
* Start the server and begin handling requests
* @this Server
* Handles the SERVER_RPC_NEW event. If there is a handler associated with
* the requested method, use that handler to respond to the request. Then
* wait for the next request
* @param {grpc.internal~Event} event The event to handle with tag
* SERVER_RPC_NEW
*/
this.start = function() {
if (this.started) {
throw new Error('Server is already running');
function handleNewCall(err, event) {
if (err) {
return;
}
this.started = true;
server.start();
/**
* Handles the SERVER_RPC_NEW event. If there is a handler associated with
* the requested method, use that handler to respond to the request. Then
* wait for the next request
* @param {grpc.Event} event The event to handle with tag SERVER_RPC_NEW
*/
function handleNewCall(err, event) {
if (err) {
return;
}
var details = event.new_call;
var call = details.call;
var method = details.method;
var metadata = Metadata._fromCoreRepresentation(details.metadata);
if (method === null) {
return;
}
server.requestCall(handleNewCall);
var handler;
if (handlers.hasOwnProperty(method)) {
handler = handlers[method];
} else {
var batch = {};
batch[grpc.opType.SEND_INITIAL_METADATA] =
(new Metadata())._getCoreRepresentation();
batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
code: constants.status.UNIMPLEMENTED,
details: '',
metadata: {}
};
batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
call.startBatch(batch, function() {});
return;
}
streamHandlers[handler.type](call, handler, metadata);
var details = event.new_call;
var call = details.call;
var method = details.method;
var metadata = Metadata._fromCoreRepresentation(details.metadata);
if (method === null) {
return;
}
server.requestCall(handleNewCall);
};
/**
* Gracefully shuts down the server. The server will stop receiving new calls,
* and any pending calls will complete. The callback will be called when all
* pending calls have completed and the server is fully shut down. This method
* is idempotent with itself and forceShutdown.
* @param {function()} callback The shutdown complete callback
*/
this.tryShutdown = function(callback) {
server.tryShutdown(callback);
};
self._server.requestCall(handleNewCall);
var handler;
if (self.handlers.hasOwnProperty(method)) {
handler = self.handlers[method];
} else {
var batch = {};
batch[grpc.opType.SEND_INITIAL_METADATA] =
(new Metadata())._getCoreRepresentation();
batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
code: constants.status.UNIMPLEMENTED,
details: '',
metadata: {}
};
batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
call.startBatch(batch, function() {});
return;
}
streamHandlers[handler.type](call, handler, metadata);
}
this._server.requestCall(handleNewCall);
};
/**
* Forcibly shuts down the server. The server will stop receiving new calls
* and cancel all pending calls. When it returns, the server has shut down.
* This method is idempotent with itself and tryShutdown, and it will trigger
* any outstanding tryShutdown callbacks.
*/
this.forceShutdown = function() {
server.forceShutdown();
};
}
/**
* Unified type for application handlers for all types of calls
* @typedef {(grpc.Server~handleUnaryCall
* |grpc.Server~handleClientStreamingCall
* |grpc.Server~handleServerStreamingCall
* |grpc.Server~handleBidiStreamingCall)} grpc.Server~handleCall
*/
/**
* Registers a handler to handle the named method. Fails if there already is
* a handler for the given method. Returns true on success
* @param {string} name The name of the method that the provided function should
* handle/respond to.
* @param {function} handler Function that takes a stream of request values and
* returns a stream of response values
* @param {function(*):Buffer} serialize Serialization function for responses
* @param {function(Buffer):*} deserialize Deserialization function for requests
* @param {grpc.Server~handleCall} handler Function that takes a stream of
* request values and returns a stream of response values
* @param {grpc~serialize} serialize Serialization function for responses
* @param {grpc~deserialize} deserialize Deserialization function for requests
* @param {string} type The streaming type of method that this handles
* @return {boolean} True if the handler was set. False if a handler was already
* set for that name.
@ -700,6 +835,27 @@ Server.prototype.register = function(name, handler, serialize, deserialize,
return true;
};
/**
* Gracefully shuts down the server. The server will stop receiving new calls,
* and any pending calls will complete. The callback will be called when all
* pending calls have completed and the server is fully shut down. This method
* is idempotent with itself and forceShutdown.
* @param {function()} callback The shutdown complete callback
*/
Server.prototype.tryShutdown = function(callback) {
this._server.tryShutdown(callback);
};
/**
* Forcibly shuts down the server. The server will stop receiving new calls
* and cancel all pending calls. When it returns, the server has shut down.
* This method is idempotent with itself and tryShutdown, and it will trigger
* any outstanding tryShutdown callbacks.
*/
Server.prototype.forceShutdown = function() {
this._server.forceShutdown();
};
var unimplementedStatusResponse = {
code: constants.status.UNIMPLEMENTED,
details: 'The server does not implement this method'
@ -721,13 +877,10 @@ var defaultHandler = {
};
/**
* Add a service to the server, with a corresponding implementation. If you are
* generating this from a proto file, you should instead use
* addProtoService.
* @param {Object<String, *>} service The service descriptor, as
* {@link module:src/common.getProtobufServiceAttrs} returns
* @param {Object<String, function>} implementation Map of method names to
* method implementation for the provided service.
* Add a service to the server, with a corresponding implementation.
* @param {grpc~ServiceDefinition} service The service descriptor
* @param {Object<String, grpc.Server~handleCall>} implementation Map of method
* names to method implementation for the provided service.
*/
Server.prototype.addService = function(service, implementation) {
if (!_.isObject(service) || !_.isObject(implementation)) {
@ -788,10 +941,10 @@ var logAddProtoServiceDeprecationOnce = _.once(function() {
/**
* Add a proto service to the server, with a corresponding implementation
* @deprecated Use grpc.load and Server#addService instead
* @deprecated Use {@link grpc.Server#addService} instead
* @param {Protobuf.Reflect.Service} service The proto service descriptor
* @param {Object<String, function>} implementation Map of method names to
* method implementation for the provided service.
* @param {Object<String, grpc.Server~handleCall>} implementation Map of method
* names to method implementation for the provided service.
*/
Server.prototype.addProtoService = function(service, implementation) {
var options;
@ -815,10 +968,11 @@ Server.prototype.addProtoService = function(service, implementation) {
};
/**
* Binds the server to the given port, with SSL enabled if creds is given
* Binds the server to the given port, with SSL disabled if creds is an
* insecure credentials object
* @param {string} port The port that the server should bind on, in the format
* "address:port"
* @param {ServerCredentials=} creds Server credential object to be used for
* @param {grpc.ServerCredentials} creds Server credential object to be used for
* SSL. Pass an insecure credentials object for an insecure port.
*/
Server.prototype.bind = function(port, creds) {
@ -828,7 +982,4 @@ Server.prototype.bind = function(port, creds) {
return this._server.addHttp2Port(port, creds);
};
/**
* @see module:src/server~Server
*/
exports.Server = Server;

@ -100,7 +100,6 @@ describe('Proto message long int serialize and deserialize', function() {
var longNumDeserialize = deserializeCls(messages_proto.LongValues,
num_options);
var serialized = longSerialize({int_64: pos_value});
console.log(longDeserialize(serialized));
assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string');
/* With the longsAsStrings option disabled, long values are represented as
* objects with 3 keys: low, high, and unsigned */

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

Loading…
Cancel
Save