Browse Source

Merge github.com:grpc/grpc into selectivity

Craig Tiller 8 years ago
parent
commit
e54eb13ed7
100 changed files with 2199 additions and 1836 deletions
  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_workaround_cronet_compression_filter",
         "grpc_server_backward_compatibility",
-    ]
+    ],
 )
 
 grpc_cc_library(
@@ -1400,22 +1400,22 @@ GRPCXX_PUBLIC_HDRS = [
 
 grpc_cc_library(
     name = "grpc++_base",
-    hdrs = GRPCXX_HDRS,
     srcs = GRPCXX_SRCS,
-    public_hdrs = GRPCXX_PUBLIC_HDRS,
+    hdrs = GRPCXX_HDRS,
     language = "c++",
+    public_hdrs = GRPCXX_PUBLIC_HDRS,
     deps = [
-        "grpc++_codegen_base",
         "grpc",
+        "grpc++_codegen_base",
     ],
 )
 
 grpc_cc_library(
     name = "grpc++_base_unsecure",
-    hdrs = GRPCXX_HDRS,
     srcs = GRPCXX_SRCS,
-    public_hdrs = GRPCXX_PUBLIC_HDRS,
+    hdrs = GRPCXX_HDRS,
     language = "c++",
+    public_hdrs = GRPCXX_PUBLIC_HDRS,
     deps = [
         "grpc++_codegen_base",
         "grpc_unsecure",
@@ -1539,5 +1539,4 @@ grpc_cc_library(
     ],
 )
 
-
 grpc_generate_one_off_targets()

+ 30 - 305
CMakeLists.txt

@@ -2273,133 +2273,6 @@ add_library(grpc++
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
-  src/core/lib/channel/channel_args.c
-  src/core/lib/channel/channel_stack.c
-  src/core/lib/channel/channel_stack_builder.c
-  src/core/lib/channel/connected_channel.c
-  src/core/lib/channel/handshaker.c
-  src/core/lib/channel/handshaker_factory.c
-  src/core/lib/channel/handshaker_registry.c
-  src/core/lib/compression/compression.c
-  src/core/lib/compression/message_compress.c
-  src/core/lib/http/format_request.c
-  src/core/lib/http/httpcli.c
-  src/core/lib/http/parser.c
-  src/core/lib/iomgr/closure.c
-  src/core/lib/iomgr/combiner.c
-  src/core/lib/iomgr/endpoint.c
-  src/core/lib/iomgr/endpoint_pair_posix.c
-  src/core/lib/iomgr/endpoint_pair_uv.c
-  src/core/lib/iomgr/endpoint_pair_windows.c
-  src/core/lib/iomgr/error.c
-  src/core/lib/iomgr/ev_epoll1_linux.c
-  src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
-  src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
-  src/core/lib/iomgr/ev_epollex_linux.c
-  src/core/lib/iomgr/ev_epollsig_linux.c
-  src/core/lib/iomgr/ev_poll_posix.c
-  src/core/lib/iomgr/ev_posix.c
-  src/core/lib/iomgr/ev_windows.c
-  src/core/lib/iomgr/exec_ctx.c
-  src/core/lib/iomgr/executor.c
-  src/core/lib/iomgr/iocp_windows.c
-  src/core/lib/iomgr/iomgr.c
-  src/core/lib/iomgr/iomgr_posix.c
-  src/core/lib/iomgr/iomgr_uv.c
-  src/core/lib/iomgr/iomgr_windows.c
-  src/core/lib/iomgr/is_epollexclusive_available.c
-  src/core/lib/iomgr/load_file.c
-  src/core/lib/iomgr/lockfree_event.c
-  src/core/lib/iomgr/network_status_tracker.c
-  src/core/lib/iomgr/polling_entity.c
-  src/core/lib/iomgr/pollset_set_uv.c
-  src/core/lib/iomgr/pollset_set_windows.c
-  src/core/lib/iomgr/pollset_uv.c
-  src/core/lib/iomgr/pollset_windows.c
-  src/core/lib/iomgr/resolve_address_posix.c
-  src/core/lib/iomgr/resolve_address_uv.c
-  src/core/lib/iomgr/resolve_address_windows.c
-  src/core/lib/iomgr/resource_quota.c
-  src/core/lib/iomgr/sockaddr_utils.c
-  src/core/lib/iomgr/socket_factory_posix.c
-  src/core/lib/iomgr/socket_mutator.c
-  src/core/lib/iomgr/socket_utils_common_posix.c
-  src/core/lib/iomgr/socket_utils_linux.c
-  src/core/lib/iomgr/socket_utils_posix.c
-  src/core/lib/iomgr/socket_utils_uv.c
-  src/core/lib/iomgr/socket_utils_windows.c
-  src/core/lib/iomgr/socket_windows.c
-  src/core/lib/iomgr/tcp_client_posix.c
-  src/core/lib/iomgr/tcp_client_uv.c
-  src/core/lib/iomgr/tcp_client_windows.c
-  src/core/lib/iomgr/tcp_posix.c
-  src/core/lib/iomgr/tcp_server_posix.c
-  src/core/lib/iomgr/tcp_server_utils_posix_common.c
-  src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c
-  src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c
-  src/core/lib/iomgr/tcp_server_uv.c
-  src/core/lib/iomgr/tcp_server_windows.c
-  src/core/lib/iomgr/tcp_uv.c
-  src/core/lib/iomgr/tcp_windows.c
-  src/core/lib/iomgr/time_averaged_stats.c
-  src/core/lib/iomgr/timer_generic.c
-  src/core/lib/iomgr/timer_heap.c
-  src/core/lib/iomgr/timer_manager.c
-  src/core/lib/iomgr/timer_uv.c
-  src/core/lib/iomgr/udp_server.c
-  src/core/lib/iomgr/unix_sockets_posix.c
-  src/core/lib/iomgr/unix_sockets_posix_noop.c
-  src/core/lib/iomgr/wakeup_fd_cv.c
-  src/core/lib/iomgr/wakeup_fd_eventfd.c
-  src/core/lib/iomgr/wakeup_fd_nospecial.c
-  src/core/lib/iomgr/wakeup_fd_pipe.c
-  src/core/lib/iomgr/wakeup_fd_posix.c
-  src/core/lib/iomgr/workqueue_uv.c
-  src/core/lib/iomgr/workqueue_windows.c
-  src/core/lib/json/json.c
-  src/core/lib/json/json_reader.c
-  src/core/lib/json/json_string.c
-  src/core/lib/json/json_writer.c
-  src/core/lib/slice/b64.c
-  src/core/lib/slice/percent_encoding.c
-  src/core/lib/slice/slice.c
-  src/core/lib/slice/slice_buffer.c
-  src/core/lib/slice/slice_hash_table.c
-  src/core/lib/slice/slice_intern.c
-  src/core/lib/slice/slice_string_helpers.c
-  src/core/lib/surface/alarm.c
-  src/core/lib/surface/api_trace.c
-  src/core/lib/surface/byte_buffer.c
-  src/core/lib/surface/byte_buffer_reader.c
-  src/core/lib/surface/call.c
-  src/core/lib/surface/call_details.c
-  src/core/lib/surface/call_log_batch.c
-  src/core/lib/surface/channel.c
-  src/core/lib/surface/channel_init.c
-  src/core/lib/surface/channel_ping.c
-  src/core/lib/surface/channel_stack_type.c
-  src/core/lib/surface/completion_queue.c
-  src/core/lib/surface/completion_queue_factory.c
-  src/core/lib/surface/event_string.c
-  src/core/lib/surface/lame_client.cc
-  src/core/lib/surface/metadata_array.c
-  src/core/lib/surface/server.c
-  src/core/lib/surface/validate_metadata.c
-  src/core/lib/surface/version.c
-  src/core/lib/transport/bdp_estimator.c
-  src/core/lib/transport/byte_stream.c
-  src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/error_utils.c
-  src/core/lib/transport/metadata.c
-  src/core/lib/transport/metadata_batch.c
-  src/core/lib/transport/pid_controller.c
-  src/core/lib/transport/service_config.c
-  src/core/lib/transport/static_metadata.c
-  src/core/lib/transport/status_conversion.c
-  src/core/lib/transport/timeout_encoding.c
-  src/core/lib/transport/transport.c
-  src/core/lib/transport/transport_op_string.c
-  src/core/lib/debug/trace.c
   third_party/nanopb/pb_common.c
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_encode.c
@@ -2440,7 +2313,6 @@ target_link_libraries(grpc++
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc
-  gpr
 )
 
 foreach(_hdr
@@ -2537,17 +2409,6 @@ foreach(_hdr
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.h
-  include/grpc/grpc.h
-  include/grpc/grpc_posix.h
-  include/grpc/grpc_security_constants.h
-  include/grpc/load_reporting.h
-  include/grpc/slice.h
-  include/grpc/slice_buffer.h
-  include/grpc/status.h
-  include/grpc/support/workaround_list.h
   include/grpc++/impl/codegen/proto_utils.h
   include/grpc++/impl/codegen/config_protobuf.h
 )
@@ -2606,6 +2467,34 @@ add_library(grpc++_cronet
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
+  third_party/nanopb/pb_common.c
+  third_party/nanopb/pb_decode.c
+  third_party/nanopb/pb_encode.c
+  src/cpp/codegen/codegen_init.cc
+  src/core/ext/transport/chttp2/client/insecure/channel_create.c
+  src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
+  src/core/ext/transport/chttp2/client/chttp2_connector.c
+  src/core/ext/transport/chttp2/transport/bin_decoder.c
+  src/core/ext/transport/chttp2/transport/bin_encoder.c
+  src/core/ext/transport/chttp2/transport/chttp2_plugin.c
+  src/core/ext/transport/chttp2/transport/chttp2_transport.c
+  src/core/ext/transport/chttp2/transport/frame_data.c
+  src/core/ext/transport/chttp2/transport/frame_goaway.c
+  src/core/ext/transport/chttp2/transport/frame_ping.c
+  src/core/ext/transport/chttp2/transport/frame_rst_stream.c
+  src/core/ext/transport/chttp2/transport/frame_settings.c
+  src/core/ext/transport/chttp2/transport/frame_window_update.c
+  src/core/ext/transport/chttp2/transport/hpack_encoder.c
+  src/core/ext/transport/chttp2/transport/hpack_parser.c
+  src/core/ext/transport/chttp2/transport/hpack_table.c
+  src/core/ext/transport/chttp2/transport/http2_settings.c
+  src/core/ext/transport/chttp2/transport/huffsyms.c
+  src/core/ext/transport/chttp2/transport/incoming_metadata.c
+  src/core/ext/transport/chttp2/transport/parsing.c
+  src/core/ext/transport/chttp2/transport/stream_lists.c
+  src/core/ext/transport/chttp2/transport/stream_map.c
+  src/core/ext/transport/chttp2/transport/varint.c
+  src/core/ext/transport/chttp2/transport/writing.c
   src/core/lib/channel/channel_args.c
   src/core/lib/channel/channel_stack.c
   src/core/lib/channel/channel_stack_builder.c
@@ -2733,34 +2622,6 @@ add_library(grpc++_cronet
   src/core/lib/transport/transport.c
   src/core/lib/transport/transport_op_string.c
   src/core/lib/debug/trace.c
-  third_party/nanopb/pb_common.c
-  third_party/nanopb/pb_decode.c
-  third_party/nanopb/pb_encode.c
-  src/cpp/codegen/codegen_init.cc
-  src/core/ext/transport/chttp2/client/insecure/channel_create.c
-  src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
-  src/core/ext/transport/chttp2/client/chttp2_connector.c
-  src/core/ext/transport/chttp2/transport/bin_decoder.c
-  src/core/ext/transport/chttp2/transport/bin_encoder.c
-  src/core/ext/transport/chttp2/transport/chttp2_plugin.c
-  src/core/ext/transport/chttp2/transport/chttp2_transport.c
-  src/core/ext/transport/chttp2/transport/frame_data.c
-  src/core/ext/transport/chttp2/transport/frame_goaway.c
-  src/core/ext/transport/chttp2/transport/frame_ping.c
-  src/core/ext/transport/chttp2/transport/frame_rst_stream.c
-  src/core/ext/transport/chttp2/transport/frame_settings.c
-  src/core/ext/transport/chttp2/transport/frame_window_update.c
-  src/core/ext/transport/chttp2/transport/hpack_encoder.c
-  src/core/ext/transport/chttp2/transport/hpack_parser.c
-  src/core/ext/transport/chttp2/transport/hpack_table.c
-  src/core/ext/transport/chttp2/transport/http2_settings.c
-  src/core/ext/transport/chttp2/transport/huffsyms.c
-  src/core/ext/transport/chttp2/transport/incoming_metadata.c
-  src/core/ext/transport/chttp2/transport/parsing.c
-  src/core/ext/transport/chttp2/transport/stream_lists.c
-  src/core/ext/transport/chttp2/transport/stream_map.c
-  src/core/ext/transport/chttp2/transport/varint.c
-  src/core/ext/transport/chttp2/transport/writing.c
   src/core/ext/transport/chttp2/alpn/alpn.c
   src/core/ext/filters/http/client/http_client_filter.c
   src/core/ext/filters/http/http_filters_plugin.c
@@ -2841,6 +2702,7 @@ target_link_libraries(grpc++_cronet
   ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   grpc_cronet
+  grpc
 )
 
 foreach(_hdr
@@ -3383,133 +3245,6 @@ add_library(grpc++_unsecure
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
-  src/core/lib/channel/channel_args.c
-  src/core/lib/channel/channel_stack.c
-  src/core/lib/channel/channel_stack_builder.c
-  src/core/lib/channel/connected_channel.c
-  src/core/lib/channel/handshaker.c
-  src/core/lib/channel/handshaker_factory.c
-  src/core/lib/channel/handshaker_registry.c
-  src/core/lib/compression/compression.c
-  src/core/lib/compression/message_compress.c
-  src/core/lib/http/format_request.c
-  src/core/lib/http/httpcli.c
-  src/core/lib/http/parser.c
-  src/core/lib/iomgr/closure.c
-  src/core/lib/iomgr/combiner.c
-  src/core/lib/iomgr/endpoint.c
-  src/core/lib/iomgr/endpoint_pair_posix.c
-  src/core/lib/iomgr/endpoint_pair_uv.c
-  src/core/lib/iomgr/endpoint_pair_windows.c
-  src/core/lib/iomgr/error.c
-  src/core/lib/iomgr/ev_epoll1_linux.c
-  src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
-  src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
-  src/core/lib/iomgr/ev_epollex_linux.c
-  src/core/lib/iomgr/ev_epollsig_linux.c
-  src/core/lib/iomgr/ev_poll_posix.c
-  src/core/lib/iomgr/ev_posix.c
-  src/core/lib/iomgr/ev_windows.c
-  src/core/lib/iomgr/exec_ctx.c
-  src/core/lib/iomgr/executor.c
-  src/core/lib/iomgr/iocp_windows.c
-  src/core/lib/iomgr/iomgr.c
-  src/core/lib/iomgr/iomgr_posix.c
-  src/core/lib/iomgr/iomgr_uv.c
-  src/core/lib/iomgr/iomgr_windows.c
-  src/core/lib/iomgr/is_epollexclusive_available.c
-  src/core/lib/iomgr/load_file.c
-  src/core/lib/iomgr/lockfree_event.c
-  src/core/lib/iomgr/network_status_tracker.c
-  src/core/lib/iomgr/polling_entity.c
-  src/core/lib/iomgr/pollset_set_uv.c
-  src/core/lib/iomgr/pollset_set_windows.c
-  src/core/lib/iomgr/pollset_uv.c
-  src/core/lib/iomgr/pollset_windows.c
-  src/core/lib/iomgr/resolve_address_posix.c
-  src/core/lib/iomgr/resolve_address_uv.c
-  src/core/lib/iomgr/resolve_address_windows.c
-  src/core/lib/iomgr/resource_quota.c
-  src/core/lib/iomgr/sockaddr_utils.c
-  src/core/lib/iomgr/socket_factory_posix.c
-  src/core/lib/iomgr/socket_mutator.c
-  src/core/lib/iomgr/socket_utils_common_posix.c
-  src/core/lib/iomgr/socket_utils_linux.c
-  src/core/lib/iomgr/socket_utils_posix.c
-  src/core/lib/iomgr/socket_utils_uv.c
-  src/core/lib/iomgr/socket_utils_windows.c
-  src/core/lib/iomgr/socket_windows.c
-  src/core/lib/iomgr/tcp_client_posix.c
-  src/core/lib/iomgr/tcp_client_uv.c
-  src/core/lib/iomgr/tcp_client_windows.c
-  src/core/lib/iomgr/tcp_posix.c
-  src/core/lib/iomgr/tcp_server_posix.c
-  src/core/lib/iomgr/tcp_server_utils_posix_common.c
-  src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c
-  src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c
-  src/core/lib/iomgr/tcp_server_uv.c
-  src/core/lib/iomgr/tcp_server_windows.c
-  src/core/lib/iomgr/tcp_uv.c
-  src/core/lib/iomgr/tcp_windows.c
-  src/core/lib/iomgr/time_averaged_stats.c
-  src/core/lib/iomgr/timer_generic.c
-  src/core/lib/iomgr/timer_heap.c
-  src/core/lib/iomgr/timer_manager.c
-  src/core/lib/iomgr/timer_uv.c
-  src/core/lib/iomgr/udp_server.c
-  src/core/lib/iomgr/unix_sockets_posix.c
-  src/core/lib/iomgr/unix_sockets_posix_noop.c
-  src/core/lib/iomgr/wakeup_fd_cv.c
-  src/core/lib/iomgr/wakeup_fd_eventfd.c
-  src/core/lib/iomgr/wakeup_fd_nospecial.c
-  src/core/lib/iomgr/wakeup_fd_pipe.c
-  src/core/lib/iomgr/wakeup_fd_posix.c
-  src/core/lib/iomgr/workqueue_uv.c
-  src/core/lib/iomgr/workqueue_windows.c
-  src/core/lib/json/json.c
-  src/core/lib/json/json_reader.c
-  src/core/lib/json/json_string.c
-  src/core/lib/json/json_writer.c
-  src/core/lib/slice/b64.c
-  src/core/lib/slice/percent_encoding.c
-  src/core/lib/slice/slice.c
-  src/core/lib/slice/slice_buffer.c
-  src/core/lib/slice/slice_hash_table.c
-  src/core/lib/slice/slice_intern.c
-  src/core/lib/slice/slice_string_helpers.c
-  src/core/lib/surface/alarm.c
-  src/core/lib/surface/api_trace.c
-  src/core/lib/surface/byte_buffer.c
-  src/core/lib/surface/byte_buffer_reader.c
-  src/core/lib/surface/call.c
-  src/core/lib/surface/call_details.c
-  src/core/lib/surface/call_log_batch.c
-  src/core/lib/surface/channel.c
-  src/core/lib/surface/channel_init.c
-  src/core/lib/surface/channel_ping.c
-  src/core/lib/surface/channel_stack_type.c
-  src/core/lib/surface/completion_queue.c
-  src/core/lib/surface/completion_queue_factory.c
-  src/core/lib/surface/event_string.c
-  src/core/lib/surface/lame_client.cc
-  src/core/lib/surface/metadata_array.c
-  src/core/lib/surface/server.c
-  src/core/lib/surface/validate_metadata.c
-  src/core/lib/surface/version.c
-  src/core/lib/transport/bdp_estimator.c
-  src/core/lib/transport/byte_stream.c
-  src/core/lib/transport/connectivity_state.c
-  src/core/lib/transport/error_utils.c
-  src/core/lib/transport/metadata.c
-  src/core/lib/transport/metadata_batch.c
-  src/core/lib/transport/pid_controller.c
-  src/core/lib/transport/service_config.c
-  src/core/lib/transport/static_metadata.c
-  src/core/lib/transport/status_conversion.c
-  src/core/lib/transport/timeout_encoding.c
-  src/core/lib/transport/transport.c
-  src/core/lib/transport/transport_op_string.c
-  src/core/lib/debug/trace.c
   third_party/nanopb/pb_common.c
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_encode.c
@@ -3550,6 +3285,7 @@ target_link_libraries(grpc++_unsecure
   ${_gRPC_ALLTARGETS_LIBRARIES}
   gpr
   grpc_unsecure
+  grpc
 )
 
 foreach(_hdr
@@ -3646,17 +3382,6 @@ foreach(_hdr
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.h
-  include/grpc/grpc.h
-  include/grpc/grpc_posix.h
-  include/grpc/grpc_security_constants.h
-  include/grpc/load_reporting.h
-  include/grpc/slice.h
-  include/grpc/slice_buffer.h
-  include/grpc/status.h
-  include/grpc/support/workaround_list.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
   get_filename_component(_path ${_path} PATH)

+ 43 - 319
Makefile

@@ -4196,133 +4196,6 @@ LIBGRPC++_SRC = \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
-    src/core/lib/channel/channel_args.c \
-    src/core/lib/channel/channel_stack.c \
-    src/core/lib/channel/channel_stack_builder.c \
-    src/core/lib/channel/connected_channel.c \
-    src/core/lib/channel/handshaker.c \
-    src/core/lib/channel/handshaker_factory.c \
-    src/core/lib/channel/handshaker_registry.c \
-    src/core/lib/compression/compression.c \
-    src/core/lib/compression/message_compress.c \
-    src/core/lib/http/format_request.c \
-    src/core/lib/http/httpcli.c \
-    src/core/lib/http/parser.c \
-    src/core/lib/iomgr/closure.c \
-    src/core/lib/iomgr/combiner.c \
-    src/core/lib/iomgr/endpoint.c \
-    src/core/lib/iomgr/endpoint_pair_posix.c \
-    src/core/lib/iomgr/endpoint_pair_uv.c \
-    src/core/lib/iomgr/endpoint_pair_windows.c \
-    src/core/lib/iomgr/error.c \
-    src/core/lib/iomgr/ev_epoll1_linux.c \
-    src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
-    src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
-    src/core/lib/iomgr/ev_epollex_linux.c \
-    src/core/lib/iomgr/ev_epollsig_linux.c \
-    src/core/lib/iomgr/ev_poll_posix.c \
-    src/core/lib/iomgr/ev_posix.c \
-    src/core/lib/iomgr/ev_windows.c \
-    src/core/lib/iomgr/exec_ctx.c \
-    src/core/lib/iomgr/executor.c \
-    src/core/lib/iomgr/iocp_windows.c \
-    src/core/lib/iomgr/iomgr.c \
-    src/core/lib/iomgr/iomgr_posix.c \
-    src/core/lib/iomgr/iomgr_uv.c \
-    src/core/lib/iomgr/iomgr_windows.c \
-    src/core/lib/iomgr/is_epollexclusive_available.c \
-    src/core/lib/iomgr/load_file.c \
-    src/core/lib/iomgr/lockfree_event.c \
-    src/core/lib/iomgr/network_status_tracker.c \
-    src/core/lib/iomgr/polling_entity.c \
-    src/core/lib/iomgr/pollset_set_uv.c \
-    src/core/lib/iomgr/pollset_set_windows.c \
-    src/core/lib/iomgr/pollset_uv.c \
-    src/core/lib/iomgr/pollset_windows.c \
-    src/core/lib/iomgr/resolve_address_posix.c \
-    src/core/lib/iomgr/resolve_address_uv.c \
-    src/core/lib/iomgr/resolve_address_windows.c \
-    src/core/lib/iomgr/resource_quota.c \
-    src/core/lib/iomgr/sockaddr_utils.c \
-    src/core/lib/iomgr/socket_factory_posix.c \
-    src/core/lib/iomgr/socket_mutator.c \
-    src/core/lib/iomgr/socket_utils_common_posix.c \
-    src/core/lib/iomgr/socket_utils_linux.c \
-    src/core/lib/iomgr/socket_utils_posix.c \
-    src/core/lib/iomgr/socket_utils_uv.c \
-    src/core/lib/iomgr/socket_utils_windows.c \
-    src/core/lib/iomgr/socket_windows.c \
-    src/core/lib/iomgr/tcp_client_posix.c \
-    src/core/lib/iomgr/tcp_client_uv.c \
-    src/core/lib/iomgr/tcp_client_windows.c \
-    src/core/lib/iomgr/tcp_posix.c \
-    src/core/lib/iomgr/tcp_server_posix.c \
-    src/core/lib/iomgr/tcp_server_utils_posix_common.c \
-    src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \
-    src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \
-    src/core/lib/iomgr/tcp_server_uv.c \
-    src/core/lib/iomgr/tcp_server_windows.c \
-    src/core/lib/iomgr/tcp_uv.c \
-    src/core/lib/iomgr/tcp_windows.c \
-    src/core/lib/iomgr/time_averaged_stats.c \
-    src/core/lib/iomgr/timer_generic.c \
-    src/core/lib/iomgr/timer_heap.c \
-    src/core/lib/iomgr/timer_manager.c \
-    src/core/lib/iomgr/timer_uv.c \
-    src/core/lib/iomgr/udp_server.c \
-    src/core/lib/iomgr/unix_sockets_posix.c \
-    src/core/lib/iomgr/unix_sockets_posix_noop.c \
-    src/core/lib/iomgr/wakeup_fd_cv.c \
-    src/core/lib/iomgr/wakeup_fd_eventfd.c \
-    src/core/lib/iomgr/wakeup_fd_nospecial.c \
-    src/core/lib/iomgr/wakeup_fd_pipe.c \
-    src/core/lib/iomgr/wakeup_fd_posix.c \
-    src/core/lib/iomgr/workqueue_uv.c \
-    src/core/lib/iomgr/workqueue_windows.c \
-    src/core/lib/json/json.c \
-    src/core/lib/json/json_reader.c \
-    src/core/lib/json/json_string.c \
-    src/core/lib/json/json_writer.c \
-    src/core/lib/slice/b64.c \
-    src/core/lib/slice/percent_encoding.c \
-    src/core/lib/slice/slice.c \
-    src/core/lib/slice/slice_buffer.c \
-    src/core/lib/slice/slice_hash_table.c \
-    src/core/lib/slice/slice_intern.c \
-    src/core/lib/slice/slice_string_helpers.c \
-    src/core/lib/surface/alarm.c \
-    src/core/lib/surface/api_trace.c \
-    src/core/lib/surface/byte_buffer.c \
-    src/core/lib/surface/byte_buffer_reader.c \
-    src/core/lib/surface/call.c \
-    src/core/lib/surface/call_details.c \
-    src/core/lib/surface/call_log_batch.c \
-    src/core/lib/surface/channel.c \
-    src/core/lib/surface/channel_init.c \
-    src/core/lib/surface/channel_ping.c \
-    src/core/lib/surface/channel_stack_type.c \
-    src/core/lib/surface/completion_queue.c \
-    src/core/lib/surface/completion_queue_factory.c \
-    src/core/lib/surface/event_string.c \
-    src/core/lib/surface/lame_client.cc \
-    src/core/lib/surface/metadata_array.c \
-    src/core/lib/surface/server.c \
-    src/core/lib/surface/validate_metadata.c \
-    src/core/lib/surface/version.c \
-    src/core/lib/transport/bdp_estimator.c \
-    src/core/lib/transport/byte_stream.c \
-    src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/error_utils.c \
-    src/core/lib/transport/metadata.c \
-    src/core/lib/transport/metadata_batch.c \
-    src/core/lib/transport/pid_controller.c \
-    src/core/lib/transport/service_config.c \
-    src/core/lib/transport/static_metadata.c \
-    src/core/lib/transport/status_conversion.c \
-    src/core/lib/transport/timeout_encoding.c \
-    src/core/lib/transport/transport.c \
-    src/core/lib/transport/transport_op_string.c \
-    src/core/lib/debug/trace.c \
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
@@ -4422,17 +4295,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.h \
-    include/grpc/grpc.h \
-    include/grpc/grpc_posix.h \
-    include/grpc/grpc_security_constants.h \
-    include/grpc/load_reporting.h \
-    include/grpc/slice.h \
-    include/grpc/slice_buffer.h \
-    include/grpc/status.h \
-    include/grpc/support/workaround_list.h \
     include/grpc++/impl/codegen/proto_utils.h \
     include/grpc++/impl/codegen/config_protobuf.h \
 
@@ -4471,18 +4333,18 @@ endif
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll -lgpr$(SHARED_VERSION_CORE)-dll
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll
 else
-$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc -lgpr
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
 endif
@@ -4537,6 +4399,34 @@ LIBGRPC++_CRONET_SRC = \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
+    third_party/nanopb/pb_common.c \
+    third_party/nanopb/pb_decode.c \
+    third_party/nanopb/pb_encode.c \
+    src/cpp/codegen/codegen_init.cc \
+    src/core/ext/transport/chttp2/client/insecure/channel_create.c \
+    src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
+    src/core/ext/transport/chttp2/client/chttp2_connector.c \
+    src/core/ext/transport/chttp2/transport/bin_decoder.c \
+    src/core/ext/transport/chttp2/transport/bin_encoder.c \
+    src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
+    src/core/ext/transport/chttp2/transport/chttp2_transport.c \
+    src/core/ext/transport/chttp2/transport/frame_data.c \
+    src/core/ext/transport/chttp2/transport/frame_goaway.c \
+    src/core/ext/transport/chttp2/transport/frame_ping.c \
+    src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
+    src/core/ext/transport/chttp2/transport/frame_settings.c \
+    src/core/ext/transport/chttp2/transport/frame_window_update.c \
+    src/core/ext/transport/chttp2/transport/hpack_encoder.c \
+    src/core/ext/transport/chttp2/transport/hpack_parser.c \
+    src/core/ext/transport/chttp2/transport/hpack_table.c \
+    src/core/ext/transport/chttp2/transport/http2_settings.c \
+    src/core/ext/transport/chttp2/transport/huffsyms.c \
+    src/core/ext/transport/chttp2/transport/incoming_metadata.c \
+    src/core/ext/transport/chttp2/transport/parsing.c \
+    src/core/ext/transport/chttp2/transport/stream_lists.c \
+    src/core/ext/transport/chttp2/transport/stream_map.c \
+    src/core/ext/transport/chttp2/transport/varint.c \
+    src/core/ext/transport/chttp2/transport/writing.c \
     src/core/lib/channel/channel_args.c \
     src/core/lib/channel/channel_stack.c \
     src/core/lib/channel/channel_stack_builder.c \
@@ -4664,34 +4554,6 @@ LIBGRPC++_CRONET_SRC = \
     src/core/lib/transport/transport.c \
     src/core/lib/transport/transport_op_string.c \
     src/core/lib/debug/trace.c \
-    third_party/nanopb/pb_common.c \
-    third_party/nanopb/pb_decode.c \
-    third_party/nanopb/pb_encode.c \
-    src/cpp/codegen/codegen_init.cc \
-    src/core/ext/transport/chttp2/client/insecure/channel_create.c \
-    src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
-    src/core/ext/transport/chttp2/client/chttp2_connector.c \
-    src/core/ext/transport/chttp2/transport/bin_decoder.c \
-    src/core/ext/transport/chttp2/transport/bin_encoder.c \
-    src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
-    src/core/ext/transport/chttp2/transport/chttp2_transport.c \
-    src/core/ext/transport/chttp2/transport/frame_data.c \
-    src/core/ext/transport/chttp2/transport/frame_goaway.c \
-    src/core/ext/transport/chttp2/transport/frame_ping.c \
-    src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
-    src/core/ext/transport/chttp2/transport/frame_settings.c \
-    src/core/ext/transport/chttp2/transport/frame_window_update.c \
-    src/core/ext/transport/chttp2/transport/hpack_encoder.c \
-    src/core/ext/transport/chttp2/transport/hpack_parser.c \
-    src/core/ext/transport/chttp2/transport/hpack_table.c \
-    src/core/ext/transport/chttp2/transport/http2_settings.c \
-    src/core/ext/transport/chttp2/transport/huffsyms.c \
-    src/core/ext/transport/chttp2/transport/incoming_metadata.c \
-    src/core/ext/transport/chttp2/transport/parsing.c \
-    src/core/ext/transport/chttp2/transport/stream_lists.c \
-    src/core/ext/transport/chttp2/transport/stream_map.c \
-    src/core/ext/transport/chttp2/transport/varint.c \
-    src/core/ext/transport/chttp2/transport/writing.c \
     src/core/ext/transport/chttp2/alpn/alpn.c \
     src/core/ext/filters/http/client/http_client_filter.c \
     src/core/ext/filters/http/http_filters_plugin.c \
@@ -4878,18 +4740,18 @@ endif
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll -lgrpc$(SHARED_VERSION_CORE)-dll
 else
-$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
+$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet -lgrpc
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet -lgrpc
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
 endif
@@ -5304,133 +5166,6 @@ LIBGRPC++_UNSECURE_SRC = \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
-    src/core/lib/channel/channel_args.c \
-    src/core/lib/channel/channel_stack.c \
-    src/core/lib/channel/channel_stack_builder.c \
-    src/core/lib/channel/connected_channel.c \
-    src/core/lib/channel/handshaker.c \
-    src/core/lib/channel/handshaker_factory.c \
-    src/core/lib/channel/handshaker_registry.c \
-    src/core/lib/compression/compression.c \
-    src/core/lib/compression/message_compress.c \
-    src/core/lib/http/format_request.c \
-    src/core/lib/http/httpcli.c \
-    src/core/lib/http/parser.c \
-    src/core/lib/iomgr/closure.c \
-    src/core/lib/iomgr/combiner.c \
-    src/core/lib/iomgr/endpoint.c \
-    src/core/lib/iomgr/endpoint_pair_posix.c \
-    src/core/lib/iomgr/endpoint_pair_uv.c \
-    src/core/lib/iomgr/endpoint_pair_windows.c \
-    src/core/lib/iomgr/error.c \
-    src/core/lib/iomgr/ev_epoll1_linux.c \
-    src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \
-    src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \
-    src/core/lib/iomgr/ev_epollex_linux.c \
-    src/core/lib/iomgr/ev_epollsig_linux.c \
-    src/core/lib/iomgr/ev_poll_posix.c \
-    src/core/lib/iomgr/ev_posix.c \
-    src/core/lib/iomgr/ev_windows.c \
-    src/core/lib/iomgr/exec_ctx.c \
-    src/core/lib/iomgr/executor.c \
-    src/core/lib/iomgr/iocp_windows.c \
-    src/core/lib/iomgr/iomgr.c \
-    src/core/lib/iomgr/iomgr_posix.c \
-    src/core/lib/iomgr/iomgr_uv.c \
-    src/core/lib/iomgr/iomgr_windows.c \
-    src/core/lib/iomgr/is_epollexclusive_available.c \
-    src/core/lib/iomgr/load_file.c \
-    src/core/lib/iomgr/lockfree_event.c \
-    src/core/lib/iomgr/network_status_tracker.c \
-    src/core/lib/iomgr/polling_entity.c \
-    src/core/lib/iomgr/pollset_set_uv.c \
-    src/core/lib/iomgr/pollset_set_windows.c \
-    src/core/lib/iomgr/pollset_uv.c \
-    src/core/lib/iomgr/pollset_windows.c \
-    src/core/lib/iomgr/resolve_address_posix.c \
-    src/core/lib/iomgr/resolve_address_uv.c \
-    src/core/lib/iomgr/resolve_address_windows.c \
-    src/core/lib/iomgr/resource_quota.c \
-    src/core/lib/iomgr/sockaddr_utils.c \
-    src/core/lib/iomgr/socket_factory_posix.c \
-    src/core/lib/iomgr/socket_mutator.c \
-    src/core/lib/iomgr/socket_utils_common_posix.c \
-    src/core/lib/iomgr/socket_utils_linux.c \
-    src/core/lib/iomgr/socket_utils_posix.c \
-    src/core/lib/iomgr/socket_utils_uv.c \
-    src/core/lib/iomgr/socket_utils_windows.c \
-    src/core/lib/iomgr/socket_windows.c \
-    src/core/lib/iomgr/tcp_client_posix.c \
-    src/core/lib/iomgr/tcp_client_uv.c \
-    src/core/lib/iomgr/tcp_client_windows.c \
-    src/core/lib/iomgr/tcp_posix.c \
-    src/core/lib/iomgr/tcp_server_posix.c \
-    src/core/lib/iomgr/tcp_server_utils_posix_common.c \
-    src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.c \
-    src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.c \
-    src/core/lib/iomgr/tcp_server_uv.c \
-    src/core/lib/iomgr/tcp_server_windows.c \
-    src/core/lib/iomgr/tcp_uv.c \
-    src/core/lib/iomgr/tcp_windows.c \
-    src/core/lib/iomgr/time_averaged_stats.c \
-    src/core/lib/iomgr/timer_generic.c \
-    src/core/lib/iomgr/timer_heap.c \
-    src/core/lib/iomgr/timer_manager.c \
-    src/core/lib/iomgr/timer_uv.c \
-    src/core/lib/iomgr/udp_server.c \
-    src/core/lib/iomgr/unix_sockets_posix.c \
-    src/core/lib/iomgr/unix_sockets_posix_noop.c \
-    src/core/lib/iomgr/wakeup_fd_cv.c \
-    src/core/lib/iomgr/wakeup_fd_eventfd.c \
-    src/core/lib/iomgr/wakeup_fd_nospecial.c \
-    src/core/lib/iomgr/wakeup_fd_pipe.c \
-    src/core/lib/iomgr/wakeup_fd_posix.c \
-    src/core/lib/iomgr/workqueue_uv.c \
-    src/core/lib/iomgr/workqueue_windows.c \
-    src/core/lib/json/json.c \
-    src/core/lib/json/json_reader.c \
-    src/core/lib/json/json_string.c \
-    src/core/lib/json/json_writer.c \
-    src/core/lib/slice/b64.c \
-    src/core/lib/slice/percent_encoding.c \
-    src/core/lib/slice/slice.c \
-    src/core/lib/slice/slice_buffer.c \
-    src/core/lib/slice/slice_hash_table.c \
-    src/core/lib/slice/slice_intern.c \
-    src/core/lib/slice/slice_string_helpers.c \
-    src/core/lib/surface/alarm.c \
-    src/core/lib/surface/api_trace.c \
-    src/core/lib/surface/byte_buffer.c \
-    src/core/lib/surface/byte_buffer_reader.c \
-    src/core/lib/surface/call.c \
-    src/core/lib/surface/call_details.c \
-    src/core/lib/surface/call_log_batch.c \
-    src/core/lib/surface/channel.c \
-    src/core/lib/surface/channel_init.c \
-    src/core/lib/surface/channel_ping.c \
-    src/core/lib/surface/channel_stack_type.c \
-    src/core/lib/surface/completion_queue.c \
-    src/core/lib/surface/completion_queue_factory.c \
-    src/core/lib/surface/event_string.c \
-    src/core/lib/surface/lame_client.cc \
-    src/core/lib/surface/metadata_array.c \
-    src/core/lib/surface/server.c \
-    src/core/lib/surface/validate_metadata.c \
-    src/core/lib/surface/version.c \
-    src/core/lib/transport/bdp_estimator.c \
-    src/core/lib/transport/byte_stream.c \
-    src/core/lib/transport/connectivity_state.c \
-    src/core/lib/transport/error_utils.c \
-    src/core/lib/transport/metadata.c \
-    src/core/lib/transport/metadata_batch.c \
-    src/core/lib/transport/pid_controller.c \
-    src/core/lib/transport/service_config.c \
-    src/core/lib/transport/static_metadata.c \
-    src/core/lib/transport/status_conversion.c \
-    src/core/lib/transport/timeout_encoding.c \
-    src/core/lib/transport/transport.c \
-    src/core/lib/transport/transport_op_string.c \
-    src/core/lib/debug/trace.c \
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
@@ -5530,17 +5265,6 @@ PUBLIC_HEADERS_CXX += \
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.h \
-    include/grpc/grpc.h \
-    include/grpc/grpc_posix.h \
-    include/grpc/grpc_security_constants.h \
-    include/grpc/load_reporting.h \
-    include/grpc/slice.h \
-    include/grpc/slice_buffer.h \
-    include/grpc/status.h \
-    include/grpc/support/workaround_list.h \
 
 LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC))))
 
@@ -5567,18 +5291,18 @@ endif
 
 
 ifeq ($(SYSTEM),MINGW32)
-$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
+$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll -lgrpc$(SHARED_VERSION_CORE)-dll
 else
-$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE)
+$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS)  $(ZLIB_DEP) $(CARES_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE)
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
 ifeq ($(SYSTEM),Darwin)
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure -lgrpc
 else
-	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
+	$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure -lgrpc
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
 endif

+ 1 - 0
Rakefile

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

+ 3 - 2
build.yaml

@@ -960,9 +960,10 @@ filegroups:
   - src/cpp/util/status.cc
   - src/cpp/util/string_ref.cc
   - src/cpp/util/time_cc.cc
+  deps:
+  - grpc
   uses:
   - grpc++_codegen_base
-  - grpc_base
   - nanopb
 - name: grpc++_codegen_base
   language: c++
@@ -4628,8 +4629,8 @@ php_config_m4:
   deps:
   - grpc
   - gpr
-  - ares
   - boringssl
+  - z
   headers:
   - src/php/ext/grpc/byte_buffer.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()/src/php/ext/grpc)
   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"
 
@@ -23,10 +21,8 @@ if test "$PHP_GRPC" != "no"; then
 
   case $host in
     *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)
       ;;
@@ -641,58 +637,9 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl/ssl/tls13_server.c \
     third_party/boringssl/ssl/tls_method.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 \
     -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)
 
@@ -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/x509v3)
   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)
 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
   * e.g. application/grpc-web+[proto, json, thrift]
+  * the sender should always specify the message format, e.g. +proto, +json
+  * the receiver should assume the default is "+proto" when the message format is missing in Content-Type (as "application/grpc-web")
 2. application/grpc-web-text
   * text-encoded streams of “application/grpc-web”
   * e.g. application/grpc-web-text+[proto, thrift]

+ 1 - 0
grpc.def

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

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

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

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

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

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

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

+ 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_;
 };
 
-/// Add proto reflection plugin to ServerBuilder. This function should be called
-/// at the static initialization time.
+/// Add proto reflection plugin to \a ServerBuilder.
+/// This function should be called at the static initialization time.
 void InitProtoReflectionServerBuilderPlugin();
 
 }  // namespace reflection

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

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

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

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

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

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

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

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

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

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

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

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

+ 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.
 /// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
 /// (JWT) created with this credentials. It should not exceed
-/// grpc_max_auth_token_lifetime or will be cropped to this value.
+/// \a grpc_max_auth_token_lifetime or will be cropped to this value.
 std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
     const grpc::string& json_key, long token_lifetime_seconds);
 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 1 - 1
package.json

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

+ 52 - 78
package.xml

@@ -10,7 +10,7 @@
   <email>grpc-packages@google.com</email>
   <active>yes</active>
  </lead>
- <date>2017-03-01</date>
+ <date>2017-05-22</date>
  <time>16:06:07</time>
  <version>
   <release>1.4.0dev</release>
@@ -22,15 +22,19 @@
  </stability>
  <license>BSD</license>
  <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>
  <contents>
   <dir baseinstalldir="/" name="/">
     <file baseinstalldir="/" name="config.m4" role="src" />
+    <file baseinstalldir="/" name="config.w32" role="src" />
     <file baseinstalldir="/" name="src/php/README.md" role="src" />
-    <file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
-    <file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
     <file baseinstalldir="/" name="src/php/ext/grpc/byte_buffer.c" role="src" />
     <file baseinstalldir="/" name="src/php/ext/grpc/call.c" role="src" />
     <file baseinstalldir="/" name="src/php/ext/grpc/call_credentials.c" role="src" />
@@ -1058,79 +1062,33 @@
     <file baseinstalldir="/" name="third_party/boringssl/ssl/tls13_server.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/tls_method.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/ssl/tls_record.c" role="src" />
-    <file baseinstalldir="/" name="third_party/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>
  </contents>
  <dependencies>
@@ -1443,6 +1401,22 @@ Update to wrap gRPC C Core version 0.10.0
    <license>BSD</license>
    <notes>
 - 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
    </notes>
   </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["output_type_id"] = MessageIdentifierName(output_type->full_name());
 
-  out->Print("/**\n");
-  out->Print(GetPHPComments(method, " *").c_str());
+  out->Print(GetPHPComments(method, " //").c_str());
   if (method->client_streaming()) {
     out->Print(vars,
-               " * @param array $$metadata metadata\n"
-               " * @param array $$options call options\n */\n"
+               " // @param array $$metadata metadata\n"
+               " // @param array $$options call options\n"
                "public function $name$($$metadata = [], "
                "$$options = []) {\n");
     out->Indent();
@@ -87,9 +86,9 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
                "$$metadata, $$options);\n");
   } else {
     out->Print(vars,
-               " * @param \\$input_type_id$ $$argument input argument\n"
-               " * @param array $$metadata metadata\n"
-               " * @param array $$options call options\n */\n"
+               " // @param \\$input_type_id$ $$argument input argument\n"
+               " // @param array $$metadata metadata\n"
+               " // @param array $$options call options\n"
                "public function $name$(\\$input_type_id$ $$argument,\n"
                "  $$metadata = [], $$options = []) {\n");
     out->Indent();
@@ -116,10 +115,10 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
   out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n");
   out->Indent();
   out->Print(
-      "/**\n * @param string $$hostname hostname\n"
-      " * @param array $$opts channel options\n"
-      " * @param \\Grpc\\Channel $$channel (optional) re-use channel "
-      "object\n */\n"
+      " // @param string $$hostname hostname\n"
+      " // @param array $$opts channel options\n"
+      " // @param \\Grpc\\Channel $$channel (optional) re-use channel "
+      "object\n"
       "public function __construct($$hostname, $$opts, "
       "$$channel = null) {\n");
   out->Indent();

+ 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,
                                            chand->interested_parties);
   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,
-                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) {
     /* already cancelled before subchannel became ready */
     grpc_error *cancellation_error =
@@ -1180,6 +1183,15 @@ static void start_transport_stream_op_batch_locked_inner(
             &calld->next_step)) {
       calld->pick_pending = false;
       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 {
       grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
                                              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.
 
-    \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
     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

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

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

+ 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. */
 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 */

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

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

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

+ 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_resolved_addresses **addresses);
 
+void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
+                          const char *addr, const char *default_port,
+                          grpc_pollset_set *interested_parties,
+                          grpc_closure *on_done,
+                          grpc_resolved_addresses **addresses);
+
 /* Initialize gRPC ares wrapper. Must be called at least once before
    grpc_resolve_address_ares(). */
 grpc_error *grpc_ares_init(void);

+ 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,
                        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)bdp -
       (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,
                (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,
@@ -2280,6 +2292,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
       }
 
       int64_t estimate = -1;
+      double bdp_guess = -1;
       if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
         double target = 1 + log2((double)estimate);
         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 =
             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;
       }
+
+      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");
   } else {

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

@@ -56,6 +56,8 @@ struct grpc_tcp_listener {
   int port;
   /* linked list */
   struct grpc_tcp_listener *next;
+
+  bool closed;
 };
 
 struct grpc_tcp_server {
@@ -77,6 +79,8 @@ struct grpc_tcp_server {
   /* shutdown callback */
   grpc_closure *shutdown_complete;
 
+  bool shutdown;
+
   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.tail = NULL;
   s->shutdown_complete = shutdown_complete;
+  s->shutdown = false;
   *server = s;
   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) {
+  GPR_ASSERT(s->shutdown);
   if (s->shutdown_complete != NULL) {
     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_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   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);
   }
   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) {
   int immediately_done = 0;
   grpc_tcp_listener *sp;
 
+  GPR_ASSERT(!s->shutdown);
+  s->shutdown = true;
+
   if (s->open_ports == 0) {
     immediately_done = 1;
   }
   for (sp = s->head; sp; sp = sp->next) {
-    uv_close((uv_handle_t *)sp->handle, handle_close_callback);
+    close_listener(sp);
   }
 
   if (immediately_done) {
@@ -196,9 +212,14 @@ static void on_connect(uv_stream_t *server, int status) {
   int err;
 
   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));
@@ -287,6 +308,7 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, uv_tcp_t *handle,
   sp->handle = handle;
   sp->port = port;
   sp->port_index = port_index;
+  sp->closed = false;
   handle->data = sp;
   s->open_ports++;
   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
 #define TCP_UNREF(exec_ctx, tcp, reason) \
   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,
                       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)) {
     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,
                     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);
 }
 #else
@@ -311,6 +312,7 @@ static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
     tcp->shutting_down = true;
     uv_shutdown_t *req = &tcp->shutdown_req;
     uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
+    grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
   }
   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);
 
 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->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));
   }
 
-  a = gpr_zalloc(sizeof(arg));
+  a = (arg *)gpr_zalloc(sizeof(arg));
   a->name = name;
   a->help = help;
   a->type = type;
@@ -302,7 +302,7 @@ static int normal_state(gpr_cmdline *cl, char *str) {
     eq = strchr(str, '=');
     if (eq != NULL) {
       /* 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));
       arg_name[eq - str] = 0;
     } 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,
                                     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(max_bucket_start > resolution);
   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;
   GPR_ASSERT(h->num_buckets > 1);
   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;
 }
 

+ 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. */
-  *host = gpr_malloc(host_len + 1);
+  *host = (char *)gpr_malloc(host_len + 1);
   memcpy(*host, host_start, host_len);
   (*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;
-  dst = gpr_malloc(len);
+  dst = (char *)gpr_malloc(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) {
   if (out->length == 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;
 }
 
 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 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) {
   uint32_t out = 0;
-  uint32_t new;
+  uint32_t new_val;
   size_t i;
 
   if (len == 0) return 0; /* must have some bytes */
 
   for (i = 0; i < len; i++) {
     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;
@@ -201,7 +201,7 @@ int gpr_parse_nonnegative_int(const char *value) {
 char *gpr_leftpad(const char *str, char flag, size_t length) {
   const size_t str_length = strlen(str);
   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);
   memcpy(out + out_length - str_length, str, str_length);
   out[out_length] = 0;
@@ -225,7 +225,7 @@ char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep,
   if (nstrs > 0) {
     out_length += sep_len * (nstrs - 1); /* separators */
   }
-  out = gpr_malloc(out_length);
+  out = (char *)gpr_malloc(out_length);
   out_length = 0;
   for (i = 0; i < nstrs; 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) {
   if (sv->count == sv->capacity) {
     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;
 }
@@ -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,
                                 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));
   out[end - beg] = 0;
   if (*nstrs == *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;
   ++*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. */
   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(). */
     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) {
     return NULL;
   } 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 *));
     exec_args[argc] = NULL;
     execv(exec_args[0], exec_args);
@@ -76,7 +76,7 @@ gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
     _exit(1);
     return NULL;
   } else {
-    r = gpr_zalloc(sizeof(gpr_subprocess));
+    r = (gpr_subprocess *)gpr_zalloc(sizeof(gpr_subprocess));
     r->pid = pid;
     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;
   /* don't use gpr_malloc as we may cause an infinite recursion with
    * the profiling code */
-  struct thd_arg *a = malloc(sizeof(*a));
+  struct thd_arg *a = (struct thd_arg *)malloc(sizeof(*a));
   GPR_ASSERT(a != NULL);
   a->body = thd_body;
   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;
 }
 
+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,
                                            int64_t 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
 bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
                                      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
 bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
                                            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() {
+  for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
+    (*plugin)->UpdateServerBuilder(this);
+  }
+
   ChannelArguments args;
   for (auto option = options_.begin(); option != options_.end(); ++option) {
     (*option)->UpdateArguments(&args);

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

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

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

@@ -117,7 +117,7 @@ namespace Grpc.Core.Internal
             {
                 var ctx = BatchContextSafeHandle.Create();
                 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;
                 completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
                 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();
             }
         }

+ 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,
                 BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
             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,
                 BatchContextSafeHandle ctx);
             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);
             public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
                 BatchContextSafeHandle ctx);
@@ -406,7 +406,7 @@ namespace Grpc.Core.Internal
             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 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 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,
                                                                   keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
                                                                   new UIntPtr((ulong)keyCertPairCertChainArray.Length),
-                                                                  forceClientAuth);
+                                                                  forceClientAuth ? 1 : 0);
         }
 
         protected override bool ReleaseHandle()

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

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

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

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

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

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

+ 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
 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.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
 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.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
  * - longsAsStrings: deserialize long values as strings instead of objects.
  *   Defaults to true
- * - enumsAsStrings: deserialize enum values as strings instead of numbers.
- *   Defaults to true
  * - deprecatedArgumentOrder: Use the beta method argument order for client
  *   methods, with optional arguments after the callback. Defaults to false.
  *   This option is only a temporary stopgap measure to smooth an API breakage.
@@ -105,10 +103,6 @@ exports.loadObject = function loadObject(value, options) {
   switch (protobufjsVersion) {
     case 6: return protobuf_js_6_common.loadObject(value, options);
     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);
     default:
     throw new Error('Unrecognized protobufjsVersion', protobufjsVersion);
@@ -117,19 +111,6 @@ exports.loadObject = function loadObject(value, options) {
 
 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
  * following options:
@@ -139,8 +120,6 @@ function applyProtoRoot(filename, root) {
  *   Buffers. Defaults to false
  * - longsAsStrings: deserialize long values as strings instead of objects.
  *   Defaults to true
- * - enumsAsStrings: deserialize enum values as strings instead of numbers.
- *   Defaults to true
  * - deprecatedArgumentOrder: Use the beta method argument order for client
  *   methods, with optional arguments after the callback. Defaults to false.
  *   This option is only a temporary stopgap measure to smooth an API breakage.
@@ -152,17 +131,31 @@ function applyProtoRoot(filename, root) {
  * @return {Object<string, *>} The resulting gRPC object
  */
 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.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(

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

@@ -45,8 +45,7 @@ var client = require('./client');
  *     objects. Defaults to true
  * @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
    * @param {Buffer} arg_buf The buffer to deserialize
@@ -55,7 +54,8 @@ exports.deserializeCls = function deserializeCls(cls, binaryAsBase64,
   return function deserialize(arg_buf) {
     // Convert to a native object with binary fields as Buffers (first 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,
       requestSerialize: serializeCls(method.resolvedRequestType.build()),
       requestDeserialize: deserializeCls(method.resolvedRequestType.build(),
-                                         binaryAsBase64, longsAsStrings),
+                                         options),
       responseSerialize: serializeCls(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
  * @deprecated Use grpc.load and Server#addService instead
@@ -792,8 +797,7 @@ Server.prototype.addProtoService = function(service, implementation) {
   var options;
   var protobuf_js_5_common = require('./protobuf_js_5_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)) {
     options = _.defaults(service.grpc_options, common.defaultGrpcOptions);
     this.addService(

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

@@ -37,16 +37,15 @@ var assert = require('assert');
 var _ = require('lodash');
 
 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 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;
 
@@ -101,6 +100,7 @@ describe('Proto message long int serialize and deserialize', function() {
     var longNumDeserialize = deserializeCls(messages_proto.LongValues,
                                             num_options);
     var serialized = longSerialize({int_64: pos_value});
+    console.log(longDeserialize(serialized));
     assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string');
     /* With the longsAsStrings option disabled, long values are represented as
      * objects with 3 keys: low, high, and unsigned */
@@ -136,7 +136,8 @@ describe('Proto message bytes serialize and deserialize', function() {
     var serialized = sequenceSerialize({repeated_field: [10]});
     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 = {
       bytes_field: new Buffer(''),
       repeated_field: [10]
@@ -155,7 +156,8 @@ describe('Proto message bytes serialize and deserialize', function() {
     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 oneofDeserialize = deserializeCls(
       messages_proto.OneOfValues, default_options);
@@ -193,7 +195,8 @@ describe('Proto message enum serialize and deserialize', function() {
     assert.deepEqual(enumDeserialize(nameSerialized),
                      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 nameDeserialized = enumDeserialize(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 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 mathServiceAttrs = grpc.loadObject(
@@ -332,9 +331,7 @@ describe('Echo service', function() {
   var server;
   var client;
   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 Client = grpc.loadObject(echo_service);
     server = new grpc.Server();
@@ -357,6 +354,13 @@ describe('Echo service', function() {
       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() {
   function toString(val) {
@@ -457,9 +461,7 @@ describe('Echo metadata', function() {
   var server;
   var metadata;
   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 Client = grpc.loadObject(test_service);
     server = new grpc.Server();
@@ -560,9 +562,7 @@ describe('Client malformed response handling', function() {
   var client;
   var badArg = new Buffer([0xFF]);
   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 malformed_test_service = {
       unary: {
@@ -669,9 +669,7 @@ describe('Server serialization failure handling', function() {
   var client;
   var server;
   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 malformed_test_service = {
       unary: {
@@ -772,16 +770,13 @@ describe('Server serialization failure handling', function() {
   });
 });
 describe('Other conditions', function() {
-  var test_service;
   var Client;
   var client;
   var server;
   var port;
   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);
     server = new grpc.Server();
     var trailer_metadata = new grpc.Metadata();
@@ -1121,15 +1116,12 @@ describe('Call propagation', function() {
   var proxy;
   var proxy_impl;
 
-  var test_service;
   var Client;
   var client;
   var server;
   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();
     Client = grpc.loadObject(test_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];
 }
 
+- (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
 - (void)testExceptions {
   // 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,
                                       GRPC_SLICE_LENGTH(elem->value), false);
       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;
 }
@@ -256,8 +261,6 @@ PHP_METHOD(Call, startBatch) {
   object_init(result);
   php_grpc_ulong index;
   zval *recv_status;
-  PHP_GRPC_MAKE_STD_ZVAL(recv_status);
-  object_init(recv_status);
   zval *value;
   zval *inner_value;
   zval *message_value;
@@ -439,7 +442,7 @@ PHP_METHOD(Call, startBatch) {
   grpc_completion_queue_pluck(completion_queue, call->wrapped,
                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 #if PHP_MAJOR_VERSION >= 7
-  zval recv_md;
+  zval *recv_md;
 #endif
   for (int i = 0; i < op_num; i++) {
     switch(ops[i].op) {
@@ -460,8 +463,10 @@ PHP_METHOD(Call, startBatch) {
       array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC);
       add_property_zval(result, "metadata", array);
 #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
       PHP_GRPC_DELREF(array);
       break;
@@ -475,12 +480,16 @@ PHP_METHOD(Call, startBatch) {
       }
       break;
     case GRPC_OP_RECV_STATUS_ON_CLIENT:
+      PHP_GRPC_MAKE_STD_ZVAL(recv_status);
+      object_init(recv_status);
 #if PHP_MAJOR_VERSION < 7
       array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC);
       add_property_zval(recv_status, "metadata", array);
 #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
       PHP_GRPC_DELREF(array);
       add_property_long(recv_status, "code", status);
@@ -489,6 +498,9 @@ PHP_METHOD(Call, startBatch) {
                                    true);
       gpr_free(status_details_text);
       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_FREE_STD_ZVAL(recv_status);
       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);
   php_grpc_add_property_string(arg, "service_url", context.service_url, 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
   zval **params[1];
   params[0] = &arg;
   state->fci->params = params;
   state->fci->retval_ptr_ptr = &retval;
 #else
+  PHP_GRPC_MAKE_STD_ZVAL(retval);
   state->fci->params = arg;
   state->fci->retval = retval;
 #endif
   state->fci->param_count = 1;
 
+  PHP_GRPC_DELREF(arg);
+
   /* call the user callback function */
   zend_call_function(state->fci, state->fci_cache TSRMLS_CC);
 
   grpc_status_code code = GRPC_STATUS_OK;
   grpc_metadata_array metadata;
+  bool cleanup = true;
 
   if (Z_TYPE_P(retval) != IS_ARRAY) {
+    cleanup = false;
     code = GRPC_STATUS_INVALID_ARGUMENT;
   } else if (!create_metadata_array(retval, &metadata)) {
-    grpc_metadata_array_destroy(&metadata);
     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 */
   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 */
@@ -207,8 +227,10 @@ void plugin_destroy_state(void *ptr) {
   plugin_state *state = (plugin_state *)ptr;
   efree(state->fci);
   efree(state->fci_cache);
+#if PHP_MAJOR_VERSION < 7
   PHP_GRPC_FREE_STD_ZVAL(state->fci->params);
   PHP_GRPC_FREE_STD_ZVAL(state->fci->retval);
+#endif
   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_join_host_port_type gpr_join_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_message_type gpr_log_message_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_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_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_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");

+ 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);
 extern gpr_split_host_port_type 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);
 extern gpr_log_type 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)
     require_relative "#{distrib_lib_dir}/grpc_c"
   else
-    require_relative 'grpc_c'
+    require 'grpc/grpc_c'
   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()/src/php/ext/grpc)
     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"
 
@@ -25,10 +23,8 @@
 
     case $host in
       *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)
         ;;
@@ -39,7 +35,7 @@
       ${source} ${"\\"}
       % endfor
       % 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:
       ${source} ${"\\"}
       % endfor
@@ -47,13 +43,13 @@
       % endfor
       , $ext_shared, , -fvisibility=hidden ${"\\"}
       -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)
   <%
     dirs = {}
     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:
           dirs[source[:source.rfind('/')]] = 1
     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",
       "nan": "^2.0.0",
       "node-pre-gyp": "^0.6.0",
-      "protobufjs": "^6.7.0"
+      "protobufjs": "^5.0.0"
     },
     "devDependencies": {
       "async": "^2.0.1",

+ 26 - 5
templates/package.xml.template

@@ -12,7 +12,7 @@
     <email>grpc-packages@google.com</email>
     <active>yes</active>
    </lead>
-   <date>2017-03-01</date>
+   <date>2017-05-22</date>
    <time>16:06:07</time>
    <version>
     <release>${settings.php_version.php()}</release>
@@ -24,15 +24,19 @@
    </stability>
    <license>BSD</license>
    <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>
    <contents>
     <dir baseinstalldir="/" name="/">
       <file baseinstalldir="/" name="config.m4" role="src" />
+      <file baseinstalldir="/" name="config.w32" role="src" />
       <file baseinstalldir="/" name="src/php/README.md" role="src" />
-      <file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
-      <file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
       % for source in php_config_m4.src + php_config_m4.headers:
       <file baseinstalldir="/" name="${source}" role="src" />
       % endfor
@@ -43,6 +47,7 @@
       % endfor
       % endif
       % endfor
+      <file name="LICENSE" role="doc" />
     </dir>
    </contents>
    <dependencies>
@@ -355,6 +360,22 @@
      <license>BSD</license>
      <notes>
   - 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
      </notes>
     </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
   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.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts

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

@@ -50,11 +50,11 @@
   mkdir -p ../../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.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;
 }
 
+static bool is_probably_integer(void *p) { return ((uintptr_t)p) < 1000000; }
+
 static void expectation_to_strvec(gpr_strvec *buf, expectation *e) {
   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);
 
   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,
                                   grpc_channel_args *server_args) {
+  int i;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   fullstack_fixture_data *ffd = f->fixture_data;
   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].type = GRPC_ARG_INTEGER;
     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/http/parser.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/error.h"
 #include "src/core/lib/iomgr/exec_ctx.h"
@@ -71,6 +72,8 @@ struct grpc_end2end_http_proxy {
   gpr_mu* mu;
   grpc_pollset* pollset;
   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_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_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_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_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_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_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_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_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_deferred_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*)gpr_malloc(sizeof(*proxy));
   memset(proxy, 0, sizeof(*proxy));
+  proxy->combiner = grpc_combiner_create(NULL);
   gpr_ref_init(&proxy->users, 1);
   // Construct proxy address.
   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_closure_create(destroy_pollset, proxy->pollset,
                                             grpc_schedule_on_exec_ctx));
+  grpc_combiner_unref(&exec_ctx, proxy->combiner);
   gpr_free(proxy);
   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_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
   grpc_endpoint_destroy(exec_ctx, tcp);
+  gpr_mu_lock(args->mu);
   GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
+  gpr_mu_unlock(args->mu);
 }
 
 void bad_server_thread(void *vargs) {

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

@@ -98,12 +98,12 @@ namespace {
 template <typename ServiceType>
 class CountedService : public ServiceType {
  public:
-  int request_count() {
+  size_t request_count() {
     std::unique_lock<std::mutex> lock(mu_);
     return request_count_;
   }
 
-  int response_count() {
+  size_t response_count() {
     std::unique_lock<std::mutex> lock(mu_);
     return response_count_;
   }
@@ -121,8 +121,8 @@ class CountedService : public ServiceType {
   std::mutex mu_;
 
  private:
-  int request_count_ = 0;
-  int response_count_ = 0;
+  size_t request_count_ = 0;
+  size_t response_count_ = 0;
 };
 
 using BackendService = CountedService<TestServiceImpl>;
@@ -243,9 +243,18 @@ class BalancerServiceImpl : public BalancerService {
   }
 
   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;
-    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();
       server->set_ip_address(Ip4ToPackedString("127.0.0.1"));
       server->set_port(backend_port);
@@ -327,10 +336,8 @@ class GrpclbEnd2endTest : public ::testing::Test {
     ChannelArguments args;
     args.SetPointer(GRPC_ARG_FAKE_RESOLVER_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_);
   }
 
@@ -467,26 +474,33 @@ class SingleBalancerTest : public GrpclbEnd2endTest {
 };
 
 TEST_F(SingleBalancerTest, Vanilla) {
+  const size_t kNumRpcsPerAddress = 100;
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0);
   // Make sure that trying to connect works without a call.
   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) {
-    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.
   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.
-  EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
   // 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.
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
@@ -500,7 +514,7 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
   ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0);
   // Send non-empty serverlist only after kServerlistDelayMs
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
       kServerlistDelayMs);
 
   const auto t0 = system_clock::now();
@@ -518,17 +532,20 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
 
   // Each backend should have gotten 1 request.
   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) {
-    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.
-  EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
   // 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.
   EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
@@ -539,10 +556,11 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
 
   // Send a serverlist right away.
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+      0);
   // ... and the same one a bit later.
   ScheduleResponseForBalancer(
-      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()),
+      0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
       kServerlistDelayMs);
 
   // Send num_backends/2 requests.
@@ -550,14 +568,19 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
   // only the first half of the backends will receive them.
   for (size_t i = 0; i < backends_.size(); ++i) {
     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
-      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);
   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.
@@ -566,7 +589,7 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
       gpr_time_from_millis(kServerlistDelayMs * 1.1, GPR_TIMESPAN)));
 
   // 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.
   statuses_and_responses = SendRpc(
@@ -575,52 +598,146 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
   // Because a duplicated serverlist should have no effect, all backends must
   // have been hit once now.
   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);
   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.
-  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.
   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 {
  public:
   SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 2) {}
 };
 
 TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) {
+  const size_t kNumRpcsPerAddress = 100;
   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) {
-    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.
   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.
-  EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+  EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
   // 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();
-  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_load_balancing);
   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);
 }
 

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

@@ -42,7 +42,6 @@
 #include <grpc++/server_builder.h>
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
-#include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
@@ -131,22 +130,10 @@ class RoundRobinEnd2endTest : public ::testing::Test {
     int port_;
     std::unique_ptr<Server> server_;
     MyTestServiceImpl service_;
-    std::unique_ptr<std::thread> thread_;
 
     explicit ServerData(const grpc::string& server_host) {
       port_ = grpc_pick_unused_port_or_die();
       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;
       server_address << server_host << ":" << port_;
       ServerBuilder builder;
@@ -154,18 +141,13 @@ class RoundRobinEnd2endTest : public ::testing::Test {
                                InsecureServerCredentials());
       builder.RegisterService(&service_);
       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_;
-  CompletionQueue cli_cq_;
   std::shared_ptr<Channel> channel_;
   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
   std::vector<std::unique_ptr<ServerData>> servers_;
@@ -197,10 +179,13 @@ TEST_F(RoundRobinEnd2endTest, RoundRobin) {
   const int kNumServers = 3;
   StartServers(kNumServers);
   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) {
-    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.
   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) {
+    grpc_chttp2_transport* client =
+        reinterpret_cast<grpc_chttp2_transport*>(client_transport_);
     out << " writes/iter:"
         << ((double)stats_.num_writes / (double)state.iterations())
         << " cli_transport_stalls/iter:"
@@ -116,7 +118,8 @@ class TrickledCHTTP2 : public EndpointPairFixture {
             (double)state.iterations())
         << " svr_stream_stalls/iter:"
         << ((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) {

+ 2 - 0
tools/README.md

@@ -13,6 +13,8 @@ container engine, BigQuery etc)
 
 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.
 
 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
 
-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
   # 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 

+ 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/sync_stream.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_gcc_atomic.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_generic.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
 # 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/sync_stream.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_gcc_atomic.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_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 \
-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/client/channel_cc.cc \
 src/cpp/client/client_context.cc \

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