Merge pull request #6924 from dgquintas/grpclb_v0

gRPC LB policy
pull/7024/head
kpayson64 9 years ago committed by GitHub
commit 1e3fdbe7fd
  1. 6
      BUILD
  2. 2
      CMakeLists.txt
  3. 169
      Makefile
  4. 1
      binding.gyp
  5. 20
      build.yaml
  6. 1
      config.m4
  7. 3
      gRPC-Core.podspec
  8. 2
      grpc.gemspec
  9. 2
      package.xml
  10. 11
      src/core/ext/client_config/lb_policy.h
  11. 1039
      src/core/ext/lb_policy/grpclb/grpclb.c
  12. 44
      src/core/ext/lb_policy/grpclb/grpclb.h
  13. 141
      src/core/ext/lb_policy/grpclb/load_balancer_api.c
  14. 36
      src/core/ext/lb_policy/grpclb/load_balancer_api.h
  15. 4
      src/core/plugin_registry/grpc_plugin_registry.c
  16. 4
      src/core/plugin_registry/grpc_unsecure_plugin_registry.c
  17. 1
      src/python/grpcio/grpc_core_dependencies.py
  18. 9
      test/core/end2end/cq_verifier.c
  19. 3
      test/core/end2end/cq_verifier.h
  20. 6
      test/core/nanopb/fuzzer_response.c
  21. 18
      test/cpp/grpclb/grpclb_api_test.cc
  22. 688
      test/cpp/grpclb/grpclb_test.cc
  23. 2
      tools/doxygen/Doxyfile.core.internal
  24. 27
      tools/run_tests/sources_and_headers.json
  25. 21
      tools/run_tests/tests.json
  26. 3
      vsprojects/vcxproj/grpc/grpc.vcxproj
  27. 6
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  28. 284
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
  29. 629
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
  30. 3
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  31. 6
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
  32. 215
      vsprojects/vcxproj/test/grpclb_test/grpclb_test.vcxproj
  33. 39
      vsprojects/vcxproj/test/grpclb_test/grpclb_test.vcxproj.filters

@ -300,6 +300,7 @@ cc_library(
"src/core/ext/client_config/subchannel_call_holder.h",
"src/core/ext/client_config/subchannel_index.h",
"src/core/ext/client_config/uri_parser.h",
"src/core/ext/lb_policy/grpclb/grpclb.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
"src/core/ext/load_reporting/load_reporting.h",
@ -476,6 +477,7 @@ cc_library(
"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/lb_policy/grpclb/grpclb.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
"src/core/ext/lb_policy/pick_first/pick_first.c",
@ -1021,6 +1023,7 @@ cc_library(
"src/core/ext/client_config/uri_parser.h",
"src/core/ext/load_reporting/load_reporting.h",
"src/core/ext/load_reporting/load_reporting_filter.h",
"src/core/ext/lb_policy/grpclb/grpclb.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
"src/core/ext/census/aggregation.h",
@ -1170,6 +1173,7 @@ cc_library(
"src/core/ext/resolver/sockaddr/sockaddr_resolver.c",
"src/core/ext/load_reporting/load_reporting.c",
"src/core/ext/load_reporting/load_reporting_filter.c",
"src/core/ext/lb_policy/grpclb/grpclb.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
"src/core/ext/lb_policy/pick_first/pick_first.c",
@ -1956,6 +1960,7 @@ objc_library(
"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/lb_policy/grpclb/grpclb.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
"src/core/ext/lb_policy/pick_first/pick_first.c",
@ -2148,6 +2153,7 @@ objc_library(
"src/core/ext/client_config/subchannel_call_holder.h",
"src/core/ext/client_config/subchannel_index.h",
"src/core/ext/client_config/uri_parser.h",
"src/core/ext/lb_policy/grpclb/grpclb.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
"src/core/ext/load_reporting/load_reporting.h",

@ -442,6 +442,7 @@ add_library(grpc
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/lb_policy/grpclb/grpclb.c
src/core/ext/lb_policy/grpclb/load_balancer_api.c
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
third_party/nanopb/pb_common.c
@ -899,6 +900,7 @@ add_library(grpc_unsecure
src/core/ext/resolver/sockaddr/sockaddr_resolver.c
src/core/ext/load_reporting/load_reporting.c
src/core/ext/load_reporting/load_reporting_filter.c
src/core/ext/lb_policy/grpclb/grpclb.c
src/core/ext/lb_policy/grpclb/load_balancer_api.c
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
third_party/nanopb/pb_common.c

@ -1048,6 +1048,7 @@ grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin
grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test
hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test
interop_client: $(BINDIR)/$(CONFIG)/interop_client
interop_server: $(BINDIR)/$(CONFIG)/interop_server
@ -1403,6 +1404,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
$(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/grpclb_test \
$(BINDIR)/$(CONFIG)/hybrid_end2end_test \
$(BINDIR)/$(CONFIG)/interop_client \
$(BINDIR)/$(CONFIG)/interop_server \
@ -1487,6 +1489,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
$(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/grpclb_test \
$(BINDIR)/$(CONFIG)/hybrid_end2end_test \
$(BINDIR)/$(CONFIG)/interop_client \
$(BINDIR)/$(CONFIG)/interop_server \
@ -1774,6 +1777,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/golden_file_test || ( echo test golden_file_test failed ; exit 1 )
$(E) "[RUN] Testing grpclb_api_test"
$(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 )
$(E) "[RUN] Testing grpclb_test"
$(Q) $(BINDIR)/$(CONFIG)/grpclb_test || ( echo test grpclb_test failed ; exit 1 )
$(E) "[RUN] Testing hybrid_end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/hybrid_end2end_test || ( echo test hybrid_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing interop_test"
@ -2681,6 +2686,7 @@ LIBGRPC_SRC = \
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/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \
@ -3056,8 +3062,123 @@ LIBGRPC_TEST_UTIL_SRC = \
test/core/util/port_server_client.c \
test/core/util/port_windows.c \
test/core/util/slice_splitter.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/compress_filter.c \
src/core/lib/channel/connected_channel.c \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.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/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll_linux.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.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_windows.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/network_status_tracker.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_windows.c \
src/core/lib/iomgr/resolve_address_posix.c \
src/core/lib/iomgr/resolve_address_windows.c \
src/core/lib/iomgr/sockaddr_utils.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_windows.c \
src/core/lib/iomgr/tcp_client_posix.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_windows.c \
src/core/lib/iomgr/tcp_windows.c \
src/core/lib/iomgr/time_averaged_stats.c \
src/core/lib/iomgr/timer.c \
src/core/lib/iomgr/timer_heap.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_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_posix.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/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/event_string.c \
src/core/lib/surface/lame_client.c \
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/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \
PUBLIC_HEADERS_C += \
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/status.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \
include/grpc/impl/codegen/grpc_types.h \
include/grpc/impl/codegen/propagation_bits.h \
include/grpc/impl/codegen/status.h \
include/grpc/impl/codegen/alloc.h \
include/grpc/impl/codegen/atm.h \
include/grpc/impl/codegen/atm_gcc_atomic.h \
include/grpc/impl/codegen/atm_gcc_sync.h \
include/grpc/impl/codegen/atm_windows.h \
include/grpc/impl/codegen/log.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/slice.h \
include/grpc/impl/codegen/slice_buffer.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/impl/codegen/time.h \
LIBGRPC_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_TEST_UTIL_SRC))))
@ -3270,6 +3391,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
src/core/ext/load_reporting/load_reporting.c \
src/core/ext/load_reporting/load_reporting_filter.c \
src/core/ext/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \
@ -11320,6 +11442,53 @@ endif
$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc
GRPCLB_TEST_SRC = \
$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \
test/cpp/grpclb/grpclb_test.cc \
GRPCLB_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPCLB_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpclb_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/grpclb_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/grpclb_test: $(PROTOBUF_DEP) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(GRPCLB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpclb_test
endif
endif
$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a
$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a
deps_grpclb_test: $(GRPCLB_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(GRPCLB_TEST_OBJS:.o=.dep)
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc
HYBRID_END2END_TEST_SRC = \
test/cpp/end2end/hybrid_end2end_test.cc \

@ -727,6 +727,7 @@
'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/lb_policy/grpclb/grpclb.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',

@ -376,11 +376,14 @@ filegroups:
- gpr_codegen
- name: grpc_lb_policy_grpclb
headers:
- src/core/ext/lb_policy/grpclb/grpclb.h
- src/core/ext/lb_policy/grpclb/load_balancer_api.h
- src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
src:
- src/core/ext/lb_policy/grpclb/grpclb.c
- src/core/ext/lb_policy/grpclb/load_balancer_api.c
- src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
plugin: grpc_lb_policy_grpclb
uses:
- grpc_base
- grpc_client_config
@ -816,6 +819,7 @@ libs:
- grpc_lb_policy_grpclb
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
- grpc_lb_policy_grpclb
- grpc_resolver_dns_native
- grpc_resolver_sockaddr
- grpc_load_reporting
@ -882,6 +886,7 @@ libs:
- grpc
filegroups:
- grpc_test_util_base
- grpc_base
vs_project_guid: '{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}'
- name: grpc_test_util_unsecure
build: private
@ -913,6 +918,7 @@ libs:
- grpc_lb_policy_grpclb
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
- grpc_lb_policy_grpclb
- census
generate_plugin_registry: true
secure: false
@ -2750,6 +2756,20 @@ targets:
- grpc_test_util
- grpc++
- grpc
- name: grpclb_test
gtest: false
build: test
language: c++
src:
- src/proto/grpc/lb/v1/load_balancer.proto
- test/cpp/grpclb/grpclb_test.cc
deps:
- gpr
- gpr_test_util
- grpc
- grpc++
- grpc++_test_util
- grpc_test_util
- name: hybrid_end2end_test
gtest: true
build: test

@ -246,6 +246,7 @@ if test "$PHP_GRPC" != "no"; then
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/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \

@ -393,6 +393,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_config/subchannel_call_holder.h',
'src/core/ext/client_config/subchannel_index.h',
'src/core/ext/client_config/uri_parser.h',
'src/core/ext/lb_policy/grpclb/grpclb.h',
'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'third_party/nanopb/pb.h',
@ -573,6 +574,7 @@ Pod::Spec.new do |s|
'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/lb_policy/grpclb/grpclb.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',
@ -748,6 +750,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_config/subchannel_call_holder.h',
'src/core/ext/client_config/subchannel_index.h',
'src/core/ext/client_config/uri_parser.h',
'src/core/ext/lb_policy/grpclb/grpclb.h',
'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'third_party/nanopb/pb.h',

@ -312,6 +312,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_config/subchannel_call_holder.h )
s.files += %w( src/core/ext/client_config/subchannel_index.h )
s.files += %w( src/core/ext/client_config/uri_parser.h )
s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.h )
s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h )
s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
s.files += %w( third_party/nanopb/pb.h )
@ -492,6 +493,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c )
s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.c )
s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c )
s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c )
s.files += %w( third_party/nanopb/pb_common.c )

@ -320,6 +320,7 @@
<file baseinstalldir="/" name="src/core/ext/client_config/subchannel_call_holder.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_config/subchannel_index.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_config/uri_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
@ -500,6 +501,7 @@
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />

@ -73,7 +73,7 @@ struct grpc_lb_policy_vtable {
void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_closure *closure);
/** try to enter a READY connectivity state */
/** Try to enter a READY connectivity state */
void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** check the current connectivity of the lb_policy */
@ -82,7 +82,9 @@ struct grpc_lb_policy_vtable {
grpc_error **connectivity_error);
/** call notify when the connectivity state of a channel changes from *state.
Updates *state with the new state of the policy */
Updates *state with the new state of the policy. Calling with a NULL \a
state cancels the subscription.
*/
void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
grpc_connectivity_state *state,
@ -125,7 +127,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
/** Given initial metadata in \a initial_metadata, find an appropriate
target for this rpc, and 'return' it by calling \a on_complete after setting
\a target.
Picking can be asynchronous. Any IO should be done under \a pollset. */
Picking can be asynchronous. Any IO should be done under \a pollent. */
int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_polling_entity *pollent,
grpc_metadata_batch *initial_metadata,
@ -147,8 +149,11 @@ void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq);
/** Try to enter a READY connectivity state */
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/* Call notify when the connectivity state of a channel changes from \a *state.
* Updates \a *state with the new state of the policy */
void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
grpc_connectivity_state *state,

File diff suppressed because it is too large Load Diff

@ -0,0 +1,44 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H
#define GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H
#include "src/core/ext/client_config/lb_policy_factory.h"
/** Returns a load balancing factory for the glb policy, which tries to connect
* to a load balancing server to decide the next successfully connected
* subchannel to pick. */
grpc_lb_policy_factory *grpc_glb_lb_factory_create();
#endif /* GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H */

@ -38,9 +38,15 @@
#include <grpc/support/alloc.h>
typedef struct decode_serverlist_arg {
int first_pass;
int i;
/* 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;
} decode_serverlist_arg;
@ -48,23 +54,24 @@ typedef struct decode_serverlist_arg {
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 != 0) { /* first pass */
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)) {
return false;
}
dec_arg->num_servers++;
} else { /* second pass */
} else { /* second pass. Actually decode. */
grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
memset(server, 0, sizeof(grpc_grpclb_server));
GPR_ASSERT(dec_arg->num_servers > 0);
if (dec_arg->i == 0) { /* first iteration of second pass */
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)) {
return false;
}
dec_arg->servers[dec_arg->i++] = server;
dec_arg->servers[dec_arg->decoding_idx++] = server;
}
return true;
@ -102,57 +109,59 @@ void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
gpr_free(request);
}
grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) {
bool status;
typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response;
grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse(
gpr_slice encoded_grpc_grpclb_response) {
pb_istream_t stream =
pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
GPR_SLICE_LENGTH(encoded_response));
grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
memset(res, 0, sizeof(*res));
status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res);
if (!status) {
grpc_grpclb_response_destroy(res);
pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_grpc_grpclb_response),
GPR_SLICE_LENGTH(encoded_grpc_grpclb_response));
grpc_grpclb_response res;
memset(&res, 0, sizeof(grpc_grpclb_response));
if (!pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res)) {
return NULL;
}
return res;
grpc_grpclb_initial_response *initial_res =
gpr_malloc(sizeof(grpc_grpclb_initial_response));
memcpy(initial_res, &res.initial_response,
sizeof(grpc_grpclb_initial_response));
return initial_res;
}
grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
gpr_slice encoded_response) {
gpr_slice encoded_grpc_grpclb_response) {
bool status;
decode_serverlist_arg arg;
pb_istream_t stream =
pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
GPR_SLICE_LENGTH(encoded_response));
pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_grpc_grpclb_response),
GPR_SLICE_LENGTH(encoded_grpc_grpclb_response));
pb_istream_t stream_at_start = stream;
grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
memset(res, 0, sizeof(*res));
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 = 1;
status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res);
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);
if (!status) {
grpc_grpclb_response_destroy(res);
return NULL;
}
arg.first_pass = 0;
arg.first_pass = false;
status =
pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, res);
pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, &res);
if (!status) {
grpc_grpclb_response_destroy(res);
return NULL;
}
grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
memset(sl, 0, sizeof(*sl));
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;
if (res.server_list.has_expiration_interval) {
sl->expiration_interval = res.server_list.expiration_interval;
}
grpc_grpclb_response_destroy(res);
return sl;
}
@ -167,6 +176,72 @@ void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) {
gpr_free(serverlist);
}
void grpc_grpclb_response_destroy(grpc_grpclb_response *response) {
grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
const grpc_grpclb_serverlist *sl) {
grpc_grpclb_serverlist *copy = gpr_malloc(sizeof(grpc_grpclb_serverlist));
memset(copy, 0, sizeof(grpc_grpclb_serverlist));
copy->num_servers = sl->num_servers;
memcpy(&copy->expiration_interval, &sl->expiration_interval,
sizeof(grpc_grpclb_duration));
copy->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * sl->num_servers);
for (size_t i = 0; i < sl->num_servers; i++) {
copy->servers[i] = gpr_malloc(sizeof(grpc_grpclb_server));
memcpy(copy->servers[i], sl->servers[i], sizeof(grpc_grpclb_server));
}
return copy;
}
bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs,
const grpc_grpclb_serverlist *rhs) {
if ((lhs == NULL) || (rhs == NULL)) {
return false;
}
if (lhs->num_servers != rhs->num_servers) {
return false;
}
if (grpc_grpclb_duration_compare(&lhs->expiration_interval,
&rhs->expiration_interval) != 0) {
return false;
}
for (size_t i = 0; i < lhs->num_servers; i++) {
if (!grpc_grpclb_server_equals(lhs->servers[i], rhs->servers[i])) {
return false;
}
}
return true;
}
bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs,
const grpc_grpclb_server *rhs) {
return memcmp(lhs, rhs, sizeof(grpc_grpclb_server)) == 0;
}
int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs,
const grpc_grpclb_duration *rhs) {
GPR_ASSERT(lhs && rhs);
if (lhs->has_seconds && rhs->has_seconds) {
if (lhs->seconds < rhs->seconds) return -1;
if (lhs->seconds > rhs->seconds) return 1;
} else if (lhs->has_seconds) {
return 1;
} else if (rhs->has_seconds) {
return -1;
}
GPR_ASSERT(lhs->seconds == rhs->seconds);
if (lhs->has_nanos && rhs->has_nanos) {
if (lhs->nanos < rhs->nanos) return -1;
if (lhs->nanos > rhs->nanos) return 1;
} else if (lhs->has_nanos) {
return 1;
} else if (rhs->has_nanos) {
return -1;
}
return 0;
}
void grpc_grpclb_initial_response_destroy(
grpc_grpclb_initial_response *response) {
gpr_free(response);
}

@ -46,7 +46,7 @@ extern "C" {
#define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128
typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request;
typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response;
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 {
@ -64,19 +64,37 @@ gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request);
/** Destroy \a request */
void grpc_grpclb_request_destroy(grpc_grpclb_request *request);
/** Parse (ie, decode) the bytes in \a encoded_response as a \a
* grpc_grpclb_response */
grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response);
/** Parse (ie, decode) the bytes in \a encoded_grpc_grpclb_response as a \a
* grpc_grpclb_initial_response */
grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse(
gpr_slice encoded_grpc_grpclb_response);
/** Parse the list of servers from an encoded \a grpc_grpclb_response */
grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
gpr_slice encoded_grpc_grpclb_response);
/** Return a copy of \a sl. The caller is responsible for calling \a
* grpc_grpclb_destroy_serverlist on the returned copy. */
grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
const grpc_grpclb_serverlist *sl);
bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs,
const grpc_grpclb_serverlist *rhs);
bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs,
const grpc_grpclb_server *rhs);
/** Destroy \a serverlist */
void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist);
/** Parse the list of servers from an encoded \a grpc_grpclb_response */
grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
gpr_slice encoded_response);
/** Compare \a lhs against \a rhs and return 0 if \a lhs and \a rhs are equal,
* < 0 if \a lhs represents a duration shorter than \a rhs and > 0 otherwise */
int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs,
const grpc_grpclb_duration *rhs);
/** Destroy \a response */
void grpc_grpclb_response_destroy(grpc_grpclb_response *response);
/** Destroy \a initial_response */
void grpc_grpclb_initial_response_destroy(
grpc_grpclb_initial_response *response);
#ifdef __cplusplus
}

@ -37,6 +37,8 @@ extern void grpc_chttp2_plugin_init(void);
extern void grpc_chttp2_plugin_shutdown(void);
extern void grpc_client_config_init(void);
extern void grpc_client_config_shutdown(void);
extern void grpc_lb_policy_grpclb_init(void);
extern void grpc_lb_policy_grpclb_shutdown(void);
extern void grpc_lb_policy_pick_first_init(void);
extern void grpc_lb_policy_pick_first_shutdown(void);
extern void grpc_lb_policy_round_robin_init(void);
@ -55,6 +57,8 @@ void grpc_register_built_in_plugins(void) {
grpc_chttp2_plugin_shutdown);
grpc_register_plugin(grpc_client_config_init,
grpc_client_config_shutdown);
grpc_register_plugin(grpc_lb_policy_grpclb_init,
grpc_lb_policy_grpclb_shutdown);
grpc_register_plugin(grpc_lb_policy_pick_first_init,
grpc_lb_policy_pick_first_shutdown);
grpc_register_plugin(grpc_lb_policy_round_robin_init,

@ -43,6 +43,8 @@ extern void grpc_resolver_sockaddr_init(void);
extern void grpc_resolver_sockaddr_shutdown(void);
extern void grpc_load_reporting_plugin_init(void);
extern void grpc_load_reporting_plugin_shutdown(void);
extern void grpc_lb_policy_grpclb_init(void);
extern void grpc_lb_policy_grpclb_shutdown(void);
extern void grpc_lb_policy_pick_first_init(void);
extern void grpc_lb_policy_pick_first_shutdown(void);
extern void grpc_lb_policy_round_robin_init(void);
@ -61,6 +63,8 @@ void grpc_register_built_in_plugins(void) {
grpc_resolver_sockaddr_shutdown);
grpc_register_plugin(grpc_load_reporting_plugin_init,
grpc_load_reporting_plugin_shutdown);
grpc_register_plugin(grpc_lb_policy_grpclb_init,
grpc_lb_policy_grpclb_shutdown);
grpc_register_plugin(grpc_lb_policy_pick_first_init,
grpc_lb_policy_pick_first_shutdown);
grpc_register_plugin(grpc_lb_policy_round_robin_init,

@ -240,6 +240,7 @@ CORE_SOURCE_FILES = [
'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/lb_policy/grpclb/grpclb.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',

@ -259,9 +259,10 @@ void cq_verify(cq_verifier *v) {
gpr_strvec_destroy(&have_tags);
}
void cq_verify_empty(cq_verifier *v) {
gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_seconds(1, GPR_TIMESPAN));
void cq_verify_empty_timeout(cq_verifier *v, int timeout_sec) {
gpr_timespec deadline =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_seconds(timeout_sec, GPR_TIMESPAN));
grpc_event ev;
GPR_ASSERT(v->expect.next == &v->expect && "expectation queue must be empty");
@ -275,6 +276,8 @@ void cq_verify_empty(cq_verifier *v) {
}
}
void cq_verify_empty(cq_verifier *v) { cq_verify_empty_timeout(v, 1); }
static expectation *add(cq_verifier *v, grpc_completion_type type, void *tag) {
expectation *e = gpr_malloc(sizeof(expectation));
e->type = type;

@ -55,6 +55,9 @@ void cq_verify(cq_verifier *v);
/* ensure that the completion queue is empty */
void cq_verify_empty(cq_verifier *v);
/* ensure that the completion queue is empty, waiting up to \a timeout secs. */
void cq_verify_empty_timeout(cq_verifier *v, int timeout_sec);
/* Various expectation matchers
Any functions taking ... expect a NULL terminated list of key/value pairs
(each pair using two parameter slots) of metadata that MUST be present in

@ -43,9 +43,9 @@ bool leak_check = true;
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size);
grpc_grpclb_response *response;
if ((response = grpc_grpclb_response_parse(slice))) {
grpc_grpclb_response_destroy(response);
grpc_grpclb_initial_response *response;
if ((response = grpc_grpclb_initial_response_parse(slice))) {
grpc_grpclb_initial_response_destroy(response);
}
gpr_slice_unref(slice);
return 0;

@ -58,26 +58,24 @@ TEST_F(GrpclbTest, CreateRequest) {
grpc_grpclb_request_destroy(c_req);
}
TEST_F(GrpclbTest, ParseResponse) {
TEST_F(GrpclbTest, ParseInitialResponse) {
LoadBalanceResponse response;
auto* initial_response = response.mutable_initial_response();
auto* client_stats_report_interval =
initial_response->mutable_client_stats_report_interval();
client_stats_report_interval->set_seconds(123);
client_stats_report_interval->set_nanos(456);
const std::string encoded_response = response.SerializeAsString();
gpr_slice encoded_slice =
gpr_slice_from_copied_string(encoded_response.c_str());
grpc_grpclb_response* c_response = grpc_grpclb_response_parse(encoded_slice);
EXPECT_TRUE(c_response->has_initial_response);
EXPECT_FALSE(c_response->initial_response.has_load_balancer_delegate);
EXPECT_EQ(c_response->initial_response.client_stats_report_interval.seconds,
123);
EXPECT_EQ(c_response->initial_response.client_stats_report_interval.nanos,
456);
grpc_grpclb_initial_response* c_initial_response =
grpc_grpclb_initial_response_parse(encoded_slice);
EXPECT_FALSE(c_initial_response->has_load_balancer_delegate);
EXPECT_EQ(c_initial_response->client_stats_report_interval.seconds, 123);
EXPECT_EQ(c_initial_response->client_stats_report_interval.nanos, 456);
gpr_slice_unref(encoded_slice);
grpc_grpclb_response_destroy(c_response);
grpc_grpclb_initial_response_destroy(c_initial_response);
}
TEST_F(GrpclbTest, ParseResponseServerList) {

@ -0,0 +1,688 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <cinttypes>
#include <cstdarg>
#include <cstdint>
#include <cstring>
#include <string>
extern "C" {
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include "src/core/ext/client_config/client_channel.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/support/tmpfile.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/server.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
}
#include "src/proto/grpc/lb/v1/load_balancer.pb.h"
#define NUM_BACKENDS 4
// TODO(dgq): Other scenarios in need of testing:
// - Send an empty serverlist update and verify that the client request blocks
// until a new serverlist with actual contents is available.
// - Send identical serverlist update
// - Test reception of invalid serverlist
// - Test pinging
// - Test against a non-LB server. That server should return UNIMPLEMENTED and
// the call should fail.
// - Random LB server closing the stream unexpectedly.
namespace grpc {
namespace {
typedef struct client_fixture {
grpc_channel *client;
char *server_uri;
grpc_completion_queue *cq;
} client_fixture;
typedef struct server_fixture {
grpc_server *server;
grpc_call *server_call;
grpc_completion_queue *cq;
char *servers_hostport;
int port;
gpr_thd_id tid;
int num_calls_serviced;
} server_fixture;
typedef struct test_fixture {
server_fixture lb_server;
server_fixture lb_backends[NUM_BACKENDS];
client_fixture client;
int lb_server_update_delay_ms;
} test_fixture;
static void *tag(intptr_t t) { return (void *)t; }
static gpr_slice build_response_payload_slice(
const char *host, int *ports, size_t nports,
int64_t expiration_interval_secs, int32_t expiration_interval_nanos) {
// server_list {
// servers {
// ip_address: "127.0.0.1"
// port: ...
// load_balance_token: "token..."
// }
// ...
// }
grpc::lb::v1::LoadBalanceResponse response;
auto *serverlist = response.mutable_server_list();
if (expiration_interval_secs > 0 || expiration_interval_nanos > 0) {
auto *expiration_interval = serverlist->mutable_expiration_interval();
if (expiration_interval_secs > 0) {
expiration_interval->set_seconds(expiration_interval_secs);
}
if (expiration_interval_nanos > 0) {
expiration_interval->set_nanos(expiration_interval_nanos);
}
}
for (size_t i = 0; i < nports; i++) {
auto *server = serverlist->add_servers();
server->set_ip_address(host);
server->set_port(ports[i]);
// The following long long int cast is meant to work around the
// disfunctional implementation of std::to_string in gcc 4.4, which doesn't
// have a version for int but does have one for long long int.
server->set_load_balance_token("token" +
std::to_string((long long int)ports[i]));
}
gpr_log(GPR_INFO, "generating response: %s",
response.ShortDebugString().c_str());
const gpr_slice response_slice =
gpr_slice_from_copied_string(response.SerializeAsString().c_str());
return response_slice;
}
static void drain_cq(grpc_completion_queue *cq) {
grpc_event ev;
do {
ev = grpc_completion_queue_next(cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
NULL);
} while (ev.type != GRPC_QUEUE_SHUTDOWN);
}
static void sleep_ms(int delay_ms) {
gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_millis(delay_ms, GPR_TIMESPAN)));
}
static void start_lb_server(server_fixture *sf, int *ports, size_t nports,
int update_delay_ms) {
grpc_call *s;
cq_verifier *cqv = cq_verifier_create(sf->cq);
grpc_op ops[6];
grpc_op *op;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
grpc_call_error error;
int was_cancelled = 2;
grpc_byte_buffer *request_payload_recv;
grpc_byte_buffer *response_payload;
memset(ops, 0, sizeof(ops));
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
error = grpc_server_request_call(sf->server, &s, &call_details,
&request_metadata_recv, sf->cq, sf->cq,
tag(200));
GPR_ASSERT(GRPC_CALL_OK == error);
gpr_log(GPR_INFO, "LB Server[%s] up", sf->servers_hostport);
cq_expect_completion(cqv, tag(200), 1);
cq_verify(cqv);
gpr_log(GPR_INFO, "LB Server[%s] after tag 200", sf->servers_hostport);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(201), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
gpr_log(GPR_INFO, "LB Server[%s] after tag 201", sf->servers_hostport);
// receive request for backends
op = ops;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(202), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(202), 1);
cq_verify(cqv);
gpr_log(GPR_INFO, "LB Server[%s] after RECV_MSG", sf->servers_hostport);
// TODO(dgq): validate request.
grpc_byte_buffer_destroy(request_payload_recv);
gpr_slice response_payload_slice;
for (int i = 0; i < 2; i++) {
if (i == 0) {
// First half of the ports.
response_payload_slice =
build_response_payload_slice("127.0.0.1", ports, nports / 2, -1, -1);
} else {
// Second half of the ports.
sleep_ms(update_delay_ms);
response_payload_slice =
build_response_payload_slice("127.0.0.1", ports + (nports / 2),
(nports + 1) / 2 /* ceil */, -1, -1);
}
response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1);
op = ops;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = response_payload;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(203), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(203), 1);
cq_verify(cqv);
gpr_log(GPR_INFO, "LB Server[%s] after SEND_MESSAGE, iter %d",
sf->servers_hostport, i);
grpc_byte_buffer_destroy(response_payload);
gpr_slice_unref(response_payload_slice);
}
gpr_log(GPR_INFO, "LB Server[%s] shutting down", sf->servers_hostport);
op = ops;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
op->data.send_status_from_server.status_details = "xyz";
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(204), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(201), 1);
cq_expect_completion(cqv, tag(204), 1);
cq_verify(cqv);
gpr_log(GPR_INFO, "LB Server[%s] after tag 204. All done. LB server out",
sf->servers_hostport);
grpc_call_destroy(s);
cq_verifier_destroy(cqv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
}
static void start_backend_server(server_fixture *sf) {
grpc_call *s;
cq_verifier *cqv;
grpc_op ops[6];
grpc_op *op;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
grpc_call_error error;
int was_cancelled;
grpc_byte_buffer *request_payload_recv;
grpc_byte_buffer *response_payload;
grpc_event ev;
while (true) {
memset(ops, 0, sizeof(ops));
cqv = cq_verifier_create(sf->cq);
was_cancelled = 2;
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
error = grpc_server_request_call(sf->server, &s, &call_details,
&request_metadata_recv, sf->cq, sf->cq,
tag(100));
GPR_ASSERT(GRPC_CALL_OK == error);
gpr_log(GPR_INFO, "Server[%s] up", sf->servers_hostport);
ev = grpc_completion_queue_next(sf->cq,
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(60), NULL);
if (!ev.success) {
gpr_log(GPR_INFO, "Server[%s] being torn down", sf->servers_hostport);
cq_verifier_destroy(cqv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
return;
}
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
gpr_log(GPR_INFO, "Server[%s] after tag 100", sf->servers_hostport);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(101), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
gpr_log(GPR_INFO, "Server[%s] after tag 101", sf->servers_hostport);
bool exit = false;
gpr_slice response_payload_slice =
gpr_slice_from_copied_string("hello you");
while (!exit) {
op = ops;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &request_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
ev = grpc_completion_queue_next(
sf->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), NULL);
if (ev.type == GRPC_OP_COMPLETE && ev.success) {
GPR_ASSERT(ev.tag = tag(102));
if (request_payload_recv == NULL) {
exit = true;
gpr_log(GPR_INFO,
"Server[%s] recv \"close\" from client, exiting. Call #%d",
sf->servers_hostport, sf->num_calls_serviced);
}
} else {
gpr_log(GPR_INFO, "Server[%s] forced to shutdown. Call #%d",
sf->servers_hostport, sf->num_calls_serviced);
exit = true;
}
gpr_log(GPR_INFO, "Server[%s] after tag 102. Call #%d",
sf->servers_hostport, sf->num_calls_serviced);
if (!exit) {
response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
op = ops;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = response_payload;
op->flags = 0;
op->reserved = NULL;
op++;
error =
grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
ev = grpc_completion_queue_next(
sf->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), NULL);
if (ev.type == GRPC_OP_COMPLETE && ev.success) {
GPR_ASSERT(ev.tag = tag(103));
} else {
gpr_log(GPR_INFO, "Server[%s] forced to shutdown. Call #%d",
sf->servers_hostport, sf->num_calls_serviced);
exit = true;
}
gpr_log(GPR_INFO, "Server[%s] after tag 103. Call #%d",
sf->servers_hostport, sf->num_calls_serviced);
grpc_byte_buffer_destroy(response_payload);
}
grpc_byte_buffer_destroy(request_payload_recv);
}
++sf->num_calls_serviced;
gpr_log(GPR_INFO, "Server[%s] OUT OF THE LOOP", sf->servers_hostport);
gpr_slice_unref(response_payload_slice);
op = ops;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
op->data.send_status_from_server.status_details = "Backend server out a-ok";
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(101), 1);
cq_expect_completion(cqv, tag(104), 1);
cq_verify(cqv);
gpr_log(GPR_INFO, "Server[%s] DONE. After servicing %d calls",
sf->servers_hostport, sf->num_calls_serviced);
grpc_call_destroy(s);
cq_verifier_destroy(cqv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
}
}
static void perform_request(client_fixture *cf) {
grpc_call *c;
cq_verifier *cqv = cq_verifier_create(cf->cq);
grpc_op ops[6];
grpc_op *op;
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_status_code status;
grpc_call_error error;
char *details = NULL;
size_t details_capacity = 0;
grpc_byte_buffer *request_payload;
grpc_byte_buffer *response_payload_recv;
int i;
memset(ops, 0, sizeof(ops));
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
c = grpc_channel_create_call(cf->client, NULL, GRPC_PROPAGATE_DEFAULTS,
cf->cq, "/foo", "foo.test.google.fr:1234",
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1000), NULL);
gpr_log(GPR_INFO, "Call 0x%" PRIxPTR " created", (intptr_t)c);
GPR_ASSERT(c);
char *peer;
grpc_metadata_array_init(&initial_metadata_recv);
grpc_metadata_array_init(&trailing_metadata_recv);
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata = &initial_metadata_recv;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
op->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
for (i = 0; i < 4; i++) {
request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
op = ops;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message = request_payload;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = &response_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
peer = grpc_call_get_peer(c);
cq_expect_completion(cqv, tag(2), 1);
cq_verify(cqv);
gpr_free(peer);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
}
gpr_slice_unref(request_payload_slice);
op = ops;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(1), 1);
cq_expect_completion(cqv, tag(3), 1);
cq_verify(cqv);
peer = grpc_call_get_peer(c);
gpr_log(GPR_INFO, "Client DONE WITH SERVER %s ", peer);
gpr_free(peer);
grpc_call_destroy(c);
cq_verify_empty_timeout(cqv, 1);
cq_verifier_destroy(cqv);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
gpr_free(details);
}
static void setup_client(const char *server_hostport, client_fixture *cf) {
cf->cq = grpc_completion_queue_create(NULL);
cf->server_uri = gpr_strdup(server_hostport);
cf->client = grpc_insecure_channel_create(cf->server_uri, NULL, NULL);
}
static void teardown_client(client_fixture *cf) {
grpc_completion_queue_shutdown(cf->cq);
drain_cq(cf->cq);
grpc_completion_queue_destroy(cf->cq);
cf->cq = NULL;
grpc_channel_destroy(cf->client);
cf->client = NULL;
gpr_free(cf->server_uri);
}
static void setup_server(const char *host, server_fixture *sf) {
int assigned_port;
sf->cq = grpc_completion_queue_create(NULL);
const char *colon_idx = strchr(host, ':');
if (colon_idx) {
const char *port_str = colon_idx + 1;
sf->port = atoi(port_str);
sf->servers_hostport = gpr_strdup(host);
} else {
sf->port = grpc_pick_unused_port_or_die();
gpr_join_host_port(&sf->servers_hostport, host, sf->port);
}
sf->server = grpc_server_create(NULL, NULL);
grpc_server_register_completion_queue(sf->server, sf->cq, NULL);
GPR_ASSERT((assigned_port = grpc_server_add_insecure_http2_port(
sf->server, sf->servers_hostport)) > 0);
GPR_ASSERT(sf->port == assigned_port);
grpc_server_start(sf->server);
}
static void teardown_server(server_fixture *sf) {
if (!sf->server) return;
gpr_log(GPR_INFO, "Server[%s] shutting down", sf->servers_hostport);
grpc_server_shutdown_and_notify(sf->server, sf->cq, tag(1000));
GPR_ASSERT(grpc_completion_queue_pluck(
sf->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
.type == GRPC_OP_COMPLETE);
grpc_server_destroy(sf->server);
gpr_thd_join(sf->tid);
sf->server = NULL;
grpc_completion_queue_shutdown(sf->cq);
drain_cq(sf->cq);
grpc_completion_queue_destroy(sf->cq);
gpr_log(GPR_INFO, "Server[%s] bye bye", sf->servers_hostport);
gpr_free(sf->servers_hostport);
}
static void fork_backend_server(void *arg) {
server_fixture *sf = static_cast<server_fixture *>(arg);
start_backend_server(sf);
}
static void fork_lb_server(void *arg) {
test_fixture *tf = static_cast<test_fixture *>(arg);
int ports[NUM_BACKENDS];
for (int i = 0; i < NUM_BACKENDS; i++) {
ports[i] = tf->lb_backends[i].port;
}
start_lb_server(&tf->lb_server, ports, NUM_BACKENDS,
tf->lb_server_update_delay_ms);
}
static void setup_test_fixture(test_fixture *tf,
int lb_server_update_delay_ms) {
tf->lb_server_update_delay_ms = lb_server_update_delay_ms;
gpr_thd_options options = gpr_thd_options_default();
gpr_thd_options_set_joinable(&options);
for (int i = 0; i < NUM_BACKENDS; ++i) {
setup_server("127.0.0.1", &tf->lb_backends[i]);
gpr_thd_new(&tf->lb_backends[i].tid, fork_backend_server,
&tf->lb_backends[i], &options);
}
setup_server("127.0.0.1", &tf->lb_server);
gpr_thd_new(&tf->lb_server.tid, fork_lb_server, &tf->lb_server, &options);
char *server_uri;
gpr_asprintf(&server_uri, "ipv4:%s?lb_policy=grpclb&lb_enabled=1",
tf->lb_server.servers_hostport);
setup_client(server_uri, &tf->client);
gpr_free(server_uri);
}
static void teardown_test_fixture(test_fixture *tf) {
teardown_client(&tf->client);
for (int i = 0; i < NUM_BACKENDS; ++i) {
teardown_server(&tf->lb_backends[i]);
}
teardown_server(&tf->lb_server);
}
// The LB server will send two updates: batch 1 and batch 2. Each batch
// contains
// two addresses, both of a valid and running backend server. Batch 1 is
// readily
// available and provided as soon as the client establishes the streaming
// call.
// Batch 2 is sent after a delay of \a lb_server_update_delay_ms
// milliseconds.
static test_fixture test_update(int lb_server_update_delay_ms) {
gpr_log(GPR_INFO, "start %s(%d)", __func__, lb_server_update_delay_ms);
test_fixture tf;
memset(&tf, 0, sizeof(tf));
setup_test_fixture(&tf, lb_server_update_delay_ms);
perform_request(
&tf.client); // "consumes" 1st backend server of 1st serverlist
perform_request(
&tf.client); // "consumes" 2nd backend server of 1st serverlist
perform_request(
&tf.client); // "consumes" 1st backend server of 2nd serverlist
perform_request(
&tf.client); // "consumes" 2nd backend server of 2nd serverlist
teardown_test_fixture(&tf);
gpr_log(GPR_INFO, "end %s(%d)", __func__, lb_server_update_delay_ms);
return tf;
}
} // namespace
} // namespace grpc
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
grpc::test_fixture tf_result;
// Clients take a bit over one second to complete a call (the last part of the
// call sleeps for 1 second while verifying the client's completion queue is
// empty). Therefore:
//
// If the LB server waits 800ms before sending an update, it will arrive
// before the first client request is done, skipping the second server from
// batch 1 altogether: the 2nd client request will go to the 1st server of
// batch 2 (ie, the third one out of the four total servers).
tf_result = grpc::test_update(800);
GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 0);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced == 2);
GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 1);
// If the LB server waits 1500ms, the update arrives after having picked the
// 2nd server from batch 1 but before the next pick for the first server of
// batch 2. All server are used.
tf_result = grpc::test_update(1500);
GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 1);
// If the LB server waits > 2000ms, the update arrives after the first two
// request are done and the third pick is performed, which returns, in RR
// fashion, the 1st server of the 1st update. Therefore, the second server of
// batch 1 is hit twice, whereas the first server of batch 2 is never hit.
tf_result = grpc::test_update(2100);
GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 2);
GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced == 1);
GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 0);
grpc_shutdown();
return 0;
}

@ -931,6 +931,7 @@ src/core/ext/client_config/subchannel.h \
src/core/ext/client_config/subchannel_call_holder.h \
src/core/ext/client_config/subchannel_index.h \
src/core/ext/client_config/uri_parser.h \
src/core/ext/lb_policy/grpclb/grpclb.h \
src/core/ext/lb_policy/grpclb/load_balancer_api.h \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \
third_party/nanopb/pb.h \
@ -1111,6 +1112,7 @@ 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/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \

@ -2245,6 +2245,27 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc++",
"grpc++_test_util",
"grpc_test_util"
],
"headers": [
"src/proto/grpc/lb/v1/load_balancer.grpc.pb.h",
"src/proto/grpc/lb/v1/load_balancer.pb.h"
],
"language": "c++",
"name": "grpclb_test",
"src": [
"test/cpp/grpclb/grpclb_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -4177,6 +4198,7 @@
"gpr",
"grpc_base",
"grpc_lb_policy_grpclb",
"grpc_lb_policy_grpclb",
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_load_reporting",
@ -4230,6 +4252,7 @@
"gpr",
"gpr_test_util",
"grpc",
"grpc_base",
"grpc_test_util_base"
],
"headers": [
@ -4271,6 +4294,7 @@
"gpr",
"grpc_base",
"grpc_lb_policy_grpclb",
"grpc_lb_policy_grpclb",
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_load_reporting",
@ -6063,12 +6087,15 @@
"nanopb"
],
"headers": [
"src/core/ext/lb_policy/grpclb/grpclb.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
],
"language": "c",
"name": "grpc_lb_policy_grpclb",
"src": [
"src/core/ext/lb_policy/grpclb/grpclb.c",
"src/core/ext/lb_policy/grpclb/grpclb.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",

@ -2290,6 +2290,27 @@
"windows"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"flaky": false,
"gtest": false,
"language": "c++",
"name": "grpclb_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{
"args": [],
"ci_platforms": [

@ -440,6 +440,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_call_holder.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\subchannel_index.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
<ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
@ -787,6 +788,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.c">

@ -496,6 +496,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c">
<Filter>src\core\ext\transport\chttp2\client\insecure</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClCompile>
@ -1079,6 +1082,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.h">
<Filter>src\core\ext\client_config</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClInclude>

@ -146,6 +146,35 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\status.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\core\end2end\data\ssl_test_data.h" />
<ClInclude Include="$(SolutionDir)\..\test\core\security\oauth2_utils.h" />
@ -160,6 +189,85 @@
<ClInclude Include="$(SolutionDir)\..\test\core\util\port.h" />
<ClInclude Include="$(SolutionDir)\..\test\core\util\port_server_client.h" />
<ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\client_certs.c">
@ -196,6 +304,182 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\util\slice_splitter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">

@ -52,6 +52,353 @@
<ClCompile Include="$(SolutionDir)\..\test\core\util\slice_splitter.c">
<Filter>test\core\util</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
<Filter>src\core\lib\compression</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
<Filter>src\core\lib\compression</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c">
<Filter>src\core\lib\debug</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c">
<Filter>src\core\lib\http</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c">
<Filter>src\core\lib\http</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\http\parser.c">
<Filter>src\core\lib\http</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_common_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_linux.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix_noop.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_eventfd.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_nospecial.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json.c">
<Filter>src\core\lib\json</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_reader.c">
<Filter>src\core\lib\json</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_string.c">
<Filter>src\core\lib\json</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\json\json_writer.c">
<Filter>src\core\lib\json</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\alarm.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\byte_buffer_reader.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_details.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\call_log_batch.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_ping.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\event_string.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\metadata_array.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\server.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\validate_metadata.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\version.c">
<Filter>src\core\lib\surface</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
<Filter>include\grpc</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer_reader.h">
<Filter>include\grpc</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\compression.h">
<Filter>include\grpc</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\grpc.h">
<Filter>include\grpc</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_posix.h">
<Filter>include\grpc</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\status.h">
<Filter>include\grpc</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\core\end2end\data\ssl_test_data.h">
@ -93,9 +440,291 @@
<ClInclude Include="$(SolutionDir)\..\test\core\util\slice_splitter.h">
<Filter>test\core\util</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_args.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\channel_stack_builder.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\compress_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\connected_channel.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\context.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
<Filter>src\core\lib\compression</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h">
<Filter>src\core\lib\compression</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h">
<Filter>src\core\lib\debug</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h">
<Filter>src\core\lib\http</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h">
<Filter>src\core\lib\http</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h">
<Filter>src\core\lib\http</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\closure.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_and_epoll_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iocp_windows.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\polling_entity.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_set_windows.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\pollset_windows.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\resolve_address.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_utils.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sockaddr_windows.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_server.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_windows.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\time_averaged_stats.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_pipe.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\wakeup_fd_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_posix.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\workqueue_windows.h">
<Filter>src\core\lib\iomgr</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json.h">
<Filter>src\core\lib\json</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_common.h">
<Filter>src\core\lib\json</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_reader.h">
<Filter>src\core\lib\json</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\json\json_writer.h">
<Filter>src\core\lib\json</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\api_trace.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\call_test_only.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_init.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\channel_stack_type.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\completion_queue.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\event_string.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\init.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\lame_client.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\surface\server.h">
<Filter>src\core\lib\surface</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\byte_stream.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\connectivity_state.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="include">
<UniqueIdentifier>{50129440-aff7-7df7-682c-b9671be19a6f}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc">
<UniqueIdentifier>{d448b078-95a6-6fca-fe4a-8b44dd71f359}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc\impl">
<UniqueIdentifier>{314a6801-6fe3-9211-33d8-ecf3332c1151}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc\impl\codegen">
<UniqueIdentifier>{8e97f1e1-f4d1-a56e-0837-7901778fb3b9}</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{7d107d7c-1da3-9525-3ba1-3a411b552ea8}</UniqueIdentifier>
</Filter>
<Filter Include="src\core">
<UniqueIdentifier>{f7bfac91-5eb2-dea7-4601-6c63edbbf997}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib">
<UniqueIdentifier>{f4e8c61e-1ca6-0fdd-7b5e-b7f9a30c9a21}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\channel">
<UniqueIdentifier>{1cd1503c-bec0-5ade-c75f-aa25c80975ec}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\compression">
<UniqueIdentifier>{09632582-2cc3-5618-d673-65d3884f8ce5}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\debug">
<UniqueIdentifier>{2c1a72e9-886e-8082-9d2f-0fc9cb3ab996}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\http">
<UniqueIdentifier>{4862ecce-fa07-eb5e-5c05-bfa753c8bfe5}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\iomgr">
<UniqueIdentifier>{fc7f488e-08b4-8366-3720-1f7ffaa0b0b3}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\json">
<UniqueIdentifier>{89bc8f83-e29a-ddab-8f6b-22df11cdc867}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\surface">
<UniqueIdentifier>{7f2b7dca-395f-94dd-c9ad-9a286bd9751e}</UniqueIdentifier>
</Filter>
<Filter Include="src\core\lib\transport">
<UniqueIdentifier>{5249e884-ea07-6782-531d-ec622c54b9af}</UniqueIdentifier>
</Filter>
<Filter Include="test">
<UniqueIdentifier>{a2783de3-4fcf-718d-a859-c2108350ff33}</UniqueIdentifier>
</Filter>

@ -407,6 +407,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_config\uri_parser.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
<ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
@ -702,6 +703,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.c">

@ -421,6 +421,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.c">
<Filter>src\core\ext\load_reporting</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.c">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.c">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClCompile>
@ -920,6 +923,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\load_reporting\load_reporting_filter.h">
<Filter>src\core\ext\load_reporting</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h">
<Filter>src\core\ext\lb_policy\grpclb</Filter>
</ClInclude>

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9D6FFE17-ABF0-A851-268E-9E3E8C573CBB}</ProjectGuid>
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
<Import Project="$(SolutionDir)\..\vsprojects\global.props" />
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
<Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetName>grpclb_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetName>grpclb_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.pb.cc">
</ClCompile>
<ClInclude Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.pb.h">
</ClInclude>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.grpc.pb.cc">
</ClCompile>
<ClInclude Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.grpc.pb.h">
</ClInclude>
<ClCompile Include="$(SolutionDir)\..\test\cpp\grpclb\grpclb_test.cc">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
<Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
<Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
</Target>
</Project>

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.proto">
<Filter>src\proto\grpc\lb\v1</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\grpclb\grpclb_test.cc">
<Filter>test\cpp\grpclb</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{082bbcbc-bbd8-db7d-afe9-fa0fec76863d}</UniqueIdentifier>
</Filter>
<Filter Include="src\proto">
<UniqueIdentifier>{7c61995a-80c2-ef3d-0a4b-baf2221c12f8}</UniqueIdentifier>
</Filter>
<Filter Include="src\proto\grpc">
<UniqueIdentifier>{fc2920d4-902c-fdf0-d4b8-6b22e1361105}</UniqueIdentifier>
</Filter>
<Filter Include="src\proto\grpc\lb">
<UniqueIdentifier>{4778352a-559f-b008-e3d2-4ae9181260df}</UniqueIdentifier>
</Filter>
<Filter Include="src\proto\grpc\lb\v1">
<UniqueIdentifier>{36a4326b-4f2a-4720-b730-e40fe078fd40}</UniqueIdentifier>
</Filter>
<Filter Include="test">
<UniqueIdentifier>{e0ba55a2-37d9-5029-6f4e-64f097307340}</UniqueIdentifier>
</Filter>
<Filter Include="test\cpp">
<UniqueIdentifier>{ad67d6ba-d08b-7879-2929-20f0f01c9918}</UniqueIdentifier>
</Filter>
<Filter Include="test\cpp\grpclb">
<UniqueIdentifier>{4498fa30-2dab-584c-5711-a1055cec30f6}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save