Merge github.com:grpc/grpc into nudiff

pull/10048/head
Craig Tiller 8 years ago
commit 77bcd5a58a
  1. 24
      .pylintrc
  2. 64
      CMakeLists.txt
  3. 80
      Makefile
  4. 21
      bazel/cc_grpc_library.bzl
  5. 3
      bazel/grpc_build_system.bzl
  6. 24
      build.yaml
  7. 2
      composer.json
  8. 2
      doc/PROTOCOL-WEB.md
  9. 60
      doc/server_side_auth.md
  10. 2
      examples/php/composer.json
  11. 2
      gRPC-Core.podspec
  12. 42
      package.xml
  13. 4
      src/compiler/cpp_generator.cc
  14. 2
      src/core/ext/client_channel/client_channel_plugin.c
  15. 10
      src/core/ext/client_channel/http_proxy.c
  16. 22
      src/core/ext/client_channel/parse_address.c
  17. 22
      src/core/ext/client_channel/resolver_registry.c
  18. 5
      src/core/ext/client_channel/resolver_registry.h
  19. 11
      src/core/ext/client_channel/subchannel.c
  20. 3
      src/core/ext/client_channel/subchannel.h
  21. 37
      src/core/ext/client_channel/uri_parser.c
  22. 4
      src/core/ext/client_channel/uri_parser.h
  23. 2
      src/core/ext/lb_policy/grpclb/grpclb.c
  24. 2
      src/core/ext/transport/chttp2/client/chttp2_connector.c
  25. 3
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  26. 7
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  27. 4
      src/core/lib/http/parser.c
  28. 10
      src/core/lib/iomgr/sockaddr_utils.c
  29. 8
      src/core/lib/support/sync.c
  30. 4
      src/core/lib/surface/call.c
  31. 35
      src/core/lib/transport/transport.c
  32. 6
      src/core/lib/transport/transport.h
  33. 2
      src/core/lib/tsi/test_creds/BUILD
  34. 4
      src/cpp/server/health/default_health_check_service.cc
  35. 2
      src/php/README.md
  36. 2
      src/php/composer.json
  37. 26
      src/python/grpcio/grpc/__init__.py
  38. 24
      src/python/grpcio/grpc/_auth.py
  39. 17
      src/python/grpcio/grpc/_channel.py
  40. 12
      src/python/grpcio/grpc/_common.py
  41. 6
      src/python/grpcio/grpc/_plugin_wrapping.py
  42. 20
      src/python/grpcio/grpc/_server.py
  43. 5
      src/python/grpcio/grpc/beta/_client_adaptations.py
  44. 159
      src/python/grpcio/grpc/beta/_connectivity_channel.py
  45. 18
      src/python/grpcio/grpc/beta/_server_adaptations.py
  46. 9
      src/python/grpcio/grpc/beta/implementations.py
  47. 2
      src/python/grpcio/grpc/framework/foundation/logging_pool.py
  48. 2
      src/python/grpcio_tests/tests/http2/negative_http2_client.py
  49. 2
      templates/composer.json.template
  50. 2
      templates/gRPC-Core.podspec.template
  51. 42
      templates/package.xml.template
  52. 2
      templates/src/php/composer.json.template
  53. 2
      test/core/census/BUILD
  54. 2
      test/core/channel/BUILD
  55. 116
      test/core/client_channel/parse_address_test.c
  56. 2
      test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
  57. 4
      test/core/client_channel/resolvers/dns_resolver_test.c
  58. 4
      test/core/client_channel/resolvers/sockaddr_resolver_test.c
  59. 5
      test/core/client_channel/uri_fuzzer_test.c
  60. 23
      test/core/client_channel/uri_parser_test.c
  61. 2
      test/core/compression/BUILD
  62. BIN
      test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6520142139752448
  63. 2
      test/core/handshake/BUILD
  64. 16
      test/core/iomgr/sockaddr_utils_test.c
  65. 33
      test/core/iomgr/tcp_server_posix_test.c
  66. 1
      test/core/slice/percent_encoding_test.c
  67. 2
      test/core/support/BUILD
  68. 2
      test/core/surface/BUILD
  69. 7
      test/core/transport/BUILD
  70. 58
      test/core/transport/stream_owned_slice_test.c
  71. 3
      test/core/util/BUILD
  72. 48
      test/core/util/port.c
  73. 256
      test/core/util/port_posix.c
  74. 10
      test/core/util/port_server_client.c
  75. 7
      test/core/util/port_server_client.h
  76. 247
      test/core/util/port_windows.c
  77. 2
      test/cpp/codegen/compiler_test_golden
  78. 98
      test/cpp/interop/http2_client.cc
  79. 3
      test/cpp/interop/http2_client.h
  80. 45
      test/cpp/microbenchmarks/bm_call_create.cc
  81. 15
      test/cpp/microbenchmarks/bm_metadata.cc
  82. 3
      tools/dockerfile/interoptest/grpc_interop_cxx/build_interop.sh
  83. 1
      tools/doxygen/Doxyfile.c++
  84. 1
      tools/doxygen/Doxyfile.c++.internal
  85. 1
      tools/doxygen/Doxyfile.core
  86. 1
      tools/doxygen/Doxyfile.core.internal
  87. 2
      tools/gce/linux_performance_worker_init.sh
  88. 17
      tools/internal_ci/windows/grpc_master.bat
  89. 73
      tools/jenkins/run_full_performance_released.sh
  90. 138
      tools/profiling/microbenchmarks/bm2bq.py
  91. 5
      tools/profiling/microbenchmarks/bm_json.py
  92. 38
      tools/run_tests/generated/sources_and_headers.json
  93. 66
      tools/run_tests/generated/tests.json
  94. 11
      tools/run_tests/performance/scenario_config.py
  95. 15
      tools/run_tests/python_utils/start_port_server.py
  96. 6
      tools/run_tests/run_interop_tests.py
  97. 15
      tools/run_tests/run_microbenchmark.py
  98. 17
      tools/run_tests/run_tests.py
  99. 3
      tools/run_tests/run_tests_matrix.py
  100. 46
      tools/run_tests/start_port_server.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,3 +1,14 @@
[VARIABLES]
# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection
# not include "unused_" and "ignored_" by default?
dummy-variables-rgx=^ignored_|^unused_
[MISCELLANEOUS]
# NOTE(nathaniel): We are big fans of "TODO(<issue link>): " and
# "NOTE(<username or issue link>): ". We do not allow "TODO:",
# "TODO(<username>):", "FIXME:", or anything else.
notes=FIXME,XXX
[MESSAGES CONTROL] [MESSAGES CONTROL]
#TODO: Enable missing-docstring #TODO: Enable missing-docstring
@ -11,15 +22,11 @@
#TODO: Enable protected-access #TODO: Enable protected-access
#TODO: Enable no-name-in-module #TODO: Enable no-name-in-module
#TODO: Enable unused-argument #TODO: Enable unused-argument
#TODO: Enable fixme
#TODO: Enable wrong-import-order #TODO: Enable wrong-import-order
#TODO: Enable no-value-for-parameter # TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279):
#TODO: Enable cyclic-import # enable cyclic-import after a 1.7-or-later pylint release that recognizes our
#TODO: Enable unused-variable # disable=cyclic-import suppressions.
#TODO: Enable redefined-outer-name
#TODO: Enable unused-import
#TODO: Enable too-many-instance-attributes #TODO: Enable too-many-instance-attributes
#TODO: Enable broad-except
#TODO: Enable too-many-locals #TODO: Enable too-many-locals
#TODO: Enable too-many-lines #TODO: Enable too-many-lines
#TODO: Enable redefined-variable-type #TODO: Enable redefined-variable-type
@ -29,6 +36,5 @@
#TODO: Enable too-many-return-statements #TODO: Enable too-many-return-statements
#TODO: Enable too-many-nested-blocks #TODO: Enable too-many-nested-blocks
#TODO: Enable super-init-not-called #TODO: Enable super-init-not-called
#TODO: Enable no-self-use
disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,wrong-import-order,cyclic-import,too-many-instance-attributes,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called

@ -440,6 +440,7 @@ add_dependencies(buildtests_c mlog_test)
add_dependencies(buildtests_c multiple_server_queues_test) add_dependencies(buildtests_c multiple_server_queues_test)
add_dependencies(buildtests_c murmur_hash_test) add_dependencies(buildtests_c murmur_hash_test)
add_dependencies(buildtests_c no_server_test) add_dependencies(buildtests_c no_server_test)
add_dependencies(buildtests_c parse_address_test)
add_dependencies(buildtests_c percent_encoding_test) add_dependencies(buildtests_c percent_encoding_test)
if(_gRPC_PLATFORM_LINUX) if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c pollset_set_test) add_dependencies(buildtests_c pollset_set_test)
@ -464,6 +465,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c socket_utils_test) add_dependencies(buildtests_c socket_utils_test)
endif() endif()
add_dependencies(buildtests_c status_conversion_test) add_dependencies(buildtests_c status_conversion_test)
add_dependencies(buildtests_c stream_owned_slice_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c tcp_client_posix_test) add_dependencies(buildtests_c tcp_client_posix_test)
endif() endif()
@ -1447,10 +1449,8 @@ add_library(grpc_test_util
test/core/util/mock_endpoint.c test/core/util/mock_endpoint.c
test/core/util/parse_hexstring.c test/core/util/parse_hexstring.c
test/core/util/passthru_endpoint.c test/core/util/passthru_endpoint.c
test/core/util/port_posix.c test/core/util/port.c
test/core/util/port_server_client.c test/core/util/port_server_client.c
test/core/util/port_uv.c
test/core/util/port_windows.c
test/core/util/slice_splitter.c test/core/util/slice_splitter.c
test/core/util/trickle_endpoint.c test/core/util/trickle_endpoint.c
src/core/lib/channel/channel_args.c src/core/lib/channel/channel_args.c
@ -1656,10 +1656,8 @@ add_library(grpc_test_util_unsecure
test/core/util/mock_endpoint.c test/core/util/mock_endpoint.c
test/core/util/parse_hexstring.c test/core/util/parse_hexstring.c
test/core/util/passthru_endpoint.c test/core/util/passthru_endpoint.c
test/core/util/port_posix.c test/core/util/port.c
test/core/util/port_server_client.c test/core/util/port_server_client.c
test/core/util/port_uv.c
test/core/util/port_windows.c
test/core/util/slice_splitter.c test/core/util/slice_splitter.c
test/core/util/trickle_endpoint.c test/core/util/trickle_endpoint.c
) )
@ -6443,6 +6441,33 @@ target_link_libraries(no_server_test
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_executable(parse_address_test
test/core/client_channel/parse_address_test.c
)
target_include_directories(parse_address_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(parse_address_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(percent_encoding_test add_executable(percent_encoding_test
test/core/slice/percent_encoding_test.c test/core/slice/percent_encoding_test.c
) )
@ -6933,6 +6958,33 @@ target_link_libraries(status_conversion_test
gpr gpr
) )
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(stream_owned_slice_test
test/core/transport/stream_owned_slice_test.c
)
target_include_directories(stream_owned_slice_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(stream_owned_slice_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)

@ -1002,6 +1002,7 @@ murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test
nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test
nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test
no_server_test: $(BINDIR)/$(CONFIG)/no_server_test no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
parse_address_test: $(BINDIR)/$(CONFIG)/parse_address_test
percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer
percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test
@ -1024,6 +1025,7 @@ sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test
socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test
ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test
stream_owned_slice_test: $(BINDIR)/$(CONFIG)/stream_owned_slice_test
tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test tcp_client_posix_test: $(BINDIR)/$(CONFIG)/tcp_client_posix_test
tcp_client_uv_test: $(BINDIR)/$(CONFIG)/tcp_client_uv_test tcp_client_uv_test: $(BINDIR)/$(CONFIG)/tcp_client_uv_test
tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test tcp_posix_test: $(BINDIR)/$(CONFIG)/tcp_posix_test
@ -1360,6 +1362,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/multiple_server_queues_test \ $(BINDIR)/$(CONFIG)/multiple_server_queues_test \
$(BINDIR)/$(CONFIG)/murmur_hash_test \ $(BINDIR)/$(CONFIG)/murmur_hash_test \
$(BINDIR)/$(CONFIG)/no_server_test \ $(BINDIR)/$(CONFIG)/no_server_test \
$(BINDIR)/$(CONFIG)/parse_address_test \
$(BINDIR)/$(CONFIG)/percent_encoding_test \ $(BINDIR)/$(CONFIG)/percent_encoding_test \
$(BINDIR)/$(CONFIG)/pollset_set_test \ $(BINDIR)/$(CONFIG)/pollset_set_test \
$(BINDIR)/$(CONFIG)/resolve_address_posix_test \ $(BINDIR)/$(CONFIG)/resolve_address_posix_test \
@ -1378,6 +1381,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/sockaddr_utils_test \ $(BINDIR)/$(CONFIG)/sockaddr_utils_test \
$(BINDIR)/$(CONFIG)/socket_utils_test \ $(BINDIR)/$(CONFIG)/socket_utils_test \
$(BINDIR)/$(CONFIG)/status_conversion_test \ $(BINDIR)/$(CONFIG)/status_conversion_test \
$(BINDIR)/$(CONFIG)/stream_owned_slice_test \
$(BINDIR)/$(CONFIG)/tcp_client_posix_test \ $(BINDIR)/$(CONFIG)/tcp_client_posix_test \
$(BINDIR)/$(CONFIG)/tcp_client_uv_test \ $(BINDIR)/$(CONFIG)/tcp_client_uv_test \
$(BINDIR)/$(CONFIG)/tcp_posix_test \ $(BINDIR)/$(CONFIG)/tcp_posix_test \
@ -1793,6 +1797,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/murmur_hash_test || ( echo test murmur_hash_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/murmur_hash_test || ( echo test murmur_hash_test failed ; exit 1 )
$(E) "[RUN] Testing no_server_test" $(E) "[RUN] Testing no_server_test"
$(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 )
$(E) "[RUN] Testing parse_address_test"
$(Q) $(BINDIR)/$(CONFIG)/parse_address_test || ( echo test parse_address_test failed ; exit 1 )
$(E) "[RUN] Testing percent_encoding_test" $(E) "[RUN] Testing percent_encoding_test"
$(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 )
$(E) "[RUN] Testing pollset_set_test" $(E) "[RUN] Testing pollset_set_test"
@ -1829,6 +1835,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 )
$(E) "[RUN] Testing status_conversion_test" $(E) "[RUN] Testing status_conversion_test"
$(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 )
$(E) "[RUN] Testing stream_owned_slice_test"
$(Q) $(BINDIR)/$(CONFIG)/stream_owned_slice_test || ( echo test stream_owned_slice_test failed ; exit 1 )
$(E) "[RUN] Testing tcp_client_posix_test" $(E) "[RUN] Testing tcp_client_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/tcp_client_posix_test || ( echo test tcp_client_posix_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/tcp_client_posix_test || ( echo test tcp_client_posix_test failed ; exit 1 )
$(E) "[RUN] Testing tcp_client_uv_test" $(E) "[RUN] Testing tcp_client_uv_test"
@ -3319,10 +3327,8 @@ LIBGRPC_TEST_UTIL_SRC = \
test/core/util/mock_endpoint.c \ test/core/util/mock_endpoint.c \
test/core/util/parse_hexstring.c \ test/core/util/parse_hexstring.c \
test/core/util/passthru_endpoint.c \ test/core/util/passthru_endpoint.c \
test/core/util/port_posix.c \ test/core/util/port.c \
test/core/util/port_server_client.c \ test/core/util/port_server_client.c \
test/core/util/port_uv.c \
test/core/util/port_windows.c \
test/core/util/slice_splitter.c \ test/core/util/slice_splitter.c \
test/core/util/trickle_endpoint.c \ test/core/util/trickle_endpoint.c \
src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_args.c \
@ -3521,10 +3527,8 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
test/core/util/mock_endpoint.c \ test/core/util/mock_endpoint.c \
test/core/util/parse_hexstring.c \ test/core/util/parse_hexstring.c \
test/core/util/passthru_endpoint.c \ test/core/util/passthru_endpoint.c \
test/core/util/port_posix.c \ test/core/util/port.c \
test/core/util/port_server_client.c \ test/core/util/port_server_client.c \
test/core/util/port_uv.c \
test/core/util/port_windows.c \
test/core/util/slice_splitter.c \ test/core/util/slice_splitter.c \
test/core/util/trickle_endpoint.c \ test/core/util/trickle_endpoint.c \
@ -11083,6 +11087,38 @@ endif
endif endif
PARSE_ADDRESS_TEST_SRC = \
test/core/client_channel/parse_address_test.c \
PARSE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PARSE_ADDRESS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/parse_address_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/parse_address_test: $(PARSE_ADDRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(PARSE_ADDRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/parse_address_test
endif
$(OBJDIR)/$(CONFIG)/test/core/client_channel/parse_address_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_parse_address_test: $(PARSE_ADDRESS_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(PARSE_ADDRESS_TEST_OBJS:.o=.dep)
endif
endif
PERCENT_DECODE_FUZZER_SRC = \ PERCENT_DECODE_FUZZER_SRC = \
test/core/slice/percent_decode_fuzzer.c \ test/core/slice/percent_decode_fuzzer.c \
@ -11787,6 +11823,38 @@ endif
endif endif
STREAM_OWNED_SLICE_TEST_SRC = \
test/core/transport/stream_owned_slice_test.c \
STREAM_OWNED_SLICE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STREAM_OWNED_SLICE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/stream_owned_slice_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/stream_owned_slice_test: $(STREAM_OWNED_SLICE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(STREAM_OWNED_SLICE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/stream_owned_slice_test
endif
$(OBJDIR)/$(CONFIG)/test/core/transport/stream_owned_slice_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_stream_owned_slice_test: $(STREAM_OWNED_SLICE_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(STREAM_OWNED_SLICE_TEST_OBJS:.o=.dep)
endif
endif
TCP_CLIENT_POSIX_TEST_SRC = \ TCP_CLIENT_POSIX_TEST_SRC = \
test/core/iomgr/tcp_client_posix_test.c \ test/core/iomgr/tcp_client_posix_test.c \

@ -2,7 +2,7 @@
load("//:bazel/generate_cc.bzl", "generate_cc") load("//:bazel/generate_cc.bzl", "generate_cc")
def cc_grpc_library(name, srcs, deps, proto_only, **kwargs): def cc_grpc_library(name, srcs, deps, proto_only, use_external = False, **kwargs):
"""Generates C++ grpc classes from a .proto file. """Generates C++ grpc classes from a .proto file.
Assumes the generated classes will be used in cc_api_version = 2. Assumes the generated classes will be used in cc_api_version = 2.
@ -12,6 +12,8 @@ def cc_grpc_library(name, srcs, deps, proto_only, **kwargs):
srcs: a single proto_library, which wraps the .proto files with services. srcs: a single proto_library, which wraps the .proto files with services.
deps: a list of C++ proto_library (or cc_proto_library) which provides deps: a list of C++ proto_library (or cc_proto_library) which provides
the compiled code of any message that the services depend on. the compiled code of any message that the services depend on.
use_external: When True the grpc deps are prefixed with //external. This
allows grpc to be used as a dependency in other bazel projects.
**kwargs: rest of arguments, e.g., compatible_with and visibility. **kwargs: rest of arguments, e.g., compatible_with and visibility.
""" """
if len(srcs) > 1: if len(srcs) > 1:
@ -37,18 +39,31 @@ def cc_grpc_library(name, srcs, deps, proto_only, **kwargs):
) )
if not proto_only: if not proto_only:
if use_external:
# when this file is used by non-grpc projects
plugin = "//external:grpc_cpp_plugin"
else:
plugin = "//:grpc_cpp_plugin"
generate_cc( generate_cc(
name = codegen_grpc_target, name = codegen_grpc_target,
srcs = [proto_target], srcs = [proto_target],
plugin = "//:grpc_cpp_plugin", plugin = plugin,
**kwargs **kwargs
) )
if use_external:
# when this file is used by non-grpc projects
grpc_deps = ["//external:grpc++", "//external:grpc++_codegen_proto",
"//external:protobuf"]
else:
grpc_deps = ["//:grpc++", "//:grpc++_codegen_proto", "//external:protobuf"]
native.cc_library( native.cc_library(
name = name, name = name,
srcs = [":" + codegen_grpc_target, ":" + codegen_target], srcs = [":" + codegen_grpc_target, ":" + codegen_target],
hdrs = [":" + codegen_grpc_target, ":" + codegen_target], hdrs = [":" + codegen_grpc_target, ":" + codegen_target],
deps = deps + ["//:grpc++", "//:grpc++_codegen_proto", "//external:protobuf"], deps = deps + grpc_deps,
**kwargs **kwargs
) )
else: else:

@ -58,11 +58,12 @@ def grpc_proto_plugin(name, srcs = [], deps = []):
load("//:bazel/cc_grpc_library.bzl", "cc_grpc_library") load("//:bazel/cc_grpc_library.bzl", "cc_grpc_library")
def grpc_proto_library(name, srcs = [], deps = [], well_known_deps = [], has_services = True): def grpc_proto_library(name, srcs = [], deps = [], well_known_deps = [], has_services = True, use_external = False):
cc_grpc_library( cc_grpc_library(
name = name, name = name,
srcs = srcs, srcs = srcs,
deps = deps, deps = deps,
proto_only = not has_services, proto_only = not has_services,
use_external = use_external,
) )

@ -611,10 +611,8 @@ filegroups:
- test/core/util/mock_endpoint.c - test/core/util/mock_endpoint.c
- test/core/util/parse_hexstring.c - test/core/util/parse_hexstring.c
- test/core/util/passthru_endpoint.c - test/core/util/passthru_endpoint.c
- test/core/util/port_posix.c - test/core/util/port.c
- test/core/util/port_server_client.c - test/core/util/port_server_client.c
- test/core/util/port_uv.c
- test/core/util/port_windows.c
- test/core/util/slice_splitter.c - test/core/util/slice_splitter.c
- test/core/util/trickle_endpoint.c - test/core/util/trickle_endpoint.c
deps: deps:
@ -2494,6 +2492,16 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: parse_address_test
build: test
language: c
src:
- test/core/client_channel/parse_address_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: percent_decode_fuzzer - name: percent_decode_fuzzer
build: fuzzer build: fuzzer
language: c language: c
@ -2750,6 +2758,16 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: stream_owned_slice_test
build: test
language: c
src:
- test/core/transport/stream_owned_slice_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: tcp_client_posix_test - name: tcp_client_posix_test
cpu_cost: 0.5 cpu_cost: 0.5
build: test build: test

@ -7,7 +7,7 @@
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"require": { "require": {
"php": ">=5.5.0", "php": ">=5.5.0",
"google/protobuf": "v3.1.0" "google/protobuf": "^v3.1.0"
}, },
"require-dev": { "require-dev": {
"google/auth": "v0.9" "google/auth": "v0.9"

@ -94,8 +94,6 @@ the response stream needs to be text encoded e.g. when XHR is used or due
to security policies with XHR to security policies with XHR
* Accept: application/grpc-web-text * Accept: application/grpc-web-text
2. The default text encoding is base64 2. The default text encoding is base64
* Text encoding may be specified with Content-Type or Accept headers as
* application/grpc-web-text-base64
* Note that “Content-Transfer-Encoding: base64” should not be used. * Note that “Content-Transfer-Encoding: base64” should not be used.
Due to in-stream base64 padding when delimiting messages, the entire Due to in-stream base64 padding when delimiting messages, the entire
response body is not necessarily a valid base64-encoded entity response body is not necessarily a valid base64-encoded entity

@ -0,0 +1,60 @@
Server-side API for Authenticating Clients
==========================================
NOTE: This document describes how server-side authentication works in C-core based gRPC implementations only. In gRPC Java and Go, server side authentication is handled differently.
## AuthContext
To perform server-side authentication, gRPC exposes the *authentication context* for each call. The context exposes important authentication-related information about the RPC such as the type of security/authentication type being used and the peer identity.
The authentication context is structured as a multi-map of key-value pairs - the *auth properties*. In addition to that, for authenticated RPCs, the set of properties corresponding to a selected key will represent the verified identity of the caller - the *peer identity*.
The contents of the *auth properties* are populated by an *auth interceptor*. The interceptor also chooses which property key will act as the peer identity (e.g. for client certificate authentication this property will be `"x509_common_name"` or `"x509_subject_alternative_name"`).
WARNING: AuthContext is the only reliable source of truth when it comes to authenticating RPCs. Using any other call/context properties for authentication purposes is wrong and inherently unsafe.
####Example AuthContext contents
For secure channel using mutual TLS authentication with both client and server certificates (test certificates from this repository are used).
Populated auth properties:
```
"transport_security_type": "ssl" # connection is secured using TLS/SSL
"x509_common_name": "*.test.google.com" # from client's certificate
"x509_pem_cert": "-----BEGIN CERTIFICATE-----\n..." # client's PEM encoded certificate
"x509_subject_alternative_name": "*.test.google.fr"
"x509_subject_alternative_name": "waterzooi.test.google.be"
"x509_subject_alternative_name": "*.test.youtube.com"
"x509_subject_alternative_name": "192.168.1.3"
```
The peer identity is set of all properties named `"x509_subject_alternative_name"`:
```
peer_identity_property_name = "x509_subject_alternative_name"
```
## AuthProperty
Auth properties are elements of the AuthContext. They have a name (a key of type string) and a value which can be a string or binary data.
## Auth Interceptors
Auth interceptors are gRPC components that populate contents of the auth context based on gRPC's internal state and/or call metadata.
gRPC comes with some basic "interceptors" already built-in.
WARNING: While there is a public API that allows anyone to write their own custom interceptor, please think twice before using it.
There are legitimate uses for custom interceptors but you should keep in mind that as auth interceptors essentially decide which RPCs are authenticated and which are not, their code is very sensitive from the security perspective and getting things wrong might have serious consequences. If unsure, we strongly recommend to rely on official & proven interceptors that come with gRPC.
####Available auth interceptors
- TLS/SSL certificate authentication (built into gRPC's security layer, automatically used whenever you use a secure connection)
- (coming soon) JWT auth token authentication
- more will be added over time
## Status (by language)
C-core exposes low level API to access auth context contents and to implement an auth interceptor.
In C++, the auth interceptor API is exposed as `AuthMetadataProcessor`.
A high level API to access AuthContext contents is available in these languages:
- C++
- C# (implementation in-progress)
- other languages coming soon

@ -2,7 +2,7 @@
"name": "grpc/grpc-demo", "name": "grpc/grpc-demo",
"description": "gRPC example for PHP", "description": "gRPC example for PHP",
"require": { "require": {
"grpc/grpc": "v1.1.0" "grpc/grpc": "^v1.1.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

@ -917,7 +917,7 @@ Pod::Spec.new do |s|
'test/core/util/debugger_macros.c', 'test/core/util/debugger_macros.c',
'test/core/util/test_config.{c,h}', 'test/core/util/test_config.{c,h}',
'test/core/util/port.h', 'test/core/util/port.h',
'test/core/util/port_posix.c', 'test/core/util/port.c',
'test/core/util/port_server_client.{c,h}' 'test/core/util/port_server_client.{c,h}'
end end
end end

@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email> <email>grpc-packages@google.com</email>
<active>yes</active> <active>yes</active>
</lead> </lead>
<date>2017-01-13</date> <date>2017-03-01</date>
<time>16:06:07</time> <time>16:06:07</time>
<version> <version>
<release>1.2.0dev</release> <release>1.2.0dev</release>
@ -22,8 +22,8 @@
</stability> </stability>
<license>BSD</license> <license>BSD</license>
<notes> <notes>
- PHP Proto3 adoption #8179 - Added arg info macros #9751
- Various bug fixes - Updated codegen to be consistent with protobuf #9492
</notes> </notes>
<contents> <contents>
<dir baseinstalldir="/" name="/"> <dir baseinstalldir="/" name="/">
@ -1276,8 +1276,8 @@ Update to wrap gRPC C Core version 0.10.0
</release> </release>
<release> <release>
<version> <version>
<release>1.1.0dev</release> <release>1.1.0RC1</release>
<api>1.1.0dev</api> <api>1.1.0RC1</api>
</version> </version>
<stability> <stability>
<release>beta</release> <release>beta</release>
@ -1290,5 +1290,37 @@ Update to wrap gRPC C Core version 0.10.0
- Various bug fixes - Various bug fixes
</notes> </notes>
</release> </release>
<release>
<version>
<release>1.1.0</release>
<api>1.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2017-01-31</date>
<license>BSD</license>
<notes>
- PHP Proto3 adoption #8179
- Various bug fixes
</notes>
</release>
<release>
<version>
<release>1.2.0RC1</release>
<api>1.2.0RC1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2017-03-01</date>
<license>BSD</license>
<notes>
- Added arg info macros #9751
- Updated codegen to be consistent with protobuf #9492
</notes>
</release>
</changelog> </changelog>
</package> </package>

@ -102,7 +102,7 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
vars["filename_base"] = file->filename_without_ext(); vars["filename_base"] = file->filename_without_ext();
vars["message_header_ext"] = file->message_header_ext(); vars["message_header_ext"] = file->message_header_ext();
printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
printer->Print(vars, printer->Print(vars,
"// If you make any local change, they will be lost.\n"); "// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n"); printer->Print(vars, "// source: $filename$\n");
@ -1010,7 +1010,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
vars["message_header_ext"] = file->message_header_ext(); vars["message_header_ext"] = file->message_header_ext();
vars["service_header_ext"] = file->service_header_ext(); vars["service_header_ext"] = file->service_header_ext();
printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
printer->Print(vars, printer->Print(vars,
"// If you make any local change, they will be lost.\n"); "// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n\n"); printer->Print(vars, "// source: $filename$\n\n");

@ -64,7 +64,7 @@ static bool set_default_host_if_unset(grpc_exec_ctx *exec_ctx,
} }
} }
char *default_authority = grpc_get_default_authority( char *default_authority = grpc_get_default_authority(
grpc_channel_stack_builder_get_target(builder)); exec_ctx, grpc_channel_stack_builder_get_target(builder));
if (default_authority != NULL) { if (default_authority != NULL) {
grpc_arg arg; grpc_arg arg;
arg.type = GRPC_ARG_STRING; arg.type = GRPC_ARG_STRING;

@ -46,10 +46,11 @@
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/support/env.h" #include "src/core/lib/support/env.h"
static char* grpc_get_http_proxy_server() { static char* grpc_get_http_proxy_server(grpc_exec_ctx* exec_ctx) {
char* uri_str = gpr_getenv("http_proxy"); char* uri_str = gpr_getenv("http_proxy");
if (uri_str == NULL) return NULL; if (uri_str == NULL) return NULL;
grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */); grpc_uri* uri =
grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */);
char* proxy_name = NULL; char* proxy_name = NULL;
if (uri == NULL || uri->authority == NULL) { if (uri == NULL || uri->authority == NULL) {
gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var"); gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var");
@ -76,9 +77,10 @@ static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
const grpc_channel_args* args, const grpc_channel_args* args,
char** name_to_resolve, char** name_to_resolve,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
*name_to_resolve = grpc_get_http_proxy_server(); *name_to_resolve = grpc_get_http_proxy_server(exec_ctx);
if (*name_to_resolve == NULL) return false; if (*name_to_resolve == NULL) return false;
grpc_uri* uri = grpc_uri_parse(server_uri, false /* suppress_errors */); grpc_uri* uri =
grpc_uri_parse(exec_ctx, server_uri, false /* suppress_errors */);
if (uri == NULL || uri->path[0] == '\0') { if (uri == NULL || uri->path[0] == '\0') {
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"'http_proxy' environment variable set, but cannot " "'http_proxy' environment variable set, but cannot "

@ -44,6 +44,7 @@
#include <grpc/support/host_port.h> #include <grpc/support/host_port.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/support/string.h"
#ifdef GRPC_HAVE_UNIX_SOCKET #ifdef GRPC_HAVE_UNIX_SOCKET
@ -120,10 +121,31 @@ int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
memset(in6, 0, sizeof(*in6)); memset(in6, 0, sizeof(*in6));
resolved_addr->len = sizeof(*in6); resolved_addr->len = sizeof(*in6);
in6->sin6_family = AF_INET6; in6->sin6_family = AF_INET6;
/* Handle the RFC6874 syntax for IPv6 zone identifiers. */
char *host_end = (char *)gpr_memrchr(host, '%', strlen(host));
if (host_end != NULL) {
GPR_ASSERT(host_end >= host);
char host_without_scope[INET6_ADDRSTRLEN];
size_t host_without_scope_len = (size_t)(host_end - host);
strncpy(host_without_scope, host, host_without_scope_len);
host_without_scope[host_without_scope_len] = '\0';
if (inet_pton(AF_INET6, host_without_scope, &in6->sin6_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host_without_scope);
goto done;
}
if (gpr_parse_bytes_to_uint32(host_end + 1,
strlen(host) - host_without_scope_len - 1,
&in6->sin6_scope_id) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1);
goto done;
}
} else {
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) { if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host); gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
goto done; goto done;
} }
}
if (port != NULL) { if (port != NULL) {
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||

@ -108,22 +108,23 @@ static grpc_resolver_factory *lookup_factory_by_uri(grpc_uri *uri) {
return lookup_factory(uri->scheme); return lookup_factory(uri->scheme);
} }
static grpc_resolver_factory *resolve_factory(const char *target, static grpc_resolver_factory *resolve_factory(grpc_exec_ctx *exec_ctx,
const char *target,
grpc_uri **uri, grpc_uri **uri,
char **canonical_target) { char **canonical_target) {
grpc_resolver_factory *factory = NULL; grpc_resolver_factory *factory = NULL;
GPR_ASSERT(uri != NULL); GPR_ASSERT(uri != NULL);
*uri = grpc_uri_parse(target, 1); *uri = grpc_uri_parse(exec_ctx, target, 1);
factory = lookup_factory_by_uri(*uri); factory = lookup_factory_by_uri(*uri);
if (factory == NULL) { if (factory == NULL) {
grpc_uri_destroy(*uri); grpc_uri_destroy(*uri);
gpr_asprintf(canonical_target, "%s%s", g_default_resolver_prefix, target); gpr_asprintf(canonical_target, "%s%s", g_default_resolver_prefix, target);
*uri = grpc_uri_parse(*canonical_target, 1); *uri = grpc_uri_parse(exec_ctx, *canonical_target, 1);
factory = lookup_factory_by_uri(*uri); factory = lookup_factory_by_uri(*uri);
if (factory == NULL) { if (factory == NULL) {
grpc_uri_destroy(grpc_uri_parse(target, 0)); grpc_uri_destroy(grpc_uri_parse(exec_ctx, target, 0));
grpc_uri_destroy(grpc_uri_parse(*canonical_target, 0)); grpc_uri_destroy(grpc_uri_parse(exec_ctx, *canonical_target, 0));
gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target, gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target,
*canonical_target); *canonical_target);
} }
@ -138,7 +139,7 @@ grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
grpc_uri *uri = NULL; grpc_uri *uri = NULL;
char *canonical_target = NULL; char *canonical_target = NULL;
grpc_resolver_factory *factory = grpc_resolver_factory *factory =
resolve_factory(target, &uri, &canonical_target); resolve_factory(exec_ctx, target, &uri, &canonical_target);
grpc_resolver *resolver; grpc_resolver *resolver;
grpc_resolver_args resolver_args; grpc_resolver_args resolver_args;
memset(&resolver_args, 0, sizeof(resolver_args)); memset(&resolver_args, 0, sizeof(resolver_args));
@ -153,21 +154,22 @@ grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
return resolver; return resolver;
} }
char *grpc_get_default_authority(const char *target) { char *grpc_get_default_authority(grpc_exec_ctx *exec_ctx, const char *target) {
grpc_uri *uri = NULL; grpc_uri *uri = NULL;
char *canonical_target = NULL; char *canonical_target = NULL;
grpc_resolver_factory *factory = grpc_resolver_factory *factory =
resolve_factory(target, &uri, &canonical_target); resolve_factory(exec_ctx, target, &uri, &canonical_target);
char *authority = grpc_resolver_factory_get_default_authority(factory, uri); char *authority = grpc_resolver_factory_get_default_authority(factory, uri);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
gpr_free(canonical_target); gpr_free(canonical_target);
return authority; return authority;
} }
char *grpc_resolver_factory_add_default_prefix_if_needed(const char *target) { char *grpc_resolver_factory_add_default_prefix_if_needed(
grpc_exec_ctx *exec_ctx, const char *target) {
grpc_uri *uri = NULL; grpc_uri *uri = NULL;
char *canonical_target = NULL; char *canonical_target = NULL;
resolve_factory(target, &uri, &canonical_target); resolve_factory(exec_ctx, target, &uri, &canonical_target);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
return canonical_target == NULL ? gpr_strdup(target) : canonical_target; return canonical_target == NULL ? gpr_strdup(target) : canonical_target;
} }

@ -74,10 +74,11 @@ grpc_resolver_factory *grpc_resolver_factory_lookup(const char *name);
/** Given a target, return a (freshly allocated with gpr_malloc) string /** Given a target, return a (freshly allocated with gpr_malloc) string
representing the default authority to pass from a client. */ representing the default authority to pass from a client. */
char *grpc_get_default_authority(const char *target); char *grpc_get_default_authority(grpc_exec_ctx *exec_ctx, const char *target);
/** Returns a newly allocated string containing \a target, adding the /** Returns a newly allocated string containing \a target, adding the
default prefix if needed. */ default prefix if needed. */
char *grpc_resolver_factory_add_default_prefix_if_needed(const char *target); char *grpc_resolver_factory_add_default_prefix_if_needed(
grpc_exec_ctx *exec_ctx, const char *target);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */

@ -331,7 +331,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
} }
c->pollset_set = grpc_pollset_set_create(); c->pollset_set = grpc_pollset_set_create();
grpc_resolved_address *addr = gpr_malloc(sizeof(*addr)); grpc_resolved_address *addr = gpr_malloc(sizeof(*addr));
grpc_get_subchannel_address_arg(args->args, addr); grpc_get_subchannel_address_arg(exec_ctx, args->args, addr);
grpc_set_initial_connect_string(&addr, &c->initial_connect_string); grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
grpc_resolved_address *new_address = NULL; grpc_resolved_address *new_address = NULL;
grpc_channel_args *new_args = NULL; grpc_channel_args *new_args = NULL;
@ -787,9 +787,9 @@ grpc_call_stack *grpc_subchannel_call_get_call_stack(
return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
} }
static void grpc_uri_to_sockaddr(const char *uri_str, static void grpc_uri_to_sockaddr(grpc_exec_ctx *exec_ctx, const char *uri_str,
grpc_resolved_address *addr) { grpc_resolved_address *addr) {
grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); grpc_uri *uri = grpc_uri_parse(exec_ctx, uri_str, 0 /* suppress_errors */);
GPR_ASSERT(uri != NULL); GPR_ASSERT(uri != NULL);
if (strcmp(uri->scheme, "ipv4") == 0) { if (strcmp(uri->scheme, "ipv4") == 0) {
GPR_ASSERT(parse_ipv4(uri, addr)); GPR_ASSERT(parse_ipv4(uri, addr));
@ -801,12 +801,13 @@ static void grpc_uri_to_sockaddr(const char *uri_str,
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
} }
void grpc_get_subchannel_address_arg(const grpc_channel_args *args, void grpc_get_subchannel_address_arg(grpc_exec_ctx *exec_ctx,
const grpc_channel_args *args,
grpc_resolved_address *addr) { grpc_resolved_address *addr) {
const char *addr_uri_str = grpc_get_subchannel_address_uri_arg(args); const char *addr_uri_str = grpc_get_subchannel_address_uri_arg(args);
memset(addr, 0, sizeof(*addr)); memset(addr, 0, sizeof(*addr));
if (*addr_uri_str != '\0') { if (*addr_uri_str != '\0') {
grpc_uri_to_sockaddr(addr_uri_str, addr); grpc_uri_to_sockaddr(exec_ctx, addr_uri_str, addr);
} }
} }

@ -175,7 +175,8 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
const grpc_subchannel_args *args); const grpc_subchannel_args *args);
/// Sets \a addr from \a args. /// Sets \a addr from \a args.
void grpc_get_subchannel_address_arg(const grpc_channel_args *args, void grpc_get_subchannel_address_arg(grpc_exec_ctx *exec_ctx,
const grpc_channel_args *args,
grpc_resolved_address *addr); grpc_resolved_address *addr);
/// Returns the URI string for the address to connect to. /// Returns the URI string for the address to connect to.

@ -35,13 +35,15 @@
#include <string.h> #include <string.h>
#include <grpc/slice.h>
#include <grpc/slice_buffer.h> #include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
/** a size_t default value... maps to all 1's */ /** a size_t default value... maps to all 1's */
@ -68,11 +70,16 @@ static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section,
return NULL; return NULL;
} }
/** Returns a copy of \a src[begin, end) */ /** Returns a copy of percent decoded \a src[begin, end) */
static char *copy_component(const char *src, size_t begin, size_t end) { static char *decode_and_copy_component(grpc_exec_ctx *exec_ctx, const char *src,
char *out = gpr_malloc(end - begin + 1); size_t begin, size_t end) {
memcpy(out, src + begin, end - begin); grpc_slice component =
out[end - begin] = 0; grpc_slice_from_copied_buffer(src + begin, end - begin);
grpc_slice decoded_component =
grpc_permissive_percent_decode_slice(component);
char *out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII);
grpc_slice_unref_internal(exec_ctx, component);
grpc_slice_unref_internal(exec_ctx, decoded_component);
return out; return out;
} }
@ -175,7 +182,8 @@ static void parse_query_parts(grpc_uri *uri) {
} }
} }
grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) { grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text,
int suppress_errors) {
grpc_uri *uri; grpc_uri *uri;
size_t scheme_begin = 0; size_t scheme_begin = 0;
size_t scheme_end = NOT_SET; size_t scheme_end = NOT_SET;
@ -263,11 +271,16 @@ grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
} }
uri = gpr_zalloc(sizeof(*uri)); uri = gpr_zalloc(sizeof(*uri));
uri->scheme = copy_component(uri_text, scheme_begin, scheme_end); uri->scheme =
uri->authority = copy_component(uri_text, authority_begin, authority_end); decode_and_copy_component(exec_ctx, uri_text, scheme_begin, scheme_end);
uri->path = copy_component(uri_text, path_begin, path_end); uri->authority = decode_and_copy_component(exec_ctx, uri_text,
uri->query = copy_component(uri_text, query_begin, query_end); authority_begin, authority_end);
uri->fragment = copy_component(uri_text, fragment_begin, fragment_end); uri->path =
decode_and_copy_component(exec_ctx, uri_text, path_begin, path_end);
uri->query =
decode_and_copy_component(exec_ctx, uri_text, query_begin, query_end);
uri->fragment = decode_and_copy_component(exec_ctx, uri_text, fragment_begin,
fragment_end);
parse_query_parts(uri); parse_query_parts(uri);
return uri; return uri;

@ -35,6 +35,7 @@
#define GRPC_CORE_EXT_CLIENT_CHANNEL_URI_PARSER_H #define GRPC_CORE_EXT_CLIENT_CHANNEL_URI_PARSER_H
#include <stddef.h> #include <stddef.h>
#include "src/core/lib/iomgr/exec_ctx.h"
typedef struct { typedef struct {
char *scheme; char *scheme;
@ -51,7 +52,8 @@ typedef struct {
} grpc_uri; } grpc_uri;
/** parse a uri, return NULL on failure */ /** parse a uri, return NULL on failure */
grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors); grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text,
int suppress_errors);
/** return the part of a query string after the '=' in "?key=xxx&...", or NULL /** return the part of a query string after the '=' in "?key=xxx&...", or NULL
* if key is not present */ * if key is not present */

@ -861,7 +861,7 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI); arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(arg != NULL); GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_STRING); GPR_ASSERT(arg->type == GRPC_ARG_STRING);
grpc_uri *uri = grpc_uri_parse(arg->value.string, true); grpc_uri *uri = grpc_uri_parse(exec_ctx, arg->value.string, true);
GPR_ASSERT(uri->path[0] != '\0'); GPR_ASSERT(uri->path[0] != '\0');
glb_policy->server_name = glb_policy->server_name =
gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path); gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);

@ -226,7 +226,7 @@ static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx,
grpc_closure *notify) { grpc_closure *notify) {
chttp2_connector *c = (chttp2_connector *)con; chttp2_connector *c = (chttp2_connector *)con;
grpc_resolved_address addr; grpc_resolved_address addr;
grpc_get_subchannel_address_arg(args->channel_args, &addr); grpc_get_subchannel_address_arg(exec_ctx, args->channel_args, &addr);
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
GPR_ASSERT(c->notify == NULL); GPR_ASSERT(c->notify == NULL);
c->notify = notify; c->notify = notify;

@ -72,7 +72,8 @@ static grpc_channel *client_channel_factory_create_channel(
grpc_arg arg; grpc_arg arg;
arg.type = GRPC_ARG_STRING; arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVER_URI; arg.key = GRPC_ARG_SERVER_URI;
arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(target); arg.value.string =
grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target);
const char *to_remove[] = {GRPC_ARG_SERVER_URI}; const char *to_remove[] = {GRPC_ARG_SERVER_URI};
grpc_channel_args *new_args = grpc_channel_args *new_args =
grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1); grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);

@ -83,7 +83,7 @@ static grpc_subchannel_args *get_secure_naming_subchannel_args(
const char *server_uri_str = server_uri_arg->value.string; const char *server_uri_str = server_uri_arg->value.string;
GPR_ASSERT(server_uri_str != NULL); GPR_ASSERT(server_uri_str != NULL);
grpc_uri *server_uri = grpc_uri *server_uri =
grpc_uri_parse(server_uri_str, true /* supress errors */); grpc_uri_parse(exec_ctx, server_uri_str, true /* supress errors */);
GPR_ASSERT(server_uri != NULL); GPR_ASSERT(server_uri != NULL);
const char *server_uri_path; const char *server_uri_path;
server_uri_path = server_uri_path =
@ -96,7 +96,7 @@ static grpc_subchannel_args *get_secure_naming_subchannel_args(
const char *target_uri_str = const char *target_uri_str =
grpc_get_subchannel_address_uri_arg(args->args); grpc_get_subchannel_address_uri_arg(args->args);
grpc_uri *target_uri = grpc_uri *target_uri =
grpc_uri_parse(target_uri_str, false /* suppress errors */); grpc_uri_parse(exec_ctx, target_uri_str, false /* suppress errors */);
GPR_ASSERT(target_uri != NULL); GPR_ASSERT(target_uri != NULL);
if (target_uri->path[0] != '\0') { // "path" may be empty if (target_uri->path[0] != '\0') { // "path" may be empty
const grpc_slice key = grpc_slice_from_static_string( const grpc_slice key = grpc_slice_from_static_string(
@ -181,7 +181,8 @@ static grpc_channel *client_channel_factory_create_channel(
grpc_arg arg; grpc_arg arg;
arg.type = GRPC_ARG_STRING; arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVER_URI; arg.key = GRPC_ARG_SERVER_URI;
arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(target); arg.value.string =
grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target);
const char *to_remove[] = {GRPC_ARG_SERVER_URI}; const char *to_remove[] = {GRPC_ARG_SERVER_URI};
grpc_channel_args *new_args = grpc_channel_args *new_args =
grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1); grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);

@ -284,9 +284,9 @@ static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte,
case GRPC_HTTP_HEADERS: case GRPC_HTTP_HEADERS:
if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) { if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) {
if (grpc_http1_trace) if (grpc_http1_trace)
gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded", gpr_log(GPR_ERROR, "HTTP header max line length (%d) exceeded",
GRPC_HTTP_PARSER_MAX_HEADER_LENGTH); GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
return GRPC_ERROR_NONE; return GRPC_ERROR_CREATE("HTTP header max line length exceeded");
} }
parser->cur_line[parser->cur_line_length] = byte; parser->cur_line[parser->cur_line_length] = byte;
parser->cur_line_length++; parser->cur_line_length++;

@ -162,6 +162,7 @@ int grpc_sockaddr_to_string(char **out,
char ntop_buf[INET6_ADDRSTRLEN]; char ntop_buf[INET6_ADDRSTRLEN];
const void *ip = NULL; const void *ip = NULL;
int port; int port;
uint32_t sin6_scope_id = 0;
int ret; int ret;
*out = NULL; *out = NULL;
@ -177,10 +178,19 @@ int grpc_sockaddr_to_string(char **out,
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
ip = &addr6->sin6_addr; ip = &addr6->sin6_addr;
port = ntohs(addr6->sin6_port); port = ntohs(addr6->sin6_port);
sin6_scope_id = addr6->sin6_scope_id;
} }
if (ip != NULL && if (ip != NULL &&
grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) { grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) {
if (sin6_scope_id != 0) {
char *host_with_scope;
/* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */
gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
ret = gpr_join_host_port(out, host_with_scope, port);
gpr_free(host_with_scope);
} else {
ret = gpr_join_host_port(out, ntop_buf, port); ret = gpr_join_host_port(out, ntop_buf, port);
}
} else { } else {
ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family); ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
} }

@ -37,6 +37,8 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include <assert.h>
/* Number of mutexes to allocate for events, to avoid lock contention. /* Number of mutexes to allocate for events, to avoid lock contention.
Should be a prime. */ Should be a prime. */
enum { event_sync_partitions = 31 }; enum { event_sync_partitions = 31 };
@ -99,8 +101,12 @@ void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); } void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
void gpr_ref_non_zero(gpr_refcount *r) { void gpr_ref_non_zero(gpr_refcount *r) {
#ifndef NDEBUG
gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1); gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
GPR_ASSERT(prior > 0); assert(prior > 0);
#else
gpr_ref(r);
#endif
} }
void gpr_refn(gpr_refcount *r, int n) { void gpr_refn(gpr_refcount *r, int n) {

@ -161,6 +161,7 @@ struct grpc_call {
bool receiving_message; bool receiving_message;
bool requested_final_op; bool requested_final_op;
bool received_final_op; bool received_final_op;
bool sent_any_op;
/* have we received initial metadata */ /* have we received initial metadata */
bool has_initial_md_been_received; bool has_initial_md_been_received;
@ -488,7 +489,7 @@ void grpc_call_destroy(grpc_call *c) {
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->destroy_called); GPR_ASSERT(!c->destroy_called);
c->destroy_called = 1; c->destroy_called = 1;
cancel = !c->received_final_op; cancel = c->sent_any_op && !c->received_final_op;
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
if (cancel) { if (cancel) {
cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
@ -1678,6 +1679,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_closure_init(&bctl->finish_batch, finish_batch, bctl, grpc_closure_init(&bctl->finish_batch, finish_batch, bctl,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
stream_op->on_complete = &bctl->finish_batch; stream_op->on_complete = &bctl->finish_batch;
call->sent_any_op = true;
gpr_mu_unlock(&call->mu); gpr_mu_unlock(&call->mu);
execute_op(exec_ctx, call, stream_op); execute_op(exec_ctx, call, stream_op);

@ -84,6 +84,39 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
} }
} }
#define STREAM_REF_FROM_SLICE_REF(p) \
((grpc_stream_refcount *)(((uint8_t *)p) - \
offsetof(grpc_stream_refcount, slice_refcount)))
static void slice_stream_ref(void *p) {
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p), "slice");
#else
grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p));
#endif
}
static void slice_stream_unref(grpc_exec_ctx *exec_ctx, void *p) {
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p), "slice");
#else
grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p));
#endif
}
grpc_slice grpc_slice_from_stream_owned_buffer(grpc_stream_refcount *refcount,
void *buffer, size_t length) {
slice_stream_ref(&refcount->slice_refcount);
return (grpc_slice){.refcount = &refcount->slice_refcount,
.data.refcounted = {.bytes = buffer, .length = length}};
}
static const grpc_slice_refcount_vtable stream_ref_slice_vtable = {
.ref = slice_stream_ref,
.unref = slice_stream_unref,
.eq = grpc_slice_default_eq_impl,
.hash = grpc_slice_default_hash_impl};
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifdef GRPC_STREAM_REFCOUNT_DEBUG
void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
grpc_iomgr_cb_func cb, void *cb_arg, grpc_iomgr_cb_func cb, void *cb_arg,
@ -95,6 +128,8 @@ void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
#endif #endif
gpr_ref_init(&refcount->refs, initial_refs); gpr_ref_init(&refcount->refs, initial_refs);
grpc_closure_init(&refcount->destroy, cb, cb_arg, grpc_schedule_on_exec_ctx); grpc_closure_init(&refcount->destroy, cb, cb_arg, grpc_schedule_on_exec_ctx);
refcount->slice_refcount.vtable = &stream_ref_slice_vtable;
refcount->slice_refcount.sub_refcount = &refcount->slice_refcount;
} }
static void move64(uint64_t *from, uint64_t *to) { static void move64(uint64_t *from, uint64_t *to) {

@ -64,6 +64,7 @@ typedef struct grpc_stream_refcount {
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifdef GRPC_STREAM_REFCOUNT_DEBUG
const char *object_type; const char *object_type;
#endif #endif
grpc_slice_refcount slice_refcount;
} grpc_stream_refcount; } grpc_stream_refcount;
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifdef GRPC_STREAM_REFCOUNT_DEBUG
@ -84,6 +85,11 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount);
grpc_stream_ref_init(rc, ir, cb, cb_arg) grpc_stream_ref_init(rc, ir, cb, cb_arg)
#endif #endif
/* Wrap a buffer that is owned by some stream object into a slice that shares
the same refcount */
grpc_slice grpc_slice_from_stream_owned_buffer(grpc_stream_refcount *refcount,
void *buffer, size_t length);
typedef struct { typedef struct {
uint64_t framing_bytes; uint64_t framing_bytes;
uint64_t data_bytes; uint64_t data_bytes;

@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses(["notice"]) # 3-clause BSD
exports_files([ exports_files([
"ca.pem", "ca.pem",
"server1.key", "server1.key",

@ -63,7 +63,9 @@ Status DefaultHealthCheckService::HealthCheckServiceImpl::Check(
ServerContext* context, const ByteBuffer* request, ByteBuffer* response) { ServerContext* context, const ByteBuffer* request, ByteBuffer* response) {
// Decode request. // Decode request.
std::vector<Slice> slices; std::vector<Slice> slices;
request->Dump(&slices); if (!request->Dump(&slices).ok()) {
return Status(StatusCode::INVALID_ARGUMENT, "");
}
uint8_t* request_bytes = nullptr; uint8_t* request_bytes = nullptr;
bool request_bytes_owned = false; bool request_bytes_owned = false;
size_t request_size = 0; size_t request_size = 0;

@ -158,7 +158,7 @@ $ composer install
### Protobuf compiler ### Protobuf compiler
Again if you don't have it already, you need to install the protobuf compiler Again if you don't have it already, you need to install the protobuf compiler
`protoc`, version 3.2.0+. `protoc`, version 3.1.0+ (the newer the better).
If `protoc` hasn't been installed, you can download the `protoc` binaries from If `protoc` hasn't been installed, you can download the `protoc` binaries from
[the protocol buffers Github repository](https://github.com/google/protobuf/releases). [the protocol buffers Github repository](https://github.com/google/protobuf/releases).

@ -5,7 +5,7 @@
"version": "1.2.0", "version": "1.2.0",
"require": { "require": {
"php": ">=5.5.0", "php": ">=5.5.0",
"google/protobuf": "v3.1.0" "google/protobuf": "^v3.1.0"
}, },
"require-dev": { "require-dev": {
"google/auth": "v0.9" "google/auth": "v0.9"

@ -1004,7 +1004,7 @@ def unary_unary_rpc_method_handler(behavior,
An RpcMethodHandler for a unary-unary RPC method constructed from the given An RpcMethodHandler for a unary-unary RPC method constructed from the given
parameters. parameters.
""" """
from grpc import _utilities from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(False, False, request_deserializer, return _utilities.RpcMethodHandler(False, False, request_deserializer,
response_serializer, behavior, None, response_serializer, behavior, None,
None, None) None, None)
@ -1025,7 +1025,7 @@ def unary_stream_rpc_method_handler(behavior,
An RpcMethodHandler for a unary-stream RPC method constructed from the An RpcMethodHandler for a unary-stream RPC method constructed from the
given parameters. given parameters.
""" """
from grpc import _utilities from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(False, True, request_deserializer, return _utilities.RpcMethodHandler(False, True, request_deserializer,
response_serializer, None, behavior, response_serializer, None, behavior,
None, None) None, None)
@ -1046,7 +1046,7 @@ def stream_unary_rpc_method_handler(behavior,
An RpcMethodHandler for a stream-unary RPC method constructed from the An RpcMethodHandler for a stream-unary RPC method constructed from the
given parameters. given parameters.
""" """
from grpc import _utilities from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(True, False, request_deserializer, return _utilities.RpcMethodHandler(True, False, request_deserializer,
response_serializer, None, None, response_serializer, None, None,
behavior, None) behavior, None)
@ -1068,7 +1068,7 @@ def stream_stream_rpc_method_handler(behavior,
An RpcMethodHandler for a stream-stream RPC method constructed from the An RpcMethodHandler for a stream-stream RPC method constructed from the
given parameters. given parameters.
""" """
from grpc import _utilities from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(True, True, request_deserializer, return _utilities.RpcMethodHandler(True, True, request_deserializer,
response_serializer, None, None, None, response_serializer, None, None, None,
behavior) behavior)
@ -1085,7 +1085,7 @@ def method_handlers_generic_handler(service, method_handlers):
Returns: Returns:
A GenericRpcHandler constructed from the given parameters. A GenericRpcHandler constructed from the given parameters.
""" """
from grpc import _utilities from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.DictionaryGenericHandler(service, method_handlers) return _utilities.DictionaryGenericHandler(service, method_handlers)
@ -1124,7 +1124,7 @@ def metadata_call_credentials(metadata_plugin, name=None):
Returns: Returns:
A CallCredentials. A CallCredentials.
""" """
from grpc import _plugin_wrapping from grpc import _plugin_wrapping # pylint: disable=cyclic-import
if name is None: if name is None:
try: try:
effective_name = metadata_plugin.__name__ effective_name = metadata_plugin.__name__
@ -1147,7 +1147,7 @@ def access_token_call_credentials(access_token):
Returns: Returns:
A CallCredentials. A CallCredentials.
""" """
from grpc import _auth from grpc import _auth # pylint: disable=cyclic-import
return metadata_call_credentials( return metadata_call_credentials(
_auth.AccessTokenCallCredentials(access_token)) _auth.AccessTokenCallCredentials(access_token))
@ -1161,7 +1161,7 @@ def composite_call_credentials(*call_credentials):
Returns: Returns:
A CallCredentials object composed of the given CallCredentials objects. A CallCredentials object composed of the given CallCredentials objects.
""" """
from grpc import _credential_composition from grpc import _credential_composition # pylint: disable=cyclic-import
cygrpc_call_credentials = tuple( cygrpc_call_credentials = tuple(
single_call_credentials._credentials single_call_credentials._credentials
for single_call_credentials in call_credentials) for single_call_credentials in call_credentials)
@ -1180,7 +1180,7 @@ def composite_channel_credentials(channel_credentials, *call_credentials):
A ChannelCredentials composed of the given ChannelCredentials and A ChannelCredentials composed of the given ChannelCredentials and
CallCredentials objects. CallCredentials objects.
""" """
from grpc import _credential_composition from grpc import _credential_composition # pylint: disable=cyclic-import
cygrpc_call_credentials = tuple( cygrpc_call_credentials = tuple(
single_call_credentials._credentials single_call_credentials._credentials
for single_call_credentials in call_credentials) for single_call_credentials in call_credentials)
@ -1237,7 +1237,7 @@ def channel_ready_future(channel):
A Future that matures when the given Channel has connectivity A Future that matures when the given Channel has connectivity
ChannelConnectivity.READY. ChannelConnectivity.READY.
""" """
from grpc import _utilities from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.channel_ready_future(channel) return _utilities.channel_ready_future(channel)
@ -1252,7 +1252,7 @@ def insecure_channel(target, options=None):
Returns: Returns:
A Channel to the target through which RPCs may be conducted. A Channel to the target through which RPCs may be conducted.
""" """
from grpc import _channel from grpc import _channel # pylint: disable=cyclic-import
return _channel.Channel(target, () if options is None else options, None) return _channel.Channel(target, () if options is None else options, None)
@ -1268,7 +1268,7 @@ def secure_channel(target, credentials, options=None):
Returns: Returns:
A Channel to the target through which RPCs may be conducted. A Channel to the target through which RPCs may be conducted.
""" """
from grpc import _channel from grpc import _channel # pylint: disable=cyclic-import
return _channel.Channel(target, () if options is None else options, return _channel.Channel(target, () if options is None else options,
credentials._credentials) credentials._credentials)
@ -1290,7 +1290,7 @@ def server(thread_pool, handlers=None, options=None):
Returns: Returns:
A Server with which RPCs can be serviced. A Server with which RPCs can be serviced.
""" """
from grpc import _server from grpc import _server # pylint: disable=cyclic-import
return _server.Server(thread_pool, () if handlers is None else handlers, () return _server.Server(thread_pool, () if handlers is None else handlers, ()
if options is None else options) if options is None else options)

@ -39,6 +39,19 @@ def _sign_request(callback, token, error):
callback(metadata, error) callback(metadata, error)
def _create_get_token_callback(callback):
def get_token_callback(future):
try:
access_token = future.result().access_token
except Exception as exception: # pylint: disable=broad-except
_sign_request(callback, None, exception)
else:
_sign_request(callback, access_token, None)
return get_token_callback
class GoogleCallCredentials(grpc.AuthMetadataPlugin): class GoogleCallCredentials(grpc.AuthMetadataPlugin):
"""Metadata wrapper for GoogleCredentials from the oauth2client library.""" """Metadata wrapper for GoogleCredentials from the oauth2client library."""
@ -59,16 +72,7 @@ class GoogleCallCredentials(grpc.AuthMetadataPlugin):
additional_claims={'aud': context.service_url}) additional_claims={'aud': context.service_url})
else: else:
future = self._pool.submit(self._credentials.get_access_token) future = self._pool.submit(self._credentials.get_access_token)
future.add_done_callback( future.add_done_callback(_create_get_token_callback(callback))
lambda x: self._get_token_callback(callback, x))
def _get_token_callback(self, callback, future):
try:
access_token = future.result().access_token
except Exception as e:
_sign_request(callback, None, e)
else:
_sign_request(callback, access_token, None)
def __del__(self): def __del__(self):
self._pool.shutdown(wait=False) self._pool.shutdown(wait=False)

@ -200,7 +200,7 @@ def _consume_request_iterator(request_iterator, state, call,
request = next(request_iterator) request = next(request_iterator)
except StopIteration: except StopIteration:
break break
except Exception as e: except Exception: # pylint: disable=broad-except
logging.exception("Exception iterating requests!") logging.exception("Exception iterating requests!")
call.cancel() call.cancel()
_abort(state, grpc.StatusCode.UNKNOWN, _abort(state, grpc.StatusCode.UNKNOWN,
@ -387,13 +387,14 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call):
with self._state.condition: with self._state.condition:
while self._state.initial_metadata is None: while self._state.initial_metadata is None:
self._state.condition.wait() self._state.condition.wait()
return _common.application_metadata(self._state.initial_metadata) return _common.to_application_metadata(self._state.initial_metadata)
def trailing_metadata(self): def trailing_metadata(self):
with self._state.condition: with self._state.condition:
while self._state.trailing_metadata is None: while self._state.trailing_metadata is None:
self._state.condition.wait() self._state.condition.wait()
return _common.application_metadata(self._state.trailing_metadata) return _common.to_application_metadata(
self._state.trailing_metadata)
def code(self): def code(self):
with self._state.condition: with self._state.condition:
@ -473,7 +474,7 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None) state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None)
operations = ( operations = (
cygrpc.operation_send_initial_metadata( cygrpc.operation_send_initial_metadata(
_common.cygrpc_metadata(metadata), _EMPTY_FLAGS), _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_request, _EMPTY_FLAGS), cygrpc.operation_send_message(serialized_request, _EMPTY_FLAGS),
cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),
@ -563,7 +564,7 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
)), event_handler) )), event_handler)
operations = ( operations = (
cygrpc.operation_send_initial_metadata( cygrpc.operation_send_initial_metadata(
_common.cygrpc_metadata(metadata), _common.to_cygrpc_metadata(metadata),
_EMPTY_FLAGS), cygrpc.operation_send_message( _EMPTY_FLAGS), cygrpc.operation_send_message(
serialized_request, _EMPTY_FLAGS), serialized_request, _EMPTY_FLAGS),
cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
@ -603,7 +604,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
None) None)
operations = ( operations = (
cygrpc.operation_send_initial_metadata( cygrpc.operation_send_initial_metadata(
_common.cygrpc_metadata(metadata), _EMPTY_FLAGS), _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),)
call_error = call.start_client_batch( call_error = call.start_client_batch(
@ -657,7 +658,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
event_handler) event_handler)
operations = ( operations = (
cygrpc.operation_send_initial_metadata( cygrpc.operation_send_initial_metadata(
_common.cygrpc_metadata(metadata), _EMPTY_FLAGS), _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS), cygrpc.operation_receive_message(_EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),)
call_error = call.start_client_batch( call_error = call.start_client_batch(
@ -700,7 +701,7 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable):
event_handler) event_handler)
operations = ( operations = (
cygrpc.operation_send_initial_metadata( cygrpc.operation_send_initial_metadata(
_common.cygrpc_metadata(metadata), _EMPTY_FLAGS), _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),)
call_error = call.start_client_batch( call_error = call.start_client_batch(
cygrpc.Operations(operations), event_handler) cygrpc.Operations(operations), event_handler)

@ -97,22 +97,22 @@ def decode(b):
def channel_args(options): def channel_args(options):
channel_args = [] cygrpc_args = []
for key, value in options: for key, value in options:
if isinstance(value, six.string_types): if isinstance(value, six.string_types):
channel_args.append(cygrpc.ChannelArg(encode(key), encode(value))) cygrpc_args.append(cygrpc.ChannelArg(encode(key), encode(value)))
else: else:
channel_args.append(cygrpc.ChannelArg(encode(key), value)) cygrpc_args.append(cygrpc.ChannelArg(encode(key), value))
return cygrpc.ChannelArgs(channel_args) return cygrpc.ChannelArgs(cygrpc_args)
def cygrpc_metadata(application_metadata): def to_cygrpc_metadata(application_metadata):
return EMPTY_METADATA if application_metadata is None else cygrpc.Metadata( return EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
cygrpc.Metadatum(encode(key), encode(value)) cygrpc.Metadatum(encode(key), encode(value))
for key, value in application_metadata) for key, value in application_metadata)
def application_metadata(cygrpc_metadata): def to_application_metadata(cygrpc_metadata):
if cygrpc_metadata is None: if cygrpc_metadata is None:
return () return ()
else: else:

@ -66,9 +66,9 @@ class _WrappedCygrpcCallback(object):
def _invoke_success(self, metadata): def _invoke_success(self, metadata):
try: try:
cygrpc_metadata = _common.cygrpc_metadata(metadata) cygrpc_metadata = _common.to_cygrpc_metadata(metadata)
except Exception as error: except Exception as exception: # pylint: disable=broad-except
self._invoke_failure(error) self._invoke_failure(exception)
return return
self.cygrpc_callback(cygrpc_metadata, cygrpc.StatusCode.ok, b'') self.cygrpc_callback(cygrpc_metadata, cygrpc.StatusCode.ok, b'')

@ -142,14 +142,14 @@ def _abort(state, call, code, details):
effective_details = details if state.details is None else state.details effective_details = details if state.details is None else state.details
if state.initial_metadata_allowed: if state.initial_metadata_allowed:
operations = (cygrpc.operation_send_initial_metadata( operations = (cygrpc.operation_send_initial_metadata(
_common.EMPTY_METADATA, _EMPTY_FLAGS), _common.EMPTY_METADATA,
cygrpc.operation_send_status_from_server( _EMPTY_FLAGS), cygrpc.operation_send_status_from_server(
_common.cygrpc_metadata(state.trailing_metadata), _common.to_cygrpc_metadata(state.trailing_metadata),
effective_code, effective_details, _EMPTY_FLAGS),) effective_code, effective_details, _EMPTY_FLAGS),)
token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN
else: else:
operations = (cygrpc.operation_send_status_from_server( operations = (cygrpc.operation_send_status_from_server(
_common.cygrpc_metadata(state.trailing_metadata), _common.to_cygrpc_metadata(state.trailing_metadata),
effective_code, effective_details, _EMPTY_FLAGS),) effective_code, effective_details, _EMPTY_FLAGS),)
token = _SEND_STATUS_FROM_SERVER_TOKEN token = _SEND_STATUS_FROM_SERVER_TOKEN
call.start_server_batch( call.start_server_batch(
@ -250,7 +250,7 @@ class _Context(grpc.ServicerContext):
self._state.disable_next_compression = True self._state.disable_next_compression = True
def invocation_metadata(self): def invocation_metadata(self):
return _common.application_metadata(self._rpc_event.request_metadata) return _common.to_application_metadata(self._rpc_event.request_metadata)
def peer(self): def peer(self):
return _common.decode(self._rpc_event.operation_call.peer()) return _common.decode(self._rpc_event.operation_call.peer())
@ -262,7 +262,8 @@ class _Context(grpc.ServicerContext):
else: else:
if self._state.initial_metadata_allowed: if self._state.initial_metadata_allowed:
operation = cygrpc.operation_send_initial_metadata( operation = cygrpc.operation_send_initial_metadata(
_common.cygrpc_metadata(initial_metadata), _EMPTY_FLAGS) _common.to_cygrpc_metadata(initial_metadata),
_EMPTY_FLAGS)
self._rpc_event.operation_call.start_server_batch( self._rpc_event.operation_call.start_server_batch(
cygrpc.Operations((operation,)), cygrpc.Operations((operation,)),
_send_initial_metadata(self._state)) _send_initial_metadata(self._state))
@ -273,7 +274,7 @@ class _Context(grpc.ServicerContext):
def set_trailing_metadata(self, trailing_metadata): def set_trailing_metadata(self, trailing_metadata):
with self._state.condition: with self._state.condition:
self._state.trailing_metadata = _common.cygrpc_metadata( self._state.trailing_metadata = _common.to_cygrpc_metadata(
trailing_metadata) trailing_metadata)
def set_code(self, code): def set_code(self, code):
@ -342,7 +343,7 @@ def _unary_request(rpc_event, state, request_deserializer):
if state.client is _CANCELLED or state.statused: if state.client is _CANCELLED or state.statused:
return None return None
else: else:
start_server_batch_result = rpc_event.operation_call.start_server_batch( rpc_event.operation_call.start_server_batch(
cygrpc.Operations( cygrpc.Operations(
(cygrpc.operation_receive_message(_EMPTY_FLAGS),)), (cygrpc.operation_receive_message(_EMPTY_FLAGS),)),
_receive_message(state, rpc_event.operation_call, _receive_message(state, rpc_event.operation_call,
@ -436,7 +437,8 @@ def _send_response(rpc_event, state, serialized_response):
def _status(rpc_event, state, serialized_response): def _status(rpc_event, state, serialized_response):
with state.condition: with state.condition:
if state.client is not _CANCELLED: if state.client is not _CANCELLED:
trailing_metadata = _common.cygrpc_metadata(state.trailing_metadata) trailing_metadata = _common.to_cygrpc_metadata(
state.trailing_metadata)
code = _completion_code(state) code = _completion_code(state)
details = _details(state) details = _details(state)
operations = [ operations = [

@ -30,7 +30,6 @@
import grpc import grpc
from grpc import _common from grpc import _common
from grpc._cython import cygrpc
from grpc.beta import interfaces from grpc.beta import interfaces
from grpc.framework.common import cardinality from grpc.framework.common import cardinality
from grpc.framework.foundation import future from grpc.framework.foundation import future
@ -621,8 +620,8 @@ class _GenericStub(face.GenericStub):
class _DynamicStub(face.DynamicStub): class _DynamicStub(face.DynamicStub):
def __init__(self, generic_stub, group, cardinalities): def __init__(self, backing_generic_stub, group, cardinalities):
self._generic_stub = generic_stub self._generic_stub = backing_generic_stub
self._group = group self._group = group
self._cardinalities = cardinalities self._cardinalities = cardinalities

@ -1,159 +0,0 @@
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Affords a connectivity-state-listenable channel."""
import threading
import time
from grpc._adapter import _low
from grpc._adapter import _types
from grpc.beta import interfaces
from grpc.framework.foundation import callable_util
_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = (
'Exception calling channel subscription callback!')
_LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
state: connectivity
for state, connectivity in zip(_types.ConnectivityState,
interfaces.ChannelConnectivity)
}
class ConnectivityChannel(object):
def __init__(self, low_channel):
self._lock = threading.Lock()
self._low_channel = low_channel
self._polling = False
self._connectivity = None
self._try_to_connect = False
self._callbacks_and_connectivities = []
self._delivering = False
def _deliveries(self, connectivity):
callbacks_needing_update = []
for callback_and_connectivity in self._callbacks_and_connectivities:
callback, callback_connectivity = callback_and_connectivity
if callback_connectivity is not connectivity:
callbacks_needing_update.append(callback)
callback_and_connectivity[1] = connectivity
return callbacks_needing_update
def _deliver(self, initial_connectivity, initial_callbacks):
connectivity = initial_connectivity
callbacks = initial_callbacks
while True:
for callback in callbacks:
callable_util.call_logging_exceptions(
callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE,
connectivity)
with self._lock:
callbacks = self._deliveries(self._connectivity)
if callbacks:
connectivity = self._connectivity
else:
self._delivering = False
return
def _spawn_delivery(self, connectivity, callbacks):
delivering_thread = threading.Thread(
target=self._deliver, args=(connectivity, callbacks,))
delivering_thread.start()
self._delivering = True
# TODO(issue 3064): Don't poll.
def _poll_connectivity(self, low_channel, initial_try_to_connect):
try_to_connect = initial_try_to_connect
low_connectivity = low_channel.check_connectivity_state(try_to_connect)
with self._lock:
self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[
low_connectivity]
callbacks = tuple(
callback
for callback, unused_but_known_to_be_none_connectivity in
self._callbacks_and_connectivities)
for callback_and_connectivity in self._callbacks_and_connectivities:
callback_and_connectivity[1] = self._connectivity
if callbacks:
self._spawn_delivery(self._connectivity, callbacks)
completion_queue = _low.CompletionQueue()
while True:
low_channel.watch_connectivity_state(low_connectivity,
time.time() + 0.2,
completion_queue, None)
event = completion_queue.next()
with self._lock:
if not self._callbacks_and_connectivities and not self._try_to_connect:
self._polling = False
self._connectivity = None
completion_queue.shutdown()
break
try_to_connect = self._try_to_connect
self._try_to_connect = False
if event.success or try_to_connect:
low_connectivity = low_channel.check_connectivity_state(
try_to_connect)
with self._lock:
self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[
low_connectivity]
if not self._delivering:
callbacks = self._deliveries(self._connectivity)
if callbacks:
self._spawn_delivery(self._connectivity, callbacks)
def subscribe(self, callback, try_to_connect):
with self._lock:
if not self._callbacks_and_connectivities and not self._polling:
polling_thread = threading.Thread(
target=self._poll_connectivity,
args=(self._low_channel, bool(try_to_connect)))
polling_thread.start()
self._polling = True
self._callbacks_and_connectivities.append([callback, None])
elif not self._delivering and self._connectivity is not None:
self._spawn_delivery(self._connectivity, (callback,))
self._try_to_connect |= bool(try_to_connect)
self._callbacks_and_connectivities.append(
[callback, self._connectivity])
else:
self._try_to_connect |= bool(try_to_connect)
self._callbacks_and_connectivities.append([callback, None])
def unsubscribe(self, callback):
with self._lock:
for index, (subscribed_callback, unused_connectivity
) in enumerate(self._callbacks_and_connectivities):
if callback == subscribed_callback:
self._callbacks_and_connectivities.pop(index)
break
def low_channel(self):
return self._low_channel

@ -78,7 +78,7 @@ class _FaceServicerContext(face.ServicerContext):
return _ServerProtocolContext(self._servicer_context) return _ServerProtocolContext(self._servicer_context)
def invocation_metadata(self): def invocation_metadata(self):
return _common.cygrpc_metadata( return _common.to_cygrpc_metadata(
self._servicer_context.invocation_metadata()) self._servicer_context.invocation_metadata())
def initial_metadata(self, initial_metadata): def initial_metadata(self, initial_metadata):
@ -351,27 +351,27 @@ class _GenericRpcHandler(grpc.GenericRpcHandler):
class _Server(interfaces.Server): class _Server(interfaces.Server):
def __init__(self, server): def __init__(self, grpc_server):
self._server = server self._grpc_server = grpc_server
def add_insecure_port(self, address): def add_insecure_port(self, address):
return self._server.add_insecure_port(address) return self._grpc_server.add_insecure_port(address)
def add_secure_port(self, address, server_credentials): def add_secure_port(self, address, server_credentials):
return self._server.add_secure_port(address, server_credentials) return self._grpc_server.add_secure_port(address, server_credentials)
def start(self): def start(self):
self._server.start() self._grpc_server.start()
def stop(self, grace): def stop(self, grace):
return self._server.stop(grace) return self._grpc_server.stop(grace)
def __enter__(self): def __enter__(self):
self._server.start() self._grpc_server.start()
return self return self
def __exit__(self, exc_type, exc_val, exc_tb): def __exit__(self, exc_type, exc_val, exc_tb):
self._server.stop(None) self._grpc_server.stop(None)
return False return False

@ -29,16 +29,15 @@
"""Entry points into the Beta API of gRPC Python.""" """Entry points into the Beta API of gRPC Python."""
# threading is referenced from specification in this module. # threading is referenced from specification in this module.
import abc
import enum
import threading # pylint: disable=unused-import import threading # pylint: disable=unused-import
# cardinality and face are referenced from specification in this module. # interfaces, cardinality, and face are referenced from specification in this
# module.
import grpc import grpc
from grpc import _auth from grpc import _auth
from grpc.beta import _client_adaptations from grpc.beta import _client_adaptations
from grpc.beta import _server_adaptations from grpc.beta import _server_adaptations
from grpc.beta import interfaces from grpc.beta import interfaces # pylint: disable=unused-import
from grpc.framework.common import cardinality # pylint: disable=unused-import from grpc.framework.common import cardinality # pylint: disable=unused-import
from grpc.framework.interfaces.face import face # pylint: disable=unused-import from grpc.framework.interfaces.face import face # pylint: disable=unused-import
@ -218,7 +217,7 @@ def dynamic_stub(channel, service, cardinalities, options=None):
Returns: Returns:
A face.DynamicStub with which RPCs can be invoked. A face.DynamicStub with which RPCs can be invoked.
""" """
effective_options = StubOptions() if options is None else options effective_options = _EMPTY_STUB_OPTIONS if options is None else options
return _client_adaptations.dynamic_stub( return _client_adaptations.dynamic_stub(
channel._channel, # pylint: disable=protected-access channel._channel, # pylint: disable=protected-access
service, service,

@ -39,7 +39,7 @@ def _wrap(behavior):
def _wrapping(*args, **kwargs): def _wrapping(*args, **kwargs):
try: try:
return behavior(*args, **kwargs) return behavior(*args, **kwargs)
except Exception as e: except Exception:
logging.exception( logging.exception(
'Unexpected exception from %s executed in logging pool!', 'Unexpected exception from %s executed in logging pool!',
behavior) behavior)

@ -31,6 +31,7 @@
import argparse import argparse
import grpc import grpc
import time
from src.proto.grpc.testing import test_pb2 from src.proto.grpc.testing import test_pb2
from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import messages_pb2
@ -75,6 +76,7 @@ def _goaway(stub):
first_response = stub.UnaryCall(_SIMPLE_REQUEST) first_response = stub.UnaryCall(_SIMPLE_REQUEST)
_validate_payload_type_and_length(first_response, messages_pb2.COMPRESSABLE, _validate_payload_type_and_length(first_response, messages_pb2.COMPRESSABLE,
_RESPONSE_SIZE) _RESPONSE_SIZE)
time.sleep(1)
second_response = stub.UnaryCall(_SIMPLE_REQUEST) second_response = stub.UnaryCall(_SIMPLE_REQUEST)
_validate_payload_type_and_length(second_response, _validate_payload_type_and_length(second_response,
messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) messages_pb2.COMPRESSABLE, _RESPONSE_SIZE)

@ -9,7 +9,7 @@
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"require": { "require": {
"php": ">=5.5.0", "php": ">=5.5.0",
"google/protobuf": "v3.1.0" "google/protobuf": "^v3.1.0"
}, },
"require-dev": { "require-dev": {
"google/auth": "v0.9" "google/auth": "v0.9"

@ -191,7 +191,7 @@
'test/core/util/debugger_macros.c', 'test/core/util/debugger_macros.c',
'test/core/util/test_config.{c,h}', 'test/core/util/test_config.{c,h}',
'test/core/util/port.h', 'test/core/util/port.h',
'test/core/util/port_posix.c', 'test/core/util/port.c',
'test/core/util/port_server_client.{c,h}' 'test/core/util/port_server_client.{c,h}'
end end
end end

@ -12,7 +12,7 @@
<email>grpc-packages@google.com</email> <email>grpc-packages@google.com</email>
<active>yes</active> <active>yes</active>
</lead> </lead>
<date>2017-01-13</date> <date>2017-03-01</date>
<time>16:06:07</time> <time>16:06:07</time>
<version> <version>
<release>${settings.php_version.php()}</release> <release>${settings.php_version.php()}</release>
@ -24,8 +24,8 @@
</stability> </stability>
<license>BSD</license> <license>BSD</license>
<notes> <notes>
- PHP Proto3 adoption #8179 - Added arg info macros #9751
- Various bug fixes - Updated codegen to be consistent with protobuf #9492
</notes> </notes>
<contents> <contents>
<dir baseinstalldir="/" name="/"> <dir baseinstalldir="/" name="/">
@ -312,8 +312,8 @@
</release> </release>
<release> <release>
<version> <version>
<release>1.1.0dev</release> <release>1.1.0RC1</release>
<api>1.1.0dev</api> <api>1.1.0RC1</api>
</version> </version>
<stability> <stability>
<release>beta</release> <release>beta</release>
@ -326,5 +326,37 @@
- Various bug fixes - Various bug fixes
</notes> </notes>
</release> </release>
<release>
<version>
<release>1.1.0</release>
<api>1.1.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2017-01-31</date>
<license>BSD</license>
<notes>
- PHP Proto3 adoption #8179
- Various bug fixes
</notes>
</release>
<release>
<version>
<release>1.2.0RC1</release>
<api>1.2.0RC1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2017-03-01</date>
<license>BSD</license>
<notes>
- Added arg info macros #9751
- Updated codegen to be consistent with protobuf #9492
</notes>
</release>
</changelog> </changelog>
</package> </package>

@ -7,7 +7,7 @@
"version": "${settings.php_version.php_composer()}", "version": "${settings.php_version.php_composer()}",
"require": { "require": {
"php": ">=5.5.0", "php": ">=5.5.0",
"google/protobuf": "v3.1.0" "google/protobuf": "^v3.1.0"
}, },
"require-dev": { "require-dev": {
"google/auth": "v0.9" "google/auth": "v0.9"

@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses(["notice"]) # 3-clause BSD
cc_test( cc_test(
name = "context_test", name = "context_test",
srcs = ["context_test.c"], srcs = ["context_test.c"],

@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses(["notice"]) # 3-clause BSD
cc_test( cc_test(
name = "channel_args_test", name = "channel_args_test",
srcs = ["channel_args_test.c"], srcs = ["channel_args_test.c"],

@ -0,0 +1,116 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/ext/client_channel/parse_address.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include <string.h>
#ifdef GRPC_HAVE_UNIX_SOCKET
#include <sys/un.h>
#endif
#include <grpc/support/log.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/socket_utils.h"
#include "test/core/util/test_config.h"
#ifdef GRPC_HAVE_UNIX_SOCKET
static void test_parse_unix(const char *uri_text, const char *pathname) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
grpc_resolved_address addr;
GPR_ASSERT(1 == parse_unix(uri, &addr));
struct sockaddr_un *addr_un = (struct sockaddr_un *)addr.addr;
GPR_ASSERT(AF_UNIX == addr_un->sun_family);
GPR_ASSERT(0 == strcmp(addr_un->sun_path, pathname));
grpc_uri_destroy(uri);
grpc_exec_ctx_finish(&exec_ctx);
}
#else /* GRPC_HAVE_UNIX_SOCKET */
static void test_parse_unix(const char *uri_text, const char *pathname) {}
#endif /* GRPC_HAVE_UNIX_SOCKET */
static void test_parse_ipv4(const char *uri_text, const char *host,
unsigned short port) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
grpc_resolved_address addr;
char ntop_buf[INET_ADDRSTRLEN];
GPR_ASSERT(1 == parse_ipv4(uri, &addr));
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr.addr;
GPR_ASSERT(AF_INET == addr_in->sin_family);
GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET, &addr_in->sin_addr, ntop_buf,
sizeof(ntop_buf)));
GPR_ASSERT(0 == strcmp(ntop_buf, host));
GPR_ASSERT(ntohs(addr_in->sin_port) == port);
grpc_uri_destroy(uri);
grpc_exec_ctx_finish(&exec_ctx);
}
static void test_parse_ipv6(const char *uri_text, const char *host,
unsigned short port, uint32_t scope_id) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
grpc_resolved_address addr;
char ntop_buf[INET6_ADDRSTRLEN];
GPR_ASSERT(1 == parse_ipv6(uri, &addr));
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr.addr;
GPR_ASSERT(AF_INET6 == addr_in6->sin6_family);
GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET6, &addr_in6->sin6_addr, ntop_buf,
sizeof(ntop_buf)));
GPR_ASSERT(0 == strcmp(ntop_buf, host));
GPR_ASSERT(ntohs(addr_in6->sin6_port) == port);
GPR_ASSERT(addr_in6->sin6_scope_id == scope_id);
grpc_uri_destroy(uri);
grpc_exec_ctx_finish(&exec_ctx);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_parse_unix("unix:/path/name", "/path/name");
test_parse_ipv4("ipv4:192.0.2.1:12345", "192.0.2.1", 12345);
test_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0);
test_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2);
}

@ -69,7 +69,7 @@ static grpc_error *my_resolve_address(const char *name, const char *addr,
static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx, static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx,
const char *name) { const char *name) {
grpc_resolver_factory *factory = grpc_resolver_factory_lookup("dns"); grpc_resolver_factory *factory = grpc_resolver_factory_lookup("dns");
grpc_uri *uri = grpc_uri_parse(name, 0); grpc_uri *uri = grpc_uri_parse(exec_ctx, name, 0);
GPR_ASSERT(uri); GPR_ASSERT(uri);
grpc_resolver_args args; grpc_resolver_args args;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));

@ -43,7 +43,7 @@ static grpc_combiner *g_combiner;
static void test_succeeds(grpc_resolver_factory *factory, const char *string) { static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(string, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args; grpc_resolver_args args;
grpc_resolver *resolver; grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string, gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string,
@ -61,7 +61,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
static void test_fails(grpc_resolver_factory *factory, const char *string) { static void test_fails(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(string, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args; grpc_resolver_args args;
grpc_resolver *resolver; grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string, gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string,

@ -57,7 +57,7 @@ void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
static void test_succeeds(grpc_resolver_factory *factory, const char *string) { static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(string, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args; grpc_resolver_args args;
grpc_resolver *resolver; grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string, gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string,
@ -84,7 +84,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
static void test_fails(grpc_resolver_factory *factory, const char *string) { static void test_fails(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(string, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args; grpc_resolver_args args;
grpc_resolver *resolver; grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string, gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string,

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/uri_parser.h" #include "src/core/ext/client_channel/uri_parser.h"
#include "src/core/lib/iomgr/exec_ctx.h"
bool squelch = true; bool squelch = true;
bool leak_check = true; bool leak_check = true;
@ -47,10 +48,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
memcpy(s, data, size); memcpy(s, data, size);
s[size] = 0; s[size] = 0;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *x; grpc_uri *x;
if ((x = grpc_uri_parse(s, 1))) { if ((x = grpc_uri_parse(&exec_ctx, s, 1))) {
grpc_uri_destroy(x); grpc_uri_destroy(x);
} }
grpc_exec_ctx_finish(&exec_ctx);
gpr_free(s); gpr_free(s);
return 0; return 0;
} }

@ -37,29 +37,35 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
static void test_succeeds(const char *uri_text, const char *scheme, static void test_succeeds(const char *uri_text, const char *scheme,
const char *authority, const char *path, const char *authority, const char *path,
const char *query, const char *fragment) { const char *query, const char *fragment) {
grpc_uri *uri = grpc_uri_parse(uri_text, 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri); GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp(scheme, uri->scheme)); GPR_ASSERT(0 == strcmp(scheme, uri->scheme));
GPR_ASSERT(0 == strcmp(authority, uri->authority)); GPR_ASSERT(0 == strcmp(authority, uri->authority));
GPR_ASSERT(0 == strcmp(path, uri->path)); GPR_ASSERT(0 == strcmp(path, uri->path));
GPR_ASSERT(0 == strcmp(query, uri->query)); GPR_ASSERT(0 == strcmp(query, uri->query));
GPR_ASSERT(0 == strcmp(fragment, uri->fragment)); GPR_ASSERT(0 == strcmp(fragment, uri->fragment));
grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
} }
static void test_fails(const char *uri_text) { static void test_fails(const char *uri_text) {
GPR_ASSERT(NULL == grpc_uri_parse(uri_text, 0)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(NULL == grpc_uri_parse(&exec_ctx, uri_text, 0));
grpc_exec_ctx_finish(&exec_ctx);
} }
static void test_query_parts() { static void test_query_parts() {
{ {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const char *uri_text = "http://foo/path?a&b=B&c=&#frag"; const char *uri_text = "http://foo/path?a&b=B&c=&#frag";
grpc_uri *uri = grpc_uri_parse(uri_text, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri); GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme)); GPR_ASSERT(0 == strcmp("http", uri->scheme));
@ -86,12 +92,14 @@ static void test_query_parts() {
GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, "")); GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, ""));
GPR_ASSERT(0 == strcmp("frag", uri->fragment)); GPR_ASSERT(0 == strcmp("frag", uri->fragment));
grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
} }
{ {
/* test the current behavior of multiple query part values */ /* test the current behavior of multiple query part values */
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const char *uri_text = "http://auth/path?foo=bar=baz&foobar=="; const char *uri_text = "http://auth/path?foo=bar=baz&foobar==";
grpc_uri *uri = grpc_uri_parse(uri_text, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri); GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme)); GPR_ASSERT(0 == strcmp("http", uri->scheme));
@ -103,12 +111,14 @@ static void test_query_parts() {
GPR_ASSERT(0 == strcmp("bar", grpc_uri_get_query_arg(uri, "foo"))); GPR_ASSERT(0 == strcmp("bar", grpc_uri_get_query_arg(uri, "foo")));
GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "foobar"))); GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "foobar")));
grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
} }
{ {
/* empty query */ /* empty query */
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const char *uri_text = "http://foo/path"; const char *uri_text = "http://foo/path";
grpc_uri *uri = grpc_uri_parse(uri_text, 0); grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri); GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme)); GPR_ASSERT(0 == strcmp("http", uri->scheme));
@ -119,6 +129,7 @@ static void test_query_parts() {
GPR_ASSERT(NULL == uri->query_parts); GPR_ASSERT(NULL == uri->query_parts);
GPR_ASSERT(NULL == uri->query_parts_values); GPR_ASSERT(NULL == uri->query_parts_values);
GPR_ASSERT(0 == strcmp("", uri->fragment)); GPR_ASSERT(0 == strcmp("", uri->fragment));
grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
} }
} }
@ -142,6 +153,8 @@ int main(int argc, char **argv) {
test_succeeds("http:?legit#twice", "http", "", "", "legit", "twice"); test_succeeds("http:?legit#twice", "http", "", "", "legit", "twice");
test_succeeds("http://foo?bar#lol?", "http", "foo", "", "bar", "lol?"); test_succeeds("http://foo?bar#lol?", "http", "foo", "", "bar", "lol?");
test_succeeds("http://foo?bar#lol?/", "http", "foo", "", "bar", "lol?/"); test_succeeds("http://foo?bar#lol?/", "http", "foo", "", "bar", "lol?/");
test_succeeds("ipv6:[2001:db8::1%252]:12345", "ipv6", "",
"[2001:db8::1%2]:12345", "", "");
test_fails("xyz"); test_fails("xyz");
test_fails("http:?dangling-pct-%0"); test_fails("http:?dangling-pct-%0");

@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses(["notice"]) # 3-clause BSD
cc_test( cc_test(
name = "algorithm_test", name = "algorithm_test",
srcs = ["algorithm_test.c"], srcs = ["algorithm_test.c"],

@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses(["notice"]) # 3-clause BSD
cc_test( cc_test(
name = "client_ssl", name = "client_ssl",
srcs = ["client_ssl.c"], srcs = ["client_ssl.c"],

@ -70,6 +70,12 @@ static grpc_resolved_address make_addr6(const uint8_t *data, size_t data_len) {
return resolved_addr6; return resolved_addr6;
} }
static void set_addr6_scope_id(grpc_resolved_address *addr, uint32_t scope_id) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr->addr;
GPR_ASSERT(addr6->sin6_family == AF_INET6);
addr6->sin6_scope_id = scope_id;
}
static const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, static const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff, 192, 0, 2, 1}; 0, 0, 0xff, 0xff, 192, 0, 2, 1};
@ -222,6 +228,16 @@ static void test_sockaddr_to_string(void) {
expect_sockaddr_str("[2001:db8::1]:12345", &input6, 1); expect_sockaddr_str("[2001:db8::1]:12345", &input6, 1);
expect_sockaddr_uri("ipv6:[2001:db8::1]:12345", &input6); expect_sockaddr_uri("ipv6:[2001:db8::1]:12345", &input6);
set_addr6_scope_id(&input6, 2);
expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 0);
expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 1);
expect_sockaddr_uri("ipv6:[2001:db8::1%252]:12345", &input6);
set_addr6_scope_id(&input6, 101);
expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 0);
expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 1);
expect_sockaddr_uri("ipv6:[2001:db8::1%25101]:12345", &input6);
input6 = make_addr6(kMapped, sizeof(kMapped)); input6 = make_addr6(kMapped, sizeof(kMapped));
expect_sockaddr_str("[::ffff:192.0.2.1]:12345", &input6, 0); expect_sockaddr_str("[::ffff:192.0.2.1]:12345", &input6, 0);
expect_sockaddr_str("192.0.2.1:12345", &input6, 1); expect_sockaddr_str("192.0.2.1:12345", &input6, 1);

@ -454,7 +454,8 @@ int main(int argc, char **argv) {
const grpc_channel_args channel_args = {1, chan_args}; const grpc_channel_args channel_args = {1, chan_args};
struct ifaddrs *ifa = NULL; struct ifaddrs *ifa = NULL;
struct ifaddrs *ifa_it; struct ifaddrs *ifa_it;
test_addrs dst_addrs; // Zalloc dst_addrs to avoid oversized frames.
test_addrs *dst_addrs = gpr_zalloc(sizeof(*dst_addrs));
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
grpc_init(); grpc_init();
g_pollset = gpr_zalloc(grpc_pollset_size()); g_pollset = gpr_zalloc(grpc_pollset_size());
@ -469,24 +470,25 @@ int main(int argc, char **argv) {
gpr_log(GPR_ERROR, "getifaddrs: %s", strerror(errno)); gpr_log(GPR_ERROR, "getifaddrs: %s", strerror(errno));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
dst_addrs.naddrs = 0; dst_addrs->naddrs = 0;
for (ifa_it = ifa; ifa_it != NULL && dst_addrs.naddrs < MAX_ADDRS; for (ifa_it = ifa; ifa_it != NULL && dst_addrs->naddrs < MAX_ADDRS;
ifa_it = ifa_it->ifa_next) { ifa_it = ifa_it->ifa_next) {
if (ifa_it->ifa_addr == NULL) { if (ifa_it->ifa_addr == NULL) {
continue; continue;
} else if (ifa_it->ifa_addr->sa_family == AF_INET) { } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
dst_addrs.addrs[dst_addrs.naddrs].addr.len = sizeof(struct sockaddr_in); dst_addrs->addrs[dst_addrs->naddrs].addr.len = sizeof(struct sockaddr_in);
} else if (ifa_it->ifa_addr->sa_family == AF_INET6) { } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
dst_addrs.addrs[dst_addrs.naddrs].addr.len = sizeof(struct sockaddr_in6); dst_addrs->addrs[dst_addrs->naddrs].addr.len =
sizeof(struct sockaddr_in6);
} else { } else {
continue; continue;
} }
memcpy(dst_addrs.addrs[dst_addrs.naddrs].addr.addr, ifa_it->ifa_addr, memcpy(dst_addrs->addrs[dst_addrs->naddrs].addr.addr, ifa_it->ifa_addr,
dst_addrs.addrs[dst_addrs.naddrs].addr.len); dst_addrs->addrs[dst_addrs->naddrs].addr.len);
GPR_ASSERT( GPR_ASSERT(
grpc_sockaddr_set_port(&dst_addrs.addrs[dst_addrs.naddrs].addr, 0)); grpc_sockaddr_set_port(&dst_addrs->addrs[dst_addrs->naddrs].addr, 0));
test_addr_init_str(&dst_addrs.addrs[dst_addrs.naddrs]); test_addr_init_str(&dst_addrs->addrs[dst_addrs->naddrs]);
++dst_addrs.naddrs; ++dst_addrs->naddrs;
} }
freeifaddrs(ifa); freeifaddrs(ifa);
ifa = NULL; ifa = NULL;
@ -495,20 +497,21 @@ int main(int argc, char **argv) {
test_connect(1, NULL, NULL, false); test_connect(1, NULL, NULL, false);
test_connect(10, NULL, NULL, false); test_connect(10, NULL, NULL, false);
/* Set dst_addrs.addrs[i].len=0 for dst_addrs that are unreachable with a "::" /* Set dst_addrs->addrs[i].len=0 for dst_addrs that are unreachable with a
listener. */ "::" listener. */
test_connect(1, NULL, &dst_addrs, true); test_connect(1, NULL, dst_addrs, true);
/* Test connect(2) with dst_addrs. */ /* Test connect(2) with dst_addrs. */
test_connect(1, &channel_args, &dst_addrs, false); test_connect(1, &channel_args, dst_addrs, false);
/* Test connect(2) with dst_addrs. */ /* Test connect(2) with dst_addrs. */
test_connect(10, &channel_args, &dst_addrs, false); test_connect(10, &channel_args, dst_addrs, false);
grpc_closure_init(&destroyed, destroy_pollset, g_pollset, grpc_closure_init(&destroyed, destroy_pollset, g_pollset,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed); grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
grpc_shutdown(); grpc_shutdown();
gpr_free(dst_addrs);
gpr_free(g_pollset); gpr_free(g_pollset);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

@ -146,6 +146,7 @@ int main(int argc, char **argv) {
TEST_VECTOR("\x0f", "%0F", grpc_url_percent_encoding_unreserved_bytes); TEST_VECTOR("\x0f", "%0F", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xff", "%FF", grpc_url_percent_encoding_unreserved_bytes); TEST_VECTOR("\xff", "%FF", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xee", "%EE", grpc_url_percent_encoding_unreserved_bytes); TEST_VECTOR("\xee", "%EE", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("%2", "%252", grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%", "%", TEST_NONCONFORMANT_VECTOR("%", "%",
grpc_url_percent_encoding_unreserved_bytes); grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%A", "%A", TEST_NONCONFORMANT_VECTOR("%A", "%A",

@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses(["notice"]) # 3-clause BSD
cc_test( cc_test(
name = "alloc_test", name = "alloc_test",
srcs = ["alloc_test.c"], srcs = ["alloc_test.c"],

@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
licenses(["notice"]) # 3-clause BSD
cc_test( cc_test(
name = "alarm_test", name = "alarm_test",
srcs = ["alarm_test.c"], srcs = ["alarm_test.c"],

@ -64,6 +64,13 @@ cc_test(
copts = ['-std=c99'] copts = ['-std=c99']
) )
cc_test(
name = "stream_owned_slice_test",
srcs = ["stream_owned_slice_test.c"],
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
copts = ['-std=c99']
)
cc_test( cc_test(
name = "timeout_encoding_test", name = "timeout_encoding_test",
srcs = ["timeout_encoding_test.c"], srcs = ["timeout_encoding_test.c"],

@ -0,0 +1,58 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/transport/transport.h"
#include "test/core/util/test_config.h"
#include <grpc/support/log.h>
static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
uint8_t buffer[] = "abc123";
grpc_stream_refcount r;
GRPC_STREAM_REF_INIT(&r, 1, do_nothing, NULL, "test");
GPR_ASSERT(r.refs.count == 1);
grpc_slice slice =
grpc_slice_from_stream_owned_buffer(&r, buffer, sizeof(buffer));
GPR_ASSERT(GRPC_SLICE_START_PTR(slice) == buffer);
GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == sizeof(buffer));
GPR_ASSERT(r.refs.count == 2);
grpc_slice_unref(slice);
GPR_ASSERT(r.refs.count == 1);
return 0;
}

@ -51,9 +51,8 @@ cc_library(
"mock_endpoint.c", "mock_endpoint.c",
"parse_hexstring.c", "parse_hexstring.c",
"passthru_endpoint.c", "passthru_endpoint.c",
"port_posix.c", "port.c",
"port_server_client.c", "port_server_client.c",
"port_windows.c",
"reconnect_server.c", "reconnect_server.c",
"slice_splitter.c", "slice_splitter.c",
"test_tcp_server.c", "test_tcp_server.c",

@ -33,17 +33,24 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
#if defined(GRPC_UV) && defined(GRPC_TEST_PICK_PORT) #if defined(GRPC_TEST_PICK_PORT)
#include "test/core/util/port.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/support/env.h" #include "src/core/lib/http/httpcli.h"
#include "test/core/util/port.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "test/core/util/port_server_client.h" #include "test/core/util/port_server_client.h"
// Almost everything in this file has been copied from port_posix.c
static int *chosen_ports = NULL; static int *chosen_ports = NULL;
static size_t num_chosen_ports = 0; static size_t num_chosen_ports = 0;
@ -51,7 +58,6 @@ static int free_chosen_port(int port) {
size_t i; size_t i;
int found = 0; int found = 0;
size_t found_at = 0; size_t found_at = 0;
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
/* Find the port and erase it from the list, then tell the server it can be /* Find the port and erase it from the list, then tell the server it can be
freed. */ freed. */
for (i = 0; i < num_chosen_ports; i++) { for (i = 0; i < num_chosen_ports; i++) {
@ -64,24 +70,16 @@ static int free_chosen_port(int port) {
if (found) { if (found) {
chosen_ports[found_at] = chosen_ports[num_chosen_ports - 1]; chosen_ports[found_at] = chosen_ports[num_chosen_ports - 1];
num_chosen_ports--; num_chosen_ports--;
if (env) { grpc_free_port_using_server(port);
grpc_free_port_using_server(env, port);
} }
}
gpr_free(env);
return found; return found;
} }
static void free_chosen_ports(void) { static void free_chosen_ports(void) {
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
if (env != NULL) {
size_t i; size_t i;
for (i = 0; i < num_chosen_ports; i++) { for (i = 0; i < num_chosen_ports; i++) {
grpc_free_port_using_server(env, chosen_ports[i]); grpc_free_port_using_server(chosen_ports[i]);
}
gpr_free(env);
} }
gpr_free(chosen_ports); gpr_free(chosen_ports);
} }
@ -95,23 +93,27 @@ static void chose_port(int port) {
} }
int grpc_pick_unused_port(void) { int grpc_pick_unused_port(void) {
// Currently only works with the port server int port = grpc_pick_port_using_server();
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
GPR_ASSERT(env);
int port = grpc_pick_port_using_server(env);
gpr_free(env);
if (port != 0) { if (port != 0) {
chose_port(port); chose_port(port);
} }
return port; return port;
} }
int grpc_pick_unused_port_or_die(void) { int grpc_pick_unused_port_or_die(void) {
int port = grpc_pick_unused_port(); int port = grpc_pick_unused_port();
GPR_ASSERT(port > 0); if (port == 0) {
fprintf(stderr,
"gRPC tests require a helper port server to allocate ports used \n"
"during the test.\n\n"
"This server is not currently running.\n\n"
"To start it, run tools/run_tests/start_port_server.py\n\n");
exit(1);
}
return port; return port;
} }
void grpc_recycle_unused_port(int port) { GPR_ASSERT(free_chosen_port(port)); } void grpc_recycle_unused_port(int port) { GPR_ASSERT(free_chosen_port(port)); }
#endif /* GRPC_UV && GRPC_TEST_PICK_PORT */ #endif /* GRPC_TEST_PICK_PORT */

@ -1,256 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/iomgr/port.h"
#include "test/core/util/test_config.h"
#if defined(GRPC_POSIX_SOCKET) && defined(GRPC_TEST_PICK_PORT)
#include "test/core/util/port.h"
#include <errno.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/support/env.h"
#include "test/core/util/port_server_client.h"
#define NUM_RANDOM_PORTS_TO_PICK 100
static int *chosen_ports = NULL;
static size_t num_chosen_ports = 0;
static int has_port_been_chosen(int port) {
size_t i;
for (i = 0; i < num_chosen_ports; i++) {
if (chosen_ports[i] == port) {
return 1;
}
}
return 0;
}
static int free_chosen_port(int port) {
size_t i;
int found = 0;
size_t found_at = 0;
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
/* Find the port and erase it from the list, then tell the server it can be
freed. */
for (i = 0; i < num_chosen_ports; i++) {
if (chosen_ports[i] == port) {
GPR_ASSERT(found == 0);
found = 1;
found_at = i;
}
}
if (found) {
chosen_ports[found_at] = chosen_ports[num_chosen_ports - 1];
num_chosen_ports--;
if (env) {
grpc_free_port_using_server(env, port);
}
}
gpr_free(env);
return found;
}
static void free_chosen_ports(void) {
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
if (env != NULL) {
size_t i;
for (i = 0; i < num_chosen_ports; i++) {
grpc_free_port_using_server(env, chosen_ports[i]);
}
gpr_free(env);
}
gpr_free(chosen_ports);
}
static void chose_port(int port) {
if (chosen_ports == NULL) {
atexit(free_chosen_ports);
}
num_chosen_ports++;
chosen_ports = gpr_realloc(chosen_ports, sizeof(int) * num_chosen_ports);
chosen_ports[num_chosen_ports - 1] = port;
}
static bool is_port_available(int *port, bool is_tcp) {
GPR_ASSERT(*port >= 0);
GPR_ASSERT(*port <= 65535);
/* For a port to be considered available, the kernel must support
at least one of (IPv6, IPv4), and the port must be available
on each supported family. */
bool got_socket = false;
for (int is_ipv6 = 1; is_ipv6 >= 0; is_ipv6--) {
const int fd =
socket(is_ipv6 ? AF_INET6 : AF_INET, is_tcp ? SOCK_STREAM : SOCK_DGRAM,
is_tcp ? IPPROTO_TCP : 0);
if (fd >= 0) {
got_socket = true;
} else {
continue;
}
/* Reuseaddr lets us start up a server immediately after it exits */
const int one = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
gpr_log(GPR_ERROR, "setsockopt() failed: %s", strerror(errno));
close(fd);
return false;
}
/* Try binding to port */
grpc_resolved_address addr;
if (is_ipv6) {
grpc_sockaddr_make_wildcard6(*port, &addr); /* [::]:port */
} else {
grpc_sockaddr_make_wildcard4(*port, &addr); /* 0.0.0.0:port */
}
if (bind(fd, (struct sockaddr *)addr.addr, (socklen_t)addr.len) < 0) {
gpr_log(GPR_DEBUG, "bind(port=%d) failed: %s", *port, strerror(errno));
close(fd);
return false;
}
/* Get the bound port number */
if (getsockname(fd, (struct sockaddr *)addr.addr, (socklen_t *)&addr.len) <
0) {
gpr_log(GPR_ERROR, "getsockname() failed: %s", strerror(errno));
close(fd);
return false;
}
GPR_ASSERT(addr.len <= sizeof(addr.addr));
const int actual_port = grpc_sockaddr_get_port(&addr);
GPR_ASSERT(actual_port > 0);
if (*port == 0) {
*port = actual_port;
} else {
GPR_ASSERT(*port == actual_port);
}
close(fd);
}
if (!got_socket) {
gpr_log(GPR_ERROR, "socket() failed: %s", strerror(errno));
return false;
}
return true;
}
int grpc_pick_unused_port(void) {
/* We repeatedly pick a port and then see whether or not it is
available for use both as a TCP socket and a UDP socket. First, we
pick a random large port number. For subsequent
iterations, we bind to an anonymous port and let the OS pick the
port number. The random port picking reduces the probability of
races with other processes on kernels that want to reuse the same
port numbers over and over. */
/* In alternating iterations we trial UDP ports before TCP ports UDP
ports -- it could be the case that this machine has been using up
UDP ports and they are scarcer. */
/* Type of port to first pick in next iteration */
bool is_tcp = true;
int trial = 0;
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
if (env) {
int port = grpc_pick_port_using_server(env);
gpr_free(env);
if (port != 0) {
chose_port(port);
}
return port;
}
for (;;) {
int port;
trial++;
if (trial == 1) {
port = getpid() % (65536 - 30000) + 30000;
} else if (trial <= NUM_RANDOM_PORTS_TO_PICK) {
port = rand() % (65536 - 30000) + 30000;
} else {
port = 0;
}
if (has_port_been_chosen(port)) {
continue;
}
if (!is_port_available(&port, is_tcp)) {
continue;
}
GPR_ASSERT(port > 0);
/* Check that the port # is free for the other type of socket also */
if (!is_port_available(&port, !is_tcp)) {
/* In the next iteration trial to bind to the other type first
because perhaps it is more rare. */
is_tcp = !is_tcp;
continue;
}
chose_port(port);
return port;
}
/* The port iterator reached the end without finding a suitable port. */
return 0;
}
int grpc_pick_unused_port_or_die(void) {
int port = grpc_pick_unused_port();
GPR_ASSERT(port > 0);
return port;
}
void grpc_recycle_unused_port(int port) { GPR_ASSERT(free_chosen_port(port)); }
#endif /* GRPC_POSIX_SOCKET && GRPC_TEST_PICK_PORT */

@ -74,7 +74,7 @@ static void freed_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_unlock(pr->mu); gpr_mu_unlock(pr->mu);
} }
void grpc_free_port_using_server(char *server, int port) { void grpc_free_port_using_server(int port) {
grpc_httpcli_context context; grpc_httpcli_context context;
grpc_httpcli_request req; grpc_httpcli_request req;
grpc_httpcli_response rsp; grpc_httpcli_response rsp;
@ -95,7 +95,7 @@ void grpc_free_port_using_server(char *server, int port) {
shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops, shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
req.host = server; req.host = GRPC_PORT_SERVER_ADDRESS;
gpr_asprintf(&path, "/drop/%d", port); gpr_asprintf(&path, "/drop/%d", port);
req.http.path = path; req.http.path = path;
@ -198,7 +198,7 @@ static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_unlock(pr->mu); gpr_mu_unlock(pr->mu);
} }
int grpc_pick_port_using_server(char *server) { int grpc_pick_port_using_server(void) {
grpc_httpcli_context context; grpc_httpcli_context context;
grpc_httpcli_request req; grpc_httpcli_request req;
portreq pr; portreq pr;
@ -215,10 +215,10 @@ int grpc_pick_port_using_server(char *server) {
shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops, shutdown_closure = grpc_closure_create(destroy_pops_and_shutdown, &pr.pops,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
pr.port = -1; pr.port = -1;
pr.server = server; pr.server = GRPC_PORT_SERVER_ADDRESS;
pr.ctx = &context; pr.ctx = &context;
req.host = server; req.host = GRPC_PORT_SERVER_ADDRESS;
req.http.path = "/get"; req.http.path = "/get";
grpc_httpcli_context_init(&context); grpc_httpcli_context_init(&context);

@ -36,7 +36,10 @@
// C interface to port_server.py // C interface to port_server.py
int grpc_pick_port_using_server(char *server); // must be synchronized with tools/run_tests/python_utils/start_port_server.py
void grpc_free_port_using_server(char *server, int port); #define GRPC_PORT_SERVER_ADDRESS "localhost:32766"
int grpc_pick_port_using_server(void);
void grpc_free_port_using_server(int port);
#endif // GRPC_TEST_CORE_UTIL_PORT_SERVER_CLIENT_H #endif // GRPC_TEST_CORE_UTIL_PORT_SERVER_CLIENT_H

@ -1,247 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/iomgr/port.h"
#include "test/core/util/test_config.h"
#if defined(GRPC_WINSOCK_SOCKET) && defined(GRPC_TEST_PICK_PORT)
#include "src/core/lib/iomgr/sockaddr.h"
#include "test/core/util/port.h"
#include <errno.h>
#include <process.h>
#include <stdio.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/support/env.h"
#include "test/core/util/port_server_client.h"
#if GPR_GETPID_IN_UNISTD_H
#include <sys/unistd.h>
static int _getpid() { return getpid(); }
#endif
#define NUM_RANDOM_PORTS_TO_PICK 100
static int *chosen_ports = NULL;
static size_t num_chosen_ports = 0;
static int has_port_been_chosen(int port) {
size_t i;
for (i = 0; i < num_chosen_ports; i++) {
if (chosen_ports[i] == port) {
return 1;
}
}
return 0;
}
static int free_chosen_port(int port) {
size_t i;
int found = 0;
size_t found_at = 0;
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
if (env != NULL) {
/* Find the port and erase it from the list, then tell the server it can be
freed. */
for (i = 0; i < num_chosen_ports; i++) {
if (chosen_ports[i] == port) {
GPR_ASSERT(found == 0);
found = 1;
found_at = i;
}
}
if (found) {
chosen_ports[found_at] = chosen_ports[num_chosen_ports - 1];
grpc_free_port_using_server(env, port);
num_chosen_ports--;
}
}
return found;
}
static void free_chosen_ports(void) {
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
if (env != NULL) {
size_t i;
for (i = 0; i < num_chosen_ports; i++) {
grpc_free_port_using_server(env, chosen_ports[i]);
}
gpr_free(env);
}
gpr_free(chosen_ports);
}
static void chose_port(int port) {
if (chosen_ports == NULL) {
atexit(free_chosen_ports);
}
num_chosen_ports++;
chosen_ports = gpr_realloc(chosen_ports, sizeof(int) * num_chosen_ports);
chosen_ports[num_chosen_ports - 1] = port;
}
static int is_port_available(int *port, int is_tcp) {
const int proto = is_tcp ? IPPROTO_TCP : 0;
const SOCKET fd = socket(AF_INET, is_tcp ? SOCK_STREAM : SOCK_DGRAM, proto);
int one = 1;
struct sockaddr_in addr;
socklen_t alen = sizeof(addr);
int actual_port;
GPR_ASSERT(*port >= 0);
GPR_ASSERT(*port <= 65535);
if (INVALID_SOCKET == fd) {
gpr_log(GPR_ERROR, "socket() failed: %s", strerror(errno));
return 0;
}
/* Reuseaddr lets us start up a server immediately after it exits */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one,
sizeof(one)) < 0) {
gpr_log(GPR_ERROR, "setsockopt() failed: %s", strerror(errno));
closesocket(fd);
return 0;
}
/* Try binding to port */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons((u_short)*port);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
gpr_log(GPR_DEBUG, "bind(port=%d) failed: %s", *port, strerror(errno));
closesocket(fd);
return 0;
}
/* Get the bound port number */
if (getsockname(fd, (struct sockaddr *)&addr, &alen) < 0) {
gpr_log(GPR_ERROR, "getsockname() failed: %s", strerror(errno));
closesocket(fd);
return 0;
}
GPR_ASSERT(alen <= (socklen_t)sizeof(addr));
actual_port = ntohs(addr.sin_port);
GPR_ASSERT(actual_port > 0);
if (*port == 0) {
*port = actual_port;
} else {
GPR_ASSERT(*port == actual_port);
}
closesocket(fd);
return 1;
}
int grpc_pick_unused_port(void) {
/* We repeatedly pick a port and then see whether or not it is
available for use both as a TCP socket and a UDP socket. First, we
pick a random large port number. For subsequent
iterations, we bind to an anonymous port and let the OS pick the
port number. The random port picking reduces the probability of
races with other processes on kernels that want to reuse the same
port numbers over and over. */
/* In alternating iterations we trial UDP ports before TCP ports UDP
ports -- it could be the case that this machine has been using up
UDP ports and they are scarcer. */
/* Type of port to first pick in next iteration */
int is_tcp = 1;
int trial = 0;
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER");
if (env) {
int port = grpc_pick_port_using_server(env);
gpr_free(env);
if (port != 0) {
return port;
}
}
for (;;) {
int port;
trial++;
if (trial == 1) {
port = _getpid() % (65536 - 30000) + 30000;
} else if (trial <= NUM_RANDOM_PORTS_TO_PICK) {
port = rand() % (65536 - 30000) + 30000;
} else {
port = 0;
}
if (has_port_been_chosen(port)) {
continue;
}
if (!is_port_available(&port, is_tcp)) {
continue;
}
GPR_ASSERT(port > 0);
/* Check that the port # is free for the other type of socket also */
if (!is_port_available(&port, !is_tcp)) {
/* In the next iteration trial to bind to the other type first
because perhaps it is more rare. */
is_tcp = !is_tcp;
continue;
}
/* TODO(ctiller): consider caching this port in some structure, to avoid
handing it out again */
chose_port(port);
return port;
}
/* The port iterator reached the end without finding a suitable port. */
return 0;
}
int grpc_pick_unused_port_or_die(void) {
int port = grpc_pick_unused_port();
GPR_ASSERT(port > 0);
return port;
}
void grpc_recycle_unused_port(int port) { GPR_ASSERT(free_chosen_port(port)); }
#endif /* GRPC_WINSOCK_SOCKET && GRPC_TEST_PICK_PORT */

@ -1,4 +1,4 @@
// Generated by the gRPC protobuf plugin. // Generated by the gRPC C++ plugin.
// If you make any local change, they will be lost. // If you make any local change, they will be lost.
// source: src/proto/grpc/testing/compiler_test.proto // source: src/proto/grpc/testing/compiler_test.proto
// Original file comments: // Original file comments:

@ -65,7 +65,9 @@ Http2Client::ServiceStub::ServiceStub(std::shared_ptr<Channel> channel)
TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); } TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); }
Http2Client::Http2Client(std::shared_ptr<Channel> channel) Http2Client::Http2Client(std::shared_ptr<Channel> channel)
: serviceStub_(channel), channel_(channel) {} : serviceStub_(channel),
channel_(channel),
defaultRequest_(BuildDefaultRequest()) {}
bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) { bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) {
if (s.error_code() == expected_code) { if (s.error_code() == expected_code) {
@ -77,18 +79,24 @@ bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) {
abort(); abort();
} }
bool Http2Client::DoRstAfterHeader() { Status Http2Client::SendUnaryCall(SimpleResponse* response) {
gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after header");
ClientContext context; ClientContext context;
return serviceStub_.Get()->UnaryCall(&context, defaultRequest_, response);
}
SimpleRequest Http2Client::BuildDefaultRequest() {
SimpleRequest request; SimpleRequest request;
SimpleResponse response;
request.set_response_size(kLargeResponseSize); request.set_response_size(kLargeResponseSize);
grpc::string payload(kLargeRequestSize, '\0'); grpc::string payload(kLargeRequestSize, '\0');
request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
return request;
}
Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); bool Http2Client::DoRstAfterHeader() {
AssertStatusCode(s, grpc::StatusCode::UNKNOWN); gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after header");
SimpleResponse response;
AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
GPR_ASSERT(!response.has_payload()); // no data should be received GPR_ASSERT(!response.has_payload()); // no data should be received
gpr_log(GPR_DEBUG, "Done testing reset stream after header"); gpr_log(GPR_DEBUG, "Done testing reset stream after header");
@ -98,15 +106,8 @@ bool Http2Client::DoRstAfterHeader() {
bool Http2Client::DoRstAfterData() { bool Http2Client::DoRstAfterData() {
gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after data"); gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after data");
ClientContext context;
SimpleRequest request;
SimpleResponse response; SimpleResponse response;
request.set_response_size(kLargeResponseSize); AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
grpc::string payload(kLargeRequestSize, '\0');
request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
AssertStatusCode(s, grpc::StatusCode::UNKNOWN);
GPR_ASSERT(response.has_payload()); // data should be received GPR_ASSERT(response.has_payload()); // data should be received
gpr_log(GPR_DEBUG, "Done testing reset stream after data"); gpr_log(GPR_DEBUG, "Done testing reset stream after data");
@ -116,15 +117,8 @@ bool Http2Client::DoRstAfterData() {
bool Http2Client::DoRstDuringData() { bool Http2Client::DoRstDuringData() {
gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream during data"); gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream during data");
ClientContext context;
SimpleRequest request;
SimpleResponse response; SimpleResponse response;
request.set_response_size(kLargeResponseSize); AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
grpc::string payload(kLargeRequestSize, '\0');
request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
AssertStatusCode(s, grpc::StatusCode::UNKNOWN);
GPR_ASSERT(!response.has_payload()); // no data should be received GPR_ASSERT(!response.has_payload()); // no data should be received
gpr_log(GPR_DEBUG, "Done testing reset stream during data"); gpr_log(GPR_DEBUG, "Done testing reset stream during data");
@ -133,56 +127,37 @@ bool Http2Client::DoRstDuringData() {
bool Http2Client::DoGoaway() { bool Http2Client::DoGoaway() {
gpr_log(GPR_DEBUG, "Sending two RPCs and expecting goaway"); gpr_log(GPR_DEBUG, "Sending two RPCs and expecting goaway");
int numCalls = 2;
for (int i = 0; i < numCalls; i++) {
ClientContext context;
SimpleRequest request;
SimpleResponse response; SimpleResponse response;
request.set_response_size(kLargeResponseSize); AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
grpc::string payload(kLargeRequestSize, '\0');
request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
AssertStatusCode(s, grpc::StatusCode::OK);
GPR_ASSERT(response.payload().body() == GPR_ASSERT(response.payload().body() ==
grpc::string(kLargeResponseSize, '\0')); grpc::string(kLargeResponseSize, '\0'));
}
// Sleep for one second to give time for client to receive goaway frame.
gpr_timespec sleep_time = gpr_time_add(
gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(1, GPR_TIMESPAN));
gpr_sleep_until(sleep_time);
response.Clear();
AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
GPR_ASSERT(response.payload().body() ==
grpc::string(kLargeResponseSize, '\0'));
gpr_log(GPR_DEBUG, "Done testing goaway"); gpr_log(GPR_DEBUG, "Done testing goaway");
return true; return true;
} }
bool Http2Client::DoPing() { bool Http2Client::DoPing() {
gpr_log(GPR_DEBUG, "Sending RPC and expecting ping"); gpr_log(GPR_DEBUG, "Sending RPC and expecting ping");
ClientContext context;
SimpleRequest request;
SimpleResponse response; SimpleResponse response;
request.set_response_size(kLargeResponseSize); AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
grpc::string payload(kLargeRequestSize, '\0');
request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
AssertStatusCode(s, grpc::StatusCode::OK);
GPR_ASSERT(response.payload().body() == GPR_ASSERT(response.payload().body() ==
grpc::string(kLargeResponseSize, '\0')); grpc::string(kLargeResponseSize, '\0'));
gpr_log(GPR_DEBUG, "Done testing ping"); gpr_log(GPR_DEBUG, "Done testing ping");
return true; return true;
} }
void Http2Client::MaxStreamsWorker(std::shared_ptr<grpc::Channel> channel) { void Http2Client::MaxStreamsWorker(std::shared_ptr<grpc::Channel> channel) {
ClientContext context;
SimpleRequest request;
SimpleResponse response; SimpleResponse response;
request.set_response_size(kLargeResponseSize); AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
grpc::string payload(kLargeRequestSize, '\0');
request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s =
TestService::NewStub(channel)->UnaryCall(&context, request, &response);
AssertStatusCode(s, grpc::StatusCode::OK);
GPR_ASSERT(response.payload().body() == GPR_ASSERT(response.payload().body() ==
grpc::string(kLargeResponseSize, '\0')); grpc::string(kLargeResponseSize, '\0'));
} }
@ -192,15 +167,8 @@ bool Http2Client::DoMaxStreams() {
// Make an initial call on the channel to ensure the server's max streams // Make an initial call on the channel to ensure the server's max streams
// setting is received // setting is received
ClientContext context;
SimpleRequest request;
SimpleResponse response; SimpleResponse response;
request.set_response_size(kLargeResponseSize); AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
grpc::string payload(kLargeRequestSize, '\0');
request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s =
TestService::NewStub(channel_)->UnaryCall(&context, request, &response);
AssertStatusCode(s, grpc::StatusCode::OK);
GPR_ASSERT(response.payload().body() == GPR_ASSERT(response.payload().body() ==
grpc::string(kLargeResponseSize, '\0')); grpc::string(kLargeResponseSize, '\0'));
@ -240,7 +208,11 @@ int main(int argc, char** argv) {
char host_port[host_port_buf_size]; char host_port[host_port_buf_size];
snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(), snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
FLAGS_server_port); FLAGS_server_port);
grpc::testing::Http2Client client(grpc::CreateTestChannel(host_port, false)); std::shared_ptr<grpc::Channel> channel =
grpc::CreateTestChannel(host_port, false);
GPR_ASSERT(channel->WaitForConnected(gpr_time_add(
gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(300, GPR_TIMESPAN))));
grpc::testing::Http2Client client(channel);
gpr_log(GPR_INFO, "Testing case: %s", FLAGS_test_case.c_str()); gpr_log(GPR_INFO, "Testing case: %s", FLAGS_test_case.c_str());
int ret = 0; int ret = 0;
if (FLAGS_test_case == "rst_after_header") { if (FLAGS_test_case == "rst_after_header") {

@ -70,8 +70,11 @@ class Http2Client {
void MaxStreamsWorker(std::shared_ptr<grpc::Channel> channel); void MaxStreamsWorker(std::shared_ptr<grpc::Channel> channel);
bool AssertStatusCode(const Status& s, StatusCode expected_code); bool AssertStatusCode(const Status& s, StatusCode expected_code);
Status SendUnaryCall(SimpleResponse* response);
SimpleRequest BuildDefaultRequest();
ServiceStub serviceStub_; ServiceStub serviceStub_;
std::shared_ptr<Channel> channel_; std::shared_ptr<Channel> channel_;
SimpleRequest defaultRequest_;
}; };
} // namespace testing } // namespace testing

@ -62,21 +62,48 @@ static struct Init {
~Init() { grpc_shutdown(); } ~Init() { grpc_shutdown(); }
} g_init; } g_init;
static void BM_InsecureChannelWithDefaults(benchmark::State &state) { class BaseChannelFixture {
grpc_channel *channel = public:
grpc_insecure_channel_create("localhost:12345", NULL, NULL); BaseChannelFixture(grpc_channel *channel) : channel_(channel) {}
~BaseChannelFixture() { grpc_channel_destroy(channel_); }
grpc_channel *channel() const { return channel_; }
private:
grpc_channel *const channel_;
};
class InsecureChannel : public BaseChannelFixture {
public:
InsecureChannel()
: BaseChannelFixture(
grpc_insecure_channel_create("localhost:1234", NULL, NULL)) {}
};
class LameChannel : public BaseChannelFixture {
public:
LameChannel()
: BaseChannelFixture(grpc_lame_client_channel_create(
"localhost:1234", GRPC_STATUS_UNAUTHENTICATED, "blah")) {}
};
template <class Fixture>
static void BM_CallCreateDestroy(benchmark::State &state) {
Fixture fixture;
grpc_completion_queue *cq = grpc_completion_queue_create(NULL); grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
grpc_slice method = grpc_slice_from_static_string("/foo/bar");
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
void *method_hdl =
grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
while (state.KeepRunning()) { while (state.KeepRunning()) {
grpc_call_destroy(grpc_channel_create_call(channel, NULL, grpc_call_destroy(grpc_channel_create_registered_call(
GRPC_PROPAGATE_DEFAULTS, cq, fixture.channel(), NULL, GRPC_PROPAGATE_DEFAULTS, cq, method_hdl,
method, NULL, deadline, NULL)); deadline, NULL));
} }
grpc_channel_destroy(channel);
grpc_completion_queue_destroy(cq); grpc_completion_queue_destroy(cq);
} }
BENCHMARK(BM_InsecureChannelWithDefaults);
BENCHMARK_TEMPLATE(BM_CallCreateDestroy, InsecureChannel);
BENCHMARK_TEMPLATE(BM_CallCreateDestroy, LameChannel);
static void FilterDestroy(grpc_exec_ctx *exec_ctx, void *arg, static void FilterDestroy(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {

@ -36,8 +36,10 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
extern "C" { extern "C" {
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/transport.h"
} }
#include "third_party/benchmark/include/benchmark/benchmark.h" #include "third_party/benchmark/include/benchmark/benchmark.h"
@ -62,6 +64,19 @@ static void BM_SliceFromCopied(benchmark::State& state) {
} }
BENCHMARK(BM_SliceFromCopied); BENCHMARK(BM_SliceFromCopied);
static void BM_SliceFromStreamOwnedBuffer(benchmark::State& state) {
grpc_stream_refcount r;
GRPC_STREAM_REF_INIT(&r, 1, NULL, NULL, "test");
char buffer[64];
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
while (state.KeepRunning()) {
grpc_slice_unref_internal(&exec_ctx, grpc_slice_from_stream_owned_buffer(
&r, buffer, sizeof(buffer)));
}
grpc_exec_ctx_finish(&exec_ctx);
}
BENCHMARK(BM_SliceFromStreamOwnedBuffer);
static void BM_SliceIntern(benchmark::State& state) { static void BM_SliceIntern(benchmark::State& state) {
gpr_slice slice = grpc_slice_from_static_string("abc"); gpr_slice slice = grpc_slice_from_static_string("abc");
while (state.KeepRunning()) { while (state.KeepRunning()) {

@ -47,3 +47,6 @@ make install-certs
# build C++ interop client & server # build C++ interop client & server
make interop_client interop_server make interop_client interop_server
# build C++ http2 client
make http2_client

@ -786,6 +786,7 @@ doc/naming.md \
doc/negative-http2-interop-test-descriptions.md \ doc/negative-http2-interop-test-descriptions.md \
doc/server-reflection.md \ doc/server-reflection.md \
doc/server_reflection_tutorial.md \ doc/server_reflection_tutorial.md \
doc/server_side_auth.md \
doc/service_config.md \ doc/service_config.md \
doc/statuscodes.md \ doc/statuscodes.md \
doc/stress_test_framework.md \ doc/stress_test_framework.md \

@ -786,6 +786,7 @@ doc/naming.md \
doc/negative-http2-interop-test-descriptions.md \ doc/negative-http2-interop-test-descriptions.md \
doc/server-reflection.md \ doc/server-reflection.md \
doc/server_reflection_tutorial.md \ doc/server_reflection_tutorial.md \
doc/server_side_auth.md \
doc/service_config.md \ doc/service_config.md \
doc/statuscodes.md \ doc/statuscodes.md \
doc/stress_test_framework.md \ doc/stress_test_framework.md \

@ -785,6 +785,7 @@ doc/naming.md \
doc/negative-http2-interop-test-descriptions.md \ doc/negative-http2-interop-test-descriptions.md \
doc/server-reflection.md \ doc/server-reflection.md \
doc/server_reflection_tutorial.md \ doc/server_reflection_tutorial.md \
doc/server_side_auth.md \
doc/service_config.md \ doc/service_config.md \
doc/statuscodes.md \ doc/statuscodes.md \
doc/stress_test_framework.md \ doc/stress_test_framework.md \

@ -785,6 +785,7 @@ doc/naming.md \
doc/negative-http2-interop-test-descriptions.md \ doc/negative-http2-interop-test-descriptions.md \
doc/server-reflection.md \ doc/server-reflection.md \
doc/server_reflection_tutorial.md \ doc/server_reflection_tutorial.md \
doc/server_side_auth.md \
doc/service_config.md \ doc/service_config.md \
doc/statuscodes.md \ doc/statuscodes.md \
doc/stress_test_framework.md \ doc/stress_test_framework.md \

@ -142,7 +142,7 @@ gem install bundler
# Significant performance improvements with grpc-go have been observed after # Significant performance improvements with grpc-go have been observed after
# upgrading from go 1.5 to a later version, so a later go version is preferred. # upgrading from go 1.5 to a later version, so a later go version is preferred.
# Following go install instructions from https://golang.org/doc/install # Following go install instructions from https://golang.org/doc/install
GO_VERSION=1.7.1 GO_VERSION=1.8
OS=linux OS=linux
ARCH=amd64 ARCH=amd64
curl -O https://storage.googleapis.com/golang/go${GO_VERSION}.${OS}-${ARCH}.tar.gz curl -O https://storage.googleapis.com/golang/go${GO_VERSION}.${OS}-${ARCH}.tar.gz

@ -27,18 +27,17 @@
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
setlocal @rem make sure msys binaries are preferred over cygwin binaries
@rem set path to python 2.7
set PATH=C:\tools\msys64\usr\bin;C:\Python27;%PATH%
@rem enter repo root @rem enter repo root
cd /d %~dp0\..\..\.. cd /d %~dp0\..\..\..
git submodule update --init git submodule update --init
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x c_windows_dbg_sponge_log.xml --report_suite_name c_windows_dbg -l c -c dbg python tools/run_tests/run_tests_matrix.py -f basictests windows -j 1 --inner_jobs 8 || goto :error
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x c_windows_opt_sponge_log.xml --report_suite_name c_windows_opt -l c -c opt goto :EOF
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x csharp_windows_dbg_sponge_log.xml --report_suite_name csharp_windows_dbg -l csharp -c dbg
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x csharp_windows_opt_sponge_log.xml --report_suite_name csharp_windows_opt -l csharp -c opt :error
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x node_windows_dbg_sponge_log.xml --report_suite_name node_windows_dbg -l node -c dbg exit /b %errorlevel%
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x node_windows_opt_sponge_log.xml --report_suite_name node_windows_opt -l node -c opt
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x python_windows_dbg_sponge_log.xml --report_suite_name python_windows_dbg -l python -c dbg
sh tools\run_tests\helper_scripts\run_tests_in_workspace.sh -t -j 4 -x python_windows_opt_sponge_log.xml --report_suite_name python_windows_opt -l python -c opt

@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# A frozen version of run_full_performance.sh that runs full performance test
# suite for the latest released stable version of gRPC.
set -ex
# Enter the gRPC repo root
cd $(dirname $0)/../..
# run 8core client vs 8core server
tools/run_tests/run_performance_tests.py \
-l c++ csharp node ruby java python go node_express \
--netperf \
--category scalable \
--bq_result_table performance_released.performance_experiment \
--remote_worker_host grpc-performance-server-8core grpc-performance-client-8core grpc-performance-client2-8core \
--xml_report report_8core.xml \
|| EXIT_CODE=1
# prevent pushing leftover build files to remote hosts in the next step.
git clean -fdxq --exclude='report*.xml'
# scalability with 32cores (and upload to a different BQ table)
tools/run_tests/run_performance_tests.py \
-l c++ java csharp go \
--netperf \
--category scalable \
--bq_result_table performance_released.performance_experiment_32core \
--remote_worker_host grpc-performance-server-32core grpc-performance-client-32core grpc-performance-client2-32core \
--xml_report report_32core.xml \
|| EXIT_CODE=1
# prevent pushing leftover build files to remote hosts in the next step.
git clean -fdxq --exclude='report*.xml'
# selected scenarios on Windows
tools/run_tests/run_performance_tests.py \
-l csharp \
--category scalable \
--bq_result_table performance_released.performance_experiment_windows \
--remote_worker_host grpc-performance-windows1 grpc-performance-windows2 \
--xml_report report_windows.xml \
|| EXIT_CODE=1
exit $EXIT_CODE

@ -88,7 +88,145 @@ else:
writer = csv.DictWriter(sys.stdout, [c for c,t in columns]) writer = csv.DictWriter(sys.stdout, [c for c,t in columns])
<<<<<<< HEAD
for row in bm_json.expand_json(js, js2): for row in bm_json.expand_json(js, js2):
=======
bm_specs = {
'BM_UnaryPingPong': {
'tpl': ['fixture', 'client_mutator', 'server_mutator'],
'dyn': ['request_size', 'response_size'],
},
'BM_PumpStreamClientToServer': {
'tpl': ['fixture'],
'dyn': ['request_size'],
},
'BM_PumpStreamServerToClient': {
'tpl': ['fixture'],
'dyn': ['request_size'],
},
'BM_StreamingPingPong': {
'tpl': ['fixture', 'client_mutator', 'server_mutator'],
'dyn': ['request_size', 'request_count'],
},
'BM_StreamingPingPongMsgs': {
'tpl': ['fixture', 'client_mutator', 'server_mutator'],
'dyn': ['request_size'],
},
'BM_PumpStreamServerToClient_Trickle': {
'tpl': [],
'dyn': ['request_size', 'bandwidth_kilobits'],
},
'BM_ErrorStringOnNewError': {
'tpl': ['fixture'],
'dyn': [],
},
'BM_ErrorStringRepeatedly': {
'tpl': ['fixture'],
'dyn': [],
},
'BM_ErrorGetStatus': {
'tpl': ['fixture'],
'dyn': [],
},
'BM_ErrorGetStatusCode': {
'tpl': ['fixture'],
'dyn': [],
},
'BM_ErrorHttpError': {
'tpl': ['fixture'],
'dyn': [],
},
'BM_HasClearGrpcStatus': {
'tpl': ['fixture'],
'dyn': [],
},
'BM_IsolatedFilter' : {
'tpl': ['fixture', 'client_mutator'],
'dyn': [],
},
'BM_HpackEncoderEncodeHeader' : {
'tpl': ['fixture'],
'dyn': ['end_of_stream', 'request_size'],
},
'BM_HpackParserParseHeader' : {
'tpl': ['fixture'],
'dyn': [],
},
'BM_CallCreateDestroy' : {
'tpl': ['fixture'],
'dyn': [],
},
}
def numericalize(s):
if not s: return ''
if s[-1] == 'k':
return int(s[:-1]) * 1024
if s[-1] == 'M':
return int(s[:-1]) * 1024 * 1024
if 0 <= (ord(s[-1]) - ord('0')) <= 9:
return int(s)
assert 'not a number: %s' % s
def parse_name(name):
if '<' not in name and '/' not in name and name not in bm_specs:
return {'name': name}
rest = name
out = {}
tpl_args = []
dyn_args = []
if '<' in rest:
tpl_bit = rest[rest.find('<') + 1 : rest.rfind('>')]
arg = ''
nesting = 0
for c in tpl_bit:
if c == '<':
nesting += 1
arg += c
elif c == '>':
nesting -= 1
arg += c
elif c == ',':
if nesting == 0:
tpl_args.append(arg.strip())
arg = ''
else:
arg += c
else:
arg += c
tpl_args.append(arg.strip())
rest = rest[:rest.find('<')] + rest[rest.rfind('>') + 1:]
if '/' in rest:
s = rest.split('/')
rest = s[0]
dyn_args = s[1:]
name = rest
assert name in bm_specs, 'bm_specs needs to be expanded for %s' % name
assert len(dyn_args) == len(bm_specs[name]['dyn'])
assert len(tpl_args) == len(bm_specs[name]['tpl'])
out['name'] = name
out.update(dict((k, numericalize(v)) for k, v in zip(bm_specs[name]['dyn'], dyn_args)))
out.update(dict(zip(bm_specs[name]['tpl'], tpl_args)))
return out
for bm in js['benchmarks']:
context = js['context']
if 'label' in bm:
labels_list = [s.split(':') for s in bm['label'].strip().split(' ') if len(s) and s[0] != '#']
for el in labels_list:
el[0] = el[0].replace('/iter', '_per_iteration')
labels = dict(labels_list)
else:
labels = {}
row = {
'jenkins_build': os.environ.get('BUILD_NUMBER', ''),
'jenkins_job': os.environ.get('JOB_NAME', ''),
}
row.update(context)
row.update(bm)
row.update(parse_name(row['name']))
row.update(labels)
>>>>>>> cf54c151f1853af1fe1df2058ccbc2ca3a26c43c
if 'label' in row: if 'label' in row:
del row['label'] del row['label']
del row['cpp_name'] del row['cpp_name']

@ -90,6 +90,10 @@ _BM_SPECS = {
'tpl': ['fixture'], 'tpl': ['fixture'],
'dyn': [], 'dyn': [],
}, },
'BM_CallCreateDestroy' : {
'tpl': ['fixture'],
'dyn': [],
},
} }
def numericalize(s): def numericalize(s):
@ -170,4 +174,3 @@ def expand_json(js, js2 = None):
row['real_time'] = bm2['real_time'] row['real_time'] = bm2['real_time']
row['iterations'] = bm2['iterations'] row['iterations'] = bm2['iterations']
yield row yield row

@ -1657,6 +1657,23 @@
"third_party": false, "third_party": false,
"type": "target" "type": "target"
}, },
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "parse_address_test",
"src": [
"test/core/client_channel/parse_address_test.c"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"gpr", "gpr",
@ -2032,6 +2049,23 @@
"third_party": false, "third_party": false,
"type": "target" "type": "target"
}, },
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "stream_owned_slice_test",
"src": [
"test/core/transport/stream_owned_slice_test.c"
],
"third_party": false,
"type": "target"
},
{ {
"deps": [ "deps": [
"gpr", "gpr",
@ -7952,12 +7986,10 @@
"test/core/util/parse_hexstring.h", "test/core/util/parse_hexstring.h",
"test/core/util/passthru_endpoint.c", "test/core/util/passthru_endpoint.c",
"test/core/util/passthru_endpoint.h", "test/core/util/passthru_endpoint.h",
"test/core/util/port.c",
"test/core/util/port.h", "test/core/util/port.h",
"test/core/util/port_posix.c",
"test/core/util/port_server_client.c", "test/core/util/port_server_client.c",
"test/core/util/port_server_client.h", "test/core/util/port_server_client.h",
"test/core/util/port_uv.c",
"test/core/util/port_windows.c",
"test/core/util/slice_splitter.c", "test/core/util/slice_splitter.c",
"test/core/util/slice_splitter.h", "test/core/util/slice_splitter.h",
"test/core/util/trickle_endpoint.c", "test/core/util/trickle_endpoint.c",

@ -1719,6 +1719,28 @@
"windows" "windows"
] ]
}, },
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "parse_address_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{ {
"args": [], "args": [],
"ci_platforms": [ "ci_platforms": [
@ -2115,6 +2137,28 @@
"windows" "windows"
] ]
}, },
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "stream_owned_slice_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{ {
"args": [], "args": [],
"ci_platforms": [ "ci_platforms": [
@ -80560,6 +80604,28 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6520142139752448"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [
"tsan"
],
"exclude_iomgrs": [
"uv"
],
"flaky": false,
"language": "c",
"name": "api_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0597bbdd657fa4ed14443994c9147a1a7bbc205f" "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-0597bbdd657fa4ed14443994c9147a1a7bbc205f"

@ -413,11 +413,12 @@ class NodeLanguage:
client_type='ASYNC_CLIENT', server_type='async_server', client_type='ASYNC_CLIENT', server_type='async_server',
client_language='c++') client_language='c++')
yield _ping_pong_scenario( # TODO(murgatroid99): fix bugs with this scenario and re-enable it
'node_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY', # yield _ping_pong_scenario(
client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER', # 'node_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
unconstrained_client='async', # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
categories=[SCALABLE, SMOKETEST]) # unconstrained_client='async',
# categories=[SCALABLE, SMOKETEST])
# TODO(jtattermusch): make this scenario work # TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario( #yield _ping_pong_scenario(

@ -40,7 +40,10 @@ import tempfile
import time import time
def start_port_server(port_server_port): # must be synchronized with test/core/utils/port_server_client.h
_PORT_SERVER_PORT = 32766
def start_port_server():
# check if a compatible port server is running # check if a compatible port server is running
# if incompatible (version mismatch) ==> start a new one # if incompatible (version mismatch) ==> start a new one
# if not running ==> start a new one # if not running ==> start a new one
@ -48,7 +51,7 @@ def start_port_server(port_server_port):
try: try:
version = int( version = int(
urllib.request.urlopen( urllib.request.urlopen(
'http://localhost:%d/version_number' % port_server_port, 'http://localhost:%d/version_number' % _PORT_SERVER_PORT,
timeout=10).read()) timeout=10).read())
logging.info('detected port server running version %d', version) logging.info('detected port server running version %d', version)
running = True running = True
@ -67,7 +70,7 @@ def start_port_server(port_server_port):
if not running: if not running:
logging.info('port_server version mismatch: killing the old one') logging.info('port_server version mismatch: killing the old one')
urllib.request.urlopen('http://localhost:%d/quitquitquit' % urllib.request.urlopen('http://localhost:%d/quitquitquit' %
port_server_port).read() _PORT_SERVER_PORT).read()
time.sleep(1) time.sleep(1)
if not running: if not running:
fd, logfile = tempfile.mkstemp() fd, logfile = tempfile.mkstemp()
@ -76,7 +79,7 @@ def start_port_server(port_server_port):
args = [ args = [
sys.executable, sys.executable,
os.path.abspath('tools/run_tests/python_utils/port_server.py'), os.path.abspath('tools/run_tests/python_utils/port_server.py'),
'-p', '%d' % port_server_port, '-l', logfile '-p', '%d' % _PORT_SERVER_PORT, '-l', logfile
] ]
env = dict(os.environ) env = dict(os.environ)
env['BUILD_ID'] = 'pleaseDontKillMeJenkins' env['BUILD_ID'] = 'pleaseDontKillMeJenkins'
@ -107,7 +110,7 @@ def start_port_server(port_server_port):
time.sleep(1) time.sleep(1)
try: try:
urllib.request.urlopen( urllib.request.urlopen(
'http://localhost:%d/get' % port_server_port, 'http://localhost:%d/get' % _PORT_SERVER_PORT,
timeout=1).read() timeout=1).read()
logging.info( logging.info(
'last ditch attempt to contact port server succeeded') 'last ditch attempt to contact port server succeeded')
@ -119,7 +122,7 @@ def start_port_server(port_server_port):
print(port_log) print(port_log)
sys.exit(1) sys.exit(1)
try: try:
port_server_url = 'http://localhost:%d/get' % port_server_port port_server_url = 'http://localhost:%d/get' % _PORT_SERVER_PORT
urllib.request.urlopen(port_server_url, timeout=1).read() urllib.request.urlopen(port_server_url, timeout=1).read()
logging.info('port server is up and ready') logging.info('port server is up and ready')
break break

@ -77,11 +77,15 @@ class CXXLanguage:
def __init__(self): def __init__(self):
self.client_cwd = None self.client_cwd = None
self.server_cwd = None self.server_cwd = None
self.http2_cwd = None
self.safename = 'cxx' self.safename = 'cxx'
def client_cmd(self, args): def client_cmd(self, args):
return ['bins/opt/interop_client'] + args return ['bins/opt/interop_client'] + args
def client_cmd_http2interop(self, args):
return ['bins/opt/http2_client'] + args
def cloud_to_prod_env(self): def cloud_to_prod_env(self):
return {} return {}
@ -474,7 +478,7 @@ _HTTP2_TEST_CASES = ['tls', 'framing']
_HTTP2_BADSERVER_TEST_CASES = ['rst_after_header', 'rst_after_data', 'rst_during_data', _HTTP2_BADSERVER_TEST_CASES = ['rst_after_header', 'rst_after_data', 'rst_during_data',
'goaway', 'ping', 'max_streams'] 'goaway', 'ping', 'max_streams']
_LANGUAGES_FOR_HTTP2_BADSERVER_TESTS = ['java', 'go', 'python'] _LANGUAGES_FOR_HTTP2_BADSERVER_TESTS = ['java', 'go', 'python', 'c++']
DOCKER_WORKDIR_ROOT = '/var/local/git/grpc' DOCKER_WORKDIR_ROOT = '/var/local/git/grpc'

@ -44,8 +44,7 @@ os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
if not os.path.exists('reports'): if not os.path.exists('reports'):
os.makedirs('reports') os.makedirs('reports')
port_server_port = 32766 start_port_server.start_port_server()
start_port_server.start_port_server(port_server_port)
def fnize(s): def fnize(s):
out = '' out = ''
@ -110,8 +109,7 @@ def collect_latency(bm_name, args):
if len(benchmarks) >= min(16, multiprocessing.cpu_count()): if len(benchmarks) >= min(16, multiprocessing.cpu_count()):
# run up to half the cpu count: each benchmark can use up to two cores # run up to half the cpu count: each benchmark can use up to two cores
# (one for the microbenchmark, one for the data flush) # (one for the microbenchmark, one for the data flush)
jobset.run(benchmarks, maxjobs=max(1, multiprocessing.cpu_count()/2), jobset.run(benchmarks, maxjobs=max(1, multiprocessing.cpu_count()/2))
add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count()) jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
jobset.run(cleanup, maxjobs=multiprocessing.cpu_count()) jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())
benchmarks = [] benchmarks = []
@ -119,8 +117,7 @@ def collect_latency(bm_name, args):
cleanup = [] cleanup = []
# run the remaining benchmarks that weren't flushed # run the remaining benchmarks that weren't flushed
if len(benchmarks): if len(benchmarks):
jobset.run(benchmarks, maxjobs=max(1, multiprocessing.cpu_count()/2), jobset.run(benchmarks, maxjobs=max(1, multiprocessing.cpu_count()/2))
add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count()) jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
jobset.run(cleanup, maxjobs=multiprocessing.cpu_count()) jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())
@ -156,8 +153,7 @@ def collect_perf(bm_name, args):
if len(benchmarks) >= 20: if len(benchmarks) >= 20:
# run up to half the cpu count: each benchmark can use up to two cores # run up to half the cpu count: each benchmark can use up to two cores
# (one for the microbenchmark, one for the data flush) # (one for the microbenchmark, one for the data flush)
jobset.run(benchmarks, maxjobs=1, jobset.run(benchmarks, maxjobs=1)
add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count()) jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
jobset.run(cleanup, maxjobs=multiprocessing.cpu_count()) jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())
benchmarks = [] benchmarks = []
@ -165,8 +161,7 @@ def collect_perf(bm_name, args):
cleanup = [] cleanup = []
# run the remaining benchmarks that weren't flushed # run the remaining benchmarks that weren't flushed
if len(benchmarks): if len(benchmarks):
jobset.run(benchmarks, maxjobs=1, jobset.run(benchmarks, maxjobs=1)
add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port})
jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count()) jobset.run(profile_analysis, maxjobs=multiprocessing.cpu_count())
jobset.run(cleanup, maxjobs=multiprocessing.cpu_count()) jobset.run(cleanup, maxjobs=multiprocessing.cpu_count())

@ -692,18 +692,11 @@ class RubyLanguage(object):
_check_compiler(self.args.compiler, ['default']) _check_compiler(self.args.compiler, ['default'])
def test_specs(self): def test_specs(self):
#TODO(apolcyn) turn mac ruby tests back on once ruby 2.4 issues done
if platform_string() == 'mac':
print('skipping ruby test_specs on mac until running on 2.4')
return []
return [self.config.job_spec(['tools/run_tests/helper_scripts/run_ruby.sh'], return [self.config.job_spec(['tools/run_tests/helper_scripts/run_ruby.sh'],
timeout_seconds=10*60, timeout_seconds=10*60,
environ=_FORCE_ENVIRON_FOR_WRAPPERS)] environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
def pre_build_steps(self): def pre_build_steps(self):
if platform_string() == 'mac':
print('skipping ruby pre_build_steps on mac until running on 2.4')
return []
return [['tools/run_tests/helper_scripts/pre_build_ruby.sh']] return [['tools/run_tests/helper_scripts/pre_build_ruby.sh']]
def make_targets(self): def make_targets(self):
@ -713,15 +706,9 @@ class RubyLanguage(object):
return [] return []
def build_steps(self): def build_steps(self):
if platform_string() == 'mac':
print('skipping ruby build_steps on mac until running on 2.4')
return []
return [['tools/run_tests/helper_scripts/build_ruby.sh']] return [['tools/run_tests/helper_scripts/build_ruby.sh']]
def post_tests_steps(self): def post_tests_steps(self):
if platform_string() == 'mac':
print('skipping ruby post_test_steps on mac until running on 2.4')
return []
return [['tools/run_tests/helper_scripts/post_tests_ruby.sh']] return [['tools/run_tests/helper_scripts/post_tests_ruby.sh']]
def makefile_name(self): def makefile_name(self):
@ -1451,8 +1438,7 @@ def _build_and_run(
# start antagonists # start antagonists
antagonists = [subprocess.Popen(['tools/run_tests/python_utils/antagonist.py']) antagonists = [subprocess.Popen(['tools/run_tests/python_utils/antagonist.py'])
for _ in range(0, args.antagonists)] for _ in range(0, args.antagonists)]
port_server_port = 32766 start_port_server.start_port_server()
start_port_server.start_port_server(port_server_port)
resultset = None resultset = None
num_test_failures = 0 num_test_failures = 0
try: try:
@ -1495,7 +1481,6 @@ def _build_and_run(
all_runs, check_cancelled, newline_on_success=newline_on_success, all_runs, check_cancelled, newline_on_success=newline_on_success,
travis=args.travis, maxjobs=args.jobs, travis=args.travis, maxjobs=args.jobs,
stop_on_failure=args.stop_on_failure, stop_on_failure=args.stop_on_failure,
add_env={'GRPC_TEST_PORT_SERVER': 'localhost:%d' % port_server_port},
quiet_success=args.quiet_success) quiet_success=args.quiet_success)
if resultset: if resultset:
for k, v in sorted(resultset.items()): for k, v in sorted(resultset.items()):

@ -70,7 +70,8 @@ def _workspace_jobspec(name, runtests_args=[], workspace_name=None, inner_jobs=_
workspace_name = 'workspace_%s' % name workspace_name = 'workspace_%s' % name
env = {'WORKSPACE_NAME': workspace_name} env = {'WORKSPACE_NAME': workspace_name}
test_job = jobset.JobSpec( test_job = jobset.JobSpec(
cmdline=['tools/run_tests/helper_scripts/run_tests_in_workspace.sh', cmdline=['bash',
'tools/run_tests/helper_scripts/run_tests_in_workspace.sh',
'-t', '-t',
'-j', str(inner_jobs), '-j', str(inner_jobs),
'-x', '../report_%s.xml' % name, '-x', '../report_%s.xml' % name,

@ -0,0 +1,46 @@
#!/usr/bin/env python
# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
Wrapper around port server starting code.
Used by developers who wish to run individual C/C++ tests outside of the
run_tests.py infrastructure.
The path to this file is called out in test/core/util/port.c, and printed as
an error message to users.
"""
import python_utils.start_port_server as start_port_server
start_port_server.start_port_server()
print "Port server started successfully"

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

Loading…
Cancel
Save