浏览代码

Merge github.com:grpc/grpc into selectivity

Craig Tiller 8 年之前
父节点
当前提交
e54eb13ed7
共有 100 个文件被更改,包括 2199 次插入1836 次删除
  1. 6 7
      BUILD
  2. 30 305
      CMakeLists.txt
  3. 43 319
      Makefile
  4. 1 0
      Rakefile
  5. 3 2
      build.yaml
  6. 1 55
      config.m4
  7. 642 0
      config.w32
  8. 2 0
      doc/PROTOCOL-WEB.md
  9. 1 0
      grpc.def
  10. 8 6
      include/grpc++/create_channel.h
  11. 2 2
      include/grpc++/create_channel_posix.h
  12. 1 1
      include/grpc++/ext/health_check_service_server_builder_option.h
  13. 2 2
      include/grpc++/ext/proto_server_reflection_plugin.h
  14. 1 0
      include/grpc++/grpc++.h
  15. 1 1
      include/grpc++/health_check_service_interface.h
  16. 4 3
      include/grpc++/impl/codegen/client_context.h
  17. 5 0
      include/grpc++/impl/server_builder_plugin.h
  18. 8 7
      include/grpc++/resource_quota.h
  19. 4 1
      include/grpc++/security/auth_metadata_processor.h
  20. 1 1
      include/grpc++/security/credentials.h
  21. 6 5
      include/grpc++/security/server_credentials.h
  22. 27 19
      include/grpc++/server.h
  23. 27 18
      include/grpc++/server_builder.h
  24. 3 2
      include/grpc++/server_posix.h
  25. 6 6
      include/grpc++/support/channel_arguments.h
  26. 5 5
      include/grpc++/support/error_details.h
  27. 1 1
      include/grpc++/support/slice.h
  28. 2 2
      include/grpc++/test/server_context_test_spouse.h
  29. 1 1
      include/grpc/support/log.h
  30. 1 1
      package.json
  31. 52 78
      package.xml
  32. 10 11
      src/compiler/php_generator.cc
  33. 15 3
      src/core/ext/filters/client_channel/client_channel.c
  34. 3 1
      src/core/ext/filters/client_channel/lb_policy.h
  35. 64 17
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
  36. 43 46
      src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
  37. 1 1
      src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
  38. 176 283
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
  39. 65 64
      src/core/ext/filters/client_channel/parse_address.c
  40. 6 0
      src/core/ext/filters/client_channel/parse_address.h
  41. 11 7
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
  42. 59 14
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
  43. 6 0
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
  44. 30 11
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  45. 27 5
      src/core/lib/iomgr/tcp_server_uv.c
  46. 8 6
      src/core/lib/iomgr/tcp_uv.c
  47. 3 3
      src/core/lib/support/cmdline.c
  48. 2 2
      src/core/lib/support/histogram.c
  49. 1 1
      src/core/lib/support/host_port.c
  50. 12 12
      src/core/lib/support/string.c
  51. 1 1
      src/core/lib/support/string_posix.c
  52. 2 2
      src/core/lib/support/subprocess_posix.c
  53. 1 1
      src/core/lib/support/thd_posix.c
  54. 5 0
      src/core/lib/transport/bdp_estimator.c
  55. 2 0
      src/core/lib/transport/bdp_estimator.h
  56. 4 0
      src/cpp/server/server_builder.cc
  57. 4 1
      src/csharp/Grpc.Core/Internal/CallError.cs
  58. 2 2
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  59. 3 3
      src/csharp/Grpc.Core/Internal/NativeMethods.cs
  60. 1 1
      src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
  61. 15 13
      src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
  62. 42 15
      src/csharp/Grpc.IntegrationTesting/Histogram.cs
  63. 25 1
      src/csharp/Grpc.IntegrationTesting/HistogramTest.cs
  64. 5 5
      src/csharp/build_packages_dotnetcli.bat
  65. 5 5
      src/csharp/build_packages_dotnetcli.sh
  66. 24 31
      src/node/index.js
  67. 5 5
      src/node/src/protobuf_js_5_common.js
  68. 6 2
      src/node/src/server.js
  69. 12 9
      src/node/test/common_test.js
  70. 17 25
      src/node/test/surface_test.js
  71. 29 0
      src/objective-c/tests/GRPCClientTests.m
  72. 19 7
      src/php/ext/grpc/call.c
  73. 25 3
      src/php/ext/grpc/call_credentials.c
  74. 2 0
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  75. 3 0
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  76. 1 1
      src/ruby/lib/grpc/grpc.rb
  77. 3 7
      templates/config.m4.template
  78. 31 0
      templates/config.w32.template
  79. 1 1
      templates/package.json.template
  80. 26 5
      templates/package.xml.template
  81. 5 5
      templates/src/csharp/build_packages_dotnetcli.bat.template
  82. 5 5
      templates/src/csharp/build_packages_dotnetcli.sh.template
  83. 47 0
      templates/tools/dockerfile/go_build_interop.sh.include
  84. 3 0
      templates/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh.template
  85. 3 0
      templates/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh.template
  86. 7 1
      test/core/end2end/cq_verifier.c
  87. 2 1
      test/core/end2end/fixtures/h2_full+workarounds.c
  88. 12 7
      test/core/end2end/fixtures/http_proxy_fixture.c
  89. 2 0
      test/core/surface/concurrent_connectivity_test.c
  90. 163 46
      test/cpp/end2end/grpclb_end2end_test.cc
  91. 8 23
      test/cpp/end2end/round_robin_end2end_test.cc
  92. 4 1
      test/cpp/microbenchmarks/bm_fullstack_trickle.cc
  93. 2 0
      tools/README.md
  94. 39 0
      tools/dockerfile/grpc_artifact_linux_armv6/Dockerfile
  95. 39 0
      tools/dockerfile/grpc_artifact_linux_armv7/Dockerfile
  96. 48 0
      tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh
  97. 48 0
      tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh
  98. 1 1
      tools/dockerfile/push_testing_images.sh
  99. 1 12
      tools/doxygen/Doxyfile.c++
  100. 0 251
      tools/doxygen/Doxyfile.c++.internal

+ 6 - 7
BUILD

@@ -745,7 +745,7 @@ grpc_cc_library(
         "grpc_transport_chttp2_server_insecure",
         "grpc_transport_chttp2_server_insecure",
         "grpc_workaround_cronet_compression_filter",
         "grpc_workaround_cronet_compression_filter",
         "grpc_server_backward_compatibility",
         "grpc_server_backward_compatibility",
-    ]
+    ],
 )
 )
 
 
 grpc_cc_library(
 grpc_cc_library(
@@ -1400,22 +1400,22 @@ GRPCXX_PUBLIC_HDRS = [
 
 
 grpc_cc_library(
 grpc_cc_library(
     name = "grpc++_base",
     name = "grpc++_base",
-    hdrs = GRPCXX_HDRS,
     srcs = GRPCXX_SRCS,
     srcs = GRPCXX_SRCS,
-    public_hdrs = GRPCXX_PUBLIC_HDRS,
+    hdrs = GRPCXX_HDRS,
     language = "c++",
     language = "c++",
+    public_hdrs = GRPCXX_PUBLIC_HDRS,
     deps = [
     deps = [
-        "grpc++_codegen_base",
         "grpc",
         "grpc",
+        "grpc++_codegen_base",
     ],
     ],
 )
 )
 
 
 grpc_cc_library(
 grpc_cc_library(
     name = "grpc++_base_unsecure",
     name = "grpc++_base_unsecure",
-    hdrs = GRPCXX_HDRS,
     srcs = GRPCXX_SRCS,
     srcs = GRPCXX_SRCS,
-    public_hdrs = GRPCXX_PUBLIC_HDRS,
+    hdrs = GRPCXX_HDRS,
     language = "c++",
     language = "c++",
+    public_hdrs = GRPCXX_PUBLIC_HDRS,
     deps = [
     deps = [
         "grpc++_codegen_base",
         "grpc++_codegen_base",
         "grpc_unsecure",
         "grpc_unsecure",
@@ -1539,5 +1539,4 @@ grpc_cc_library(
     ],
     ],
 )
 )
 
 
-
 grpc_generate_one_off_targets()
 grpc_generate_one_off_targets()

+ 30 - 305
CMakeLists.txt

@@ -2273,133 +2273,6 @@ add_library(grpc++
   src/cpp/util/status.cc
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.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_common.c
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_encode.c
   third_party/nanopb/pb_encode.c
@@ -2440,7 +2313,6 @@ target_link_libraries(grpc++
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
   grpc
-  gpr
 )
 )
 
 
 foreach(_hdr
 foreach(_hdr
@@ -2537,17 +2409,6 @@ foreach(_hdr
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.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/proto_utils.h
   include/grpc++/impl/codegen/config_protobuf.h
   include/grpc++/impl/codegen/config_protobuf.h
 )
 )
@@ -2606,6 +2467,34 @@ add_library(grpc++_cronet
   src/cpp/util/status.cc
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.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_args.c
   src/core/lib/channel/channel_stack.c
   src/core/lib/channel/channel_stack.c
   src/core/lib/channel/channel_stack_builder.c
   src/core/lib/channel/channel_stack_builder.c
@@ -2733,34 +2622,6 @@ add_library(grpc++_cronet
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
   src/core/lib/transport/transport_op_string.c
   src/core/lib/debug/trace.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/transport/chttp2/alpn/alpn.c
   src/core/ext/filters/http/client/http_client_filter.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/http_filters_plugin.c
@@ -2841,6 +2702,7 @@ target_link_libraries(grpc++_cronet
   ${_gRPC_ALLTARGETS_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   gpr
   grpc_cronet
   grpc_cronet
+  grpc
 )
 )
 
 
 foreach(_hdr
 foreach(_hdr
@@ -3383,133 +3245,6 @@ add_library(grpc++_unsecure
   src/cpp/util/status.cc
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.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_common.c
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_encode.c
   third_party/nanopb/pb_encode.c
@@ -3550,6 +3285,7 @@ target_link_libraries(grpc++_unsecure
   ${_gRPC_ALLTARGETS_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   gpr
   grpc_unsecure
   grpc_unsecure
+  grpc
 )
 )
 
 
 foreach(_hdr
 foreach(_hdr
@@ -3646,17 +3382,6 @@ foreach(_hdr
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.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})
   string(REPLACE "include/" "" _path ${_hdr})
   get_filename_component(_path ${_path} PATH)
   get_filename_component(_path ${_path} PATH)

+ 43 - 319
Makefile

@@ -4196,133 +4196,6 @@ LIBGRPC++_SRC = \
     src/cpp/util/status.cc \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.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_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
     third_party/nanopb/pb_encode.c \
@@ -4422,17 +4295,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.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/proto_utils.h \
     include/grpc++/impl/codegen/config_protobuf.h \
     include/grpc++/impl/codegen/config_protobuf.h \
 
 
@@ -4471,18 +4333,18 @@ endif
 
 
 
 
 ifeq ($(SYSTEM),MINGW32)
 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 $@"
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 	$(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
 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 $@"
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
 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
 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.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
 endif
 endif
@@ -4537,6 +4399,34 @@ LIBGRPC++_CRONET_SRC = \
     src/cpp/util/status.cc \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.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_args.c \
     src/core/lib/channel/channel_stack.c \
     src/core/lib/channel/channel_stack.c \
     src/core/lib/channel/channel_stack_builder.c \
     src/core/lib/channel/channel_stack_builder.c \
@@ -4664,34 +4554,6 @@ LIBGRPC++_CRONET_SRC = \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
     src/core/lib/transport/transport_op_string.c \
     src/core/lib/debug/trace.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/transport/chttp2/alpn/alpn.c \
     src/core/ext/filters/http/client/http_client_filter.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/http_filters_plugin.c \
@@ -4878,18 +4740,18 @@ endif
 
 
 
 
 ifeq ($(SYSTEM),MINGW32)
 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 $@"
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 	$(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
 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 $@"
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
 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
 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.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
 endif
 endif
@@ -5304,133 +5166,6 @@ LIBGRPC++_UNSECURE_SRC = \
     src/cpp/util/status.cc \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.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_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
     third_party/nanopb/pb_encode.c \
@@ -5530,17 +5265,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.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))))
 LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC))))
 
 
@@ -5567,18 +5291,18 @@ endif
 
 
 
 
 ifeq ($(SYSTEM),MINGW32)
 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 $@"
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 	$(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
 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 $@"
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
 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
 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.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
 endif
 endif

+ 1 - 0
Rakefile

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

+ 3 - 2
build.yaml

@@ -960,9 +960,10 @@ filegroups:
   - src/cpp/util/status.cc
   - src/cpp/util/status.cc
   - src/cpp/util/string_ref.cc
   - src/cpp/util/string_ref.cc
   - src/cpp/util/time_cc.cc
   - src/cpp/util/time_cc.cc
+  deps:
+  - grpc
   uses:
   uses:
   - grpc++_codegen_base
   - grpc++_codegen_base
-  - grpc_base
   - nanopb
   - nanopb
 - name: grpc++_codegen_base
 - name: grpc++_codegen_base
   language: c++
   language: c++
@@ -4628,8 +4629,8 @@ php_config_m4:
   deps:
   deps:
   - grpc
   - grpc
   - gpr
   - gpr
-  - ares
   - boringssl
   - boringssl
+  - z
   headers:
   headers:
   - src/php/ext/grpc/byte_buffer.h
   - src/php/ext/grpc/byte_buffer.h
   - src/php/ext/grpc/call.h
   - src/php/ext/grpc/call.h

+ 1 - 55
config.m4

@@ -8,8 +8,6 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
-  PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares)
-  PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/cares)
 
 
   LIBS="-lpthread $LIBS"
   LIBS="-lpthread $LIBS"
 
 
@@ -23,10 +21,8 @@ if test "$PHP_GRPC" != "no"; then
 
 
   case $host in
   case $host in
     *darwin*)
     *darwin*)
-      PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_darwin)
       ;;
       ;;
     *)
     *)
-      PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_linux)
       PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
       PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
       PHP_ADD_LIBRARY(rt)
       PHP_ADD_LIBRARY(rt)
       ;;
       ;;
@@ -641,58 +637,9 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl/ssl/tls13_server.c \
     third_party/boringssl/ssl/tls13_server.c \
     third_party/boringssl/ssl/tls_method.c \
     third_party/boringssl/ssl/tls_method.c \
     third_party/boringssl/ssl/tls_record.c \
     third_party/boringssl/ssl/tls_record.c \
-    third_party/cares/cares/ares__close_sockets.c \
-    third_party/cares/cares/ares__get_hostent.c \
-    third_party/cares/cares/ares__read_line.c \
-    third_party/cares/cares/ares__timeval.c \
-    third_party/cares/cares/ares_cancel.c \
-    third_party/cares/cares/ares_create_query.c \
-    third_party/cares/cares/ares_data.c \
-    third_party/cares/cares/ares_destroy.c \
-    third_party/cares/cares/ares_expand_name.c \
-    third_party/cares/cares/ares_expand_string.c \
-    third_party/cares/cares/ares_fds.c \
-    third_party/cares/cares/ares_free_hostent.c \
-    third_party/cares/cares/ares_free_string.c \
-    third_party/cares/cares/ares_getenv.c \
-    third_party/cares/cares/ares_gethostbyaddr.c \
-    third_party/cares/cares/ares_gethostbyname.c \
-    third_party/cares/cares/ares_getnameinfo.c \
-    third_party/cares/cares/ares_getopt.c \
-    third_party/cares/cares/ares_getsock.c \
-    third_party/cares/cares/ares_init.c \
-    third_party/cares/cares/ares_library_init.c \
-    third_party/cares/cares/ares_llist.c \
-    third_party/cares/cares/ares_mkquery.c \
-    third_party/cares/cares/ares_nowarn.c \
-    third_party/cares/cares/ares_options.c \
-    third_party/cares/cares/ares_parse_a_reply.c \
-    third_party/cares/cares/ares_parse_aaaa_reply.c \
-    third_party/cares/cares/ares_parse_mx_reply.c \
-    third_party/cares/cares/ares_parse_naptr_reply.c \
-    third_party/cares/cares/ares_parse_ns_reply.c \
-    third_party/cares/cares/ares_parse_ptr_reply.c \
-    third_party/cares/cares/ares_parse_soa_reply.c \
-    third_party/cares/cares/ares_parse_srv_reply.c \
-    third_party/cares/cares/ares_parse_txt_reply.c \
-    third_party/cares/cares/ares_platform.c \
-    third_party/cares/cares/ares_process.c \
-    third_party/cares/cares/ares_query.c \
-    third_party/cares/cares/ares_search.c \
-    third_party/cares/cares/ares_send.c \
-    third_party/cares/cares/ares_strcasecmp.c \
-    third_party/cares/cares/ares_strdup.c \
-    third_party/cares/cares/ares_strerror.c \
-    third_party/cares/cares/ares_timeout.c \
-    third_party/cares/cares/ares_version.c \
-    third_party/cares/cares/ares_writev.c \
-    third_party/cares/cares/bitncmp.c \
-    third_party/cares/cares/inet_net_pton.c \
-    third_party/cares/cares/inet_ntop.c \
-    third_party/cares/cares/windows_port.c \
     , $ext_shared, , -fvisibility=hidden \
     , $ext_shared, , -fvisibility=hidden \
     -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \
     -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \
-    -D_HAS_EXCEPTIONS=0 -DNOMINMAX)
+    -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0)
 
 
   PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
   PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
 
 
@@ -792,6 +739,5 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509v3)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509v3)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/ssl)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/ssl)
-  PHP_ADD_BUILD_DIR($ext_builddir/third_party/cares/cares)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/nanopb)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/nanopb)
 fi
 fi

+ 642 - 0
config.w32

@@ -0,0 +1,642 @@
+// $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\\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");
+}

+ 2 - 0
doc/PROTOCOL-WEB.md

@@ -37,6 +37,8 @@ Content-Type
 
 
 1. application/grpc-web
 1. application/grpc-web
   * e.g. application/grpc-web+[proto, json, thrift]
   * 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
 2. application/grpc-web-text
   * text-encoded streams of “application/grpc-web”
   * text-encoded streams of “application/grpc-web”
   * e.g. application/grpc-web-text+[proto, thrift]
   * e.g. application/grpc-web-text+[proto, thrift]

+ 1 - 0
grpc.def

@@ -232,6 +232,7 @@ EXPORTS
     gpr_histogram_merge_contents
     gpr_histogram_merge_contents
     gpr_join_host_port
     gpr_join_host_port
     gpr_split_host_port
     gpr_split_host_port
+    gpr_log_severity_string
     gpr_log
     gpr_log
     gpr_log_message
     gpr_log_message
     gpr_set_log_verbosity
     gpr_set_log_verbosity

+ 8 - 6
include/grpc++/create_channel.h

@@ -43,23 +43,25 @@
 
 
 namespace grpc {
 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 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(
 std::shared_ptr<Channel> CreateChannel(
     const grpc::string& target,
     const grpc::string& target,
     const std::shared_ptr<ChannelCredentials>& creds);
     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
 /// \warning For advanced use and testing ONLY. Override default channel
 /// arguments only if necessary.
 /// arguments only if necessary.
 ///
 ///
 /// \param target The URI of the endpoint to connect to.
 /// \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.
 /// \param args Options for channel creation.
 std::shared_ptr<Channel> CreateCustomChannel(
 std::shared_ptr<Channel> CreateCustomChannel(
     const grpc::string& target,
     const grpc::string& target,

+ 2 - 2
include/grpc++/create_channel_posix.h

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

+ 1 - 1
include/grpc++/ext/health_check_service_server_builder_option.h

@@ -44,7 +44,7 @@ namespace grpc {
 
 
 class HealthCheckServiceServerBuilderOption : public ServerBuilderOption {
 class HealthCheckServiceServerBuilderOption : public ServerBuilderOption {
  public:
  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.
   /// To explicitly disable default service, pass in a nullptr.
   explicit HealthCheckServiceServerBuilderOption(
   explicit HealthCheckServiceServerBuilderOption(
       std::unique_ptr<HealthCheckServiceInterface> hc);
       std::unique_ptr<HealthCheckServiceInterface> hc);

+ 2 - 2
include/grpc++/ext/proto_server_reflection_plugin.h

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

+ 1 - 0
include/grpc++/grpc++.h

@@ -76,6 +76,7 @@
 // IWYU pragma: end_exports
 // IWYU pragma: end_exports
 
 
 namespace grpc {
 namespace grpc {
+/// Return gRPC library version.
 grpc::string Version();
 grpc::string Version();
 }  // namespace grpc
 }  // namespace grpc
 
 

+ 1 - 1
include/grpc++/health_check_service_interface.h

@@ -47,7 +47,7 @@ class HealthCheckServiceInterface {
  public:
  public:
   virtual ~HealthCheckServiceInterface() {}
   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,
   virtual void SetServingStatus(const grpc::string& service_name,
                                 bool serving) = 0;
                                 bool serving) = 0;
   /// Apply to all registered service names.
   /// Apply to all registered service names.

+ 4 - 3
include/grpc++/impl/codegen/client_context.h

@@ -307,7 +307,7 @@ class ClientContext {
 
 
   /// Flag whether the initial metadata should be \a corked
   /// 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.
   /// write of first message in the stream.
   ///
   ///
   /// \param corked The flag indicating whether the initial metadata is to be
   /// \param corked The flag indicating whether the initial metadata is to be
@@ -331,8 +331,9 @@ class ClientContext {
     return census_context_;
     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.
   /// There is no guarantee the call will be cancelled.
   void TryCancel();
   void TryCancel();

+ 5 - 0
include/grpc++/impl/server_builder_plugin.h

@@ -40,6 +40,7 @@
 
 
 namespace grpc {
 namespace grpc {
 
 
+class ServerBuilder;
 class ServerInitializer;
 class ServerInitializer;
 class ChannelArguments;
 class ChannelArguments;
 
 
@@ -51,6 +52,10 @@ class ServerBuilderPlugin {
   virtual ~ServerBuilderPlugin() {}
   virtual ~ServerBuilderPlugin() {}
   virtual grpc::string name() = 0;
   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
   /// InitServer will be called in ServerBuilder::BuildAndStart(), after the
   /// Server instance is created.
   /// Server instance is created.
   virtual void InitServer(ServerInitializer* si) = 0;
   virtual void InitServer(ServerInitializer* si) = 0;

+ 8 - 7
include/grpc++/resource_quota.h

@@ -42,9 +42,10 @@ struct grpc_resource_quota;
 namespace grpc {
 namespace grpc {
 
 
 /// ResourceQuota represents a bound on memory usage by the gRPC library.
 /// 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 {
 class ResourceQuota final : private GrpcLibraryCodegen {
  public:
  public:
   /// \param name - a unique name for this ResourceQuota.
   /// \param name - a unique name for this ResourceQuota.
@@ -52,10 +53,10 @@ class ResourceQuota final : private GrpcLibraryCodegen {
   ResourceQuota();
   ResourceQuota();
   ~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);
   ResourceQuota& Resize(size_t new_size);
 
 
   grpc_resource_quota* c_resource_quota() const { return impl_; }
   grpc_resource_quota* c_resource_quota() const { return impl_; }

+ 4 - 1
include/grpc++/security/auth_metadata_processor.h

@@ -42,6 +42,9 @@
 
 
 namespace grpc {
 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 {
 class AuthMetadataProcessor {
  public:
  public:
   typedef std::multimap<grpc::string_ref, grpc::string_ref> InputMetadata;
   typedef std::multimap<grpc::string_ref, grpc::string_ref> InputMetadata;
@@ -49,7 +52,7 @@ class AuthMetadataProcessor {
 
 
   virtual ~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.
   /// a different thread from the one processing the call.
   virtual bool IsBlocking() const { return true; }
   virtual bool IsBlocking() const { return true; }
 
 

+ 1 - 1
include/grpc++/security/credentials.h

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

+ 6 - 5
include/grpc++/security/server_credentials.h

@@ -70,7 +70,7 @@ class ServerCredentials {
 
 
 /// Options to create ServerCredentials with SSL
 /// Options to create ServerCredentials with SSL
 struct SslServerCredentialsOptions {
 struct SslServerCredentialsOptions {
-  /// Deprecated
+  /// \warning Deprecated
   SslServerCredentialsOptions()
   SslServerCredentialsOptions()
       : force_client_auth(false),
       : force_client_auth(false),
         client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {}
         client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {}
@@ -84,12 +84,13 @@ struct SslServerCredentialsOptions {
   };
   };
   grpc::string pem_root_certs;
   grpc::string pem_root_certs;
   std::vector<PemKeyCertPair> pem_key_cert_pairs;
   std::vector<PemKeyCertPair> pem_key_cert_pairs;
-  /// Deprecated
+  /// \warning Deprecated
   bool force_client_auth;
   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;
   grpc_ssl_client_certificate_request_type client_certificate_request;
 };
 };
 
 

+ 27 - 19
include/grpc++/server.h

@@ -60,23 +60,26 @@ class HealthCheckServiceInterface;
 class ServerContext;
 class ServerContext;
 class ServerInitializer;
 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 {
 class Server final : public ServerInterface, private GrpcLibraryCodegen {
  public:
  public:
   ~Server();
   ~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
   /// \warning The server must be either shutting down or some other thread must
   /// call \a Shutdown for this function to ever return.
   /// call \a Shutdown for this function to ever return.
   void Wait() override;
   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 {
   class GlobalCallbacks {
    public:
    public:
     virtual ~GlobalCallbacks() {}
     virtual ~GlobalCallbacks() {}
@@ -92,12 +95,14 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
     virtual void AddPort(Server* server, const grpc::string& addr,
     virtual void AddPort(Server* server, const grpc::string& addr,
                          ServerCredentials* creds, int port) {}
                          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);
   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();
   grpc_server* c_server();
 
 
   /// Returns the health check service.
   /// 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.
   /// service. The service must exist for the lifetime of the Server instance.
   void RegisterAsyncGenericService(AsyncGenericService* service) override;
   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,
   /// \param addr The address to try to bind to the server (eg, localhost:1234,
   /// 192.168.1.1:31416, [::1]:27182, etc.).
   /// 192.168.1.1:31416, [::1]:27182, etc.).
   /// \params creds The credentials associated with the server.
   /// \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,
   int AddListeningPort(const grpc::string& addr,
                        ServerCredentials* creds) override;
                        ServerCredentials* creds) override;
 
 
@@ -194,13 +201,14 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
 
 
   const int max_receive_message_size_;
   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>>>
   std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
       sync_server_cqs_;
       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_;
   std::vector<std::unique_ptr<SyncRequestThreadManager>> sync_req_mgrs_;
 
 
   // Sever status
   // Sever status

+ 27 - 18
include/grpc++/server_builder.h

@@ -71,7 +71,13 @@ class ServerBuilder {
   ServerBuilder();
   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.
   /// 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
   /// 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.
   /// 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
   /// 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
   /// Only matches requests with :authority \a host
   ServerBuilder& RegisterService(const grpc::string& host, Service* service);
   ServerBuilder& RegisterService(const grpc::string& host, Service* service);
 
 
@@ -110,7 +116,7 @@ class ServerBuilder {
   /// enabled by default.
   /// enabled by default.
   ///
   ///
   /// Incoming calls compressed with an unsupported algorithm will fail with
   /// Incoming calls compressed with an unsupported algorithm will fail with
-  /// GRPC_STATUS_UNIMPLEMENTED.
+  /// \a GRPC_STATUS_UNIMPLEMENTED.
   ServerBuilder& SetCompressionAlgorithmSupportStatus(
   ServerBuilder& SetCompressionAlgorithmSupportStatus(
       grpc_compression_algorithm algorithm, bool enabled);
       grpc_compression_algorithm algorithm, bool enabled);
 
 
@@ -139,15 +145,17 @@ class ServerBuilder {
     return SetOption(MakeChannelArgumentOption(arg, value));
     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.
   /// It can be invoked multiple times.
   ///
   ///
   /// \param addr The address to try to bind to the server (eg, localhost:1234,
   /// \param addr The address to try to bind to the server (eg, localhost:1234,
   /// 192.168.1.1:31416, [::1]:27182, etc.).
   /// 192.168.1.1:31416, [::1]:27182, etc.).
   /// \params creds The credentials associated with the server.
   /// \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.
   // TODO(dgq): the "port" part seems to be a misnomer.
   ServerBuilder& AddListeningPort(const grpc::string& addr,
   ServerBuilder& AddListeningPort(const grpc::string& addr,
@@ -169,12 +177,13 @@ class ServerBuilder {
   /// server_->Shutdown();
   /// server_->Shutdown();
   /// cq_->Shutdown();  // Always *after* the associated server's 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
   /// 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(
   std::unique_ptr<ServerCompletionQueue> AddCompletionQueue(
       bool is_frequently_polled = true);
       bool is_frequently_polled = true);
 
 
@@ -206,18 +215,18 @@ class ServerBuilder {
           max_pollers(2),
           max_pollers(2),
           cq_timeout_msec(10000) {}
           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;
     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;
     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;
     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;
     int cq_timeout_msec;
   };
   };
 
 
@@ -238,7 +247,7 @@ class ServerBuilder {
 
 
   SyncServerSettings sync_server_settings_;
   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::vector<ServerCompletionQueue*> cqs_;
 
 
   std::shared_ptr<ServerCredentials> creds_;
   std::shared_ptr<ServerCredentials> creds_;

+ 3 - 2
include/grpc++/server_posix.h

@@ -43,9 +43,10 @@ namespace grpc {
 
 
 #ifdef GPR_SUPPORT_CHANNELS_FROM_FD
 #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.
 /// \param fd The file descriptor representing a socket.
 void AddInsecureChannelFromFd(Server* server, int fd);
 void AddInsecureChannelFromFd(Server* server, int fd);
 
 

+ 6 - 6
include/grpc++/support/channel_arguments.h

@@ -49,7 +49,7 @@ class ChannelArgumentsTest;
 class ResourceQuota;
 class ResourceQuota;
 
 
 /// Options for channel creation. The user can use generic setters to pass
 /// 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.
 /// concrete setters are provided.
 class ChannelArguments {
 class ChannelArguments {
  public:
  public:
@@ -82,13 +82,13 @@ class ChannelArguments {
   /// Set the socket mutator for the channel.
   /// Set the socket mutator for the channel.
   void SetSocketMutator(grpc_socket_mutator* mutator);
   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);
   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);
   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 SetMaxReceiveMessageSize(int size);
   void SetMaxSendMessageSize(int size);
   void SetMaxSendMessageSize(int size);
 
 
@@ -115,8 +115,8 @@ class ChannelArguments {
   /// Set a textual argument \a value under \a key.
   /// Set a textual argument \a value under \a key.
   void SetString(const grpc::string& key, const grpc::string& value);
   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 c_channel_args() const {
     grpc_channel_args out;
     grpc_channel_args out;
     out.num_args = args_.size();
     out.num_args = args_.size();

+ 5 - 5
include/grpc++/support/error_details.h

@@ -44,16 +44,16 @@ class Status;
 
 
 namespace grpc {
 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.
 /// The given \a to object will be cleared.
 /// On success, returns status with OK.
 /// 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);
 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 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);
 Status SetErrorDetails(const ::google::rpc::Status& from, Status* to);
 
 
 }  // namespace grpc
 }  // namespace grpc

+ 1 - 1
include/grpc++/support/slice.h

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

+ 2 - 2
include/grpc++/test/server_context_test_spouse.h

@@ -47,7 +47,7 @@ class ServerContextTestSpouse {
   explicit ServerContextTestSpouse(ServerContext* ctx) : ctx_(ctx) {}
   explicit ServerContextTestSpouse(ServerContext* ctx) : ctx_(ctx) {}
 
 
   /// Inject client metadata to the ServerContext for the test. The test spouse
   /// 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) {
   void AddClientMetadata(const grpc::string& key, const grpc::string& value) {
     client_metadata_storage_.insert(
     client_metadata_storage_.insert(
         std::pair<grpc::string, grpc::string>(key, value));
         std::pair<grpc::string, grpc::string>(key, value));
@@ -70,7 +70,7 @@ class ServerContextTestSpouse {
   }
   }
 
 
  private:
  private:
-  ServerContext* ctx_;  /// not owned
+  ServerContext* ctx_;  // not owned
   std::multimap<grpc::string, grpc::string> client_metadata_storage_;
   std::multimap<grpc::string, grpc::string> client_metadata_storage_;
 };
 };
 
 

+ 1 - 1
include/grpc/support/log.h

@@ -65,7 +65,7 @@ typedef enum gpr_log_severity {
 #define GPR_LOG_VERBOSITY_UNSET -1
 #define GPR_LOG_VERBOSITY_UNSET -1
 
 
 /** Returns a string representation of the log severity */
 /** 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 */
 /** Macros to build log contexts at various severity levels */
 #define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG
 #define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG

+ 1 - 1
package.json

@@ -34,7 +34,7 @@
     "lodash": "^4.15.0",
     "lodash": "^4.15.0",
     "nan": "^2.0.0",
     "nan": "^2.0.0",
     "node-pre-gyp": "^0.6.0",
     "node-pre-gyp": "^0.6.0",
-    "protobufjs": "^6.7.0"
+    "protobufjs": "^5.0.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "async": "^2.0.1",
     "async": "^2.0.1",

+ 52 - 78
package.xml

@@ -10,7 +10,7 @@
   <email>grpc-packages@google.com</email>
   <email>grpc-packages@google.com</email>
   <active>yes</active>
   <active>yes</active>
  </lead>
  </lead>
- <date>2017-03-01</date>
+ <date>2017-05-22</date>
  <time>16:06:07</time>
  <time>16:06:07</time>
  <version>
  <version>
   <release>1.4.0dev</release>
   <release>1.4.0dev</release>
@@ -22,15 +22,19 @@
  </stability>
  </stability>
  <license>BSD</license>
  <license>BSD</license>
  <notes>
  <notes>
-- Added arg info macros #9751
-- Updated codegen to be consistent with protobuf #9492
+- 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>
  </notes>
  <contents>
  <contents>
   <dir baseinstalldir="/" name="/">
   <dir baseinstalldir="/" name="/">
     <file baseinstalldir="/" name="config.m4" role="src" />
     <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/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/byte_buffer.c" role="src" />
     <file baseinstalldir="/" name="src/php/ext/grpc/call.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" />
     <file baseinstalldir="/" name="src/php/ext/grpc/call_credentials.c" role="src" />
@@ -1058,79 +1062,33 @@
     <file baseinstalldir="/" name="third_party/boringssl/ssl/tls13_server.c" role="src" />
     <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_method.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/tls_record.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/tls_record.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_data.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_dns.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_getenv.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_getopt.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_inet_net_pton.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_iphlpapi.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_ipv6.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_library_init.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_llist.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_nowarn.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_platform.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_private.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_rules.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_setup.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_strcasecmp.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_strdup.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_version.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/bitncmp.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/config-win32.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/setup_once.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/ares_build.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/config_linux/ares_config.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/config_darwin/ares_config.h" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares__close_sockets.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares__get_hostent.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares__read_line.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares__timeval.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_cancel.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_create_query.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_data.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_destroy.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_expand_name.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_expand_string.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_fds.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_free_hostent.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_free_string.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_getenv.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_gethostbyaddr.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_gethostbyname.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_getnameinfo.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_getopt.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_getsock.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_init.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_library_init.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_llist.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_mkquery.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_nowarn.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_options.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_a_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_aaaa_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_mx_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_naptr_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_ns_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_ptr_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_soa_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_srv_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_txt_reply.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_platform.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_process.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_query.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_search.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_send.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_strcasecmp.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_strdup.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_strerror.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_timeout.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_version.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/ares_writev.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/bitncmp.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/inet_net_pton.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/inet_ntop.c" role="src" />
-    <file baseinstalldir="/" name="third_party/cares/cares/windows_port.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>
   </dir>
  </contents>
  </contents>
  <dependencies>
  <dependencies>
@@ -1443,6 +1401,22 @@ Update to wrap gRPC C Core version 0.10.0
    <license>BSD</license>
    <license>BSD</license>
    <notes>
    <notes>
 - Added arg info macros #9751
 - Added arg info macros #9751
+- Updated codegen to be consistent with protobuf #9492
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>1.2.0</release>
+    <api>1.2.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2017-03-20</date>
+   <license>BSD</license>
+   <notes>
+- Added arg info macros #9751
 - Updated codegen to be consistent with protobuf #9492
 - Updated codegen to be consistent with protobuf #9492
    </notes>
    </notes>
   </release>
   </release>

+ 10 - 11
src/compiler/php_generator.cc

@@ -67,12 +67,11 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
   vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
   vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
   vars["output_type_id"] = MessageIdentifierName(output_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()) {
   if (method->client_streaming()) {
     out->Print(vars,
     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 = [], "
                "public function $name$($$metadata = [], "
                "$$options = []) {\n");
                "$$options = []) {\n");
     out->Indent();
     out->Indent();
@@ -87,9 +86,9 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
                "$$metadata, $$options);\n");
                "$$metadata, $$options);\n");
   } else {
   } else {
     out->Print(vars,
     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"
                "public function $name$(\\$input_type_id$ $$argument,\n"
                "  $$metadata = [], $$options = []) {\n");
                "  $$metadata = [], $$options = []) {\n");
     out->Indent();
     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->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n");
   out->Indent();
   out->Indent();
   out->Print(
   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, "
       "public function __construct($$hostname, $$opts, "
       "$$channel = null) {\n");
       "$$channel = null) {\n");
   out->Indent();
   out->Indent();

+ 15 - 3
src/core/ext/filters/client_channel/client_channel.c

@@ -914,10 +914,13 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
   grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
   grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
                                            chand->interested_parties);
                                            chand->interested_parties);
   if (calld->connected_subchannel == NULL) {
   if (calld->connected_subchannel == NULL) {
-    gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
+    gpr_atm_no_barrier_store(&calld->subchannel_call, (gpr_atm)CANCELLED_CALL);
     fail_locked(exec_ctx, calld,
     fail_locked(exec_ctx, calld,
-                GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
-                    "Failed to create subchannel", &error, 1));
+                error == GRPC_ERROR_NONE
+                    ? GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                          "Call dropped by load balancing policy")
+                    : GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+                          "Failed to create subchannel", &error, 1));
   } else if (GET_CALL(calld) == CANCELLED_CALL) {
   } else if (GET_CALL(calld) == CANCELLED_CALL) {
     /* already cancelled before subchannel became ready */
     /* already cancelled before subchannel became ready */
     grpc_error *cancellation_error =
     grpc_error *cancellation_error =
@@ -1180,6 +1183,15 @@ static void start_transport_stream_op_batch_locked_inner(
             &calld->next_step)) {
             &calld->next_step)) {
       calld->pick_pending = false;
       calld->pick_pending = false;
       GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
       GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
+      if (calld->connected_subchannel == NULL) {
+        gpr_atm_no_barrier_store(&calld->subchannel_call,
+                                 (gpr_atm)CANCELLED_CALL);
+        grpc_error *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+            "Call dropped by load balancing policy");
+        fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
+        grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
+        return;  // Early out.
+      }
     } else {
     } else {
       grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
       grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
                                              chand->interested_parties);
                                              chand->interested_parties);

+ 3 - 1
src/core/ext/filters/client_channel/lb_policy.h

@@ -149,7 +149,9 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
 
 
 /** Finds an appropriate subchannel for a call, based on \a pick_args.
 /** Finds an appropriate subchannel for a call, based on \a pick_args.
 
 
-    \a target will be set to the selected subchannel, or NULL on failure.
+    \a target will be set to the selected subchannel, or NULL on failure
+    or when the LB policy decides to drop the call.
+
     Upon success, \a user_data will be set to whatever opaque information
     Upon success, \a user_data will be set to whatever opaque information
     may need to be propagated from the LB policy, or NULL if not needed.
     may need to be propagated from the LB policy, or NULL if not needed.
     \a context will be populated with context to pass to the subchannel
     \a context will be populated with context to pass to the subchannel

+ 64 - 17
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c

@@ -327,6 +327,11 @@ typedef struct glb_lb_policy {
    * response has arrived. */
    * response has arrived. */
   grpc_grpclb_serverlist *serverlist;
   grpc_grpclb_serverlist *serverlist;
 
 
+  /** Index into serverlist for next pick.
+   * If the server at this index is a drop, we return a drop.
+   * Otherwise, we delegate to the RR policy. */
+  size_t serverlist_index;
+
   /** list of picks that are waiting on RR's policy connectivity */
   /** list of picks that are waiting on RR's policy connectivity */
   pending_pick *pending_picks;
   pending_pick *pending_picks;
 
 
@@ -402,6 +407,9 @@ struct rr_connectivity_data {
 
 
 static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
 static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
                             bool log) {
                             bool log) {
+  if (server->drop_for_rate_limiting || server->drop_for_load_balancing) {
+    return false;
+  }
   const grpc_grpclb_ip_address *ip = &server->ip_address;
   const grpc_grpclb_ip_address *ip = &server->ip_address;
   if (server->port >> 16 != 0) {
   if (server->port >> 16 != 0) {
     if (log) {
     if (log) {
@@ -411,7 +419,6 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
     }
     }
     return false;
     return false;
   }
   }
-
   if (ip->size != 4 && ip->size != 16) {
   if (ip->size != 4 && ip->size != 16) {
     if (log) {
     if (log) {
       gpr_log(GPR_ERROR,
       gpr_log(GPR_ERROR,
@@ -445,11 +452,12 @@ static const grpc_lb_user_data_vtable lb_token_vtable = {
 
 
 static void parse_server(const grpc_grpclb_server *server,
 static void parse_server(const grpc_grpclb_server *server,
                          grpc_resolved_address *addr) {
                          grpc_resolved_address *addr) {
+  memset(addr, 0, sizeof(*addr));
+  if (server->drop_for_rate_limiting || server->drop_for_load_balancing) return;
   const uint16_t netorder_port = htons((uint16_t)server->port);
   const uint16_t netorder_port = htons((uint16_t)server->port);
   /* the addresses are given in binary format (a in(6)_addr struct) in
   /* the addresses are given in binary format (a in(6)_addr struct) in
    * server->ip_address.bytes. */
    * server->ip_address.bytes. */
   const grpc_grpclb_ip_address *ip = &server->ip_address;
   const grpc_grpclb_ip_address *ip = &server->ip_address;
-  memset(addr, 0, sizeof(*addr));
   if (ip->size == 4) {
   if (ip->size == 4) {
     addr->len = sizeof(struct sockaddr_in);
     addr->len = sizeof(struct sockaddr_in);
     struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr;
     struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr;
@@ -586,16 +594,51 @@ static bool update_lb_connectivity_status_locked(
   return true;
   return true;
 }
 }
 
 
-/* perform a pick over \a rr_policy. Given that a pick can return immediately
- * (ignoring its completion callback) we need to perform the cleanups this
- * callback would be otherwise resposible for */
+/* Perform a pick over \a glb_policy->rr_policy. Given that a pick can return
+ * immediately (ignoring its completion callback), we need to perform the
+ * cleanups this callback would otherwise be resposible for.
+ * If \a force_async is true, then we will manually schedule the
+ * completion callback even if the pick is available immediately. */
 static bool pick_from_internal_rr_locked(
 static bool pick_from_internal_rr_locked(
-    grpc_exec_ctx *exec_ctx, grpc_lb_policy *rr_policy,
-    const grpc_lb_policy_pick_args *pick_args,
+    grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
+    const grpc_lb_policy_pick_args *pick_args, bool force_async,
     grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
     grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
-  GPR_ASSERT(rr_policy != NULL);
+  // Look at the index into the serverlist to see if we should drop this call.
+  grpc_grpclb_server *server =
+      glb_policy->serverlist->servers[glb_policy->serverlist_index++];
+  if (glb_policy->serverlist_index == glb_policy->serverlist->num_servers) {
+    glb_policy->serverlist_index = 0;  // Wrap-around.
+  }
+  if (server->drop_for_rate_limiting || server->drop_for_load_balancing) {
+    // Not using the RR policy, so unref it.
+    if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
+      gpr_log(GPR_INFO, "Unreffing RR for drop (0x%" PRIxPTR ")",
+              (intptr_t)wc_arg->rr_policy);
+    }
+    GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
+    // Update client load reporting stats to indicate the number of
+    // dropped calls.  Note that we have to do this here instead of in
+    // the client_load_reporting filter, because we do not create a
+    // subchannel call (and therefore no client_load_reporting filter)
+    // for dropped calls.
+    grpc_grpclb_client_stats_add_call_started(wc_arg->client_stats);
+    grpc_grpclb_client_stats_add_call_finished(
+        server->drop_for_rate_limiting, server->drop_for_load_balancing,
+        false /* failed_to_send */, false /* known_received */,
+        wc_arg->client_stats);
+    grpc_grpclb_client_stats_unref(wc_arg->client_stats);
+    if (force_async) {
+      GPR_ASSERT(wc_arg->wrapped_closure != NULL);
+      grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
+      gpr_free(wc_arg->free_when_done);
+      return false;
+    }
+    gpr_free(wc_arg->free_when_done);
+    return true;
+  }
+  // Pick via the RR policy.
   const bool pick_done = grpc_lb_policy_pick_locked(
   const bool pick_done = grpc_lb_policy_pick_locked(
-      exec_ctx, rr_policy, pick_args, target, wc_arg->context,
+      exec_ctx, wc_arg->rr_policy, pick_args, target, wc_arg->context,
       (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
       (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
   if (pick_done) {
   if (pick_done) {
     /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
     /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
@@ -604,17 +647,20 @@ static bool pick_from_internal_rr_locked(
               (intptr_t)wc_arg->rr_policy);
               (intptr_t)wc_arg->rr_policy);
     }
     }
     GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
     GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
-
     /* add the load reporting initial metadata */
     /* add the load reporting initial metadata */
     initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
     initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
                                   pick_args->lb_token_mdelem_storage,
                                   pick_args->lb_token_mdelem_storage,
                                   GRPC_MDELEM_REF(wc_arg->lb_token));
                                   GRPC_MDELEM_REF(wc_arg->lb_token));
-
     // Pass on client stats via context. Passes ownership of the reference.
     // Pass on client stats via context. Passes ownership of the reference.
     GPR_ASSERT(wc_arg->client_stats != NULL);
     GPR_ASSERT(wc_arg->client_stats != NULL);
     wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats;
     wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats;
     wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats;
     wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats;
-
+    if (force_async) {
+      GPR_ASSERT(wc_arg->wrapped_closure != NULL);
+      grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
+      gpr_free(wc_arg->free_when_done);
+      return false;
+    }
     gpr_free(wc_arg->free_when_done);
     gpr_free(wc_arg->free_when_done);
   }
   }
   /* else, the pending pick will be registered and taken care of by the
   /* else, the pending pick will be registered and taken care of by the
@@ -744,8 +790,8 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
       gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
       gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
               (intptr_t)glb_policy->rr_policy);
               (intptr_t)glb_policy->rr_policy);
     }
     }
-    pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
-                                 &pp->pick_args, pp->target,
+    pick_from_internal_rr_locked(exec_ctx, glb_policy, &pp->pick_args,
+                                 true /* force_async */, pp->target,
                                  &pp->wrapped_on_complete_arg);
                                  &pp->wrapped_on_complete_arg);
   }
   }
 
 
@@ -1115,8 +1161,9 @@ static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
     wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
     wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
     wc_arg->initial_metadata = pick_args->initial_metadata;
     wc_arg->initial_metadata = pick_args->initial_metadata;
     wc_arg->free_when_done = wc_arg;
     wc_arg->free_when_done = wc_arg;
-    pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
-                                             pick_args, target, wc_arg);
+    pick_done =
+        pick_from_internal_rr_locked(exec_ctx, glb_policy, pick_args,
+                                     false /* force_async */, target, wc_arg);
   } else {
   } else {
     if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
     if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
       gpr_log(GPR_DEBUG,
       gpr_log(GPR_DEBUG,
@@ -1517,7 +1564,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
              * serverlist instance will be destroyed either upon the next
              * serverlist instance will be destroyed either upon the next
              * update or in glb_destroy() */
              * update or in glb_destroy() */
             glb_policy->serverlist = serverlist;
             glb_policy->serverlist = serverlist;
-
+            glb_policy->serverlist_index = 0;
             rr_handover_locked(exec_ctx, glb_policy);
             rr_handover_locked(exec_ctx, glb_policy);
           }
           }
         } else {
         } else {

+ 43 - 46
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c

@@ -37,44 +37,39 @@
 
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
 
 
+/* invoked once for every Server in ServerList */
+static bool count_serverlist(pb_istream_t *stream, const pb_field_t *field,
+                             void **arg) {
+  grpc_grpclb_serverlist *sl = *arg;
+  grpc_grpclb_server server;
+  if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) {
+    gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
+    return false;
+  }
+  ++sl->num_servers;
+  return true;
+}
+
 typedef struct decode_serverlist_arg {
 typedef struct decode_serverlist_arg {
-  /* The first pass counts the number of servers in the server list. The second
-   * one allocates and decodes. */
-  bool first_pass;
   /* The decoding callback is invoked once per server in serverlist. Remember
   /* The decoding callback is invoked once per server in serverlist. Remember
    * which index of the serverlist are we currently decoding */
    * which index of the serverlist are we currently decoding */
   size_t decoding_idx;
   size_t decoding_idx;
-  /* Populated after the first pass. Number of server in the input serverlist */
-  size_t num_servers;
   /* The decoded serverlist */
   /* The decoded serverlist */
-  grpc_grpclb_server **servers;
+  grpc_grpclb_serverlist *serverlist;
 } decode_serverlist_arg;
 } decode_serverlist_arg;
 
 
 /* invoked once for every Server in ServerList */
 /* invoked once for every Server in ServerList */
 static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
 static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
                               void **arg) {
                               void **arg) {
   decode_serverlist_arg *dec_arg = *arg;
   decode_serverlist_arg *dec_arg = *arg;
-  if (dec_arg->first_pass) { /* count how many server do we have */
-    grpc_grpclb_server server;
-    if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) {
-      gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
-      return false;
-    }
-    dec_arg->num_servers++;
-  } else { /* second pass. Actually decode. */
-    grpc_grpclb_server *server = gpr_zalloc(sizeof(grpc_grpclb_server));
-    GPR_ASSERT(dec_arg->num_servers > 0);
-    if (dec_arg->decoding_idx == 0) { /* first iteration of second pass */
-      dec_arg->servers =
-          gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers);
-    }
-    if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) {
-      gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
-      return false;
-    }
-    dec_arg->servers[dec_arg->decoding_idx++] = server;
+  GPR_ASSERT(dec_arg->serverlist->num_servers >= dec_arg->decoding_idx);
+  grpc_grpclb_server *server = gpr_zalloc(sizeof(grpc_grpclb_server));
+  if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) {
+    gpr_free(server);
+    gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
+    return false;
   }
   }
-
+  dec_arg->serverlist->servers[dec_arg->decoding_idx++] = server;
   return true;
   return true;
 }
 }
 
 
@@ -165,36 +160,38 @@ grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse(
 
 
 grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
 grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
     grpc_slice encoded_grpc_grpclb_response) {
     grpc_slice encoded_grpc_grpclb_response) {
-  bool status;
-  decode_serverlist_arg arg;
   pb_istream_t stream =
   pb_istream_t stream =
       pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_grpc_grpclb_response),
       pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_grpc_grpclb_response),
                              GRPC_SLICE_LENGTH(encoded_grpc_grpclb_response));
                              GRPC_SLICE_LENGTH(encoded_grpc_grpclb_response));
   pb_istream_t stream_at_start = stream;
   pb_istream_t stream_at_start = stream;
+  grpc_grpclb_serverlist *sl = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
   grpc_grpclb_response res;
   grpc_grpclb_response res;
   memset(&res, 0, sizeof(grpc_grpclb_response));
   memset(&res, 0, sizeof(grpc_grpclb_response));
-  memset(&arg, 0, sizeof(decode_serverlist_arg));
-
-  res.server_list.servers.funcs.decode = decode_serverlist;
-  res.server_list.servers.arg = &arg;
-  arg.first_pass = true;
-  status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res);
+  // First pass: count number of servers.
+  res.server_list.servers.funcs.decode = count_serverlist;
+  res.server_list.servers.arg = sl;
+  bool status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res);
   if (!status) {
   if (!status) {
+    gpr_free(sl);
     gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
     gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
     return NULL;
     return NULL;
   }
   }
-
-  arg.first_pass = false;
-  status =
-      pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, &res);
-  if (!status) {
-    gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
-    return NULL;
+  // Second pass: populate servers.
+  if (sl->num_servers > 0) {
+    sl->servers = gpr_zalloc(sizeof(grpc_grpclb_server *) * sl->num_servers);
+    decode_serverlist_arg decode_arg;
+    memset(&decode_arg, 0, sizeof(decode_arg));
+    decode_arg.serverlist = sl;
+    res.server_list.servers.funcs.decode = decode_serverlist;
+    res.server_list.servers.arg = &decode_arg;
+    status = pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields,
+                       &res);
+    if (!status) {
+      grpc_grpclb_destroy_serverlist(sl);
+      gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
+      return NULL;
+    }
   }
   }
-
-  grpc_grpclb_serverlist *sl = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
-  sl->num_servers = arg.num_servers;
-  sl->servers = arg.servers;
   if (res.server_list.has_expiration_interval) {
   if (res.server_list.has_expiration_interval) {
     sl->expiration_interval = res.server_list.expiration_interval;
     sl->expiration_interval = res.server_list.expiration_interval;
   }
   }
@@ -228,7 +225,7 @@ grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
 
 
 bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs,
 bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs,
                                    const grpc_grpclb_serverlist *rhs) {
                                    const grpc_grpclb_serverlist *rhs) {
-  if ((lhs == NULL) || (rhs == NULL)) {
+  if (lhs == NULL || rhs == NULL) {
     return false;
     return false;
   }
   }
   if (lhs->num_servers != rhs->num_servers) {
   if (lhs->num_servers != rhs->num_servers) {

+ 1 - 1
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h

@@ -51,7 +51,7 @@ typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request;
 typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response;
 typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response;
 typedef grpc_lb_v1_Server grpc_grpclb_server;
 typedef grpc_lb_v1_Server grpc_grpclb_server;
 typedef grpc_lb_v1_Duration grpc_grpclb_duration;
 typedef grpc_lb_v1_Duration grpc_grpclb_duration;
-typedef struct grpc_grpclb_serverlist {
+typedef struct {
   grpc_grpclb_server **servers;
   grpc_grpclb_server **servers;
   size_t num_servers;
   size_t num_servers;
   grpc_grpclb_duration expiration_interval;
   grpc_grpclb_duration expiration_interval;

+ 176 - 283
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c

@@ -99,26 +99,13 @@ typedef struct pending_pick {
   grpc_closure *on_complete;
   grpc_closure *on_complete;
 } pending_pick;
 } 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 {
 typedef struct {
-  /** index within policy->subchannels */
-  size_t index;
   /** backpointer to owning policy */
   /** backpointer to owning policy */
   round_robin_lb_policy *policy;
   round_robin_lb_policy *policy;
   /** subchannel itself */
   /** subchannel itself */
   grpc_subchannel *subchannel;
   grpc_subchannel *subchannel;
   /** notification that connectivity has changed on subchannel */
   /** notification that connectivity has changed on subchannel */
   grpc_closure connectivity_changed_closure;
   grpc_closure connectivity_changed_closure;
-  /** this subchannels current position in subchannel->ready_list */
-  ready_list *ready_list_node;
   /** last observed connectivity. Not updated by
   /** last observed connectivity. Not updated by
    * \a grpc_subchannel_notify_on_state_change. Used to determine the previous
    * \a grpc_subchannel_notify_on_state_change. Used to determine the previous
    * state while processing the new state in \a rr_connectivity_changed */
    * state while processing the new state in \a rr_connectivity_changed */
@@ -126,6 +113,10 @@ typedef struct {
   /** current connectivity state. Updated by \a
   /** current connectivity state. Updated by \a
    * grpc_subchannel_notify_on_state_change */
    * grpc_subchannel_notify_on_state_change */
   grpc_connectivity_state curr_connectivity_state;
   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 */
   /** the subchannel's target user data */
   void *user_data;
   void *user_data;
   /** vtable to operate over \a user_data */
   /** vtable to operate over \a user_data */
@@ -141,182 +132,106 @@ struct round_robin_lb_policy {
 
 
   /** all our subchannels */
   /** all our subchannels */
   size_t num_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;
   size_t num_transient_failures;
-  /** how many subchannels are IDLE */
+  /** how many subchannels are in state IDLE */
   size_t num_idle;
   size_t num_idle;
 
 
   /** have we started picking? */
   /** have we started picking? */
-  int started_picking;
+  bool started_picking;
   /** are we shutting down? */
   /** are we shutting down? */
-  int shutdown;
+  bool shutdown;
   /** List of picks that are waiting on connectivity */
   /** List of picks that are waiting on connectivity */
   pending_pick *pending_picks;
   pending_pick *pending_picks;
 
 
   /** our connectivity state tracker */
   /** our connectivity state tracker */
   grpc_connectivity_state_tracker 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)) {
   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)) {
   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) {
 static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   round_robin_lb_policy *p = (round_robin_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)) {
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
     gpr_log(GPR_DEBUG, "Destroying Round Robin policy at %p", (void *)pol);
     gpr_log(GPR_DEBUG, "Destroying Round Robin policy at %p", (void *)pol);
   }
   }
-
   for (size_t i = 0; i < p->num_subchannels; i++) {
   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);
   grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
   gpr_free(p->subchannels);
   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);
   gpr_free(p);
 }
 }
 
 
 static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
 static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   round_robin_lb_policy *p = (round_robin_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)) {
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
     gpr_log(GPR_DEBUG, "Shutting down Round Robin policy at %p", (void *)pol);
     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)) {
   while ((pp = p->pending_picks)) {
     p->pending_picks = pp->next;
     p->pending_picks = pp->next;
     *pp->target = NULL;
     *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(
   grpc_connectivity_state_set(
       exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
       exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "rr_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_connected_subchannel **target,
                                   grpc_error *error) {
                                   grpc_error *error) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   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;
   p->pending_picks = NULL;
   while (pp != NULL) {
   while (pp != NULL) {
     pending_pick *next = pp->next;
     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,
                                    uint32_t initial_metadata_flags_eq,
                                    grpc_error *error) {
                                    grpc_error *error) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   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;
   p->pending_picks = NULL;
   while (pp != NULL) {
   while (pp != NULL) {
     pending_pick *next = pp->next;
     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,
 static void start_picking_locked(grpc_exec_ctx *exec_ctx,
                                  round_robin_lb_policy *p) {
                                  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_call_context_element *context, void **user_data,
                           grpc_closure *on_complete) {
                           grpc_closure *on_complete) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   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)) {
   if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
     gpr_log(GPR_INFO, "Round Robin %p trying to pick", (void *)pol);
     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 */
     /* readily available, report right away */
+    subchannel_data *sd = &p->subchannels[next_ready_index];
     *target = GRPC_CONNECTED_SUBCHANNEL_REF(
     *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) {
     if (user_data != NULL) {
-      *user_data = selected->user_data;
+      *user_data = sd->user_data;
     }
     }
     if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
     if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
       gpr_log(GPR_DEBUG,
       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 */
     /* 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;
     return 1;
   } else {
   } else {
     /* no pick currently available. Save for later in list of pending picks */
     /* no pick currently available. Save for later in list of pending picks */
     if (!p->started_picking) {
     if (!p->started_picking) {
       start_picking_locked(exec_ctx, p);
       start_picking_locked(exec_ctx, p);
     }
     }
-    pp = gpr_malloc(sizeof(*pp));
+    pending_pick *pp = gpr_malloc(sizeof(*pp));
     pp->next = p->pending_picks;
     pp->next = p->pending_picks;
     pp->target = target;
     pp->target = target;
     pp->on_complete = on_complete;
     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;
   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);
     GPR_ASSERT(p->num_transient_failures > 0);
     --p->num_transient_failures;
     --p->num_transient_failures;
   } else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
   } else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
     GPR_ASSERT(p->num_idle > 0);
     GPR_ASSERT(p->num_idle > 0);
     --p->num_idle;
     --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.
 /* sd is the subchannel_data associted with the updated subchannel.
  * shutdown_error will only be used upon policy transition to TRANSIENT_FAILURE
  * shutdown_error will only be used upon policy transition to TRANSIENT_FAILURE
  * or SHUTDOWN */
  * 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) {
     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
   /* In priority order. The first rule to match terminates the search (ie, if we
    * are on rule n, all previous rules were unfulfilled).
    * 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.
    *    CHECK: p->num_idle == p->num_subchannels.
    */
    */
   round_robin_lb_policy *p = sd->policy;
   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_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY,
                                 GRPC_ERROR_NONE, "rr_ready");
                                 GRPC_ERROR_NONE, "rr_ready");
     return GRPC_CHANNEL_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) {
                                            grpc_error *error) {
   subchannel_data *sd = arg;
   subchannel_data *sd = arg;
   round_robin_lb_policy *p = sd->policy;
   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) {
   if (p->shutdown) {
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
     GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
-    GRPC_ERROR_UNREF(error);
     return;
     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
       /* at this point we know there's at least one suitable subchannel. Go
        * ahead and pick one and notify the pending suitors in
        * ahead and pick one and notify the pending suitors in
        * p->pending_picks. This preemtively replicates rr_pick()'s actions. */
        * 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 (p->pending_picks != NULL) {
         /* if the selected subchannel is going to be used for the pending
         /* if the selected subchannel is going to be used for the pending
          * picks, update the last picked pointer */
          * 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)) {
       while ((pp = p->pending_picks)) {
         p->pending_picks = pp->next;
         p->pending_picks = pp->next;
         *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(
         *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)) {
         if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
           gpr_log(GPR_DEBUG,
           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);
         grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
         gpr_free(pp);
         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(
 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,
 static void rr_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
                                grpc_closure *closure) {
                                grpc_closure *closure) {
   round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
   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),
         grpc_subchannel_get_connected_subchannel(selected->subchannel),
         "rr_picked");
         "rr_picked");
     grpc_connected_subchannel_ping(exec_ctx, target, closure);
     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);
   p->subchannels = gpr_zalloc(sizeof(*p->subchannels) * num_addrs);
 
 
   grpc_subchannel_args sc_args;
   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++) {
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     /* Skip balancer addresses, since we only know how to handle backends. */
     /* Skip balancer addresses, since we only know how to handle backends. */
     if (addresses->addresses[i].is_balancer) continue;
     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)) {
     if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
       char *address_uri =
       char *address_uri =
           grpc_sockaddr_to_uri(&addresses->addresses[i].address);
           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);
       gpr_free(address_uri);
     }
     }
     grpc_channel_args_destroy(exec_ctx, new_args);
     grpc_channel_args_destroy(exec_ctx, new_args);
 
 
     if (subchannel != NULL) {
     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->policy = p;
-      sd->index = subchannel_idx;
       sd->subchannel = subchannel;
       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;
       sd->user_data_vtable = addresses->user_data_vtable;
       if (sd->user_data_vtable != NULL) {
       if (sd->user_data_vtable != NULL) {
         sd->user_data =
         sd->user_data =
             sd->user_data_vtable->copy(addresses->addresses[i].user_data);
             sd->user_data_vtable->copy(addresses->addresses[i].user_data);
       }
       }
-      ++subchannel_idx;
       grpc_closure_init(&sd->connectivity_changed_closure,
       grpc_closure_init(&sd->connectivity_changed_closure,
                         rr_connectivity_changed_locked, sd,
                         rr_connectivity_changed_locked, sd,
                         grpc_combiner_scheduler(args->combiner, false));
                         grpc_combiner_scheduler(args->combiner, false));
+      ++subchannel_index;
     }
     }
   }
   }
-  if (subchannel_idx == 0) {
+  if (subchannel_index == 0) {
     /* couldn't create any subchannel. Bail out */
     /* couldn't create any subchannel. Bail out */
     gpr_free(p->subchannels);
     gpr_free(p->subchannels);
     gpr_free(p);
     gpr_free(p);
     return NULL;
     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_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner);
   grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
   grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,

+ 65 - 64
src/core/ext/filters/client_channel/parse_address.c

@@ -57,11 +57,11 @@ bool grpc_parse_unix(const grpc_uri *uri,
   struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
   struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
   const size_t maxlen = sizeof(un->sun_path);
   const size_t maxlen = sizeof(un->sun_path);
   const size_t path_len = strnlen(uri->path, maxlen);
   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;
   un->sun_family = AF_UNIX;
   strcpy(un->sun_path, uri->path);
   strcpy(un->sun_path, uri->path);
   resolved_addr->len = sizeof(*un);
   resolved_addr->len = sizeof(*un);
-  return 1;
+  return true;
 }
 }
 
 
 #else /* GRPC_HAVE_UNIX_SOCKET */
 #else /* GRPC_HAVE_UNIX_SOCKET */
@@ -73,74 +73,65 @@ bool grpc_parse_unix(const grpc_uri *uri,
 
 
 #endif /* GRPC_HAVE_UNIX_SOCKET */
 #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 *host;
   char *port;
   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;
   in->sin_family = AF_INET;
   if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
   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;
     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;
     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:
 done:
   gpr_free(host);
   gpr_free(host);
   gpr_free(port);
   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) {
                      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;
     return false;
   }
   }
   const char *host_port = uri->path;
   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 (*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;
   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));
   char *host_end = (char *)gpr_memrchr(host, '%', strlen(host));
   if (host_end != NULL) {
   if (host_end != NULL) {
     GPR_ASSERT(host_end >= host);
     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);
       gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1);
       goto done;
       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;
     in6->sin6_scope_id = sin6_scope_id;
   } else {
   } else {
     if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
     if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
@@ -167,24 +158,34 @@ bool grpc_parse_ipv6(const grpc_uri *uri,
       goto done;
       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;
     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:
 done:
   gpr_free(host);
   gpr_free(host);
   gpr_free(port);
   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) {
 bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr) {

+ 6 - 0
src/core/ext/filters/client_channel/parse_address.h

@@ -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. */
 /** Populate \a resolved_addr from \a uri. Returns true upon success. */
 bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
 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 */
 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */

+ 11 - 7
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c

@@ -61,6 +61,8 @@
 typedef struct {
 typedef struct {
   /** base class: must be first */
   /** base class: must be first */
   grpc_resolver base;
   grpc_resolver base;
+  /** DNS server to use (if not system default) */
+  char *dns_server;
   /** name to resolve (usually the same as target_name) */
   /** name to resolve (usually the same as target_name) */
   char *name_to_resolve;
   char *name_to_resolve;
   /** default port to use */
   /** 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_resolved_addresses_destroy(r->addresses);
     grpc_lb_addresses_destroy(exec_ctx, addresses);
     grpc_lb_addresses_destroy(exec_ctx, addresses);
   } else {
   } 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 now = gpr_now(GPR_CLOCK_MONOTONIC);
     gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
     gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
     gpr_timespec timeout = gpr_time_sub(next_try, now);
     gpr_timespec timeout = gpr_time_sub(next_try, now);
@@ -221,9 +225,9 @@ static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx,
   GPR_ASSERT(!r->resolving);
   GPR_ASSERT(!r->resolving);
   r->resolving = true;
   r->resolving = true;
   r->addresses = NULL;
   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,
 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_channel_args_destroy(exec_ctx, r->resolved_result);
   }
   }
   grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
   grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
+  gpr_free(r->dns_server);
   gpr_free(r->name_to_resolve);
   gpr_free(r->name_to_resolve);
   gpr_free(r->default_port);
   gpr_free(r->default_port);
   grpc_channel_args_destroy(exec_ctx, r->channel_args);
   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) {
                                       const char *default_port) {
   // Get name from args.
   // Get name from args.
   const char *path = args->uri->path;
   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;
   if (path[0] == '/') ++path;
   // Create resolver.
   // Create resolver.
   ares_dns_resolver *r = gpr_zalloc(sizeof(ares_dns_resolver));
   ares_dns_resolver *r = gpr_zalloc(sizeof(ares_dns_resolver));
   grpc_resolver_init(&r->base, &dns_ares_resolver_vtable, args->combiner);
   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->name_to_resolve = gpr_strdup(path);
   r->default_port = gpr_strdup(default_port);
   r->default_port = gpr_strdup(default_port);
   r->channel_args = grpc_channel_args_copy(args->args);
   r->channel_args = grpc_channel_args_copy(args->args);

+ 59 - 14
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c

@@ -48,7 +48,10 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.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/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/executor.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/iomgr_internal.h"
 #include "src/core/lib/iomgr/sockaddr_utils.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;
 static gpr_mu g_init_mu;
 
 
 typedef struct grpc_ares_request {
 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 */
   /** following members are set in grpc_resolve_address_ares_impl */
   /** host to resolve, parsed from the name to resolve */
   /** host to resolve, parsed from the name to resolve */
   char *host;
   char *host;
@@ -192,11 +197,12 @@ static void on_done_cb(void *arg, int status, int timeouts,
   grpc_ares_request_unref(NULL, r);
   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 */
   /* TODO(zyc): Enable tracing after #9603 is checked in */
   /* if (grpc_dns_trace) {
   /* if (grpc_dns_trace) {
       gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s",
       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;
   char *port;
   gpr_split_host_port(name, &host, &port);
   gpr_split_host_port(name, &host, &port);
   if (host == NULL) {
   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_CREATE_FROM_STATIC_STRING("unparseable host:port"),
         GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
         GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
-    grpc_closure_sched(exec_ctx, on_done, err);
     goto error_cleanup;
     goto error_cleanup;
   } else if (port == NULL) {
   } else if (port == NULL) {
     if (default_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_CREATE_FROM_STATIC_STRING("no port in name"),
           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
-      grpc_closure_sched(exec_ctx, on_done, err);
       goto error_cleanup;
       goto error_cleanup;
     }
     }
     port = gpr_strdup(default_port);
     port = gpr_strdup(default_port);
   }
   }
 
 
   grpc_ares_ev_driver *ev_driver;
   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));
   grpc_ares_request *r = gpr_malloc(sizeof(grpc_ares_request));
   gpr_mu_init(&r->mu);
   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->success = false;
   r->error = GRPC_ERROR_NONE;
   r->error = GRPC_ERROR_NONE;
   ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
   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);
   gpr_ref_init(&r->pending_queries, 2);
   if (grpc_ipv6_loopback_available()) {
   if (grpc_ipv6_loopback_available()) {
     gpr_ref(&r->pending_queries);
     gpr_ref(&r->pending_queries);
@@ -254,10 +289,20 @@ void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
   return;
   return;
 
 
 error_cleanup:
 error_cleanup:
+  grpc_closure_sched(exec_ctx, on_done, error);
   gpr_free(host);
   gpr_free(host);
   gpr_free(port);
   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)(
 void (*grpc_resolve_address_ares)(
     grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
     grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
     grpc_pollset_set *interested_parties, grpc_closure *on_done,
     grpc_pollset_set *interested_parties, grpc_closure *on_done,

+ 6 - 0
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h

@@ -51,6 +51,12 @@ extern void (*grpc_resolve_address_ares)(grpc_exec_ctx *exec_ctx,
                                          grpc_closure *on_done,
                                          grpc_closure *on_done,
                                          grpc_resolved_addresses **addresses);
                                          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
 /* Initialize gRPC ares wrapper. Must be called at least once before
    grpc_resolve_address_ares(). */
    grpc_resolve_address_ares(). */
 grpc_error *grpc_ares_init(void);
 grpc_error *grpc_ares_init(void);

+ 30 - 11
src/core/ext/transport/chttp2/transport/chttp2_transport.c

@@ -2139,15 +2139,8 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
 
 
 static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
 static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
                        double bdp_dbl) {
                        double bdp_dbl) {
-  int32_t bdp;
-  const int32_t kMinBDP = 128;
-  if (bdp_dbl <= kMinBDP) {
-    bdp = kMinBDP;
-  } else if (bdp_dbl > INT32_MAX) {
-    bdp = INT32_MAX;
-  } else {
-    bdp = (int32_t)(bdp_dbl);
-  }
+  // initial window size bounded [1,2^31-1], but we set the min to 128.
+  int32_t bdp = GPR_CLAMP((int32_t)bdp_dbl, 128, INT32_MAX);
   int64_t delta =
   int64_t delta =
       (int64_t)bdp -
       (int64_t)bdp -
       (int64_t)t->settings[GRPC_LOCAL_SETTINGS]
       (int64_t)t->settings[GRPC_LOCAL_SETTINGS]
@@ -2161,7 +2154,26 @@ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
   }
   }
   push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
   push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
                (uint32_t)bdp);
                (uint32_t)bdp);
-  push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, (uint32_t)bdp);
+}
+
+static void update_frame(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+                         double bw_dbl, double bdp_dbl) {
+  int32_t bdp = GPR_CLAMP((int32_t)bdp_dbl, 128, INT32_MAX);
+  int32_t target = GPR_MAX((int32_t)bw_dbl / 1000, bdp);
+  // frame size is bounded [2^14,2^24-1]
+  int32_t frame_size = GPR_CLAMP(target, 16384, 16777215);
+  int64_t delta = (int64_t)frame_size -
+                  (int64_t)t->settings[GRPC_LOCAL_SETTINGS]
+                                      [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
+  if (delta == 0 || (delta > -frame_size / 10 && delta < frame_size / 10)) {
+    return;
+  }
+  if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
+    gpr_log(GPR_DEBUG, "%s: update max_frame size to %d", t->peer_string,
+            (int)frame_size);
+  }
+  push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
+               (uint32_t)frame_size);
 }
 }
 
 
 static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
 static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
@@ -2280,6 +2292,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
       }
       }
 
 
       int64_t estimate = -1;
       int64_t estimate = -1;
+      double bdp_guess = -1;
       if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
       if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
         double target = 1 + log2((double)estimate);
         double target = 1 + log2((double)estimate);
         double memory_pressure = grpc_resource_quota_get_memory_pressure(
         double memory_pressure = grpc_resource_quota_get_memory_pressure(
@@ -2297,9 +2310,15 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
         }
         }
         double log2_bdp_guess =
         double log2_bdp_guess =
             grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
             grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
-        update_bdp(exec_ctx, t, pow(2, log2_bdp_guess));
+        bdp_guess = pow(2, log2_bdp_guess);
+        update_bdp(exec_ctx, t, bdp_guess);
         t->last_pid_update = now;
         t->last_pid_update = now;
       }
       }
+
+      double bw = -1;
+      if (grpc_bdp_estimator_get_bw(&t->bdp_estimator, &bw)) {
+        update_frame(exec_ctx, t, bw, bdp_guess);
+      }
     }
     }
     GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
     GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
   } else {
   } else {

+ 27 - 5
src/core/lib/iomgr/tcp_server_uv.c

@@ -56,6 +56,8 @@ struct grpc_tcp_listener {
   int port;
   int port;
   /* linked list */
   /* linked list */
   struct grpc_tcp_listener *next;
   struct grpc_tcp_listener *next;
+
+  bool closed;
 };
 };
 
 
 struct grpc_tcp_server {
 struct grpc_tcp_server {
@@ -77,6 +79,8 @@ struct grpc_tcp_server {
   /* shutdown callback */
   /* shutdown callback */
   grpc_closure *shutdown_complete;
   grpc_closure *shutdown_complete;
 
 
+  bool shutdown;
+
   grpc_resource_quota *resource_quota;
   grpc_resource_quota *resource_quota;
 };
 };
 
 
@@ -109,6 +113,7 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
   s->shutdown_starting.head = NULL;
   s->shutdown_starting.head = NULL;
   s->shutdown_starting.tail = NULL;
   s->shutdown_starting.tail = NULL;
   s->shutdown_complete = shutdown_complete;
   s->shutdown_complete = shutdown_complete;
+  s->shutdown = false;
   *server = s;
   *server = s;
   return GRPC_ERROR_NONE;
   return GRPC_ERROR_NONE;
 }
 }
@@ -125,6 +130,7 @@ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
 }
 }
 
 
 static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
 static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+  GPR_ASSERT(s->shutdown);
   if (s->shutdown_complete != NULL) {
   if (s->shutdown_complete != NULL) {
     grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE);
     grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE);
   }
   }
@@ -144,21 +150,31 @@ static void handle_close_callback(uv_handle_t *handle) {
   grpc_tcp_listener *sp = (grpc_tcp_listener *)handle->data;
   grpc_tcp_listener *sp = (grpc_tcp_listener *)handle->data;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   sp->server->open_ports--;
   sp->server->open_ports--;
-  if (sp->server->open_ports == 0) {
+  if (sp->server->open_ports == 0 && sp->server->shutdown) {
     finish_shutdown(&exec_ctx, sp->server);
     finish_shutdown(&exec_ctx, sp->server);
   }
   }
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 }
 
 
+static void close_listener(grpc_tcp_listener *sp) {
+  if (!sp->closed) {
+    sp->closed = true;
+    uv_close((uv_handle_t *)sp->handle, handle_close_callback);
+  }
+}
+
 static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
 static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
   int immediately_done = 0;
   int immediately_done = 0;
   grpc_tcp_listener *sp;
   grpc_tcp_listener *sp;
 
 
+  GPR_ASSERT(!s->shutdown);
+  s->shutdown = true;
+
   if (s->open_ports == 0) {
   if (s->open_ports == 0) {
     immediately_done = 1;
     immediately_done = 1;
   }
   }
   for (sp = s->head; sp; sp = sp->next) {
   for (sp = s->head; sp; sp = sp->next) {
-    uv_close((uv_handle_t *)sp->handle, handle_close_callback);
+    close_listener(sp);
   }
   }
 
 
   if (immediately_done) {
   if (immediately_done) {
@@ -196,9 +212,14 @@ static void on_connect(uv_stream_t *server, int status) {
   int err;
   int err;
 
 
   if (status < 0) {
   if (status < 0) {
-    gpr_log(GPR_INFO, "Skipping on_accept due to error: %s",
-            uv_strerror(status));
-    return;
+    switch (status) {
+      case UV_EINTR:
+      case UV_EAGAIN:
+        return;
+      default:
+        close_listener(sp);
+        return;
+    }
   }
   }
 
 
   client = gpr_malloc(sizeof(uv_tcp_t));
   client = gpr_malloc(sizeof(uv_tcp_t));
@@ -287,6 +308,7 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, uv_tcp_t *handle,
   sp->handle = handle;
   sp->handle = handle;
   sp->port = port;
   sp->port = port;
   sp->port_index = port_index;
   sp->port_index = port_index;
+  sp->closed = false;
   handle->data = sp;
   handle->data = sp;
   s->open_ports++;
   s->open_ports++;
   GPR_ASSERT(sp->handle);
   GPR_ASSERT(sp->handle);

+ 8 - 6
src/core/lib/iomgr/tcp_uv.c

@@ -88,12 +88,12 @@ static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
 #ifdef GRPC_TCP_REFCOUNT_DEBUG
 #ifdef GRPC_TCP_REFCOUNT_DEBUG
 #define TCP_UNREF(exec_ctx, tcp, reason) \
 #define TCP_UNREF(exec_ctx, tcp, reason) \
   tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
   tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
-#define TCP_REF(tcp, reason) \
-  tcp_ref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
+#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
 static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
 static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
                       const char *reason, const char *file, int line) {
                       const char *reason, const char *file, int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
-          reason, tcp->refcount.count, tcp->refcount.count - 1);
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "TCP unref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason,
+          tcp->refcount.count, tcp->refcount.count - 1);
   if (gpr_unref(&tcp->refcount)) {
   if (gpr_unref(&tcp->refcount)) {
     tcp_free(exec_ctx, tcp);
     tcp_free(exec_ctx, tcp);
   }
   }
@@ -101,8 +101,9 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
 
 
 static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
 static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
                     int line) {
                     int line) {
-  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP   ref %p : %s %d -> %d", tcp,
-          reason, tcp->refcount.count, tcp->refcount.count + 1);
+  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+          "TCP   ref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason,
+          tcp->refcount.count, tcp->refcount.count + 1);
   gpr_ref(&tcp->refcount);
   gpr_ref(&tcp->refcount);
 }
 }
 #else
 #else
@@ -311,6 +312,7 @@ static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
     tcp->shutting_down = true;
     tcp->shutting_down = true;
     uv_shutdown_t *req = &tcp->shutdown_req;
     uv_shutdown_t *req = &tcp->shutdown_req;
     uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
     uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
+    grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
   }
   }
   GRPC_ERROR_UNREF(why);
   GRPC_ERROR_UNREF(why);
 }
 }

+ 3 - 3
src/core/lib/support/cmdline.c

@@ -71,7 +71,7 @@ struct gpr_cmdline {
 static int normal_state(gpr_cmdline *cl, char *arg);
 static int normal_state(gpr_cmdline *cl, char *arg);
 
 
 gpr_cmdline *gpr_cmdline_create(const char *description) {
 gpr_cmdline *gpr_cmdline_create(const char *description) {
-  gpr_cmdline *cl = gpr_zalloc(sizeof(gpr_cmdline));
+  gpr_cmdline *cl = (gpr_cmdline *)gpr_zalloc(sizeof(gpr_cmdline));
 
 
   cl->description = description;
   cl->description = description;
   cl->state = normal_state;
   cl->state = normal_state;
@@ -100,7 +100,7 @@ static void add_arg(gpr_cmdline *cl, const char *name, const char *help,
     GPR_ASSERT(0 != strcmp(a->name, name));
     GPR_ASSERT(0 != strcmp(a->name, name));
   }
   }
 
 
-  a = gpr_zalloc(sizeof(arg));
+  a = (arg *)gpr_zalloc(sizeof(arg));
   a->name = name;
   a->name = name;
   a->help = help;
   a->help = help;
   a->type = type;
   a->type = type;
@@ -302,7 +302,7 @@ static int normal_state(gpr_cmdline *cl, char *str) {
     eq = strchr(str, '=');
     eq = strchr(str, '=');
     if (eq != NULL) {
     if (eq != NULL) {
       /* copy the string into a temp buffer and extract the name */
       /* copy the string into a temp buffer and extract the name */
-      tmp = arg_name = gpr_malloc((size_t)(eq - str + 1));
+      tmp = arg_name = (char *)gpr_malloc((size_t)(eq - str + 1));
       memcpy(arg_name, str, (size_t)(eq - str));
       memcpy(arg_name, str, (size_t)(eq - str));
       arg_name[eq - str] = 0;
       arg_name[eq - str] = 0;
     } else {
     } else {

+ 2 - 2
src/core/lib/support/histogram.c

@@ -88,7 +88,7 @@ static double bucket_start(gpr_histogram *h, double x) {
 
 
 gpr_histogram *gpr_histogram_create(double resolution,
 gpr_histogram *gpr_histogram_create(double resolution,
                                     double max_bucket_start) {
                                     double max_bucket_start) {
-  gpr_histogram *h = gpr_malloc(sizeof(gpr_histogram));
+  gpr_histogram *h = (gpr_histogram *)gpr_malloc(sizeof(gpr_histogram));
   GPR_ASSERT(resolution > 0.0);
   GPR_ASSERT(resolution > 0.0);
   GPR_ASSERT(max_bucket_start > resolution);
   GPR_ASSERT(max_bucket_start > resolution);
   h->sum = 0.0;
   h->sum = 0.0;
@@ -102,7 +102,7 @@ gpr_histogram *gpr_histogram_create(double resolution,
   h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
   h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
   GPR_ASSERT(h->num_buckets > 1);
   GPR_ASSERT(h->num_buckets > 1);
   GPR_ASSERT(h->num_buckets < 100000000);
   GPR_ASSERT(h->num_buckets < 100000000);
-  h->buckets = gpr_zalloc(sizeof(uint32_t) * h->num_buckets);
+  h->buckets = (uint32_t *)gpr_zalloc(sizeof(uint32_t) * h->num_buckets);
   return h;
   return h;
 }
 }
 
 

+ 1 - 1
src/core/lib/support/host_port.c

@@ -98,7 +98,7 @@ int gpr_split_host_port(const char *name, char **host, char **port) {
   }
   }
 
 
   /* Allocate return values. */
   /* Allocate return values. */
-  *host = gpr_malloc(host_len + 1);
+  *host = (char *)gpr_malloc(host_len + 1);
   memcpy(*host, host_start, host_len);
   memcpy(*host, host_start, host_len);
   (*host)[host_len] = '\0';
   (*host)[host_len] = '\0';
 
 

+ 12 - 12
src/core/lib/support/string.c

@@ -53,7 +53,7 @@ char *gpr_strdup(const char *src) {
   }
   }
 
 
   len = strlen(src) + 1;
   len = strlen(src) + 1;
-  dst = gpr_malloc(len);
+  dst = (char *)gpr_malloc(len);
 
 
   memcpy(dst, src, len);
   memcpy(dst, src, len);
 
 
@@ -74,13 +74,13 @@ static dump_out dump_out_create(void) {
 static void dump_out_append(dump_out *out, char c) {
 static void dump_out_append(dump_out *out, char c) {
   if (out->length == out->capacity) {
   if (out->length == out->capacity) {
     out->capacity = GPR_MAX(8, 2 * out->capacity);
     out->capacity = GPR_MAX(8, 2 * out->capacity);
-    out->data = gpr_realloc(out->data, out->capacity);
+    out->data = (char *)gpr_realloc(out->data, out->capacity);
   }
   }
   out->data[out->length++] = c;
   out->data[out->length++] = c;
 }
 }
 
 
 static void hexdump(dump_out *out, const char *buf, size_t len) {
 static void hexdump(dump_out *out, const char *buf, size_t len) {
-  static const char hex[16] = "0123456789abcdef";
+  static const char *hex = "0123456789abcdef";
 
 
   const uint8_t *const beg = (const uint8_t *)buf;
   const uint8_t *const beg = (const uint8_t *)buf;
   const uint8_t *const end = beg + len;
   const uint8_t *const end = beg + len;
@@ -124,16 +124,16 @@ char *gpr_dump(const char *buf, size_t len, uint32_t flags) {
 
 
 int gpr_parse_bytes_to_uint32(const char *buf, size_t len, uint32_t *result) {
 int gpr_parse_bytes_to_uint32(const char *buf, size_t len, uint32_t *result) {
   uint32_t out = 0;
   uint32_t out = 0;
-  uint32_t new;
+  uint32_t new_val;
   size_t i;
   size_t i;
 
 
   if (len == 0) return 0; /* must have some bytes */
   if (len == 0) return 0; /* must have some bytes */
 
 
   for (i = 0; i < len; i++) {
   for (i = 0; i < len; i++) {
     if (buf[i] < '0' || buf[i] > '9') return 0; /* bad char */
     if (buf[i] < '0' || buf[i] > '9') return 0; /* bad char */
-    new = 10 * out + (uint32_t)(buf[i] - '0');
-    if (new < out) return 0; /* overflow */
-    out = new;
+    new_val = 10 * out + (uint32_t)(buf[i] - '0');
+    if (new_val < out) return 0; /* overflow */
+    out = new_val;
   }
   }
 
 
   *result = out;
   *result = out;
@@ -201,7 +201,7 @@ int gpr_parse_nonnegative_int(const char *value) {
 char *gpr_leftpad(const char *str, char flag, size_t length) {
 char *gpr_leftpad(const char *str, char flag, size_t length) {
   const size_t str_length = strlen(str);
   const size_t str_length = strlen(str);
   const size_t out_length = str_length > length ? str_length : length;
   const size_t out_length = str_length > length ? str_length : length;
-  char *out = gpr_malloc(out_length + 1);
+  char *out = (char *)gpr_malloc(out_length + 1);
   memset(out, flag, out_length - str_length);
   memset(out, flag, out_length - str_length);
   memcpy(out + out_length - str_length, str, str_length);
   memcpy(out + out_length - str_length, str, str_length);
   out[out_length] = 0;
   out[out_length] = 0;
@@ -225,7 +225,7 @@ char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep,
   if (nstrs > 0) {
   if (nstrs > 0) {
     out_length += sep_len * (nstrs - 1); /* separators */
     out_length += sep_len * (nstrs - 1); /* separators */
   }
   }
-  out = gpr_malloc(out_length);
+  out = (char *)gpr_malloc(out_length);
   out_length = 0;
   out_length = 0;
   for (i = 0; i < nstrs; i++) {
   for (i = 0; i < nstrs; i++) {
     const size_t slen = strlen(strs[i]);
     const size_t slen = strlen(strs[i]);
@@ -256,7 +256,7 @@ void gpr_strvec_destroy(gpr_strvec *sv) {
 void gpr_strvec_add(gpr_strvec *sv, char *str) {
 void gpr_strvec_add(gpr_strvec *sv, char *str) {
   if (sv->count == sv->capacity) {
   if (sv->count == sv->capacity) {
     sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
     sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
-    sv->strs = gpr_realloc(sv->strs, sizeof(char *) * sv->capacity);
+    sv->strs = (char **)gpr_realloc(sv->strs, sizeof(char *) * sv->capacity);
   }
   }
   sv->strs[sv->count++] = str;
   sv->strs[sv->count++] = str;
 }
 }
@@ -278,12 +278,12 @@ int gpr_stricmp(const char *a, const char *b) {
 
 
 static void add_string_to_split(const char *beg, const char *end, char ***strs,
 static void add_string_to_split(const char *beg, const char *end, char ***strs,
                                 size_t *nstrs, size_t *capstrs) {
                                 size_t *nstrs, size_t *capstrs) {
-  char *out = gpr_malloc((size_t)(end - beg) + 1);
+  char *out = (char *)gpr_malloc((size_t)(end - beg) + 1);
   memcpy(out, beg, (size_t)(end - beg));
   memcpy(out, beg, (size_t)(end - beg));
   out[end - beg] = 0;
   out[end - beg] = 0;
   if (*nstrs == *capstrs) {
   if (*nstrs == *capstrs) {
     *capstrs = GPR_MAX(8, 2 * *capstrs);
     *capstrs = GPR_MAX(8, 2 * *capstrs);
-    *strs = gpr_realloc(*strs, sizeof(*strs) * *capstrs);
+    *strs = (char **)gpr_realloc(*strs, sizeof(*strs) * *capstrs);
   }
   }
   (*strs)[*nstrs] = out;
   (*strs)[*nstrs] = out;
   ++*nstrs;
   ++*nstrs;

+ 1 - 1
src/core/lib/support/string_posix.c

@@ -58,7 +58,7 @@ int gpr_asprintf(char **strp, const char *format, ...) {
 
 
   /* Allocate a new buffer, with space for the NUL terminator. */
   /* Allocate a new buffer, with space for the NUL terminator. */
   strp_buflen = (size_t)ret + 1;
   strp_buflen = (size_t)ret + 1;
-  if ((*strp = gpr_malloc(strp_buflen)) == NULL) {
+  if ((*strp = (char *)gpr_malloc(strp_buflen)) == NULL) {
     /* This shouldn't happen, because gpr_malloc() calls abort(). */
     /* This shouldn't happen, because gpr_malloc() calls abort(). */
     return -1;
     return -1;
   }
   }

+ 2 - 2
src/core/lib/support/subprocess_posix.c

@@ -67,7 +67,7 @@ gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
   if (pid == -1) {
   if (pid == -1) {
     return NULL;
     return NULL;
   } else if (pid == 0) {
   } else if (pid == 0) {
-    exec_args = gpr_malloc(((size_t)argc + 1) * sizeof(char *));
+    exec_args = (char **)gpr_malloc(((size_t)argc + 1) * sizeof(char *));
     memcpy(exec_args, argv, (size_t)argc * sizeof(char *));
     memcpy(exec_args, argv, (size_t)argc * sizeof(char *));
     exec_args[argc] = NULL;
     exec_args[argc] = NULL;
     execv(exec_args[0], exec_args);
     execv(exec_args[0], exec_args);
@@ -76,7 +76,7 @@ gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
     _exit(1);
     _exit(1);
     return NULL;
     return NULL;
   } else {
   } else {
-    r = gpr_zalloc(sizeof(gpr_subprocess));
+    r = (gpr_subprocess *)gpr_zalloc(sizeof(gpr_subprocess));
     r->pid = pid;
     r->pid = pid;
     return r;
     return r;
   }
   }

+ 1 - 1
src/core/lib/support/thd_posix.c

@@ -65,7 +65,7 @@ int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
   pthread_t p;
   pthread_t p;
   /* don't use gpr_malloc as we may cause an infinite recursion with
   /* don't use gpr_malloc as we may cause an infinite recursion with
    * the profiling code */
    * the profiling code */
-  struct thd_arg *a = malloc(sizeof(*a));
+  struct thd_arg *a = (struct thd_arg *)malloc(sizeof(*a));
   GPR_ASSERT(a != NULL);
   GPR_ASSERT(a != NULL);
   a->body = thd_body;
   a->body = thd_body;
   a->arg = arg;
   a->arg = arg;

+ 5 - 0
src/core/lib/transport/bdp_estimator.c

@@ -53,6 +53,11 @@ bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
   return true;
   return true;
 }
 }
 
 
+bool grpc_bdp_estimator_get_bw(grpc_bdp_estimator *estimator, double *bw) {
+  *bw = estimator->bw_est;
+  return true;
+}
+
 bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
 bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
                                            int64_t num_bytes) {
                                            int64_t num_bytes) {
   estimator->accumulator += num_bytes;
   estimator->accumulator += num_bytes;

+ 2 - 0
src/core/lib/transport/bdp_estimator.h

@@ -64,6 +64,8 @@ void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name);
 // Returns true if a reasonable estimate could be obtained
 // Returns true if a reasonable estimate could be obtained
 bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
 bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
                                      int64_t *estimate);
                                      int64_t *estimate);
+// Returns true if a reasonable estimate could be obtained
+bool grpc_bdp_estimator_get_bw(grpc_bdp_estimator *estimator, double *bw);
 // Returns true if the user should schedule a ping
 // Returns true if the user should schedule a ping
 bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
 bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
                                            int64_t num_bytes);
                                            int64_t num_bytes);

+ 4 - 0
src/cpp/server/server_builder.cc

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

+ 4 - 1
src/csharp/Grpc.Core/Internal/CallError.cs

@@ -72,7 +72,10 @@ namespace Grpc.Core.Internal
         /// </summary>
         /// </summary>
         public static void CheckOk(this CallError callError)
         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);
+            }
         }
         }
     }
     }
 }
 }

+ 2 - 2
src/csharp/Grpc.Core/Internal/CallSafeHandle.cs

@@ -117,7 +117,7 @@ namespace Grpc.Core.Internal
             {
             {
                 var ctx = BatchContextSafeHandle.Create();
                 var ctx = BatchContextSafeHandle.Create();
                 completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
-                Native.grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata).CheckOk();
+                Native.grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata ? 1 : 0).CheckOk();
             }
             }
         }
         }
 
 
@@ -140,7 +140,7 @@ namespace Grpc.Core.Internal
                 var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero;
                 var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero;
                 completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 var statusDetailBytes = MarshalUtils.GetBytesUTF8(status.Detail);
                 var statusDetailBytes = MarshalUtils.GetBytesUTF8(status.Detail);
-                Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata,
+                Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata ? 1 : 0,
                     optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
                     optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
             }
             }
         }
         }

+ 3 - 3
src/csharp/Grpc.Core/Internal/NativeMethods.cs

@@ -346,11 +346,11 @@ namespace Grpc.Core.Internal
             public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call,
             public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
             public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call,
             public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call,
-                BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata);
+                BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, int sendEmptyInitialMetadata);
             public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
             public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
                 BatchContextSafeHandle ctx);
             public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call,
             public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call,
-                BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
+                BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata,
                 byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
                 byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
             public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
             public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
                 BatchContextSafeHandle ctx);
@@ -406,7 +406,7 @@ namespace Grpc.Core.Internal
             public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(NativeMetadataInterceptor interceptor);
             public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(NativeMetadataInterceptor interceptor);
             public delegate void grpcsharp_metadata_credentials_notify_from_plugin_delegate(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
             public delegate void grpcsharp_metadata_credentials_notify_from_plugin_delegate(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
 
 
-            public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth);
+            public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, int forceClientAuth);
             public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials);
             public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials);
 
 
             public delegate ServerSafeHandle grpcsharp_server_create_delegate(ChannelArgsSafeHandle args);
             public delegate ServerSafeHandle grpcsharp_server_create_delegate(ChannelArgsSafeHandle args);

+ 1 - 1
src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs

@@ -53,7 +53,7 @@ namespace Grpc.Core.Internal
             return Native.grpcsharp_ssl_server_credentials_create(pemRootCerts,
             return Native.grpcsharp_ssl_server_credentials_create(pemRootCerts,
                                                                   keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
                                                                   keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
                                                                   new UIntPtr((ulong)keyCertPairCertChainArray.Length),
                                                                   new UIntPtr((ulong)keyCertPairCertChainArray.Length),
-                                                                  forceClientAuth);
+                                                                  forceClientAuth ? 1 : 0);
         }
         }
 
 
         protected override bool ReleaseHandle()
         protected override bool ReleaseHandle()

+ 15 - 13
src/csharp/Grpc.IntegrationTesting/ClientRunners.cs

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

+ 42 - 15
src/csharp/Grpc.IntegrationTesting/Histogram.cs

@@ -84,15 +84,27 @@ namespace Grpc.IntegrationTesting
             }
             }
         }
         }
 
 
-
         /// <summary>
         /// <summary>
-        /// Gets snapshot of stats and reset 
+        /// Gets snapshot of stats and optionally resets the histogram.
         /// </summary>
         /// </summary>
         public HistogramData GetSnapshot(bool reset = false)
         public HistogramData GetSnapshot(bool reset = false)
         {
         {
             lock (myLock)
             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)]++;
             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()
         private void ResetUnsafe()

+ 25 - 1
src/csharp/Grpc.IntegrationTesting/HistogramTest.cs

@@ -73,13 +73,37 @@ namespace Grpc.IntegrationTesting
         {
         {
             var hist = new Histogram(0.01, 60e9);
             var hist = new Histogram(0.01, 60e9);
             hist.AddObservation(-0.5);  // should be in the first bucket
             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();
             var data = hist.GetSnapshot();
             Assert.AreEqual(1, data.Bucket[0]);
             Assert.AreEqual(1, data.Bucket[0]);
             Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]);
             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]
         [Test]
         public void Reset()
         public void Reset()
         {
         {

+ 5 - 5
src/csharp/build_packages_dotnetcli.bat

@@ -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
 @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\
 xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\
 
 
-%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
+%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
 
 
 %NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
 %NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
 %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts
 %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts

+ 5 - 5
src/csharp/build_packages_dotnetcli.sh

@@ -48,11 +48,11 @@ dotnet restore Grpc.sln
 mkdir -p ../../libs/opt
 mkdir -p ../../libs/opt
 cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
 cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
 
 
-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
+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.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
 nuget pack Grpc.Tools.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
 nuget pack Grpc.Tools.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts

+ 24 - 31
src/node/index.js

@@ -70,8 +70,6 @@ grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii'));
  *   Buffers. Defaults to false
  *   Buffers. Defaults to false
  * - longsAsStrings: deserialize long values as strings instead of objects.
  * - longsAsStrings: deserialize long values as strings instead of objects.
  *   Defaults to true
  *   Defaults to true
- * - enumsAsStrings: deserialize enum values as strings instead of numbers.
- *   Defaults to true
  * - deprecatedArgumentOrder: Use the beta method argument order for client
  * - deprecatedArgumentOrder: Use the beta method argument order for client
  *   methods, with optional arguments after the callback. Defaults to false.
  *   methods, with optional arguments after the callback. Defaults to false.
  *   This option is only a temporary stopgap measure to smooth an API breakage.
  *   This option is only a temporary stopgap measure to smooth an API breakage.
@@ -105,10 +103,6 @@ exports.loadObject = function loadObject(value, options) {
   switch (protobufjsVersion) {
   switch (protobufjsVersion) {
     case 6: return protobuf_js_6_common.loadObject(value, options);
     case 6: return protobuf_js_6_common.loadObject(value, options);
     case 5:
     case 5:
-    var deprecation_message = 'Calling grpc.loadObject with an object ' +
-        'generated by ProtoBuf.js 5 is deprecated. Please upgrade to ' +
-        'ProtoBuf.js 6.';
-    common.log(grpc.logVerbosity.INFO, deprecation_message);
     return protobuf_js_5_common.loadObject(value, options);
     return protobuf_js_5_common.loadObject(value, options);
     default:
     default:
     throw new Error('Unrecognized protobufjsVersion', protobufjsVersion);
     throw new Error('Unrecognized protobufjsVersion', protobufjsVersion);
@@ -117,19 +111,6 @@ exports.loadObject = function loadObject(value, options) {
 
 
 var loadObject = exports.loadObject;
 var loadObject = exports.loadObject;
 
 
-function applyProtoRoot(filename, root) {
-  if (_.isString(filename)) {
-    return filename;
-  }
-  filename.root = path.resolve(filename.root) + '/';
-  root.resolvePath = function(originPath, importPath, alreadyNormalized) {
-    return ProtoBuf.util.path.resolve(filename.root,
-                                      importPath,
-                                      alreadyNormalized);
-  };
-  return filename.file;
-}
-
 /**
 /**
  * Load a gRPC object from a .proto file. The options object can provide the
  * Load a gRPC object from a .proto file. The options object can provide the
  * following options:
  * following options:
@@ -139,8 +120,6 @@ function applyProtoRoot(filename, root) {
  *   Buffers. Defaults to false
  *   Buffers. Defaults to false
  * - longsAsStrings: deserialize long values as strings instead of objects.
  * - longsAsStrings: deserialize long values as strings instead of objects.
  *   Defaults to true
  *   Defaults to true
- * - enumsAsStrings: deserialize enum values as strings instead of numbers.
- *   Defaults to true
  * - deprecatedArgumentOrder: Use the beta method argument order for client
  * - deprecatedArgumentOrder: Use the beta method argument order for client
  *   methods, with optional arguments after the callback. Defaults to false.
  *   methods, with optional arguments after the callback. Defaults to false.
  *   This option is only a temporary stopgap measure to smooth an API breakage.
  *   This option is only a temporary stopgap measure to smooth an API breakage.
@@ -152,17 +131,31 @@ function applyProtoRoot(filename, root) {
  * @return {Object<string, *>} The resulting gRPC object
  * @return {Object<string, *>} The resulting gRPC object
  */
  */
 exports.load = function load(filename, format, options) {
 exports.load = function load(filename, format, options) {
-  /* Note: format is currently unused, because the API for loading a proto
-     file or a JSON file is identical in Protobuf.js 6. In the future, there is
-     still the possibility of adding other formats that would be loaded
-     differently */
   options = _.defaults(options, common.defaultGrpcOptions);
   options = _.defaults(options, common.defaultGrpcOptions);
-  options.protobufjs_version = 6;
-  var root = new ProtoBuf.Root();
-  var parse_options = {keepCase: !options.convertFieldsToCamelCase};
-  return loadObject(root.loadSync(applyProtoRoot(filename, root),
-                                  parse_options),
-                    options);
+  options.protobufjsVersion = 5;
+  if (!format) {
+    format = 'proto';
+  }
+  var convertFieldsToCamelCaseOriginal = ProtoBuf.convertFieldsToCamelCase;
+  if(options && options.hasOwnProperty('convertFieldsToCamelCase')) {
+    ProtoBuf.convertFieldsToCamelCase = options.convertFieldsToCamelCase;
+  }
+  var builder;
+  try {
+    switch(format) {
+      case 'proto':
+      builder = ProtoBuf.loadProtoFile(filename);
+      break;
+      case 'json':
+      builder = ProtoBuf.loadJsonFile(filename);
+      break;
+      default:
+      throw new Error('Unrecognized format "' + format + '"');
+    }
+  } finally {
+    ProtoBuf.convertFieldsToCamelCase = convertFieldsToCamelCaseOriginal;
+  }
+  return loadObject(builder.ns, options);
 };
 };
 
 
 var log_template = _.template(
 var log_template = _.template(

+ 5 - 5
src/node/src/protobuf_js_5_common.js

@@ -45,8 +45,7 @@ var client = require('./client');
  *     objects. Defaults to true
  *     objects. Defaults to true
  * @return {function(Buffer):cls} The deserialization function
  * @return {function(Buffer):cls} The deserialization function
  */
  */
-exports.deserializeCls = function deserializeCls(cls, binaryAsBase64,
-                                                 longsAsStrings) {
+exports.deserializeCls = function deserializeCls(cls, options) {
   /**
   /**
    * Deserialize a buffer to a message object
    * Deserialize a buffer to a message object
    * @param {Buffer} arg_buf The buffer to deserialize
    * @param {Buffer} arg_buf The buffer to deserialize
@@ -55,7 +54,8 @@ exports.deserializeCls = function deserializeCls(cls, binaryAsBase64,
   return function deserialize(arg_buf) {
   return function deserialize(arg_buf) {
     // Convert to a native object with binary fields as Buffers (first argument)
     // Convert to a native object with binary fields as Buffers (first argument)
     // and longs as strings (second argument)
     // and longs as strings (second argument)
-    return cls.decode(arg_buf).toRaw(binaryAsBase64, longsAsStrings);
+    return cls.decode(arg_buf).toRaw(options.binaryAsBase64,
+                                     options.longsAsStrings);
   };
   };
 };
 };
 
 
@@ -128,10 +128,10 @@ exports.getProtobufServiceAttrs = function getProtobufServiceAttrs(service,
       responseType: method.resolvedResponseType,
       responseType: method.resolvedResponseType,
       requestSerialize: serializeCls(method.resolvedRequestType.build()),
       requestSerialize: serializeCls(method.resolvedRequestType.build()),
       requestDeserialize: deserializeCls(method.resolvedRequestType.build(),
       requestDeserialize: deserializeCls(method.resolvedRequestType.build(),
-                                         binaryAsBase64, longsAsStrings),
+                                         options),
       responseSerialize: serializeCls(method.resolvedResponseType.build()),
       responseSerialize: serializeCls(method.resolvedResponseType.build()),
       responseDeserialize: deserializeCls(method.resolvedResponseType.build(),
       responseDeserialize: deserializeCls(method.resolvedResponseType.build(),
-                                          binaryAsBase64, longsAsStrings)
+                                          options)
     };
     };
   }));
   }));
 };
 };

+ 6 - 2
src/node/src/server.js

@@ -781,6 +781,11 @@ Server.prototype.addService = function(service, implementation) {
   });
   });
 };
 };
 
 
+var logAddProtoServiceDeprecationOnce = _.once(function() {
+    common.log(constants.logVerbosity.INFO,
+               'Server#addProtoService is deprecated. Use addService instead');
+});
+
 /**
 /**
  * Add a proto service to the server, with a corresponding implementation
  * Add a proto service to the server, with a corresponding implementation
  * @deprecated Use grpc.load and Server#addService instead
  * @deprecated Use grpc.load and Server#addService instead
@@ -792,8 +797,7 @@ Server.prototype.addProtoService = function(service, implementation) {
   var options;
   var options;
   var protobuf_js_5_common = require('./protobuf_js_5_common');
   var protobuf_js_5_common = require('./protobuf_js_5_common');
   var protobuf_js_6_common = require('./protobuf_js_6_common');
   var protobuf_js_6_common = require('./protobuf_js_6_common');
-  common.log(constants.logVerbosity.INFO,
-             'Server#addProtoService is deprecated. Use addService instead');
+  logAddProtoServiceDeprecationOnce();
   if (protobuf_js_5_common.isProbablyProtobufJs5(service)) {
   if (protobuf_js_5_common.isProbablyProtobufJs5(service)) {
     options = _.defaults(service.grpc_options, common.defaultGrpcOptions);
     options = _.defaults(service.grpc_options, common.defaultGrpcOptions);
     this.addService(
     this.addService(

+ 12 - 9
src/node/test/common_test.js

@@ -37,16 +37,15 @@ var assert = require('assert');
 var _ = require('lodash');
 var _ = require('lodash');
 
 
 var common = require('../src/common');
 var common = require('../src/common');
-var protobuf_js_6_common = require('../src/protobuf_js_6_common');
+var protobuf_js_5_common = require('../src/protobuf_js_5_common');
 
 
-var serializeCls = protobuf_js_6_common.serializeCls;
-var deserializeCls = protobuf_js_6_common.deserializeCls;
+var serializeCls = protobuf_js_5_common.serializeCls;
+var deserializeCls = protobuf_js_5_common.deserializeCls;
 
 
 var ProtoBuf = require('protobufjs');
 var ProtoBuf = require('protobufjs');
 
 
-var messages_proto = new ProtoBuf.Root();
-messages_proto = messages_proto.loadSync(
-    __dirname + '/test_messages.proto', {keepCase: true}).resolveAll();
+var messages_proto = ProtoBuf.loadProtoFile(
+    __dirname + '/test_messages.proto').build();
 
 
 var default_options = common.defaultGrpcOptions;
 var default_options = common.defaultGrpcOptions;
 
 
@@ -101,6 +100,7 @@ describe('Proto message long int serialize and deserialize', function() {
     var longNumDeserialize = deserializeCls(messages_proto.LongValues,
     var longNumDeserialize = deserializeCls(messages_proto.LongValues,
                                             num_options);
                                             num_options);
     var serialized = longSerialize({int_64: pos_value});
     var serialized = longSerialize({int_64: pos_value});
+    console.log(longDeserialize(serialized));
     assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string');
     assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string');
     /* With the longsAsStrings option disabled, long values are represented as
     /* With the longsAsStrings option disabled, long values are represented as
      * objects with 3 keys: low, high, and unsigned */
      * objects with 3 keys: low, high, and unsigned */
@@ -136,7 +136,8 @@ describe('Proto message bytes serialize and deserialize', function() {
     var serialized = sequenceSerialize({repeated_field: [10]});
     var serialized = sequenceSerialize({repeated_field: [10]});
     assert.strictEqual(expected_serialize.compare(serialized), 0);
     assert.strictEqual(expected_serialize.compare(serialized), 0);
   });
   });
-  it('should deserialize packed or unpacked repeated', function() {
+  // This tests a bug that was fixed in Protobuf.js 6
+  it.skip('should deserialize packed or unpacked repeated', function() {
     var expectedDeserialize = {
     var expectedDeserialize = {
       bytes_field: new Buffer(''),
       bytes_field: new Buffer(''),
       repeated_field: [10]
       repeated_field: [10]
@@ -155,7 +156,8 @@ describe('Proto message bytes serialize and deserialize', function() {
     assert.deepEqual(unpackedDeserialized, expectedDeserialize);
     assert.deepEqual(unpackedDeserialized, expectedDeserialize);
   });
   });
 });
 });
-describe('Proto message oneof serialize and deserialize', function() {
+// This tests a bug that was fixed in Protobuf.js 6
+describe.skip('Proto message oneof serialize and deserialize', function() {
   var oneofSerialize = serializeCls(messages_proto.OneOfValues);
   var oneofSerialize = serializeCls(messages_proto.OneOfValues);
   var oneofDeserialize = deserializeCls(
   var oneofDeserialize = deserializeCls(
       messages_proto.OneOfValues, default_options);
       messages_proto.OneOfValues, default_options);
@@ -193,7 +195,8 @@ describe('Proto message enum serialize and deserialize', function() {
     assert.deepEqual(enumDeserialize(nameSerialized),
     assert.deepEqual(enumDeserialize(nameSerialized),
                      enumDeserialize(numberSerialized));
                      enumDeserialize(numberSerialized));
   });
   });
-  it('Should deserialize as a string the enumsAsStrings option', function() {
+  // This tests a bug that was fixed in Protobuf.js 6
+  it.skip('Should correctly handle the enumsAsStrings option', function() {
     var serialized = enumSerialize({enum_value: 'TWO'});
     var serialized = enumSerialize({enum_value: 'TWO'});
     var nameDeserialized = enumDeserialize(serialized);
     var nameDeserialized = enumDeserialize(serialized);
     var numberDeserialized = enumIntDeserialize(serialized);
     var numberDeserialized = enumIntDeserialize(serialized);

+ 17 - 25
src/node/test/surface_test.js

@@ -43,9 +43,8 @@ var ProtoBuf = require('protobufjs');
 
 
 var grpc = require('..');
 var grpc = require('..');
 
 
-var math_proto = new ProtoBuf.Root();
-math_proto = math_proto.loadSync(__dirname +
-    '/../../proto/math/math.proto', {keepCase: true});
+var math_proto = ProtoBuf.loadProtoFile(__dirname +
+    '/../../proto/math/math.proto');
 
 
 var mathService = math_proto.lookup('math.Math');
 var mathService = math_proto.lookup('math.Math');
 var mathServiceAttrs = grpc.loadObject(
 var mathServiceAttrs = grpc.loadObject(
@@ -332,9 +331,7 @@ describe('Echo service', function() {
   var server;
   var server;
   var client;
   var client;
   before(function() {
   before(function() {
-    var test_proto = new ProtoBuf.Root();
-    test_proto = test_proto.loadSync(__dirname + '/echo_service.proto',
-                                         {keepCase: true});
+    var test_proto = ProtoBuf.loadProtoFile(__dirname + '/echo_service.proto');
     var echo_service = test_proto.lookup('EchoService');
     var echo_service = test_proto.lookup('EchoService');
     var Client = grpc.loadObject(echo_service);
     var Client = grpc.loadObject(echo_service);
     server = new grpc.Server();
     server = new grpc.Server();
@@ -357,6 +354,13 @@ describe('Echo service', function() {
       done();
       done();
     });
     });
   });
   });
+  it('Should convert an undefined argument to default values', function(done) {
+    client.echo(undefined, function(error, response) {
+      assert.ifError(error);
+      assert.deepEqual(response, {value: '', value2: 0});
+      done();
+    });
+  });
 });
 });
 describe('Generic client and server', function() {
 describe('Generic client and server', function() {
   function toString(val) {
   function toString(val) {
@@ -457,9 +461,7 @@ describe('Echo metadata', function() {
   var server;
   var server;
   var metadata;
   var metadata;
   before(function() {
   before(function() {
-    var test_proto = new ProtoBuf.Root();
-    test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
-                                         {keepCase: true});
+    var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
     var test_service = test_proto.lookup('TestService');
     var test_service = test_proto.lookup('TestService');
     var Client = grpc.loadObject(test_service);
     var Client = grpc.loadObject(test_service);
     server = new grpc.Server();
     server = new grpc.Server();
@@ -560,9 +562,7 @@ describe('Client malformed response handling', function() {
   var client;
   var client;
   var badArg = new Buffer([0xFF]);
   var badArg = new Buffer([0xFF]);
   before(function() {
   before(function() {
-    var test_proto = new ProtoBuf.Root();
-    test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
-                                         {keepCase: true});
+    var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
     var test_service = test_proto.lookup('TestService');
     var test_service = test_proto.lookup('TestService');
     var malformed_test_service = {
     var malformed_test_service = {
       unary: {
       unary: {
@@ -669,9 +669,7 @@ describe('Server serialization failure handling', function() {
   var client;
   var client;
   var server;
   var server;
   before(function() {
   before(function() {
-    var test_proto = new ProtoBuf.Root();
-    test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
-                                         {keepCase: true});
+    var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
     var test_service = test_proto.lookup('TestService');
     var test_service = test_proto.lookup('TestService');
     var malformed_test_service = {
     var malformed_test_service = {
       unary: {
       unary: {
@@ -772,16 +770,13 @@ describe('Server serialization failure handling', function() {
   });
   });
 });
 });
 describe('Other conditions', function() {
 describe('Other conditions', function() {
-  var test_service;
   var Client;
   var Client;
   var client;
   var client;
   var server;
   var server;
   var port;
   var port;
   before(function() {
   before(function() {
-    var test_proto = new ProtoBuf.Root();
-    test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
-                                         {keepCase: true});
-    test_service = test_proto.lookup('TestService');
+    var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
+    var test_service = test_proto.lookup('TestService');
     Client = grpc.loadObject(test_service);
     Client = grpc.loadObject(test_service);
     server = new grpc.Server();
     server = new grpc.Server();
     var trailer_metadata = new grpc.Metadata();
     var trailer_metadata = new grpc.Metadata();
@@ -1121,15 +1116,12 @@ describe('Call propagation', function() {
   var proxy;
   var proxy;
   var proxy_impl;
   var proxy_impl;
 
 
-  var test_service;
   var Client;
   var Client;
   var client;
   var client;
   var server;
   var server;
   before(function() {
   before(function() {
-    var test_proto = new ProtoBuf.Root();
-    test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
-                                         {keepCase: true});
-    test_service = test_proto.lookup('TestService');
+    var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
+    var test_service = test_proto.lookup('TestService');
     server = new grpc.Server();
     server = new grpc.Server();
     Client = grpc.loadObject(test_service);
     Client = grpc.loadObject(test_service);
     server.addService(Client.service, {
     server.addService(Client.service, {

+ 29 - 0
src/objective-c/tests/GRPCClientTests.m

@@ -293,6 +293,35 @@ static GRPCProtoMethod *kUnaryCallMethod;
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 }
 
 
+- (void)testTrailers {
+  __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
+  __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
+
+  GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
+                                             path:kEmptyCallMethod.HTTPPath
+                                   requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
+  // Setting this special key in the header will cause the interop server to echo back the
+  // trailer data.
+  const unsigned char raw_bytes[] = {1,2,3,4};
+  NSData *trailer_data = [NSData dataWithBytes:raw_bytes length:sizeof(raw_bytes)];
+  call.requestHeaders[@"x-grpc-test-echo-trailing-bin"] = trailer_data;
+
+  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+    XCTAssertNotNil(value, @"nil value received as response.");
+    XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
+    [response fulfill];
+  } completionHandler:^(NSError *errorOrNil) {
+    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+    XCTAssertEqualObjects((NSData *)call.responseTrailers[@"x-grpc-test-echo-trailing-bin"],
+                          trailer_data,
+                          @"Did not receive expected trailer");
+    [completion fulfill];
+  }];
+
+  [call startWithWriteable:responsesWriteable];
+  [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
+}
+
 // TODO(makarandd): Move to a different file that contains only unit tests
 // TODO(makarandd): Move to a different file that contains only unit tests
 - (void)testExceptions {
 - (void)testExceptions {
   // Try to set parameters to nil for GRPCCall. This should cause an exception
   // Try to set parameters to nil for GRPCCall. This should cause an exception

+ 19 - 7
src/php/ext/grpc/call.c

@@ -125,7 +125,12 @@ zval *grpc_parse_metadata_array(grpc_metadata_array
       php_grpc_add_next_index_stringl(inner_array, str_val,
       php_grpc_add_next_index_stringl(inner_array, str_val,
                                       GRPC_SLICE_LENGTH(elem->value), false);
                                       GRPC_SLICE_LENGTH(elem->value), false);
       add_assoc_zval(array, str_key, inner_array);
       add_assoc_zval(array, str_key, inner_array);
+      PHP_GRPC_FREE_STD_ZVAL(inner_array);
     }
     }
+    efree(str_key);
+#if PHP_MAJOR_VERSION >= 7
+    efree(str_val);
+#endif
   }
   }
   return array;
   return array;
 }
 }
@@ -256,8 +261,6 @@ PHP_METHOD(Call, startBatch) {
   object_init(result);
   object_init(result);
   php_grpc_ulong index;
   php_grpc_ulong index;
   zval *recv_status;
   zval *recv_status;
-  PHP_GRPC_MAKE_STD_ZVAL(recv_status);
-  object_init(recv_status);
   zval *value;
   zval *value;
   zval *inner_value;
   zval *inner_value;
   zval *message_value;
   zval *message_value;
@@ -439,7 +442,7 @@ PHP_METHOD(Call, startBatch) {
   grpc_completion_queue_pluck(completion_queue, call->wrapped,
   grpc_completion_queue_pluck(completion_queue, call->wrapped,
                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 #if PHP_MAJOR_VERSION >= 7
 #if PHP_MAJOR_VERSION >= 7
-  zval recv_md;
+  zval *recv_md;
 #endif
 #endif
   for (int i = 0; i < op_num; i++) {
   for (int i = 0; i < op_num; i++) {
     switch(ops[i].op) {
     switch(ops[i].op) {
@@ -460,8 +463,10 @@ PHP_METHOD(Call, startBatch) {
       array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC);
       array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC);
       add_property_zval(result, "metadata", array);
       add_property_zval(result, "metadata", array);
 #else
 #else
-      recv_md = *grpc_parse_metadata_array(&recv_metadata);
-      add_property_zval(result, "metadata", &recv_md);
+      recv_md = grpc_parse_metadata_array(&recv_metadata);
+      add_property_zval(result, "metadata", recv_md);
+      zval_ptr_dtor(recv_md);
+      PHP_GRPC_FREE_STD_ZVAL(recv_md);
 #endif
 #endif
       PHP_GRPC_DELREF(array);
       PHP_GRPC_DELREF(array);
       break;
       break;
@@ -475,12 +480,16 @@ PHP_METHOD(Call, startBatch) {
       }
       }
       break;
       break;
     case GRPC_OP_RECV_STATUS_ON_CLIENT:
     case GRPC_OP_RECV_STATUS_ON_CLIENT:
+      PHP_GRPC_MAKE_STD_ZVAL(recv_status);
+      object_init(recv_status);
 #if PHP_MAJOR_VERSION < 7
 #if PHP_MAJOR_VERSION < 7
       array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC);
       array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC);
       add_property_zval(recv_status, "metadata", array);
       add_property_zval(recv_status, "metadata", array);
 #else
 #else
-      recv_md = *grpc_parse_metadata_array(&recv_trailing_metadata);
-      add_property_zval(recv_status, "metadata", &recv_md);
+      recv_md = grpc_parse_metadata_array(&recv_trailing_metadata);
+      add_property_zval(recv_status, "metadata", recv_md);
+      zval_ptr_dtor(recv_md);
+      PHP_GRPC_FREE_STD_ZVAL(recv_md);
 #endif
 #endif
       PHP_GRPC_DELREF(array);
       PHP_GRPC_DELREF(array);
       add_property_long(recv_status, "code", status);
       add_property_long(recv_status, "code", status);
@@ -489,6 +498,9 @@ PHP_METHOD(Call, startBatch) {
                                    true);
                                    true);
       gpr_free(status_details_text);
       gpr_free(status_details_text);
       add_property_zval(result, "status", recv_status);
       add_property_zval(result, "status", recv_status);
+#if PHP_MAJOR_VERSION >= 7
+      zval_ptr_dtor(recv_status);
+#endif
       PHP_GRPC_DELREF(recv_status);
       PHP_GRPC_DELREF(recv_status);
       PHP_GRPC_FREE_STD_ZVAL(recv_status);
       PHP_GRPC_FREE_STD_ZVAL(recv_status);
       break;
       break;

+ 25 - 3
src/php/ext/grpc/call_credentials.c

@@ -172,34 +172,54 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
   object_init(arg);
   object_init(arg);
   php_grpc_add_property_string(arg, "service_url", context.service_url, true);
   php_grpc_add_property_string(arg, "service_url", context.service_url, true);
   php_grpc_add_property_string(arg, "method_name", context.method_name, true);
   php_grpc_add_property_string(arg, "method_name", context.method_name, true);
-  zval *retval;
-  PHP_GRPC_MAKE_STD_ZVAL(retval);
+  zval *retval = NULL;
 #if PHP_MAJOR_VERSION < 7
 #if PHP_MAJOR_VERSION < 7
   zval **params[1];
   zval **params[1];
   params[0] = &arg;
   params[0] = &arg;
   state->fci->params = params;
   state->fci->params = params;
   state->fci->retval_ptr_ptr = &retval;
   state->fci->retval_ptr_ptr = &retval;
 #else
 #else
+  PHP_GRPC_MAKE_STD_ZVAL(retval);
   state->fci->params = arg;
   state->fci->params = arg;
   state->fci->retval = retval;
   state->fci->retval = retval;
 #endif
 #endif
   state->fci->param_count = 1;
   state->fci->param_count = 1;
 
 
+  PHP_GRPC_DELREF(arg);
+
   /* call the user callback function */
   /* call the user callback function */
   zend_call_function(state->fci, state->fci_cache TSRMLS_CC);
   zend_call_function(state->fci, state->fci_cache TSRMLS_CC);
 
 
   grpc_status_code code = GRPC_STATUS_OK;
   grpc_status_code code = GRPC_STATUS_OK;
   grpc_metadata_array metadata;
   grpc_metadata_array metadata;
+  bool cleanup = true;
 
 
   if (Z_TYPE_P(retval) != IS_ARRAY) {
   if (Z_TYPE_P(retval) != IS_ARRAY) {
+    cleanup = false;
     code = GRPC_STATUS_INVALID_ARGUMENT;
     code = GRPC_STATUS_INVALID_ARGUMENT;
   } else if (!create_metadata_array(retval, &metadata)) {
   } else if (!create_metadata_array(retval, &metadata)) {
-    grpc_metadata_array_destroy(&metadata);
     code = GRPC_STATUS_INVALID_ARGUMENT;
     code = GRPC_STATUS_INVALID_ARGUMENT;
   }
   }
 
 
+  if (retval != NULL) {
+#if PHP_MAJOR_VERSION < 7
+    zval_ptr_dtor(&retval);
+#else
+    zval_ptr_dtor(arg);
+    zval_ptr_dtor(retval);
+    PHP_GRPC_FREE_STD_ZVAL(arg);
+    PHP_GRPC_FREE_STD_ZVAL(retval);
+#endif
+  }
+
   /* Pass control back to core */
   /* Pass control back to core */
   cb(user_data, metadata.metadata, metadata.count, code, NULL);
   cb(user_data, metadata.metadata, metadata.count, code, NULL);
+  if (cleanup) {
+    for (int i = 0; i < metadata.count; i++) {
+      grpc_slice_unref(metadata.metadata[i].value);
+    }
+    grpc_metadata_array_destroy(&metadata);
+  }
 }
 }
 
 
 /* Cleanup function for plugin creds API */
 /* Cleanup function for plugin creds API */
@@ -207,8 +227,10 @@ void plugin_destroy_state(void *ptr) {
   plugin_state *state = (plugin_state *)ptr;
   plugin_state *state = (plugin_state *)ptr;
   efree(state->fci);
   efree(state->fci);
   efree(state->fci_cache);
   efree(state->fci_cache);
+#if PHP_MAJOR_VERSION < 7
   PHP_GRPC_FREE_STD_ZVAL(state->fci->params);
   PHP_GRPC_FREE_STD_ZVAL(state->fci->params);
   PHP_GRPC_FREE_STD_ZVAL(state->fci->retval);
   PHP_GRPC_FREE_STD_ZVAL(state->fci->retval);
+#endif
   efree(state);
   efree(state);
 }
 }
 
 

+ 2 - 0
src/ruby/ext/grpc/rb_grpc_imports.generated.c

@@ -270,6 +270,7 @@ gpr_histogram_get_contents_type gpr_histogram_get_contents_import;
 gpr_histogram_merge_contents_type gpr_histogram_merge_contents_import;
 gpr_histogram_merge_contents_type gpr_histogram_merge_contents_import;
 gpr_join_host_port_type gpr_join_host_port_import;
 gpr_join_host_port_type gpr_join_host_port_import;
 gpr_split_host_port_type gpr_split_host_port_import;
 gpr_split_host_port_type gpr_split_host_port_import;
+gpr_log_severity_string_type gpr_log_severity_string_import;
 gpr_log_type gpr_log_import;
 gpr_log_type gpr_log_import;
 gpr_log_message_type gpr_log_message_import;
 gpr_log_message_type gpr_log_message_import;
 gpr_set_log_verbosity_type gpr_set_log_verbosity_import;
 gpr_set_log_verbosity_type gpr_set_log_verbosity_import;
@@ -571,6 +572,7 @@ void grpc_rb_load_imports(HMODULE library) {
   gpr_histogram_merge_contents_import = (gpr_histogram_merge_contents_type) GetProcAddress(library, "gpr_histogram_merge_contents");
   gpr_histogram_merge_contents_import = (gpr_histogram_merge_contents_type) GetProcAddress(library, "gpr_histogram_merge_contents");
   gpr_join_host_port_import = (gpr_join_host_port_type) GetProcAddress(library, "gpr_join_host_port");
   gpr_join_host_port_import = (gpr_join_host_port_type) GetProcAddress(library, "gpr_join_host_port");
   gpr_split_host_port_import = (gpr_split_host_port_type) GetProcAddress(library, "gpr_split_host_port");
   gpr_split_host_port_import = (gpr_split_host_port_type) GetProcAddress(library, "gpr_split_host_port");
+  gpr_log_severity_string_import = (gpr_log_severity_string_type) GetProcAddress(library, "gpr_log_severity_string");
   gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log");
   gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log");
   gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message");
   gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message");
   gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity");
   gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity");

+ 3 - 0
src/ruby/ext/grpc/rb_grpc_imports.generated.h

@@ -761,6 +761,9 @@ extern gpr_join_host_port_type gpr_join_host_port_import;
 typedef int(*gpr_split_host_port_type)(const char *name, char **host, char **port);
 typedef int(*gpr_split_host_port_type)(const char *name, char **host, char **port);
 extern gpr_split_host_port_type gpr_split_host_port_import;
 extern gpr_split_host_port_type gpr_split_host_port_import;
 #define gpr_split_host_port gpr_split_host_port_import
 #define gpr_split_host_port gpr_split_host_port_import
+typedef const char *(*gpr_log_severity_string_type)(gpr_log_severity severity);
+extern gpr_log_severity_string_type gpr_log_severity_string_import;
+#define gpr_log_severity_string gpr_log_severity_string_import
 typedef void(*gpr_log_type)(const char *file, int line, gpr_log_severity severity, const char *format, ...) GPR_PRINT_FORMAT_CHECK(4, 5);
 typedef void(*gpr_log_type)(const char *file, int line, gpr_log_severity severity, const char *format, ...) GPR_PRINT_FORMAT_CHECK(4, 5);
 extern gpr_log_type gpr_log_import;
 extern gpr_log_type gpr_log_import;
 #define gpr_log gpr_log_import
 #define gpr_log gpr_log_import

+ 1 - 1
src/ruby/lib/grpc/grpc.rb

@@ -34,6 +34,6 @@ begin
   if File.directory?(distrib_lib_dir)
   if File.directory?(distrib_lib_dir)
     require_relative "#{distrib_lib_dir}/grpc_c"
     require_relative "#{distrib_lib_dir}/grpc_c"
   else
   else
-    require_relative 'grpc_c'
+    require 'grpc/grpc_c'
   end
   end
 end
 end

+ 3 - 7
templates/config.m4.template

@@ -10,8 +10,6 @@
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
-    PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares)
-    PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/cares)
 
 
     LIBS="-lpthread $LIBS"
     LIBS="-lpthread $LIBS"
 
 
@@ -25,10 +23,8 @@
 
 
     case $host in
     case $host in
       *darwin*)
       *darwin*)
-        PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_darwin)
         ;;
         ;;
       *)
       *)
-        PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_linux)
         PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
         PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
         PHP_ADD_LIBRARY(rt)
         PHP_ADD_LIBRARY(rt)
         ;;
         ;;
@@ -39,7 +35,7 @@
       ${source} ${"\\"}
       ${source} ${"\\"}
       % endfor
       % endfor
       % for lib in libs:
       % for lib in libs:
-      % if lib.name in php_config_m4.get('deps', []):
+      % if lib.name in php_config_m4.get('deps', []) and lib.name != 'z':
       % for source in lib.src:
       % for source in lib.src:
       ${source} ${"\\"}
       ${source} ${"\\"}
       % endfor
       % endfor
@@ -47,13 +43,13 @@
       % endfor
       % endfor
       , $ext_shared, , -fvisibility=hidden ${"\\"}
       , $ext_shared, , -fvisibility=hidden ${"\\"}
       -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN ${"\\"}
       -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN ${"\\"}
-      -D_HAS_EXCEPTIONS=0 -DNOMINMAX)
+      -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0)
 
 
     PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
     PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
   <%
   <%
     dirs = {}
     dirs = {}
     for lib in libs:
     for lib in libs:
-      if lib.name in php_config_m4.get('deps', []):
+      if lib.name in php_config_m4.get('deps', []) and lib.name != 'z':
         for source in lib.src:
         for source in lib.src:
           dirs[source[:source.rfind('/')]] = 1
           dirs[source[:source.rfind('/')]] = 1
     dirs = dirs.keys()
     dirs = dirs.keys()

+ 31 - 0
templates/config.w32.template

@@ -0,0 +1,31 @@
+%YAML 1.2
+--- |
+  // $Id$
+  // vim:ft=javascript
+
+  ARG_WITH("grpc", "grpc support", "no");
+
+  if (PHP_GRPC != "no") {
+
+    grpc_source =
+      % for source in php_config_m4.src:
+      "${source.replace('/','\\\\')} " +
+      % endfor
+      % for lib in libs:
+      % if lib.name in php_config_m4.get('deps', []) and lib.name != 'ares':
+      % for source in lib.src:
+      "${source.replace('/','\\\\')} " +
+      % endfor
+      % endif
+      % endfor
+      "";
+
+    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");
+  }

+ 1 - 1
templates/package.json.template

@@ -36,7 +36,7 @@
       "lodash": "^4.15.0",
       "lodash": "^4.15.0",
       "nan": "^2.0.0",
       "nan": "^2.0.0",
       "node-pre-gyp": "^0.6.0",
       "node-pre-gyp": "^0.6.0",
-      "protobufjs": "^6.7.0"
+      "protobufjs": "^5.0.0"
     },
     },
     "devDependencies": {
     "devDependencies": {
       "async": "^2.0.1",
       "async": "^2.0.1",

+ 26 - 5
templates/package.xml.template

@@ -12,7 +12,7 @@
     <email>grpc-packages@google.com</email>
     <email>grpc-packages@google.com</email>
     <active>yes</active>
     <active>yes</active>
    </lead>
    </lead>
-   <date>2017-03-01</date>
+   <date>2017-05-22</date>
    <time>16:06:07</time>
    <time>16:06:07</time>
    <version>
    <version>
     <release>${settings.php_version.php()}</release>
     <release>${settings.php_version.php()}</release>
@@ -24,15 +24,19 @@
    </stability>
    </stability>
    <license>BSD</license>
    <license>BSD</license>
    <notes>
    <notes>
-  - Added arg info macros #9751
-  - Updated codegen to be consistent with protobuf #9492
+  - 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>
    </notes>
    <contents>
    <contents>
     <dir baseinstalldir="/" name="/">
     <dir baseinstalldir="/" name="/">
       <file baseinstalldir="/" name="config.m4" role="src" />
       <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/README.md" role="src" />
-      <file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
-      <file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
       % for source in php_config_m4.src + php_config_m4.headers:
       % for source in php_config_m4.src + php_config_m4.headers:
       <file baseinstalldir="/" name="${source}" role="src" />
       <file baseinstalldir="/" name="${source}" role="src" />
       % endfor
       % endfor
@@ -43,6 +47,7 @@
       % endfor
       % endfor
       % endif
       % endif
       % endfor
       % endfor
+      <file name="LICENSE" role="doc" />
     </dir>
     </dir>
    </contents>
    </contents>
    <dependencies>
    <dependencies>
@@ -355,6 +360,22 @@
      <license>BSD</license>
      <license>BSD</license>
      <notes>
      <notes>
   - Added arg info macros #9751
   - Added arg info macros #9751
+  - Updated codegen to be consistent with protobuf #9492
+     </notes>
+    </release>
+    <release>
+     <version>
+      <release>1.2.0</release>
+      <api>1.2.0</api>
+     </version>
+     <stability>
+      <release>stable</release>
+      <api>stable</api>
+     </stability>
+     <date>2017-03-20</date>
+     <license>BSD</license>
+     <notes>
+  - Added arg info macros #9751
   - Updated codegen to be consistent with protobuf #9492
   - Updated codegen to be consistent with protobuf #9492
      </notes>
      </notes>
     </release>
     </release>

+ 5 - 5
templates/src/csharp/build_packages_dotnetcli.bat.template

@@ -53,11 +53,11 @@
   @rem To be able to build, we also need to put grpc_csharp_ext to its normal location
   @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${"\\"}
   xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release${"\\"}
   
   
-  %%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
+  %%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
   
   
   %%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
   %%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
   %%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts
   %%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts

+ 5 - 5
templates/src/csharp/build_packages_dotnetcli.sh.template

@@ -50,11 +50,11 @@
   mkdir -p ../../libs/opt
   mkdir -p ../../libs/opt
   cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
   cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
   
   
-  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
+  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 "${settings.csharp_version}" -OutputDirectory ../../artifacts
   nuget pack Grpc.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts
   nuget pack Grpc.Tools.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts
   nuget pack Grpc.Tools.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts

+ 47 - 0
templates/tools/dockerfile/go_build_interop.sh.include

@@ -0,0 +1,47 @@
+#!/bin/bash
+# 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.
+#
+# Builds Go interop server and client in a base image.
+set -e
+
+# Clone just the grpc-go source code without any dependencies.
+# We are cloning from a local git repo that contains the right revision
+# to test instead of using "go get" to download from Github directly.
+git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc
+
+# Get all gRPC Go dependencies
+(cd src/google.golang.org/grpc && make deps && make testdeps)
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# Build the interop client and server
+(cd src/google.golang.org/grpc/interop/client && go install)
+(cd src/google.golang.org/grpc/interop/server && go install)

+ 3 - 0
templates/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh.template

@@ -0,0 +1,3 @@
+%YAML 1.2
+--- |
+  <%include file="../../go_build_interop.sh.include"/>  

+ 3 - 0
templates/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh.template

@@ -0,0 +1,3 @@
+%YAML 1.2
+--- |
+  <%include file="../../go_build_interop.sh.include"/>  

+ 7 - 1
test/core/end2end/cq_verifier.c

@@ -189,10 +189,16 @@ int byte_buffer_eq_string(grpc_byte_buffer *bb, const char *str) {
   return res;
   return res;
 }
 }
 
 
+static bool is_probably_integer(void *p) { return ((uintptr_t)p) < 1000000; }
+
 static void expectation_to_strvec(gpr_strvec *buf, expectation *e) {
 static void expectation_to_strvec(gpr_strvec *buf, expectation *e) {
   char *tmp;
   char *tmp;
 
 
-  gpr_asprintf(&tmp, "%p ", e->tag);
+  if (is_probably_integer(e->tag)) {
+    gpr_asprintf(&tmp, "tag(%" PRIdPTR ") ", (intptr_t)e->tag);
+  } else {
+    gpr_asprintf(&tmp, "%p ", e->tag);
+  }
   gpr_strvec_add(buf, tmp);
   gpr_strvec_add(buf, tmp);
 
 
   switch (e->type) {
   switch (e->type) {

+ 2 - 1
test/core/end2end/fixtures/h2_full+workarounds.c

@@ -83,10 +83,11 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f,
 
 
 void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
 void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
                                   grpc_channel_args *server_args) {
                                   grpc_channel_args *server_args) {
+  int i;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   fullstack_fixture_data *ffd = f->fixture_data;
   fullstack_fixture_data *ffd = f->fixture_data;
   grpc_arg args[GRPC_MAX_WORKAROUND_ID];
   grpc_arg args[GRPC_MAX_WORKAROUND_ID];
-  for (uint32_t i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) {
+  for (i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) {
     args[i].key = workarounds_arg[i];
     args[i].key = workarounds_arg[i];
     args[i].type = GRPC_ARG_INTEGER;
     args[i].type = GRPC_ARG_INTEGER;
     args[i].value.integer = 1;
     args[i].value.integer = 1;

+ 12 - 7
test/core/end2end/fixtures/http_proxy_fixture.c

@@ -50,6 +50,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/iomgr/closure.h"
 #include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/combiner.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/endpoint.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
@@ -71,6 +72,8 @@ struct grpc_end2end_http_proxy {
   gpr_mu* mu;
   gpr_mu* mu;
   grpc_pollset* pollset;
   grpc_pollset* pollset;
   gpr_refcount users;
   gpr_refcount users;
+
+  grpc_combiner* combiner;
 };
 };
 
 
 //
 //
@@ -400,19 +403,19 @@ static void on_accept(grpc_exec_ctx* exec_ctx, void* arg,
   grpc_pollset_set_add_pollset(exec_ctx, conn->pollset_set, proxy->pollset);
   grpc_pollset_set_add_pollset(exec_ctx, conn->pollset_set, proxy->pollset);
   grpc_endpoint_add_to_pollset_set(exec_ctx, endpoint, conn->pollset_set);
   grpc_endpoint_add_to_pollset_set(exec_ctx, endpoint, conn->pollset_set);
   grpc_closure_init(&conn->on_read_request_done, on_read_request_done, conn,
   grpc_closure_init(&conn->on_read_request_done, on_read_request_done, conn,
-                    grpc_schedule_on_exec_ctx);
+                    grpc_combiner_scheduler(conn->proxy->combiner, false));
   grpc_closure_init(&conn->on_server_connect_done, on_server_connect_done, conn,
   grpc_closure_init(&conn->on_server_connect_done, on_server_connect_done, conn,
-                    grpc_schedule_on_exec_ctx);
+                    grpc_combiner_scheduler(conn->proxy->combiner, false));
   grpc_closure_init(&conn->on_write_response_done, on_write_response_done, conn,
   grpc_closure_init(&conn->on_write_response_done, on_write_response_done, conn,
-                    grpc_schedule_on_exec_ctx);
+                    grpc_combiner_scheduler(conn->proxy->combiner, false));
   grpc_closure_init(&conn->on_client_read_done, on_client_read_done, conn,
   grpc_closure_init(&conn->on_client_read_done, on_client_read_done, conn,
-                    grpc_schedule_on_exec_ctx);
+                    grpc_combiner_scheduler(conn->proxy->combiner, false));
   grpc_closure_init(&conn->on_client_write_done, on_client_write_done, conn,
   grpc_closure_init(&conn->on_client_write_done, on_client_write_done, conn,
-                    grpc_schedule_on_exec_ctx);
+                    grpc_combiner_scheduler(conn->proxy->combiner, false));
   grpc_closure_init(&conn->on_server_read_done, on_server_read_done, conn,
   grpc_closure_init(&conn->on_server_read_done, on_server_read_done, conn,
-                    grpc_schedule_on_exec_ctx);
+                    grpc_combiner_scheduler(conn->proxy->combiner, false));
   grpc_closure_init(&conn->on_server_write_done, on_server_write_done, conn,
   grpc_closure_init(&conn->on_server_write_done, on_server_write_done, conn,
-                    grpc_schedule_on_exec_ctx);
+                    grpc_combiner_scheduler(conn->proxy->combiner, false));
   grpc_slice_buffer_init(&conn->client_read_buffer);
   grpc_slice_buffer_init(&conn->client_read_buffer);
   grpc_slice_buffer_init(&conn->client_deferred_write_buffer);
   grpc_slice_buffer_init(&conn->client_deferred_write_buffer);
   grpc_slice_buffer_init(&conn->client_write_buffer);
   grpc_slice_buffer_init(&conn->client_write_buffer);
@@ -453,6 +456,7 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) {
   grpc_end2end_http_proxy* proxy =
   grpc_end2end_http_proxy* proxy =
       (grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy));
       (grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy));
   memset(proxy, 0, sizeof(*proxy));
   memset(proxy, 0, sizeof(*proxy));
+  proxy->combiner = grpc_combiner_create(NULL);
   gpr_ref_init(&proxy->users, 1);
   gpr_ref_init(&proxy->users, 1);
   // Construct proxy address.
   // Construct proxy address.
   const int proxy_port = grpc_pick_unused_port_or_die();
   const int proxy_port = grpc_pick_unused_port_or_die();
@@ -504,6 +508,7 @@ void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) {
   grpc_pollset_shutdown(&exec_ctx, proxy->pollset,
   grpc_pollset_shutdown(&exec_ctx, proxy->pollset,
                         grpc_closure_create(destroy_pollset, proxy->pollset,
                         grpc_closure_create(destroy_pollset, proxy->pollset,
                                             grpc_schedule_on_exec_ctx));
                                             grpc_schedule_on_exec_ctx));
+  grpc_combiner_unref(&exec_ctx, proxy->combiner);
   gpr_free(proxy);
   gpr_free(proxy);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 }

+ 2 - 0
test/core/surface/concurrent_connectivity_test.c

@@ -112,7 +112,9 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp,
   grpc_endpoint_shutdown(exec_ctx, tcp,
   grpc_endpoint_shutdown(exec_ctx, tcp,
                          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
                          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
   grpc_endpoint_destroy(exec_ctx, tcp);
   grpc_endpoint_destroy(exec_ctx, tcp);
+  gpr_mu_lock(args->mu);
   GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
   GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
+  gpr_mu_unlock(args->mu);
 }
 }
 
 
 void bad_server_thread(void *vargs) {
 void bad_server_thread(void *vargs) {

+ 163 - 46
test/cpp/end2end/grpclb_end2end_test.cc

@@ -98,12 +98,12 @@ namespace {
 template <typename ServiceType>
 template <typename ServiceType>
 class CountedService : public ServiceType {
 class CountedService : public ServiceType {
  public:
  public:
-  int request_count() {
+  size_t request_count() {
     std::unique_lock<std::mutex> lock(mu_);
     std::unique_lock<std::mutex> lock(mu_);
     return request_count_;
     return request_count_;
   }
   }
 
 
-  int response_count() {
+  size_t response_count() {
     std::unique_lock<std::mutex> lock(mu_);
     std::unique_lock<std::mutex> lock(mu_);
     return response_count_;
     return response_count_;
   }
   }
@@ -121,8 +121,8 @@ class CountedService : public ServiceType {
   std::mutex mu_;
   std::mutex mu_;
 
 
  private:
  private:
-  int request_count_ = 0;
-  int response_count_ = 0;
+  size_t request_count_ = 0;
+  size_t response_count_ = 0;
 };
 };
 
 
 using BackendService = CountedService<TestServiceImpl>;
 using BackendService = CountedService<TestServiceImpl>;
@@ -243,9 +243,18 @@ class BalancerServiceImpl : public BalancerService {
   }
   }
 
 
   static LoadBalanceResponse BuildResponseForBackends(
   static LoadBalanceResponse BuildResponseForBackends(
-      const std::vector<int>& backend_ports) {
+      const std::vector<int>& backend_ports, int num_drops_for_rate_limiting,
+      int num_drops_for_load_balancing) {
     LoadBalanceResponse response;
     LoadBalanceResponse response;
-    for (const int backend_port : backend_ports) {
+    for (int i = 0; i < num_drops_for_rate_limiting; ++i) {
+      auto* server = response.mutable_server_list()->add_servers();
+      server->set_drop_for_rate_limiting(true);
+    }
+    for (int i = 0; i < num_drops_for_load_balancing; ++i) {
+      auto* server = response.mutable_server_list()->add_servers();
+      server->set_drop_for_load_balancing(true);
+    }
+    for (const int& backend_port : backend_ports) {
       auto* server = response.mutable_server_list()->add_servers();
       auto* server = response.mutable_server_list()->add_servers();
       server->set_ip_address(Ip4ToPackedString("127.0.0.1"));
       server->set_ip_address(Ip4ToPackedString("127.0.0.1"));
       server->set_port(backend_port);
       server->set_port(backend_port);
@@ -327,10 +336,8 @@ class GrpclbEnd2endTest : public ::testing::Test {
     ChannelArguments args;
     ChannelArguments args;
     args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
     args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
                     response_generator_);
                     response_generator_);
-    std::ostringstream uri;
-    uri << "test:///servername_not_used";
-    channel_ =
-        CreateCustomChannel(uri.str(), InsecureChannelCredentials(), args);
+    channel_ = CreateCustomChannel("test:///not_used",
+                                   InsecureChannelCredentials(), args);
     stub_ = grpc::testing::EchoTestService::NewStub(channel_);
     stub_ = grpc::testing::EchoTestService::NewStub(channel_);
   }
   }
 
 
@@ -467,26 +474,33 @@ class SingleBalancerTest : public GrpclbEnd2endTest {
 };
 };
 
 
 TEST_F(SingleBalancerTest, Vanilla) {
 TEST_F(SingleBalancerTest, Vanilla) {
+  const size_t kNumRpcsPerAddress = 100;
   ScheduleResponseForBalancer(
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0);
   // Make sure that trying to connect works without a call.
   // Make sure that trying to connect works without a call.
   channel_->GetState(true /* try_to_connect */);
   channel_->GetState(true /* try_to_connect */);
-  // Start servers and send 100 RPCs per server.
-  const auto& statuses_and_responses = SendRpc(kMessage_, 100 * num_backends_);
+  // Send 100 RPCs per server.
+  const auto& statuses_and_responses =
+      SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
 
 
   for (const auto& status_and_response : statuses_and_responses) {
   for (const auto& status_and_response : statuses_and_responses) {
-    EXPECT_TRUE(status_and_response.first.ok());
-    EXPECT_EQ(status_and_response.second.message(), kMessage_);
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+    EXPECT_EQ(response.message(), kMessage_);
   }
   }
 
 
   // Each backend should have gotten 100 requests.
   // Each backend should have gotten 100 requests.
   for (size_t i = 0; i < backends_.size(); ++i) {
   for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(100, backend_servers_[i].service_->request_count());
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backend_servers_[i].service_->request_count());
   }
   }
   // The balancer got a single request.
   // The balancer got a single request.
-  EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
   // and sent a single response.
   // and sent a single response.
-  EXPECT_EQ(1, balancer_servers_[0].service_->response_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
 
 
   // Check LB policy name for the channel.
   // Check LB policy name for the channel.
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
@@ -500,7 +514,7 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
   ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0);
   ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0);
   // Send non-empty serverlist only after kServerlistDelayMs
   // Send non-empty serverlist only after kServerlistDelayMs
   ScheduleResponseForBalancer(
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
       kServerlistDelayMs);
       kServerlistDelayMs);
 
 
   const auto t0 = system_clock::now();
   const auto t0 = system_clock::now();
@@ -518,17 +532,20 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
 
 
   // Each backend should have gotten 1 request.
   // Each backend should have gotten 1 request.
   for (size_t i = 0; i < backends_.size(); ++i) {
   for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(1, backend_servers_[i].service_->request_count());
+    EXPECT_EQ(1U, backend_servers_[i].service_->request_count());
   }
   }
   for (const auto& status_and_response : statuses_and_responses) {
   for (const auto& status_and_response : statuses_and_responses) {
-    EXPECT_TRUE(status_and_response.first.ok());
-    EXPECT_EQ(status_and_response.second.message(), kMessage_);
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+    EXPECT_EQ(response.message(), kMessage_);
   }
   }
 
 
   // The balancer got a single request.
   // The balancer got a single request.
-  EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
   // and sent two responses.
   // and sent two responses.
-  EXPECT_EQ(2, balancer_servers_[0].service_->response_count());
+  EXPECT_EQ(2U, balancer_servers_[0].service_->response_count());
 
 
   // Check LB policy name for the channel.
   // Check LB policy name for the channel.
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
@@ -539,10 +556,11 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
 
 
   // Send a serverlist right away.
   // Send a serverlist right away.
   ScheduleResponseForBalancer(
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0);
   // ... and the same one a bit later.
   // ... and the same one a bit later.
   ScheduleResponseForBalancer(
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
       kServerlistDelayMs);
       kServerlistDelayMs);
 
 
   // Send num_backends/2 requests.
   // Send num_backends/2 requests.
@@ -550,14 +568,19 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
   // only the first half of the backends will receive them.
   // only the first half of the backends will receive them.
   for (size_t i = 0; i < backends_.size(); ++i) {
   for (size_t i = 0; i < backends_.size(); ++i) {
     if (i < backends_.size() / 2)
     if (i < backends_.size() / 2)
-      EXPECT_EQ(1, backend_servers_[i].service_->request_count());
+      EXPECT_EQ(1U, backend_servers_[i].service_->request_count())
+          << "for backend #" << i;
     else
     else
-      EXPECT_EQ(0, backend_servers_[i].service_->request_count());
+      EXPECT_EQ(0U, backend_servers_[i].service_->request_count())
+          << "for backend #" << i;
   }
   }
   EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
   EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
   for (const auto& status_and_response : statuses_and_responses) {
   for (const auto& status_and_response : statuses_and_responses) {
-    EXPECT_TRUE(status_and_response.first.ok());
-    EXPECT_EQ(status_and_response.second.message(), kMessage_);
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+    EXPECT_EQ(response.message(), kMessage_);
   }
   }
 
 
   // Wait for the (duplicated) serverlist update.
   // Wait for the (duplicated) serverlist update.
@@ -566,7 +589,7 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
       gpr_time_from_millis(kServerlistDelayMs * 1.1, GPR_TIMESPAN)));
       gpr_time_from_millis(kServerlistDelayMs * 1.1, GPR_TIMESPAN)));
 
 
   // Verify the LB has sent two responses.
   // Verify the LB has sent two responses.
-  EXPECT_EQ(2, balancer_servers_[0].service_->response_count());
+  EXPECT_EQ(2U, balancer_servers_[0].service_->response_count());
 
 
   // Some more calls to complete the total number of backends.
   // Some more calls to complete the total number of backends.
   statuses_and_responses = SendRpc(
   statuses_and_responses = SendRpc(
@@ -575,52 +598,146 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
   // Because a duplicated serverlist should have no effect, all backends must
   // Because a duplicated serverlist should have no effect, all backends must
   // have been hit once now.
   // have been hit once now.
   for (size_t i = 0; i < backends_.size(); ++i) {
   for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(1, backend_servers_[i].service_->request_count());
+    EXPECT_EQ(1U, backend_servers_[i].service_->request_count());
   }
   }
   EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
   EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
   for (const auto& status_and_response : statuses_and_responses) {
   for (const auto& status_and_response : statuses_and_responses) {
-    EXPECT_TRUE(status_and_response.first.ok());
-    EXPECT_EQ(status_and_response.second.message(), kMessage_);
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+    EXPECT_EQ(response.message(), kMessage_);
   }
   }
 
 
   // The balancer got a single request.
   // The balancer got a single request.
-  EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
   // Check LB policy name for the channel.
   // Check LB policy name for the channel.
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
 }
 }
 
 
+TEST_F(SingleBalancerTest, Drop) {
+  const size_t kNumRpcsPerAddress = 100;
+  ScheduleResponseForBalancer(
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 1, 2),
+      0);
+  // Send 100 RPCs for each server and drop address.
+  const auto& statuses_and_responses =
+      SendRpc(kMessage_, kNumRpcsPerAddress * (num_backends_ + 3));
+
+  size_t num_drops = 0;
+  for (const auto& status_and_response : statuses_and_responses) {
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    if (!status.ok() &&
+        status.error_message() == "Call dropped by load balancing policy") {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kMessage_);
+    }
+  }
+  EXPECT_EQ(kNumRpcsPerAddress * 3, num_drops);
+
+  // Each backend should have gotten 100 requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backend_servers_[i].service_->request_count());
+  }
+  // The balancer got a single request.
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
+  // and sent a single response.
+  EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
+}
+
 class SingleBalancerWithClientLoadReportingTest : public GrpclbEnd2endTest {
 class SingleBalancerWithClientLoadReportingTest : public GrpclbEnd2endTest {
  public:
  public:
   SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 2) {}
   SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 2) {}
 };
 };
 
 
 TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) {
 TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) {
+  const size_t kNumRpcsPerAddress = 100;
   ScheduleResponseForBalancer(
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
-  // Start servers and send 100 RPCs per server.
-  const auto& statuses_and_responses = SendRpc(kMessage_, 100 * num_backends_);
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0);
+  // Send 100 RPCs per server.
+  const auto& statuses_and_responses =
+      SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
 
 
   for (const auto& status_and_response : statuses_and_responses) {
   for (const auto& status_and_response : statuses_and_responses) {
-    EXPECT_TRUE(status_and_response.first.ok());
-    EXPECT_EQ(status_and_response.second.message(), kMessage_);
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                             << " message=" << status.error_message();
+    EXPECT_EQ(response.message(), kMessage_);
   }
   }
 
 
   // Each backend should have gotten 100 requests.
   // Each backend should have gotten 100 requests.
   for (size_t i = 0; i < backends_.size(); ++i) {
   for (size_t i = 0; i < backends_.size(); ++i) {
-    EXPECT_EQ(100, backend_servers_[i].service_->request_count());
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backend_servers_[i].service_->request_count());
   }
   }
   // The balancer got a single request.
   // The balancer got a single request.
-  EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
   // and sent a single response.
   // and sent a single response.
-  EXPECT_EQ(1, balancer_servers_[0].service_->response_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
 
 
   const ClientStats client_stats = WaitForLoadReports();
   const ClientStats client_stats = WaitForLoadReports();
-  EXPECT_EQ(100 * num_backends_, client_stats.num_calls_started);
-  EXPECT_EQ(100 * num_backends_, client_stats.num_calls_finished);
+  EXPECT_EQ(kNumRpcsPerAddress * num_backends_, client_stats.num_calls_started);
+  EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
+            client_stats.num_calls_finished);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_rate_limiting);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_rate_limiting);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_load_balancing);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_load_balancing);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send);
   EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send);
-  EXPECT_EQ(100 * num_backends_,
+  EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
+            client_stats.num_calls_finished_known_received);
+}
+
+TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) {
+  const size_t kNumRpcsPerAddress = 3;
+  ScheduleResponseForBalancer(
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 2, 1),
+      0);
+  // Send 100 RPCs for each server and drop address.
+  const auto& statuses_and_responses =
+      SendRpc(kMessage_, kNumRpcsPerAddress * (num_backends_ + 3));
+
+  size_t num_drops = 0;
+  for (const auto& status_and_response : statuses_and_responses) {
+    const Status& status = status_and_response.first;
+    const EchoResponse& response = status_and_response.second;
+    if (!status.ok() &&
+        status.error_message() == "Call dropped by load balancing policy") {
+      ++num_drops;
+    } else {
+      EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+                               << " message=" << status.error_message();
+      EXPECT_EQ(response.message(), kMessage_);
+    }
+  }
+  EXPECT_EQ(kNumRpcsPerAddress * 3, num_drops);
+
+  // Each backend should have gotten 100 requests.
+  for (size_t i = 0; i < backends_.size(); ++i) {
+    EXPECT_EQ(kNumRpcsPerAddress,
+              backend_servers_[i].service_->request_count());
+  }
+  // The balancer got a single request.
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
+  // and sent a single response.
+  EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
+
+  const ClientStats client_stats = WaitForLoadReports();
+  EXPECT_EQ(kNumRpcsPerAddress * (num_backends_ + 3),
+            client_stats.num_calls_started);
+  EXPECT_EQ(kNumRpcsPerAddress * (num_backends_ + 3),
+            client_stats.num_calls_finished);
+  EXPECT_EQ(kNumRpcsPerAddress * 2,
+            client_stats.num_calls_finished_with_drop_for_rate_limiting);
+  EXPECT_EQ(kNumRpcsPerAddress,
+            client_stats.num_calls_finished_with_drop_for_load_balancing);
+  EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send);
+  EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
             client_stats.num_calls_finished_known_received);
             client_stats.num_calls_finished_known_received);
 }
 }
 
 

+ 8 - 23
test/cpp/end2end/round_robin_end2end_test.cc

@@ -42,7 +42,6 @@
 #include <grpc++/server_builder.h>
 #include <grpc++/server_builder.h>
 #include <grpc/grpc.h>
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
-#include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <grpc/support/time.h>
 
 
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
@@ -131,22 +130,10 @@ class RoundRobinEnd2endTest : public ::testing::Test {
     int port_;
     int port_;
     std::unique_ptr<Server> server_;
     std::unique_ptr<Server> server_;
     MyTestServiceImpl service_;
     MyTestServiceImpl service_;
-    std::unique_ptr<std::thread> thread_;
 
 
     explicit ServerData(const grpc::string& server_host) {
     explicit ServerData(const grpc::string& server_host) {
       port_ = grpc_pick_unused_port_or_die();
       port_ = grpc_pick_unused_port_or_die();
       gpr_log(GPR_INFO, "starting server on port %d", port_);
       gpr_log(GPR_INFO, "starting server on port %d", port_);
-      std::mutex mu;
-      std::condition_variable cond;
-      thread_.reset(new std::thread(
-          std::bind(&ServerData::Start, this, server_host, &mu, &cond)));
-      std::unique_lock<std::mutex> lock(mu);
-      cond.wait(lock);
-      gpr_log(GPR_INFO, "server startup complete");
-    }
-
-    void Start(const grpc::string& server_host, std::mutex* mu,
-               std::condition_variable* cond) {
       std::ostringstream server_address;
       std::ostringstream server_address;
       server_address << server_host << ":" << port_;
       server_address << server_host << ":" << port_;
       ServerBuilder builder;
       ServerBuilder builder;
@@ -154,18 +141,13 @@ class RoundRobinEnd2endTest : public ::testing::Test {
                                InsecureServerCredentials());
                                InsecureServerCredentials());
       builder.RegisterService(&service_);
       builder.RegisterService(&service_);
       server_ = builder.BuildAndStart();
       server_ = builder.BuildAndStart();
-      std::lock_guard<std::mutex> lock(*mu);
-      cond->notify_one();
+      gpr_log(GPR_INFO, "server startup complete");
     }
     }
 
 
-    void Shutdown() {
-      server_->Shutdown();
-      thread_->join();
-    }
+    void Shutdown() { server_->Shutdown(); }
   };
   };
 
 
   const grpc::string server_host_;
   const grpc::string server_host_;
-  CompletionQueue cli_cq_;
   std::shared_ptr<Channel> channel_;
   std::shared_ptr<Channel> channel_;
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
   std::vector<std::unique_ptr<ServerData>> servers_;
   std::vector<std::unique_ptr<ServerData>> servers_;
@@ -197,10 +179,13 @@ TEST_F(RoundRobinEnd2endTest, RoundRobin) {
   const int kNumServers = 3;
   const int kNumServers = 3;
   StartServers(kNumServers);
   StartServers(kNumServers);
   ResetStub(true /* round_robin */);
   ResetStub(true /* round_robin */);
-  SendRpc(kNumServers);
-  // One request should have gone to each server.
+  // Send one RPC per backend and make sure they are used in order.
+  // Note: This relies on the fact that the subchannels are reported in
+  // state READY in the order in which the addresses are specified,
+  // which is only true because the backends are all local.
   for (size_t i = 0; i < servers_.size(); ++i) {
   for (size_t i = 0; i < servers_.size(); ++i) {
-    EXPECT_EQ(1, servers_[i]->service_.request_count());
+    SendRpc(1);
+    EXPECT_EQ(1, servers_[i]->service_.request_count()) << "for backend #" << i;
   }
   }
   // Check LB policy name for the channel.
   // Check LB policy name for the channel.
   EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
   EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());

+ 4 - 1
test/cpp/microbenchmarks/bm_fullstack_trickle.cc

@@ -101,6 +101,8 @@ class TrickledCHTTP2 : public EndpointPairFixture {
   }
   }
 
 
   void AddToLabel(std::ostream& out, benchmark::State& state) {
   void AddToLabel(std::ostream& out, benchmark::State& state) {
+    grpc_chttp2_transport* client =
+        reinterpret_cast<grpc_chttp2_transport*>(client_transport_);
     out << " writes/iter:"
     out << " writes/iter:"
         << ((double)stats_.num_writes / (double)state.iterations())
         << ((double)stats_.num_writes / (double)state.iterations())
         << " cli_transport_stalls/iter:"
         << " cli_transport_stalls/iter:"
@@ -116,7 +118,8 @@ class TrickledCHTTP2 : public EndpointPairFixture {
             (double)state.iterations())
             (double)state.iterations())
         << " svr_stream_stalls/iter:"
         << " svr_stream_stalls/iter:"
         << ((double)server_stats_.streams_stalled_due_to_stream_flow_control /
         << ((double)server_stats_.streams_stalled_due_to_stream_flow_control /
-            (double)state.iterations());
+            (double)state.iterations())
+        << " cli_bw_est:" << (double)client->bdp_estimator.bw_est;
   }
   }
 
 
   void Log(int64_t iteration) {
   void Log(int64_t iteration) {

+ 2 - 0
tools/README.md

@@ -13,6 +13,8 @@ container engine, BigQuery etc)
 
 
 internal_ci: Support for running tests on an internal CI platform.
 internal_ci: Support for running tests on an internal CI platform.
 
 
+interop_matrix: Scripts to build, upload, and run gRPC clients in docker with various language/runtimes. 
+
 jenkins: Support for running tests on Jenkins.
 jenkins: Support for running tests on Jenkins.
 
 
 run_tests: Scripts to run gRPC tests in parallel.
 run_tests: Scripts to run gRPC tests in parallel.

+ 39 - 0
tools/dockerfile/grpc_artifact_linux_armv6/Dockerfile

@@ -0,0 +1,39 @@
+# 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.
+
+# Docker file for building gRPC Raspbian binaries
+
+FROM quay.io/grpc/raspbian_armv6
+
+# Place any extra build instructions between these commands
+# Recommend modifying upstream docker image (quay.io/grpc/raspbian_armv6)
+# for build steps because running them under QEMU is very slow
+# (https://github.com/kpayson64/armv7hf-debian-qemu)
+# RUN [ "cross-build-start" ]
+# RUN [ "cross-build-end" ]

+ 39 - 0
tools/dockerfile/grpc_artifact_linux_armv7/Dockerfile

@@ -0,0 +1,39 @@
+# 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.
+
+# Docker file for building gRPC Raspbian binaries
+
+FROM quay.io/grpc/raspbian_armv7
+
+# Place any extra build instructions between these commands
+# Recommend modifying upstream docker image (quay.io/grpc/raspbian_armv7)
+# for build steps because running them under QEMU is very slow
+# (https://github.com/kpayson64/armv7hf-debian-qemu)
+# RUN [ "cross-build-start" ]
+# RUN [ "cross-build-end" ]

+ 48 - 0
tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh

@@ -0,0 +1,48 @@
+#!/bin/bash
+# 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.
+#
+# Builds Go interop server and client in a base image.
+set -e
+
+# Clone just the grpc-go source code without any dependencies.
+# We are cloning from a local git repo that contains the right revision
+# to test instead of using "go get" to download from Github directly.
+git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc
+
+# Get all gRPC Go dependencies
+(cd src/google.golang.org/grpc && make deps && make testdeps)
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# Build the interop client and server
+(cd src/google.golang.org/grpc/interop/client && go install)
+(cd src/google.golang.org/grpc/interop/server && go install)
+  

+ 48 - 0
tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh

@@ -0,0 +1,48 @@
+#!/bin/bash
+# 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.
+#
+# Builds Go interop server and client in a base image.
+set -e
+
+# Clone just the grpc-go source code without any dependencies.
+# We are cloning from a local git repo that contains the right revision
+# to test instead of using "go get" to download from Github directly.
+git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc
+
+# Get all gRPC Go dependencies
+(cd src/google.golang.org/grpc && make deps && make testdeps)
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# Build the interop client and server
+(cd src/google.golang.org/grpc/interop/client && go install)
+(cd src/google.golang.org/grpc/interop/server && go install)
+  

+ 1 - 1
tools/dockerfile/push_testing_images.sh

@@ -44,7 +44,7 @@ cd -
 
 
 DOCKERHUB_ORGANIZATION=grpctesting
 DOCKERHUB_ORGANIZATION=grpctesting
 
 
-for DOCKERFILE_DIR in tools/dockerfile/test/* tools/dockerfile/grpc_artifact_*
+for DOCKERFILE_DIR in tools/dockerfile/test/* tools/dockerfile/grpc_artifact_* tools/dockerfile/interoptest/*
 do
 do
   # Generate image name based on Dockerfile checksum. That works well as long
   # Generate image name based on Dockerfile checksum. That works well as long
   # as can count on dockerfiles being written in a way that changing the logical 
   # as can count on dockerfiles being written in a way that changing the logical 

+ 1 - 12
tools/doxygen/Doxyfile.c++

@@ -871,12 +871,6 @@ include/grpc++/support/string_ref.h \
 include/grpc++/support/stub_options.h \
 include/grpc++/support/stub_options.h \
 include/grpc++/support/sync_stream.h \
 include/grpc++/support/sync_stream.h \
 include/grpc++/support/time.h \
 include/grpc++/support/time.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/impl/codegen/atm.h \
 include/grpc/impl/codegen/atm.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
@@ -895,12 +889,7 @@ include/grpc/impl/codegen/status.h \
 include/grpc/impl/codegen/sync.h \
 include/grpc/impl/codegen/sync.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
-include/grpc/impl/codegen/sync_windows.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/sync_windows.h
 
 
 # This tag can be used to specify the character encoding of the source files
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

+ 0 - 251
tools/doxygen/Doxyfile.c++.internal

@@ -872,12 +872,6 @@ include/grpc++/support/string_ref.h \
 include/grpc++/support/stub_options.h \
 include/grpc++/support/stub_options.h \
 include/grpc++/support/sync_stream.h \
 include/grpc++/support/sync_stream.h \
 include/grpc++/support/time.h \
 include/grpc++/support/time.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/impl/codegen/atm.h \
 include/grpc/impl/codegen/atm.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_atomic.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
 include/grpc/impl/codegen/atm_gcc_sync.h \
@@ -897,251 +891,6 @@ include/grpc/impl/codegen/sync.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_generic.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_posix.h \
 include/grpc/impl/codegen/sync_windows.h \
 include/grpc/impl/codegen/sync_windows.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 \
-src/core/lib/channel/channel_args.c \
-src/core/lib/channel/channel_args.h \
-src/core/lib/channel/channel_stack.c \
-src/core/lib/channel/channel_stack.h \
-src/core/lib/channel/channel_stack_builder.c \
-src/core/lib/channel/channel_stack_builder.h \
-src/core/lib/channel/connected_channel.c \
-src/core/lib/channel/connected_channel.h \
-src/core/lib/channel/context.h \
-src/core/lib/channel/handshaker.c \
-src/core/lib/channel/handshaker.h \
-src/core/lib/channel/handshaker_factory.c \
-src/core/lib/channel/handshaker_factory.h \
-src/core/lib/channel/handshaker_registry.c \
-src/core/lib/channel/handshaker_registry.h \
-src/core/lib/compression/algorithm_metadata.h \
-src/core/lib/compression/compression.c \
-src/core/lib/compression/message_compress.c \
-src/core/lib/compression/message_compress.h \
-src/core/lib/debug/trace.c \
-src/core/lib/debug/trace.h \
-src/core/lib/http/format_request.c \
-src/core/lib/http/format_request.h \
-src/core/lib/http/httpcli.c \
-src/core/lib/http/httpcli.h \
-src/core/lib/http/parser.c \
-src/core/lib/http/parser.h \
-src/core/lib/iomgr/closure.c \
-src/core/lib/iomgr/closure.h \
-src/core/lib/iomgr/combiner.c \
-src/core/lib/iomgr/combiner.h \
-src/core/lib/iomgr/endpoint.c \
-src/core/lib/iomgr/endpoint.h \
-src/core/lib/iomgr/endpoint_pair.h \
-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/error.h \
-src/core/lib/iomgr/error_internal.h \
-src/core/lib/iomgr/ev_epoll1_linux.c \
-src/core/lib/iomgr/ev_epoll1_linux.h \
-src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
-src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h \
-src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
-src/core/lib/iomgr/ev_epoll_thread_pool_linux.h \
-src/core/lib/iomgr/ev_epollex_linux.c \
-src/core/lib/iomgr/ev_epollex_linux.h \
-src/core/lib/iomgr/ev_epollsig_linux.c \
-src/core/lib/iomgr/ev_epollsig_linux.h \
-src/core/lib/iomgr/ev_poll_posix.c \
-src/core/lib/iomgr/ev_poll_posix.h \
-src/core/lib/iomgr/ev_posix.c \
-src/core/lib/iomgr/ev_posix.h \
-src/core/lib/iomgr/ev_windows.c \
-src/core/lib/iomgr/exec_ctx.c \
-src/core/lib/iomgr/exec_ctx.h \
-src/core/lib/iomgr/executor.c \
-src/core/lib/iomgr/executor.h \
-src/core/lib/iomgr/iocp_windows.c \
-src/core/lib/iomgr/iocp_windows.h \
-src/core/lib/iomgr/iomgr.c \
-src/core/lib/iomgr/iomgr.h \
-src/core/lib/iomgr/iomgr_internal.h \
-src/core/lib/iomgr/iomgr_posix.c \
-src/core/lib/iomgr/iomgr_posix.h \
-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/is_epollexclusive_available.h \
-src/core/lib/iomgr/load_file.c \
-src/core/lib/iomgr/load_file.h \
-src/core/lib/iomgr/lockfree_event.c \
-src/core/lib/iomgr/lockfree_event.h \
-src/core/lib/iomgr/network_status_tracker.c \
-src/core/lib/iomgr/network_status_tracker.h \
-src/core/lib/iomgr/polling_entity.c \
-src/core/lib/iomgr/polling_entity.h \
-src/core/lib/iomgr/pollset.h \
-src/core/lib/iomgr/pollset_set.h \
-src/core/lib/iomgr/pollset_set_uv.c \
-src/core/lib/iomgr/pollset_set_windows.c \
-src/core/lib/iomgr/pollset_set_windows.h \
-src/core/lib/iomgr/pollset_uv.c \
-src/core/lib/iomgr/pollset_uv.h \
-src/core/lib/iomgr/pollset_windows.c \
-src/core/lib/iomgr/pollset_windows.h \
-src/core/lib/iomgr/port.h \
-src/core/lib/iomgr/resolve_address.h \
-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/resource_quota.h \
-src/core/lib/iomgr/sockaddr.h \
-src/core/lib/iomgr/sockaddr_posix.h \
-src/core/lib/iomgr/sockaddr_utils.c \
-src/core/lib/iomgr/sockaddr_utils.h \
-src/core/lib/iomgr/sockaddr_windows.h \
-src/core/lib/iomgr/socket_factory_posix.c \
-src/core/lib/iomgr/socket_factory_posix.h \
-src/core/lib/iomgr/socket_mutator.c \
-src/core/lib/iomgr/socket_mutator.h \
-src/core/lib/iomgr/socket_utils.h \
-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_posix.h \
-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/socket_windows.h \
-src/core/lib/iomgr/sys_epoll_wrapper.h \
-src/core/lib/iomgr/tcp_client.h \
-src/core/lib/iomgr/tcp_client_posix.c \
-src/core/lib/iomgr/tcp_client_posix.h \
-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_posix.h \
-src/core/lib/iomgr/tcp_server.h \
-src/core/lib/iomgr/tcp_server_posix.c \
-src/core/lib/iomgr/tcp_server_utils_posix.h \
-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_uv.h \
-src/core/lib/iomgr/tcp_windows.c \
-src/core/lib/iomgr/tcp_windows.h \
-src/core/lib/iomgr/time_averaged_stats.c \
-src/core/lib/iomgr/time_averaged_stats.h \
-src/core/lib/iomgr/timer.h \
-src/core/lib/iomgr/timer_generic.c \
-src/core/lib/iomgr/timer_generic.h \
-src/core/lib/iomgr/timer_heap.c \
-src/core/lib/iomgr/timer_heap.h \
-src/core/lib/iomgr/timer_manager.c \
-src/core/lib/iomgr/timer_manager.h \
-src/core/lib/iomgr/timer_uv.c \
-src/core/lib/iomgr/timer_uv.h \
-src/core/lib/iomgr/udp_server.c \
-src/core/lib/iomgr/udp_server.h \
-src/core/lib/iomgr/unix_sockets_posix.c \
-src/core/lib/iomgr/unix_sockets_posix.h \
-src/core/lib/iomgr/unix_sockets_posix_noop.c \
-src/core/lib/iomgr/wakeup_fd_cv.c \
-src/core/lib/iomgr/wakeup_fd_cv.h \
-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_pipe.h \
-src/core/lib/iomgr/wakeup_fd_posix.c \
-src/core/lib/iomgr/wakeup_fd_posix.h \
-src/core/lib/iomgr/workqueue.h \
-src/core/lib/iomgr/workqueue_uv.c \
-src/core/lib/iomgr/workqueue_uv.h \
-src/core/lib/iomgr/workqueue_windows.c \
-src/core/lib/iomgr/workqueue_windows.h \
-src/core/lib/json/json.c \
-src/core/lib/json/json.h \
-src/core/lib/json/json_common.h \
-src/core/lib/json/json_reader.c \
-src/core/lib/json/json_reader.h \
-src/core/lib/json/json_string.c \
-src/core/lib/json/json_writer.c \
-src/core/lib/json/json_writer.h \
-src/core/lib/slice/b64.c \
-src/core/lib/slice/b64.h \
-src/core/lib/slice/percent_encoding.c \
-src/core/lib/slice/percent_encoding.h \
-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_hash_table.h \
-src/core/lib/slice/slice_intern.c \
-src/core/lib/slice/slice_internal.h \
-src/core/lib/slice/slice_string_helpers.c \
-src/core/lib/slice/slice_string_helpers.h \
-src/core/lib/surface/alarm.c \
-src/core/lib/surface/api_trace.c \
-src/core/lib/surface/api_trace.h \
-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.h \
-src/core/lib/surface/call_details.c \
-src/core/lib/surface/call_log_batch.c \
-src/core/lib/surface/call_test_only.h \
-src/core/lib/surface/channel.c \
-src/core/lib/surface/channel.h \
-src/core/lib/surface/channel_init.c \
-src/core/lib/surface/channel_init.h \
-src/core/lib/surface/channel_ping.c \
-src/core/lib/surface/channel_stack_type.c \
-src/core/lib/surface/channel_stack_type.h \
-src/core/lib/surface/completion_queue.c \
-src/core/lib/surface/completion_queue.h \
-src/core/lib/surface/completion_queue_factory.c \
-src/core/lib/surface/completion_queue_factory.h \
-src/core/lib/surface/event_string.c \
-src/core/lib/surface/event_string.h \
-src/core/lib/surface/init.h \
-src/core/lib/surface/lame_client.cc \
-src/core/lib/surface/lame_client.h \
-src/core/lib/surface/metadata_array.c \
-src/core/lib/surface/server.c \
-src/core/lib/surface/server.h \
-src/core/lib/surface/validate_metadata.c \
-src/core/lib/surface/validate_metadata.h \
-src/core/lib/surface/version.c \
-src/core/lib/transport/bdp_estimator.c \
-src/core/lib/transport/bdp_estimator.h \
-src/core/lib/transport/byte_stream.c \
-src/core/lib/transport/byte_stream.h \
-src/core/lib/transport/connectivity_state.c \
-src/core/lib/transport/connectivity_state.h \
-src/core/lib/transport/error_utils.c \
-src/core/lib/transport/error_utils.h \
-src/core/lib/transport/http2_errors.h \
-src/core/lib/transport/metadata.c \
-src/core/lib/transport/metadata.h \
-src/core/lib/transport/metadata_batch.c \
-src/core/lib/transport/metadata_batch.h \
-src/core/lib/transport/pid_controller.c \
-src/core/lib/transport/pid_controller.h \
-src/core/lib/transport/service_config.c \
-src/core/lib/transport/service_config.h \
-src/core/lib/transport/static_metadata.c \
-src/core/lib/transport/static_metadata.h \
-src/core/lib/transport/status_conversion.c \
-src/core/lib/transport/status_conversion.h \
-src/core/lib/transport/timeout_encoding.c \
-src/core/lib/transport/timeout_encoding.h \
-src/core/lib/transport/transport.c \
-src/core/lib/transport/transport.h \
-src/core/lib/transport/transport_impl.h \
-src/core/lib/transport/transport_op_string.c \
 src/cpp/README.md \
 src/cpp/README.md \
 src/cpp/client/channel_cc.cc \
 src/cpp/client/channel_cc.cc \
 src/cpp/client/client_context.cc \
 src/cpp/client/client_context.cc \

部分文件因为文件数量过多而无法显示