Merge branch 'master' into uv_core_transport

pull/8125/head
murgatroid99 8 years ago
commit dc393537fb
  1. 148
      BUILD
  2. 163
      CMakeLists.txt
  3. 223
      Makefile
  4. 22
      build.yaml
  5. 6
      doc/interop-test-descriptions.md
  6. 3
      include/grpc++/security/credentials.h
  7. 141
      src/core/ext/client_channel/client_channel.c
  8. 56
      src/core/ext/client_channel/method_config.c
  9. 24
      src/core/ext/client_channel/method_config.h
  10. 77
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  11. 74
      src/core/lib/channel/message_size_filter.c
  12. 113
      src/core/lib/iomgr/udp_server.c
  13. 2
      src/core/lib/iomgr/udp_server.h
  14. 37
      src/core/lib/transport/mdstr_hash_table.c
  15. 9
      src/core/lib/transport/mdstr_hash_table.h
  16. 69
      src/cpp/client/cronet_credentials.cc
  17. 4
      src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs
  18. 1
      src/csharp/Grpc.Core/DefaultCallInvoker.cs
  19. 1
      src/csharp/Grpc.Core/Grpc.Core.csproj
  20. 1
      src/csharp/Grpc.Core/GrpcEnvironment.cs
  21. 15
      src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
  22. 29
      src/csharp/Grpc.Core/Internal/CompletionRegistry.cs
  23. 2
      src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs
  24. 7
      src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
  25. 41
      src/csharp/Grpc.Core/Internal/NativeMethods.cs
  26. 85
      src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
  27. 6
      src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
  28. 6
      src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs
  29. 70
      src/csharp/Grpc.Core/Metadata.cs
  30. 56
      src/csharp/Grpc.Core/Server.cs
  31. 16
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  32. 8
      src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
  33. 5
      src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
  34. 37
      src/csharp/Grpc.IntegrationTesting/Test.cs
  35. 105
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  36. 64
      src/csharp/ext/grpc_csharp_ext.c
  37. 16
      src/node/interop/interop_client.js
  38. 4
      src/node/test/interop_sanity_test.js
  39. 27
      test/cpp/interop/interop_test.cc
  40. 79
      test/cpp/interop/stress_test.cc
  41. 25
      tools/run_tests/run_performance_tests.py
  42. 23
      tools/run_tests/sources_and_headers.json
  43. 2
      vsprojects/vcxproj/test/stress_test/stress_test.vcxproj
  44. 3
      vsprojects/vcxproj/test/stress_test/stress_test.vcxproj.filters

148
BUILD

@ -1484,6 +1484,154 @@ cc_library(
cc_library(
name = "grpc++_cronet",
srcs = [
"src/cpp/client/create_channel_internal.h",
"src/cpp/common/channel_filter.h",
"src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h",
"src/cpp/client/cronet_credentials.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/common/insecure_create_auth_context.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/client/channel_cc.cc",
"src/cpp/client/client_context.cc",
"src/cpp/client/create_channel.cc",
"src/cpp/client/create_channel_internal.cc",
"src/cpp/client/create_channel_posix.cc",
"src/cpp/client/credentials_cc.cc",
"src/cpp/client/generic_stub.cc",
"src/cpp/common/channel_arguments.cc",
"src/cpp/common/channel_filter.cc",
"src/cpp/common/completion_queue_cc.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
"src/cpp/server/dynamic_thread_pool.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_cc.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
"src/cpp/server/server_posix.cc",
"src/cpp/util/byte_buffer_cc.cc",
"src/cpp/util/slice_cc.cc",
"src/cpp/util/status.cc",
"src/cpp/util/string_ref.cc",
"src/cpp/util/time_cc.cc",
"src/cpp/codegen/codegen_init.cc",
],
hdrs = [
"include/grpc++/alarm.h",
"include/grpc++/channel.h",
"include/grpc++/client_context.h",
"include/grpc++/completion_queue.h",
"include/grpc++/create_channel.h",
"include/grpc++/create_channel_posix.h",
"include/grpc++/generic/async_generic_service.h",
"include/grpc++/generic/generic_stub.h",
"include/grpc++/grpc++.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
"include/grpc++/impl/codegen/core_codegen.h",
"include/grpc++/impl/grpc_library.h",
"include/grpc++/impl/method_handler_impl.h",
"include/grpc++/impl/rpc_method.h",
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/serialization_traits.h",
"include/grpc++/impl/server_builder_option.h",
"include/grpc++/impl/server_builder_plugin.h",
"include/grpc++/impl/server_initializer.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",
"include/grpc++/impl/sync_no_cxx11.h",
"include/grpc++/impl/thd.h",
"include/grpc++/impl/thd_cxx11.h",
"include/grpc++/impl/thd_no_cxx11.h",
"include/grpc++/security/auth_context.h",
"include/grpc++/security/auth_metadata_processor.h",
"include/grpc++/security/credentials.h",
"include/grpc++/security/server_credentials.h",
"include/grpc++/server.h",
"include/grpc++/server_builder.h",
"include/grpc++/server_context.h",
"include/grpc++/server_posix.h",
"include/grpc++/support/async_stream.h",
"include/grpc++/support/async_unary_call.h",
"include/grpc++/support/byte_buffer.h",
"include/grpc++/support/channel_arguments.h",
"include/grpc++/support/config.h",
"include/grpc++/support/slice.h",
"include/grpc++/support/status.h",
"include/grpc++/support/status_code_enum.h",
"include/grpc++/support/string_ref.h",
"include/grpc++/support/stub_options.h",
"include/grpc++/support/sync_stream.h",
"include/grpc++/support/time.h",
"include/grpc++/impl/codegen/async_stream.h",
"include/grpc++/impl/codegen/async_unary_call.h",
"include/grpc++/impl/codegen/call.h",
"include/grpc++/impl/codegen/call_hook.h",
"include/grpc++/impl/codegen/channel_interface.h",
"include/grpc++/impl/codegen/client_context.h",
"include/grpc++/impl/codegen/client_unary_call.h",
"include/grpc++/impl/codegen/completion_queue.h",
"include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/create_auth_context.h",
"include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/rpc_method.h",
"include/grpc++/impl/codegen/rpc_service_method.h",
"include/grpc++/impl/codegen/security/auth_context.h",
"include/grpc++/impl/codegen/serialization_traits.h",
"include/grpc++/impl/codegen/server_context.h",
"include/grpc++/impl/codegen/server_interface.h",
"include/grpc++/impl/codegen/service_type.h",
"include/grpc++/impl/codegen/status.h",
"include/grpc++/impl/codegen/status_code_enum.h",
"include/grpc++/impl/codegen/status_helper.h",
"include/grpc++/impl/codegen/string_ref.h",
"include/grpc++/impl/codegen/stub_options.h",
"include/grpc++/impl/codegen/sync.h",
"include/grpc++/impl/codegen/sync_cxx11.h",
"include/grpc++/impl/codegen/sync_no_cxx11.h",
"include/grpc++/impl/codegen/sync_stream.h",
"include/grpc++/impl/codegen/time.h",
"include/grpc/impl/codegen/byte_buffer_reader.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc/impl/codegen/atm.h",
"include/grpc/impl/codegen/atm_gcc_atomic.h",
"include/grpc/impl/codegen/atm_gcc_sync.h",
"include/grpc/impl/codegen/atm_windows.h",
"include/grpc/impl/codegen/gpr_types.h",
"include/grpc/impl/codegen/port_platform.h",
"include/grpc/impl/codegen/slice.h",
"include/grpc/impl/codegen/sync.h",
"include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_windows.h",
],
includes = [
"include",
".",
],
deps = [
"//external:libssl",
":gpr",
":grpc_cronet",
],
)
cc_library(
name = "grpc++_reflection",
srcs = [

@ -1211,6 +1211,169 @@ if (gRPC_INSTALL)
endif()
add_library(grpc++_cronet
src/cpp/client/cronet_credentials.cc
src/cpp/client/insecure_credentials.cc
src/cpp/common/insecure_create_auth_context.cc
src/cpp/server/insecure_server_credentials.cc
src/cpp/client/channel_cc.cc
src/cpp/client/client_context.cc
src/cpp/client/create_channel.cc
src/cpp/client/create_channel_internal.cc
src/cpp/client/create_channel_posix.cc
src/cpp/client/credentials_cc.cc
src/cpp/client/generic_stub.cc
src/cpp/common/channel_arguments.cc
src/cpp/common/channel_filter.cc
src/cpp/common/completion_queue_cc.cc
src/cpp/common/core_codegen.cc
src/cpp/common/rpc_method.cc
src/cpp/server/async_generic_service.cc
src/cpp/server/create_default_thread_pool.cc
src/cpp/server/dynamic_thread_pool.cc
src/cpp/server/server_builder.cc
src/cpp/server/server_cc.cc
src/cpp/server/server_context.cc
src/cpp/server/server_credentials.cc
src/cpp/server/server_posix.cc
src/cpp/util/byte_buffer_cc.cc
src/cpp/util/slice_cc.cc
src/cpp/util/status.cc
src/cpp/util/string_ref.cc
src/cpp/util/time_cc.cc
src/cpp/codegen/codegen_init.cc
)
target_include_directories(grpc++_cronet
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${ZLIB_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
)
target_link_libraries(grpc++_cronet
${_gRPC_BASELIB_LIBRARIES}
${_gRPC_SSL_LIBRARIES}
gpr
grpc_cronet
)
foreach(_hdr
include/grpc++/alarm.h
include/grpc++/channel.h
include/grpc++/client_context.h
include/grpc++/completion_queue.h
include/grpc++/create_channel.h
include/grpc++/create_channel_posix.h
include/grpc++/generic/async_generic_service.h
include/grpc++/generic/generic_stub.h
include/grpc++/grpc++.h
include/grpc++/impl/call.h
include/grpc++/impl/client_unary_call.h
include/grpc++/impl/codegen/core_codegen.h
include/grpc++/impl/grpc_library.h
include/grpc++/impl/method_handler_impl.h
include/grpc++/impl/rpc_method.h
include/grpc++/impl/rpc_service_method.h
include/grpc++/impl/serialization_traits.h
include/grpc++/impl/server_builder_option.h
include/grpc++/impl/server_builder_plugin.h
include/grpc++/impl/server_initializer.h
include/grpc++/impl/service_type.h
include/grpc++/impl/sync.h
include/grpc++/impl/sync_cxx11.h
include/grpc++/impl/sync_no_cxx11.h
include/grpc++/impl/thd.h
include/grpc++/impl/thd_cxx11.h
include/grpc++/impl/thd_no_cxx11.h
include/grpc++/security/auth_context.h
include/grpc++/security/auth_metadata_processor.h
include/grpc++/security/credentials.h
include/grpc++/security/server_credentials.h
include/grpc++/server.h
include/grpc++/server_builder.h
include/grpc++/server_context.h
include/grpc++/server_posix.h
include/grpc++/support/async_stream.h
include/grpc++/support/async_unary_call.h
include/grpc++/support/byte_buffer.h
include/grpc++/support/channel_arguments.h
include/grpc++/support/config.h
include/grpc++/support/slice.h
include/grpc++/support/status.h
include/grpc++/support/status_code_enum.h
include/grpc++/support/string_ref.h
include/grpc++/support/stub_options.h
include/grpc++/support/sync_stream.h
include/grpc++/support/time.h
include/grpc++/impl/codegen/async_stream.h
include/grpc++/impl/codegen/async_unary_call.h
include/grpc++/impl/codegen/call.h
include/grpc++/impl/codegen/call_hook.h
include/grpc++/impl/codegen/channel_interface.h
include/grpc++/impl/codegen/client_context.h
include/grpc++/impl/codegen/client_unary_call.h
include/grpc++/impl/codegen/completion_queue.h
include/grpc++/impl/codegen/completion_queue_tag.h
include/grpc++/impl/codegen/config.h
include/grpc++/impl/codegen/core_codegen_interface.h
include/grpc++/impl/codegen/create_auth_context.h
include/grpc++/impl/codegen/grpc_library.h
include/grpc++/impl/codegen/method_handler_impl.h
include/grpc++/impl/codegen/rpc_method.h
include/grpc++/impl/codegen/rpc_service_method.h
include/grpc++/impl/codegen/security/auth_context.h
include/grpc++/impl/codegen/serialization_traits.h
include/grpc++/impl/codegen/server_context.h
include/grpc++/impl/codegen/server_interface.h
include/grpc++/impl/codegen/service_type.h
include/grpc++/impl/codegen/status.h
include/grpc++/impl/codegen/status_code_enum.h
include/grpc++/impl/codegen/status_helper.h
include/grpc++/impl/codegen/string_ref.h
include/grpc++/impl/codegen/stub_options.h
include/grpc++/impl/codegen/sync.h
include/grpc++/impl/codegen/sync_cxx11.h
include/grpc++/impl/codegen/sync_no_cxx11.h
include/grpc++/impl/codegen/sync_stream.h
include/grpc++/impl/codegen/time.h
include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h
include/grpc/impl/codegen/grpc_types.h
include/grpc/impl/codegen/propagation_bits.h
include/grpc/impl/codegen/status.h
include/grpc/impl/codegen/atm.h
include/grpc/impl/codegen/atm_gcc_atomic.h
include/grpc/impl/codegen/atm_gcc_sync.h
include/grpc/impl/codegen/atm_windows.h
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/slice.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
)
string(REPLACE "include/" "" _path ${_hdr})
get_filename_component(_path ${_path} PATH)
install(FILES ${_hdr}
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}"
)
endforeach()
if (gRPC_INSTALL)
install(TARGETS grpc++_cronet EXPORT gRPCTargets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
endif()
add_library(grpc++_reflection
src/cpp/ext/proto_server_reflection.cc
src/cpp/ext/proto_server_reflection_plugin.cc

@ -1208,12 +1208,12 @@ static: static_c static_cxx
static_c: pc_c pc_c_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a
static_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a
static_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a
shared: shared_c shared_cxx
shared_c: pc_c pc_c_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT)
shared_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT)
shared_cxx: pc_cxx pc_cxx_unsecure cache.mk $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT)
shared_csharp: shared_c $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT)
grpc_csharp_ext: shared_csharp
@ -1903,6 +1903,8 @@ strip-static_cxx: static_cxx
ifeq ($(CONFIG),opt)
$(E) "[STRIP] Stripping libgrpc++.a"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++.a
$(E) "[STRIP] Stripping libgrpc++_cronet.a"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a
$(E) "[STRIP] Stripping libgrpc++_reflection.a"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a
$(E) "[STRIP] Stripping libgrpc++_unsecure.a"
@ -1925,6 +1927,8 @@ strip-shared_cxx: shared_cxx
ifeq ($(CONFIG),opt)
$(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT)
$(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT)
$(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT)
$(E) "[STRIP] Stripping $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT)"
@ -2246,6 +2250,9 @@ install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx
$(E) "[INSTALL] Installing libgrpc++.a"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(prefix)/lib/libgrpc++.a
$(E) "[INSTALL] Installing libgrpc++_cronet.a"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(prefix)/lib/libgrpc++_cronet.a
$(E) "[INSTALL] Installing libgrpc++_reflection.a"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(prefix)/lib/libgrpc++_reflection.a
@ -2308,6 +2315,15 @@ ifeq ($(SYSTEM),MINGW32)
else ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc++.so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc++.so
endif
$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT)
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet-imp.a $(prefix)/lib/libgrpc++_cronet-imp.a
else ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc++_cronet.so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(prefix)/lib/libgrpc++_cronet.so
endif
$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT)"
$(Q) $(INSTALL) -d $(prefix)/lib
@ -3847,6 +3863,198 @@ endif
endif
LIBGRPC++_CRONET_SRC = \
src/cpp/client/cronet_credentials.cc \
src/cpp/client/insecure_credentials.cc \
src/cpp/common/insecure_create_auth_context.cc \
src/cpp/server/insecure_server_credentials.cc \
src/cpp/client/channel_cc.cc \
src/cpp/client/client_context.cc \
src/cpp/client/create_channel.cc \
src/cpp/client/create_channel_internal.cc \
src/cpp/client/create_channel_posix.cc \
src/cpp/client/credentials_cc.cc \
src/cpp/client/generic_stub.cc \
src/cpp/common/channel_arguments.cc \
src/cpp/common/channel_filter.cc \
src/cpp/common/completion_queue_cc.cc \
src/cpp/common/core_codegen.cc \
src/cpp/common/rpc_method.cc \
src/cpp/server/async_generic_service.cc \
src/cpp/server/create_default_thread_pool.cc \
src/cpp/server/dynamic_thread_pool.cc \
src/cpp/server/server_builder.cc \
src/cpp/server/server_cc.cc \
src/cpp/server/server_context.cc \
src/cpp/server/server_credentials.cc \
src/cpp/server/server_posix.cc \
src/cpp/util/byte_buffer_cc.cc \
src/cpp/util/slice_cc.cc \
src/cpp/util/status.cc \
src/cpp/util/string_ref.cc \
src/cpp/util/time_cc.cc \
src/cpp/codegen/codegen_init.cc \
PUBLIC_HEADERS_CXX += \
include/grpc++/alarm.h \
include/grpc++/channel.h \
include/grpc++/client_context.h \
include/grpc++/completion_queue.h \
include/grpc++/create_channel.h \
include/grpc++/create_channel_posix.h \
include/grpc++/generic/async_generic_service.h \
include/grpc++/generic/generic_stub.h \
include/grpc++/grpc++.h \
include/grpc++/impl/call.h \
include/grpc++/impl/client_unary_call.h \
include/grpc++/impl/codegen/core_codegen.h \
include/grpc++/impl/grpc_library.h \
include/grpc++/impl/method_handler_impl.h \
include/grpc++/impl/rpc_method.h \
include/grpc++/impl/rpc_service_method.h \
include/grpc++/impl/serialization_traits.h \
include/grpc++/impl/server_builder_option.h \
include/grpc++/impl/server_builder_plugin.h \
include/grpc++/impl/server_initializer.h \
include/grpc++/impl/service_type.h \
include/grpc++/impl/sync.h \
include/grpc++/impl/sync_cxx11.h \
include/grpc++/impl/sync_no_cxx11.h \
include/grpc++/impl/thd.h \
include/grpc++/impl/thd_cxx11.h \
include/grpc++/impl/thd_no_cxx11.h \
include/grpc++/security/auth_context.h \
include/grpc++/security/auth_metadata_processor.h \
include/grpc++/security/credentials.h \
include/grpc++/security/server_credentials.h \
include/grpc++/server.h \
include/grpc++/server_builder.h \
include/grpc++/server_context.h \
include/grpc++/server_posix.h \
include/grpc++/support/async_stream.h \
include/grpc++/support/async_unary_call.h \
include/grpc++/support/byte_buffer.h \
include/grpc++/support/channel_arguments.h \
include/grpc++/support/config.h \
include/grpc++/support/slice.h \
include/grpc++/support/status.h \
include/grpc++/support/status_code_enum.h \
include/grpc++/support/string_ref.h \
include/grpc++/support/stub_options.h \
include/grpc++/support/sync_stream.h \
include/grpc++/support/time.h \
include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \
include/grpc++/impl/codegen/client_context.h \
include/grpc++/impl/codegen/client_unary_call.h \
include/grpc++/impl/codegen/completion_queue.h \
include/grpc++/impl/codegen/completion_queue_tag.h \
include/grpc++/impl/codegen/config.h \
include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/create_auth_context.h \
include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/rpc_method.h \
include/grpc++/impl/codegen/rpc_service_method.h \
include/grpc++/impl/codegen/security/auth_context.h \
include/grpc++/impl/codegen/serialization_traits.h \
include/grpc++/impl/codegen/server_context.h \
include/grpc++/impl/codegen/server_interface.h \
include/grpc++/impl/codegen/service_type.h \
include/grpc++/impl/codegen/status.h \
include/grpc++/impl/codegen/status_code_enum.h \
include/grpc++/impl/codegen/status_helper.h \
include/grpc++/impl/codegen/string_ref.h \
include/grpc++/impl/codegen/stub_options.h \
include/grpc++/impl/codegen/sync.h \
include/grpc++/impl/codegen/sync_cxx11.h \
include/grpc++/impl/codegen/sync_no_cxx11.h \
include/grpc++/impl/codegen/sync_stream.h \
include/grpc++/impl/codegen/time.h \
include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \
include/grpc/impl/codegen/grpc_types.h \
include/grpc/impl/codegen/propagation_bits.h \
include/grpc/impl/codegen/status.h \
include/grpc/impl/codegen/atm.h \
include/grpc/impl/codegen/atm_gcc_atomic.h \
include/grpc/impl/codegen/atm_gcc_sync.h \
include/grpc/impl/codegen/atm_windows.h \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/slice.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a: openssl_dep_error
$(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT): openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
$(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a: protobuf_dep_error
$(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT): protobuf_dep_error
else
$(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_CRONET_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(OPENSSL_MERGE_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a
$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(LIBGRPC++_CRONET_OBJS) $(LIBGPR_OBJS) $(ZLIB_MERGE_OBJS) $(OPENSSL_MERGE_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a
endif
ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/grpc_cronet.$(SHARED_EXT) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_cronet.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_cronet-imp
else
$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION).$(SHARED_EXT): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT) $(OPENSSL_DEP)
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet
else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.1 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION).so
endif
endif
endif
endif
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(LIBGRPC++_CRONET_OBJS:.o=.dep)
endif
endif
LIBGRPC++_REFLECTION_SRC = \
src/cpp/ext/proto_server_reflection.cc \
src/cpp/ext/proto_server_reflection_plugin.cc \
@ -12260,16 +12468,16 @@ $(BINDIR)/$(CONFIG)/interop_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/interop_test: $(PROTOBUF_DEP) $(INTEROP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(BINDIR)/$(CONFIG)/interop_test: $(PROTOBUF_DEP) $(INTEROP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(INTEROP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/interop_test
$(Q) $(LDXX) $(LDFLAGS) $(INTEROP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/interop_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_interop_test: $(INTEROP_TEST_OBJS:.o=.dep)
@ -13129,6 +13337,7 @@ STRESS_TEST_SRC = \
$(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \
test/cpp/interop/client_helper.cc \
test/cpp/interop/interop_client.cc \
test/cpp/interop/stress_interop_client.cc \
test/cpp/interop/stress_test.cc \
@ -13171,6 +13380,8 @@ $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/metrics.o: $(LIBDIR)/$(CONFIG)/libgr
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(OBJDIR)/$(CONFIG)/test/cpp/interop/client_helper.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_interop_client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
@ -13186,6 +13397,7 @@ ifneq ($(NO_DEPS),true)
-include $(STRESS_TEST_OBJS:.o=.dep)
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/interop/client_helper.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_interop_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
$(OBJDIR)/$(CONFIG)/test/cpp/interop/stress_test.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
@ -15911,6 +16123,7 @@ src/core/lib/tsi/ssl_transport_security.c: $(OPENSSL_DEP)
src/core/lib/tsi/transport_security.c: $(OPENSSL_DEP)
src/core/plugin_registry/grpc_cronet_plugin_registry.c: $(OPENSSL_DEP)
src/core/plugin_registry/grpc_plugin_registry.c: $(OPENSSL_DEP)
src/cpp/client/cronet_credentials.cc: $(OPENSSL_DEP)
src/cpp/client/secure_credentials.cc: $(OPENSSL_DEP)
src/cpp/common/auth_property_iterator.cc: $(OPENSSL_DEP)
src/cpp/common/secure_auth_context.cc: $(OPENSSL_DEP)

@ -1028,6 +1028,26 @@ libs:
- grpc++_codegen_base_src
secure: check
vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}'
- name: grpc++_cronet
build: all
language: c++
src:
- src/cpp/client/cronet_credentials.cc
- src/cpp/client/insecure_credentials.cc
- src/cpp/common/insecure_create_auth_context.cc
- src/cpp/server/insecure_server_credentials.cc
deps:
- gpr
- grpc_cronet
baselib: true
dll: true
filegroups:
- grpc++_base
- grpc++_codegen_base
- grpc++_codegen_base_src
platforms:
- linux
secure: true
- name: grpc++_reflection
build: all
language: c++
@ -3106,6 +3126,7 @@ targets:
- grpc
- gpr_test_util
- gpr
- grpc++_test_config
platforms:
- mac
- linux
@ -3416,6 +3437,7 @@ targets:
- src/proto/grpc/testing/messages.proto
- src/proto/grpc/testing/metrics.proto
- src/proto/grpc/testing/test.proto
- test/cpp/interop/client_helper.cc
- test/cpp/interop/interop_client.cc
- test/cpp/interop/stress_interop_client.cc
- test/cpp/interop/stress_test.cc

@ -779,21 +779,21 @@ Client asserts:
### unimplemented_method
This test verifies that calling an unimplemented RPC method returns the
This test verifies that calling an unimplemented RPC method returns the
UNIMPLEMENTED status code.
Server features:
N/A
Procedure:
* Client calls `grpc.testing.TestService/UnimplementedMethod` with an empty
* Client calls `grpc.testing.TestService/UnimplementedCall` with an empty
request (defined as `grpc.testing.Empty`):
```
{
}
```
Client asserts:
* received status code is 12 (UNIMPLEMENTED)

@ -201,6 +201,9 @@ std::shared_ptr<CallCredentials> CompositeCallCredentials(
/// Credentials for an unencrypted, unauthenticated channel
std::shared_ptr<ChannelCredentials> InsecureChannelCredentials();
/// Credentials for a channel using Cronet.
std::shared_ptr<ChannelCredentials> CronetChannelCredentials(void* engine);
// User defined metadata credentials.
class MetadataCredentialsPlugin {
public:

@ -60,6 +60,54 @@
/* Client channel implementation */
/*************************************************************************
* METHOD-CONFIG TABLE
*/
typedef enum {
WAIT_FOR_READY_UNSET,
WAIT_FOR_READY_FALSE,
WAIT_FOR_READY_TRUE
} wait_for_ready_value;
typedef struct method_parameters {
gpr_timespec timeout;
wait_for_ready_value wait_for_ready;
} method_parameters;
static void *method_parameters_copy(void *value) {
void *new_value = gpr_malloc(sizeof(method_parameters));
memcpy(new_value, value, sizeof(method_parameters));
return new_value;
}
static int method_parameters_cmp(void *value1, void *value2) {
const method_parameters *v1 = value1;
const method_parameters *v2 = value2;
const int retval = gpr_time_cmp(v1->timeout, v2->timeout);
if (retval != 0) return retval;
if (v1->wait_for_ready > v2->wait_for_ready) return 1;
if (v1->wait_for_ready < v2->wait_for_ready) return -1;
return 0;
}
static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
gpr_free, method_parameters_copy, method_parameters_cmp};
static void *method_config_convert_value(
const grpc_method_config *method_config) {
method_parameters *value = gpr_malloc(sizeof(method_parameters));
const gpr_timespec *timeout = grpc_method_config_get_timeout(method_config);
value->timeout = timeout != NULL ? *timeout : gpr_time_0(GPR_TIMESPAN);
const bool *wait_for_ready =
grpc_method_config_get_wait_for_ready(method_config);
value->wait_for_ready =
wait_for_ready == NULL
? WAIT_FOR_READY_UNSET
: (wait_for_ready ? WAIT_FOR_READY_TRUE : WAIT_FOR_READY_FALSE);
return value;
}
/*************************************************************************
* CHANNEL-WIDE FUNCTIONS
*/
@ -76,8 +124,8 @@ typedef struct client_channel_channel_data {
gpr_mu mu;
/** currently active load balancer */
grpc_lb_policy *lb_policy;
/** method config table */
grpc_method_config_table *method_config_table;
/** maps method names to method_parameters structs */
grpc_mdstr_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */
grpc_resolver_result *resolver_result;
/** a list of closures that are all waiting for config to come in */
@ -177,7 +225,7 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
channel_data *chand = arg;
grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy;
grpc_method_config_table *method_config_table = NULL;
grpc_mdstr_hash_table *method_params_table = NULL;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
bool exit_idle = false;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
@ -230,8 +278,9 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
lb_policy_args.additional_args, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
method_config_table = grpc_method_config_table_ref(
(grpc_method_config_table *)channel_arg->value.pointer.p);
method_params_table = grpc_method_config_table_convert(
(grpc_method_config_table *)channel_arg->value.pointer.p,
method_config_convert_value, &method_parameters_vtable);
}
grpc_resolver_result_unref(exec_ctx, chand->resolver_result);
chand->resolver_result = NULL;
@ -245,10 +294,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_lock(&chand->mu);
old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy;
if (chand->method_config_table != NULL) {
grpc_method_config_table_unref(chand->method_config_table);
if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(chand->method_params_table);
}
chand->method_config_table = method_config_table;
chand->method_params_table = method_params_table;
if (lb_policy != NULL) {
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
NULL);
@ -409,8 +458,8 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
chand->interested_parties);
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
}
if (chand->method_config_table != NULL) {
grpc_method_config_table_unref(chand->method_config_table);
if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(chand->method_params_table);
}
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
grpc_pollset_set_destroy(chand->interested_parties);
@ -448,11 +497,7 @@ typedef struct client_channel_call_data {
grpc_mdstr *path; // Request path.
gpr_timespec call_start_time;
gpr_timespec deadline;
enum {
WAIT_FOR_READY_UNSET,
WAIT_FOR_READY_FALSE,
WAIT_FOR_READY_TRUE
} wait_for_ready_from_service_config;
wait_for_ready_value wait_for_ready_from_service_config;
grpc_closure read_service_config;
grpc_error *cancel_error;
@ -846,41 +891,39 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
if (error == GRPC_ERROR_NONE) {
// Get the method config table from channel data.
gpr_mu_lock(&chand->mu);
grpc_method_config_table *method_config_table = NULL;
if (chand->method_config_table != NULL) {
method_config_table =
grpc_method_config_table_ref(chand->method_config_table);
grpc_mdstr_hash_table *method_params_table = NULL;
if (chand->method_params_table != NULL) {
method_params_table =
grpc_mdstr_hash_table_ref(chand->method_params_table);
}
gpr_mu_unlock(&chand->mu);
// If the method config table was present, use it.
if (method_config_table != NULL) {
const grpc_method_config *method_config =
grpc_method_config_table_get_method_config(method_config_table,
calld->path);
if (method_config != NULL) {
const gpr_timespec *per_method_timeout =
grpc_method_config_get_timeout(method_config);
const bool *wait_for_ready =
grpc_method_config_get_wait_for_ready(method_config);
if (per_method_timeout != NULL || wait_for_ready != NULL) {
if (method_params_table != NULL) {
const method_parameters *method_params =
grpc_method_config_table_get(method_params_table, calld->path);
if (method_params != NULL) {
const bool have_method_timeout =
gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
if (have_method_timeout ||
method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
gpr_mu_lock(&calld->mu);
if (per_method_timeout != NULL) {
gpr_timespec per_method_deadline =
gpr_time_add(calld->call_start_time, *per_method_timeout);
if (have_method_timeout) {
const gpr_timespec per_method_deadline =
gpr_time_add(calld->call_start_time, method_params->timeout);
if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
calld->deadline = per_method_deadline;
// Reset deadline timer.
grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
}
}
if (wait_for_ready != NULL) {
if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
calld->wait_for_ready_from_service_config =
*wait_for_ready ? WAIT_FOR_READY_TRUE : WAIT_FOR_READY_FALSE;
method_params->wait_for_ready;
}
gpr_mu_unlock(&calld->mu);
}
}
grpc_method_config_table_unref(method_config_table);
grpc_mdstr_hash_table_unref(method_params_table);
}
}
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
@ -917,29 +960,25 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
gpr_mu_lock(&chand->mu);
if (chand->lb_policy != NULL) {
// We already have a resolver result, so check for service config.
if (chand->method_config_table != NULL) {
grpc_method_config_table *method_config_table =
grpc_method_config_table_ref(chand->method_config_table);
if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table *method_params_table =
grpc_mdstr_hash_table_ref(chand->method_params_table);
gpr_mu_unlock(&chand->mu);
grpc_method_config *method_config =
grpc_method_config_table_get_method_config(method_config_table,
args->path);
if (method_config != NULL) {
const gpr_timespec *per_method_timeout =
grpc_method_config_get_timeout(method_config);
if (per_method_timeout != NULL) {
method_parameters *method_params =
grpc_method_config_table_get(method_params_table, args->path);
if (method_params != NULL) {
if (gpr_time_cmp(method_params->timeout,
gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
gpr_timespec per_method_deadline =
gpr_time_add(calld->call_start_time, *per_method_timeout);
gpr_time_add(calld->call_start_time, method_params->timeout);
calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
}
const bool *wait_for_ready =
grpc_method_config_get_wait_for_ready(method_config);
if (wait_for_ready != NULL) {
if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
calld->wait_for_ready_from_service_config =
*wait_for_ready ? WAIT_FOR_READY_TRUE : WAIT_FOR_READY_FALSE;
method_params->wait_for_ready;
}
}
grpc_method_config_table_unref(method_config_table);
grpc_mdstr_hash_table_unref(method_params_table);
} else {
gpr_mu_unlock(&chand->mu);
}

@ -254,12 +254,12 @@ int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
return grpc_mdstr_hash_table_cmp(table1, table2);
}
grpc_method_config* grpc_method_config_table_get_method_config(
const grpc_method_config_table* table, const grpc_mdstr* path) {
grpc_method_config* method_config = grpc_mdstr_hash_table_get(table, path);
void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* path) {
void* value = grpc_mdstr_hash_table_get(table, path);
// If we didn't find a match for the path, try looking for a wildcard
// entry (i.e., change "/service/method" to "/service/*").
if (method_config == NULL) {
if (value == NULL) {
const char* path_str = grpc_mdstr_as_c_string(path);
const char* sep = strrchr(path_str, '/') + 1;
const size_t len = (size_t)(sep - path_str);
@ -269,10 +269,10 @@ grpc_method_config* grpc_method_config_table_get_method_config(
buf[len + 1] = '\0';
grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
gpr_free(buf);
method_config = grpc_mdstr_hash_table_get(table, wildcard_path);
value = grpc_mdstr_hash_table_get(table, wildcard_path);
GRPC_MDSTR_UNREF(wildcard_path);
}
return method_config;
return value;
}
static void* copy_arg(void* p) { return grpc_method_config_table_ref(p); }
@ -294,3 +294,47 @@ grpc_arg grpc_method_config_table_create_channel_arg(
arg.value.pointer.vtable = &arg_vtable;
return arg;
}
// State used by convert_entry() below.
typedef struct conversion_state {
void* (*convert_value)(const grpc_method_config* method_config);
const grpc_mdstr_hash_table_vtable* vtable;
size_t num_entries;
grpc_mdstr_hash_table_entry* entries;
} conversion_state;
// A function to be passed to grpc_mdstr_hash_table_iterate() to create
// a copy of the entries.
static void convert_entry(const grpc_mdstr_hash_table_entry* entry,
void* user_data) {
conversion_state* state = user_data;
state->entries[state->num_entries].key = GRPC_MDSTR_REF(entry->key);
state->entries[state->num_entries].value = state->convert_value(entry->value);
state->entries[state->num_entries].vtable = state->vtable;
++state->num_entries;
}
grpc_mdstr_hash_table* grpc_method_config_table_convert(
const grpc_method_config_table* table,
void* (*convert_value)(const grpc_method_config* method_config),
const grpc_mdstr_hash_table_vtable* vtable) {
// Create an array of the entries in the table with converted values.
conversion_state state;
state.convert_value = convert_value;
state.vtable = vtable;
state.num_entries = 0;
state.entries = gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) *
grpc_mdstr_hash_table_num_entries(table));
grpc_mdstr_hash_table_iterate(table, convert_entry, &state);
// Create a new table based on the array we just constructed.
grpc_mdstr_hash_table* new_table =
grpc_mdstr_hash_table_create(state.num_entries, state.entries);
// Clean up the array.
for (size_t i = 0; i < state.num_entries; ++i) {
GRPC_MDSTR_UNREF(state.entries[i].key);
vtable->destroy_value(state.entries[i].value);
}
gpr_free(state.entries);
// Return the new table.
return new_table;
}

@ -106,11 +106,31 @@ int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
/// the form "/service/method".
/// Returns NULL if the method has no config.
/// Caller does NOT own a reference to the result.
grpc_method_config* grpc_method_config_table_get_method_config(
const grpc_method_config_table* table, const grpc_mdstr* path);
///
/// Note: This returns a void* instead of a grpc_method_config* so that
/// it can also be used for tables constructed via
/// grpc_method_config_table_convert().
void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* path);
/// Returns a channel arg containing \a table.
grpc_arg grpc_method_config_table_create_channel_arg(
grpc_method_config_table* table);
/// Generates a new table from \a table whose values are converted to a
/// new form via the \a convert_value function. The new table will use
/// \a vtable for its values.
///
/// This is generally used to convert the table's value type from
/// grpc_method_config to a simple struct containing only the parameters
/// relevant to a particular filter, thus avoiding the need for a hash
/// table lookup on the fast path. In that scenario, \a convert_value
/// will return a new instance of the struct containing the values from
/// the grpc_method_config, and \a vtable provides the methods for
/// operating on the struct type.
grpc_mdstr_hash_table* grpc_method_config_table_convert(
const grpc_method_config_table* table,
void* (*convert_value)(const grpc_method_config* method_config),
const grpc_mdstr_hash_table_vtable* vtable);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_METHOD_CONFIG_H */

@ -853,53 +853,51 @@ static bool contains_non_ok_status(grpc_metadata_batch *batch) {
static void add_fetched_slice_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
grpc_chttp2_stream *s) {
s->fetched_send_message_length +=
(uint32_t)GPR_SLICE_LENGTH(s->fetching_slice);
gpr_slice_buffer_add(&s->flow_controlled_buffer, s->fetching_slice);
if (s->id != 0) {
grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message");
}
}
static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
if (s->fetching_send_message == NULL) {
/* Stream was cancelled before message fetch completed */
abort(); /* TODO(ctiller): what cleanup here? */
return;
}
if (s->fetched_send_message_length == s->fetching_send_message->length) {
int64_t notify_offset = s->next_message_end_offset;
if (notify_offset <= s->flow_controlled_bytes_written) {
grpc_chttp2_complete_closure_step(
exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_NONE,
"fetching_send_message_finished");
} else {
grpc_chttp2_write_cb *cb = t->write_cb_pool;
if (cb == NULL) {
cb = gpr_malloc(sizeof(*cb));
for (;;) {
if (s->fetching_send_message == NULL) {
/* Stream was cancelled before message fetch completed */
abort(); /* TODO(ctiller): what cleanup here? */
return; /* early out */
}
if (s->fetched_send_message_length == s->fetching_send_message->length) {
int64_t notify_offset = s->next_message_end_offset;
if (notify_offset <= s->flow_controlled_bytes_written) {
grpc_chttp2_complete_closure_step(
exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_NONE,
"fetching_send_message_finished");
} else {
t->write_cb_pool = cb->next;
grpc_chttp2_write_cb *cb = t->write_cb_pool;
if (cb == NULL) {
cb = gpr_malloc(sizeof(*cb));
} else {
t->write_cb_pool = cb->next;
}
cb->call_at_byte = notify_offset;
cb->closure = s->fetching_send_message_finished;
s->fetching_send_message_finished = NULL;
cb->next = s->on_write_finished_cbs;
s->on_write_finished_cbs = cb;
}
cb->call_at_byte = notify_offset;
cb->closure = s->fetching_send_message_finished;
s->fetching_send_message_finished = NULL;
cb->next = s->on_write_finished_cbs;
s->on_write_finished_cbs = cb;
s->fetching_send_message = NULL;
return; /* early out */
} else if (grpc_byte_stream_next(exec_ctx, s->fetching_send_message,
&s->fetching_slice, UINT32_MAX,
&s->complete_fetch)) {
add_fetched_slice_locked(exec_ctx, t, s);
}
s->fetching_send_message = NULL;
} else if (grpc_byte_stream_next(exec_ctx, s->fetching_send_message,
&s->fetching_slice, UINT32_MAX,
&s->complete_fetch)) {
add_fetched_slice_locked(exec_ctx, t, s);
}
}
static void add_fetched_slice_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
s->fetched_send_message_length +=
(uint32_t)GPR_SLICE_LENGTH(s->fetching_slice);
gpr_slice_buffer_add(&s->flow_controlled_buffer, s->fetching_slice);
if (s->id != 0) {
grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message");
}
continue_fetching_send_locked(exec_ctx, t, s);
}
static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
@ -908,6 +906,7 @@ static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
grpc_chttp2_transport *t = s->t;
if (error == GRPC_ERROR_NONE) {
add_fetched_slice_locked(exec_ctx, t, s);
continue_fetching_send_locked(exec_ctx, t, s);
} else {
/* TODO(ctiller): what to do here */
abort();

@ -45,6 +45,44 @@
// The protobuf library will (by default) start warning at 100 megs.
#define DEFAULT_MAX_RECV_MESSAGE_LENGTH (4 * 1024 * 1024)
typedef struct message_size_limits {
int max_send_size;
int max_recv_size;
} message_size_limits;
static void* message_size_limits_copy(void* value) {
void* new_value = gpr_malloc(sizeof(message_size_limits));
memcpy(new_value, value, sizeof(message_size_limits));
return new_value;
}
static int message_size_limits_cmp(void* value1, void* value2) {
const message_size_limits* v1 = value1;
const message_size_limits* v2 = value2;
if (v1->max_send_size > v2->max_send_size) return 1;
if (v1->max_send_size < v2->max_send_size) return -1;
if (v1->max_recv_size > v2->max_recv_size) return 1;
if (v1->max_recv_size < v2->max_recv_size) return -1;
return 0;
}
static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = {
gpr_free, message_size_limits_copy, message_size_limits_cmp};
static void* method_config_convert_value(
const grpc_method_config* method_config) {
message_size_limits* value = gpr_malloc(sizeof(message_size_limits));
const int32_t* max_request_message_bytes =
grpc_method_config_get_max_request_message_bytes(method_config);
value->max_send_size =
max_request_message_bytes != NULL ? *max_request_message_bytes : -1;
const int32_t* max_response_message_bytes =
grpc_method_config_get_max_response_message_bytes(method_config);
value->max_recv_size =
max_response_message_bytes != NULL ? *max_response_message_bytes : -1;
return value;
}
typedef struct call_data {
int max_send_size;
int max_recv_size;
@ -61,8 +99,8 @@ typedef struct call_data {
typedef struct channel_data {
int max_send_size;
int max_recv_size;
// Method config table.
grpc_method_config_table* method_config_table;
// Maps path names to message_size_limits structs.
grpc_mdstr_hash_table* method_limit_table;
} channel_data;
// Callback invoked when we receive a message. Here we check the max
@ -132,24 +170,19 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
// size to the receive limit.
calld->max_send_size = chand->max_send_size;
calld->max_recv_size = chand->max_recv_size;
if (chand->method_config_table != NULL) {
grpc_method_config* method_config =
grpc_method_config_table_get_method_config(chand->method_config_table,
args->path);
if (method_config != NULL) {
const int32_t* max_request_message_bytes =
grpc_method_config_get_max_request_message_bytes(method_config);
if (max_request_message_bytes != NULL &&
(*max_request_message_bytes < calld->max_send_size ||
if (chand->method_limit_table != NULL) {
message_size_limits* limits =
grpc_method_config_table_get(chand->method_limit_table, args->path);
if (limits != NULL) {
if (limits->max_send_size >= 0 &&
(limits->max_send_size < calld->max_send_size ||
calld->max_send_size < 0)) {
calld->max_send_size = *max_request_message_bytes;
calld->max_send_size = limits->max_send_size;
}
const int32_t* max_response_message_bytes =
grpc_method_config_get_max_response_message_bytes(method_config);
if (max_response_message_bytes != NULL &&
(*max_response_message_bytes < calld->max_recv_size ||
if (limits->max_recv_size >= 0 &&
(limits->max_recv_size < calld->max_recv_size ||
calld->max_recv_size < 0)) {
calld->max_recv_size = *max_response_message_bytes;
calld->max_recv_size = limits->max_recv_size;
}
}
}
@ -191,8 +224,9 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
chand->method_config_table = grpc_method_config_table_ref(
(grpc_method_config_table*)channel_arg->value.pointer.p);
chand->method_limit_table = grpc_method_config_table_convert(
(grpc_method_config_table*)channel_arg->value.pointer.p,
method_config_convert_value, &message_size_limits_vtable);
}
}
@ -200,7 +234,7 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element* elem) {
channel_data* chand = elem->channel_data;
grpc_method_config_table_unref(chand->method_config_table);
grpc_mdstr_hash_table_unref(chand->method_limit_table);
}
const grpc_channel_filter grpc_message_size_filter = {

@ -65,12 +65,12 @@
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/socket_utils_posix.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/support/string.h"
#define INIT_PORT_CAP 2
/* one listening port */
typedef struct {
typedef struct grpc_udp_listener grpc_udp_listener;
struct grpc_udp_listener {
int fd;
grpc_fd *emfd;
grpc_udp_server *server;
@ -79,12 +79,13 @@ typedef struct {
grpc_closure destroyed_closure;
grpc_udp_server_read_cb read_cb;
grpc_udp_server_orphan_cb orphan_cb;
} server_port;
struct grpc_udp_listener *next;
};
/* the overall server */
struct grpc_udp_server {
gpr_mu mu;
gpr_cv cv;
/* active port count: how many ports are actually still listening */
size_t active_ports;
@ -94,10 +95,10 @@ struct grpc_udp_server {
/* is this server shutting down? (boolean) */
int shutdown;
/* all listening ports */
server_port *ports;
size_t nports;
size_t port_capacity;
/* linked list of server ports */
grpc_udp_listener *head;
grpc_udp_listener *tail;
unsigned nports;
/* shutdown callback */
grpc_closure *shutdown_complete;
@ -113,24 +114,29 @@ struct grpc_udp_server {
grpc_udp_server *grpc_udp_server_create(void) {
grpc_udp_server *s = gpr_malloc(sizeof(grpc_udp_server));
gpr_mu_init(&s->mu);
gpr_cv_init(&s->cv);
s->active_ports = 0;
s->destroyed_ports = 0;
s->shutdown = 0;
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
s->head = NULL;
s->tail = NULL;
s->nports = 0;
s->port_capacity = INIT_PORT_CAP;
return s;
}
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
if (s->shutdown_complete != NULL) {
grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
}
gpr_mu_destroy(&s->mu);
gpr_cv_destroy(&s->cv);
gpr_free(s->ports);
while (s->head) {
grpc_udp_listener *sp = s->head;
s->head = sp->next;
gpr_free(sp);
}
gpr_free(s);
}
@ -151,8 +157,6 @@ static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
events will be received on them - at this point it's safe to destroy
things */
static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
size_t i;
/* delete ALL the things */
gpr_mu_lock(&s->mu);
@ -161,9 +165,11 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
return;
}
if (s->nports) {
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
if (s->head) {
grpc_udp_listener *sp;
for (sp = s->head; sp; sp = sp->next) {
grpc_unlink_if_unix_domain_socket(&sp->addr.sockaddr);
sp->destroyed_closure.cb = destroyed_port;
sp->destroyed_closure.cb_arg = s;
@ -184,7 +190,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
grpc_closure *on_done) {
size_t i;
grpc_udp_listener *sp;
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->shutdown);
@ -194,14 +200,10 @@ void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
/* shutdown all fd's */
if (s->active_ports) {
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
/* Call the orphan_cb to signal that the FD is about to be closed and
* should no longer be used. */
for (sp = s->head; sp; sp = sp->next) {
GPR_ASSERT(sp->orphan_cb);
sp->orphan_cb(sp->emfd);
grpc_fd_shutdown(exec_ctx, s->ports[i].emfd);
grpc_fd_shutdown(exec_ctx, sp->emfd);
}
gpr_mu_unlock(&s->mu);
} else {
@ -279,10 +281,10 @@ error:
/* event manager callback when reads are ready */
static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
server_port *sp = arg;
grpc_udp_listener *sp = arg;
gpr_mu_lock(&sp->server->mu);
if (error != GRPC_ERROR_NONE) {
gpr_mu_lock(&sp->server->mu);
if (0 == --sp->server->active_ports) {
gpr_mu_unlock(&sp->server->mu);
deactivated_all_ports(exec_ctx, sp->server);
@ -298,13 +300,14 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
/* Re-arm the notification event so we get another chance to read. */
grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
gpr_mu_unlock(&sp->server->mu);
}
static int add_socket_to_server(grpc_udp_server *s, int fd,
const grpc_resolved_address *addr,
grpc_udp_server_read_cb read_cb,
grpc_udp_server_orphan_cb orphan_cb) {
server_port *sp;
grpc_udp_listener *sp;
int port;
char *addr_str;
char *name;
@ -315,12 +318,15 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
gpr_free(addr_str);
gpr_mu_lock(&s->mu);
/* append it to the list under a lock */
if (s->nports == s->port_capacity) {
s->port_capacity *= 2;
s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
s->nports++;
sp = gpr_malloc(sizeof(grpc_udp_listener));
sp->next = NULL;
if (s->head == NULL) {
s->head = sp;
} else {
s->tail->next = sp;
}
sp = &s->ports[s->nports++];
s->tail = sp;
sp->server = s;
sp->fd = fd;
sp->emfd = grpc_fd_create(fd, name);
@ -339,9 +345,9 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
const grpc_resolved_address *addr,
grpc_udp_server_read_cb read_cb,
grpc_udp_server_orphan_cb orphan_cb) {
grpc_udp_listener *sp;
int allocated_port1 = -1;
int allocated_port2 = -1;
unsigned i;
int fd;
grpc_dualstack_mode dsmode;
grpc_resolved_address addr6_v4mapped;
@ -355,9 +361,9 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
/* Check if this is a wildcard port, and if so, try to keep the port the same
as some previously created listener. */
if (grpc_sockaddr_get_port(addr) == 0) {
for (i = 0; i < s->nports; i++) {
for (sp = s->head; sp; sp = sp->next) {
sockname_temp.len = sizeof(struct sockaddr_storage);
if (0 == getsockname(s->ports[i].fd,
if (0 == getsockname(sp->fd,
(struct sockaddr *)sockname_temp.addr,
(socklen_t *)&sockname_temp.len)) {
port = grpc_sockaddr_get_port(&sockname_temp);
@ -413,27 +419,40 @@ done:
}
int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index) {
return (port_index < s->nports) ? s->ports[port_index].fd : -1;
grpc_udp_listener *sp;
if (port_index >= s->nports) {
return -1;
}
for (sp = s->head; sp && port_index != 0; sp = sp->next) {
--port_index;
}
return sp->fd;
}
void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
grpc_pollset **pollsets, size_t pollset_count,
grpc_server *server) {
size_t i, j;
size_t i;
gpr_mu_lock(&s->mu);
grpc_udp_listener *sp;
GPR_ASSERT(s->active_ports == 0);
s->pollsets = pollsets;
s->grpc_server = server;
for (i = 0; i < s->nports; i++) {
for (j = 0; j < pollset_count; j++) {
grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd);
sp = s->head;
while (sp != NULL) {
for (i = 0; i < pollset_count; i++) {
grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
}
s->ports[i].read_closure.cb = on_read;
s->ports[i].read_closure.cb_arg = &s->ports[i];
grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd,
&s->ports[i].read_closure);
sp->read_closure.cb = on_read;
sp->read_closure.cb_arg = sp;
grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
s->active_ports++;
sp = sp->next;
}
gpr_mu_unlock(&s->mu);
}

@ -60,7 +60,7 @@ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server,
grpc_pollset **pollsets, size_t pollset_count,
struct grpc_server *server);
int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index);
int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index);
/* Add a port to the server, returning port number on success, or negative
on failure.

@ -42,6 +42,7 @@
struct grpc_mdstr_hash_table {
gpr_refcount refs;
size_t num_entries;
size_t size;
grpc_mdstr_hash_table_entry* entries;
};
@ -50,13 +51,12 @@ struct grpc_mdstr_hash_table {
static size_t grpc_mdstr_hash_table_find_index(
const grpc_mdstr_hash_table* table, const grpc_mdstr* key,
bool find_empty) {
for (size_t i = 0; i < table->num_entries; ++i) {
const size_t idx = (key->hash + i * i) % table->num_entries;
if (table->entries[idx].key == NULL)
return find_empty ? idx : table->num_entries;
for (size_t i = 0; i < table->size; ++i) {
const size_t idx = (key->hash + i * i) % table->size;
if (table->entries[idx].key == NULL) return find_empty ? idx : table->size;
if (table->entries[idx].key == key) return idx;
}
return table->num_entries; // Not found.
return table->size; // Not found.
}
static void grpc_mdstr_hash_table_add(
@ -65,7 +65,7 @@ static void grpc_mdstr_hash_table_add(
GPR_ASSERT(value != NULL);
const size_t idx =
grpc_mdstr_hash_table_find_index(table, key, true /* find_empty */);
GPR_ASSERT(idx != table->num_entries); // Table should never be full.
GPR_ASSERT(idx != table->size); // Table should never be full.
grpc_mdstr_hash_table_entry* entry = &table->entries[idx];
entry->key = GRPC_MDSTR_REF(key);
entry->value = vtable->copy_value(value);
@ -77,11 +77,11 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table));
memset(table, 0, sizeof(*table));
gpr_ref_init(&table->refs, 1);
table->num_entries = num_entries;
// Quadratic probing gets best performance when the table is no more
// than half full.
table->num_entries = num_entries * 2;
const size_t entry_size =
sizeof(grpc_mdstr_hash_table_entry) * table->num_entries;
table->size = num_entries * 2;
const size_t entry_size = sizeof(grpc_mdstr_hash_table_entry) * table->size;
table->entries = gpr_malloc(entry_size);
memset(table->entries, 0, entry_size);
for (size_t i = 0; i < num_entries; ++i) {
@ -98,7 +98,7 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) {
int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) {
if (table != NULL && gpr_unref(&table->refs)) {
for (size_t i = 0; i < table->num_entries; ++i) {
for (size_t i = 0; i < table->size; ++i) {
grpc_mdstr_hash_table_entry* entry = &table->entries[i];
if (entry->key != NULL) {
GRPC_MDSTR_UNREF(entry->key);
@ -112,11 +112,15 @@ int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) {
return 0;
}
size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table) {
return table->num_entries;
}
void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* key) {
const size_t idx =
grpc_mdstr_hash_table_find_index(table, key, false /* find_empty */);
if (idx == table->num_entries) return NULL; // Not found.
if (idx == table->size) return NULL; // Not found.
return table->entries[idx].value;
}
@ -140,3 +144,14 @@ int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
}
return 0;
}
void grpc_mdstr_hash_table_iterate(
const grpc_mdstr_hash_table* table,
void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
void* user_data) {
for (size_t i = 0; i < table->size; ++i) {
if (table->entries[i].key != NULL) {
func(&table->entries[i], user_data);
}
}
}

@ -70,6 +70,9 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table);
/** Returns 1 when \a table is destroyed. */
int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table);
/** Returns the number of entries in \a table. */
size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table);
/** Returns the value from \a table associated with \a key.
Returns NULL if \a key is not found. */
void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
@ -80,4 +83,10 @@ void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
const grpc_mdstr_hash_table* table2);
/** Iterates over the entries in \a table, calling \a func for each entry. */
void grpc_mdstr_hash_table_iterate(
const grpc_mdstr_hash_table* table,
void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
void* user_data);
#endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */

@ -0,0 +1,69 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc++/security/credentials.h>
#include <grpc++/channel.h>
#include <grpc++/support/channel_arguments.h>
#include <grpc/grpc_cronet.h>
#include "src/cpp/client/create_channel_internal.h"
namespace grpc {
class CronetChannelCredentialsImpl GRPC_FINAL : public ChannelCredentials {
public:
CronetChannelCredentialsImpl(void* engine) : engine_(engine) {}
std::shared_ptr<grpc::Channel> CreateChannel(
const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
return CreateChannelInternal(
"", grpc_cronet_secure_channel_create(engine_, target.c_str(),
&channel_args, nullptr));
}
SecureChannelCredentials* AsSecureCredentials() GRPC_OVERRIDE {
return nullptr;
}
private:
void* engine_;
};
std::shared_ptr<ChannelCredentials> CronetChannelCredentials(void* engine) {
return std::shared_ptr<ChannelCredentials>(
new CronetChannelCredentialsImpl(engine));
}
} // namespace grpc

@ -33,6 +33,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Grpc.Core;
@ -72,9 +73,10 @@ namespace Grpc.Auth
public static AsyncAuthInterceptor FromAccessToken(string accessToken)
{
GrpcPreconditions.CheckNotNull(accessToken);
return new AsyncAuthInterceptor(async (context, metadata) =>
return new AsyncAuthInterceptor((context, metadata) =>
{
metadata.Add(CreateBearerTokenHeader(accessToken));
return Task.FromResult<object>(null);
});
}

@ -102,6 +102,7 @@ namespace Grpc.Core
return Calls.AsyncDuplexStreamingCall(call);
}
/// <summary>Creates call invocation details for given method.</summary>
protected virtual CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
where TRequest : class
where TResponse : class

@ -138,6 +138,7 @@
<Compile Include="Internal\CallError.cs" />
<Compile Include="Logging\LogLevel.cs" />
<Compile Include="Logging\LogLevelFilterLogger.cs" />
<Compile Include="Internal\RequestCallContextSafeHandle.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Core.nuspec" />

@ -59,7 +59,6 @@ namespace Grpc.Core
static ILogger logger = new NullLogger();
readonly object myLock = new object();
readonly GrpcThreadPool threadPool;
readonly DebugStats debugStats = new DebugStats();
readonly AtomicCounter cqPickerCounter = new AtomicCounter();

@ -93,21 +93,6 @@ namespace Grpc.Core.Internal
return data;
}
// Gets data of server_rpc_new completion.
public ServerRpcNew GetServerRpcNew(Server server)
{
var call = Native.grpcsharp_batch_context_server_rpc_new_call(this);
var method = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_server_rpc_new_method(this));
var host = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_server_rpc_new_host(this));
var deadline = Native.grpcsharp_batch_context_server_rpc_new_deadline(this);
IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_server_rpc_new_request_metadata(this);
var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr);
return new ServerRpcNew(server, call, method, host, deadline, metadata);
}
// Gets data of receive_close_on_server completion.
public bool GetReceivedCloseOnServerCancelled()
{

@ -44,6 +44,8 @@ namespace Grpc.Core.Internal
internal delegate void BatchCompletionDelegate(bool success, BatchContextSafeHandle ctx);
internal delegate void RequestCallCompletionDelegate(bool success, RequestCallContextSafeHandle ctx);
internal class CompletionRegistry
{
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<CompletionRegistry>();
@ -68,6 +70,12 @@ namespace Grpc.Core.Internal
Register(ctx.Handle, opCallback);
}
public void RegisterRequestCallCompletion(RequestCallContextSafeHandle ctx, RequestCallCompletionDelegate callback)
{
OpCompletionDelegate opCallback = ((success) => HandleRequestCallCompletion(success, ctx, callback));
Register(ctx.Handle, opCallback);
}
public OpCompletionDelegate Extract(IntPtr key)
{
OpCompletionDelegate value;
@ -84,7 +92,26 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
Logger.Error(e, "Exception occured while invoking completion delegate.");
Logger.Error(e, "Exception occured while invoking batch completion delegate.");
}
finally
{
if (ctx != null)
{
ctx.Dispose();
}
}
}
private static void HandleRequestCallCompletion(bool success, RequestCallContextSafeHandle ctx, RequestCallCompletionDelegate callback)
{
try
{
callback(success, ctx);
}
catch (Exception e)
{
Logger.Error(e, "Exception occured while invoking request call completion delegate.");
}
finally
{

@ -48,7 +48,7 @@ namespace Grpc.Core.Internal
readonly Func<CallOptions, CallOptions> callOptionsInterceptor;
/// <summary>
/// Initializes a new instance of the <see cref="Grpc.Core.InterceptingCallInvoker"/> class.
/// Initializes a new instance of the <see cref="Grpc.Core.Internal.InterceptingCallInvoker"/> class.
/// </summary>
public InterceptingCallInvoker(CallInvoker callInvoker,
Func<string, string> hostInterceptor = null,

@ -78,7 +78,10 @@ namespace Grpc.Core.Internal
{
var context = new AuthInterceptorContext(Marshal.PtrToStringAnsi(serviceUrlPtr),
Marshal.PtrToStringAnsi(methodNamePtr));
StartGetMetadata(context, callbackPtr, userDataPtr);
// Don't await, we are in a native callback and need to return.
#pragma warning disable 4014
GetMetadataAsync(context, callbackPtr, userDataPtr);
#pragma warning restore 4014
}
catch (Exception e)
{
@ -87,7 +90,7 @@ namespace Grpc.Core.Internal
}
}
private async Task StartGetMetadata(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr)
private async Task GetMetadataAsync(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr)
{
try
{

@ -64,14 +64,17 @@ namespace Grpc.Core.Internal
public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate grpcsharp_batch_context_recv_status_on_client_status;
public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate grpcsharp_batch_context_recv_status_on_client_details;
public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate grpcsharp_batch_context_recv_status_on_client_trailing_metadata;
public readonly Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate grpcsharp_batch_context_server_rpc_new_call;
public readonly Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate grpcsharp_batch_context_server_rpc_new_method;
public readonly Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate grpcsharp_batch_context_server_rpc_new_host;
public readonly Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate grpcsharp_batch_context_server_rpc_new_deadline;
public readonly Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate grpcsharp_batch_context_server_rpc_new_request_metadata;
public readonly Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate grpcsharp_batch_context_recv_close_on_server_cancelled;
public readonly Delegates.grpcsharp_batch_context_destroy_delegate grpcsharp_batch_context_destroy;
public readonly Delegates.grpcsharp_request_call_context_create_delegate grpcsharp_request_call_context_create;
public readonly Delegates.grpcsharp_request_call_context_call_delegate grpcsharp_request_call_context_call;
public readonly Delegates.grpcsharp_request_call_context_method_delegate grpcsharp_request_call_context_method;
public readonly Delegates.grpcsharp_request_call_context_host_delegate grpcsharp_request_call_context_host;
public readonly Delegates.grpcsharp_request_call_context_deadline_delegate grpcsharp_request_call_context_deadline;
public readonly Delegates.grpcsharp_request_call_context_request_metadata_delegate grpcsharp_request_call_context_request_metadata;
public readonly Delegates.grpcsharp_request_call_context_destroy_delegate grpcsharp_request_call_context_destroy;
public readonly Delegates.grpcsharp_composite_call_credentials_create_delegate grpcsharp_composite_call_credentials_create;
public readonly Delegates.grpcsharp_call_credentials_release_delegate grpcsharp_call_credentials_release;
@ -170,14 +173,17 @@ namespace Grpc.Core.Internal
this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library);
this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library);
this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library);
this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library);
this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library);
this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library);
this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library);
this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library);
this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library);
this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library);
this.grpcsharp_request_call_context_create = GetMethodDelegate<Delegates.grpcsharp_request_call_context_create_delegate>(library);
this.grpcsharp_request_call_context_call = GetMethodDelegate<Delegates.grpcsharp_request_call_context_call_delegate>(library);
this.grpcsharp_request_call_context_method = GetMethodDelegate<Delegates.grpcsharp_request_call_context_method_delegate>(library);
this.grpcsharp_request_call_context_host = GetMethodDelegate<Delegates.grpcsharp_request_call_context_host_delegate>(library);
this.grpcsharp_request_call_context_deadline = GetMethodDelegate<Delegates.grpcsharp_request_call_context_deadline_delegate>(library);
this.grpcsharp_request_call_context_request_metadata = GetMethodDelegate<Delegates.grpcsharp_request_call_context_request_metadata_delegate>(library);
this.grpcsharp_request_call_context_destroy = GetMethodDelegate<Delegates.grpcsharp_request_call_context_destroy_delegate>(library);
this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library);
this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library);
@ -302,14 +308,17 @@ namespace Grpc.Core.Internal
public delegate StatusCode grpcsharp_batch_context_recv_status_on_client_status_delegate(BatchContextSafeHandle ctx);
public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_details_delegate(BatchContextSafeHandle ctx); // returns const char*
public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate(BatchContextSafeHandle ctx);
public delegate CallSafeHandle grpcsharp_batch_context_server_rpc_new_call_delegate(BatchContextSafeHandle ctx);
public delegate IntPtr grpcsharp_batch_context_server_rpc_new_method_delegate(BatchContextSafeHandle ctx); // returns const char*
public delegate IntPtr grpcsharp_batch_context_server_rpc_new_host_delegate(BatchContextSafeHandle ctx); // returns const char*
public delegate Timespec grpcsharp_batch_context_server_rpc_new_deadline_delegate(BatchContextSafeHandle ctx);
public delegate IntPtr grpcsharp_batch_context_server_rpc_new_request_metadata_delegate(BatchContextSafeHandle ctx);
public delegate int grpcsharp_batch_context_recv_close_on_server_cancelled_delegate(BatchContextSafeHandle ctx);
public delegate void grpcsharp_batch_context_destroy_delegate(IntPtr ctx);
public delegate RequestCallContextSafeHandle grpcsharp_request_call_context_create_delegate();
public delegate CallSafeHandle grpcsharp_request_call_context_call_delegate(RequestCallContextSafeHandle ctx);
public delegate IntPtr grpcsharp_request_call_context_method_delegate(RequestCallContextSafeHandle ctx); // returns const char*
public delegate IntPtr grpcsharp_request_call_context_host_delegate(RequestCallContextSafeHandle ctx); // returns const char*
public delegate Timespec grpcsharp_request_call_context_deadline_delegate(RequestCallContextSafeHandle ctx);
public delegate IntPtr grpcsharp_request_call_context_request_metadata_delegate(RequestCallContextSafeHandle ctx);
public delegate void grpcsharp_request_call_context_destroy_delegate(IntPtr ctx);
public delegate CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create_delegate(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2);
public delegate void grpcsharp_call_credentials_release_delegate(IntPtr credentials);
@ -393,7 +402,7 @@ namespace Grpc.Core.Internal
public delegate int grpcsharp_server_add_insecure_http2_port_delegate(ServerSafeHandle server, string addr);
public delegate int grpcsharp_server_add_secure_http2_port_delegate(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds);
public delegate void grpcsharp_server_start_delegate(ServerSafeHandle server);
public delegate CallError grpcsharp_server_request_call_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
public delegate CallError grpcsharp_server_request_call_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx);
public delegate void grpcsharp_server_cancel_all_calls_delegate(ServerSafeHandle server);
public delegate void grpcsharp_server_shutdown_and_notify_callback_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
public delegate void grpcsharp_server_destroy_delegate(IntPtr server);

@ -0,0 +1,85 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Runtime.InteropServices;
using Grpc.Core;
namespace Grpc.Core.Internal
{
/// <summary>
/// grpcsharp_request_call_context
/// </summary>
internal class RequestCallContextSafeHandle : SafeHandleZeroIsInvalid
{
static readonly NativeMethods Native = NativeMethods.Get();
private RequestCallContextSafeHandle()
{
}
public static RequestCallContextSafeHandle Create()
{
return Native.grpcsharp_request_call_context_create();
}
public IntPtr Handle
{
get
{
return handle;
}
}
// Gets data of server_rpc_new completion.
public ServerRpcNew GetServerRpcNew(Server server)
{
var call = Native.grpcsharp_request_call_context_call(this);
var method = Marshal.PtrToStringAnsi(Native.grpcsharp_request_call_context_method(this));
var host = Marshal.PtrToStringAnsi(Native.grpcsharp_request_call_context_host(this));
var deadline = Native.grpcsharp_request_call_context_deadline(this);
IntPtr metadataArrayPtr = Native.grpcsharp_request_call_context_request_metadata(this);
var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr);
return new ServerRpcNew(server, call, method, host, deadline, metadata);
}
protected override bool ReleaseHandle()
{
Native.grpcsharp_request_call_context_destroy(handle);
return true;
}
}
}

@ -85,12 +85,12 @@ namespace Grpc.Core.Internal
}
}
public void RequestCall(BatchCompletionDelegate callback, CompletionQueueSafeHandle completionQueue)
public void RequestCall(RequestCallCompletionDelegate callback, CompletionQueueSafeHandle completionQueue)
{
using (completionQueue.NewScope())
{
var ctx = BatchContextSafeHandle.Create();
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, callback);
var ctx = RequestCallContextSafeHandle.Create();
completionQueue.CompletionRegistry.RegisterRequestCallCompletion(ctx, callback);
Native.grpcsharp_server_request_call(this, completionQueue, ctx).CheckOk();
}
}

@ -134,7 +134,11 @@ namespace Grpc.Core.Internal
{
throw new MissingMethodException(string.Format("The native method \"{0}\" does not exist", methodName));
}
return Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
#if NETSTANDARD1_5
return Marshal.GetDelegateForFunctionPointer<T>(ptr); // non-generic version is obsolete
#else
return Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T; // generic version not available in .NET45
#endif
}
/// <summary>

@ -95,11 +95,18 @@ namespace Grpc.Core
#region IList members
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public int IndexOf(Metadata.Entry item)
{
return entries.IndexOf(item);
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public void Insert(int index, Metadata.Entry item)
{
GrpcPreconditions.CheckNotNull(item);
@ -107,12 +114,18 @@ namespace Grpc.Core
entries.Insert(index, item);
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public void RemoveAt(int index)
{
CheckWriteable();
entries.RemoveAt(index);
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public Metadata.Entry this[int index]
{
get
@ -128,6 +141,9 @@ namespace Grpc.Core
}
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public void Add(Metadata.Entry item)
{
GrpcPreconditions.CheckNotNull(item);
@ -135,48 +151,75 @@ namespace Grpc.Core
entries.Add(item);
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public void Add(string key, string value)
{
Add(new Entry(key, value));
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public void Add(string key, byte[] valueBytes)
{
Add(new Entry(key, valueBytes));
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public void Clear()
{
CheckWriteable();
entries.Clear();
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public bool Contains(Metadata.Entry item)
{
return entries.Contains(item);
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public void CopyTo(Metadata.Entry[] array, int arrayIndex)
{
entries.CopyTo(array, arrayIndex);
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public int Count
{
get { return entries.Count; }
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public bool IsReadOnly
{
get { return readOnly; }
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public bool Remove(Metadata.Entry item)
{
CheckWriteable();
return entries.Remove(item);
}
/// <summary>
/// <see cref="T:IList`1"/>
/// </summary>
public IEnumerator<Metadata.Entry> GetEnumerator()
{
return entries.GetEnumerator();
@ -221,7 +264,7 @@ namespace Grpc.Core
public Entry(string key, byte[] valueBytes)
{
this.key = NormalizeKey(key);
GrpcPreconditions.CheckArgument(this.key.EndsWith(BinaryHeaderSuffix),
GrpcPreconditions.CheckArgument(HasBinaryHeaderSuffix(this.key),
"Key for binary valued metadata entry needs to have suffix indicating binary value.");
this.value = null;
GrpcPreconditions.CheckNotNull(valueBytes, "valueBytes");
@ -237,7 +280,7 @@ namespace Grpc.Core
public Entry(string key, string value)
{
this.key = NormalizeKey(key);
GrpcPreconditions.CheckArgument(!this.key.EndsWith(BinaryHeaderSuffix),
GrpcPreconditions.CheckArgument(!HasBinaryHeaderSuffix(this.key),
"Key for ASCII valued metadata entry cannot have suffix indicating binary value.");
this.value = GrpcPreconditions.CheckNotNull(value, "value");
this.valueBytes = null;
@ -324,7 +367,7 @@ namespace Grpc.Core
/// </summary>
internal static Entry CreateUnsafe(string key, byte[] valueBytes)
{
if (key.EndsWith(BinaryHeaderSuffix))
if (HasBinaryHeaderSuffix(key))
{
return new Entry(key, null, valueBytes);
}
@ -338,6 +381,27 @@ namespace Grpc.Core
"Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores and hyphens.");
return normalized;
}
/// <summary>
/// Returns <c>true</c> if the key has "-bin" binary header suffix.
/// </summary>
private static bool HasBinaryHeaderSuffix(string key)
{
// We don't use just string.EndsWith because its implementation is extremely slow
// on CoreCLR and we've seen significant differences in gRPC benchmarks caused by it.
// See https://github.com/dotnet/coreclr/issues/5612
int len = key.Length;
if (len >= 4 &&
key[len - 4] == '-' &&
key[len - 3] == 'b' &&
key[len - 2] == 'i' &&
key[len - 1] == 'n')
{
return true;
}
return false;
}
}
}
}

@ -47,7 +47,7 @@ namespace Grpc.Core
/// </summary>
public class Server
{
const int InitialAllowRpcTokenCountPerCq = 10;
const int DefaultRequestCallTokensPerCq = 2000;
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<Server>();
readonly AtomicCounter activeCallCounter = new AtomicCounter();
@ -66,7 +66,7 @@ namespace Grpc.Core
bool startRequested;
volatile bool shutdownRequested;
int requestCallTokensPerCq = DefaultRequestCallTokensPerCq;
/// <summary>
/// Creates a new server.
@ -132,6 +132,27 @@ namespace Grpc.Core
}
}
/// <summary>
/// Experimental API. Might anytime change without prior notice.
/// Number or calls requested via grpc_server_request_call at any given time for each completion queue.
/// </summary>
public int RequestCallTokensPerCompletionQueue
{
get
{
return requestCallTokensPerCq;
}
set
{
lock (myLock)
{
GrpcPreconditions.CheckState(!startRequested);
GrpcPreconditions.CheckArgument(value > 0);
requestCallTokensPerCq = value;
}
}
}
/// <summary>
/// Starts the server.
/// </summary>
@ -145,9 +166,7 @@ namespace Grpc.Core
handle.Start();
// Starting with more than one AllowOneRpc tokens can significantly increase
// unary RPC throughput.
for (int i = 0; i < InitialAllowRpcTokenCountPerCq; i++)
for (int i = 0; i < requestCallTokensPerCq; i++)
{
foreach (var cq in environment.CompletionQueues)
{
@ -310,7 +329,7 @@ namespace Grpc.Core
/// <summary>
/// Selects corresponding handler for given call and handles the call.
/// </summary>
private async Task HandleCallAsync(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
private async Task HandleCallAsync(ServerRpcNew newRpc, CompletionQueueSafeHandle cq, Action continuation)
{
try
{
@ -325,25 +344,40 @@ namespace Grpc.Core
{
Logger.Warning(e, "Exception while handling RPC.");
}
finally
{
continuation();
}
}
/// <summary>
/// Handles the native callback.
/// </summary>
private void HandleNewServerRpc(bool success, BatchContextSafeHandle ctx, CompletionQueueSafeHandle cq)
private void HandleNewServerRpc(bool success, RequestCallContextSafeHandle ctx, CompletionQueueSafeHandle cq)
{
Task.Run(() => AllowOneRpc(cq));
bool nextRpcRequested = false;
if (success)
{
ServerRpcNew newRpc = ctx.GetServerRpcNew(this);
var newRpc = ctx.GetServerRpcNew(this);
// after server shutdown, the callback returns with null call
if (!newRpc.Call.IsInvalid)
{
HandleCallAsync(newRpc, cq); // we don't need to await.
nextRpcRequested = true;
// Start asynchronous handler for the call.
// Don't await, the continuations will run on gRPC thread pool once triggered
// by cq.Next().
#pragma warning disable 4014
HandleCallAsync(newRpc, cq, () => AllowOneRpc(cq));
#pragma warning restore 4014
}
}
if (!nextRpcRequested)
{
AllowOneRpc(cq);
}
}
/// <summary>

@ -195,8 +195,11 @@ namespace Grpc.IntegrationTesting
case "status_code_and_message":
await RunStatusCodeAndMessageAsync(client);
break;
case "unimplemented_service":
RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel));
break;
case "unimplemented_method":
RunUnimplementedMethod(new UnimplementedService.UnimplementedServiceClient(channel));
RunUnimplementedMethod(client);
break;
case "client_compressed_unary":
RunClientCompressedUnary(client);
@ -577,7 +580,16 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunUnimplementedMethod(UnimplementedService.UnimplementedServiceClient client)
public static void RunUnimplementedService(UnimplementedService.UnimplementedServiceClient client)
{
Console.WriteLine("running unimplemented_service");
var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));
Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
Console.WriteLine("Passed!");
}
public static void RunUnimplementedMethod(TestService.TestServiceClient client)
{
Console.WriteLine("running unimplemented_method");
var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));

@ -145,10 +145,16 @@ namespace Grpc.IntegrationTesting
await InteropClient.RunStatusCodeAndMessageAsync(client);
}
[Test]
public void UnimplementedService()
{
InteropClient.RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel));
}
[Test]
public void UnimplementedMethod()
{
InteropClient.RunUnimplementedMethod(new UnimplementedService.UnimplementedServiceClient(channel));
InteropClient.RunUnimplementedMethod(client);
}
}
}

@ -76,6 +76,11 @@ namespace Grpc.IntegrationTesting
private async Task RunAsync()
{
// (ThreadPoolSize == ProcessorCount) gives best throughput in benchmarks
// and doesn't seem to harm performance even when server and client
// are running on the same machine.
GrpcEnvironment.SetThreadPoolSize(Environment.ProcessorCount);
string host = "0.0.0.0";
int port = options.DriverPort;

@ -24,25 +24,28 @@ namespace Grpc.Testing {
string.Concat(
"CiFzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3Rlc3QucHJvdG8SDGdycGMudGVz",
"dGluZxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9lbXB0eS5wcm90bxolc3Jj",
"L3Byb3RvL2dycGMvdGVzdGluZy9tZXNzYWdlcy5wcm90bzK7BAoLVGVzdFNl",
"L3Byb3RvL2dycGMvdGVzdGluZy9tZXNzYWdlcy5wcm90bzLLBQoLVGVzdFNl",
"cnZpY2USNQoJRW1wdHlDYWxsEhMuZ3JwYy50ZXN0aW5nLkVtcHR5GhMuZ3Jw",
"Yy50ZXN0aW5nLkVtcHR5EkYKCVVuYXJ5Q2FsbBIbLmdycGMudGVzdGluZy5T",
"aW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlEmwK",
"E1N0cmVhbWluZ091dHB1dENhbGwSKC5ncnBjLnRlc3RpbmcuU3RyZWFtaW5n",
"T3V0cHV0Q2FsbFJlcXVlc3QaKS5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0",
"cHV0Q2FsbFJlc3BvbnNlMAESaQoSU3RyZWFtaW5nSW5wdXRDYWxsEicuZ3Jw",
"Yy50ZXN0aW5nLlN0cmVhbWluZ0lucHV0Q2FsbFJlcXVlc3QaKC5ncnBjLnRl",
"c3RpbmcuU3RyZWFtaW5nSW5wdXRDYWxsUmVzcG9uc2UoARJpCg5GdWxsRHVw",
"bGV4Q2FsbBIoLmdycGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVx",
"dWVzdBopLmdycGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVzcG9u",
"c2UoATABEmkKDkhhbGZEdXBsZXhDYWxsEiguZ3JwYy50ZXN0aW5nLlN0cmVh",
"bWluZ091dHB1dENhbGxSZXF1ZXN0GikuZ3JwYy50ZXN0aW5nLlN0cmVhbWlu",
"Z091dHB1dENhbGxSZXNwb25zZSgBMAEyVQoUVW5pbXBsZW1lbnRlZFNlcnZp",
"Y2USPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRlc3RpbmcuRW1wdHka",
"Ey5ncnBjLnRlc3RpbmcuRW1wdHkyiQEKEFJlY29ubmVjdFNlcnZpY2USOwoF",
"U3RhcnQSHS5ncnBjLnRlc3RpbmcuUmVjb25uZWN0UGFyYW1zGhMuZ3JwYy50",
"ZXN0aW5nLkVtcHR5EjgKBFN0b3ASEy5ncnBjLnRlc3RpbmcuRW1wdHkaGy5n",
"cnBjLnRlc3RpbmcuUmVjb25uZWN0SW5mb2IGcHJvdG8z"));
"aW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlEk8K",
"EkNhY2hlYWJsZVVuYXJ5Q2FsbBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1",
"ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlEmwKE1N0cmVhbWlu",
"Z091dHB1dENhbGwSKC5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2Fs",
"bFJlcXVlc3QaKS5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2FsbFJl",
"c3BvbnNlMAESaQoSU3RyZWFtaW5nSW5wdXRDYWxsEicuZ3JwYy50ZXN0aW5n",
"LlN0cmVhbWluZ0lucHV0Q2FsbFJlcXVlc3QaKC5ncnBjLnRlc3RpbmcuU3Ry",
"ZWFtaW5nSW5wdXRDYWxsUmVzcG9uc2UoARJpCg5GdWxsRHVwbGV4Q2FsbBIo",
"LmdycGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVxdWVzdBopLmdy",
"cGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVzcG9uc2UoATABEmkK",
"DkhhbGZEdXBsZXhDYWxsEiguZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1",
"dENhbGxSZXF1ZXN0GikuZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1dENh",
"bGxSZXNwb25zZSgBMAESPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRl",
"c3RpbmcuRW1wdHkaEy5ncnBjLnRlc3RpbmcuRW1wdHkyVQoUVW5pbXBsZW1l",
"bnRlZFNlcnZpY2USPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRlc3Rp",
"bmcuRW1wdHkaEy5ncnBjLnRlc3RpbmcuRW1wdHkyiQEKEFJlY29ubmVjdFNl",
"cnZpY2USOwoFU3RhcnQSHS5ncnBjLnRlc3RpbmcuUmVjb25uZWN0UGFyYW1z",
"GhMuZ3JwYy50ZXN0aW5nLkVtcHR5EjgKBFN0b3ASEy5ncnBjLnRlc3Rpbmcu",
"RW1wdHkaGy5ncnBjLnRlc3RpbmcuUmVjb25uZWN0SW5mb2IGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.EmptyReflection.Descriptor, global::Grpc.Testing.MessagesReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(null, null));

@ -71,6 +71,13 @@ namespace Grpc.Testing {
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_CacheableUnaryCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
MethodType.Unary,
__ServiceName,
"CacheableUnaryCall",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse>(
MethodType.ServerStreaming,
__ServiceName,
@ -99,6 +106,13 @@ namespace Grpc.Testing {
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
static readonly Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty> __Method_UnimplementedCall = new Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty>(
MethodType.Unary,
__ServiceName,
"UnimplementedCall",
__Marshaller_Empty,
__Marshaller_Empty);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
@ -124,6 +138,16 @@ namespace Grpc.Testing {
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
/// <summary>
/// One request followed by one response. Response has cache control
/// headers set such that a caching HTTP proxy (such as GFE) can
/// satisfy subsequent requests.
/// </summary>
public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
/// <summary>
/// One request followed by a sequence of responses (streamed download).
/// The server returns the payload with client desired type and sizes.
@ -163,6 +187,15 @@ namespace Grpc.Testing {
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
/// <summary>
/// The test server will not implement this method. It will be used
/// to test the behavior when clients call unimplemented methods.
/// </summary>
public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for TestService</summary>
@ -245,6 +278,42 @@ namespace Grpc.Testing {
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
/// <summary>
/// One request followed by one response. Response has cache control
/// headers set such that a caching HTTP proxy (such as GFE) can
/// satisfy subsequent requests.
/// </summary>
public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return CacheableUnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// One request followed by one response. Response has cache control
/// headers set such that a caching HTTP proxy (such as GFE) can
/// satisfy subsequent requests.
/// </summary>
public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_CacheableUnaryCall, null, options, request);
}
/// <summary>
/// One request followed by one response. Response has cache control
/// headers set such that a caching HTTP proxy (such as GFE) can
/// satisfy subsequent requests.
/// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return CacheableUnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// One request followed by one response. Response has cache control
/// headers set such that a caching HTTP proxy (such as GFE) can
/// satisfy subsequent requests.
/// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_CacheableUnaryCall, null, options, request);
}
/// <summary>
/// One request followed by a sequence of responses (streamed download).
/// The server returns the payload with client desired type and sizes.
/// </summary>
@ -314,6 +383,38 @@ namespace Grpc.Testing {
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options);
}
/// <summary>
/// The test server will not implement this method. It will be used
/// to test the behavior when clients call unimplemented methods.
/// </summary>
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// The test server will not implement this method. It will be used
/// to test the behavior when clients call unimplemented methods.
/// </summary>
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request);
}
/// <summary>
/// The test server will not implement this method. It will be used
/// to test the behavior when clients call unimplemented methods.
/// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// The test server will not implement this method. It will be used
/// to test the behavior when clients call unimplemented methods.
/// </summary>
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override TestServiceClient NewInstance(ClientBaseConfiguration configuration)
{
@ -327,10 +428,12 @@ namespace Grpc.Testing {
return ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_CacheableUnaryCall, serviceImpl.CacheableUnaryCall)
.AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall)
.AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall)
.AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall)
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall)
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
}
}

@ -84,11 +84,6 @@ typedef struct grpcsharp_batch_context {
size_t status_details_capacity;
} recv_status_on_client;
int recv_close_on_server_cancelled;
struct {
grpc_call *call;
grpc_call_details call_details;
grpc_metadata_array request_metadata;
} server_rpc_new;
} grpcsharp_batch_context;
GPR_EXPORT grpcsharp_batch_context *GPR_CALLTYPE grpcsharp_batch_context_create() {
@ -97,6 +92,18 @@ GPR_EXPORT grpcsharp_batch_context *GPR_CALLTYPE grpcsharp_batch_context_create(
return ctx;
}
typedef struct {
grpc_call *call;
grpc_call_details call_details;
grpc_metadata_array request_metadata;
} grpcsharp_request_call_context;
GPR_EXPORT grpcsharp_request_call_context *GPR_CALLTYPE grpcsharp_request_call_context_create() {
grpcsharp_request_call_context *ctx = gpr_malloc(sizeof(grpcsharp_request_call_context));
memset(ctx, 0, sizeof(grpcsharp_request_call_context));
return ctx;
}
/*
* Destroys array->metadata.
* The array pointer itself is not freed.
@ -230,13 +237,20 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_batch_context_destroy(grpcsharp_batch_con
&(ctx->recv_status_on_client.trailing_metadata));
gpr_free((void *)ctx->recv_status_on_client.status_details);
gpr_free(ctx);
}
GPR_EXPORT void GPR_CALLTYPE grpcsharp_request_call_context_destroy(grpcsharp_request_call_context *ctx) {
if (!ctx) {
return;
}
/* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is
supposed
to take its ownership. */
grpc_call_details_destroy(&(ctx->server_rpc_new.call_details));
grpc_call_details_destroy(&(ctx->call_details));
grpcsharp_metadata_array_destroy_metadata_only(
&(ctx->server_rpc_new.request_metadata));
&(ctx->request_metadata));
gpr_free(ctx);
}
@ -303,32 +317,32 @@ grpcsharp_batch_context_recv_status_on_client_trailing_metadata(
return &(ctx->recv_status_on_client.trailing_metadata);
}
GPR_EXPORT grpc_call *GPR_CALLTYPE grpcsharp_batch_context_server_rpc_new_call(
const grpcsharp_batch_context *ctx) {
return ctx->server_rpc_new.call;
GPR_EXPORT grpc_call *GPR_CALLTYPE grpcsharp_request_call_context_call(
const grpcsharp_request_call_context *ctx) {
return ctx->call;
}
GPR_EXPORT const char *GPR_CALLTYPE
grpcsharp_batch_context_server_rpc_new_method(
const grpcsharp_batch_context *ctx) {
return ctx->server_rpc_new.call_details.method;
grpcsharp_request_call_context_method(
const grpcsharp_request_call_context *ctx) {
return ctx->call_details.method;
}
GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_batch_context_server_rpc_new_host(
const grpcsharp_batch_context *ctx) {
return ctx->server_rpc_new.call_details.host;
GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_request_call_context_host(
const grpcsharp_request_call_context *ctx) {
return ctx->call_details.host;
}
GPR_EXPORT gpr_timespec GPR_CALLTYPE
grpcsharp_batch_context_server_rpc_new_deadline(
const grpcsharp_batch_context *ctx) {
return ctx->server_rpc_new.call_details.deadline;
grpcsharp_request_call_context_deadline(
const grpcsharp_request_call_context *ctx) {
return ctx->call_details.deadline;
}
GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE
grpcsharp_batch_context_server_rpc_new_request_metadata(
const grpcsharp_batch_context *ctx) {
return &(ctx->server_rpc_new.request_metadata);
grpcsharp_request_call_context_request_metadata(
const grpcsharp_request_call_context *ctx) {
return &(ctx->request_metadata);
}
GPR_EXPORT int32_t GPR_CALLTYPE
@ -853,10 +867,10 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server *server) {
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq,
grpcsharp_batch_context *ctx) {
grpcsharp_request_call_context *ctx) {
return grpc_server_request_call(
server, &(ctx->server_rpc_new.call), &(ctx->server_rpc_new.call_details),
&(ctx->server_rpc_new.request_metadata), cq, cq, ctx);
server, &(ctx->call), &(ctx->call_details),
&(ctx->request_metadata), cq, cq, ctx);
}
/* Security */

@ -375,7 +375,8 @@ function statusCodeAndMessage(client, done) {
duplex.end();
}
function unimplementedMethod(client, done) {
// NOTE: the client param to this function is from UnimplementedService
function unimplementedService(client, done) {
client.unimplementedCall({}, function(err, resp) {
assert(err);
assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED);
@ -384,6 +385,15 @@ function unimplementedMethod(client, done) {
});
}
// NOTE: the client param to this function is from TestService
function unimplementedMethod(client, done) {
client.unimplementedCall({}, function(err, resp) {
assert(err);
assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED);
done();
});
}
/**
* Run one of the authentication tests.
* @param {string} expected_user The expected username in the response
@ -527,8 +537,10 @@ var test_cases = {
Client: testProto.TestService},
status_code_and_message: {run: statusCodeAndMessage,
Client: testProto.TestService},
unimplemented_method: {run: unimplementedMethod,
unimplemented_service: {run: unimplementedService,
Client: testProto.UnimplementedService},
unimplemented_method: {run: unimplementedMethod,
Client: testProto.TestService},
compute_engine_creds: {run: computeEngineCreds,
Client: testProto.TestService,
getCreds: getApplicationCreds},

@ -98,6 +98,10 @@ describe('Interop tests', function() {
interop_client.runTest(port, name_override, 'status_code_and_message',
true, true, done);
});
it('should pass unimplemented_service', function(done) {
interop_client.runTest(port, name_override, 'unimplemented_service',
true, true, done);
});
it('should pass unimplemented_method', function(done) {
interop_client.runTest(port, name_override, 'unimplemented_method',
true, true, done);

@ -44,17 +44,21 @@
#include <sys/wait.h>
#include <unistd.h>
#include <gflags/gflags.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "test/core/util/port.h"
#include "test/cpp/util/test_config.h"
extern "C" {
#include "src/core/lib/iomgr/socket_utils_posix.h"
#include "src/core/lib/support/string.h"
}
DEFINE_string(extra_server_flags, "", "Extra flags to pass to server.");
int test_client(const char* root, const char* host, int port) {
int status;
pid_t cli;
@ -80,6 +84,7 @@ int test_client(const char* root, const char* host, int port) {
}
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
char* me = argv[0];
char* lslash = strrchr(me, '/');
char root[1024];
@ -105,15 +110,19 @@ int main(int argc, char** argv) {
/* start the server */
svr = fork();
if (svr == 0) {
char* binary_path;
char* port_arg;
gpr_asprintf(&binary_path, "%s/interop_server", root);
gpr_asprintf(&port_arg, "--port=%d", port);
execl(binary_path, binary_path, port_arg, NULL);
gpr_free(binary_path);
gpr_free(port_arg);
const size_t num_args = 3 + !FLAGS_extra_server_flags.empty();
char** args = (char**)gpr_malloc(sizeof(char*) * num_args);
memset(args, 0, sizeof(char*) * num_args);
gpr_asprintf(&args[0], "%s/interop_server", root);
gpr_asprintf(&args[1], "--port=%d", port);
if (!FLAGS_extra_server_flags.empty()) {
args[2] = gpr_strdup(FLAGS_extra_server_flags.c_str());
}
execv(args[0], args);
for (size_t i = 0; i < num_args - 1; ++i) {
gpr_free(args[i]);
}
gpr_free(args);
return 1;
}
/* wait a little */

@ -46,6 +46,7 @@
#include "src/proto/grpc/testing/metrics.grpc.pb.h"
#include "src/proto/grpc/testing/metrics.pb.h"
#include "test/cpp/interop/client_helper.h"
#include "test/cpp/interop/interop_client.h"
#include "test/cpp/interop/stress_interop_client.h"
#include "test/cpp/util/metrics_server.h"
@ -68,7 +69,8 @@ DEFINE_int32(test_duration_secs, -1,
DEFINE_string(server_addresses, "localhost:8080",
"The list of server"
" addresses in the format:\n"
"addresses. This option is ignored if either\n"
"server_port or server_host is specified. The format is: \n"
" \"<name_1>:<port_1>,<name_2>:<port_1>...<name_N>:<port_N>\"\n"
" Note: <name> can be servername or IP address.");
@ -79,6 +81,34 @@ DEFINE_int32(num_stubs_per_channel, 1,
"indicates the max number of parallel RPC calls on each channel "
"at any given time.");
DEFINE_string(test_case, "",
"Configure different test cases. Valid options are:\n\n"
"all : all test cases;\n"
"cancel_after_begin : cancel stream after starting it;\n"
"cancel_after_first_response: cancel on first response;\n"
"client_compressed_streaming : compressed request streaming with "
"client_compressed_unary : single compressed request;\n"
"client_streaming : request streaming with single response;\n"
"compute_engine_creds: large_unary with compute engine auth;\n"
"custom_metadata: server will echo custom metadata;\n"
"empty_stream : bi-di stream with no request/response;\n"
"empty_unary : empty (zero bytes) request and response;\n"
"half_duplex : half-duplex streaming;\n"
"jwt_token_creds: large_unary with JWT token auth;\n"
"large_unary : single request and (large) response;\n"
"oauth2_auth_token: raw oauth2 access token auth;\n"
"per_rpc_creds: raw oauth2 access token on a single rpc;\n"
"ping_pong : full-duplex streaming;\n"
"response streaming;\n"
"server_compressed_streaming : single request with compressed "
"server_compressed_unary : single compressed response;\n"
"server_streaming : single request with response streaming;\n"
"slow_consumer : single request with response streaming with "
"slow client consumer;\n"
"status_code_and_message: verify status code & message;\n"
"timeout_on_sleeping_server: deadline exceeds on stream;\n"
"unimplemented_method: client calls an unimplemented_method;\n");
// TODO(sreek): Add more test cases here in future
DEFINE_string(test_cases, "",
"List of test cases to call along with the"
@ -115,6 +145,17 @@ DEFINE_bool(do_not_abort_on_transient_failures, true,
"If set to 'true', abort() is not called in case of transient "
"failures like temporary connection failures.");
// Options from client.cc (for compatibility with interop test).
// TODO(sreek): Consolidate overlapping options
DEFINE_bool(use_tls, false, "Whether to use tls.");
DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
DEFINE_int32(server_port, 0, "Server port.");
DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
DEFINE_string(server_host_override, "foo.test.google.fr",
"Override the server host which is sent in HTTP header");
DEFINE_string(service_account_key_file, "",
"Path to service account json key file.");
using grpc::testing::kTestCaseList;
using grpc::testing::MetricsService;
using grpc::testing::MetricsServiceImpl;
@ -200,6 +241,8 @@ bool ParseTestCasesString(const grpc::string& test_cases,
void LogParameterInfo(const std::vector<grpc::string>& addresses,
const std::vector<std::pair<TestCaseType, int>>& tests) {
gpr_log(GPR_INFO, "server_addresses: %s", FLAGS_server_addresses.c_str());
gpr_log(GPR_INFO, "server_host: %s", FLAGS_server_host.c_str());
gpr_log(GPR_INFO, "server_port: %d", FLAGS_server_port);
gpr_log(GPR_INFO, "test_cases : %s", FLAGS_test_cases.c_str());
gpr_log(GPR_INFO, "sleep_duration_ms: %d", FLAGS_sleep_duration_ms);
gpr_log(GPR_INFO, "test_duration_secs: %d", FLAGS_test_duration_secs);
@ -243,11 +286,24 @@ int main(int argc, char** argv) {
// Parse the server addresses
std::vector<grpc::string> server_addresses;
ParseCommaDelimitedString(FLAGS_server_addresses, server_addresses);
if (FLAGS_server_port != 0) {
// We are using interop_client style cmdline options.
const int host_port_buf_size = 1024;
char host_port[host_port_buf_size];
snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
FLAGS_server_port);
std::string host_port_str(host_port);
ParseCommaDelimitedString(host_port_str, server_addresses);
} else {
ParseCommaDelimitedString(FLAGS_server_addresses, server_addresses);
}
// Parse test cases and weights
if (FLAGS_test_cases.length() == 0) {
gpr_log(GPR_ERROR, "Not running tests. The 'test_cases' string is empty");
// We are using interop_client style test_case option
FLAGS_test_cases = FLAGS_test_case + ":100";
} else if (FLAGS_test_case != "") {
gpr_log(GPR_ERROR, "specify --test_case or --test_cases but not both.");
return 1;
}
@ -283,9 +339,14 @@ int main(int argc, char** argv) {
// Create channel(s) for each server
for (int channel_idx = 0; channel_idx < FLAGS_num_channels_per_server;
channel_idx++) {
// TODO (sreek). This won't work for tests that require Authentication
std::shared_ptr<grpc::Channel> channel(
grpc::CreateChannel(*it, grpc::InsecureChannelCredentials()));
gpr_log(GPR_INFO, "Starting test with %s channel_idx=%d..", it->c_str(),
channel_idx);
std::shared_ptr<grpc::Channel> channel;
if (FLAGS_use_tls) {
channel = grpc::testing::CreateChannelForTestCase(FLAGS_test_case);
} else {
channel = grpc::CreateChannel(*it, grpc::InsecureChannelCredentials());
}
// Create stub(s) for each channel
for (int stub_idx = 0; stub_idx < FLAGS_num_stubs_per_channel;
@ -311,8 +372,10 @@ int main(int argc, char** argv) {
}
// Start metrics server before waiting for the stress test threads
std::unique_ptr<grpc::Server> metrics_server =
metrics_service.StartServer(FLAGS_metrics_port);
if (FLAGS_metrics_port > 0) {
std::unique_ptr<grpc::Server> metrics_server =
metrics_service.StartServer(FLAGS_metrics_port);
}
// Wait for the stress test threads to complete
for (auto it = test_threads.begin(); it != test_threads.end(); it++) {

@ -91,12 +91,11 @@ def create_qpsworker_job(language, shortname=None,
else:
host_and_port='localhost:%s' % port
# TODO(jtattermusch): with some care, we can calculate the right timeout
# of a worker from the sum of warmup + benchmark times for all the scenarios
jobspec = jobset.JobSpec(
cmdline=cmdline,
shortname=shortname,
timeout_seconds=2*60*60)
timeout_seconds=5*60, # workers get restarted after each scenario
verbose_success=True)
return QpsWorkerJob(jobspec, language, host_and_port)
@ -357,6 +356,7 @@ def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*',
def finish_qps_workers(jobs):
"""Waits for given jobs to finish and eventually kills them."""
retries = 0
num_killed = 0
while any(job.is_running() for job in jobs):
for job in qpsworker_jobs:
if job.is_running():
@ -365,10 +365,11 @@ def finish_qps_workers(jobs):
print('Killing all QPS workers.')
for job in jobs:
job.kill()
num_killed += 1
retries += 1
time.sleep(3)
print('All QPS workers finished.')
return num_killed
argp = argparse.ArgumentParser(description='Run performance tests.')
argp.add_argument('-l', '--language',
@ -450,6 +451,8 @@ scenarios = create_scenarios(languages,
if not scenarios:
raise Exception('No scenarios to run')
total_scenario_failures = 0
qps_workers_killed = 0
for scenario in scenarios:
if args.dry_run:
print(scenario.name)
@ -457,8 +460,14 @@ for scenario in scenarios:
try:
for worker in scenario.workers:
worker.start()
jobset.run([scenario.jobspec,
create_quit_jobspec(scenario.workers, remote_host=args.remote_driver_host)],
newline_on_success=True, maxjobs=1)
scenario_failures, _ = jobset.run([scenario.jobspec,
create_quit_jobspec(scenario.workers, remote_host=args.remote_driver_host)],
newline_on_success=True, maxjobs=1)
total_scenario_failures += scenario_failures
finally:
finish_qps_workers(scenario.workers)
# Consider qps workers that need to be killed as failures
qps_workers_killed += finish_qps_workers(scenario.workers)
if total_scenario_failures > 0 or qps_workers_killed > 0:
print ("%s scenarios failed and %s qps worker jobs killed" % (total_scenario_failures, qps_workers_killed))
sys.exit(1)

@ -2695,6 +2695,7 @@
"gpr",
"gpr_test_util",
"grpc",
"grpc++_test_config",
"grpc_test_util"
],
"headers": [],
@ -3135,6 +3136,7 @@
"language": "c++",
"name": "stress_test",
"src": [
"test/cpp/interop/client_helper.cc",
"test/cpp/interop/client_helper.h",
"test/cpp/interop/interop_client.cc",
"test/cpp/interop/interop_client.h",
@ -4966,6 +4968,27 @@
"third_party": false,
"type": "lib"
},
{
"deps": [
"gpr",
"grpc++_base",
"grpc++_codegen_base",
"grpc++_codegen_base_src",
"grpc_cronet"
],
"headers": [],
"is_filegroup": false,
"language": "c++",
"name": "grpc++_cronet",
"src": [
"src/cpp/client/cronet_credentials.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/common/insecure_create_auth_context.cc",
"src/cpp/server/insecure_server_credentials.cc"
],
"third_party": false,
"type": "lib"
},
{
"deps": [
"grpc++",

@ -198,6 +198,8 @@
</ClCompile>
<ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.h">
</ClInclude>
<ClCompile Include="$(SolutionDir)\..\test\cpp\interop\client_helper.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_client.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\interop\stress_interop_client.cc">

@ -13,6 +13,9 @@
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.proto">
<Filter>src\proto\grpc\testing</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\interop\client_helper.cc">
<Filter>test\cpp\interop</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_client.cc">
<Filter>test\cpp\interop</Filter>
</ClCompile>

Loading…
Cancel
Save