diff options
227 files changed, 8374 insertions, 3165 deletions
diff --git a/.gitmodules b/.gitmodules index c32881cb95..04d155cfb4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,6 +17,6 @@ [submodule "third_party/thrift"] path = third_party/thrift url = https://github.com/apache/thrift.git -[submodule "third_party/google_benchmark"] - path = third_party/google_benchmark +[submodule "third_party/benchmark"] + path = third_party/benchmark url = https://github.com/google/benchmark @@ -135,6 +135,7 @@ cc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -287,9 +288,9 @@ cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", - "src/core/lib/security/transport/handshake.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/tsi_error.h", "src/core/lib/security/util/b64.h", "src/core/lib/security/util/json_util.h", @@ -298,6 +299,7 @@ cc_library( "src/core/lib/tsi/ssl_types.h", "src/core/lib/tsi/transport_security.h", "src/core/lib/tsi/transport_security_interface.h", + "src/core/ext/transport/chttp2/server/chttp2_server.h", "src/core/ext/client_channel/client_channel.h", "src/core/ext/client_channel/client_channel_factory.h", "src/core/ext/client_channel/connector.h", @@ -313,6 +315,7 @@ cc_library( "src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/uri_parser.h", + "src/core/ext/transport/chttp2/client/chttp2_connector.h", "src/core/ext/lb_policy/grpclb/grpclb.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", @@ -481,9 +484,9 @@ cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.c", "src/core/lib/security/credentials/ssl/ssl_credentials.c", "src/core/lib/security/transport/client_auth_filter.c", - "src/core/lib/security/transport/handshake.c", "src/core/lib/security/transport/secure_endpoint.c", "src/core/lib/security/transport/security_connector.c", + "src/core/lib/security/transport/security_handshaker.c", "src/core/lib/security/transport/server_auth_filter.c", "src/core/lib/security/transport/tsi_error.c", "src/core/lib/security/util/b64.c", @@ -492,6 +495,7 @@ cc_library( "src/core/lib/tsi/fake_transport_security.c", "src/core/lib/tsi/ssl_transport_security.c", "src/core/lib/tsi/transport_security.c", + "src/core/ext/transport/chttp2/server/chttp2_server.c", "src/core/ext/transport/chttp2/client/secure/secure_channel_create.c", "src/core/ext/client_channel/channel_connectivity.c", "src/core/ext/client_channel/client_channel.c", @@ -511,6 +515,7 @@ cc_library( "src/core/ext/client_channel/subchannel.c", "src/core/ext/client_channel/subchannel_index.c", "src/core/ext/client_channel/uri_parser.c", + "src/core/ext/transport/chttp2/client/chttp2_connector.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", @@ -560,6 +565,7 @@ cc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -737,9 +743,9 @@ cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", - "src/core/lib/security/transport/handshake.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/tsi_error.h", "src/core/lib/security/util/b64.h", "src/core/lib/security/util/json_util.h", @@ -748,6 +754,7 @@ cc_library( "src/core/lib/tsi/ssl_types.h", "src/core/lib/tsi/transport_security.h", "src/core/lib/tsi/transport_security_interface.h", + "src/core/ext/transport/chttp2/client/chttp2_connector.h", "src/core/lib/surface/init.c", "src/core/lib/channel/channel_args.c", "src/core/lib/channel/channel_stack.c", @@ -921,9 +928,9 @@ cc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.c", "src/core/lib/security/credentials/ssl/ssl_credentials.c", "src/core/lib/security/transport/client_auth_filter.c", - "src/core/lib/security/transport/handshake.c", "src/core/lib/security/transport/secure_endpoint.c", "src/core/lib/security/transport/security_connector.c", + "src/core/lib/security/transport/security_handshaker.c", "src/core/lib/security/transport/server_auth_filter.c", "src/core/lib/security/transport/tsi_error.c", "src/core/lib/security/util/b64.c", @@ -932,6 +939,7 @@ cc_library( "src/core/lib/tsi/fake_transport_security.c", "src/core/lib/tsi/ssl_transport_security.c", "src/core/lib/tsi/transport_security.c", + "src/core/ext/transport/chttp2/client/chttp2_connector.c", "src/core/plugin_registry/grpc_cronet_plugin_registry.c", ], hdrs = [ @@ -954,6 +962,7 @@ cc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -1097,6 +1106,8 @@ cc_library( "src/core/ext/transport/chttp2/transport/stream_map.h", "src/core/ext/transport/chttp2/transport/varint.h", "src/core/ext/transport/chttp2/alpn/alpn.h", + "src/core/ext/transport/chttp2/server/chttp2_server.h", + "src/core/ext/transport/chttp2/client/chttp2_connector.h", "src/core/ext/client_channel/client_channel.h", "src/core/ext/client_channel/client_channel_factory.h", "src/core/ext/client_channel/connector.h", @@ -1266,8 +1277,10 @@ cc_library( "src/core/ext/transport/chttp2/transport/varint.c", "src/core/ext/transport/chttp2/transport/writing.c", "src/core/ext/transport/chttp2/alpn/alpn.c", + "src/core/ext/transport/chttp2/server/chttp2_server.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", "src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c", + "src/core/ext/transport/chttp2/client/chttp2_connector.c", "src/core/ext/client_channel/channel_connectivity.c", "src/core/ext/client_channel/client_channel.c", "src/core/ext/client_channel/client_channel_factory.c", @@ -1331,6 +1344,7 @@ cc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -1486,6 +1500,7 @@ cc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -1515,6 +1530,7 @@ cc_library( "src/cpp/server/dynamic_thread_pool.h", "src/cpp/server/thread_pool_interface.h", "src/cpp/thread_manager/thread_manager.h", + "src/core/ext/transport/chttp2/client/chttp2_connector.h", "src/core/ext/transport/chttp2/transport/bin_decoder.h", "src/core/ext/transport/chttp2/transport/bin_encoder.h", "src/core/ext/transport/chttp2/transport/chttp2_transport.h", @@ -1648,6 +1664,7 @@ cc_library( "src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/uri_parser.h", + "src/core/ext/transport/chttp2/server/chttp2_server.h", "src/core/ext/census/aggregation.h", "src/core/ext/census/base_resources.h", "src/core/ext/census/census_interface.h", @@ -1694,6 +1711,7 @@ cc_library( "src/cpp/codegen/codegen_init.cc", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", "src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c", + "src/core/ext/transport/chttp2/client/chttp2_connector.c", "src/core/ext/transport/chttp2/transport/bin_decoder.c", "src/core/ext/transport/chttp2/transport/bin_encoder.c", "src/core/ext/transport/chttp2/transport/chttp2_plugin.c", @@ -1848,6 +1866,7 @@ cc_library( "src/core/ext/client_channel/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c", + "src/core/ext/transport/chttp2/server/chttp2_server.c", "src/core/ext/census/base_resources.c", "src/core/ext/census/context.c", "src/core/ext/census/gen/census.pb.c", @@ -1944,6 +1963,7 @@ cc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -2120,6 +2140,7 @@ cc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -2282,6 +2303,7 @@ objc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -2467,9 +2489,9 @@ objc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.c", "src/core/lib/security/credentials/ssl/ssl_credentials.c", "src/core/lib/security/transport/client_auth_filter.c", - "src/core/lib/security/transport/handshake.c", "src/core/lib/security/transport/secure_endpoint.c", "src/core/lib/security/transport/security_connector.c", + "src/core/lib/security/transport/security_handshaker.c", "src/core/lib/security/transport/server_auth_filter.c", "src/core/lib/security/transport/tsi_error.c", "src/core/lib/security/util/b64.c", @@ -2478,6 +2500,7 @@ objc_library( "src/core/lib/tsi/fake_transport_security.c", "src/core/lib/tsi/ssl_transport_security.c", "src/core/lib/tsi/transport_security.c", + "src/core/ext/transport/chttp2/server/chttp2_server.c", "src/core/ext/transport/chttp2/client/secure/secure_channel_create.c", "src/core/ext/client_channel/channel_connectivity.c", "src/core/ext/client_channel/client_channel.c", @@ -2497,6 +2520,7 @@ objc_library( "src/core/ext/client_channel/subchannel.c", "src/core/ext/client_channel/subchannel_index.c", "src/core/ext/client_channel/uri_parser.c", + "src/core/ext/transport/chttp2/client/chttp2_connector.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", @@ -2546,6 +2570,7 @@ objc_library( "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -2686,9 +2711,9 @@ objc_library( "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", - "src/core/lib/security/transport/handshake.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/tsi_error.h", "src/core/lib/security/util/b64.h", "src/core/lib/security/util/json_util.h", @@ -2697,6 +2722,7 @@ objc_library( "src/core/lib/tsi/ssl_types.h", "src/core/lib/tsi/transport_security.h", "src/core/lib/tsi/transport_security_interface.h", + "src/core/ext/transport/chttp2/server/chttp2_server.h", "src/core/ext/client_channel/client_channel.h", "src/core/ext/client_channel/client_channel_factory.h", "src/core/ext/client_channel/connector.h", @@ -2712,6 +2738,7 @@ objc_library( "src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/uri_parser.h", + "src/core/ext/transport/chttp2/client/chttp2_connector.h", "src/core/ext/lb_policy/grpclb/grpclb.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 1373b75960..16e5d62de2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,6 +258,7 @@ foreach(_hdr 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_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -436,9 +437,9 @@ add_library(grpc src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/transport/client_auth_filter.c - src/core/lib/security/transport/handshake.c src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/security_connector.c + src/core/lib/security/transport/security_handshaker.c src/core/lib/security/transport/server_auth_filter.c src/core/lib/security/transport/tsi_error.c src/core/lib/security/util/b64.c @@ -447,6 +448,7 @@ add_library(grpc src/core/lib/tsi/fake_transport_security.c src/core/lib/tsi/ssl_transport_security.c src/core/lib/tsi/transport_security.c + src/core/ext/transport/chttp2/server/chttp2_server.c src/core/ext/transport/chttp2/client/secure/secure_channel_create.c src/core/ext/client_channel/channel_connectivity.c src/core/ext/client_channel/client_channel.c @@ -466,6 +468,7 @@ add_library(grpc src/core/ext/client_channel/subchannel.c src/core/ext/client_channel/subchannel_index.c src/core/ext/client_channel/uri_parser.c + src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/ext/transport/chttp2/server/insecure/server_chttp2.c src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c src/core/ext/transport/chttp2/client/insecure/channel_create.c @@ -535,6 +538,7 @@ foreach(_hdr 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_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -736,9 +740,9 @@ add_library(grpc_cronet src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/transport/client_auth_filter.c - src/core/lib/security/transport/handshake.c src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/security_connector.c + src/core/lib/security/transport/security_handshaker.c src/core/lib/security/transport/server_auth_filter.c src/core/lib/security/transport/tsi_error.c src/core/lib/security/util/b64.c @@ -747,6 +751,7 @@ add_library(grpc_cronet src/core/lib/tsi/fake_transport_security.c src/core/lib/tsi/ssl_transport_security.c src/core/lib/tsi/transport_security.c + src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/plugin_registry/grpc_cronet_plugin_registry.c ) @@ -785,6 +790,7 @@ foreach(_hdr 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_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -951,8 +957,10 @@ add_library(grpc_unsecure src/core/ext/transport/chttp2/transport/varint.c src/core/ext/transport/chttp2/transport/writing.c src/core/ext/transport/chttp2/alpn/alpn.c + src/core/ext/transport/chttp2/server/chttp2_server.c src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c + src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/ext/client_channel/channel_connectivity.c src/core/ext/client_channel/client_channel.c src/core/ext/client_channel/client_channel_factory.c @@ -1034,6 +1042,7 @@ foreach(_hdr 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_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1197,6 +1206,7 @@ foreach(_hdr 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_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1258,6 +1268,7 @@ add_library(grpc++_cronet src/cpp/codegen/codegen_init.cc src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c + src/core/ext/transport/chttp2/client/chttp2_connector.c src/core/ext/transport/chttp2/transport/bin_decoder.c src/core/ext/transport/chttp2/transport/bin_encoder.c src/core/ext/transport/chttp2/transport/chttp2_plugin.c @@ -1412,6 +1423,7 @@ add_library(grpc++_cronet src/core/ext/client_channel/uri_parser.c src/core/ext/transport/chttp2/server/insecure/server_chttp2.c src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c + src/core/ext/transport/chttp2/server/chttp2_server.c src/core/ext/census/base_resources.c src/core/ext/census/context.c src/core/ext/census/gen/census.pb.c @@ -1528,6 +1540,7 @@ foreach(_hdr 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_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1734,6 +1747,7 @@ foreach(_hdr 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_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1260,9 +1260,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc ifeq ($(EMBED_OPENSSL),true) -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a else -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a endif @@ -2552,6 +2552,7 @@ PUBLIC_HEADERS_C += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -2775,9 +2776,9 @@ LIBGRPC_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ - src/core/lib/security/transport/handshake.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ + src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/server_auth_filter.c \ src/core/lib/security/transport/tsi_error.c \ src/core/lib/security/util/b64.c \ @@ -2786,6 +2787,7 @@ LIBGRPC_SRC = \ src/core/lib/tsi/fake_transport_security.c \ src/core/lib/tsi/ssl_transport_security.c \ src/core/lib/tsi/transport_security.c \ + src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \ src/core/ext/client_channel/channel_connectivity.c \ src/core/ext/client_channel/client_channel.c \ @@ -2805,6 +2807,7 @@ LIBGRPC_SRC = \ src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/uri_parser.c \ + src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ @@ -2857,6 +2860,7 @@ PUBLIC_HEADERS_C += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3093,9 +3097,9 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ - src/core/lib/security/transport/handshake.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ + src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/server_auth_filter.c \ src/core/lib/security/transport/tsi_error.c \ src/core/lib/security/util/b64.c \ @@ -3104,6 +3108,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/tsi/fake_transport_security.c \ src/core/lib/tsi/ssl_transport_security.c \ src/core/lib/tsi/transport_security.c \ + src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/plugin_registry/grpc_cronet_plugin_registry.c \ PUBLIC_HEADERS_C += \ @@ -3126,6 +3131,7 @@ PUBLIC_HEADERS_C += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3342,6 +3348,7 @@ PUBLIC_HEADERS_C += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3562,8 +3569,10 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ + src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ + src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/client_channel/channel_connectivity.c \ src/core/ext/client_channel/client_channel.c \ src/core/ext/client_channel/client_channel_factory.c \ @@ -3630,6 +3639,7 @@ PUBLIC_HEADERS_C += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3874,6 +3884,7 @@ PUBLIC_HEADERS_CXX += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3981,6 +3992,7 @@ LIBGRPC++_CRONET_SRC = \ src/cpp/codegen/codegen_init.cc \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ + src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ src/core/ext/transport/chttp2/transport/chttp2_plugin.c \ @@ -4135,6 +4147,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/ext/client_channel/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ + src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/census/base_resources.c \ src/core/ext/census/context.c \ src/core/ext/census/gen/census.pb.c \ @@ -4234,6 +4247,7 @@ PUBLIC_HEADERS_CXX += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -4589,6 +4603,7 @@ PUBLIC_HEADERS_CXX += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -4767,6 +4782,7 @@ PUBLIC_HEADERS_CXX += \ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -6991,43 +7007,43 @@ ifneq ($(NO_DEPS),true) endif -LIBGOOGLE_BENCHMARK_SRC = \ - third_party/google_benchmark/src/benchmark.cc \ - third_party/google_benchmark/src/benchmark_register.cc \ - third_party/google_benchmark/src/colorprint.cc \ - third_party/google_benchmark/src/commandlineflags.cc \ - third_party/google_benchmark/src/complexity.cc \ - third_party/google_benchmark/src/console_reporter.cc \ - third_party/google_benchmark/src/csv_reporter.cc \ - third_party/google_benchmark/src/json_reporter.cc \ - third_party/google_benchmark/src/reporter.cc \ - third_party/google_benchmark/src/sleep.cc \ - third_party/google_benchmark/src/string_util.cc \ - third_party/google_benchmark/src/sysinfo.cc \ - third_party/google_benchmark/src/timers.cc \ +LIBBENCHMARK_SRC = \ + third_party/benchmark/src/benchmark.cc \ + third_party/benchmark/src/benchmark_register.cc \ + third_party/benchmark/src/colorprint.cc \ + third_party/benchmark/src/commandlineflags.cc \ + third_party/benchmark/src/complexity.cc \ + third_party/benchmark/src/console_reporter.cc \ + third_party/benchmark/src/csv_reporter.cc \ + third_party/benchmark/src/json_reporter.cc \ + third_party/benchmark/src/reporter.cc \ + third_party/benchmark/src/sleep.cc \ + third_party/benchmark/src/string_util.cc \ + third_party/benchmark/src/sysinfo.cc \ + third_party/benchmark/src/timers.cc \ PUBLIC_HEADERS_CXX += \ -LIBGOOGLE_BENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGOOGLE_BENCHMARK_SRC)))) +LIBBENCHMARK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBENCHMARK_SRC)))) -$(LIBGOOGLE_BENCHMARK_OBJS): CPPFLAGS += -Ithird_party/google_benchmark/include -DHAVE_POSIX_REGEX +$(LIBBENCHMARK_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX 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)/libgoogle_benchmark.a: protobuf_dep_error +$(LIBDIR)/$(CONFIG)/libbenchmark.a: protobuf_dep_error else -$(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a: $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBGOOGLE_BENCHMARK_OBJS) +$(LIBDIR)/$(CONFIG)/libbenchmark.a: $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBBENCHMARK_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` - $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a - $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(LIBGOOGLE_BENCHMARK_OBJS) + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libbenchmark.a + $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBBENCHMARK_OBJS) ifeq ($(SYSTEM),Darwin) - $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a + $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libbenchmark.a endif @@ -7036,7 +7052,7 @@ endif endif ifneq ($(NO_DEPS),true) --include $(LIBGOOGLE_BENCHMARK_OBJS:.o=.dep) +-include $(LIBBENCHMARK_OBJS:.o=.dep) endif @@ -7200,6 +7216,7 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/request_with_payload.c \ test/core/end2end/tests/resource_quota_server.c \ test/core/end2end/tests/server_finishes_request.c \ + test/core/end2end/tests/short_deadlines.c \ test/core/end2end/tests/shutdown_finishes_calls.c \ test/core/end2end/tests/shutdown_finishes_tags.c \ test/core/end2end/tests/simple_cacheable_request.c \ @@ -7286,6 +7303,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/request_with_payload.c \ test/core/end2end/tests/resource_quota_server.c \ test/core/end2end/tests/server_finishes_request.c \ + test/core/end2end/tests/short_deadlines.c \ test/core/end2end/tests/shutdown_finishes_calls.c \ test/core/end2end/tests/shutdown_finishes_tags.c \ test/core/end2end/tests/simple_cacheable_request.c \ @@ -11729,16 +11747,16 @@ $(BINDIR)/$(CONFIG)/bm_fullstack: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/bm_fullstack: $(PROTOBUF_DEP) $(BM_FULLSTACK_OBJS) $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(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 +$(BINDIR)/$(CONFIG)/bm_fullstack: $(PROTOBUF_DEP) $(BM_FULLSTACK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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 $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_OBJS) $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(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 $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack + $(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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 $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack.o: $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(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 +$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack.o: $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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 deps_bm_fullstack: $(BM_FULLSTACK_OBJS:.o=.dep) @@ -13185,16 +13203,16 @@ $(BINDIR)/$(CONFIG)/noop-benchmark: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/noop-benchmark: $(PROTOBUF_DEP) $(NOOP-BENCHMARK_OBJS) $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a +$(BINDIR)/$(CONFIG)/noop-benchmark: $(PROTOBUF_DEP) $(NOOP-BENCHMARK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(NOOP-BENCHMARK_OBJS) $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/noop-benchmark + $(Q) $(LDXX) $(LDFLAGS) $(NOOP-BENCHMARK_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/noop-benchmark endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/noop-benchmark.o: $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a +$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/noop-benchmark.o: $(LIBDIR)/$(CONFIG)/libbenchmark.a deps_noop-benchmark: $(NOOP-BENCHMARK_OBJS:.o=.dep) @@ -16760,9 +16778,9 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP) src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP) -src/core/lib/security/transport/handshake.c: $(OPENSSL_DEP) src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP) src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP) +src/core/lib/security/transport/security_handshaker.c: $(OPENSSL_DEP) src/core/lib/security/transport/server_auth_filter.c: $(OPENSSL_DEP) src/core/lib/security/transport/tsi_error.c: $(OPENSSL_DEP) src/core/lib/security/util/b64.c: $(OPENSSL_DEP) diff --git a/binding.gyp b/binding.gyp index 28d7c6b9a5..516cbdce5d 100644 --- a/binding.gyp +++ b/binding.gyp @@ -716,9 +716,9 @@ 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', - 'src/core/lib/security/transport/handshake.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', + 'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/server_auth_filter.c', 'src/core/lib/security/transport/tsi_error.c', 'src/core/lib/security/util/b64.c', @@ -727,6 +727,7 @@ 'src/core/lib/tsi/fake_transport_security.c', 'src/core/lib/tsi/ssl_transport_security.c', 'src/core/lib/tsi/transport_security.c', + 'src/core/ext/transport/chttp2/server/chttp2_server.c', 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c', 'src/core/ext/client_channel/channel_connectivity.c', 'src/core/ext/client_channel/client_channel.c', @@ -746,6 +747,7 @@ 'src/core/ext/client_channel/subchannel.c', 'src/core/ext/client_channel/subchannel_index.c', 'src/core/ext/client_channel/uri_parser.c', + 'src/core/ext/transport/chttp2/client/chttp2_connector.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', diff --git a/build.yaml b/build.yaml index 510b366b61..2555abce0c 100644 --- a/build.yaml +++ b/build.yaml @@ -144,6 +144,7 @@ filegroups: - 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_slice.h - include/grpc/impl/codegen/gpr_types.h - include/grpc/impl/codegen/port_platform.h - include/grpc/impl/codegen/slice.h @@ -495,9 +496,9 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h - src/core/lib/security/transport/auth_filters.h - - src/core/lib/security/transport/handshake.h - src/core/lib/security/transport/secure_endpoint.h - src/core/lib/security/transport/security_connector.h + - src/core/lib/security/transport/security_handshaker.h - src/core/lib/security/transport/tsi_error.h - src/core/lib/security/util/b64.h - src/core/lib/security/util/json_util.h @@ -518,9 +519,9 @@ filegroups: - src/core/lib/security/credentials/plugin/plugin_credentials.c - src/core/lib/security/credentials/ssl/ssl_credentials.c - src/core/lib/security/transport/client_auth_filter.c - - src/core/lib/security/transport/handshake.c - src/core/lib/security/transport/secure_endpoint.c - src/core/lib/security/transport/security_connector.c + - src/core/lib/security/transport/security_handshaker.c - src/core/lib/security/transport/server_auth_filter.c - src/core/lib/security/transport/tsi_error.c - src/core/lib/security/util/b64.c @@ -621,11 +622,20 @@ filegroups: - src/core/ext/transport/chttp2/alpn/alpn.c deps: - gpr +- name: grpc_transport_chttp2_client_connector + headers: + - src/core/ext/transport/chttp2/client/chttp2_connector.h + src: + - src/core/ext/transport/chttp2/client/chttp2_connector.c + uses: + - grpc_transport_chttp2 + - grpc_base - name: grpc_transport_chttp2_client_insecure src: - src/core/ext/transport/chttp2/client/insecure/channel_create.c - src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c uses: + - grpc_transport_chttp2_client_connector - grpc_transport_chttp2 - grpc_base - grpc_client_channel @@ -637,6 +647,15 @@ filegroups: - grpc_base - grpc_client_channel - grpc_secure + - grpc_transport_chttp2_client_connector +- name: grpc_transport_chttp2_server + headers: + - src/core/ext/transport/chttp2/server/chttp2_server.h + src: + - src/core/ext/transport/chttp2/server/chttp2_server.c + uses: + - grpc_transport_chttp2 + - grpc_base - name: grpc_transport_chttp2_server_insecure src: - src/core/ext/transport/chttp2/server/insecure/server_chttp2.c @@ -644,6 +663,7 @@ filegroups: uses: - grpc_transport_chttp2 - grpc_base + - grpc_transport_chttp2_server - name: grpc_transport_chttp2_server_secure src: - src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c @@ -651,6 +671,7 @@ filegroups: - grpc_transport_chttp2 - grpc_base - grpc_secure + - grpc_transport_chttp2_server - name: grpc_transport_cronet_client_secure public_headers: - include/grpc/grpc_cronet.h @@ -2830,7 +2851,7 @@ targets: src: - test/cpp/microbenchmarks/bm_fullstack.cc deps: - - google_benchmark + - benchmark - grpc++_test_util - grpc_test_util - grpc++ @@ -3280,7 +3301,7 @@ targets: src: - test/cpp/microbenchmarks/noop-benchmark.cc deps: - - google_benchmark + - benchmark - name: proto_server_reflection_test gtest: true build: test @@ -3766,6 +3787,8 @@ configs: UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1 timeout_multiplier: 1.5 defaults: + benchmark: + CPPFLAGS: -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX boringssl: CFLAGS: -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare $(NO_W_EXTRA_SEMI) @@ -3774,8 +3797,6 @@ defaults: global: CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter LDFLAGS: -g - google_benchmark: - CPPFLAGS: -Ithird_party/google_benchmark/include -DHAVE_POSIX_REGEX zlib: CFLAGS: -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-implicit-function-declaration $(W_NO_SHIFT_NEGATIVE_VALUE) -fvisibility=hidden @@ -232,9 +232,9 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ - src/core/lib/security/transport/handshake.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ + src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/server_auth_filter.c \ src/core/lib/security/transport/tsi_error.c \ src/core/lib/security/util/b64.c \ @@ -243,6 +243,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/tsi/fake_transport_security.c \ src/core/lib/tsi/ssl_transport_security.c \ src/core/lib/tsi/transport_security.c \ + src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \ src/core/ext/client_channel/channel_connectivity.c \ src/core/ext/client_channel/client_channel.c \ @@ -262,6 +263,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/uri_parser.c \ + src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ @@ -609,8 +611,10 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/dns/native) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/sockaddr) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/alpn) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/client/secure) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) diff --git a/doc/connection-backoff.md b/doc/connection-backoff.md index 251a60f384..0e83d9b97f 100644 --- a/doc/connection-backoff.md +++ b/doc/connection-backoff.md @@ -7,9 +7,10 @@ requests) and instead do some form of exponential backoff. We have several parameters: 1. INITIAL_BACKOFF (how long to wait after the first failure before retrying) - 2. MULTIPLIER (factor with which to multiply backoff after a failed retry) - 3. MAX_BACKOFF (upper bound on backoff) - 4. MIN_CONNECT_TIMEOUT (minimum time we're willing to give a connection to + 1. MULTIPLIER (factor with which to multiply backoff after a failed retry) + 1. JITTER (by how much to randomize backoffs). + 1. MAX_BACKOFF (upper bound on backoff) + 1. MIN_CONNECT_TIMEOUT (minimum time we're willing to give a connection to complete) ## Proposed Backoff Algorithm diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index c4ec01da93..f9e0164bdc 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -146,6 +146,7 @@ Pod::Spec.new do |s| '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_slice.h', 'include/grpc/impl/codegen/gpr_types.h', 'include/grpc/impl/codegen/port_platform.h', 'include/grpc/impl/codegen/slice.h', @@ -172,6 +173,7 @@ Pod::Spec.new do |s| '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_slice.h', 'include/grpc/impl/codegen/gpr_types.h', 'include/grpc/impl/codegen/port_platform.h', 'include/grpc/impl/codegen/slice.h', @@ -376,9 +378,9 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/transport/auth_filters.h', - 'src/core/lib/security/transport/handshake.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_connector.h', + 'src/core/lib/security/transport/security_handshaker.h', 'src/core/lib/security/transport/tsi_error.h', 'src/core/lib/security/util/b64.h', 'src/core/lib/security/util/json_util.h', @@ -387,6 +389,7 @@ Pod::Spec.new do |s| 'src/core/lib/tsi/ssl_types.h', 'src/core/lib/tsi/transport_security.h', 'src/core/lib/tsi/transport_security_interface.h', + 'src/core/ext/transport/chttp2/server/chttp2_server.h', 'src/core/ext/client_channel/client_channel.h', 'src/core/ext/client_channel/client_channel_factory.h', 'src/core/ext/client_channel/connector.h', @@ -402,6 +405,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_channel/subchannel.h', 'src/core/ext/client_channel/subchannel_index.h', 'src/core/ext/client_channel/uri_parser.h', + 'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/lb_policy/grpclb/grpclb.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', @@ -574,9 +578,9 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', - 'src/core/lib/security/transport/handshake.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', + 'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/server_auth_filter.c', 'src/core/lib/security/transport/tsi_error.c', 'src/core/lib/security/util/b64.c', @@ -585,6 +589,7 @@ Pod::Spec.new do |s| 'src/core/lib/tsi/fake_transport_security.c', 'src/core/lib/tsi/ssl_transport_security.c', 'src/core/lib/tsi/transport_security.c', + 'src/core/ext/transport/chttp2/server/chttp2_server.c', 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c', 'src/core/ext/client_channel/channel_connectivity.c', 'src/core/ext/client_channel/client_channel.c', @@ -604,6 +609,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_channel/subchannel.c', 'src/core/ext/client_channel/subchannel_index.c', 'src/core/ext/client_channel/uri_parser.c', + 'src/core/ext/transport/chttp2/client/chttp2_connector.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', @@ -779,9 +785,9 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/transport/auth_filters.h', - 'src/core/lib/security/transport/handshake.h', 'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/security_connector.h', + 'src/core/lib/security/transport/security_handshaker.h', 'src/core/lib/security/transport/tsi_error.h', 'src/core/lib/security/util/b64.h', 'src/core/lib/security/util/json_util.h', @@ -790,6 +796,7 @@ Pod::Spec.new do |s| 'src/core/lib/tsi/ssl_types.h', 'src/core/lib/tsi/transport_security.h', 'src/core/lib/tsi/transport_security_interface.h', + 'src/core/ext/transport/chttp2/server/chttp2_server.h', 'src/core/ext/client_channel/client_channel.h', 'src/core/ext/client_channel/client_channel_factory.h', 'src/core/ext/client_channel/connector.h', @@ -805,6 +812,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_channel/subchannel.h', 'src/core/ext/client_channel/subchannel_index.h', 'src/core/ext/client_channel/uri_parser.h', + 'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/lb_policy/grpclb/grpclb.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', diff --git a/grpc.gemspec b/grpc.gemspec index cce6f2cfcc..9c9568ce64 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -73,6 +73,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) + s.files += %w( include/grpc/impl/codegen/gpr_slice.h ) s.files += %w( include/grpc/impl/codegen/gpr_types.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) @@ -155,6 +156,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) + s.files += %w( include/grpc/impl/codegen/gpr_slice.h ) s.files += %w( include/grpc/impl/codegen/gpr_types.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) @@ -295,9 +297,9 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) s.files += %w( src/core/lib/security/transport/auth_filters.h ) - s.files += %w( src/core/lib/security/transport/handshake.h ) s.files += %w( src/core/lib/security/transport/secure_endpoint.h ) s.files += %w( src/core/lib/security/transport/security_connector.h ) + s.files += %w( src/core/lib/security/transport/security_handshaker.h ) s.files += %w( src/core/lib/security/transport/tsi_error.h ) s.files += %w( src/core/lib/security/util/b64.h ) s.files += %w( src/core/lib/security/util/json_util.h ) @@ -306,6 +308,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/tsi/ssl_types.h ) s.files += %w( src/core/lib/tsi/transport_security.h ) s.files += %w( src/core/lib/tsi/transport_security_interface.h ) + s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.h ) s.files += %w( src/core/ext/client_channel/client_channel.h ) s.files += %w( src/core/ext/client_channel/client_channel_factory.h ) s.files += %w( src/core/ext/client_channel/connector.h ) @@ -321,6 +324,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_channel/subchannel.h ) s.files += %w( src/core/ext/client_channel/subchannel_index.h ) s.files += %w( src/core/ext/client_channel/uri_parser.h ) + s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h ) s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) @@ -493,9 +497,9 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c ) s.files += %w( src/core/lib/security/transport/client_auth_filter.c ) - s.files += %w( src/core/lib/security/transport/handshake.c ) s.files += %w( src/core/lib/security/transport/secure_endpoint.c ) s.files += %w( src/core/lib/security/transport/security_connector.c ) + s.files += %w( src/core/lib/security/transport/security_handshaker.c ) s.files += %w( src/core/lib/security/transport/server_auth_filter.c ) s.files += %w( src/core/lib/security/transport/tsi_error.c ) s.files += %w( src/core/lib/security/util/b64.c ) @@ -504,6 +508,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/tsi/fake_transport_security.c ) s.files += %w( src/core/lib/tsi/ssl_transport_security.c ) s.files += %w( src/core/lib/tsi/transport_security.c ) + s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.c ) s.files += %w( src/core/ext/transport/chttp2/client/secure/secure_channel_create.c ) s.files += %w( src/core/ext/client_channel/channel_connectivity.c ) s.files += %w( src/core/ext/client_channel/client_channel.c ) @@ -523,6 +528,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_channel/subchannel.c ) s.files += %w( src/core/ext/client_channel/subchannel_index.c ) s.files += %w( src/core/ext/client_channel/uri_parser.c ) + s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index ef00163b7e..944f2c3919 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -52,6 +52,7 @@ #include <grpc++/impl/codegen/grpc_library.h> #include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/time.h> +#include <grpc/impl/codegen/atm.h> struct grpc_completion_queue; @@ -101,6 +102,7 @@ class CompletionQueue : private GrpcLibraryCodegen { /// instance. CompletionQueue() { cq_ = g_core_codegen_interface->grpc_completion_queue_create(nullptr); + InitialAvalanching(); // reserve this for the future shutdown } /// Wrap \a take, taking ownership of the instance. @@ -151,7 +153,8 @@ class CompletionQueue : private GrpcLibraryCodegen { /// Request the shutdown of the queue. /// - /// \warning This method must be called at some point. Once invoked, \a Next + /// \warning This method must be called at some point if this completion queue + /// is accessed with Next or AsyncNext. Once invoked, \a Next /// will start to return false and \a AsyncNext will return \a /// NextStatus::SHUTDOWN. Only once either one of these methods does that /// (that is, once the queue has been \em drained) can an instance of this @@ -165,6 +168,21 @@ class CompletionQueue : private GrpcLibraryCodegen { /// owership is performed. grpc_completion_queue* cq() { return cq_; } + /// Manage state of avalanching operations : completion queue tags that + /// trigger other completion queue operations. The underlying core completion + /// queue should not really shutdown until all avalanching operations have + /// been finalized. Note that we maintain the requirement that an avalanche + /// registration must take place before CQ shutdown (which must be maintained + /// elsehwere) + void InitialAvalanching() { + gpr_atm_rel_store(&avalanches_in_flight_, static_cast<gpr_atm>(1)); + } + void RegisterAvalanching() { + gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast<gpr_atm>(1)); + }; + void CompleteAvalanching(); + private: // Friend synchronous wrappers so that they can access Pluck(), which is // a semi-private API geared towards the synchronous implementation. @@ -229,6 +247,8 @@ class CompletionQueue : private GrpcLibraryCodegen { } grpc_completion_queue* cq_; // owned + + gpr_atm avalanches_in_flight_; }; /// A specific type of completion queue used by the processing of notifications diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h index 41a64bead0..666b9ff66e 100644 --- a/include/grpc++/impl/codegen/server_interface.h +++ b/include/grpc++/impl/codegen/server_interface.h @@ -140,7 +140,7 @@ class ServerInterface : public CallHook { ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag, bool delete_on_finalize); - virtual ~BaseAsyncRequest() {} + virtual ~BaseAsyncRequest(); bool FinalizeResult(void** tag, bool* status) override; diff --git a/include/grpc/impl/codegen/gpr_slice.h b/include/grpc/impl/codegen/gpr_slice.h new file mode 100644 index 0000000000..c62e976b8f --- /dev/null +++ b/include/grpc/impl/codegen/gpr_slice.h @@ -0,0 +1,84 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef GRPC_IMPL_CODEGEN_GPR_SLICE_H +#define GRPC_IMPL_CODEGEN_GPR_SLICE_H + +/* WARNING: Please do not use this header. This was added as a temporary measure + * to not break some of the external projects that depend on gpr_slice_* + * functions. We are actively working on moving all the gpr_slice_* references + * to grpc_slice_* and this file will be removed + * */ + +/* TODO (sreek) - Allowed by default but will be very soon turned off */ +#define GRPC_ALLOW_GPR_SLICE_FUNCTIONS 1 + +#ifdef GRPC_ALLOW_GPR_SLICE_FUNCTIONS + +#define gpr_slice_refcount grpc_slice_refcount +#define gpr_slice grpc_slice +#define gpr_slice_buffer grpc_slice_buffer + +#define gpr_slice_ref grpc_slice_ref +#define gpr_slice_unref grpc_slice_unref +#define gpr_slice_new grpc_slice_new +#define gpr_slice_new_with_user_data grpc_slice_new_with_user_data +#define gpr_slice_new_with_len grpc_slice_new_with_len +#define gpr_slice_malloc grpc_slice_malloc +#define gpr_slice_from_copied_string grpc_slice_from_copied_string +#define gpr_slice_from_copied_buffer grpc_slice_from_copied_buffer +#define gpr_slice_from_static_string grpc_slice_from_static_string +#define gpr_slice_sub grpc_slice_sub +#define gpr_slice_sub_no_ref grpc_slice_sub_no_ref +#define gpr_slice_split_tail grpc_slice_split_tail +#define gpr_slice_split_head grpc_slice_split_head +#define gpr_slice_cmp grpc_slice_cmp +#define gpr_slice_str_cmp grpc_slice_str_cmp + +#define gpr_slice_buffer grpc_slice_buffer +#define gpr_slice_buffer_init grpc_slice_buffer_init +#define gpr_slice_buffer_destroy grpc_slice_buffer_destroy +#define gpr_slice_buffer_add grpc_slice_buffer_add +#define gpr_slice_buffer_add_indexed grpc_slice_buffer_add_indexed +#define gpr_slice_buffer_addn grpc_slice_buffer_addn +#define gpr_slice_buffer_tiny_add grpc_slice_buffer_tiny_add +#define gpr_slice_buffer_pop grpc_slice_buffer_pop +#define gpr_slice_buffer_reset_and_unref grpc_slice_buffer_reset_and_unref +#define gpr_slice_buffer_swap grpc_slice_buffer_swap +#define gpr_slice_buffer_move_into grpc_slice_buffer_move_into +#define gpr_slice_buffer_trim_end grpc_slice_buffer_trim_end +#define gpr_slice_buffer_move_first grpc_slice_buffer_move_first +#define gpr_slice_buffer_take_first grpc_slice_buffer_take_first + +#endif /* GRPC_ALLOW_GPR_SLICE_FUNCTIONS */ + +#endif /* GRPC_IMPL_CODEGEN_GPR_SLICE_H */ diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h index 774ba0e95d..50b5426e1a 100644 --- a/include/grpc/impl/codegen/slice.h +++ b/include/grpc/impl/codegen/slice.h @@ -37,6 +37,8 @@ #include <stddef.h> #include <stdint.h> +#include <grpc/impl/codegen/gpr_slice.h> + /* Slice API A slice represents a contiguous reference counted array of bytes. @@ -115,4 +117,22 @@ typedef struct { GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(slice) #define GRPC_SLICE_IS_EMPTY(slice) (GRPC_SLICE_LENGTH(slice) == 0) +#ifdef GRPC_ALLOW_GPR_SLICE_FUNCTIONS + +/* Duplicate GPR_* definitions */ +#define GPR_SLICE_START_PTR(slice) \ + ((slice).refcount ? (slice).data.refcounted.bytes \ + : (slice).data.inlined.bytes) +#define GPR_SLICE_LENGTH(slice) \ + ((slice).refcount ? (slice).data.refcounted.length \ + : (slice).data.inlined.length) +#define GPR_SLICE_SET_LENGTH(slice, newlen) \ + ((slice).refcount ? ((slice).data.refcounted.length = (size_t)(newlen)) \ + : ((slice).data.inlined.length = (uint8_t)(newlen))) +#define GPR_SLICE_END_PTR(slice) \ + GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(slice) +#define GPR_SLICE_IS_EMPTY(slice) (GRPC_SLICE_LENGTH(slice) == 0) + +#endif /* GRPC_ALLOW_GPR_SLICE_FUNCTIONS */ + #endif /* GRPC_IMPL_CODEGEN_SLICE_H */ diff --git a/package.xml b/package.xml index 2822ac624d..2106b8f666 100644 --- a/package.xml +++ b/package.xml @@ -81,6 +81,7 @@ <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_gcc_atomic.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_gcc_sync.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_windows.h" role="src" /> + <file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_slice.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_types.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/port_platform.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/slice.h" role="src" /> @@ -163,6 +164,7 @@ <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_gcc_atomic.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_gcc_sync.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/atm_windows.h" role="src" /> + <file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_slice.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_types.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/port_platform.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/slice.h" role="src" /> @@ -303,9 +305,9 @@ <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" /> - <file baseinstalldir="/" name="src/core/lib/security/transport/handshake.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/util/b64.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" /> @@ -314,6 +316,7 @@ <file baseinstalldir="/" name="src/core/lib/tsi/ssl_types.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/tsi/transport_security.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/tsi/transport_security_interface.h" role="src" /> + <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/client_channel.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/client_channel_factory.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/connector.h" role="src" /> @@ -329,6 +332,7 @@ <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" /> + <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" /> @@ -501,9 +505,9 @@ <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.c" role="src" /> - <file baseinstalldir="/" name="src/core/lib/security/transport/handshake.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/server_auth_filter.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/util/b64.c" role="src" /> @@ -512,6 +516,7 @@ <file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/tsi/ssl_transport_security.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/tsi/transport_security.c" role="src" /> + <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/secure/secure_channel_create.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/channel_connectivity.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/client_channel.c" role="src" /> @@ -531,6 +536,7 @@ <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.c" role="src" /> + <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" /> diff --git a/src/google_benchmark/gen_build_yaml.py b/src/benchmark/gen_build_yaml.py index 302e08737a..09b76115a8 100755 --- a/src/google_benchmark/gen_build_yaml.py +++ b/src/benchmark/gen_build_yaml.py @@ -39,15 +39,15 @@ os.chdir(os.path.dirname(sys.argv[0])+'/../..') out = {} out['libs'] = [{ - 'name': 'google_benchmark', + 'name': 'benchmark', 'build': 'private', 'language': 'c++', 'secure': 'no', - 'defaults': 'google_benchmark', - 'src': sorted(glob.glob('third_party/google_benchmark/src/*.cc')), + 'defaults': 'benchmark', + 'src': sorted(glob.glob('third_party/benchmark/src/*.cc')), 'headers': sorted( - glob.glob('third_party/google_benchmark/src/*.h') + - glob.glob('third_party/google_benchmark/include/benchmark/*.h')), + glob.glob('third_party/benchmark/src/*.h') + + glob.glob('third_party/benchmark/include/benchmark/*.h')), }] print yaml.dump(out) diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index febaf135b6..b0a60092ab 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -760,6 +760,32 @@ PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config) PythonGrpcGenerator::~PythonGrpcGenerator() {} +static bool GenerateGrpc(GeneratorContext* context, PrivateGenerator& generator, + grpc::string file_name, bool generate_in_pb2_grpc) { + bool success; + std::unique_ptr<ZeroCopyOutputStream> output; + std::unique_ptr<CodedOutputStream> coded_output; + grpc::string grpc_code; + + if (generate_in_pb2_grpc) { + output.reset(context->Open(file_name)); + generator.generate_in_pb2_grpc = true; + } else { + output.reset(context->OpenForInsert(file_name, "module_scope")); + generator.generate_in_pb2_grpc = false; + } + + coded_output.reset(new CodedOutputStream(output.get())); + tie(success, grpc_code) = generator.GetGrpcServices(); + + if (success) { + coded_output->WriteRaw(grpc_code.data(), grpc_code.size()); + return true; + } else { + return false; + } +} + bool PythonGrpcGenerator::Generate(const FileDescriptor* file, const grpc::string& parameter, GeneratorContext* context, @@ -780,28 +806,15 @@ bool PythonGrpcGenerator::Generate(const FileDescriptor* file, } PrivateGenerator generator(config_, file); - - std::unique_ptr<ZeroCopyOutputStream> pb2_output( - context->OpenForAppend(pb2_file_name)); - std::unique_ptr<ZeroCopyOutputStream> grpc_output( - context->Open(pb2_grpc_file_name)); - CodedOutputStream pb2_coded_out(pb2_output.get()); - CodedOutputStream grpc_coded_out(grpc_output.get()); - bool success = false; - grpc::string pb2_code; - grpc::string grpc_code; - generator.generate_in_pb2_grpc = false; - tie(success, pb2_code) = generator.GetGrpcServices(); - if (success) { - generator.generate_in_pb2_grpc = true; - tie(success, grpc_code) = generator.GetGrpcServices(); - if (success) { - pb2_coded_out.WriteRaw(pb2_code.data(), pb2_code.size()); - grpc_coded_out.WriteRaw(grpc_code.data(), grpc_code.size()); - return true; - } + if (parameter == "grpc_2_0") { + return GenerateGrpc(context, generator, pb2_grpc_file_name, true); + } else if (parameter == "") { + return GenerateGrpc(context, generator, pb2_grpc_file_name, true) && + GenerateGrpc(context, generator, pb2_file_name, false); + } else { + *error = "Invalid parameter '" + parameter + "'."; + return false; } - return false; } } // namespace grpc_python_generator diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c index 1fcff4388a..4b3d8951d7 100644 --- a/src/core/ext/client_channel/client_channel.c +++ b/src/core/ext/client_channel/client_channel.c @@ -683,9 +683,15 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, "Failed to create subchannel", &error, 1)); } else if (GET_CALL(calld) == CANCELLED_CALL) { /* already cancelled before subchannel became ready */ - fail_locked(exec_ctx, calld, - GRPC_ERROR_CREATE_REFERENCING( - "Cancelled before creating subchannel", &error, 1)); + grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING( + "Cancelled before creating subchannel", &error, 1); + /* if due to deadline, attach the deadline exceeded status to the error */ + if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) { + cancellation_error = + grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_DEADLINE_EXCEEDED); + } + fail_locked(exec_ctx, calld, cancellation_error); } else { /* Create call on subchannel. */ grpc_subchannel_call *subchannel_call = NULL; @@ -809,7 +815,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY; } } - // TODO(dgq): make this deadline configurable somehow. const grpc_lb_policy_pick_args inputs = { initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem, gpr_inf_future(GPR_CLOCK_MONOTONIC)}; diff --git a/src/core/ext/client_channel/http_connect_handshaker.c b/src/core/ext/client_channel/http_connect_handshaker.c index 82042897b2..572af52dfd 100644 --- a/src/core/ext/client_channel/http_connect_handshaker.c +++ b/src/core/ext/client_channel/http_connect_handshaker.c @@ -41,9 +41,9 @@ #include <grpc/support/string_util.h> #include "src/core/ext/client_channel/uri_parser.h" +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" -#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/support/env.h" typedef struct http_connect_handshaker { @@ -53,27 +53,38 @@ typedef struct http_connect_handshaker { char* proxy_server; char* server_name; + gpr_refcount refcount; + gpr_mu mu; + + bool shutdown; + // Endpoint and read buffer to destroy after a shutdown. + grpc_endpoint* endpoint_to_destroy; + grpc_slice_buffer* read_buffer_to_destroy; + // State saved while performing the handshake. - grpc_endpoint* endpoint; - grpc_channel_args* args; - grpc_handshaker_done_cb cb; - void* user_data; + grpc_handshaker_args* args; + grpc_closure* on_handshake_done; // Objects for processing the HTTP CONNECT request and response. grpc_slice_buffer write_buffer; - grpc_slice_buffer* read_buffer; // Ownership passes through this object. grpc_closure request_done_closure; grpc_closure response_read_closure; grpc_http_parser http_parser; grpc_http_response http_response; - grpc_timer timeout_timer; - - gpr_refcount refcount; } http_connect_handshaker; // Unref and clean up handshaker. -static void http_connect_handshaker_unref(http_connect_handshaker* handshaker) { +static void http_connect_handshaker_unref(grpc_exec_ctx* exec_ctx, + http_connect_handshaker* handshaker) { if (gpr_unref(&handshaker->refcount)) { + gpr_mu_destroy(&handshaker->mu); + if (handshaker->endpoint_to_destroy != NULL) { + grpc_endpoint_destroy(exec_ctx, handshaker->endpoint_to_destroy); + } + if (handshaker->read_buffer_to_destroy != NULL) { + grpc_slice_buffer_destroy(handshaker->read_buffer_to_destroy); + gpr_free(handshaker->read_buffer_to_destroy); + } gpr_free(handshaker->proxy_server); gpr_free(handshaker->server_name); grpc_slice_buffer_destroy(&handshaker->write_buffer); @@ -83,28 +94,64 @@ static void http_connect_handshaker_unref(http_connect_handshaker* handshaker) { } } -// Callback invoked when deadline is exceeded. -static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - http_connect_handshaker* handshaker = arg; - if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled. - grpc_endpoint_shutdown(exec_ctx, handshaker->endpoint); +// Set args fields to NULL, saving the endpoint and read buffer for +// later destruction. +static void cleanup_args_for_failure_locked( + http_connect_handshaker* handshaker) { + handshaker->endpoint_to_destroy = handshaker->args->endpoint; + handshaker->args->endpoint = NULL; + handshaker->read_buffer_to_destroy = handshaker->args->read_buffer; + handshaker->args->read_buffer = NULL; + grpc_channel_args_destroy(handshaker->args->args); + handshaker->args->args = NULL; +} + +// If the handshake failed or we're shutting down, clean up and invoke the +// callback with the error. +static void handshake_failed_locked(grpc_exec_ctx* exec_ctx, + http_connect_handshaker* handshaker, + grpc_error* error) { + if (error == GRPC_ERROR_NONE) { + // If we were shut down after an endpoint operation succeeded but + // before the endpoint callback was invoked, we need to generate our + // own error. + error = GRPC_ERROR_CREATE("Handshaker shutdown"); } - http_connect_handshaker_unref(handshaker); + if (!handshaker->shutdown) { + // TODO(ctiller): It is currently necessary to shutdown endpoints + // before destroying them, even if we know that there are no + // pending read/write callbacks. This should be fixed, at which + // point this can be removed. + grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint); + // Not shutting down, so the handshake failed. Clean up before + // invoking the callback. + cleanup_args_for_failure_locked(handshaker); + // Set shutdown to true so that subsequent calls to + // http_connect_handshaker_shutdown() do nothing. + handshaker->shutdown = true; + } + // Invoke callback. + grpc_exec_ctx_sched(exec_ctx, handshaker->on_handshake_done, error, NULL); } // Callback invoked when finished writing HTTP CONNECT request. static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { http_connect_handshaker* handshaker = arg; - if (error != GRPC_ERROR_NONE) { - // If the write failed, invoke the callback immediately with the error. - handshaker->cb(exec_ctx, handshaker->endpoint, handshaker->args, - handshaker->read_buffer, handshaker->user_data, - GRPC_ERROR_REF(error)); + gpr_mu_lock(&handshaker->mu); + if (error != GRPC_ERROR_NONE || handshaker->shutdown) { + // If the write failed or we're shutting down, clean up and invoke the + // callback with the error. + handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error)); + gpr_mu_unlock(&handshaker->mu); + http_connect_handshaker_unref(exec_ctx, handshaker); } else { // Otherwise, read the response. - grpc_endpoint_read(exec_ctx, handshaker->endpoint, handshaker->read_buffer, + // The read callback inherits our ref to the handshaker. + grpc_endpoint_read(exec_ctx, handshaker->args->endpoint, + handshaker->args->read_buffer, &handshaker->response_read_closure); + gpr_mu_unlock(&handshaker->mu); } } @@ -112,36 +159,40 @@ static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { http_connect_handshaker* handshaker = arg; - if (error != GRPC_ERROR_NONE) { - GRPC_ERROR_REF(error); // Take ref to pass to the handshake-done callback. + gpr_mu_lock(&handshaker->mu); + if (error != GRPC_ERROR_NONE || handshaker->shutdown) { + // If the read failed or we're shutting down, clean up and invoke the + // callback with the error. + handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error)); goto done; } // Add buffer to parser. - for (size_t i = 0; i < handshaker->read_buffer->count; ++i) { - if (GRPC_SLICE_LENGTH(handshaker->read_buffer->slices[i]) > 0) { + for (size_t i = 0; i < handshaker->args->read_buffer->count; ++i) { + if (GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i]) > 0) { size_t body_start_offset = 0; error = grpc_http_parser_parse(&handshaker->http_parser, - handshaker->read_buffer->slices[i], + handshaker->args->read_buffer->slices[i], &body_start_offset); - if (error != GRPC_ERROR_NONE) goto done; + if (error != GRPC_ERROR_NONE) { + handshake_failed_locked(exec_ctx, handshaker, error); + goto done; + } if (handshaker->http_parser.state == GRPC_HTTP_BODY) { - // We've gotten back a successul response, so stop the timeout timer. - grpc_timer_cancel(exec_ctx, &handshaker->timeout_timer); // Remove the data we've already read from the read buffer, // leaving only the leftover bytes (if any). grpc_slice_buffer tmp_buffer; grpc_slice_buffer_init(&tmp_buffer); if (body_start_offset < - GRPC_SLICE_LENGTH(handshaker->read_buffer->slices[i])) { + GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i])) { grpc_slice_buffer_add( &tmp_buffer, - grpc_slice_split_tail(&handshaker->read_buffer->slices[i], + grpc_slice_split_tail(&handshaker->args->read_buffer->slices[i], body_start_offset)); } grpc_slice_buffer_addn(&tmp_buffer, - &handshaker->read_buffer->slices[i + 1], - handshaker->read_buffer->count - i - 1); - grpc_slice_buffer_swap(handshaker->read_buffer, &tmp_buffer); + &handshaker->args->read_buffer->slices[i + 1], + handshaker->args->read_buffer->count - i - 1); + grpc_slice_buffer_swap(handshaker->args->read_buffer, &tmp_buffer); grpc_slice_buffer_destroy(&tmp_buffer); break; } @@ -159,9 +210,11 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, // complete (e.g., handling chunked transfer encoding or looking // at the Content-Length: header). if (handshaker->http_parser.state != GRPC_HTTP_BODY) { - grpc_slice_buffer_reset_and_unref(handshaker->read_buffer); - grpc_endpoint_read(exec_ctx, handshaker->endpoint, handshaker->read_buffer, + grpc_slice_buffer_reset_and_unref(handshaker->args->read_buffer); + grpc_endpoint_read(exec_ctx, handshaker->args->endpoint, + handshaker->args->read_buffer, &handshaker->response_read_closure); + gpr_mu_unlock(&handshaker->mu); return; } // Make sure we got a 2xx response. @@ -172,11 +225,17 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, handshaker->http_response.status); error = GRPC_ERROR_CREATE(msg); gpr_free(msg); + handshake_failed_locked(exec_ctx, handshaker, error); + goto done; } + // Success. Invoke handshake-done callback. + grpc_exec_ctx_sched(exec_ctx, handshaker->on_handshake_done, error, NULL); done: - // Invoke handshake-done callback. - handshaker->cb(exec_ctx, handshaker->endpoint, handshaker->args, - handshaker->read_buffer, handshaker->user_data, error); + // Set shutdown to true so that subsequent calls to + // http_connect_handshaker_shutdown() do nothing. + handshaker->shutdown = true; + gpr_mu_unlock(&handshaker->mu); + http_connect_handshaker_unref(exec_ctx, handshaker); } // @@ -186,25 +245,30 @@ done: static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker_in) { http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; - http_connect_handshaker_unref(handshaker); + http_connect_handshaker_unref(exec_ctx, handshaker); } static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, - grpc_handshaker* handshaker) {} + grpc_handshaker* handshaker_in) { + http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; + gpr_mu_lock(&handshaker->mu); + if (!handshaker->shutdown) { + handshaker->shutdown = true; + grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint); + cleanup_args_for_failure_locked(handshaker); + } + gpr_mu_unlock(&handshaker->mu); +} static void http_connect_handshaker_do_handshake( grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker_in, - grpc_endpoint* endpoint, grpc_channel_args* args, - grpc_slice_buffer* read_buffer, gpr_timespec deadline, - grpc_tcp_server_acceptor* acceptor, grpc_handshaker_done_cb cb, - void* user_data) { + grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, + grpc_handshaker_args* args) { http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; + gpr_mu_lock(&handshaker->mu); // Save state in the handshaker object. - handshaker->endpoint = endpoint; handshaker->args = args; - handshaker->cb = cb; - handshaker->user_data = user_data; - handshaker->read_buffer = read_buffer; + handshaker->on_handshake_done = on_handshake_done; // Send HTTP CONNECT request. gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", handshaker->server_name, handshaker->proxy_server); @@ -216,16 +280,14 @@ static void http_connect_handshaker_do_handshake( request.handshaker = &grpc_httpcli_plaintext; grpc_slice request_slice = grpc_httpcli_format_connect_request(&request); grpc_slice_buffer_add(&handshaker->write_buffer, request_slice); - grpc_endpoint_write(exec_ctx, endpoint, &handshaker->write_buffer, - &handshaker->request_done_closure); - // Set timeout timer. The timer gets a reference to the handshaker. + // Take a new ref to be held by the write callback. gpr_ref(&handshaker->refcount); - grpc_timer_init(exec_ctx, &handshaker->timeout_timer, - gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), - on_timeout, handshaker, gpr_now(GPR_CLOCK_MONOTONIC)); + grpc_endpoint_write(exec_ctx, args->endpoint, &handshaker->write_buffer, + &handshaker->request_done_closure); + gpr_mu_unlock(&handshaker->mu); } -static const struct grpc_handshaker_vtable http_connect_handshaker_vtable = { +static const grpc_handshaker_vtable http_connect_handshaker_vtable = { http_connect_handshaker_destroy, http_connect_handshaker_shutdown, http_connect_handshaker_do_handshake}; @@ -233,10 +295,11 @@ grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server, const char* server_name) { GPR_ASSERT(proxy_server != NULL); GPR_ASSERT(server_name != NULL); - http_connect_handshaker* handshaker = - gpr_malloc(sizeof(http_connect_handshaker)); + http_connect_handshaker* handshaker = gpr_malloc(sizeof(*handshaker)); memset(handshaker, 0, sizeof(*handshaker)); grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base); + gpr_mu_init(&handshaker->mu); + gpr_ref_init(&handshaker->refcount, 1); handshaker->proxy_server = gpr_strdup(proxy_server); handshaker->server_name = gpr_strdup(server_name); grpc_slice_buffer_init(&handshaker->write_buffer); @@ -246,7 +309,6 @@ grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server, handshaker); grpc_http_parser_init(&handshaker->http_parser, GRPC_HTTP_RESPONSE, &handshaker->http_response); - gpr_ref_init(&handshaker->refcount, 1); return &handshaker->base; } diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c index a148b2a0e1..08632079d6 100644 --- a/src/core/ext/client_channel/subchannel.c +++ b/src/core/ext/client_channel/subchannel.c @@ -119,9 +119,9 @@ struct grpc_subchannel { gpr_mu mu; /** have we seen a disconnection? */ - int disconnected; + bool disconnected; /** are we connecting */ - int connecting; + bool connecting; /** connectivity state tracking */ grpc_connectivity_state_tracker state_tracker; @@ -132,7 +132,9 @@ struct grpc_subchannel { /** backoff state */ gpr_backoff backoff_state; /** do we have an active alarm? */ - int have_alarm; + bool have_alarm; + /** have we started the backoff loop */ + bool backoff_begun; /** our alarm */ grpc_timer alarm; }; @@ -264,7 +266,7 @@ static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { grpc_subchannel_index_unregister(exec_ctx, c->key, c); gpr_mu_lock(&c->mu); GPR_ASSERT(!c->disconnected); - c->disconnected = 1; + c->disconnected = true; grpc_connector_shutdown(exec_ctx, c->connector); con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); if (con != NULL) { @@ -334,16 +336,18 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, int initial_backoff_ms = GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000; int max_backoff_ms = GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000; + int min_backoff_ms = GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS * 1000; bool fixed_reconnect_backoff = false; if (c->args) { for (size_t i = 0; i < c->args->num_args; i++) { if (0 == strcmp(c->args->args[i].key, - "grpc.testing.fixed_reconnect_backoff")) { + "grpc.testing.fixed_reconnect_backoff_ms")) { GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER); fixed_reconnect_backoff = true; - initial_backoff_ms = max_backoff_ms = grpc_channel_arg_get_integer( - &c->args->args[i], - (grpc_integer_options){initial_backoff_ms, 100, INT_MAX}); + initial_backoff_ms = min_backoff_ms = max_backoff_ms = + grpc_channel_arg_get_integer( + &c->args->args[i], + (grpc_integer_options){initial_backoff_ms, 100, INT_MAX}); } else if (0 == strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) { fixed_reconnect_backoff = false; @@ -360,17 +364,18 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, } } gpr_backoff_init( - &c->backoff_state, + &c->backoff_state, initial_backoff_ms, fixed_reconnect_backoff ? 1.0 : GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER, fixed_reconnect_backoff ? 0.0 : GRPC_SUBCHANNEL_RECONNECT_JITTER, - initial_backoff_ms, max_backoff_ms); + min_backoff_ms, max_backoff_ms); gpr_mu_init(&c->mu); return grpc_subchannel_index_register(exec_ctx, key, c); } -static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { +static void continue_connect_locked(grpc_exec_ctx *exec_ctx, + grpc_subchannel *c) { grpc_connect_in_args args; args.interested_parties = c->pollset_set; @@ -386,12 +391,6 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { &c->connected); } -static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { - c->next_attempt = - gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC)); - continue_connect(exec_ctx, c); -} - grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c, grpc_error **error) { grpc_connectivity_state state; @@ -418,6 +417,73 @@ static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg, follow_up->cb(exec_ctx, follow_up->cb_arg, error); } +static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + grpc_subchannel *c = arg; + gpr_mu_lock(&c->mu); + c->have_alarm = false; + if (c->disconnected) { + error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1); + } else { + GRPC_ERROR_REF(error); + } + if (error == GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); + c->next_attempt = + gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC)); + continue_connect_locked(exec_ctx, c); + gpr_mu_unlock(&c->mu); + } else { + gpr_mu_unlock(&c->mu); + GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); + } + GRPC_ERROR_UNREF(error); +} + +static void maybe_start_connecting_locked(grpc_exec_ctx *exec_ctx, + grpc_subchannel *c) { + if (c->disconnected) { + /* Don't try to connect if we're already disconnected */ + return; + } + + if (c->connecting) { + /* Already connecting: don't restart */ + return; + } + + if (GET_CONNECTED_SUBCHANNEL(c, no_barrier) != NULL) { + /* Already connected: don't restart */ + return; + } + + if (!grpc_connectivity_state_has_watchers(&c->state_tracker)) { + /* Nobody is interested in connecting: so don't just yet */ + return; + } + + c->connecting = true; + GRPC_SUBCHANNEL_WEAK_REF(c, "connecting"); + + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + if (!c->backoff_begun) { + c->backoff_begun = true; + c->next_attempt = gpr_backoff_begin(&c->backoff_state, now); + continue_connect_locked(exec_ctx, c); + } else { + GPR_ASSERT(!c->have_alarm); + c->have_alarm = true; + gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now); + if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <= + 0) { + gpr_log(GPR_INFO, "Retry immediately"); + } else { + gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds", + time_til_next.tv_sec, time_til_next.tv_nsec); + } + grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now); + } +} + void grpc_subchannel_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_subchannel *c, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, @@ -449,13 +515,9 @@ void grpc_subchannel_notify_on_state_change( w->next = &c->root_external_state_watcher; w->prev = w->next->prev; w->next->prev = w->prev->next = w; - if (grpc_connectivity_state_notify_on_state_change( - exec_ctx, &c->state_tracker, state, &w->closure)) { - c->connecting = 1; - /* released by connection */ - GRPC_SUBCHANNEL_WEAK_REF(c, "connecting"); - start_connect(exec_ctx, c); - } + grpc_connectivity_state_notify_on_state_change(exec_ctx, &c->state_tracker, + state, &w->closure); + maybe_start_connecting_locked(exec_ctx, c); gpr_mu_unlock(&c->mu); } } @@ -575,12 +637,9 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx, Re-evaluate if we really need this. */ gpr_atm_full_barrier(); GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con)); - c->connecting = 0; /* setup subchannel watching connected subchannel for changes; subchannel - ref - for connecting is donated - to the state watcher */ + ref for connecting is donated to the state watcher */ GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); grpc_connected_subchannel_notify_on_state_change( @@ -592,28 +651,6 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx, GRPC_ERROR_NONE, "connected"); } -static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_subchannel *c = arg; - gpr_mu_lock(&c->mu); - c->have_alarm = 0; - if (c->disconnected) { - error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1); - } else { - GRPC_ERROR_REF(error); - } - if (error == GRPC_ERROR_NONE) { - gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); - c->next_attempt = - gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC)); - continue_connect(exec_ctx, c); - gpr_mu_unlock(&c->mu); - } else { - gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); - } - GRPC_ERROR_UNREF(error); -} - static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_subchannel *c = arg; @@ -621,35 +658,28 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg, GRPC_SUBCHANNEL_WEAK_REF(c, "connected"); gpr_mu_lock(&c->mu); + c->connecting = false; if (c->connecting_result.transport != NULL) { publish_transport_locked(exec_ctx, c); } else if (c->disconnected) { GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); } else { - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - GPR_ASSERT(!c->have_alarm); - c->have_alarm = 1; grpc_connectivity_state_set( exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_set_int( GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), "connect_failed"); - gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now); + const char *errmsg = grpc_error_string(error); gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <= - 0) { - gpr_log(GPR_INFO, "Retry immediately"); - } else { - gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds", - time_til_next.tv_sec, time_til_next.tv_nsec); - } - grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now); grpc_error_free_string(errmsg); + + maybe_start_connecting_locked(exec_ctx, c); + GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); } gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); + GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connected"); grpc_channel_args_destroy(delete_channel_args); } diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c index 4262d2b9a4..df0db61c22 100644 --- a/src/core/ext/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -123,10 +123,11 @@ #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/static_metadata.h" -#define BACKOFF_MULTIPLIER 1.6 -#define BACKOFF_JITTER 0.2 -#define BACKOFF_MIN_SECONDS 10 -#define BACKOFF_MAX_SECONDS 60 +#define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20 +#define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1 +#define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6 +#define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120 +#define GRPC_GRPCLB_RECONNECT_JITTER 0.2 int grpc_lb_glb_trace = 0; @@ -1107,9 +1108,12 @@ static void lb_call_init_locked(glb_lb_policy *glb_policy) { grpc_closure_init(&glb_policy->lb_on_response_received, lb_on_response_received, glb_policy); - gpr_backoff_init(&glb_policy->lb_call_backoff_state, BACKOFF_MULTIPLIER, - BACKOFF_JITTER, BACKOFF_MIN_SECONDS * 1000, - BACKOFF_MAX_SECONDS * 1000); + gpr_backoff_init(&glb_policy->lb_call_backoff_state, + GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS, + GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER, + GRPC_GRPCLB_RECONNECT_JITTER, + GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000, + GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000); } static void lb_call_destroy_locked(glb_lb_policy *glb_policy) { diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c index 665439f360..15476f5792 100644 --- a/src/core/ext/resolver/dns/native/dns_resolver.c +++ b/src/core/ext/resolver/dns/native/dns_resolver.c @@ -46,10 +46,11 @@ #include "src/core/lib/support/backoff.h" #include "src/core/lib/support/string.h" -#define BACKOFF_MULTIPLIER 1.6 -#define BACKOFF_JITTER 0.2 -#define BACKOFF_MIN_SECONDS 1 -#define BACKOFF_MAX_SECONDS 120 +#define GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS 1 +#define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1 +#define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6 +#define GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS 120 +#define GRPC_DNS_RECONNECT_JITTER 0.2 typedef struct { /** base class: must be first */ @@ -269,8 +270,11 @@ static grpc_resolver *dns_create(grpc_resolver_args *args, server_name_arg.value.string = (char *)path; r->channel_args = grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1); - gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER, - BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000); + gpr_backoff_init(&r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS, + GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER, + GRPC_DNS_RECONNECT_JITTER, + GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS * 1000, + GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000); return &r->base; } diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.c b/src/core/ext/transport/chttp2/client/chttp2_connector.c new file mode 100644 index 0000000000..58a6877b9b --- /dev/null +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.c @@ -0,0 +1,269 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/ext/transport/chttp2/client/chttp2_connector.h" + +#include <grpc/grpc.h> + +#include <string.h> + +#include <grpc/slice_buffer.h> +#include <grpc/support/alloc.h> +#include <grpc/support/string_util.h> + +#include "src/core/ext/client_channel/connector.h" +#include "src/core/ext/client_channel/http_connect_handshaker.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/iomgr/tcp_client.h" +#include "src/core/lib/security/transport/security_connector.h" + +typedef struct { + grpc_connector base; + + gpr_mu mu; + gpr_refcount refs; + + bool shutdown; + bool connecting; + + char *server_name; + grpc_chttp2_add_handshakers_func add_handshakers; + void *add_handshakers_user_data; + + grpc_closure *notify; + grpc_connect_in_args args; + grpc_connect_out_args *result; + grpc_closure initial_string_sent; + grpc_slice_buffer initial_string_buffer; + + grpc_endpoint *endpoint; // Non-NULL until handshaking starts. + + grpc_closure connected; + + grpc_handshake_manager *handshake_mgr; +} chttp2_connector; + +static void chttp2_connector_ref(grpc_connector *con) { + chttp2_connector *c = (chttp2_connector *)con; + gpr_ref(&c->refs); +} + +static void chttp2_connector_unref(grpc_exec_ctx *exec_ctx, + grpc_connector *con) { + chttp2_connector *c = (chttp2_connector *)con; + if (gpr_unref(&c->refs)) { + /* c->initial_string_buffer does not need to be destroyed */ + gpr_mu_destroy(&c->mu); + // If handshaking is not yet in progress, destroy the endpoint. + // Otherwise, the handshaker will do this for us. + if (c->endpoint != NULL) grpc_endpoint_destroy(exec_ctx, c->endpoint); + gpr_free(c->server_name); + gpr_free(c); + } +} + +static void chttp2_connector_shutdown(grpc_exec_ctx *exec_ctx, + grpc_connector *con) { + chttp2_connector *c = (chttp2_connector *)con; + gpr_mu_lock(&c->mu); + c->shutdown = true; + if (c->handshake_mgr != NULL) { + grpc_handshake_manager_shutdown(exec_ctx, c->handshake_mgr); + } + // If handshaking is not yet in progress, shutdown the endpoint. + // Otherwise, the handshaker will do this for us. + if (!c->connecting && c->endpoint != NULL) { + grpc_endpoint_shutdown(exec_ctx, c->endpoint); + } + gpr_mu_unlock(&c->mu); +} + +static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_handshaker_args *args = arg; + chttp2_connector *c = args->user_data; + gpr_mu_lock(&c->mu); + if (error != GRPC_ERROR_NONE || c->shutdown) { + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_CREATE("connector shutdown"); + // We were shut down after handshaking completed successfully, so + // destroy the endpoint here. + // TODO(ctiller): It is currently necessary to shutdown endpoints + // before destroying them, even if we know that there are no + // pending read/write callbacks. This should be fixed, at which + // point this can be removed. + grpc_endpoint_shutdown(exec_ctx, args->endpoint); + grpc_endpoint_destroy(exec_ctx, args->endpoint); + grpc_channel_args_destroy(args->args); + grpc_slice_buffer_destroy(args->read_buffer); + gpr_free(args->read_buffer); + } else { + error = GRPC_ERROR_REF(error); + } + memset(c->result, 0, sizeof(*c->result)); + } else { + c->result->transport = + grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 1); + GPR_ASSERT(c->result->transport); + grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, + args->read_buffer); + c->result->channel_args = args->args; + } + grpc_closure *notify = c->notify; + c->notify = NULL; + grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); + grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); + c->handshake_mgr = NULL; + gpr_mu_unlock(&c->mu); + chttp2_connector_unref(exec_ctx, (grpc_connector *)c); +} + +static void start_handshake_locked(grpc_exec_ctx *exec_ctx, + chttp2_connector *c) { + c->handshake_mgr = grpc_handshake_manager_create(); + char *proxy_name = grpc_get_http_proxy_server(); + if (proxy_name != NULL) { + grpc_handshake_manager_add( + c->handshake_mgr, + grpc_http_connect_handshaker_create(proxy_name, c->server_name)); + gpr_free(proxy_name); + } + if (c->add_handshakers != NULL) { + c->add_handshakers(exec_ctx, c->add_handshakers_user_data, + c->handshake_mgr); + } + grpc_handshake_manager_do_handshake( + exec_ctx, c->handshake_mgr, c->endpoint, c->args.channel_args, + c->args.deadline, NULL /* acceptor */, on_handshake_done, c); + c->endpoint = NULL; // Endpoint handed off to handshake manager. +} + +static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + chttp2_connector *c = arg; + gpr_mu_lock(&c->mu); + if (error != GRPC_ERROR_NONE || c->shutdown) { + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_CREATE("connector shutdown"); + } else { + error = GRPC_ERROR_REF(error); + } + memset(c->result, 0, sizeof(*c->result)); + grpc_closure *notify = c->notify; + c->notify = NULL; + grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); + gpr_mu_unlock(&c->mu); + chttp2_connector_unref(exec_ctx, arg); + } else { + start_handshake_locked(exec_ctx, c); + gpr_mu_unlock(&c->mu); + } +} + +static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + chttp2_connector *c = arg; + gpr_mu_lock(&c->mu); + GPR_ASSERT(c->connecting); + c->connecting = false; + if (error != GRPC_ERROR_NONE || c->shutdown) { + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_CREATE("connector shutdown"); + } else { + error = GRPC_ERROR_REF(error); + } + memset(c->result, 0, sizeof(*c->result)); + grpc_closure *notify = c->notify; + c->notify = NULL; + grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); + if (c->endpoint != NULL) grpc_endpoint_shutdown(exec_ctx, c->endpoint); + gpr_mu_unlock(&c->mu); + chttp2_connector_unref(exec_ctx, arg); + } else { + GPR_ASSERT(c->endpoint != NULL); + if (!GRPC_SLICE_IS_EMPTY(c->args.initial_connect_string)) { + grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, + c); + grpc_slice_buffer_init(&c->initial_string_buffer); + grpc_slice_buffer_add(&c->initial_string_buffer, + c->args.initial_connect_string); + grpc_endpoint_write(exec_ctx, c->endpoint, &c->initial_string_buffer, + &c->initial_string_sent); + } else { + start_handshake_locked(exec_ctx, c); + } + gpr_mu_unlock(&c->mu); + } +} + +static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx, + grpc_connector *con, + const grpc_connect_in_args *args, + grpc_connect_out_args *result, + grpc_closure *notify) { + chttp2_connector *c = (chttp2_connector *)con; + gpr_mu_lock(&c->mu); + GPR_ASSERT(c->notify == NULL); + c->notify = notify; + c->args = *args; + c->result = result; + GPR_ASSERT(c->endpoint == NULL); + chttp2_connector_ref(con); // Ref taken for callback. + grpc_closure_init(&c->connected, connected, c); + GPR_ASSERT(!c->connecting); + c->connecting = true; + grpc_tcp_client_connect(exec_ctx, &c->connected, &c->endpoint, + args->interested_parties, args->channel_args, + args->addr, args->deadline); + gpr_mu_unlock(&c->mu); +} + +static const grpc_connector_vtable chttp2_connector_vtable = { + chttp2_connector_ref, chttp2_connector_unref, chttp2_connector_shutdown, + chttp2_connector_connect}; + +grpc_connector *grpc_chttp2_connector_create( + grpc_exec_ctx *exec_ctx, const char *server_name, + grpc_chttp2_add_handshakers_func add_handshakers, + void *add_handshakers_user_data) { + chttp2_connector *c = gpr_malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + c->base.vtable = &chttp2_connector_vtable; + gpr_mu_init(&c->mu); + gpr_ref_init(&c->refs, 1); + c->server_name = gpr_strdup(server_name); + c->add_handshakers = add_handshakers; + c->add_handshakers_user_data = add_handshakers_user_data; + return &c->base; +} diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.h b/src/core/ext/transport/chttp2/client/chttp2_connector.h new file mode 100644 index 0000000000..c57fb1a9a0 --- /dev/null +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.h @@ -0,0 +1,52 @@ +/* + * + * 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. + * + */ + +#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H +#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H + +#include "src/core/ext/client_channel/connector.h" +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/iomgr/exec_ctx.h" + +typedef void (*grpc_chttp2_add_handshakers_func)( + grpc_exec_ctx* exec_ctx, void* user_data, + grpc_handshake_manager* handshake_mgr); + +/// If \a add_handshakers is non-NULL, it will be called with +/// \a add_handshakers_user_data to add handshakers. +grpc_connector* grpc_chttp2_connector_create( + grpc_exec_ctx* exec_ctx, const char* server_name, + grpc_chttp2_add_handshakers_func add_handshakers, + void* add_handshakers_user_data); + +#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_CHTTP2_CONNECTOR_H */ diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c index 8e03fd82c1..89501c5905 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c @@ -33,138 +33,17 @@ #include <grpc/grpc.h> -#include <stdlib.h> #include <string.h> -#include <grpc/slice.h> -#include <grpc/slice_buffer.h> #include <grpc/support/alloc.h> +#include <grpc/support/string_util.h> #include "src/core/ext/client_channel/client_channel.h" -#include "src/core/ext/client_channel/http_connect_handshaker.h" #include "src/core/ext/client_channel/resolver_registry.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/compress_filter.h" -#include "src/core/lib/channel/handshaker.h" -#include "src/core/lib/channel/http_client_filter.h" -#include "src/core/lib/iomgr/tcp_client.h" +#include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" -// -// connector -// - -typedef struct { - grpc_connector base; - gpr_refcount refs; - - grpc_closure *notify; - grpc_connect_in_args args; - grpc_connect_out_args *result; - grpc_closure initial_string_sent; - grpc_slice_buffer initial_string_buffer; - - grpc_endpoint *tcp; - - grpc_closure connected; - - grpc_handshake_manager *handshake_mgr; -} connector; - -static void connector_ref(grpc_connector *con) { - connector *c = (connector *)con; - gpr_ref(&c->refs); -} - -static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { - connector *c = (connector *)con; - if (gpr_unref(&c->refs)) { - /* c->initial_string_buffer does not need to be destroyed */ - grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); - gpr_free(c); - } -} - -static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - connector_unref(exec_ctx, arg); -} - -static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, - grpc_channel_args *args, - grpc_slice_buffer *read_buffer, void *user_data, - grpc_error *error) { - connector *c = user_data; - if (error != GRPC_ERROR_NONE) { - grpc_channel_args_destroy(args); - gpr_free(read_buffer); - } else { - c->result->transport = - grpc_create_chttp2_transport(exec_ctx, args, endpoint, 1); - GPR_ASSERT(c->result->transport); - grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, - read_buffer); - c->result->channel_args = args; - } - grpc_closure *notify = c->notify; - c->notify = NULL; - grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); -} - -static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - connector *c = arg; - grpc_endpoint *tcp = c->tcp; - if (tcp != NULL) { - if (!GRPC_SLICE_IS_EMPTY(c->args.initial_connect_string)) { - grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, - c); - grpc_slice_buffer_init(&c->initial_string_buffer); - grpc_slice_buffer_add(&c->initial_string_buffer, - c->args.initial_connect_string); - connector_ref(arg); - grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, - &c->initial_string_sent); - } else { - grpc_handshake_manager_do_handshake( - exec_ctx, c->handshake_mgr, tcp, c->args.channel_args, - c->args.deadline, NULL /* acceptor */, on_handshake_done, c); - } - } else { - memset(c->result, 0, sizeof(*c->result)); - grpc_closure *notify = c->notify; - c->notify = NULL; - grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL); - } -} - -static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {} - -static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con, - const grpc_connect_in_args *args, - grpc_connect_out_args *result, - grpc_closure *notify) { - connector *c = (connector *)con; - GPR_ASSERT(c->notify == NULL); - GPR_ASSERT(notify->cb); - c->notify = notify; - c->args = *args; - c->result = result; - c->tcp = NULL; - grpc_closure_init(&c->connected, connected, c); - grpc_tcp_client_connect(exec_ctx, &c->connected, &c->tcp, - args->interested_parties, args->channel_args, - args->addr, args->deadline); -} - -static const grpc_connector_vtable connector_vtable = { - connector_ref, connector_unref, connector_shutdown, connector_connect}; - -// -// client_channel_factory -// - static void client_channel_factory_ref( grpc_client_channel_factory *cc_factory) {} @@ -174,20 +53,11 @@ static void client_channel_factory_unref( static grpc_subchannel *client_channel_factory_create_subchannel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const grpc_subchannel_args *args) { - connector *c = gpr_malloc(sizeof(*c)); - memset(c, 0, sizeof(*c)); - c->base.vtable = &connector_vtable; - gpr_ref_init(&c->refs, 1); - c->handshake_mgr = grpc_handshake_manager_create(); - char *proxy_name = grpc_get_http_proxy_server(); - if (proxy_name != NULL) { - grpc_handshake_manager_add( - c->handshake_mgr, - grpc_http_connect_handshaker_create(proxy_name, args->server_name)); - gpr_free(proxy_name); - } - grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args); - grpc_connector_unref(exec_ctx, &c->base); + grpc_connector *connector = grpc_chttp2_connector_create( + exec_ctx, args->server_name, NULL /* add_handshakers */, + NULL /* user_data */); + grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args); + grpc_connector_unref(exec_ctx, connector); return s; } @@ -198,16 +68,14 @@ static grpc_channel *client_channel_factory_create_channel( grpc_channel *channel = grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL); grpc_resolver *resolver = grpc_resolver_create(target, args); - if (!resolver) { + if (resolver == NULL) { GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "client_channel_factory_create_channel"); return NULL; } - grpc_client_channel_finish_initialization( exec_ctx, grpc_channel_get_channel_stack(channel), resolver, cc_factory); GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel"); - return channel; } @@ -230,16 +98,13 @@ grpc_channel *grpc_insecure_channel_create(const char *target, GRPC_API_TRACE( "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3, (target, args, reserved)); - GPR_ASSERT(!reserved); - + GPR_ASSERT(reserved == NULL); grpc_client_channel_factory *factory = (grpc_client_channel_factory *)&client_channel_factory; grpc_channel *channel = client_channel_factory_create_channel( &exec_ctx, factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, args); - grpc_client_channel_factory_unref(&exec_ctx, factory); grpc_exec_ctx_finish(&exec_ctx); - return channel != NULL ? channel : grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create client channel"); diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 04c88a2d36..4bce3ba25f 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -33,196 +33,19 @@ #include <grpc/grpc.h> -#include <stdlib.h> #include <string.h> -#include <grpc/slice.h> -#include <grpc/slice_buffer.h> #include <grpc/support/alloc.h> +#include <grpc/support/string_util.h> #include "src/core/ext/client_channel/client_channel.h" -#include "src/core/ext/client_channel/http_connect_handshaker.h" #include "src/core/ext/client_channel/resolver_registry.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/handshaker.h" -#include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/security/transport/auth_filters.h" +#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" -#include "src/core/lib/tsi/transport_security_interface.h" - -// -// connector -// - -typedef struct { - grpc_connector base; - gpr_refcount refs; - - grpc_channel_security_connector *security_connector; - - grpc_closure *notify; - grpc_connect_in_args args; - grpc_connect_out_args *result; - grpc_closure initial_string_sent; - grpc_slice_buffer initial_string_buffer; - - gpr_mu mu; - grpc_endpoint *connecting_endpoint; - grpc_endpoint *newly_connecting_endpoint; - - grpc_closure connected_closure; - - grpc_handshake_manager *handshake_mgr; - - // TODO(roth): Remove once we eliminate on_secure_handshake_done(). - grpc_channel_args *tmp_args; -} connector; - -static void connector_ref(grpc_connector *con) { - connector *c = (connector *)con; - gpr_ref(&c->refs); -} - -static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { - connector *c = (connector *)con; - if (gpr_unref(&c->refs)) { - /* c->initial_string_buffer does not need to be destroyed */ - grpc_channel_args_destroy(c->tmp_args); - grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); - gpr_free(c); - } -} - -static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, - grpc_security_status status, - grpc_endpoint *secure_endpoint, - grpc_auth_context *auth_context) { - connector *c = arg; - gpr_mu_lock(&c->mu); - grpc_error *error = GRPC_ERROR_NONE; - if (c->connecting_endpoint == NULL) { - memset(c->result, 0, sizeof(*c->result)); - gpr_mu_unlock(&c->mu); - } else if (status != GRPC_SECURITY_OK) { - error = grpc_error_set_int(GRPC_ERROR_CREATE("Secure handshake failed"), - GRPC_ERROR_INT_SECURITY_STATUS, status); - memset(c->result, 0, sizeof(*c->result)); - c->connecting_endpoint = NULL; - gpr_mu_unlock(&c->mu); - } else { - grpc_arg auth_context_arg; - c->connecting_endpoint = NULL; - gpr_mu_unlock(&c->mu); - c->result->transport = grpc_create_chttp2_transport( - exec_ctx, c->args.channel_args, secure_endpoint, 1); - grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL); - auth_context_arg = grpc_auth_context_to_arg(auth_context); - c->result->channel_args = - grpc_channel_args_copy_and_add(c->tmp_args, &auth_context_arg, 1); - } - grpc_closure *notify = c->notify; - c->notify = NULL; - grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); -} - -static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, - grpc_channel_args *args, - grpc_slice_buffer *read_buffer, void *user_data, - grpc_error *error) { - connector *c = user_data; - c->tmp_args = args; - if (error != GRPC_ERROR_NONE) { - gpr_free(read_buffer); - grpc_closure *notify = c->notify; - c->notify = NULL; - grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); - } else { - // TODO(roth, jboeuf): Convert security connector handshaking to use new - // handshake API, and then move the code from on_secure_handshake_done() - // into this function. - grpc_channel_security_connector_do_handshake( - exec_ctx, c->security_connector, endpoint, read_buffer, - c->args.deadline, on_secure_handshake_done, c); - } -} - -static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - connector *c = arg; - grpc_handshake_manager_do_handshake( - exec_ctx, c->handshake_mgr, c->connecting_endpoint, c->args.channel_args, - c->args.deadline, NULL /* acceptor */, on_handshake_done, c); -} - -static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - connector *c = arg; - grpc_endpoint *tcp = c->newly_connecting_endpoint; - if (tcp != NULL) { - gpr_mu_lock(&c->mu); - GPR_ASSERT(c->connecting_endpoint == NULL); - c->connecting_endpoint = tcp; - gpr_mu_unlock(&c->mu); - if (!GRPC_SLICE_IS_EMPTY(c->args.initial_connect_string)) { - grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, - c); - grpc_slice_buffer_init(&c->initial_string_buffer); - grpc_slice_buffer_add(&c->initial_string_buffer, - c->args.initial_connect_string); - grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, - &c->initial_string_sent); - } else { - grpc_handshake_manager_do_handshake( - exec_ctx, c->handshake_mgr, tcp, c->args.channel_args, - c->args.deadline, NULL /* acceptor */, on_handshake_done, c); - } - } else { - memset(c->result, 0, sizeof(*c->result)); - grpc_closure *notify = c->notify; - c->notify = NULL; - grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL); - } -} - -static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) { - connector *c = (connector *)con; - grpc_endpoint *ep; - gpr_mu_lock(&c->mu); - ep = c->connecting_endpoint; - c->connecting_endpoint = NULL; - gpr_mu_unlock(&c->mu); - if (ep) { - grpc_endpoint_shutdown(exec_ctx, ep); - } -} - -static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con, - const grpc_connect_in_args *args, - grpc_connect_out_args *result, - grpc_closure *notify) { - connector *c = (connector *)con; - GPR_ASSERT(c->notify == NULL); - c->notify = notify; - c->args = *args; - c->result = result; - gpr_mu_lock(&c->mu); - GPR_ASSERT(c->connecting_endpoint == NULL); - gpr_mu_unlock(&c->mu); - grpc_closure_init(&c->connected_closure, connected, c); - grpc_tcp_client_connect( - exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint, - args->interested_parties, args->channel_args, args->addr, args->deadline); -} - -static const grpc_connector_vtable connector_vtable = { - connector_ref, connector_unref, connector_shutdown, connector_connect}; - -// -// client_channel_factory -// typedef struct { grpc_client_channel_factory base; @@ -246,26 +69,20 @@ static void client_channel_factory_unref( } } +static void add_handshakers(grpc_exec_ctx *exec_ctx, void *security_connector, + grpc_handshake_manager *handshake_mgr) { + grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector, + handshake_mgr); +} + static grpc_subchannel *client_channel_factory_create_subchannel( grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, const grpc_subchannel_args *args) { client_channel_factory *f = (client_channel_factory *)cc_factory; - connector *c = gpr_malloc(sizeof(*c)); - memset(c, 0, sizeof(*c)); - c->base.vtable = &connector_vtable; - c->security_connector = f->security_connector; - c->handshake_mgr = grpc_handshake_manager_create(); - char *proxy_name = grpc_get_http_proxy_server(); - if (proxy_name != NULL) { - grpc_handshake_manager_add( - c->handshake_mgr, - grpc_http_connect_handshaker_create(proxy_name, args->server_name)); - gpr_free(proxy_name); - } - gpr_mu_init(&c->mu); - gpr_ref_init(&c->refs, 1); - grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args); - grpc_connector_unref(exec_ctx, &c->base); + grpc_connector *connector = grpc_chttp2_connector_create( + exec_ctx, args->server_name, add_handshakers, f->security_connector); + grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args); + grpc_connector_unref(exec_ctx, connector); return s; } @@ -277,15 +94,14 @@ static grpc_channel *client_channel_factory_create_channel( grpc_channel *channel = grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL); grpc_resolver *resolver = grpc_resolver_create(target, args); - if (resolver != NULL) { - grpc_client_channel_finish_initialization( - exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base); - GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create"); - } else { + if (resolver == NULL) { GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "client_channel_factory_create_channel"); - channel = NULL; + return NULL; } + grpc_client_channel_finish_initialization( + exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base); + GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel"); return channel; } diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.c b/src/core/ext/transport/chttp2/server/chttp2_server.c new file mode 100644 index 0000000000..f0857714fc --- /dev/null +++ b/src/core/ext/transport/chttp2/server/chttp2_server.c @@ -0,0 +1,362 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/ext/transport/chttp2/server/chttp2_server.h" + +#include <grpc/grpc.h> + +#include <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/sync.h> +#include <grpc/support/useful.h> + +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/channel/http_server_filter.h" +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/tcp_server.h" +#include "src/core/lib/surface/api_trace.h" +#include "src/core/lib/surface/server.h" + +void grpc_chttp2_server_handshaker_factory_add_handshakers( + grpc_exec_ctx *exec_ctx, + grpc_chttp2_server_handshaker_factory *handshaker_factory, + grpc_handshake_manager *handshake_mgr) { + if (handshaker_factory != NULL) { + handshaker_factory->vtable->add_handshakers(exec_ctx, handshaker_factory, + handshake_mgr); + } +} + +void grpc_chttp2_server_handshaker_factory_destroy( + grpc_exec_ctx *exec_ctx, + grpc_chttp2_server_handshaker_factory *handshaker_factory) { + if (handshaker_factory != NULL) { + handshaker_factory->vtable->destroy(exec_ctx, handshaker_factory); + } +} + +typedef struct pending_handshake_manager_node { + grpc_handshake_manager *handshake_mgr; + struct pending_handshake_manager_node *next; +} pending_handshake_manager_node; + +typedef struct { + grpc_server *server; + grpc_tcp_server *tcp_server; + grpc_channel_args *args; + grpc_chttp2_server_handshaker_factory *handshaker_factory; + gpr_mu mu; + bool shutdown; + grpc_closure tcp_server_shutdown_complete; + grpc_closure *server_destroy_listener_done; + pending_handshake_manager_node *pending_handshake_mgrs; +} server_state; + +typedef struct { + server_state *server_state; + grpc_pollset *accepting_pollset; + grpc_tcp_server_acceptor *acceptor; + grpc_handshake_manager *handshake_mgr; +} server_connection_state; + +static void pending_handshake_manager_add_locked( + server_state *state, grpc_handshake_manager *handshake_mgr) { + pending_handshake_manager_node *node = gpr_malloc(sizeof(*node)); + node->handshake_mgr = handshake_mgr; + node->next = state->pending_handshake_mgrs; + state->pending_handshake_mgrs = node; +} + +static void pending_handshake_manager_remove_locked( + server_state *state, grpc_handshake_manager *handshake_mgr) { + pending_handshake_manager_node **prev_node = &state->pending_handshake_mgrs; + for (pending_handshake_manager_node *node = state->pending_handshake_mgrs; + node != NULL; node = node->next) { + if (node->handshake_mgr == handshake_mgr) { + *prev_node = node->next; + gpr_free(node); + break; + } + prev_node = &node->next; + } +} + +static void pending_handshake_manager_shutdown_locked(grpc_exec_ctx *exec_ctx, + server_state *state) { + pending_handshake_manager_node *prev_node = NULL; + for (pending_handshake_manager_node *node = state->pending_handshake_mgrs; + node != NULL; node = node->next) { + grpc_handshake_manager_shutdown(exec_ctx, node->handshake_mgr); + gpr_free(prev_node); + prev_node = node; + } + gpr_free(prev_node); + state->pending_handshake_mgrs = NULL; +} + +static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_handshaker_args *args = arg; + server_connection_state *connection_state = args->user_data; + gpr_mu_lock(&connection_state->server_state->mu); + if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) { + const char *error_str = grpc_error_string(error); + gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); + grpc_error_free_string(error_str); + if (error == GRPC_ERROR_NONE && args->endpoint != NULL) { + // We were shut down after handshaking completed successfully, so + // destroy the endpoint here. + // TODO(ctiller): It is currently necessary to shutdown endpoints + // before destroying them, even if we know that there are no + // pending read/write callbacks. This should be fixed, at which + // point this can be removed. + grpc_endpoint_shutdown(exec_ctx, args->endpoint); + grpc_endpoint_destroy(exec_ctx, args->endpoint); + grpc_channel_args_destroy(args->args); + grpc_slice_buffer_destroy(args->read_buffer); + gpr_free(args->read_buffer); + } + } else { + // If the handshaking succeeded but there is no endpoint, then the + // handshaker may have handed off the connection to some external + // code, so we can just clean up here without creating a transport. + if (args->endpoint != NULL) { + grpc_transport *transport = + grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0); + grpc_server_setup_transport( + exec_ctx, connection_state->server_state->server, transport, + connection_state->accepting_pollset, args->args); + grpc_chttp2_transport_start_reading(exec_ctx, transport, + args->read_buffer); + grpc_channel_args_destroy(args->args); + } + } + pending_handshake_manager_remove_locked(connection_state->server_state, + connection_state->handshake_mgr); + gpr_mu_unlock(&connection_state->server_state->mu); + grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); + grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server); + gpr_free(connection_state->acceptor); + gpr_free(connection_state); +} + +static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, + grpc_pollset *accepting_pollset, + grpc_tcp_server_acceptor *acceptor) { + server_state *state = arg; + gpr_mu_lock(&state->mu); + if (state->shutdown) { + gpr_mu_unlock(&state->mu); + grpc_endpoint_destroy(exec_ctx, tcp); + gpr_free(acceptor); + return; + } + grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create(); + pending_handshake_manager_add_locked(state, handshake_mgr); + gpr_mu_unlock(&state->mu); + grpc_tcp_server_ref(state->tcp_server); + server_connection_state *connection_state = + gpr_malloc(sizeof(*connection_state)); + connection_state->server_state = state; + connection_state->accepting_pollset = accepting_pollset; + connection_state->acceptor = acceptor; + connection_state->handshake_mgr = handshake_mgr; + grpc_chttp2_server_handshaker_factory_add_handshakers( + exec_ctx, state->handshaker_factory, connection_state->handshake_mgr); + // TODO(roth): We should really get this timeout value from channel + // args instead of hard-coding it. + const gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN)); + grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr, + tcp, state->args, deadline, acceptor, + on_handshake_done, connection_state); +} + +/* Server callback: start listening on our ports */ +static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server, + void *arg, grpc_pollset **pollsets, + size_t pollset_count) { + server_state *state = arg; + gpr_mu_lock(&state->mu); + state->shutdown = false; + gpr_mu_unlock(&state->mu); + grpc_tcp_server_start(exec_ctx, state->tcp_server, pollsets, pollset_count, + on_accept, state); +} + +static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + server_state *state = arg; + /* ensure all threads have unlocked */ + gpr_mu_lock(&state->mu); + grpc_closure *destroy_done = state->server_destroy_listener_done; + GPR_ASSERT(state->shutdown); + pending_handshake_manager_shutdown_locked(exec_ctx, state); + gpr_mu_unlock(&state->mu); + // Flush queued work before destroying handshaker factory, since that + // may do a synchronous unref. + grpc_exec_ctx_flush(exec_ctx); + grpc_chttp2_server_handshaker_factory_destroy(exec_ctx, + state->handshaker_factory); + if (destroy_done != NULL) { + destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error)); + grpc_exec_ctx_flush(exec_ctx); + } + grpc_channel_args_destroy(state->args); + gpr_mu_destroy(&state->mu); + gpr_free(state); +} + +/* Server callback: destroy the tcp listener (so we don't generate further + callbacks) */ +static void server_destroy_listener(grpc_exec_ctx *exec_ctx, + grpc_server *server, void *arg, + grpc_closure *destroy_done) { + server_state *state = arg; + gpr_mu_lock(&state->mu); + state->shutdown = true; + state->server_destroy_listener_done = destroy_done; + grpc_tcp_server *tcp_server = state->tcp_server; + gpr_mu_unlock(&state->mu); + grpc_tcp_server_shutdown_listeners(exec_ctx, tcp_server); + grpc_tcp_server_unref(exec_ctx, tcp_server); +} + +grpc_error *grpc_chttp2_server_add_port( + grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr, + grpc_channel_args *args, + grpc_chttp2_server_handshaker_factory *handshaker_factory, int *port_num) { + grpc_resolved_addresses *resolved = NULL; + grpc_tcp_server *tcp_server = NULL; + size_t i; + size_t count = 0; + int port_temp; + grpc_error *err = GRPC_ERROR_NONE; + server_state *state = NULL; + grpc_error **errors = NULL; + + *port_num = -1; + + /* resolve address */ + err = grpc_blocking_resolve_address(addr, "https", &resolved); + if (err != GRPC_ERROR_NONE) { + goto error; + } + state = gpr_malloc(sizeof(*state)); + memset(state, 0, sizeof(*state)); + grpc_closure_init(&state->tcp_server_shutdown_complete, + tcp_server_shutdown_complete, state); + err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete, + args, &tcp_server); + if (err != GRPC_ERROR_NONE) { + goto error; + } + + state->server = server; + state->tcp_server = tcp_server; + state->args = args; + state->handshaker_factory = handshaker_factory; + state->shutdown = true; + gpr_mu_init(&state->mu); + + const size_t naddrs = resolved->naddrs; + errors = gpr_malloc(sizeof(*errors) * naddrs); + for (i = 0; i < naddrs; i++) { + errors[i] = + grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp); + if (errors[i] == GRPC_ERROR_NONE) { + if (*port_num == -1) { + *port_num = port_temp; + } else { + GPR_ASSERT(*port_num == port_temp); + } + count++; + } + } + if (count == 0) { + char *msg; + gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved", + naddrs); + err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs); + gpr_free(msg); + goto error; + } else if (count != naddrs) { + char *msg; + gpr_asprintf(&msg, "Only %" PRIuPTR + " addresses added out of total %" PRIuPTR " resolved", + count, naddrs); + err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs); + gpr_free(msg); + + const char *warning_message = grpc_error_string(err); + gpr_log(GPR_INFO, "WARNING: %s", warning_message); + grpc_error_free_string(warning_message); + /* we managed to bind some addresses: continue */ + } + grpc_resolved_addresses_destroy(resolved); + + /* Register with the server only upon success */ + grpc_server_add_listener(exec_ctx, server, state, server_start_listener, + server_destroy_listener); + goto done; + +/* Error path: cleanup and return */ +error: + GPR_ASSERT(err != GRPC_ERROR_NONE); + if (resolved) { + grpc_resolved_addresses_destroy(resolved); + } + if (tcp_server) { + grpc_tcp_server_unref(exec_ctx, tcp_server); + } else { + grpc_channel_args_destroy(args); + grpc_chttp2_server_handshaker_factory_destroy(exec_ctx, handshaker_factory); + gpr_free(state); + } + *port_num = 0; + +done: + if (errors != NULL) { + for (i = 0; i < naddrs; i++) { + GRPC_ERROR_UNREF(errors[i]); + } + gpr_free(errors); + } + return err; +} diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.h b/src/core/ext/transport/chttp2/server/chttp2_server.h new file mode 100644 index 0000000000..aa364b565d --- /dev/null +++ b/src/core/ext/transport/chttp2/server/chttp2_server.h @@ -0,0 +1,78 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H +#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H + +#include <grpc/impl/codegen/grpc_types.h> + +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/iomgr/exec_ctx.h" + +/// A server handshaker factory is used to create handshakers for server +/// connections. +typedef struct grpc_chttp2_server_handshaker_factory + grpc_chttp2_server_handshaker_factory; + +typedef struct { + void (*add_handshakers)( + grpc_exec_ctx *exec_ctx, + grpc_chttp2_server_handshaker_factory *handshaker_factory, + grpc_handshake_manager *handshake_mgr); + void (*destroy)(grpc_exec_ctx *exec_ctx, + grpc_chttp2_server_handshaker_factory *handshaker_factory); +} grpc_chttp2_server_handshaker_factory_vtable; + +struct grpc_chttp2_server_handshaker_factory { + const grpc_chttp2_server_handshaker_factory_vtable *vtable; +}; + +void grpc_chttp2_server_handshaker_factory_add_handshakers( + grpc_exec_ctx *exec_ctx, + grpc_chttp2_server_handshaker_factory *handshaker_factory, + grpc_handshake_manager *handshake_mgr); + +void grpc_chttp2_server_handshaker_factory_destroy( + grpc_exec_ctx *exec_ctx, + grpc_chttp2_server_handshaker_factory *handshaker_factory); + +/// Adds a port to \a server. Sets \a port_num to the port number. +/// If \a handshaker_factory is not NULL, it will be used to create +/// handshakers for the port. +/// Takes ownership of \a args and \a handshaker_factory. +grpc_error *grpc_chttp2_server_add_port( + grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr, + grpc_channel_args *args, + grpc_chttp2_server_handshaker_factory *handshaker_factory, int *port_num); + +#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */ diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c index c18d618f96..7e286d4e46 100644 --- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c @@ -33,180 +33,28 @@ #include <grpc/grpc.h> -#include <grpc/support/alloc.h> #include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/useful.h> -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/ext/transport/chttp2/server/chttp2_server.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/handshaker.h" -#include "src/core/lib/channel/http_server_filter.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" -typedef struct server_connect_state { - grpc_server *server; - grpc_pollset *accepting_pollset; - grpc_tcp_server_acceptor *acceptor; - grpc_handshake_manager *handshake_mgr; -} server_connect_state; - -static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, - grpc_channel_args *args, - grpc_slice_buffer *read_buffer, void *user_data, - grpc_error *error) { - server_connect_state *state = user_data; - if (error != GRPC_ERROR_NONE) { - const char *error_str = grpc_error_string(error); - gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); - grpc_error_free_string(error_str); - GRPC_ERROR_UNREF(error); - grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr); - gpr_free(read_buffer); - } else { - // Beware that the call to grpc_create_chttp2_transport() has to happen - // before grpc_tcp_server_destroy(). This is fine here, but similar code - // asynchronously doing a handshake instead of calling - // grpc_tcp_server_start() (as in server_secure_chttp2.c) needs to add - // synchronization to avoid this case. - grpc_transport *transport = - grpc_create_chttp2_transport(exec_ctx, args, endpoint, 0); - grpc_server_setup_transport(exec_ctx, state->server, transport, - state->accepting_pollset, - grpc_server_get_channel_args(state->server)); - grpc_chttp2_transport_start_reading(exec_ctx, transport, read_buffer); - } - // Clean up. - grpc_channel_args_destroy(args); - grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); - gpr_free(state); -} - -static void on_accept(grpc_exec_ctx *exec_ctx, void *server, grpc_endpoint *tcp, - grpc_pollset *accepting_pollset, - grpc_tcp_server_acceptor *acceptor) { - server_connect_state *state = gpr_malloc(sizeof(server_connect_state)); - state->server = server; - state->accepting_pollset = accepting_pollset; - state->acceptor = acceptor; - state->handshake_mgr = grpc_handshake_manager_create(); - // TODO(roth): We should really get this timeout value from channel - // args instead of hard-coding it. - const gpr_timespec deadline = gpr_time_add( - gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN)); - grpc_handshake_manager_do_handshake( - exec_ctx, state->handshake_mgr, tcp, grpc_server_get_channel_args(server), - deadline, acceptor, on_handshake_done, state); -} - -/* Server callback: start listening on our ports */ -static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp, - grpc_pollset **pollsets, size_t pollset_count) { - grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, on_accept, - server); -} - -/* Server callback: destroy the tcp listener (so we don't generate further - callbacks) */ -static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp, - grpc_closure *destroy_done) { - grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_shutdown_listeners(exec_ctx, tcp); - grpc_tcp_server_unref(exec_ctx, tcp); - grpc_exec_ctx_sched(exec_ctx, destroy_done, GRPC_ERROR_NONE, NULL); -} - int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) { - grpc_resolved_addresses *resolved = NULL; - grpc_tcp_server *tcp = NULL; - size_t i; - size_t count = 0; - int port_num = -1; - int port_temp; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_error *err = GRPC_ERROR_NONE; - + int port_num = 0; GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2, (server, addr)); - - grpc_error **errors = NULL; - err = grpc_blocking_resolve_address(addr, "https", &resolved); - if (err != GRPC_ERROR_NONE) { - goto error; - } - - err = grpc_tcp_server_create(&exec_ctx, NULL, - grpc_server_get_channel_args(server), &tcp); + grpc_error *err = grpc_chttp2_server_add_port( + &exec_ctx, server, addr, + grpc_channel_args_copy(grpc_server_get_channel_args(server)), + NULL /* handshaker_factory */, &port_num); if (err != GRPC_ERROR_NONE) { - goto error; - } - - const size_t naddrs = resolved->naddrs; - errors = gpr_malloc(sizeof(*errors) * naddrs); - for (i = 0; i < naddrs; i++) { - errors[i] = grpc_tcp_server_add_port(tcp, &resolved->addrs[i], &port_temp); - if (errors[i] == GRPC_ERROR_NONE) { - if (port_num == -1) { - port_num = port_temp; - } else { - GPR_ASSERT(port_num == port_temp); - } - count++; - } + const char *msg = grpc_error_string(err); + gpr_log(GPR_ERROR, "%s", msg); + grpc_error_free_string(msg); + GRPC_ERROR_UNREF(err); } - if (count == 0) { - char *msg; - gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved", - naddrs); - err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs); - gpr_free(msg); - goto error; - } else if (count != naddrs) { - char *msg; - gpr_asprintf(&msg, "Only %" PRIuPTR - " addresses added out of total %" PRIuPTR " resolved", - count, naddrs); - err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs); - gpr_free(msg); - - const char *warning_message = grpc_error_string(err); - gpr_log(GPR_INFO, "WARNING: %s", warning_message); - grpc_error_free_string(warning_message); - /* we managed to bind some addresses: continue */ - } - grpc_resolved_addresses_destroy(resolved); - - /* Register with the server only upon success */ - grpc_server_add_listener(&exec_ctx, server, tcp, start, destroy); - goto done; - -/* Error path: cleanup and return */ -error: - GPR_ASSERT(err != GRPC_ERROR_NONE); - if (resolved) { - grpc_resolved_addresses_destroy(resolved); - } - if (tcp) { - grpc_tcp_server_unref(&exec_ctx, tcp); - } - port_num = 0; - - const char *msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "%s", msg); - grpc_error_free_string(msg); - GRPC_ERROR_UNREF(err); - -done: grpc_exec_ctx_finish(&exec_ctx); - if (errors != NULL) { - for (i = 0; i < naddrs; i++) { - GRPC_ERROR_UNREF(errors[i]); - } - } - gpr_free(errors); return port_num; } diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c index 942638ad7f..a33a7a3f7d 100644 --- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c @@ -38,218 +38,63 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> -#include <grpc/support/sync.h> -#include <grpc/support/useful.h> + +#include "src/core/ext/transport/chttp2/server/chttp2_server.h" + #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" -#include "src/core/lib/channel/http_server_filter.h" -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/security/transport/auth_filters.h" -#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" -typedef struct server_secure_state { - grpc_server *server; - grpc_tcp_server *tcp; - grpc_server_security_connector *sc; - grpc_server_credentials *creds; - bool is_shutdown; - gpr_mu mu; - grpc_closure tcp_server_shutdown_complete; - grpc_closure *server_destroy_listener_done; -} server_secure_state; - -typedef struct server_secure_connect { - server_secure_state *server_state; - grpc_pollset *accepting_pollset; - grpc_tcp_server_acceptor *acceptor; - grpc_handshake_manager *handshake_mgr; - // TODO(roth): Remove the following two fields when we eliminate - // grpc_server_security_connector_do_handshake(). - gpr_timespec deadline; - grpc_channel_args *args; -} server_secure_connect; - -static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, - grpc_security_status status, - grpc_endpoint *secure_endpoint, - grpc_auth_context *auth_context) { - server_secure_connect *connection_state = statep; - if (status == GRPC_SECURITY_OK) { - if (secure_endpoint) { - gpr_mu_lock(&connection_state->server_state->mu); - if (!connection_state->server_state->is_shutdown) { - grpc_transport *transport = grpc_create_chttp2_transport( - exec_ctx, grpc_server_get_channel_args( - connection_state->server_state->server), - secure_endpoint, 0); - grpc_arg args_to_add[2]; - args_to_add[0] = grpc_server_credentials_to_arg( - connection_state->server_state->creds); - args_to_add[1] = grpc_auth_context_to_arg(auth_context); - grpc_channel_args *args_copy = grpc_channel_args_copy_and_add( - connection_state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); - grpc_server_setup_transport( - exec_ctx, connection_state->server_state->server, transport, - connection_state->accepting_pollset, args_copy); - grpc_channel_args_destroy(args_copy); - grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL); - } else { - /* We need to consume this here, because the server may already have - * gone away. */ - grpc_endpoint_destroy(exec_ctx, secure_endpoint); - } - gpr_mu_unlock(&connection_state->server_state->mu); - } - } else { - gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); - } - grpc_channel_args_destroy(connection_state->args); - grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp); - gpr_free(connection_state); -} - -static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, - grpc_channel_args *args, - grpc_slice_buffer *read_buffer, void *user_data, - grpc_error *error) { - server_secure_connect *connection_state = user_data; - if (error != GRPC_ERROR_NONE) { - const char *error_str = grpc_error_string(error); - gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); - grpc_error_free_string(error_str); - GRPC_ERROR_UNREF(error); - grpc_channel_args_destroy(args); - gpr_free(read_buffer); - grpc_handshake_manager_shutdown(exec_ctx, connection_state->handshake_mgr); - grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); - grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp); - gpr_free(connection_state); - return; - } - grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); - connection_state->handshake_mgr = NULL; - // TODO(roth, jboeuf): Convert security connector handshaking to use new - // handshake API, and then move the code from on_secure_handshake_done() - // into this function. - connection_state->args = args; - grpc_server_security_connector_do_handshake( - exec_ctx, connection_state->server_state->sc, connection_state->acceptor, - endpoint, read_buffer, connection_state->deadline, - on_secure_handshake_done, connection_state); -} - -static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp, - grpc_pollset *accepting_pollset, - grpc_tcp_server_acceptor *acceptor) { - server_secure_state *server_state = statep; - server_secure_connect *connection_state = NULL; - gpr_mu_lock(&server_state->mu); - if (server_state->is_shutdown) { - gpr_mu_unlock(&server_state->mu); - grpc_endpoint_destroy(exec_ctx, tcp); - return; - } - gpr_mu_unlock(&server_state->mu); - grpc_tcp_server_ref(server_state->tcp); - connection_state = gpr_malloc(sizeof(*connection_state)); - connection_state->server_state = server_state; - connection_state->accepting_pollset = accepting_pollset; - connection_state->acceptor = acceptor; - connection_state->handshake_mgr = grpc_handshake_manager_create(); - // TODO(roth): We should really get this timeout value from channel - // args instead of hard-coding it. - connection_state->deadline = gpr_time_add( - gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN)); - grpc_handshake_manager_do_handshake( - exec_ctx, connection_state->handshake_mgr, tcp, - grpc_server_get_channel_args(connection_state->server_state->server), - connection_state->deadline, acceptor, on_handshake_done, - connection_state); +typedef struct { + grpc_chttp2_server_handshaker_factory base; + grpc_server_security_connector *security_connector; +} server_security_handshaker_factory; + +static void server_security_handshaker_factory_add_handshakers( + grpc_exec_ctx *exec_ctx, grpc_chttp2_server_handshaker_factory *hf, + grpc_handshake_manager *handshake_mgr) { + server_security_handshaker_factory *handshaker_factory = + (server_security_handshaker_factory *)hf; + grpc_server_security_connector_add_handshakers( + exec_ctx, handshaker_factory->security_connector, handshake_mgr); } -/* Server callback: start listening on our ports */ -static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server, - void *statep, grpc_pollset **pollsets, - size_t pollset_count) { - server_secure_state *server_state = statep; - gpr_mu_lock(&server_state->mu); - server_state->is_shutdown = false; - gpr_mu_unlock(&server_state->mu); - grpc_tcp_server_start(exec_ctx, server_state->tcp, pollsets, pollset_count, - on_accept, server_state); +static void server_security_handshaker_factory_destroy( + grpc_exec_ctx *exec_ctx, grpc_chttp2_server_handshaker_factory *hf) { + server_security_handshaker_factory *handshaker_factory = + (server_security_handshaker_factory *)hf; + GRPC_SECURITY_CONNECTOR_UNREF(&handshaker_factory->security_connector->base, + "server"); + gpr_free(hf); } -static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *statep, - grpc_error *error) { - server_secure_state *server_state = statep; - /* ensure all threads have unlocked */ - gpr_mu_lock(&server_state->mu); - grpc_closure *destroy_done = server_state->server_destroy_listener_done; - GPR_ASSERT(server_state->is_shutdown); - gpr_mu_unlock(&server_state->mu); - /* clean up */ - grpc_server_security_connector_shutdown(exec_ctx, server_state->sc); - - /* Flush queued work before a synchronous unref. */ - grpc_exec_ctx_flush(exec_ctx); - GRPC_SECURITY_CONNECTOR_UNREF(&server_state->sc->base, "server"); - grpc_server_credentials_unref(server_state->creds); - - if (destroy_done != NULL) { - destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error)); - grpc_exec_ctx_flush(exec_ctx); - } - gpr_free(server_state); -} - -static void server_destroy_listener(grpc_exec_ctx *exec_ctx, - grpc_server *server, void *statep, - grpc_closure *callback) { - server_secure_state *server_state = statep; - grpc_tcp_server *tcp; - gpr_mu_lock(&server_state->mu); - server_state->is_shutdown = true; - server_state->server_destroy_listener_done = callback; - tcp = server_state->tcp; - gpr_mu_unlock(&server_state->mu); - grpc_tcp_server_shutdown_listeners(exec_ctx, tcp); - grpc_tcp_server_unref(exec_ctx, server_state->tcp); -} +static const grpc_chttp2_server_handshaker_factory_vtable + server_security_handshaker_factory_vtable = { + server_security_handshaker_factory_add_handshakers, + server_security_handshaker_factory_destroy}; int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { - grpc_resolved_addresses *resolved = NULL; - grpc_tcp_server *tcp = NULL; - server_secure_state *server_state = NULL; - size_t i; - size_t count = 0; - int port_num = -1; - int port_temp; - grpc_security_status status = GRPC_SECURITY_ERROR; - grpc_server_security_connector *sc = NULL; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_error *err = GRPC_ERROR_NONE; - grpc_error **errors = NULL; - + grpc_server_security_connector *sc = NULL; + int port_num = 0; GRPC_API_TRACE( "grpc_server_add_secure_http2_port(" "server=%p, addr=%s, creds=%p)", 3, (server, addr, creds)); - - /* create security context */ + // Create security context. if (creds == NULL) { err = GRPC_ERROR_CREATE( "No credentials specified for secure server port (creds==NULL)"); - goto error; + goto done; } - status = grpc_server_credentials_create_security_connector(creds, &sc); + grpc_security_status status = + grpc_server_credentials_create_security_connector(creds, &sc); if (status != GRPC_SECURITY_OK) { char *msg; gpr_asprintf(&msg, @@ -258,107 +103,28 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, err = grpc_error_set_int(GRPC_ERROR_CREATE(msg), GRPC_ERROR_INT_SECURITY_STATUS, status); gpr_free(msg); - goto error; + goto done; } - sc->channel_args = grpc_server_get_channel_args(server); - - /* resolve address */ - err = grpc_blocking_resolve_address(addr, "https", &resolved); - if (err != GRPC_ERROR_NONE) { - goto error; - } - server_state = gpr_malloc(sizeof(*server_state)); - memset(server_state, 0, sizeof(*server_state)); - grpc_closure_init(&server_state->tcp_server_shutdown_complete, - tcp_server_shutdown_complete, server_state); - err = grpc_tcp_server_create(&exec_ctx, - &server_state->tcp_server_shutdown_complete, - grpc_server_get_channel_args(server), &tcp); + // Create handshaker factory. + server_security_handshaker_factory *handshaker_factory = + gpr_malloc(sizeof(*handshaker_factory)); + memset(handshaker_factory, 0, sizeof(*handshaker_factory)); + handshaker_factory->base.vtable = &server_security_handshaker_factory_vtable; + handshaker_factory->security_connector = sc; + // Create channel args. + grpc_arg channel_arg = grpc_server_credentials_to_arg(creds); + grpc_channel_args *args = grpc_channel_args_copy_and_add( + grpc_server_get_channel_args(server), &channel_arg, 1); + // Add server port. + err = grpc_chttp2_server_add_port(&exec_ctx, server, addr, args, + &handshaker_factory->base, &port_num); +done: + grpc_exec_ctx_finish(&exec_ctx); if (err != GRPC_ERROR_NONE) { - goto error; + const char *msg = grpc_error_string(err); + gpr_log(GPR_ERROR, "%s", msg); + grpc_error_free_string(msg); + GRPC_ERROR_UNREF(err); } - - server_state->server = server; - server_state->tcp = tcp; - server_state->sc = sc; - server_state->creds = grpc_server_credentials_ref(creds); - server_state->is_shutdown = true; - gpr_mu_init(&server_state->mu); - - errors = gpr_malloc(sizeof(*errors) * resolved->naddrs); - for (i = 0; i < resolved->naddrs; i++) { - errors[i] = grpc_tcp_server_add_port(tcp, &resolved->addrs[i], &port_temp); - if (errors[i] == GRPC_ERROR_NONE) { - if (port_num == -1) { - port_num = port_temp; - } else { - GPR_ASSERT(port_num == port_temp); - } - count++; - } - } - if (count == 0) { - char *msg; - gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved", - resolved->naddrs); - err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs); - gpr_free(msg); - goto error; - } else if (count != resolved->naddrs) { - char *msg; - gpr_asprintf(&msg, "Only %" PRIuPTR - " addresses added out of total %" PRIuPTR " resolved", - count, resolved->naddrs); - err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs); - gpr_free(msg); - - const char *warning_message = grpc_error_string(err); - gpr_log(GPR_INFO, "WARNING: %s", warning_message); - grpc_error_free_string(warning_message); - /* we managed to bind some addresses: continue */ - } else { - for (i = 0; i < resolved->naddrs; i++) { - GRPC_ERROR_UNREF(errors[i]); - } - } - gpr_free(errors); - errors = NULL; - grpc_resolved_addresses_destroy(resolved); - - /* Register with the server only upon success */ - grpc_server_add_listener(&exec_ctx, server, server_state, - server_start_listener, server_destroy_listener); - - grpc_exec_ctx_finish(&exec_ctx); return port_num; - -/* Error path: cleanup and return */ -error: - GPR_ASSERT(err != GRPC_ERROR_NONE); - if (errors != NULL) { - for (i = 0; i < resolved->naddrs; i++) { - GRPC_ERROR_UNREF(errors[i]); - } - gpr_free(errors); - } - if (resolved) { - grpc_resolved_addresses_destroy(resolved); - } - if (tcp) { - grpc_tcp_server_unref(&exec_ctx, tcp); - } else { - if (sc) { - grpc_exec_ctx_flush(&exec_ctx); - GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server"); - } - if (server_state) { - gpr_free(server_state); - } - } - grpc_exec_ctx_finish(&exec_ctx); - const char *msg = grpc_error_string(err); - GRPC_ERROR_UNREF(err); - gpr_log(GPR_ERROR, "%s", msg); - grpc_error_free_string(msg); - return 0; } diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 4e3c7ff681..6bc054866b 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -111,9 +111,6 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx, static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, void *byte_stream, grpc_error *error_ignored); -static void fail_pending_writes(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, grpc_chttp2_stream *s, - grpc_error *error); static void benign_reclaimer(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); @@ -602,11 +599,13 @@ static void set_write_state(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, write_state_name(t->write_state), write_state_name(st), reason)); t->write_state = st; - if (st == GRPC_CHTTP2_WRITE_STATE_IDLE && - t->close_transport_on_writes_finished != NULL) { - grpc_error *err = t->close_transport_on_writes_finished; - t->close_transport_on_writes_finished = NULL; - close_transport_locked(exec_ctx, t, err); + if (st == GRPC_CHTTP2_WRITE_STATE_IDLE) { + grpc_exec_ctx_enqueue_list(exec_ctx, &t->run_after_write, NULL); + if (t->close_transport_on_writes_finished != NULL) { + grpc_error *err = t->close_transport_on_writes_finished; + t->close_transport_on_writes_finished = NULL; + close_transport_locked(exec_ctx, t, err); + } } } @@ -704,8 +703,6 @@ static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp, } } - grpc_chttp2_end_write(exec_ctx, t, GRPC_ERROR_REF(error)); - switch (t->write_state) { case GRPC_CHTTP2_WRITE_STATE_IDLE: GPR_UNREACHABLE_CODE(break); @@ -734,6 +731,8 @@ static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp, break; } + grpc_chttp2_end_write(exec_ctx, t, GRPC_ERROR_REF(error)); + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing"); GPR_TIMER_END("terminate_writing_with_lock", 0); } @@ -823,7 +822,14 @@ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx, } } +/* Flag that this closure barrier wants stats to be updated before finishing */ #define CLOSURE_BARRIER_STATS_BIT (1 << 0) +/* Flag that this closure barrier may be covering a write in a pollset, and so + we should not complete this closure until we can prove that the write got + scheduled */ +#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 1) +/* First bit of the reference count, stored in the high order bits (with the low + bits being used for flags defined above) */ #define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16) static grpc_closure *add_closure_barrier(grpc_closure *closure) { @@ -850,6 +856,16 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, return; } closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT; + if (grpc_http_trace) { + const char *errstr = grpc_error_string(error); + gpr_log(GPR_DEBUG, + "complete_closure_step: %p refs=%d flags=0x%04x desc=%s err=%s", + closure, + (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT), + (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT), + desc, errstr); + grpc_error_free_string(errstr); + } if (error != GRPC_ERROR_NONE) { if (closure->error_data.error == GRPC_ERROR_NONE) { closure->error_data.error = @@ -866,7 +882,13 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, grpc_transport_move_stats(&s->stats, s->collecting_stats); s->collecting_stats = NULL; } - grpc_closure_run(exec_ctx, closure, closure->error_data.error); + if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) || + !(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) { + grpc_closure_run(exec_ctx, closure, closure->error_data.error); + } else { + grpc_closure_list_append(&t->run_after_write, closure, + closure->error_data.error); + } } } @@ -1011,6 +1033,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, if (op->send_initial_metadata != NULL) { GPR_ASSERT(s->send_initial_metadata_finished == NULL); + on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; s->send_initial_metadata_finished = add_closure_barrier(on_complete); s->send_initial_metadata = op->send_initial_metadata; const size_t metadata_size = @@ -1064,6 +1087,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, } if (op->send_message != NULL) { + on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; s->fetching_send_message_finished = add_closure_barrier(op->on_complete); if (s->write_closed) { grpc_chttp2_complete_closure_step( @@ -1101,6 +1125,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, if (op->send_trailing_metadata != NULL) { GPR_ASSERT(s->send_trailing_metadata_finished == NULL); + on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; s->send_trailing_metadata_finished = add_closure_barrier(on_complete); s->send_trailing_metadata = op->send_trailing_metadata; const size_t metadata_size = @@ -1534,9 +1559,9 @@ static grpc_error *removal_error(grpc_error *extra_error, grpc_chttp2_stream *s, return error; } -static void fail_pending_writes(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, grpc_chttp2_stream *s, - grpc_error *error) { +void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, grpc_error *error) { error = removal_error(error, s, "Pending writes failed due to stream closure"); s->send_initial_metadata = NULL; @@ -1590,13 +1615,16 @@ void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx, if (close_writes && !s->write_closed) { s->write_closed_error = GRPC_ERROR_REF(error); s->write_closed = true; - fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error)); + grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error)); grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s); } if (s->read_closed && s->write_closed) { if (s->id != 0) { remove_stream(exec_ctx, t, s->id, removal_error(GRPC_ERROR_REF(error), s, "Stream removed")); + } else { + /* Purge streams waiting on concurrency still waiting for id assignment */ + grpc_chttp2_list_remove_waiting_for_concurrency(t, s); } GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2"); } diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index b74233d992..b727965d43 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -327,6 +327,9 @@ struct grpc_chttp2_transport { */ grpc_error *close_transport_on_writes_finished; + /* a list of closures to run after writes are finished */ + grpc_closure_list run_after_write; + /* buffer pool state */ /** have we scheduled a benign cleanup? */ bool benign_reclaimer_registered; @@ -493,6 +496,8 @@ void grpc_chttp2_list_add_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream *s); int grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t, grpc_chttp2_stream **s); +void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t, + grpc_chttp2_stream *s); void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream *s); @@ -689,4 +694,8 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s); +void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, grpc_error *error); + #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */ diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.c b/src/core/ext/transport/chttp2/transport/stream_lists.c index 6d25b3ae57..a60264cc51 100644 --- a/src/core/ext/transport/chttp2/transport/stream_lists.c +++ b/src/core/ext/transport/chttp2/transport/stream_lists.c @@ -158,6 +158,11 @@ int grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t, return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); } +void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t, + grpc_chttp2_stream *s) { + stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); +} + void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t, grpc_chttp2_stream *s) { stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index a4c110101e..afc59f4b12 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -149,6 +149,9 @@ struct write_state { struct op_state { bool state_op_done[OP_NUM_OPS]; bool state_callback_received[OP_NUM_OPS]; + bool fail_state; + bool flush_read; + grpc_error *cancel_error; /* data structure for storing data coming from server */ struct read_state rs; /* data structure for storing data going to the server */ @@ -248,6 +251,12 @@ static void free_read_buffer(stream_obj *s) { } } +static grpc_error *make_error_with_desc(int error_code, const char *desc) { + grpc_error *error = GRPC_ERROR_CREATE(desc); + error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, error_code); + return error; +} + /* Add a new stream op to op storage. */ @@ -433,6 +442,18 @@ static void on_response_headers_received( grpc_mdstr_from_string(headers->headers[i].value))); } s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true; + if (!(s->state.state_op_done[OP_CANCEL_ERROR] || + s->state.state_callback_received[OP_FAILED])) { + /* Do an extra read to trigger on_succeeded() callback in case connection + is closed */ + GPR_ASSERT(s->state.rs.length_field_received == false); + s->state.rs.read_buffer = s->state.rs.grpc_header_bytes; + s->state.rs.received_bytes = 0; + s->state.rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; + CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs); + cronet_bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, + s->state.rs.remaining_bytes); + } gpr_mu_unlock(&s->mu); execute_from_storage(s); } @@ -464,7 +485,11 @@ static void on_read_completed(cronet_bidirectional_stream *stream, char *data, count); gpr_mu_lock(&s->mu); s->state.state_callback_received[OP_RECV_MESSAGE] = true; - if (count > 0) { + if (count > 0 && s->state.flush_read) { + CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs); + cronet_bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, 4096); + gpr_mu_unlock(&s->mu); + } else if (count > 0) { s->state.rs.received_bytes += count; s->state.rs.remaining_bytes -= count; if (s->state.rs.remaining_bytes > 0) { @@ -479,6 +504,10 @@ static void on_read_completed(cronet_bidirectional_stream *stream, char *data, execute_from_storage(s); } } else { + if (s->state.flush_read) { + gpr_free(s->state.rs.read_buffer); + s->state.rs.read_buffer = NULL; + } s->state.rs.read_stream_closed = true; gpr_mu_unlock(&s->mu); execute_from_storage(s); @@ -508,10 +537,27 @@ static void on_response_trailers_received( grpc_mdstr_from_string(trailers->headers[i].key), grpc_mdstr_from_string(trailers->headers[i].value))); s->state.rs.trailing_metadata_valid = true; + if (0 == strcmp(trailers->headers[i].key, "grpc-status") && + 0 != strcmp(trailers->headers[i].value, "0")) { + s->state.fail_state = true; + } } s->state.state_callback_received[OP_RECV_TRAILING_METADATA] = true; - gpr_mu_unlock(&s->mu); - execute_from_storage(s); + /* Send a EOS when server terminates the stream (testServerFinishesRequest) to + * trigger on_succeeded */ + if (!s->state.state_op_done[OP_SEND_TRAILING_METADATA] && + !(s->state.state_op_done[OP_CANCEL_ERROR] || + s->state.state_callback_received[OP_FAILED])) { + CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_write (%p, 0)", s->cbs); + s->state.state_callback_received[OP_SEND_MESSAGE] = false; + cronet_bidirectional_stream_write(s->cbs, "", 0, true); + s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true; + + gpr_mu_unlock(&s->mu); + } else { + gpr_mu_unlock(&s->mu); + execute_from_storage(s); + } } /* @@ -632,9 +678,9 @@ static bool op_can_be_run(grpc_transport_stream_op *curr_op, /* When call is canceled, every op can be run, except under following conditions */ - bool is_canceled_of_failed = stream_state->state_op_done[OP_CANCEL_ERROR] || + bool is_canceled_or_failed = stream_state->state_op_done[OP_CANCEL_ERROR] || stream_state->state_callback_received[OP_FAILED]; - if (is_canceled_of_failed) { + if (is_canceled_or_failed) { if (op_id == OP_SEND_INITIAL_METADATA) result = false; if (op_id == OP_SEND_MESSAGE) result = false; if (op_id == OP_SEND_TRAILING_METADATA) result = false; @@ -778,16 +824,10 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, op_can_be_run(stream_op, stream_state, &oas->state, OP_SEND_INITIAL_METADATA)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas); - /* This OP is the beginning. Reset various states */ - memset(&s->header_array, 0, sizeof(s->header_array)); - memset(&stream_state->rs, 0, sizeof(stream_state->rs)); - memset(&stream_state->ws, 0, sizeof(stream_state->ws)); - memset(stream_state->state_op_done, 0, sizeof(stream_state->state_op_done)); - memset(stream_state->state_callback_received, 0, - sizeof(stream_state->state_callback_received)); /* Start new cronet stream. It is destroyed in on_succeeded, on_canceled, * on_failed */ GPR_ASSERT(s->cbs == NULL); + GPR_ASSERT(!stream_state->state_op_done[OP_SEND_INITIAL_METADATA]); s->cbs = cronet_bidirectional_stream_create(s->curr_ct.engine, s->curr_gs, &cronet_callbacks); CRONET_LOG(GPR_DEBUG, "%p = cronet_bidirectional_stream_create()", s->cbs); @@ -808,10 +848,13 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, op_can_be_run(stream_op, stream_state, &oas->state, OP_RECV_INITIAL_METADATA)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas); - if (stream_state->state_op_done[OP_CANCEL_ERROR] || - stream_state->state_callback_received[OP_FAILED]) { + if (stream_state->state_op_done[OP_CANCEL_ERROR]) { grpc_exec_ctx_sched(exec_ctx, stream_op->recv_initial_metadata_ready, GRPC_ERROR_CANCELLED, NULL); + } else if (stream_state->state_callback_received[OP_FAILED]) { + grpc_exec_ctx_sched( + exec_ctx, stream_op->recv_initial_metadata_ready, + make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable."), NULL); } else { grpc_chttp2_incoming_metadata_buffer_publish( &oas->s->state.rs.initial_metadata, stream_op->recv_initial_metadata); @@ -865,12 +908,19 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, op_can_be_run(stream_op, stream_state, &oas->state, OP_RECV_MESSAGE)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas); - if (stream_state->state_op_done[OP_CANCEL_ERROR] || - stream_state->state_callback_received[OP_FAILED]) { - CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); + if (stream_state->state_op_done[OP_CANCEL_ERROR]) { + CRONET_LOG(GPR_DEBUG, "Stream is cancelled."); grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready, GRPC_ERROR_CANCELLED, NULL); stream_state->state_op_done[OP_RECV_MESSAGE] = true; + result = ACTION_TAKEN_NO_CALLBACK; + } else if (stream_state->state_callback_received[OP_FAILED]) { + CRONET_LOG(GPR_DEBUG, "Stream failed."); + grpc_exec_ctx_sched( + exec_ctx, stream_op->recv_message_ready, + make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable."), NULL); + stream_state->state_op_done[OP_RECV_MESSAGE] = true; + result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_state->rs.read_stream_closed == true) { /* No more data will be received */ CRONET_LOG(GPR_DEBUG, "read stream closed"); @@ -878,6 +928,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, GRPC_ERROR_NONE, NULL); stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; + result = ACTION_TAKEN_NO_CALLBACK; } else if (stream_state->rs.length_field_received == false) { if (stream_state->rs.received_bytes == GRPC_HEADER_SIZE_IN_BYTES && stream_state->rs.remaining_bytes == 0) { @@ -946,10 +997,15 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, GRPC_ERROR_NONE, NULL); stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; - /* Clear read state of the stream, so next read op (if it were to come) - * will work */ - stream_state->rs.received_bytes = stream_state->rs.remaining_bytes = - stream_state->rs.length_field_received = 0; + /* Do an extra read to trigger on_succeeded() callback in case connection + is closed */ + stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; + stream_state->rs.received_bytes = 0; + stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; + stream_state->rs.length_field_received = false; + CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs); + cronet_bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, + stream_state->rs.remaining_bytes); result = ACTION_TAKEN_NO_CALLBACK; } } else if (stream_op->recv_trailing_metadata && @@ -986,17 +1042,25 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, CRONET_LOG(GPR_DEBUG, "W: cronet_bidirectional_stream_cancel(%p)", s->cbs); if (s->cbs) { cronet_bidirectional_stream_cancel(s->cbs); + result = ACTION_TAKEN_WITH_CALLBACK; + } else { + result = ACTION_TAKEN_NO_CALLBACK; } stream_state->state_op_done[OP_CANCEL_ERROR] = true; - result = ACTION_TAKEN_WITH_CALLBACK; + if (!stream_state->cancel_error) { + stream_state->cancel_error = GRPC_ERROR_REF(stream_op->cancel_error); + } } else if (stream_op->on_complete && op_can_be_run(stream_op, stream_state, &oas->state, OP_ON_COMPLETE)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas); - if (stream_state->state_op_done[OP_CANCEL_ERROR] || - stream_state->state_callback_received[OP_FAILED]) { + if (stream_state->state_op_done[OP_CANCEL_ERROR]) { grpc_exec_ctx_sched(exec_ctx, stream_op->on_complete, - GRPC_ERROR_CANCELLED, NULL); + GRPC_ERROR_REF(stream_state->cancel_error), NULL); + } else if (stream_state->state_callback_received[OP_FAILED]) { + grpc_exec_ctx_sched( + exec_ctx, stream_op->on_complete, + make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable."), NULL); } else { /* All actions in this stream_op are complete. Call the on_complete * callback @@ -1017,6 +1081,15 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, make a note */ if (stream_op->recv_message) stream_state->state_op_done[OP_RECV_MESSAGE_AND_ON_COMPLETE] = true; + } else if (stream_state->fail_state && !stream_state->flush_read) { + CRONET_LOG(GPR_DEBUG, "running: %p flush read", oas); + if (stream_state->rs.read_buffer && + stream_state->rs.read_buffer != stream_state->rs.grpc_header_bytes) { + gpr_free(stream_state->rs.read_buffer); + stream_state->rs.read_buffer = NULL; + } + stream_state->rs.read_buffer = gpr_malloc(4096); + stream_state->flush_read = true; } else { result = NO_ACTION_POSSIBLE; } @@ -1042,6 +1115,8 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, memset(s->state.state_op_done, 0, sizeof(s->state.state_op_done)); memset(s->state.state_callback_received, 0, sizeof(s->state.state_callback_received)); + s->state.fail_state = s->state.flush_read = false; + s->state.cancel_error = NULL; gpr_mu_init(&s->mu); return 0; } @@ -1088,7 +1163,10 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, void *and_free_memory) {} + grpc_stream *gs, void *and_free_memory) { + stream_obj *s = (stream_obj *)gs; + GRPC_ERROR_UNREF(s->state.cancel_error); +} static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {} diff --git a/src/core/lib/channel/handshaker.c b/src/core/lib/channel/handshaker.c index a45a39981c..23edc826ca 100644 --- a/src/core/lib/channel/handshaker.c +++ b/src/core/lib/channel/handshaker.c @@ -38,12 +38,13 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/iomgr/timer.h" // // grpc_handshaker // -void grpc_handshaker_init(const struct grpc_handshaker_vtable* vtable, +void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, grpc_handshaker* handshaker) { handshaker->vtable = vtable; } @@ -60,45 +61,43 @@ void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, - grpc_endpoint* endpoint, - grpc_channel_args* args, - grpc_slice_buffer* read_buffer, - gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, - grpc_handshaker_done_cb cb, void* user_data) { - handshaker->vtable->do_handshake(exec_ctx, handshaker, endpoint, args, - read_buffer, deadline, acceptor, cb, - user_data); + grpc_closure* on_handshake_done, + grpc_handshaker_args* args) { + handshaker->vtable->do_handshake(exec_ctx, handshaker, acceptor, + on_handshake_done, args); } // // grpc_handshake_manager // -// State used while chaining handshakers. -struct grpc_handshaker_state { - // The index of the handshaker to invoke next. - size_t index; - // The deadline for all handshakers. - gpr_timespec deadline; - // The acceptor to call the handshakers with. - grpc_tcp_server_acceptor* acceptor; - // The final callback and user_data to invoke after the last handshaker. - grpc_handshaker_done_cb final_cb; - void* final_user_data; -}; - struct grpc_handshake_manager { + gpr_mu mu; + gpr_refcount refs; + bool shutdown; // An array of handshakers added via grpc_handshake_manager_add(). size_t count; grpc_handshaker** handshakers; - // State used while chaining handshakers. - struct grpc_handshaker_state* state; + // The index of the handshaker to invoke next and closure to invoke it. + size_t index; + grpc_closure call_next_handshaker; + // The acceptor to call the handshakers with. + grpc_tcp_server_acceptor* acceptor; + // Deadline timer across all handshakers. + grpc_timer deadline_timer; + // The final callback and user_data to invoke after the last handshaker. + grpc_closure on_handshake_done; + void* user_data; + // Handshaker args. + grpc_handshaker_args args; }; grpc_handshake_manager* grpc_handshake_manager_create() { grpc_handshake_manager* mgr = gpr_malloc(sizeof(grpc_handshake_manager)); memset(mgr, 0, sizeof(*mgr)); + gpr_mu_init(&mgr->mu); + gpr_ref_init(&mgr->refs, 1); return mgr; } @@ -106,6 +105,7 @@ static bool is_power_of_2(size_t n) { return (n & (n - 1)) == 0; } void grpc_handshake_manager_add(grpc_handshake_manager* mgr, grpc_handshaker* handshaker) { + gpr_mu_lock(&mgr->mu); // To avoid allocating memory for each handshaker we add, we double // the number of elements every time we need more. size_t realloc_count = 0; @@ -119,85 +119,117 @@ void grpc_handshake_manager_add(grpc_handshake_manager* mgr, gpr_realloc(mgr->handshakers, realloc_count * sizeof(grpc_handshaker*)); } mgr->handshakers[mgr->count++] = handshaker; + gpr_mu_unlock(&mgr->mu); +} + +static void grpc_handshake_manager_unref(grpc_exec_ctx* exec_ctx, + grpc_handshake_manager* mgr) { + if (gpr_unref(&mgr->refs)) { + for (size_t i = 0; i < mgr->count; ++i) { + grpc_handshaker_destroy(exec_ctx, mgr->handshakers[i]); + } + gpr_free(mgr->handshakers); + gpr_mu_destroy(&mgr->mu); + gpr_free(mgr); + } } void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr) { - for (size_t i = 0; i < mgr->count; ++i) { - grpc_handshaker_destroy(exec_ctx, mgr->handshakers[i]); - } - gpr_free(mgr->handshakers); - gpr_free(mgr); + grpc_handshake_manager_unref(exec_ctx, mgr); } void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr) { - for (size_t i = 0; i < mgr->count; ++i) { - grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[i]); + gpr_mu_lock(&mgr->mu); + // Shutdown the handshaker that's currently in progress, if any. + if (!mgr->shutdown && mgr->index > 0) { + mgr->shutdown = true; + grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[mgr->index - 1]); } - if (mgr->state != NULL) { - gpr_free(mgr->state); - mgr->state = NULL; + gpr_mu_unlock(&mgr->mu); +} + +// Helper function to call either the next handshaker or the +// on_handshake_done callback. +// Returns true if we've scheduled the on_handshake_done callback. +static bool call_next_handshaker_locked(grpc_exec_ctx* exec_ctx, + grpc_handshake_manager* mgr, + grpc_error* error) { + GPR_ASSERT(mgr->index <= mgr->count); + // If we got an error or we've been shut down or we're exiting early or + // we've finished the last handshaker, invoke the on_handshake_done + // callback. Otherwise, call the next handshaker. + if (error != GRPC_ERROR_NONE || mgr->shutdown || mgr->args.exit_early || + mgr->index == mgr->count) { + // Cancel deadline timer, since we're invoking the on_handshake_done + // callback now. + grpc_timer_cancel(exec_ctx, &mgr->deadline_timer); + grpc_exec_ctx_sched(exec_ctx, &mgr->on_handshake_done, error, NULL); + mgr->shutdown = true; + } else { + grpc_handshaker_do_handshake(exec_ctx, mgr->handshakers[mgr->index], + mgr->acceptor, &mgr->call_next_handshaker, + &mgr->args); } + ++mgr->index; + return mgr->shutdown; } // A function used as the handshaker-done callback when chaining // handshakers together. -static void call_next_handshaker(grpc_exec_ctx* exec_ctx, - grpc_endpoint* endpoint, - grpc_channel_args* args, - grpc_slice_buffer* read_buffer, - void* user_data, grpc_error* error) { - grpc_handshake_manager* mgr = user_data; - GPR_ASSERT(mgr->state != NULL); - GPR_ASSERT(mgr->state->index < mgr->count); - // If we got an error, skip all remaining handshakers and invoke the - // caller-supplied callback immediately. - if (error != GRPC_ERROR_NONE) { - mgr->state->final_cb(exec_ctx, endpoint, args, read_buffer, - mgr->state->final_user_data, error); - return; +static void call_next_handshaker(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + grpc_handshake_manager* mgr = arg; + gpr_mu_lock(&mgr->mu); + bool done = call_next_handshaker_locked(exec_ctx, mgr, GRPC_ERROR_REF(error)); + gpr_mu_unlock(&mgr->mu); + // If we're invoked the final callback, we won't be coming back + // to this function, so we can release our reference to the + // handshake manager. + if (done) { + grpc_handshake_manager_unref(exec_ctx, mgr); } - grpc_handshaker_done_cb cb = call_next_handshaker; - // If this is the last handshaker, use the caller-supplied callback - // and user_data instead of chaining back to this function again. - if (mgr->state->index == mgr->count - 1) { - cb = mgr->state->final_cb; - user_data = mgr->state->final_user_data; - } - // Invoke handshaker. - grpc_handshaker_do_handshake( - exec_ctx, mgr->handshakers[mgr->state->index], endpoint, args, - read_buffer, mgr->state->deadline, mgr->state->acceptor, cb, user_data); - ++mgr->state->index; - // If this is the last handshaker, clean up state. - if (mgr->state->index == mgr->count) { - gpr_free(mgr->state); - mgr->state = NULL; +} + +// Callback invoked when deadline is exceeded. +static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { + grpc_handshake_manager* mgr = arg; + if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled. + grpc_handshake_manager_shutdown(exec_ctx, mgr); } + grpc_handshake_manager_unref(exec_ctx, mgr); } void grpc_handshake_manager_do_handshake( grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, - grpc_endpoint* endpoint, const grpc_channel_args* args, + grpc_endpoint* endpoint, const grpc_channel_args* channel_args, gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, - grpc_handshaker_done_cb cb, void* user_data) { - grpc_channel_args* args_copy = grpc_channel_args_copy(args); - grpc_slice_buffer* read_buffer = gpr_malloc(sizeof(*read_buffer)); - grpc_slice_buffer_init(read_buffer); - if (mgr->count == 0) { - // No handshakers registered, so we just immediately call the done - // callback with the passed-in endpoint. - cb(exec_ctx, endpoint, args_copy, read_buffer, user_data, GRPC_ERROR_NONE); - } else { - GPR_ASSERT(mgr->state == NULL); - mgr->state = gpr_malloc(sizeof(struct grpc_handshaker_state)); - memset(mgr->state, 0, sizeof(*mgr->state)); - mgr->state->deadline = deadline; - mgr->state->acceptor = acceptor; - mgr->state->final_cb = cb; - mgr->state->final_user_data = user_data; - call_next_handshaker(exec_ctx, endpoint, args_copy, read_buffer, mgr, - GRPC_ERROR_NONE); + grpc_iomgr_cb_func on_handshake_done, void* user_data) { + gpr_mu_lock(&mgr->mu); + GPR_ASSERT(mgr->index == 0); + GPR_ASSERT(!mgr->shutdown); + // Construct handshaker args. These will be passed through all + // handshakers and eventually be freed by the on_handshake_done callback. + mgr->args.endpoint = endpoint; + mgr->args.args = grpc_channel_args_copy(channel_args); + mgr->args.user_data = user_data; + mgr->args.read_buffer = gpr_malloc(sizeof(*mgr->args.read_buffer)); + grpc_slice_buffer_init(mgr->args.read_buffer); + // Initialize state needed for calling handshakers. + mgr->acceptor = acceptor; + grpc_closure_init(&mgr->call_next_handshaker, call_next_handshaker, mgr); + grpc_closure_init(&mgr->on_handshake_done, on_handshake_done, &mgr->args); + // Start deadline timer, which owns a ref. + gpr_ref(&mgr->refs); + grpc_timer_init(exec_ctx, &mgr->deadline_timer, + gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), + on_timeout, mgr, gpr_now(GPR_CLOCK_MONOTONIC)); + // Start first handshaker, which also owns a ref. + gpr_ref(&mgr->refs); + bool done = call_next_handshaker_locked(exec_ctx, mgr, GRPC_ERROR_NONE); + gpr_mu_unlock(&mgr->mu); + if (done) { + grpc_handshake_manager_unref(exec_ctx, mgr); } } diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index f8a36c6473..450b7adaee 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -54,15 +54,33 @@ typedef struct grpc_handshaker grpc_handshaker; -/// Callback type invoked when a handshaker is done. -/// Takes ownership of \a args and \a read_buffer. -typedef void (*grpc_handshaker_done_cb)(grpc_exec_ctx* exec_ctx, - grpc_endpoint* endpoint, - grpc_channel_args* args, - grpc_slice_buffer* read_buffer, - void* user_data, grpc_error* error); - -struct grpc_handshaker_vtable { +/// Arguments passed through handshakers and to the on_handshake_done callback. +/// +/// For handshakers, all members are input/output parameters; for +/// example, a handshaker may read from or write to \a endpoint and +/// then later replace it with a wrapped endpoint. Similarly, a +/// handshaker may modify \a args. +/// +/// A handshaker takes ownership of the members while a handshake is in +/// progress. Upon failure or shutdown of an in-progress handshaker, +/// the handshaker is responsible for destroying the members and setting +/// them to NULL before invoking the on_handshake_done callback. +/// +/// For the on_handshake_done callback, all members are input arguments, +/// which the callback takes ownership of. +typedef struct { + grpc_endpoint* endpoint; + grpc_channel_args* args; + grpc_slice_buffer* read_buffer; + // A handshaker may set this to true before invoking on_handshake_done + // to indicate that subsequent handshakers should be skipped. + bool exit_early; + // User data passed through the handshake manager. Not used by + // individual handshakers. + void* user_data; +} grpc_handshaker_args; + +typedef struct { /// Destroys the handshaker. void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); @@ -70,43 +88,35 @@ struct grpc_handshaker_vtable { /// aborted in the middle). void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); - /// Performs handshaking. When finished, calls \a cb with \a user_data. - /// Takes ownership of \a args. - /// Takes ownership of \a read_buffer, which contains leftover bytes read - /// from the endpoint by the previous handshaker. + /// Performs handshaking, modifying \a args as needed (e.g., to + /// replace \a endpoint with a wrapped endpoint). + /// When finished, invokes \a on_handshake_done. /// \a acceptor will be NULL for client-side handshakers. void (*do_handshake)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, - grpc_endpoint* endpoint, grpc_channel_args* args, - grpc_slice_buffer* read_buffer, gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, - grpc_handshaker_done_cb cb, void* user_data); -}; + grpc_closure* on_handshake_done, + grpc_handshaker_args* args); +} grpc_handshaker_vtable; /// Base struct. To subclass, make this the first member of the /// implementation struct. struct grpc_handshaker { - const struct grpc_handshaker_vtable* vtable; + const grpc_handshaker_vtable* vtable; }; /// Called by concrete implementations to initialize the base struct. -void grpc_handshaker_init(const struct grpc_handshaker_vtable* vtable, +void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, grpc_handshaker* handshaker); -/// Convenient wrappers for invoking methods via the vtable. -/// These probably do not need to be called from anywhere but -/// grpc_handshake_manager. void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, - grpc_endpoint* endpoint, - grpc_channel_args* args, - grpc_slice_buffer* read_buffer, - gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, - grpc_handshaker_done_cb cb, void* user_data); + grpc_closure* on_handshake_done, + grpc_handshaker_args* args); /// /// grpc_handshake_manager @@ -134,15 +144,21 @@ void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr); /// Invokes handshakers in the order they were added. -/// Does NOT take ownership of \a args. Instead, makes a copy before +/// Takes ownership of \a endpoint, and then passes that ownership to +/// the \a on_handshake_done callback. +/// Does NOT take ownership of \a channel_args. Instead, makes a copy before /// invoking the first handshaker. /// \a acceptor will be NULL for client-side handshakers. -/// Invokes \a cb with \a user_data after either a handshaker fails or -/// all handshakers have completed successfully. +/// +/// When done, invokes \a on_handshake_done with a grpc_handshaker_args +/// object as its argument. If the callback is invoked with error != +/// GRPC_ERROR_NONE, then handshaking failed and the handshaker has done +/// the necessary clean-up. Otherwise, the callback takes ownership of +/// the arguments. void grpc_handshake_manager_do_handshake( grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, - grpc_endpoint* endpoint, const grpc_channel_args* args, + grpc_endpoint* endpoint, const grpc_channel_args* channel_args, gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, - grpc_handshaker_done_cb cb, void* user_data); + grpc_iomgr_cb_func on_handshake_done, void* user_data); #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */ diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c index 24d264c32a..14cdb1dab3 100644 --- a/src/core/lib/http/httpcli_security_connector.c +++ b/src/core/lib/http/httpcli_security_connector.c @@ -38,7 +38,9 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> -#include "src/core/lib/security/transport/handshake.h" + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/support/string.h" #include "src/core/lib/tsi/ssl_transport_security.h" @@ -58,52 +60,43 @@ static void httpcli_ssl_destroy(grpc_security_connector *sc) { gpr_free(sc); } -static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, - gpr_timespec deadline, - grpc_security_handshake_done_cb cb, - void *user_data) { +static void httpcli_ssl_add_handshakers(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + grpc_handshake_manager *handshake_mgr) { grpc_httpcli_ssl_channel_security_connector *c = (grpc_httpcli_ssl_channel_security_connector *)sc; - tsi_result result = TSI_OK; - tsi_handshaker *handshaker; - if (c->handshaker_factory == NULL) { - gpr_free(read_buffer); - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); - return; - } - result = tsi_ssl_handshaker_factory_create_handshaker( - c->handshaker_factory, c->secure_peer_name, &handshaker); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", - tsi_result_to_string(result)); - gpr_free(read_buffer); - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); - } else { - grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true, - nonsecure_endpoint, read_buffer, deadline, cb, - user_data); + tsi_handshaker *handshaker = NULL; + if (c->handshaker_factory != NULL) { + tsi_result result = tsi_ssl_handshaker_factory_create_handshaker( + c->handshaker_factory, c->secure_peer_name, &handshaker); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + } } + grpc_handshake_manager_add( + handshake_mgr, + grpc_security_handshaker_create(exec_ctx, handshaker, &sc->base)); } static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data) { + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked) { grpc_httpcli_ssl_channel_security_connector *c = (grpc_httpcli_ssl_channel_security_connector *)sc; - grpc_security_status status = GRPC_SECURITY_OK; + grpc_error *error = GRPC_ERROR_NONE; /* Check the peer name. */ if (c->secure_peer_name != NULL && !tsi_ssl_peer_matches_name(&peer, c->secure_peer_name)) { - gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", - c->secure_peer_name); - status = GRPC_SECURITY_ERROR; + char *msg; + gpr_asprintf(&msg, "Peer name %s is not in peer certificate", + c->secure_peer_name); + error = GRPC_ERROR_CREATE(msg); + gpr_free(msg); } - cb(exec_ctx, user_data, status, NULL); + grpc_exec_ctx_sched(exec_ctx, on_peer_checked, error, NULL); tsi_peer_destruct(&peer); } @@ -140,7 +133,7 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create( *sc = NULL; return GRPC_SECURITY_ERROR; } - c->base.do_handshake = httpcli_ssl_do_handshake; + c->base.add_handshakers = httpcli_ssl_add_handshakers; *sc = &c->base; return GRPC_SECURITY_OK; } @@ -150,19 +143,25 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create( typedef struct { void (*func)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint); void *arg; + grpc_handshake_manager *handshake_mgr; } on_done_closure; -static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp, - grpc_security_status status, - grpc_endpoint *secure_endpoint, - grpc_auth_context *auth_context) { - on_done_closure *c = rp; - if (status != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status); +static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_handshaker_args *args = arg; + on_done_closure *c = args->user_data; + if (error != GRPC_ERROR_NONE) { + const char *msg = grpc_error_string(error); + gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg); + grpc_error_free_string(msg); c->func(exec_ctx, c->arg, NULL); } else { - c->func(exec_ctx, c->arg, secure_endpoint); + grpc_channel_args_destroy(args->args); + grpc_slice_buffer_destroy(args->read_buffer); + gpr_free(args->read_buffer); + c->func(exec_ctx, c->arg, args->endpoint); } + grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); gpr_free(c); } @@ -183,11 +182,15 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg, } c->func = on_done; c->arg = arg; + c->handshake_mgr = grpc_handshake_manager_create(); GPR_ASSERT(httpcli_ssl_channel_security_connector_create( pem_root_certs, pem_root_certs_size, host, &sc) == GRPC_SECURITY_OK); - grpc_channel_security_connector_do_handshake( - exec_ctx, sc, tcp, NULL, deadline, on_secure_transport_setup_done, c); + grpc_channel_security_connector_add_handshakers(exec_ctx, sc, + c->handshake_mgr); + grpc_handshake_manager_do_handshake( + exec_ctx, c->handshake_mgr, tcp, NULL /* channel_args */, deadline, + NULL /* acceptor */, on_handshake_done, c /* user_data */); GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli"); } diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 60ee14eb23..cfc67020ae 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -90,6 +90,12 @@ static bool is_covered_by_poller(grpc_combiner *lock) { gpr_atm_acq_load(&lock->elements_covered_by_poller) > 0; } +#define IS_COVERED_BY_POLLER_FMT "(final=%d elems=%" PRIdPTR ")->%d" +#define IS_COVERED_BY_POLLER_ARGS(lock) \ + (lock)->final_list_covered_by_poller, \ + gpr_atm_acq_load(&(lock)->elements_covered_by_poller), \ + is_covered_by_poller((lock)) + grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { grpc_combiner *lock = gpr_malloc(sizeof(*lock)); lock->next_combiner_on_this_exec_ctx = NULL; @@ -197,9 +203,10 @@ bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) { GRPC_COMBINER_TRACE( gpr_log(GPR_DEBUG, "C:%p grpc_combiner_continue_exec_ctx workqueue=%p " - "is_covered_by_poller=%d exec_ctx_ready_to_finish=%d " + "is_covered_by_poller=" IS_COVERED_BY_POLLER_FMT + " exec_ctx_ready_to_finish=%d " "time_to_execute_final_list=%d", - lock, lock->optional_workqueue, is_covered_by_poller(lock), + lock, lock->optional_workqueue, IS_COVERED_BY_POLLER_ARGS(lock), grpc_exec_ctx_ready_to_finish(exec_ctx), lock->time_to_execute_final_list)); diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index 07fbfd849e..1b15e0eb4f 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -69,6 +69,9 @@ static int grpc_polling_trace = 0; /* Disabled by default */ gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \ } +/* Uncomment the following enable extra checks on poll_object operations */ +/* #define PO_DEBUG */ + static int grpc_wakeup_signal = -1; static bool is_grpc_wakeup_signal_initialized = false; @@ -95,10 +98,42 @@ void grpc_use_signal(int signum) { struct polling_island; +typedef enum { + POLL_OBJ_FD, + POLL_OBJ_POLLSET, + POLL_OBJ_POLLSET_SET +} poll_obj_type; + +typedef struct poll_obj { +#ifdef PO_DEBUG + poll_obj_type obj_type; +#endif + gpr_mu mu; + struct polling_island *pi; +} poll_obj; + +const char *poll_obj_string(poll_obj_type po_type) { + switch (po_type) { + case POLL_OBJ_FD: + return "fd"; + case POLL_OBJ_POLLSET: + return "pollset"; + case POLL_OBJ_POLLSET_SET: + return "pollset_set"; + } + + GPR_UNREACHABLE_CODE(return "UNKNOWN"); +} + /******************************************************************************* * Fd Declarations */ + +#define FD_FROM_PO(po) ((grpc_fd *)(po)) + struct grpc_fd { + poll_obj po; + int fd; /* refst format: bit 0 : 1=Active / 0=Orphaned @@ -106,8 +141,6 @@ struct grpc_fd { Ref/Unref by two to avoid altering the orphaned bit */ gpr_atm refst; - gpr_mu mu; - /* Indicates that the fd is shutdown and that any pending read/write closures should fail */ bool shutdown; @@ -120,9 +153,6 @@ struct grpc_fd { grpc_closure *read_closure; grpc_closure *write_closure; - /* The polling island to which this fd belongs to (protected by mu) */ - struct polling_island *polling_island; - struct grpc_fd *freelist_next; grpc_closure *on_done_closure; @@ -225,41 +255,21 @@ struct grpc_pollset_worker { }; struct grpc_pollset { - gpr_mu mu; + poll_obj po; + grpc_pollset_worker root_worker; bool kicked_without_pollers; bool shutting_down; /* Is the pollset shutting down ? */ bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */ grpc_closure *shutdown_done; /* Called after after shutdown is complete */ - - /* The polling island to which this pollset belongs to */ - struct polling_island *polling_island; }; /******************************************************************************* * Pollset-set Declarations */ -/* TODO: sreek - Change the pollset_set implementation such that a pollset_set - * directly points to a polling_island (and adding an fd/pollset/pollset_set to - * the current pollset_set would result in polling island merges. This would - * remove the need to maintain fd_count here. This will also significantly - * simplify the grpc_fd structure since we would no longer need to explicitly - * maintain the orphaned state */ struct grpc_pollset_set { - gpr_mu mu; - - size_t pollset_count; - size_t pollset_capacity; - grpc_pollset **pollsets; - - size_t pollset_set_count; - size_t pollset_set_capacity; - struct grpc_pollset_set **pollset_sets; - - size_t fd_count; - size_t fd_capacity; - grpc_fd **fds; + poll_obj po; }; /******************************************************************************* @@ -915,7 +925,7 @@ static void fd_global_shutdown(void) { while (fd_freelist != NULL) { grpc_fd *fd = fd_freelist; fd_freelist = fd_freelist->freelist_next; - gpr_mu_destroy(&fd->mu); + gpr_mu_destroy(&fd->po.mu); gpr_free(fd); } gpr_mu_destroy(&fd_freelist_mu); @@ -933,13 +943,17 @@ static grpc_fd *fd_create(int fd, const char *name) { if (new_fd == NULL) { new_fd = gpr_malloc(sizeof(grpc_fd)); - gpr_mu_init(&new_fd->mu); + gpr_mu_init(&new_fd->po.mu); } - /* Note: It is not really needed to get the new_fd->mu lock here. If this is a - newly created fd (or an fd we got from the freelist), no one else would be - holding a lock to it anyway. */ - gpr_mu_lock(&new_fd->mu); + /* Note: It is not really needed to get the new_fd->po.mu lock here. If this + * is a newly created fd (or an fd we got from the freelist), no one else + * would be holding a lock to it anyway. */ + gpr_mu_lock(&new_fd->po.mu); + new_fd->po.pi = NULL; +#ifdef PO_DEBUG + new_fd->po.obj_type = POLL_OBJ_FD; +#endif gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); new_fd->fd = fd; @@ -947,12 +961,11 @@ static grpc_fd *fd_create(int fd, const char *name) { new_fd->orphaned = false; new_fd->read_closure = CLOSURE_NOT_READY; new_fd->write_closure = CLOSURE_NOT_READY; - new_fd->polling_island = NULL; new_fd->freelist_next = NULL; new_fd->on_done_closure = NULL; new_fd->read_notifier_pollset = NULL; - gpr_mu_unlock(&new_fd->mu); + gpr_mu_unlock(&new_fd->po.mu); char *fd_name; gpr_asprintf(&fd_name, "%s fd=%d", name, fd); @@ -964,17 +977,13 @@ static grpc_fd *fd_create(int fd, const char *name) { return new_fd; } -static bool fd_is_orphaned(grpc_fd *fd) { - return (gpr_atm_acq_load(&fd->refst) & 1) == 0; -} - static int fd_wrapped_fd(grpc_fd *fd) { int ret_fd = -1; - gpr_mu_lock(&fd->mu); + gpr_mu_lock(&fd->po.mu); if (!fd->orphaned) { ret_fd = fd->fd; } - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); return ret_fd; } @@ -986,7 +995,7 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *error = GRPC_ERROR_NONE; polling_island *unref_pi = NULL; - gpr_mu_lock(&fd->mu); + gpr_mu_lock(&fd->po.mu); fd->on_done_closure = on_done; /* If release_fd is not NULL, we should be relinquishing control of the file @@ -1006,25 +1015,25 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, /* Remove the fd from the polling island: - Get a lock on the latest polling island (i.e the last island in the - linked list pointed by fd->polling_island). This is the island that + linked list pointed by fd->po.pi). This is the island that would actually contain the fd - Remove the fd from the latest polling island - Unlock the latest polling island - - Set fd->polling_island to NULL (but remove the ref on the polling island + - Set fd->po.pi to NULL (but remove the ref on the polling island before doing this.) */ - if (fd->polling_island != NULL) { - polling_island *pi_latest = polling_island_lock(fd->polling_island); + if (fd->po.pi != NULL) { + polling_island *pi_latest = polling_island_lock(fd->po.pi); polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error); gpr_mu_unlock(&pi_latest->mu); - unref_pi = fd->polling_island; - fd->polling_island = NULL; + unref_pi = fd->po.pi; + fd->po.pi = NULL; } grpc_exec_ctx_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error), NULL); - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ if (unref_pi != NULL) { /* Unref stale polling island here, outside the fd lock above. @@ -1089,23 +1098,23 @@ static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { grpc_pollset *notifier = NULL; - gpr_mu_lock(&fd->mu); + gpr_mu_lock(&fd->po.mu); notifier = fd->read_notifier_pollset; - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); return notifier; } static bool fd_is_shutdown(grpc_fd *fd) { - gpr_mu_lock(&fd->mu); + gpr_mu_lock(&fd->po.mu); const bool r = fd->shutdown; - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); return r; } /* Might be called multiple times */ static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - gpr_mu_lock(&fd->mu); + gpr_mu_lock(&fd->po.mu); /* Do the actual shutdown only once */ if (!fd->shutdown) { fd->shutdown = true; @@ -1116,28 +1125,28 @@ static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { set_ready_locked(exec_ctx, fd, &fd->read_closure); set_ready_locked(exec_ctx, fd, &fd->write_closure); } - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); } static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - gpr_mu_lock(&fd->mu); + gpr_mu_lock(&fd->po.mu); notify_on_locked(exec_ctx, fd, &fd->read_closure, closure); - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); } static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *closure) { - gpr_mu_lock(&fd->mu); + gpr_mu_lock(&fd->po.mu); notify_on_locked(exec_ctx, fd, &fd->write_closure, closure); - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); } static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { - gpr_mu_lock(&fd->mu); - grpc_workqueue *workqueue = GRPC_WORKQUEUE_REF( - (grpc_workqueue *)fd->polling_island, "fd_get_workqueue"); - gpr_mu_unlock(&fd->mu); + gpr_mu_lock(&fd->po.mu); + grpc_workqueue *workqueue = + GRPC_WORKQUEUE_REF((grpc_workqueue *)fd->po.pi, "fd_get_workqueue"); + gpr_mu_unlock(&fd->po.mu); return workqueue; } @@ -1277,8 +1286,12 @@ static grpc_error *kick_poller(void) { } static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { - gpr_mu_init(&pollset->mu); - *mu = &pollset->mu; + gpr_mu_init(&pollset->po.mu); + *mu = &pollset->po.mu; + pollset->po.pi = NULL; +#ifdef PO_DEBUG + pollset->po.obj_type = POLL_OBJ_POLLSET; +#endif pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; pollset->kicked_without_pollers = false; @@ -1286,8 +1299,6 @@ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { pollset->shutting_down = false; pollset->finish_shutdown_called = false; pollset->shutdown_done = NULL; - - pollset->polling_island = NULL; } /* Convert a timespec to milliseconds: @@ -1317,26 +1328,26 @@ static int poll_deadline_to_millis_timeout(gpr_timespec deadline, static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *notifier) { - /* Need the fd->mu since we might be racing with fd_notify_on_read */ - gpr_mu_lock(&fd->mu); + /* Need the fd->po.mu since we might be racing with fd_notify_on_read */ + gpr_mu_lock(&fd->po.mu); set_ready_locked(exec_ctx, fd, &fd->read_closure); fd->read_notifier_pollset = notifier; - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); } static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - /* Need the fd->mu since we might be racing with fd_notify_on_write */ - gpr_mu_lock(&fd->mu); + /* Need the fd->po.mu since we might be racing with fd_notify_on_write */ + gpr_mu_lock(&fd->po.mu); set_ready_locked(exec_ctx, fd, &fd->write_closure); - gpr_mu_unlock(&fd->mu); + gpr_mu_unlock(&fd->po.mu); } static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx, grpc_pollset *ps, char *reason) { - if (ps->polling_island != NULL) { - PI_UNREF(exec_ctx, ps->polling_island, reason); + if (ps->po.pi != NULL) { + PI_UNREF(exec_ctx, ps->po.pi, reason); } - ps->polling_island = NULL; + ps->po.pi = NULL; } static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, @@ -1346,12 +1357,12 @@ static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, pollset->finish_shutdown_called = true; - /* Release the ref and set pollset->polling_island to NULL */ + /* Release the ref and set pollset->po.pi to NULL */ pollset_release_polling_island(exec_ctx, pollset, "ps_shutdown"); grpc_exec_ctx_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE, NULL); } -/* pollset->mu lock must be held by the caller before calling this */ +/* pollset->po.mu lock must be held by the caller before calling this */ static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure) { GPR_TIMER_BEGIN("pollset_shutdown", 0); @@ -1376,7 +1387,7 @@ static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, * here */ static void pollset_destroy(grpc_pollset *pollset) { GPR_ASSERT(!pollset_has_workers(pollset)); - gpr_mu_destroy(&pollset->mu); + gpr_mu_destroy(&pollset->po.mu); } static void pollset_reset(grpc_pollset *pollset) { @@ -1386,7 +1397,7 @@ static void pollset_reset(grpc_pollset *pollset) { pollset->finish_shutdown_called = false; pollset->kicked_without_pollers = false; pollset->shutdown_done = NULL; - GPR_ASSERT(pollset->polling_island == NULL); + GPR_ASSERT(pollset->po.pi == NULL); } static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx, @@ -1426,7 +1437,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, GPR_TIMER_BEGIN("pollset_work_and_unlock", 0); /* We need to get the epoll_fd to wait on. The epoll_fd is in inside the - latest polling island pointed by pollset->polling_island. + latest polling island pointed by pollset->po.pi Since epoll_fd is immutable, we can read it without obtaining the polling island lock. There is however a possibility that the polling island (from @@ -1435,36 +1446,36 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, right-away from epoll_wait() and pick up the latest polling_island the next this function (i.e pollset_work_and_unlock()) is called */ - if (pollset->polling_island == NULL) { - pollset->polling_island = polling_island_create(exec_ctx, NULL, error); - if (pollset->polling_island == NULL) { + if (pollset->po.pi == NULL) { + pollset->po.pi = polling_island_create(exec_ctx, NULL, error); + if (pollset->po.pi == NULL) { GPR_TIMER_END("pollset_work_and_unlock", 0); return; /* Fatal error. We cannot continue */ } - PI_ADD_REF(pollset->polling_island, "ps"); + PI_ADD_REF(pollset->po.pi, "ps"); GRPC_POLLING_TRACE("pollset_work: pollset: %p created new pi: %p", - (void *)pollset, (void *)pollset->polling_island); + (void *)pollset, (void *)pollset->po.pi); } - pi = polling_island_maybe_get_latest(pollset->polling_island); + pi = polling_island_maybe_get_latest(pollset->po.pi); epoll_fd = pi->epoll_fd; - /* Update the pollset->polling_island since the island being pointed by - pollset->polling_island maybe older than the one pointed by pi) */ - if (pollset->polling_island != pi) { + /* Update the pollset->po.pi since the island being pointed by + pollset->po.pi maybe older than the one pointed by pi) */ + if (pollset->po.pi != pi) { /* Always do PI_ADD_REF before PI_UNREF because PI_UNREF may cause the polling island to be deleted */ PI_ADD_REF(pi, "ps"); - PI_UNREF(exec_ctx, pollset->polling_island, "ps"); - pollset->polling_island = pi; + PI_UNREF(exec_ctx, pollset->po.pi, "ps"); + pollset->po.pi = pi; } /* Add an extra ref so that the island does not get destroyed (which means the epoll_fd won't be closed) while we are are doing an epoll_wait() on the epoll_fd */ PI_ADD_REF(pi, "ps_work"); - gpr_mu_unlock(&pollset->mu); + gpr_mu_unlock(&pollset->po.mu); /* If we get some workqueue work to do, it might end up completing an item on the completion queue, so there's no need to poll... so we skip that and @@ -1537,17 +1548,17 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, GPR_ASSERT(pi != NULL); /* Before leaving, release the extra ref we added to the polling island. It - is important to use "pi" here (i.e our old copy of pollset->polling_island + is important to use "pi" here (i.e our old copy of pollset->po.pi that we got before releasing the polling island lock). This is because - pollset->polling_island pointer might get udpated in other parts of the + pollset->po.pi pointer might get udpated in other parts of the code when there is an island merge while we are doing epoll_wait() above */ PI_UNREF(exec_ctx, pi, "ps_work"); GPR_TIMER_END("pollset_work_and_unlock", 0); } -/* pollset->mu lock must be held by the caller before calling this. - The function pollset_work() may temporarily release the lock (pollset->mu) +/* pollset->po.mu lock must be held by the caller before calling this. + The function pollset_work() may temporarily release the lock (pollset->po.mu) during the course of its execution but it will always re-acquire the lock and ensure that it is held by the time the function returns */ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, @@ -1617,7 +1628,7 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, &g_orig_sigmask, &error); grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&pollset->mu); + gpr_mu_lock(&pollset->po.mu); /* Note: There is no need to reset worker.is_kicked to 0 since we are no longer going to use this worker */ @@ -1637,9 +1648,9 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, GPR_TIMER_MARK("pollset_work.finish_shutdown_locked", 0); finish_shutdown_locked(exec_ctx, pollset); - gpr_mu_unlock(&pollset->mu); + gpr_mu_unlock(&pollset->po.mu); grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&pollset->mu); + gpr_mu_lock(&pollset->po.mu); } *worker_hdl = NULL; @@ -1653,130 +1664,160 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, return error; } -static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_fd *fd) { - GPR_TIMER_BEGIN("pollset_add_fd", 0); - - grpc_error *error = GRPC_ERROR_NONE; +static void add_poll_object(grpc_exec_ctx *exec_ctx, poll_obj *bag, + poll_obj_type bag_type, poll_obj *item, + poll_obj_type item_type) { + GPR_TIMER_BEGIN("add_poll_object", 0); - gpr_mu_lock(&pollset->mu); - gpr_mu_lock(&fd->mu); +#ifdef PO_DEBUG + GPR_ASSERT(item->obj_type == item_type); + GPR_ASSERT(bag->obj_type == bag_type); +#endif + grpc_error *error = GRPC_ERROR_NONE; polling_island *pi_new = NULL; + gpr_mu_lock(&bag->mu); + gpr_mu_lock(&item->mu); + retry: - /* 1) If fd->polling_island and pollset->polling_island are both non-NULL and - * equal, do nothing. - * 2) If fd->polling_island and pollset->polling_island are both NULL, create - * a new polling island (with a refcount of 2) and make the polling_island - * fields in both fd and pollset to point to the new island - * 3) If one of fd->polling_island or pollset->polling_island is NULL, update - * the NULL polling_island field to point to the non-NULL polling_island - * field (ensure that the refcount on the polling island is incremented by - * 1 to account for the newly added reference) - * 4) Finally, if fd->polling_island and pollset->polling_island are non-NULL - * and different, merge both the polling islands and update the - * polling_island fields in both fd and pollset to point to the merged - * polling island. + /* + * 1) If item->pi and bag->pi are both non-NULL and equal, do nothing + * 2) If item->pi and bag->pi are both NULL, create a new polling island (with + * a refcount of 2) and point item->pi and bag->pi to the new island + * 3) If exactly one of item->pi or bag->pi is NULL, update it to point to + * the other's non-NULL pi + * 4) Finally if item->pi and bag-pi are non-NULL and not-equal, merge the + * polling islands and update item->pi and bag->pi to point to the new + * island */ - if (fd->orphaned) { - gpr_mu_unlock(&fd->mu); - gpr_mu_unlock(&pollset->mu); - /* early out */ + /* Early out if we are trying to add an 'fd' to a 'bag' but the fd is already + * orphaned */ + if (item_type == POLL_OBJ_FD && (FD_FROM_PO(item))->orphaned) { + gpr_mu_unlock(&item->mu); + gpr_mu_unlock(&bag->mu); return; } - if (fd->polling_island == pollset->polling_island) { - pi_new = fd->polling_island; + if (item->pi == bag->pi) { + pi_new = item->pi; if (pi_new == NULL) { - /* Unlock before creating a new polling island: the polling island will - create a workqueue which creates a file descriptor, and holding an fd - lock here can eventually cause a loop to appear to TSAN (making it - unhappy). We don't think it's a real loop (there's an epoch point where - that loop possibility disappears), but the advantages of keeping TSAN - happy outweigh any performance advantage we might have by keeping the - lock held. */ - gpr_mu_unlock(&fd->mu); - pi_new = polling_island_create(exec_ctx, fd, &error); - gpr_mu_lock(&fd->mu); - /* Need to reverify any assumptions made between the initial lock and - getting to this branch: if they've changed, we need to throw away our - work and figure things out again. */ - if (fd->polling_island != NULL) { - GRPC_POLLING_TRACE( - "pollset_add_fd: Raced creating new polling island. pi_new: %p " - "(fd: %d, pollset: %p)", - (void *)pi_new, fd->fd, (void *)pollset); - - /* No need to lock 'pi_new' here since this is a new polling island and - * no one has a reference to it yet */ - polling_island_remove_all_fds_locked(pi_new, true, &error); - - /* Ref and unref so that the polling island gets deleted during unref */ - PI_ADD_REF(pi_new, "dance_of_destruction"); - PI_UNREF(exec_ctx, pi_new, "dance_of_destruction"); - goto retry; + /* GPR_ASSERT(item->pi == bag->pi == NULL) */ + + /* If we are adding an fd to a bag (i.e pollset or pollset_set), then + * we need to do some extra work to make TSAN happy */ + if (item_type == POLL_OBJ_FD) { + /* Unlock before creating a new polling island: the polling island will + create a workqueue which creates a file descriptor, and holding an fd + lock here can eventually cause a loop to appear to TSAN (making it + unhappy). We don't think it's a real loop (there's an epoch point + where that loop possibility disappears), but the advantages of + keeping TSAN happy outweigh any performance advantage we might have + by keeping the lock held. */ + gpr_mu_unlock(&item->mu); + pi_new = polling_island_create(exec_ctx, FD_FROM_PO(item), &error); + gpr_mu_lock(&item->mu); + + /* Need to reverify any assumptions made between the initial lock and + getting to this branch: if they've changed, we need to throw away our + work and figure things out again. */ + if (item->pi != NULL) { + GRPC_POLLING_TRACE( + "add_poll_object: Raced creating new polling island. pi_new: %p " + "(fd: %d, %s: %p)", + (void *)pi_new, FD_FROM_PO(item)->fd, poll_obj_string(bag_type), + (void *)bag); + /* No need to lock 'pi_new' here since this is a new polling island + * and no one has a reference to it yet */ + polling_island_remove_all_fds_locked(pi_new, true, &error); + + /* Ref and unref so that the polling island gets deleted during unref + */ + PI_ADD_REF(pi_new, "dance_of_destruction"); + PI_UNREF(exec_ctx, pi_new, "dance_of_destruction"); + goto retry; + } } else { - GRPC_POLLING_TRACE( - "pollset_add_fd: Created new polling island. pi_new: %p (fd: %d, " - "pollset: %p)", - (void *)pi_new, fd->fd, (void *)pollset); + pi_new = polling_island_create(exec_ctx, NULL, &error); } + + GRPC_POLLING_TRACE( + "add_poll_object: Created new polling island. pi_new: %p (%s: %p, " + "%s: %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); + } else { + GRPC_POLLING_TRACE( + "add_poll_object: Same polling island. pi: %p (%s, %s)", + (void *)pi_new, poll_obj_string(item_type), + poll_obj_string(bag_type)); + } + } else if (item->pi == NULL) { + /* GPR_ASSERT(bag->pi != NULL) */ + /* Make pi_new point to latest pi*/ + pi_new = polling_island_lock(bag->pi); + + if (item_type == POLL_OBJ_FD) { + grpc_fd *fd = FD_FROM_PO(item); + polling_island_add_fds_locked(pi_new, &fd, 1, true, &error); } - } else if (fd->polling_island == NULL) { - pi_new = polling_island_lock(pollset->polling_island); - polling_island_add_fds_locked(pi_new, &fd, 1, true, &error); - gpr_mu_unlock(&pi_new->mu); + gpr_mu_unlock(&pi_new->mu); GRPC_POLLING_TRACE( - "pollset_add_fd: fd->pi was NULL. pi_new: %p (fd: %d, pollset: %p, " - "pollset->pi: %p)", - (void *)pi_new, fd->fd, (void *)pollset, - (void *)pollset->polling_island); - } else if (pollset->polling_island == NULL) { - pi_new = polling_island_lock(fd->polling_island); + "add_poll_obj: item->pi was NULL. pi_new: %p (item(%s): %p, " + "bag(%s): %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); + } else if (bag->pi == NULL) { + /* GPR_ASSERT(item->pi != NULL) */ + /* Make pi_new to point to latest pi */ + pi_new = polling_island_lock(item->pi); gpr_mu_unlock(&pi_new->mu); - GRPC_POLLING_TRACE( - "pollset_add_fd: pollset->pi was NULL. pi_new: %p (fd: %d, pollset: " - "%p, fd->pi: %p", - (void *)pi_new, fd->fd, (void *)pollset, (void *)fd->polling_island); + "add_poll_obj: bag->pi was NULL. pi_new: %p (item(%s): %p, " + "bag(%s): %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); } else { - pi_new = polling_island_merge(fd->polling_island, pollset->polling_island, - &error); + pi_new = polling_island_merge(item->pi, bag->pi, &error); GRPC_POLLING_TRACE( - "pollset_add_fd: polling islands merged. pi_new: %p (fd: %d, pollset: " - "%p, fd->pi: %p, pollset->pi: %p)", - (void *)pi_new, fd->fd, (void *)pollset, (void *)fd->polling_island, - (void *)pollset->polling_island); + "add_poll_obj: polling islands merged. pi_new: %p (item(%s): %p, " + "bag(%s): %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); } - /* At this point, pi_new is the polling island that both fd->polling_island - and pollset->polling_island must be pointing to */ + /* At this point, pi_new is the polling island that both item->pi and bag->pi + MUST be pointing to */ - if (fd->polling_island != pi_new) { - PI_ADD_REF(pi_new, "fd"); - if (fd->polling_island != NULL) { - PI_UNREF(exec_ctx, fd->polling_island, "fd"); + if (item->pi != pi_new) { + PI_ADD_REF(pi_new, poll_obj_string(item_type)); + if (item->pi != NULL) { + PI_UNREF(exec_ctx, item->pi, poll_obj_string(item_type)); } - fd->polling_island = pi_new; + item->pi = pi_new; } - if (pollset->polling_island != pi_new) { - PI_ADD_REF(pi_new, "ps"); - if (pollset->polling_island != NULL) { - PI_UNREF(exec_ctx, pollset->polling_island, "ps"); + if (bag->pi != pi_new) { + PI_ADD_REF(pi_new, poll_obj_string(bag_type)); + if (bag->pi != NULL) { + PI_UNREF(exec_ctx, bag->pi, poll_obj_string(bag_type)); } - pollset->polling_island = pi_new; + bag->pi = pi_new; } - gpr_mu_unlock(&fd->mu); - gpr_mu_unlock(&pollset->mu); + gpr_mu_unlock(&item->mu); + gpr_mu_unlock(&bag->mu); - GRPC_LOG_IF_ERROR("pollset_add_fd", error); + GRPC_LOG_IF_ERROR("add_poll_object", error); + GPR_TIMER_END("add_poll_object", 0); +} - GPR_TIMER_END("pollset_add_fd", 0); +static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_fd *fd) { + add_poll_object(exec_ctx, &pollset->po, POLL_OBJ_POLLSET, &fd->po, + POLL_OBJ_FD); } /******************************************************************************* @@ -1784,142 +1825,60 @@ retry: */ static grpc_pollset_set *pollset_set_create(void) { - grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set)); - memset(pollset_set, 0, sizeof(*pollset_set)); - gpr_mu_init(&pollset_set->mu); - return pollset_set; + grpc_pollset_set *pss = gpr_malloc(sizeof(*pss)); + gpr_mu_init(&pss->po.mu); + pss->po.pi = NULL; +#ifdef PO_DEBUG + pss->po.obj_type = POLL_OBJ_POLLSET_SET; +#endif + return pss; } -static void pollset_set_destroy(grpc_pollset_set *pollset_set) { - size_t i; - gpr_mu_destroy(&pollset_set->mu); - for (i = 0; i < pollset_set->fd_count; i++) { - GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); +static void pollset_set_destroy(grpc_pollset_set *pss) { + gpr_mu_destroy(&pss->po.mu); + + if (pss->po.pi != NULL) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + PI_UNREF(&exec_ctx, pss->po.pi, "pss_destroy"); + grpc_exec_ctx_finish(&exec_ctx); } - gpr_free(pollset_set->pollsets); - gpr_free(pollset_set->pollset_sets); - gpr_free(pollset_set->fds); - gpr_free(pollset_set); + + gpr_free(pss); } -static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - if (pollset_set->fd_count == pollset_set->fd_capacity) { - pollset_set->fd_capacity = GPR_MAX(8, 2 * pollset_set->fd_capacity); - pollset_set->fds = gpr_realloc( - pollset_set->fds, pollset_set->fd_capacity * sizeof(*pollset_set->fds)); - } - GRPC_FD_REF(fd, "pollset_set"); - pollset_set->fds[pollset_set->fd_count++] = fd; - for (i = 0; i < pollset_set->pollset_count; i++) { - pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd); - } - for (i = 0; i < pollset_set->pollset_set_count; i++) { - pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd); - } - gpr_mu_unlock(&pollset_set->mu); +static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) { + add_poll_object(exec_ctx, &pss->po, POLL_OBJ_POLLSET_SET, &fd->po, + POLL_OBJ_FD); } -static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - for (i = 0; i < pollset_set->fd_count; i++) { - if (pollset_set->fds[i] == fd) { - pollset_set->fd_count--; - GPR_SWAP(grpc_fd *, pollset_set->fds[i], - pollset_set->fds[pollset_set->fd_count]); - GRPC_FD_UNREF(fd, "pollset_set"); - break; - } - } - for (i = 0; i < pollset_set->pollset_set_count; i++) { - pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd); - } - gpr_mu_unlock(&pollset_set->mu); +static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) { + /* Nothing to do */ } static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset) { - size_t i, j; - gpr_mu_lock(&pollset_set->mu); - if (pollset_set->pollset_count == pollset_set->pollset_capacity) { - pollset_set->pollset_capacity = - GPR_MAX(8, 2 * pollset_set->pollset_capacity); - pollset_set->pollsets = - gpr_realloc(pollset_set->pollsets, pollset_set->pollset_capacity * - sizeof(*pollset_set->pollsets)); - } - pollset_set->pollsets[pollset_set->pollset_count++] = pollset; - for (i = 0, j = 0; i < pollset_set->fd_count; i++) { - if (fd_is_orphaned(pollset_set->fds[i])) { - GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); - } else { - pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]); - pollset_set->fds[j++] = pollset_set->fds[i]; - } - } - pollset_set->fd_count = j; - gpr_mu_unlock(&pollset_set->mu); + grpc_pollset_set *pss, grpc_pollset *ps) { + add_poll_object(exec_ctx, &pss->po, POLL_OBJ_POLLSET_SET, &ps->po, + POLL_OBJ_POLLSET); } static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - for (i = 0; i < pollset_set->pollset_count; i++) { - if (pollset_set->pollsets[i] == pollset) { - pollset_set->pollset_count--; - GPR_SWAP(grpc_pollset *, pollset_set->pollsets[i], - pollset_set->pollsets[pollset_set->pollset_count]); - break; - } - } - gpr_mu_unlock(&pollset_set->mu); + grpc_pollset_set *pss, grpc_pollset *ps) { + /* Nothing to do */ } static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { - size_t i, j; - gpr_mu_lock(&bag->mu); - if (bag->pollset_set_count == bag->pollset_set_capacity) { - bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity); - bag->pollset_sets = - gpr_realloc(bag->pollset_sets, - bag->pollset_set_capacity * sizeof(*bag->pollset_sets)); - } - bag->pollset_sets[bag->pollset_set_count++] = item; - for (i = 0, j = 0; i < bag->fd_count; i++) { - if (fd_is_orphaned(bag->fds[i])) { - GRPC_FD_UNREF(bag->fds[i], "pollset_set"); - } else { - pollset_set_add_fd(exec_ctx, item, bag->fds[i]); - bag->fds[j++] = bag->fds[i]; - } - } - bag->fd_count = j; - gpr_mu_unlock(&bag->mu); + add_poll_object(exec_ctx, &bag->po, POLL_OBJ_POLLSET_SET, &item->po, + POLL_OBJ_POLLSET_SET); } static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, grpc_pollset_set *bag, grpc_pollset_set *item) { - size_t i; - gpr_mu_lock(&bag->mu); - for (i = 0; i < bag->pollset_set_count; i++) { - if (bag->pollset_sets[i] == item) { - bag->pollset_set_count--; - GPR_SWAP(grpc_pollset_set *, bag->pollset_sets[i], - bag->pollset_sets[bag->pollset_set_count]); - break; - } - } - gpr_mu_unlock(&bag->mu); + /* Nothing to do */ } /* Test helper functions @@ -1927,9 +1886,9 @@ static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, void *grpc_fd_get_polling_island(grpc_fd *fd) { polling_island *pi; - gpr_mu_lock(&fd->mu); - pi = fd->polling_island; - gpr_mu_unlock(&fd->mu); + gpr_mu_lock(&fd->po.mu); + pi = fd->po.pi; + gpr_mu_unlock(&fd->po.mu); return pi; } @@ -1937,9 +1896,9 @@ void *grpc_fd_get_polling_island(grpc_fd *fd) { void *grpc_pollset_get_polling_island(grpc_pollset *ps) { polling_island *pi; - gpr_mu_lock(&ps->mu); - pi = ps->polling_island; - gpr_mu_unlock(&ps->mu); + gpr_mu_lock(&ps->po.mu); + pi = ps->po.pi; + gpr_mu_unlock(&ps->po.mu); return pi; } diff --git a/src/core/lib/iomgr/iomgr.c b/src/core/lib/iomgr/iomgr.c index 4fd83e0b22..3470b5ac81 100644 --- a/src/core/lib/iomgr/iomgr.c +++ b/src/core/lib/iomgr/iomgr.c @@ -108,6 +108,7 @@ void grpc_iomgr_shutdown(void) { NULL)) { gpr_mu_unlock(&g_mu); grpc_exec_ctx_flush(&exec_ctx); + grpc_iomgr_platform_flush(); gpr_mu_lock(&g_mu); continue; } diff --git a/src/core/lib/iomgr/resource_quota.c b/src/core/lib/iomgr/resource_quota.c index 051a30baa3..213d29600c 100644 --- a/src/core/lib/iomgr/resource_quota.c +++ b/src/core/lib/iomgr/resource_quota.c @@ -104,6 +104,9 @@ struct grpc_resource_user { /* Reclaimers: index 0 is the benign reclaimer, 1 is the destructive reclaimer */ grpc_closure *reclaimers[2]; + /* Reclaimers just posted: once we're in the combiner lock, we'll move them + to the array above */ + grpc_closure *new_reclaimers[2]; /* Trampoline closures to finish reclamation and re-enter the quota combiner lock */ grpc_closure post_reclaimer_closure[2]; @@ -141,6 +144,12 @@ struct grpc_resource_quota { /* Closure around rq_reclamation_done */ grpc_closure rq_reclamation_done_closure; + /* This is only really usable for debugging: it's always a stale pointer, but + a stale pointer that might just be fresh enough to guide us to where the + reclamation system is stuck */ + grpc_closure *debug_only_last_initiated_reclaimer; + grpc_resource_user *debug_only_last_reclaimer_resource_user; + /* Roots of all resource user lists */ grpc_resource_user *roots[GRPC_RULIST_COUNT]; @@ -222,6 +231,7 @@ static void rulist_remove(grpc_resource_user *resource_user, grpc_rulist list) { resource_user->links[list].prev; resource_user->links[list].prev->links[list].next = resource_user->links[list].next; + resource_user->links[list].next = resource_user->links[list].prev = NULL; } /******************************************************************************* @@ -337,6 +347,9 @@ static bool rq_reclaim(grpc_exec_ctx *exec_ctx, resource_quota->reclaiming = true; grpc_resource_quota_internal_ref(resource_quota); grpc_closure *c = resource_user->reclaimers[destructive]; + GPR_ASSERT(c); + resource_quota->debug_only_last_reclaimer_resource_user = resource_user; + resource_quota->debug_only_last_initiated_reclaimer = c; resource_user->reclaimers[destructive] = NULL; grpc_closure_run(exec_ctx, c, GRPC_ERROR_NONE); return true; @@ -418,9 +431,25 @@ static void ru_add_to_free_pool(grpc_exec_ctx *exec_ctx, void *ru, rulist_add_tail(resource_user, GRPC_RULIST_NON_EMPTY_FREE_POOL); } +static bool ru_post_reclaimer(grpc_exec_ctx *exec_ctx, + grpc_resource_user *resource_user, + bool destructive) { + grpc_closure *closure = resource_user->new_reclaimers[destructive]; + GPR_ASSERT(closure != NULL); + resource_user->new_reclaimers[destructive] = NULL; + GPR_ASSERT(resource_user->reclaimers[destructive] == NULL); + if (gpr_atm_acq_load(&resource_user->shutdown) > 0) { + grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CANCELLED, NULL); + return false; + } + resource_user->reclaimers[destructive] = closure; + return true; +} + static void ru_post_benign_reclaimer(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; + if (!ru_post_reclaimer(exec_ctx, resource_user, false)) return; if (!rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION) && rulist_empty(resource_user->resource_quota, @@ -435,6 +464,7 @@ static void ru_post_benign_reclaimer(grpc_exec_ctx *exec_ctx, void *ru, static void ru_post_destructive_reclaimer(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { grpc_resource_user *resource_user = ru; + if (!ru_post_reclaimer(exec_ctx, resource_user, true)) return; if (!rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION) && rulist_empty(resource_user->resource_quota, @@ -456,6 +486,8 @@ static void ru_shutdown(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { GRPC_ERROR_CANCELLED, NULL); resource_user->reclaimers[0] = NULL; resource_user->reclaimers[1] = NULL; + rulist_remove(resource_user, GRPC_RULIST_RECLAIMER_BENIGN); + rulist_remove(resource_user, GRPC_RULIST_RECLAIMER_DESTRUCTIVE); } static void ru_destroy(grpc_exec_ctx *exec_ctx, void *ru, grpc_error *error) { @@ -649,6 +681,8 @@ grpc_resource_user *grpc_resource_user_create( resource_user->added_to_free_pool = false; resource_user->reclaimers[0] = NULL; resource_user->reclaimers[1] = NULL; + resource_user->new_reclaimers[0] = NULL; + resource_user->new_reclaimers[1] = NULL; for (int i = 0; i < GRPC_RULIST_COUNT; i++) { resource_user->links[i].next = resource_user->links[i].prev = NULL; } @@ -748,12 +782,8 @@ void grpc_resource_user_post_reclaimer(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user, bool destructive, grpc_closure *closure) { - GPR_ASSERT(resource_user->reclaimers[destructive] == NULL); - if (gpr_atm_acq_load(&resource_user->shutdown) > 0) { - grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CANCELLED, NULL); - return; - } - resource_user->reclaimers[destructive] = closure; + GPR_ASSERT(resource_user->new_reclaimers[destructive] == NULL); + resource_user->new_reclaimers[destructive] = closure; grpc_combiner_execute(exec_ctx, resource_user->resource_quota->combiner, &resource_user->post_reclaimer_closure[destructive], GRPC_ERROR_NONE, false); diff --git a/src/core/lib/iomgr/socket_windows.c b/src/core/lib/iomgr/socket_windows.c index 35f23300dc..54911e0e31 100644 --- a/src/core/lib/iomgr/socket_windows.c +++ b/src/core/lib/iomgr/socket_windows.c @@ -76,6 +76,14 @@ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) { LPFN_DISCONNECTEX DisconnectEx; DWORD ioctl_num_bytes; + gpr_mu_lock(&winsocket->state_mu); + if (winsocket->shutdown_called) { + gpr_mu_unlock(&winsocket->state_mu); + return; + } + winsocket->shutdown_called = true; + gpr_mu_unlock(&winsocket->state_mu); + status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx), &ioctl_num_bytes, NULL, NULL); diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h index 490d0e0a06..a3875ce16c 100644 --- a/src/core/lib/iomgr/socket_windows.h +++ b/src/core/lib/iomgr/socket_windows.h @@ -87,6 +87,7 @@ typedef struct grpc_winsocket { grpc_winsocket_callback_info read_info; gpr_mu state_mu; + bool shutdown_called; /* You can't add the same socket twice to the same IO Completion Port. This prevents that. */ diff --git a/src/core/lib/iomgr/tcp_client_windows.c b/src/core/lib/iomgr/tcp_client_windows.c index 4d1e809872..1127588ebc 100644 --- a/src/core/lib/iomgr/tcp_client_windows.c +++ b/src/core/lib/iomgr/tcp_client_windows.c @@ -107,18 +107,22 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { gpr_mu_lock(&ac->mu); - if (error == GRPC_ERROR_NONE && socket != NULL) { - DWORD transfered_bytes = 0; - DWORD flags; - BOOL wsa_success = - WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped, - &transfered_bytes, FALSE, &flags); - GPR_ASSERT(transfered_bytes == 0); - if (!wsa_success) { - error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx"); + if (error == GRPC_ERROR_NONE) { + if (socket != NULL) { + DWORD transfered_bytes = 0; + DWORD flags; + BOOL wsa_success = + WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped, + &transfered_bytes, FALSE, &flags); + GPR_ASSERT(transfered_bytes == 0); + if (!wsa_success) { + error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx"); + } else { + *ep = grpc_tcp_create(socket, ac->resource_quota, ac->addr_name); + socket = NULL; + } } else { - *ep = grpc_tcp_create(socket, ac->resource_quota, ac->addr_name); - socket = NULL; + error = GRPC_ERROR_CREATE("socket is null"); } } diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index 12a4797e6f..540305e4fa 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -107,6 +107,12 @@ typedef struct { grpc_resource_user_slice_allocator slice_allocator; } grpc_tcp; +static grpc_error *tcp_annotate_error(grpc_error *src_error, grpc_tcp *tcp) { + return grpc_error_set_str( + grpc_error_set_int(src_error, GRPC_ERROR_INT_FD, tcp->fd), + GRPC_ERROR_STR_TARGET_ADDRESS, tcp->peer_string); +} + static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, grpc_error *error); static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, @@ -230,13 +236,15 @@ static void tcp_do_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure); } else { grpc_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(exec_ctx, tcp, GRPC_OS_ERROR(errno, "recvmsg")); + call_read_cb(exec_ctx, tcp, + tcp_annotate_error(GRPC_OS_ERROR(errno, "recvmsg"), tcp)); TCP_UNREF(exec_ctx, tcp, "read"); } } else if (read_bytes == 0) { /* 0 read size ==> end of stream */ grpc_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(exec_ctx, tcp, GRPC_ERROR_CREATE("Socket closed")); + call_read_cb(exec_ctx, tcp, + tcp_annotate_error(GRPC_ERROR_CREATE("Socket closed"), tcp)); TCP_UNREF(exec_ctx, tcp, "read"); } else { GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); @@ -365,8 +373,13 @@ static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) { tcp->outgoing_slice_idx = unwind_slice_idx; tcp->outgoing_byte_idx = unwind_byte_idx; return false; + } else if (errno == EPIPE) { + *error = grpc_error_set_int(GRPC_OS_ERROR(errno, "sendmsg"), + GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAVAILABLE); + return true; } else { - *error = GRPC_OS_ERROR(errno, "sendmsg"); + *error = tcp_annotate_error(GRPC_OS_ERROR(errno, "sendmsg"), tcp); return true; } } @@ -447,9 +460,10 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, if (buf->length == 0) { GPR_TIMER_END("tcp_write", 0); - grpc_exec_ctx_sched(exec_ctx, cb, grpc_fd_is_shutdown(tcp->em_fd) - ? GRPC_ERROR_CREATE("EOF") - : GRPC_ERROR_NONE, + grpc_exec_ctx_sched(exec_ctx, cb, + grpc_fd_is_shutdown(tcp->em_fd) + ? tcp_annotate_error(GRPC_ERROR_CREATE("EOF"), tcp) + : GRPC_ERROR_NONE, NULL); return; } diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h index 6eba8c4057..437a94beff 100644 --- a/src/core/lib/iomgr/tcp_server.h +++ b/src/core/lib/iomgr/tcp_server.h @@ -52,7 +52,8 @@ typedef struct grpc_tcp_server_acceptor { unsigned fd_index; } grpc_tcp_server_acceptor; -/* Called for newly connected TCP connections. */ +/* Called for newly connected TCP connections. + Takes ownership of acceptor. */ typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *ep, grpc_pollset *accepting_pollset, diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 7e2fb0f1f9..179f47ef76 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -381,16 +381,12 @@ error: /* event manager callback when reads are ready */ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { grpc_tcp_listener *sp = arg; - grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, - sp->fd_index}; - grpc_pollset *read_notifier_pollset = NULL; - grpc_fd *fdobj; if (err != GRPC_ERROR_NONE) { goto error; } - read_notifier_pollset = + grpc_pollset *read_notifier_pollset = sp->server->pollsets[(size_t)gpr_atm_no_barrier_fetch_add( &sp->server->next_pollset_to_assign, 1) % sp->server->pollset_count]; @@ -426,7 +422,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str); } - fdobj = grpc_fd_create(fd, name); + grpc_fd *fdobj = grpc_fd_create(fd, name); if (read_notifier_pollset == NULL) { gpr_log(GPR_ERROR, "Read notifier pollset is not set on the fd"); @@ -435,11 +431,17 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj); + // Create acceptor. + grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor)); + acceptor->from_server = sp->server; + acceptor->port_index = sp->port_index; + acceptor->fd_index = sp->fd_index; + sp->server->on_accept_cb( exec_ctx, sp->server->on_accept_cb_arg, grpc_tcp_create(fdobj, sp->server->resource_quota, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str), - read_notifier_pollset, &acceptor); + read_notifier_pollset, acceptor); gpr_free(name); gpr_free(addr_str); diff --git a/src/core/lib/iomgr/tcp_server_uv.c b/src/core/lib/iomgr/tcp_server_uv.c index b5b9b92a20..e1a174cfa2 100644 --- a/src/core/lib/iomgr/tcp_server_uv.c +++ b/src/core/lib/iomgr/tcp_server_uv.c @@ -188,7 +188,6 @@ static void accepted_connection_close_cb(uv_handle_t *handle) { static void on_connect(uv_stream_t *server, int status) { grpc_tcp_listener *sp = (grpc_tcp_listener *)server->data; - grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0}; uv_tcp_t *client; grpc_endpoint *ep = NULL; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; @@ -201,6 +200,7 @@ static void on_connect(uv_stream_t *server, int status) { uv_strerror(status)); return; } + client = gpr_malloc(sizeof(uv_tcp_t)); uv_tcp_init(uv_default_loop(), client); // UV documentation says this is guaranteed to succeed @@ -220,8 +220,13 @@ static void on_connect(uv_stream_t *server, int status) { gpr_log(GPR_INFO, "uv_tcp_getpeername error: %s", uv_strerror(status)); } ep = grpc_tcp_create(client, sp->server->resource_quota, peer_name_string); + // Create acceptor. + grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor)); + acceptor->from_server = sp->server; + acceptor->port_index = sp->port_index; + acceptor->fd_index = 0; sp->server->on_accept_cb(&exec_ctx, sp->server->on_accept_cb_arg, ep, NULL, - &acceptor); + acceptor); grpc_exec_ctx_finish(&exec_ctx); } } diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c index ae54c70d2d..b0c8586bac 100644 --- a/src/core/lib/iomgr/tcp_server_windows.c +++ b/src/core/lib/iomgr/tcp_server_windows.c @@ -73,6 +73,7 @@ struct grpc_tcp_listener { /* The cached AcceptEx for that port. */ LPFN_ACCEPTEX AcceptEx; int shutting_down; + int outstanding_calls; /* closure for socket notification of accept being ready */ grpc_closure on_accept; /* linked list */ @@ -140,10 +141,9 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx, return GRPC_ERROR_NONE; } -static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - if (s->shutdown_complete != NULL) { - grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); - } +static void destroy_server(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_tcp_server *s = arg; /* Now that the accepts have been aborted, we can destroy the sockets. The IOCP won't get notified on these, so we can flag them as already @@ -159,6 +159,16 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { gpr_free(s); } +static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, + grpc_tcp_server *s) { + if (s->shutdown_complete != NULL) { + grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); + } + + grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(destroy_server, s), + GRPC_ERROR_NONE, NULL); +} + grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { gpr_ref_non_zero(&s->refs); return s; @@ -180,17 +190,14 @@ static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { /* First, shutdown all fd's. This will queue abortion calls for all of the pending accepts due to the normal operation mechanism. */ if (s->active_ports == 0) { - immediately_done = 1; - } - for (sp = s->head; sp; sp = sp->next) { - sp->shutting_down = 1; - grpc_winsocket_shutdown(sp->socket); + finish_shutdown_locked(exec_ctx, s); + } else { + for (sp = s->head; sp; sp = sp->next) { + sp->shutting_down = 1; + grpc_winsocket_shutdown(sp->socket); + } } gpr_mu_unlock(&s->mu); - - if (immediately_done) { - finish_shutdown(exec_ctx, s); - } } void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { @@ -251,31 +258,30 @@ failure: return error; } -static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx, - grpc_tcp_listener *sp) { +static void decrement_active_ports_and_notify_locked(grpc_exec_ctx *exec_ctx, + grpc_tcp_listener *sp) { int notify = 0; sp->shutting_down = 0; - gpr_mu_lock(&sp->server->mu); GPR_ASSERT(sp->server->active_ports > 0); if (0 == --sp->server->active_ports) { - notify = 1; - } - gpr_mu_unlock(&sp->server->mu); - if (notify) { - finish_shutdown(exec_ctx, sp->server); + finish_shutdown_locked(exec_ctx, sp->server); } } /* In order to do an async accept, we need to create a socket first which will be the one assigned to the new incoming connection. */ -static grpc_error *start_accept(grpc_exec_ctx *exec_ctx, - grpc_tcp_listener *port) { +static grpc_error *start_accept_locked(grpc_exec_ctx *exec_ctx, + grpc_tcp_listener *port) { SOCKET sock = INVALID_SOCKET; BOOL success; DWORD addrlen = sizeof(struct sockaddr_in6) + 16; DWORD bytes_received = 0; grpc_error *error = GRPC_ERROR_NONE; + if (port->shutting_down) { + return GRPC_ERROR_NONE; + } + sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) { @@ -305,20 +311,11 @@ static grpc_error *start_accept(grpc_exec_ctx *exec_ctx, immediately process an accept that happened in the meantime. */ port->new_socket = sock; grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept); + port->outstanding_calls++; return error; failure: GPR_ASSERT(error != GRPC_ERROR_NONE); - if (port->shutting_down) { - /* We are abandoning the listener port, take that into account to prevent - occasional hangs on shutdown. The hang happens when sp->shutting_down - change is not seen by on_accept and we proceed to trying new accept, - but we fail there because the listening port has been closed in the - meantime. */ - decrement_active_ports_and_notify(exec_ctx, port); - GRPC_ERROR_UNREF(error); - return GRPC_ERROR_NONE; - } if (sock != INVALID_SOCKET) closesocket(sock); return error; } @@ -326,7 +323,6 @@ failure: /* Event manager callback when reads are ready. */ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_tcp_listener *sp = arg; - grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0}; SOCKET sock = sp->new_socket; grpc_winsocket_callback_info *info = &sp->socket->read_info; grpc_endpoint *ep = NULL; @@ -338,6 +334,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { BOOL wsa_success; int err; + gpr_mu_lock(&sp->server->mu); + peer_name.len = sizeof(struct sockaddr_storage); /* The general mechanism for shutting down is to queue abortion calls. While @@ -347,6 +345,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { const char *msg = grpc_error_string(error); gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg); grpc_error_free_string(msg); + gpr_mu_unlock(&sp->server->mu); return; } @@ -356,17 +355,12 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, &transfered_bytes, FALSE, &flags); if (!wsa_success) { - if (sp->shutting_down) { - /* During the shutdown case, we ARE expecting an error. So that's well, - and we can wake up the shutdown thread. */ - decrement_active_ports_and_notify(exec_ctx, sp); - return; - } else { + if (!sp->shutting_down) { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message); gpr_free(utf8_message); - closesocket(sock); } + closesocket(sock); } else { if (!sp->shutting_down) { peer_name_string = NULL; @@ -401,14 +395,24 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { /* The only time we should call our callback, is where we successfully managed to accept a connection, and created an endpoint. */ if (ep) { + // Create acceptor. + grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor)); + acceptor->from_server = sp->server; + acceptor->port_index = sp->port_index; + acceptor->fd_index = 0; sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep, NULL, - &acceptor); + acceptor); } /* As we were notified from the IOCP of one and exactly one accept, the former socked we created has now either been destroy or assigned to the new connection. We need to create a new one for the next connection. */ - GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp))); + GPR_ASSERT( + GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp))); + if (0 == --sp->outstanding_calls) { + decrement_active_ports_and_notify_locked(exec_ctx, sp); + } + gpr_mu_unlock(&sp->server->mu); } static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock, @@ -456,6 +460,7 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock, sp->server = s; sp->socket = grpc_winsocket_create(sock, "listener"); sp->shutting_down = 0; + sp->outstanding_calls = 0; sp->AcceptEx = AcceptEx; sp->new_socket = INVALID_SOCKET; sp->port = port; @@ -553,7 +558,8 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, s->on_accept_cb = on_accept_cb; s->on_accept_cb_arg = on_accept_cb_arg; for (sp = s->head; sp; sp = sp->next) { - GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp))); + GPR_ASSERT( + GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp))); s->active_ports++; } gpr_mu_unlock(&s->mu); diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index fd0c7a0f9d..3c24ea9afa 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -388,7 +388,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, /* Try listening on IPv6 first. */ addr = &wild6; // TODO(rjshade): Test and propagate the returned grpc_error*: - grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd); + GRPC_ERROR_UNREF(grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, + &dsmode, &fd)); allocated_port1 = add_socket_to_server(s, fd, addr, read_cb, orphan_cb); if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { goto done; @@ -402,7 +403,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, } // TODO(rjshade): Test and propagate the returned grpc_error*: - grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd); + GRPC_ERROR_UNREF(grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, + &dsmode, &fd)); if (fd < 0) { gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); } diff --git a/src/core/lib/security/transport/handshake.c b/src/core/lib/security/transport/handshake.c deleted file mode 100644 index 9623797610..0000000000 --- a/src/core/lib/security/transport/handshake.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "src/core/lib/security/transport/handshake.h" - -#include <stdbool.h> -#include <string.h> - -#include <grpc/slice_buffer.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include "src/core/lib/iomgr/timer.h" -#include "src/core/lib/security/context/security_context.h" -#include "src/core/lib/security/transport/secure_endpoint.h" -#include "src/core/lib/security/transport/tsi_error.h" - -#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 - -typedef struct { - grpc_security_connector *connector; - tsi_handshaker *handshaker; - bool is_client_side; - unsigned char *handshake_buffer; - size_t handshake_buffer_size; - grpc_endpoint *wrapped_endpoint; - grpc_endpoint *secure_endpoint; - grpc_slice_buffer left_overs; - grpc_slice_buffer incoming; - grpc_slice_buffer outgoing; - grpc_security_handshake_done_cb cb; - void *user_data; - grpc_closure on_handshake_data_sent_to_peer; - grpc_closure on_handshake_data_received_from_peer; - grpc_auth_context *auth_context; - grpc_timer timer; - gpr_refcount refs; -} grpc_security_handshake; - -static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, - void *setup, - grpc_error *error); - -static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup, - grpc_error *error); - -static void security_connector_remove_handshake(grpc_security_handshake *h) { - GPR_ASSERT(!h->is_client_side); - grpc_security_connector_handshake_list *node; - grpc_security_connector_handshake_list *tmp; - grpc_server_security_connector *sc = - (grpc_server_security_connector *)h->connector; - gpr_mu_lock(&sc->mu); - node = sc->handshaking_handshakes; - if (node && node->handshake == h) { - sc->handshaking_handshakes = node->next; - gpr_free(node); - gpr_mu_unlock(&sc->mu); - return; - } - while (node) { - if (node->next->handshake == h) { - tmp = node->next; - node->next = node->next->next; - gpr_free(tmp); - gpr_mu_unlock(&sc->mu); - return; - } - node = node->next; - } - gpr_mu_unlock(&sc->mu); -} - -static void unref_handshake(grpc_security_handshake *h) { - if (gpr_unref(&h->refs)) { - if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker); - if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer); - grpc_slice_buffer_destroy(&h->left_overs); - grpc_slice_buffer_destroy(&h->outgoing); - grpc_slice_buffer_destroy(&h->incoming); - GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); - GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake"); - gpr_free(h); - } -} - -static void security_handshake_done(grpc_exec_ctx *exec_ctx, - grpc_security_handshake *h, - grpc_error *error) { - grpc_timer_cancel(exec_ctx, &h->timer); - if (!h->is_client_side) { - security_connector_remove_handshake(h); - } - if (error == GRPC_ERROR_NONE) { - h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint, - h->auth_context); - } else { - const char *msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg); - grpc_error_free_string(msg); - - if (h->secure_endpoint != NULL) { - grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint); - grpc_endpoint_destroy(exec_ctx, h->secure_endpoint); - } else { - grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint); - } - h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL); - } - unref_handshake(h); - GRPC_ERROR_UNREF(error); -} - -static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_security_status status, - grpc_auth_context *auth_context) { - grpc_security_handshake *h = user_data; - tsi_frame_protector *protector; - tsi_result result; - if (status != GRPC_SECURITY_OK) { - security_handshake_done( - exec_ctx, h, - grpc_error_set_int(GRPC_ERROR_CREATE("Error checking peer."), - GRPC_ERROR_INT_SECURITY_STATUS, status)); - return; - } - h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake"); - result = - tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector); - if (result != TSI_OK) { - security_handshake_done( - exec_ctx, h, - grpc_set_tsi_error_result( - GRPC_ERROR_CREATE("Frame protector creation failed"), result)); - return; - } - h->secure_endpoint = - grpc_secure_endpoint_create(protector, h->wrapped_endpoint, - h->left_overs.slices, h->left_overs.count); - h->left_overs.count = 0; - h->left_overs.length = 0; - security_handshake_done(exec_ctx, h, GRPC_ERROR_NONE); - return; -} - -static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) { - tsi_peer peer; - tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); - - if (result != TSI_OK) { - security_handshake_done( - exec_ctx, h, grpc_set_tsi_error_result( - GRPC_ERROR_CREATE("Peer extraction failed"), result)); - return; - } - grpc_security_connector_check_peer(exec_ctx, h->connector, peer, - on_peer_checked, h); -} - -static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx, - grpc_security_handshake *h) { - size_t offset = 0; - tsi_result result = TSI_OK; - grpc_slice to_send; - - do { - size_t to_send_size = h->handshake_buffer_size - offset; - result = tsi_handshaker_get_bytes_to_send_to_peer( - h->handshaker, h->handshake_buffer + offset, &to_send_size); - offset += to_send_size; - if (result == TSI_INCOMPLETE_DATA) { - h->handshake_buffer_size *= 2; - h->handshake_buffer = - gpr_realloc(h->handshake_buffer, h->handshake_buffer_size); - } - } while (result == TSI_INCOMPLETE_DATA); - - if (result != TSI_OK) { - security_handshake_done(exec_ctx, h, - grpc_set_tsi_error_result( - GRPC_ERROR_CREATE("Handshake failed"), result)); - return; - } - - to_send = - grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset); - grpc_slice_buffer_reset_and_unref(&h->outgoing); - grpc_slice_buffer_add(&h->outgoing, to_send); - /* TODO(klempner,jboeuf): This should probably use the client setup - deadline */ - grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing, - &h->on_handshake_data_sent_to_peer); -} - -static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, - void *handshake, - grpc_error *error) { - grpc_security_handshake *h = handshake; - size_t consumed_slice_size = 0; - tsi_result result = TSI_OK; - size_t i; - size_t num_left_overs; - int has_left_overs_in_current_slice = 0; - - if (error != GRPC_ERROR_NONE) { - security_handshake_done( - exec_ctx, h, - GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1)); - return; - } - - for (i = 0; i < h->incoming.count; i++) { - consumed_slice_size = GRPC_SLICE_LENGTH(h->incoming.slices[i]); - result = tsi_handshaker_process_bytes_from_peer( - h->handshaker, GRPC_SLICE_START_PTR(h->incoming.slices[i]), - &consumed_slice_size); - if (!tsi_handshaker_is_in_progress(h->handshaker)) break; - } - - if (tsi_handshaker_is_in_progress(h->handshaker)) { - /* We may need more data. */ - if (result == TSI_INCOMPLETE_DATA) { - grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, - &h->on_handshake_data_received_from_peer); - return; - } else { - send_handshake_bytes_to_peer(exec_ctx, h); - return; - } - } - - if (result != TSI_OK) { - security_handshake_done(exec_ctx, h, - grpc_set_tsi_error_result( - GRPC_ERROR_CREATE("Handshake failed"), result)); - return; - } - - /* Handshake is done and successful this point. */ - has_left_overs_in_current_slice = - (consumed_slice_size < GRPC_SLICE_LENGTH(h->incoming.slices[i])); - num_left_overs = - (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1; - if (num_left_overs == 0) { - check_peer(exec_ctx, h); - return; - } - - /* Put the leftovers in our buffer (ownership transfered). */ - if (has_left_overs_in_current_slice) { - grpc_slice_buffer_add( - &h->left_overs, - grpc_slice_split_tail(&h->incoming.slices[i], consumed_slice_size)); - grpc_slice_unref( - h->incoming.slices[i]); /* split_tail above increments refcount. */ - } - grpc_slice_buffer_addn( - &h->left_overs, &h->incoming.slices[i + 1], - num_left_overs - (size_t)has_left_overs_in_current_slice); - check_peer(exec_ctx, h); -} - -/* If handshake is NULL, the handshake is done. */ -static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, - void *handshake, grpc_error *error) { - grpc_security_handshake *h = handshake; - - /* Make sure that write is OK. */ - if (error != GRPC_ERROR_NONE) { - if (handshake != NULL) - security_handshake_done( - exec_ctx, h, - GRPC_ERROR_CREATE_REFERENCING("Handshake write failed", &error, 1)); - return; - } - - /* We may be done. */ - if (tsi_handshaker_is_in_progress(h->handshaker)) { - /* TODO(klempner,jboeuf): This should probably use the client setup - deadline */ - grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, - &h->on_handshake_data_received_from_peer); - } else { - check_peer(exec_ctx, h); - } -} - -static void on_timeout(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_security_handshake *h = arg; - if (error == GRPC_ERROR_NONE) { - grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint); - } - unref_handshake(h); -} - -void grpc_do_security_handshake( - grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, - grpc_security_connector *connector, bool is_client_side, - grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer, - gpr_timespec deadline, grpc_security_handshake_done_cb cb, - void *user_data) { - grpc_security_connector_handshake_list *handshake_node; - grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake)); - memset(h, 0, sizeof(grpc_security_handshake)); - h->handshaker = handshaker; - h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake"); - h->is_client_side = is_client_side; - h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE; - h->handshake_buffer = gpr_malloc(h->handshake_buffer_size); - h->wrapped_endpoint = nonsecure_endpoint; - h->user_data = user_data; - h->cb = cb; - gpr_ref_init(&h->refs, 2); /* timer and handshake proper each get a ref */ - grpc_closure_init(&h->on_handshake_data_sent_to_peer, - on_handshake_data_sent_to_peer, h); - grpc_closure_init(&h->on_handshake_data_received_from_peer, - on_handshake_data_received_from_peer, h); - grpc_slice_buffer_init(&h->left_overs); - grpc_slice_buffer_init(&h->outgoing); - grpc_slice_buffer_init(&h->incoming); - if (read_buffer != NULL) { - grpc_slice_buffer_move_into(read_buffer, &h->incoming); - gpr_free(read_buffer); - } - if (!is_client_side) { - grpc_server_security_connector *server_connector = - (grpc_server_security_connector *)connector; - handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list)); - handshake_node->handshake = h; - gpr_mu_lock(&server_connector->mu); - handshake_node->next = server_connector->handshaking_handshakes; - server_connector->handshaking_handshakes = handshake_node; - gpr_mu_unlock(&server_connector->mu); - } - send_handshake_bytes_to_peer(exec_ctx, h); - grpc_timer_init(exec_ctx, &h->timer, - gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), - on_timeout, h, gpr_now(GPR_CLOCK_MONOTONIC)); -} - -void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, - void *handshake) { - grpc_security_handshake *h = handshake; - grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint); -} diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c index 0fbd63a7e1..5b088aa58d 100644 --- a/src/core/lib/security/transport/security_connector.c +++ b/src/core/lib/security/transport/security_connector.c @@ -43,11 +43,12 @@ #include <grpc/support/string_util.h> #include "src/core/ext/transport/chttp2/alpn/alpn.h" +#include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/security/transport/handshake.h" #include "src/core/lib/security/transport/secure_endpoint.h" +#include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/tsi/fake_transport_security.h" @@ -111,58 +112,34 @@ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, return NULL; } -void grpc_server_security_connector_shutdown( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector) { - grpc_security_connector_handshake_list *tmp; - gpr_mu_lock(&connector->mu); - while (connector->handshaking_handshakes) { - tmp = connector->handshaking_handshakes; - grpc_security_handshake_shutdown( - exec_ctx, connector->handshaking_handshakes->handshake); - connector->handshaking_handshakes = tmp->next; - gpr_free(tmp); +void grpc_channel_security_connector_add_handshakers( + grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector, + grpc_handshake_manager *handshake_mgr) { + if (connector != NULL) { + connector->add_handshakers(exec_ctx, connector, handshake_mgr); } - gpr_mu_unlock(&connector->mu); } -void grpc_channel_security_connector_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer, - gpr_timespec deadline, grpc_security_handshake_done_cb cb, - void *user_data) { - if (sc == NULL || nonsecure_endpoint == NULL) { - gpr_free(read_buffer); - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); - } else { - sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, read_buffer, deadline, - cb, user_data); - } -} - -void grpc_server_security_connector_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, gpr_timespec deadline, - grpc_security_handshake_done_cb cb, void *user_data) { - if (sc == NULL || nonsecure_endpoint == NULL) { - gpr_free(read_buffer); - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); - } else { - sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, read_buffer, - deadline, cb, user_data); +void grpc_server_security_connector_add_handshakers( + grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector, + grpc_handshake_manager *handshake_mgr) { + if (connector != NULL) { + connector->add_handshakers(exec_ctx, connector, handshake_mgr); } } void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data) { + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked) { if (sc == NULL) { - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL); + grpc_exec_ctx_sched( + exec_ctx, on_peer_checked, + GRPC_ERROR_CREATE("cannot check peer -- no security connector"), NULL); tsi_peer_destruct(&peer); } else { - sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data); + sc->vtable->check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked); } } @@ -262,45 +239,41 @@ static void fake_channel_destroy(grpc_security_connector *sc) { gpr_free(sc); } -static void fake_server_destroy(grpc_security_connector *sc) { - grpc_server_security_connector *c = (grpc_server_security_connector *)sc; - gpr_mu_destroy(&c->mu); - gpr_free(sc); -} +static void fake_server_destroy(grpc_security_connector *sc) { gpr_free(sc); } static void fake_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, void *user_data) { + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked) { const char *prop_name; - grpc_security_status status = GRPC_SECURITY_OK; - grpc_auth_context *auth_context = NULL; + grpc_error *error = GRPC_ERROR_NONE; + *auth_context = NULL; if (peer.property_count != 1) { - gpr_log(GPR_ERROR, "Fake peers should only have 1 property."); - status = GRPC_SECURITY_ERROR; + error = GRPC_ERROR_CREATE("Fake peers should only have 1 property."); goto end; } prop_name = peer.properties[0].name; if (prop_name == NULL || strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { - gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.", - prop_name == NULL ? "<EMPTY>" : prop_name); - status = GRPC_SECURITY_ERROR; + char *msg; + gpr_asprintf(&msg, "Unexpected property in fake peer: %s.", + prop_name == NULL ? "<EMPTY>" : prop_name); + error = GRPC_ERROR_CREATE(msg); + gpr_free(msg); goto end; } if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, peer.properties[0].value.length)) { - gpr_log(GPR_ERROR, "Invalid value for cert type property."); - status = GRPC_SECURITY_ERROR; + error = GRPC_ERROR_CREATE("Invalid value for cert type property."); goto end; } - auth_context = grpc_auth_context_create(NULL); + *auth_context = grpc_auth_context_create(NULL); grpc_auth_context_add_cstring_property( - auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + *auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, GRPC_FAKE_TRANSPORT_SECURITY_TYPE); end: - cb(exec_ctx, user_data, status, auth_context); - grpc_auth_context_unref(auth_context); + grpc_exec_ctx_sched(exec_ctx, on_peer_checked, error, NULL); tsi_peer_destruct(&peer); } @@ -313,26 +286,24 @@ static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx, cb(exec_ctx, user_data, GRPC_SECURITY_OK); } -static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, - gpr_timespec deadline, - grpc_security_handshake_done_cb cb, - void *user_data) { - grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base, - true, nonsecure_endpoint, read_buffer, deadline, - cb, user_data); +static void fake_channel_add_handshakers( + grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, + grpc_handshake_manager *handshake_mgr) { + grpc_handshake_manager_add( + handshake_mgr, + grpc_security_handshaker_create( + exec_ctx, tsi_create_fake_handshaker(true /* is_client */), + &sc->base)); } -static void fake_server_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, gpr_timespec deadline, - grpc_security_handshake_done_cb cb, void *user_data) { - grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base, - false, nonsecure_endpoint, read_buffer, deadline, - cb, user_data); +static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx, + grpc_server_security_connector *sc, + grpc_handshake_manager *handshake_mgr) { + grpc_handshake_manager_add( + handshake_mgr, + grpc_security_handshaker_create( + exec_ctx, tsi_create_fake_handshaker(false /* is_client */), + &sc->base)); } static grpc_security_connector_vtable fake_channel_vtable = { @@ -350,7 +321,7 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create( c->base.vtable = &fake_channel_vtable; c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); c->check_call_host = fake_channel_check_call_host; - c->do_handshake = fake_channel_do_handshake; + c->add_handshakers = fake_channel_add_handshakers; return c; } @@ -362,8 +333,7 @@ grpc_server_security_connector *grpc_fake_server_security_connector_create( gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &fake_server_vtable; c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; - c->do_handshake = fake_server_do_handshake; - gpr_mu_init(&c->mu); + c->add_handshakers = fake_server_add_handshakers; return c; } @@ -396,11 +366,9 @@ static void ssl_channel_destroy(grpc_security_connector *sc) { static void ssl_server_destroy(grpc_security_connector *sc) { grpc_ssl_server_security_connector *c = (grpc_ssl_server_security_connector *)sc; - if (c->handshaker_factory != NULL) { tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); } - gpr_mu_destroy(&c->base.mu); gpr_free(sc); } @@ -419,49 +387,35 @@ static grpc_security_status ssl_create_handshaker( return GRPC_SECURITY_OK; } -static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, - gpr_timespec deadline, - grpc_security_handshake_done_cb cb, - void *user_data) { +static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + grpc_handshake_manager *handshake_mgr) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; - tsi_handshaker *handshaker; - grpc_security_status status = ssl_create_handshaker( - c->handshaker_factory, true, - c->overridden_target_name != NULL ? c->overridden_target_name - : c->target_name, - &handshaker); - if (status != GRPC_SECURITY_OK) { - gpr_free(read_buffer); - cb(exec_ctx, user_data, status, NULL, NULL); - } else { - grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true, - nonsecure_endpoint, read_buffer, deadline, cb, - user_data); - } -} - -static void ssl_server_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, gpr_timespec deadline, - grpc_security_handshake_done_cb cb, void *user_data) { + // Instantiate TSI handshaker. + tsi_handshaker *tsi_hs = NULL; + ssl_create_handshaker(c->handshaker_factory, true /* is_client */, + c->overridden_target_name != NULL + ? c->overridden_target_name + : c->target_name, + &tsi_hs); + // Create handshakers. + grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create( + exec_ctx, tsi_hs, &sc->base)); +} + +static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx, + grpc_server_security_connector *sc, + grpc_handshake_manager *handshake_mgr) { grpc_ssl_server_security_connector *c = (grpc_ssl_server_security_connector *)sc; - tsi_handshaker *handshaker; - grpc_security_status status = - ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker); - if (status != GRPC_SECURITY_OK) { - gpr_free(read_buffer); - cb(exec_ctx, user_data, status, NULL, NULL); - } else { - grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false, - nonsecure_endpoint, read_buffer, deadline, cb, - user_data); - } + // Instantiate TSI handshaker. + tsi_handshaker *tsi_hs = NULL; + ssl_create_handshaker(c->handshaker_factory, false /* is_client */, + NULL /* peer_name */, &tsi_hs); + // Create handshakers. + grpc_handshake_manager_add(handshake_mgr, grpc_security_handshaker_create( + exec_ctx, tsi_hs, &sc->base)); } static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) { @@ -518,57 +472,53 @@ grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) { return ctx; } -static grpc_security_status ssl_check_peer(grpc_security_connector *sc, - const char *peer_name, - const tsi_peer *peer, - grpc_auth_context **auth_context) { +static grpc_error *ssl_check_peer(grpc_security_connector *sc, + const char *peer_name, const tsi_peer *peer, + grpc_auth_context **auth_context) { /* Check the ALPN. */ const tsi_peer_property *p = tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); if (p == NULL) { - gpr_log(GPR_ERROR, "Missing selected ALPN property."); - return GRPC_SECURITY_ERROR; + return GRPC_ERROR_CREATE( + "Cannot check peer: missing selected ALPN property."); } if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { - gpr_log(GPR_ERROR, "Invalid ALPN value."); - return GRPC_SECURITY_ERROR; + return GRPC_ERROR_CREATE("Cannot check peer: invalid ALPN value."); } /* Check the peer name if specified. */ if (peer_name != NULL && !ssl_host_matches_name(peer, peer_name)) { - gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name); - return GRPC_SECURITY_ERROR; + char *msg; + gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); + grpc_error *error = GRPC_ERROR_CREATE(msg); + gpr_free(msg); + return error; } *auth_context = tsi_ssl_peer_to_auth_context(peer); - return GRPC_SECURITY_OK; + return GRPC_ERROR_NONE; } static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data) { + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked) { grpc_ssl_channel_security_connector *c = (grpc_ssl_channel_security_connector *)sc; - grpc_security_status status; - grpc_auth_context *auth_context = NULL; - status = ssl_check_peer(sc, c->overridden_target_name != NULL - ? c->overridden_target_name - : c->target_name, - &peer, &auth_context); - cb(exec_ctx, user_data, status, auth_context); - grpc_auth_context_unref(auth_context); + grpc_error *error = ssl_check_peer(sc, c->overridden_target_name != NULL + ? c->overridden_target_name + : c->target_name, + &peer, auth_context); + grpc_exec_ctx_sched(exec_ctx, on_peer_checked, error, NULL); tsi_peer_destruct(&peer); } static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data) { - grpc_auth_context *auth_context = NULL; - grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context); + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked) { + grpc_error *error = ssl_check_peer(sc, NULL, &peer, auth_context); tsi_peer_destruct(&peer); - cb(exec_ctx, user_data, status, auth_context); - grpc_auth_context_unref(auth_context); + grpc_exec_ctx_sched(exec_ctx, on_peer_checked, error, NULL); } static void add_shallow_auth_property_to_peer(tsi_peer *peer, @@ -765,7 +715,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create( c->base.request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); c->base.check_call_host = ssl_channel_check_call_host; - c->base.do_handshake = ssl_channel_do_handshake; + c->base.add_handshakers = ssl_channel_add_handshakers; gpr_split_host_port(target_name, &c->target_name, &port); gpr_free(port); if (overridden_target_name != NULL) { @@ -840,8 +790,7 @@ grpc_security_status grpc_ssl_server_security_connector_create( *sc = NULL; goto error; } - gpr_mu_init(&c->base.mu); - c->base.do_handshake = ssl_server_do_handshake; + c->base.add_handshakers = ssl_server_add_handshakers; *sc = &c->base; gpr_free((void *)alpn_protocol_strings); gpr_free(alpn_protocol_string_lengths); diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h index dc02692b01..a84b359051 100644 --- a/src/core/lib/security/transport/security_connector.h +++ b/src/core/lib/security/transport/security_connector.h @@ -35,6 +35,8 @@ #define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H #include <grpc/grpc_security.h> + +#include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/tsi/transport_security_interface.h" @@ -57,21 +59,11 @@ typedef struct grpc_security_connector grpc_security_connector; #define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector" -typedef void (*grpc_security_peer_check_cb)(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_security_status status, - grpc_auth_context *auth_context); - -/* Ownership of the secure_endpoint is transfered. */ -typedef void (*grpc_security_handshake_done_cb)( - grpc_exec_ctx *exec_ctx, void *user_data, grpc_security_status status, - grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context); - typedef struct { void (*destroy)(grpc_security_connector *sc); void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, - tsi_peer peer, grpc_security_peer_check_cb cb, - void *user_data); + tsi_peer peer, grpc_auth_context **auth_context, + grpc_closure *on_peer_checked); } grpc_security_connector_vtable; typedef struct grpc_security_connector_handshake_list { @@ -106,12 +98,12 @@ void grpc_security_connector_unref(grpc_security_connector *policy); #endif /* Check the peer. Callee takes ownership of the peer object. - The callback will include the resulting auth_context. */ + When done, sets *auth_context and invokes on_peer_checked. */ void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data); + grpc_auth_context **auth_context, + grpc_closure *on_peer_checked); /* Util to encapsulate the connector in a channel arg. */ grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc); @@ -141,11 +133,9 @@ struct grpc_channel_security_connector { grpc_channel_security_connector *sc, const char *host, grpc_auth_context *auth_context, grpc_security_call_host_check_cb cb, void *user_data); - void (*do_handshake)(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, gpr_timespec deadline, - grpc_security_handshake_done_cb cb, void *user_data); + void (*add_handshakers)(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + grpc_handshake_manager *handshake_mgr); }; /* Checks that the host that will be set for a call is acceptable. */ @@ -154,11 +144,10 @@ void grpc_channel_security_connector_check_call_host( const char *host, grpc_auth_context *auth_context, grpc_security_call_host_check_cb cb, void *user_data); -/* Handshake. */ -void grpc_channel_security_connector_do_handshake( +/* Registers handshakers with \a handshake_mgr. */ +void grpc_channel_security_connector_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector, - grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer, - gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data); + grpc_handshake_manager *handshake_mgr); /* --- server_security_connector object. --- @@ -169,25 +158,14 @@ typedef struct grpc_server_security_connector grpc_server_security_connector; struct grpc_server_security_connector { grpc_security_connector base; - gpr_mu mu; - grpc_security_connector_handshake_list *handshaking_handshakes; - const grpc_channel_args *channel_args; - void (*do_handshake)(grpc_exec_ctx *exec_ctx, - grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, - grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, gpr_timespec deadline, - grpc_security_handshake_done_cb cb, void *user_data); + void (*add_handshakers)(grpc_exec_ctx *exec_ctx, + grpc_server_security_connector *sc, + grpc_handshake_manager *handshake_mgr); }; -void grpc_server_security_connector_do_handshake( +void grpc_server_security_connector_add_handshakers( grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, - grpc_slice_buffer *read_buffer, gpr_timespec deadline, - grpc_security_handshake_done_cb cb, void *user_data); - -void grpc_server_security_connector_shutdown( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector); + grpc_handshake_manager *handshake_mgr); /* --- Creation security connectors. --- */ diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c new file mode 100644 index 0000000000..41a775db85 --- /dev/null +++ b/src/core/lib/security/transport/security_handshaker.c @@ -0,0 +1,450 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/transport/security_handshaker.h" + +#include <stdbool.h> +#include <string.h> + +#include <grpc/slice_buffer.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/transport/secure_endpoint.h" +#include "src/core/lib/security/transport/tsi_error.h" + +#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 + +typedef struct { + grpc_handshaker base; + + // State set at creation time. + tsi_handshaker *handshaker; + grpc_security_connector *connector; + + gpr_mu mu; + gpr_refcount refs; + + bool shutdown; + // Endpoint and read buffer to destroy after a shutdown. + grpc_endpoint *endpoint_to_destroy; + grpc_slice_buffer *read_buffer_to_destroy; + + // State saved while performing the handshake. + grpc_handshaker_args *args; + grpc_closure *on_handshake_done; + + unsigned char *handshake_buffer; + size_t handshake_buffer_size; + grpc_slice_buffer left_overs; + grpc_slice_buffer outgoing; + grpc_closure on_handshake_data_sent_to_peer; + grpc_closure on_handshake_data_received_from_peer; + grpc_closure on_peer_checked; + grpc_auth_context *auth_context; +} security_handshaker; + +static void security_handshaker_unref(grpc_exec_ctx *exec_ctx, + security_handshaker *h) { + if (gpr_unref(&h->refs)) { + gpr_mu_destroy(&h->mu); + tsi_handshaker_destroy(h->handshaker); + if (h->endpoint_to_destroy != NULL) { + grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy); + } + if (h->read_buffer_to_destroy != NULL) { + grpc_slice_buffer_destroy(h->read_buffer_to_destroy); + gpr_free(h->read_buffer_to_destroy); + } + gpr_free(h->handshake_buffer); + grpc_slice_buffer_destroy(&h->left_overs); + grpc_slice_buffer_destroy(&h->outgoing); + GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); + GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake"); + gpr_free(h); + } +} + +// Set args fields to NULL, saving the endpoint and read buffer for +// later destruction. +static void cleanup_args_for_failure_locked(security_handshaker *h) { + h->endpoint_to_destroy = h->args->endpoint; + h->args->endpoint = NULL; + h->read_buffer_to_destroy = h->args->read_buffer; + h->args->read_buffer = NULL; + grpc_channel_args_destroy(h->args->args); + h->args->args = NULL; +} + +// If the handshake failed or we're shutting down, clean up and invoke the +// callback with the error. +static void security_handshake_failed_locked(grpc_exec_ctx *exec_ctx, + security_handshaker *h, + grpc_error *error) { + if (error == GRPC_ERROR_NONE) { + // If we were shut down after the handshake succeeded but before an + // endpoint callback was invoked, we need to generate our own error. + error = GRPC_ERROR_CREATE("Handshaker shutdown"); + } + const char *msg = grpc_error_string(error); + gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg); + grpc_error_free_string(msg); + if (!h->shutdown) { + // TODO(ctiller): It is currently necessary to shutdown endpoints + // before destroying them, even if we know that there are no + // pending read/write callbacks. This should be fixed, at which + // point this can be removed. + grpc_endpoint_shutdown(exec_ctx, h->args->endpoint); + // Not shutting down, so the write failed. Clean up before + // invoking the callback. + cleanup_args_for_failure_locked(h); + // Set shutdown to true so that subsequent calls to + // security_handshaker_shutdown() do nothing. + h->shutdown = true; + } + // Invoke callback. + grpc_exec_ctx_sched(exec_ctx, h->on_handshake_done, error, NULL); +} + +static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + security_handshaker *h = arg; + gpr_mu_lock(&h->mu); + if (error != GRPC_ERROR_NONE || h->shutdown) { + security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error)); + goto done; + } + // Get frame protector. + tsi_frame_protector *protector; + tsi_result result = + tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector); + if (result != TSI_OK) { + error = grpc_set_tsi_error_result( + GRPC_ERROR_CREATE("Frame protector creation failed"), result); + security_handshake_failed_locked(exec_ctx, h, error); + goto done; + } + // Success. + // Create secure endpoint. + h->args->endpoint = grpc_secure_endpoint_create( + protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count); + h->left_overs.count = 0; + h->left_overs.length = 0; + // Clear out the read buffer before it gets passed to the transport, + // since any excess bytes were already copied to h->left_overs. + grpc_slice_buffer_reset_and_unref(h->args->read_buffer); + // Add auth context to channel args. + grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); + grpc_channel_args *tmp_args = h->args->args; + h->args->args = + grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); + grpc_channel_args_destroy(tmp_args); + // Invoke callback. + grpc_exec_ctx_sched(exec_ctx, h->on_handshake_done, GRPC_ERROR_NONE, NULL); + // Set shutdown to true so that subsequent calls to + // security_handshaker_shutdown() do nothing. + h->shutdown = true; +done: + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); +} + +static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx, + security_handshaker *h) { + tsi_peer peer; + tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); + if (result != TSI_OK) { + return grpc_set_tsi_error_result( + GRPC_ERROR_CREATE("Peer extraction failed"), result); + } + grpc_security_connector_check_peer(exec_ctx, h->connector, peer, + &h->auth_context, &h->on_peer_checked); + return GRPC_ERROR_NONE; +} + +static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx, + security_handshaker *h) { + // Get data to send. + tsi_result result = TSI_OK; + size_t offset = 0; + do { + size_t to_send_size = h->handshake_buffer_size - offset; + result = tsi_handshaker_get_bytes_to_send_to_peer( + h->handshaker, h->handshake_buffer + offset, &to_send_size); + offset += to_send_size; + if (result == TSI_INCOMPLETE_DATA) { + h->handshake_buffer_size *= 2; + h->handshake_buffer = + gpr_realloc(h->handshake_buffer, h->handshake_buffer_size); + } + } while (result == TSI_INCOMPLETE_DATA); + if (result != TSI_OK) { + return grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Handshake failed"), + result); + } + // Send data. + grpc_slice to_send = + grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset); + grpc_slice_buffer_reset_and_unref(&h->outgoing); + grpc_slice_buffer_add(&h->outgoing, to_send); + grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing, + &h->on_handshake_data_sent_to_peer); + return GRPC_ERROR_NONE; +} + +static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, + void *arg, grpc_error *error) { + security_handshaker *h = arg; + gpr_mu_lock(&h->mu); + if (error != GRPC_ERROR_NONE || h->shutdown) { + security_handshake_failed_locked( + exec_ctx, h, + GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1)); + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); + return; + } + // Process received data. + tsi_result result = TSI_OK; + size_t consumed_slice_size = 0; + size_t i; + for (i = 0; i < h->args->read_buffer->count; i++) { + consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]); + result = tsi_handshaker_process_bytes_from_peer( + h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), + &consumed_slice_size); + if (!tsi_handshaker_is_in_progress(h->handshaker)) break; + } + if (tsi_handshaker_is_in_progress(h->handshaker)) { + /* We may need more data. */ + if (result == TSI_INCOMPLETE_DATA) { + grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer, + &h->on_handshake_data_received_from_peer); + goto done; + } else { + error = send_handshake_bytes_to_peer_locked(exec_ctx, h); + if (error != GRPC_ERROR_NONE) { + security_handshake_failed_locked(exec_ctx, h, error); + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); + return; + } + goto done; + } + } + if (result != TSI_OK) { + security_handshake_failed_locked( + exec_ctx, h, grpc_set_tsi_error_result( + GRPC_ERROR_CREATE("Handshake failed"), result)); + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); + return; + } + /* Handshake is done and successful this point. */ + bool has_left_overs_in_current_slice = + (consumed_slice_size < + GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i])); + size_t num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) + + h->args->read_buffer->count - i - 1; + if (num_left_overs > 0) { + /* Put the leftovers in our buffer (ownership transfered). */ + if (has_left_overs_in_current_slice) { + grpc_slice_buffer_add( + &h->left_overs, + grpc_slice_split_tail(&h->args->read_buffer->slices[i], + consumed_slice_size)); + /* split_tail above increments refcount. */ + grpc_slice_unref(h->args->read_buffer->slices[i]); + } + grpc_slice_buffer_addn( + &h->left_overs, &h->args->read_buffer->slices[i + 1], + num_left_overs - (size_t)has_left_overs_in_current_slice); + } + // Check peer. + error = check_peer_locked(exec_ctx, h); + if (error != GRPC_ERROR_NONE) { + security_handshake_failed_locked(exec_ctx, h, error); + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); + return; + } +done: + gpr_mu_unlock(&h->mu); +} + +static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + security_handshaker *h = arg; + gpr_mu_lock(&h->mu); + if (error != GRPC_ERROR_NONE || h->shutdown) { + security_handshake_failed_locked( + exec_ctx, h, + GRPC_ERROR_CREATE_REFERENCING("Handshake write failed", &error, 1)); + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); + return; + } + /* We may be done. */ + if (tsi_handshaker_is_in_progress(h->handshaker)) { + grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer, + &h->on_handshake_data_received_from_peer); + } else { + error = check_peer_locked(exec_ctx, h); + if (error != GRPC_ERROR_NONE) { + security_handshake_failed_locked(exec_ctx, h, error); + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); + return; + } + } + gpr_mu_unlock(&h->mu); +} + +// +// public handshaker API +// + +static void security_handshaker_destroy(grpc_exec_ctx *exec_ctx, + grpc_handshaker *handshaker) { + security_handshaker *h = (security_handshaker *)handshaker; + security_handshaker_unref(exec_ctx, h); +} + +static void security_handshaker_shutdown(grpc_exec_ctx *exec_ctx, + grpc_handshaker *handshaker) { + security_handshaker *h = (security_handshaker *)handshaker; + gpr_mu_lock(&h->mu); + if (!h->shutdown) { + h->shutdown = true; + grpc_endpoint_shutdown(exec_ctx, h->args->endpoint); + cleanup_args_for_failure_locked(h); + } + gpr_mu_unlock(&h->mu); +} + +static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx, + grpc_handshaker *handshaker, + grpc_tcp_server_acceptor *acceptor, + grpc_closure *on_handshake_done, + grpc_handshaker_args *args) { + security_handshaker *h = (security_handshaker *)handshaker; + gpr_mu_lock(&h->mu); + h->args = args; + h->on_handshake_done = on_handshake_done; + gpr_ref(&h->refs); + grpc_error *error = send_handshake_bytes_to_peer_locked(exec_ctx, h); + if (error != GRPC_ERROR_NONE) { + security_handshake_failed_locked(exec_ctx, h, error); + gpr_mu_unlock(&h->mu); + security_handshaker_unref(exec_ctx, h); + return; + } + gpr_mu_unlock(&h->mu); +} + +static const grpc_handshaker_vtable security_handshaker_vtable = { + security_handshaker_destroy, security_handshaker_shutdown, + security_handshaker_do_handshake}; + +static grpc_handshaker *security_handshaker_create( + grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, + grpc_security_connector *connector) { + security_handshaker *h = gpr_malloc(sizeof(security_handshaker)); + memset(h, 0, sizeof(security_handshaker)); + grpc_handshaker_init(&security_handshaker_vtable, &h->base); + h->handshaker = handshaker; + h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake"); + gpr_mu_init(&h->mu); + gpr_ref_init(&h->refs, 1); + h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE; + h->handshake_buffer = gpr_malloc(h->handshake_buffer_size); + grpc_closure_init(&h->on_handshake_data_sent_to_peer, + on_handshake_data_sent_to_peer, h); + grpc_closure_init(&h->on_handshake_data_received_from_peer, + on_handshake_data_received_from_peer, h); + grpc_closure_init(&h->on_peer_checked, on_peer_checked, h); + grpc_slice_buffer_init(&h->left_overs); + grpc_slice_buffer_init(&h->outgoing); + return &h->base; +} + +// +// fail_handshaker +// + +static void fail_handshaker_destroy(grpc_exec_ctx *exec_ctx, + grpc_handshaker *handshaker) { + gpr_free(handshaker); +} + +static void fail_handshaker_shutdown(grpc_exec_ctx *exec_ctx, + grpc_handshaker *handshaker) {} + +static void fail_handshaker_do_handshake(grpc_exec_ctx *exec_ctx, + grpc_handshaker *handshaker, + grpc_tcp_server_acceptor *acceptor, + grpc_closure *on_handshake_done, + grpc_handshaker_args *args) { + grpc_exec_ctx_sched(exec_ctx, on_handshake_done, + GRPC_ERROR_CREATE("Failed to create security handshaker"), + NULL); +} + +static const grpc_handshaker_vtable fail_handshaker_vtable = { + fail_handshaker_destroy, fail_handshaker_shutdown, + fail_handshaker_do_handshake}; + +static grpc_handshaker *fail_handshaker_create() { + grpc_handshaker *h = gpr_malloc(sizeof(*h)); + grpc_handshaker_init(&fail_handshaker_vtable, h); + return h; +} + +// +// exported functions +// + +grpc_handshaker *grpc_security_handshaker_create( + grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, + grpc_security_connector *connector) { + // If no TSI handshaker was created, return a handshaker that always fails. + // Otherwise, return a real security handshaker. + if (handshaker == NULL) { + return fail_handshaker_create(); + } else { + return security_handshaker_create(exec_ctx, handshaker, connector); + } +} diff --git a/src/core/lib/security/transport/handshake.h b/src/core/lib/security/transport/security_handshaker.h index f894540515..5ddbf4b451 100644 --- a/src/core/lib/security/transport/handshake.h +++ b/src/core/lib/security/transport/security_handshaker.h @@ -31,20 +31,16 @@ * */ -#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H -#define GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H +#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H +#define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H -#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/channel/handshaker.h" +#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/security/transport/security_connector.h" -/* Calls the callback upon completion. Takes owership of handshaker and - * read_buffer. */ -void grpc_do_security_handshake( +/// Creates a security handshaker using \a handshaker. +grpc_handshaker *grpc_security_handshaker_create( grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, - grpc_security_connector *connector, bool is_client_side, - grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer, - gpr_timespec deadline, grpc_security_handshake_done_cb cb, void *user_data); + grpc_security_connector *connector); -void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake); - -#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H */ +#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */ diff --git a/src/core/lib/support/backoff.c b/src/core/lib/support/backoff.c index e89ef47220..0612472712 100644 --- a/src/core/lib/support/backoff.c +++ b/src/core/lib/support/backoff.c @@ -35,8 +35,10 @@ #include <grpc/support/useful.h> -void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter, +void gpr_backoff_init(gpr_backoff *backoff, int64_t initial_connect_timeout, + double multiplier, double jitter, int64_t min_timeout_millis, int64_t max_timeout_millis) { + backoff->initial_connect_timeout = initial_connect_timeout; backoff->multiplier = multiplier; backoff->jitter = jitter; backoff->min_timeout_millis = min_timeout_millis; @@ -45,9 +47,10 @@ void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter, } gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) { - backoff->current_timeout_millis = backoff->min_timeout_millis; - return gpr_time_add( - now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN)); + backoff->current_timeout_millis = backoff->initial_connect_timeout; + const int64_t first_timeout = + GPR_MAX(backoff->current_timeout_millis, backoff->min_timeout_millis); + return gpr_time_add(now, gpr_time_from_millis(first_timeout, GPR_TIMESPAN)); } /* Generate a random number between 0 and 1. */ @@ -57,20 +60,28 @@ static double generate_uniform_random_number(uint32_t *rng_state) { } gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) { - double new_timeout_millis = + const double new_timeout_millis = backoff->multiplier * (double)backoff->current_timeout_millis; - double jitter_range = backoff->jitter * new_timeout_millis; - double jitter = + backoff->current_timeout_millis = + GPR_MIN((int64_t)new_timeout_millis, backoff->max_timeout_millis); + + const double jitter_range_width = backoff->jitter * new_timeout_millis; + const double jitter = (2 * generate_uniform_random_number(&backoff->rng_state) - 1) * - jitter_range; + jitter_range_width; + backoff->current_timeout_millis = - GPR_CLAMP((int64_t)(new_timeout_millis + jitter), - backoff->min_timeout_millis, backoff->max_timeout_millis); - return gpr_time_add( + (int64_t)((double)(backoff->current_timeout_millis) + jitter); + + const gpr_timespec current_deadline = gpr_time_add( now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN)); + + const gpr_timespec min_deadline = gpr_time_add( + now, gpr_time_from_millis(backoff->min_timeout_millis, GPR_TIMESPAN)); + + return gpr_time_max(current_deadline, min_deadline); } void gpr_backoff_reset(gpr_backoff *backoff) { - // forces step() to return a timeout of min_timeout_millis - backoff->current_timeout_millis = 0; + backoff->current_timeout_millis = backoff->initial_connect_timeout; } diff --git a/src/core/lib/support/backoff.h b/src/core/lib/support/backoff.h index 6d40c15546..5e9b740824 100644 --- a/src/core/lib/support/backoff.h +++ b/src/core/lib/support/backoff.h @@ -37,7 +37,9 @@ #include <grpc/support/time.h> typedef struct { - /// const: multiplier between retry attempts + /// const: how long to wait after the first failure before retrying + int64_t initial_connect_timeout; + /// const: factor with which to multiply backoff after a failed retry double multiplier; /// const: amount to randomize backoffs double jitter; @@ -54,7 +56,8 @@ typedef struct { } gpr_backoff; /// Initialize backoff machinery - does not need to be destroyed -void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter, +void gpr_backoff_init(gpr_backoff *backoff, int64_t initial_connect_timeout, + double multiplier, double jitter, int64_t min_timeout_millis, int64_t max_timeout_millis); /// Begin retry loop: returns a timespec for the NEXT retry diff --git a/src/core/lib/support/string.h b/src/core/lib/support/string.h index e933e2eb46..db59308425 100644 --- a/src/core/lib/support/string.h +++ b/src/core/lib/support/string.h @@ -36,8 +36,6 @@ #include <stddef.h> -#include <grpc/slice.h> -#include <grpc/slice_buffer.h> #include <grpc/support/port_platform.h> #ifdef __cplusplus diff --git a/src/core/lib/support/subprocess_posix.c b/src/core/lib/support/subprocess_posix.c index 4f4de9298e..4247a1c12b 100644 --- a/src/core/lib/support/subprocess_posix.c +++ b/src/core/lib/support/subprocess_posix.c @@ -40,6 +40,7 @@ #include <assert.h> #include <errno.h> #include <signal.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -52,7 +53,7 @@ struct gpr_subprocess { int pid; - int joined; + bool joined; }; const char *gpr_subprocess_binary_extension() { return ""; } @@ -97,9 +98,11 @@ retry: if (errno == EINTR) { goto retry; } - gpr_log(GPR_ERROR, "waitpid failed: %s", strerror(errno)); + gpr_log(GPR_ERROR, "waitpid failed for pid %d: %s", p->pid, + strerror(errno)); return -1; } + p->joined = true; return status; } diff --git a/src/core/lib/support/tmpfile.h b/src/core/lib/support/tmpfile.h index 8952e5ec3d..f613cf9bc8 100644 --- a/src/core/lib/support/tmpfile.h +++ b/src/core/lib/support/tmpfile.h @@ -36,8 +36,6 @@ #include <stdio.h> -#include <grpc/slice.h> - #ifdef __cplusplus extern "C" { #endif diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 1e0f3eeca5..8ca3cab9d5 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -1551,6 +1551,10 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; goto done_with_error; } + /* IF this is a server, then GRPC_OP_RECV_INITIAL_METADATA *must* come + from server.c. In that case, it's coming from accept_stream, and in + that case we're not necessarily covered by a poller. */ + stream_op->covered_by_poller = call->is_client; call->received_initial_metadata = 1; call->buffered_metadata[0] = op->data.recv_initial_metadata; grpc_closure_init(&call->receiving_initial_metadata_ready, diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c index 4e0feb56ac..184c1a1a16 100644 --- a/src/core/lib/surface/completion_queue.c +++ b/src/core/lib/surface/completion_queue.c @@ -354,11 +354,13 @@ static void dump_pending_tags(grpc_completion_queue *cc) { gpr_strvec v; gpr_strvec_init(&v); gpr_strvec_add(&v, gpr_strdup("PENDING TAGS:")); + gpr_mu_lock(cc->mu); for (size_t i = 0; i < cc->outstanding_tag_count; i++) { char *s; gpr_asprintf(&s, " %p", cc->outstanding_tags[i]); gpr_strvec_add(&v, s); } + gpr_mu_unlock(cc->mu); char *out = gpr_strvec_flatten(&v, NULL); gpr_strvec_destroy(&v); gpr_log(GPR_DEBUG, "%s", out); diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c index 89072879d9..4f49d7cf7d 100644 --- a/src/core/lib/transport/connectivity_state.c +++ b/src/core/lib/transport/connectivity_state.c @@ -100,7 +100,12 @@ grpc_connectivity_state grpc_connectivity_state_check( return tracker->current_state; } -int grpc_connectivity_state_notify_on_state_change( +bool grpc_connectivity_state_has_watchers( + grpc_connectivity_state_tracker *connectivity_state) { + return connectivity_state->watchers != NULL; +} + +bool grpc_connectivity_state_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current, grpc_closure *notify) { if (grpc_connectivity_state_trace) { @@ -119,7 +124,7 @@ int grpc_connectivity_state_notify_on_state_change( grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL); tracker->watchers = w->next; gpr_free(w); - return 0; + return false; } while (w != NULL) { grpc_connectivity_state_watcher *rm_candidate = w->next; @@ -127,11 +132,11 @@ int grpc_connectivity_state_notify_on_state_change( grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL); w->next = w->next->next; gpr_free(rm_candidate); - return 0; + return false; } w = w->next; } - return 0; + return false; } else { if (tracker->current_state != *current) { *current = tracker->current_state; diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h index 7a2fa52c10..769c675b79 100644 --- a/src/core/lib/transport/connectivity_state.h +++ b/src/core/lib/transport/connectivity_state.h @@ -75,13 +75,16 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, grpc_error *associated_error, const char *reason); +bool grpc_connectivity_state_has_watchers( + grpc_connectivity_state_tracker *tracker); + grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state_tracker *tracker, grpc_error **current_error); /** Return 1 if the channel should start connecting, 0 otherwise. If current==NULL cancel notify if it is already queued (success==0 in that case) */ -int grpc_connectivity_state_notify_on_state_change( +bool grpc_connectivity_state_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current, grpc_closure *notify); diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc index 00cc102f92..0408a41085 100644 --- a/src/cpp/common/completion_queue_cc.cc +++ b/src/cpp/common/completion_queue_cc.cc @@ -43,11 +43,21 @@ namespace grpc { static internal::GrpcLibraryInitializer g_gli_initializer; -CompletionQueue::CompletionQueue(grpc_completion_queue* take) : cq_(take) {} +CompletionQueue::CompletionQueue(grpc_completion_queue* take) : cq_(take) { + InitialAvalanching(); +} void CompletionQueue::Shutdown() { g_gli_initializer.summon(); - grpc_completion_queue_shutdown(cq_); + CompleteAvalanching(); +} + +void CompletionQueue::CompleteAvalanching() { + // Check if this was the last avalanching operation + if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast<gpr_atm>(-1)) == 1) { + grpc_completion_queue_shutdown(cq_); + } } CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index b7cfd6dbf1..817d85a81c 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -510,12 +510,6 @@ void Server::ShutdownInternal(gpr_timespec deadline) { ShutdownTag shutdown_tag; // Dummy shutdown tag grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); - // Shutdown all ThreadManagers. This will try to gracefully stop all the - // threads in the ThreadManagers (once they process any inflight requests) - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Shutdown(); // ThreadManager's Shutdown() - } - shutdown_cq.Shutdown(); void* tag; @@ -531,6 +525,12 @@ void Server::ShutdownInternal(gpr_timespec deadline) { // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has // successfully shutdown + // Shutdown all ThreadManagers. This will try to gracefully stop all the + // threads in the ThreadManagers (once they process any inflight requests) + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Shutdown(); // ThreadManager's Shutdown() + } + // Wait for threads in all ThreadManagers to terminate for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { (*it)->Wait(); @@ -575,9 +575,14 @@ ServerInterface::BaseAsyncRequest::BaseAsyncRequest( tag_(tag), delete_on_finalize_(delete_on_finalize), call_(nullptr) { + call_cq_->RegisterAvalanching(); // This op will trigger more ops memset(&initial_metadata_array_, 0, sizeof(initial_metadata_array_)); } +ServerInterface::BaseAsyncRequest::~BaseAsyncRequest() { + call_cq_->CompleteAvalanching(); +} + bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag, bool* status) { if (*status) { diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj index a44aaf1fdd..99e8c1a3da 100644 --- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj +++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj @@ -87,7 +87,6 @@ </ProjectReference> </ItemGroup> <ItemGroup> - <None Include="Grpc.Auth.nuspec" /> <None Include="Grpc.Auth.project.json" /> <None Include="packages.config" /> </ItemGroup> diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec deleted file mode 100644 index a1f5668e2e..0000000000 --- a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<package> - <metadata> - <id>Grpc.Auth</id> - <title>gRPC C# Auth</title> - <summary>Auth library for C# implementation of gRPC - an RPC library and framework</summary> - <description>Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.</description> - <version>$version$</version> - <authors>Google Inc.</authors> - <owners>grpc-packages</owners> - <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> - <projectUrl>https://github.com/grpc/grpc</projectUrl> - <requireLicenseAcceptance>false</requireLicenseAcceptance> - <releaseNotes>Release $version$ of gRPC C#</releaseNotes> - <copyright>Copyright 2015, Google Inc.</copyright> - <tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags> - <dependencies> - <dependency id="Google.Apis.Auth" version="1.15.0" /> - <dependency id="Grpc.Core" version="$version$" /> - </dependencies> - </metadata> - <files> - <file src="bin/ReleaseSigned/Grpc.Auth.dll" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.Auth.pdb" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.Auth.xml" target="lib/net45" /> - <file src="**\*.cs" target="src" /> - </files> -</package> diff --git a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs index 99a2d47e6e..3c3b9f7745 100644 --- a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs +++ b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs @@ -67,6 +67,9 @@ namespace Grpc.Core.Tests var credentials = new FakeCallCredentials(); Assert.AreSame(credentials, options.WithCredentials(credentials).Credentials); + var flags = CallFlags.WaitForReady | CallFlags.CacheableRequest; + Assert.AreEqual(flags, options.WithFlags(flags).Flags); + // Check that the original instance is unchanged. Assert.IsNull(options.Headers); Assert.IsNull(options.Deadline); @@ -74,6 +77,7 @@ namespace Grpc.Core.Tests Assert.IsNull(options.WriteOptions); Assert.IsNull(options.PropagationToken); Assert.IsNull(options.Credentials); + Assert.AreEqual(default(CallFlags), options.Flags); } [Test] @@ -94,5 +98,16 @@ namespace Grpc.Core.Tests Assert.AreEqual(token, new CallOptions(propagationToken: propagationToken2).Normalize().CancellationToken); Assert.Throws(typeof(ArgumentException), () => new CallOptions(cancellationToken: token, propagationToken: propagationToken2).Normalize()); } + + [Test] + public void WaitForReady() + { + var callOptions = new CallOptions(); + Assert.IsFalse(callOptions.IsWaitForReady); + + Assert.AreEqual(CallFlags.WaitForReady, callOptions.WithWaitForReady().Flags); + Assert.IsTrue(callOptions.WithWaitForReady().IsWaitForReady); + Assert.IsFalse(callOptions.WithWaitForReady(true).WithWaitForReady(false).IsWaitForReady); + } } } diff --git a/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs index 909112a47c..fe067fe8b0 100644 --- a/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs +++ b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs @@ -115,27 +115,27 @@ namespace Grpc.Core.Internal.Tests return "PEER"; } - public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { UnaryResponseClientHandler = callback; } - public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { throw new NotImplementedException(); } - public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray) + public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { UnaryResponseClientHandler = callback; } - public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { ReceivedStatusOnClientHandler = callback; } - public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray) + public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { ReceivedStatusOnClientHandler = callback; } diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs index f1eb13dffc..1c28277df5 100644 --- a/src/csharp/Grpc.Core.Tests/SanityTest.cs +++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs @@ -115,7 +115,8 @@ namespace Grpc.Core.Tests var otherAssemblies = new[] { "Grpc.Examples.Tests", "Grpc.HealthCheck.Tests", - "Grpc.IntegrationTesting" + "Grpc.IntegrationTesting", + "Grpc.Reflection.Tests", }; foreach (var assemblyName in otherAssemblies) { diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs index 35548cfc96..ce43dae171 100644 --- a/src/csharp/Grpc.Core/CallOptions.cs +++ b/src/csharp/Grpc.Core/CallOptions.cs @@ -50,6 +50,7 @@ namespace Grpc.Core WriteOptions writeOptions; ContextPropagationToken propagationToken; CallCredentials credentials; + CallFlags flags; /// <summary> /// Creates a new instance of <c>CallOptions</c> struct. @@ -69,6 +70,7 @@ namespace Grpc.Core this.writeOptions = writeOptions; this.propagationToken = propagationToken; this.credentials = credentials; + this.flags = default(CallFlags); } /// <summary> @@ -126,6 +128,24 @@ namespace Grpc.Core } /// <summary> + /// If <c>true</c> and and channel is in <c>ChannelState.TransientFailure</c>, the call will attempt waiting for the channel to recover + /// instead of failing immediately (which is the default "FailFast" semantics). + /// Note: experimental API that can change or be removed without any prior notice. + /// </summary> + public bool IsWaitForReady + { + get { return (this.flags & CallFlags.WaitForReady) == CallFlags.WaitForReady; } + } + + /// <summary> + /// Flags to use for this call. + /// </summary> + internal CallFlags Flags + { + get { return this.flags; } + } + + /// <summary> /// Returns new instance of <see cref="CallOptions"/> with /// <c>Headers</c> set to the value provided. Values of all other fields are preserved. /// </summary> @@ -198,6 +218,32 @@ namespace Grpc.Core } /// <summary> + /// Returns new instance of <see cref="CallOptions"/> with "WaitForReady" semantics enabled/disabled. + /// <see cref="IsWaitForReady"/>. + /// Note: experimental API that can change or be removed without any prior notice. + /// </summary> + public CallOptions WithWaitForReady(bool waitForReady = true) + { + if (waitForReady) + { + return WithFlags(this.flags | CallFlags.WaitForReady); + } + return WithFlags(this.flags & ~CallFlags.WaitForReady); + } + + /// <summary> + /// Returns new instance of <see cref="CallOptions"/> with + /// <c>Flags</c> set to the value provided. Values of all other fields are preserved. + /// </summary> + /// <param name="flags">The call flags.</param> + internal CallOptions WithFlags(CallFlags flags) + { + var newOptions = this; + newOptions.flags = flags; + return newOptions; + } + + /// <summary> /// Returns a new instance of <see cref="CallOptions"/> with /// all previously unset values set to their defaults and deadline and cancellation /// token propagated when appropriate. diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index b9715183d0..5bfb978ca6 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -140,9 +140,9 @@ <Compile Include="Logging\LogLevelFilterLogger.cs" /> <Compile Include="Internal\RequestCallContextSafeHandle.cs" /> <Compile Include="Utils\TaskUtils.cs" /> + <Compile Include="Internal\CallFlags.cs" /> </ItemGroup> <ItemGroup> - <None Include="Grpc.Core.nuspec" /> <None Include="Grpc.Core.project.json" /> <None Include="packages.config" /> </ItemGroup> @@ -154,4 +154,4 @@ <Link>roots.pem</Link> </EmbeddedResource> </ItemGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec deleted file mode 100644 index b2a0160147..0000000000 --- a/src/csharp/Grpc.Core/Grpc.Core.nuspec +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<package> - <metadata> - <id>Grpc.Core</id> - <title>gRPC C# Core</title> - <summary>Core C# implementation of gRPC - an RPC library and framework</summary> - <description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.</description> - <version>$version$</version> - <authors>Google Inc.</authors> - <owners>grpc-packages</owners> - <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> - <projectUrl>https://github.com/grpc/grpc</projectUrl> - <requireLicenseAcceptance>false</requireLicenseAcceptance> - <releaseNotes>Release $version$ of gRPC C#</releaseNotes> - <copyright>Copyright 2015, Google Inc.</copyright> - <tags>gRPC RPC Protocol HTTP/2</tags> - <dependencies> - <dependency id="System.Interactive.Async" version="3.1.1" /> - </dependencies> - </metadata> - <files> - <file src="bin/ReleaseSigned/Grpc.Core.dll" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" /> - <file src="**\*.cs" target="src" /> - <file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" /> - <!-- without backslashes in the the source path, nuget won't copy the files --> - <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x86.dll" /> - <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x64.dll" /> - <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x86.so" /> - <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x64.so" /> - <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x86.dylib" /> - <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x64.dylib" /> - </files> -</package> diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index da45c4829d..1f738a3b6f 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -106,7 +106,7 @@ namespace Grpc.Core.Internal using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) using (var ctx = BatchContextSafeHandle.Create()) { - call.StartUnary(ctx, payload, metadataArray, GetWriteFlagsForCall()); + call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); var ev = cq.Pluck(ctx.Handle); @@ -150,7 +150,7 @@ namespace Grpc.Core.Internal unaryResponseTcs = new TaskCompletionSource<TResponse>(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { - call.StartUnary(HandleUnaryResponse, payload, metadataArray, GetWriteFlagsForCall()); + call.StartUnary(HandleUnaryResponse, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); } return unaryResponseTcs.Task; } @@ -174,7 +174,7 @@ namespace Grpc.Core.Internal unaryResponseTcs = new TaskCompletionSource<TResponse>(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { - call.StartClientStreaming(HandleUnaryResponse, metadataArray); + call.StartClientStreaming(HandleUnaryResponse, metadataArray, details.Options.Flags); } return unaryResponseTcs.Task; @@ -200,7 +200,7 @@ namespace Grpc.Core.Internal streamingResponseCallFinishedTcs = new TaskCompletionSource<object>(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { - call.StartServerStreaming(HandleFinished, payload, metadataArray, GetWriteFlagsForCall()); + call.StartServerStreaming(HandleFinished, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); } call.StartReceiveInitialMetadata(HandleReceivedResponseHeaders); } @@ -222,7 +222,7 @@ namespace Grpc.Core.Internal streamingResponseCallFinishedTcs = new TaskCompletionSource<object>(); using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) { - call.StartDuplexStreaming(HandleFinished, metadataArray); + call.StartDuplexStreaming(HandleFinished, metadataArray, details.Options.Flags); } call.StartReceiveInitialMetadata(HandleReceivedResponseHeaders); } diff --git a/src/csharp/Grpc.Core/Internal/CallFlags.cs b/src/csharp/Grpc.Core/Internal/CallFlags.cs new file mode 100644 index 0000000000..454fa9b1f4 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallFlags.cs @@ -0,0 +1,60 @@ +#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; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Flags to enable special call behaviors (client-side only). + /// </summary> + [Flags] + internal enum CallFlags + { + /// <summary> + /// The call is idempotent (retrying the call doesn't change the outcome of the operation). + /// </summary> + IdempotentRequest = 0x10, + + /// <summary> + /// If channel is in <c>ChannelState.TransientFailure</c>, attempt waiting for the channel to recover + /// instead of failing the call immediately. + /// </summary> + WaitForReady = 0x20, + + /// <summary> + /// The call is cacheable. gRPC is free to use GET verb */ + /// </summary> + CacheableRequest = 0x40 + } +} diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index f817a61bce..6bfcc7fa74 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -63,50 +63,50 @@ namespace Grpc.Core.Internal Native.grpcsharp_call_set_credentials(this, credentials).CheckOk(); } - public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata())); - Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags) + Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags) .CheckOk(); } } - public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { - Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags) + Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags) .CheckOk(); } - public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray) + public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata())); - Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray).CheckOk(); + Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray, callFlags).CheckOk(); } } - public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) + public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient())); - Native.grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags).CheckOk(); + Native.grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags).CheckOk(); } } - public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray) + public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) { using (completionQueue.NewScope()) { var ctx = BatchContextSafeHandle.Create(); completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient())); - Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray).CheckOk(); + Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray, callFlags).CheckOk(); } } diff --git a/src/csharp/Grpc.Core/Internal/INativeCall.cs b/src/csharp/Grpc.Core/Internal/INativeCall.cs index cd3719cb50..94fbb08feb 100644 --- a/src/csharp/Grpc.Core/Internal/INativeCall.cs +++ b/src/csharp/Grpc.Core/Internal/INativeCall.cs @@ -31,6 +31,7 @@ #endregion using System; +using Grpc.Core; namespace Grpc.Core.Internal { @@ -54,19 +55,19 @@ namespace Grpc.Core.Internal { void Cancel(); - void CancelWithStatus(Grpc.Core.Status status); + void CancelWithStatus(Status status); string GetPeer(); - void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, Grpc.Core.WriteFlags writeFlags); + void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); - void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, Grpc.Core.WriteFlags writeFlags); + void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); - void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray); + void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags); - void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, Grpc.Core.WriteFlags writeFlags); + void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); - void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray); + void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags); void StartReceiveMessage(ReceivedMessageHandler callback); @@ -74,11 +75,11 @@ namespace Grpc.Core.Internal void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray); - void StartSendMessage(SendCompletionHandler callback, byte[] payload, Grpc.Core.WriteFlags writeFlags, bool sendEmptyInitialMetadata); + void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata); void StartSendCloseFromClient(SendCompletionHandler callback); - void StartSendStatusFromServer(SendCompletionHandler callback, Grpc.Core.Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, Grpc.Core.WriteFlags writeFlags); + void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, WriteFlags writeFlags); void StartServerSide(ReceivedCloseOnServerHandler callback); } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 40ba7e30cb..ce38e37093 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -325,14 +325,14 @@ namespace Grpc.Core.Internal public delegate CallError grpcsharp_call_cancel_delegate(CallSafeHandle call); public delegate CallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description); public delegate CallError grpcsharp_call_start_unary_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, - MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, + MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata); public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call, diff --git a/src/csharp/Grpc.Dotnet.sln b/src/csharp/Grpc.Dotnet.sln index 98b3cd54ab..824c6822f7 100644 --- a/src/csharp/Grpc.Dotnet.sln +++ b/src/csharp/Grpc.Dotnet.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Core", "Grpc.Core\Grpc.Core.xproj", "{DC9908B6-F291-4FC8-A46D-2EA2551790EC}" EndProject @@ -31,6 +31,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.Ser EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.xproj", "{0EBC910B-8867-4D3E-8686-91F34183D839}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.xproj", "{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.xproj", "{FE90181D-A4B3-4A5C-8490-F07561E18E3B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -93,6 +97,14 @@ Global {0EBC910B-8867-4D3E-8686-91F34183D839}.Debug|Any CPU.Build.0 = Debug|Any CPU {0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.ActiveCfg = Release|Any CPU {0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.Build.0 = Release|Any CPU + {2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.Build.0 = Release|Any CPU + {FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs index fae4fd3c26..e5b76f8305 100644 --- a/src/csharp/Grpc.Examples/Math.cs +++ b/src/csharp/Grpc.Examples/Math.cs @@ -1,5 +1,5 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! -// source: math.proto +// source: math/math.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -9,11 +9,11 @@ using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Math { - /// <summary>Holder for reflection information generated from math.proto</summary> + /// <summary>Holder for reflection information generated from math/math.proto</summary> public static partial class MathReflection { #region Descriptor - /// <summary>File descriptor for math.proto</summary> + /// <summary>File descriptor for math/math.proto</summary> public static pbr::FileDescriptor Descriptor { get { return descriptor; } } @@ -22,15 +22,15 @@ namespace Math { static MathReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB", - "KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB", - "IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB", - "IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50", - "GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu", - "RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E", - "aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51", - "bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAFiBnByb3Rv", - "Mw==")); + "Cg9tYXRoL21hdGgucHJvdG8SBG1hdGgiLAoHRGl2QXJncxIQCghkaXZpZGVu", + "ZBgBIAEoAxIPCgdkaXZpc29yGAIgASgDIi8KCERpdlJlcGx5EhAKCHF1b3Rp", + "ZW50GAEgASgDEhEKCXJlbWFpbmRlchgCIAEoAyIYCgdGaWJBcmdzEg0KBWxp", + "bWl0GAEgASgDIhIKA051bRILCgNudW0YASABKAMiGQoIRmliUmVwbHkSDQoF", + "Y291bnQYASABKAMypAEKBE1hdGgSJgoDRGl2Eg0ubWF0aC5EaXZBcmdzGg4u", + "bWF0aC5EaXZSZXBseSIAEi4KB0Rpdk1hbnkSDS5tYXRoLkRpdkFyZ3MaDi5t", + "YXRoLkRpdlJlcGx5IgAoATABEiMKA0ZpYhINLm1hdGguRmliQXJncxoJLm1h", + "dGguTnVtIgAwARIfCgNTdW0SCS5tYXRoLk51bRoJLm1hdGguTnVtIgAoAWIG", + "cHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 21727d57c6..8b431c7218 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -1,5 +1,5 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! -// source: math.proto +// source: math/math.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj index c8b6d478b7..7418768316 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -62,13 +62,12 @@ <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> - <None Include="Grpc.HealthCheck.nuspec" /> <None Include="Grpc.HealthCheck.project.json" /> <None Include="packages.config" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj"> - <Project>{ccc4440e-49f7-4790-b0af-feabb0837ae7}</Project> + <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project> <Name>Grpc.Core</Name> </ProjectReference> </ItemGroup> diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec deleted file mode 100644 index f2e36ba2be..0000000000 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<package> - <metadata> - <id>Grpc.HealthCheck</id> - <title>gRPC C# Healthchecking</title> - <summary>Implementation of gRPC health service</summary> - <description>Example implementation of grpc.health.v1 service that can be used for health-checking.</description> - <version>$version$</version> - <authors>Google Inc.</authors> - <owners>grpc-packages</owners> - <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> - <projectUrl>https://github.com/grpc/grpc</projectUrl> - <requireLicenseAcceptance>false</requireLicenseAcceptance> - <copyright>Copyright 2015, Google Inc.</copyright> - <tags>gRPC health check</tags> - <dependencies> - <dependency id="Google.Protobuf" version="$ProtobufVersion$" /> - <dependency id="Grpc.Core" version="$version$" /> - <dependency id="System.Interactive.Async" version="3.1.1" /> - </dependencies> - </metadata> - <files> - <file src="bin/ReleaseSigned/Grpc.HealthCheck.dll" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.HealthCheck.pdb" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.HealthCheck.xml" target="lib/net45" /> - <file src="**\*.cs" target="src" /> - </files> -</package> diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs index b8e2e2274c..b9880d9636 100644 --- a/src/csharp/Grpc.HealthCheck/Health.cs +++ b/src/csharp/Grpc.HealthCheck/Health.cs @@ -1,5 +1,5 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! -// source: health.proto +// source: grpc/health/v1/health.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code @@ -9,11 +9,11 @@ using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Health.V1 { - /// <summary>Holder for reflection information generated from health.proto</summary> + /// <summary>Holder for reflection information generated from grpc/health/v1/health.proto</summary> public static partial class HealthReflection { #region Descriptor - /// <summary>File descriptor for health.proto</summary> + /// <summary>File descriptor for grpc/health/v1/health.proto</summary> public static pbr::FileDescriptor Descriptor { get { return descriptor; } } @@ -22,14 +22,14 @@ namespace Grpc.Health.V1 { static HealthReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "CgxoZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYxIiUKEkhlYWx0aENoZWNr", - "UmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNIZWFsdGhDaGVja1Jlc3Bv", - "bnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVhbHRoLnYxLkhlYWx0aENo", - "ZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1TZXJ2aW5nU3RhdHVzEgsK", - "B1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9UX1NFUlZJTkcQAjJaCgZI", - "ZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jl", - "cXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jlc3BvbnNlQhGq", - "Ag5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z")); + "ChtncnBjL2hlYWx0aC92MS9oZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYx", + "IiUKEkhlYWx0aENoZWNrUmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNI", + "ZWFsdGhDaGVja1Jlc3BvbnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVh", + "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1T", + "ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U", + "X1NFUlZJTkcQAjJaCgZIZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52", + "MS5IZWFsdGhDaGVja1JlcXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhD", + "aGVja1Jlc3BvbnNlQhGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 03381f0b88..ad5cf11b75 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -1,5 +1,5 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! -// source: health.proto +// source: grpc/health/v1/health.proto // Original file comments: // Copyright 2015, Google Inc. // All rights reserved. diff --git a/src/csharp/Grpc.Reflection.Tests/.gitignore b/src/csharp/Grpc.Reflection.Tests/.gitignore new file mode 100644 index 0000000000..1746e3269e --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj new file mode 100644 index 0000000000..cebcf59ce8 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{B88F91D6-436D-4C78-8B99-47800FA8DE03}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Grpc.Reflection.Tests</RootNamespace> + <AssemblyName>Grpc.Reflection.Tests</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\ReleaseSigned</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <SignAssembly>True</SignAssembly> + <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + <Reference Include="nunit.framework"> + <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath> + </Reference> + <Reference Include="nunitlite"> + <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath> + </Reference> + <Reference Include="Google.Protobuf"> + <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> + </Reference> + <Reference Include="System.Interactive.Async"> + <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Grpc.Core\Version.cs"> + <Link>Version.cs</Link> + </Compile> + <Compile Include="SymbolRegistryTest.cs" /> + <Compile Include="ReflectionClientServerTest.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="NUnitMain.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj"> + <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project> + <Name>Grpc.Core</Name> + </ProjectReference> + <ProjectReference Include="..\Grpc.Reflection\Grpc.Reflection.csproj"> + <Project>{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}</Project> + <Name>Grpc.Reflection</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="Grpc.Reflection.Tests.project.json" /> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.project.json b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.project.json new file mode 100644 index 0000000000..c2f5bcb163 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.project.json @@ -0,0 +1,8 @@ +{ + "frameworks": { + "net45": { } + }, + "runtimes": { + "win": { } + } +} diff --git a/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.xproj b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.xproj new file mode 100644 index 0000000000..4a3100853d --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.xproj @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + </PropertyGroup> + <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>fe90181d-a4b3-4a5c-8490-f07561e18e3b</ProjectGuid> + <RootNamespace>Grpc.Reflection.Tests</RootNamespace> + <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> + <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> + </PropertyGroup> + <PropertyGroup> + <SchemaVersion>2.0</SchemaVersion> + </PropertyGroup> + <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs new file mode 100644 index 0000000000..a60d7b03eb --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs @@ -0,0 +1,59 @@ +#region Copyright notice and license + +// 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. + +#endregion + +using System; +using System.Reflection; +using Grpc.Core; +using Grpc.Core.Logging; +using NUnit.Common; +using NUnitLite; + +namespace Grpc.Reflection.Tests +{ + /// <summary> + /// Provides entry point for NUnitLite + /// </summary> + public class NUnitMain + { + public static int Main(string[] args) + { + // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. + GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); +#if NETCOREAPP1_0 + return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); +#else + return new AutoRun().Execute(args); +#endif + } + } +} diff --git a/src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d29054a4d1 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,44 @@ +#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.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Reflection.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs b/src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs new file mode 100644 index 0000000000..1d0845e276 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs @@ -0,0 +1,154 @@ +#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.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Reflection; +using Grpc.Reflection.V1Alpha; +using NUnit.Framework; + +namespace Grpc.Reflection.Tests +{ + /// <summary> + /// Reflection client talks to reflection server. + /// </summary> + public class ReflectionClientServerTest + { + const string Host = "localhost"; + Server server; + Channel channel; + ServerReflection.ServerReflectionClient client; + ReflectionServiceImpl serviceImpl; + + [TestFixtureSetUp] + public void Init() + { + serviceImpl = new ReflectionServiceImpl(ServerReflection.Descriptor); + + server = new Server + { + Services = { ServerReflection.BindService(serviceImpl) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + server.Start(); + channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + + client = new ServerReflection.ServerReflectionClient(channel); + } + + [TestFixtureTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task FileByFilename_NotFound() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileByFilename = "somepackage/nonexistent.proto" + }); + Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode); + } + + [Test] + public async Task FileByFilename() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileByFilename = "grpc/reflection/v1alpha/reflection.proto" + }); + Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count); + Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]); + } + + [Test] + public async Task FileContainingSymbol() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileContainingSymbol = "grpc.reflection.v1alpha.ServerReflection" + }); + Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count); + Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]); + } + + [Test] + public async Task FileContainingSymbol_NotFound() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileContainingSymbol = "somepackage.Nonexistent" + }); + Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode); + } + + [Test] + public async Task ListServices() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + ListServices = "" + }); + Assert.AreEqual(1, response.ListServicesResponse.Service.Count); + Assert.AreEqual(ServerReflection.Descriptor.FullName, response.ListServicesResponse.Service[0].Name); + } + + [Test] + public async Task FileContainingExtension() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileContainingExtension = new ExtensionRequest() + }); + Assert.AreEqual((int)StatusCode.Unimplemented, response.ErrorResponse.ErrorCode); + } + + private async Task<ServerReflectionResponse> SingleRequestAsync(ServerReflectionRequest request) + { + var call = client.ServerReflectionInfo(); + await call.RequestStream.WriteAsync(request); + Assert.IsTrue(await call.ResponseStream.MoveNext()); + + var response = call.ResponseStream.Current; + await call.RequestStream.CompleteAsync(); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + return response; + } + } +} diff --git a/src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs b/src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs new file mode 100644 index 0000000000..68ee6dc10d --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs @@ -0,0 +1,63 @@ +#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 Grpc.Reflection; +using Grpc.Reflection.V1Alpha; +using NUnit.Framework; + + +namespace Grpc.Reflection.Tests +{ + /// <summary> + /// Tests for ReflectionServiceImpl + /// </summary> + public class SymbolRegistryTest + { + SymbolRegistry registry = SymbolRegistry.FromFiles(new[] { ReflectionReflection.Descriptor, Google.Protobuf.WellKnownTypes.Duration.Descriptor.File }); + + [Test] + public void FileByName() + { + Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileByName("google/protobuf/duration.proto")); + Assert.IsNull(registry.FileByName("somepackage/nonexistent.proto")); + } + + [Test] + public void FileContainingSymbol() + { + Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileContainingSymbol("google.protobuf.Duration")); + Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo")); // method + Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection")); // service + Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflectionRequest")); // message + Assert.IsNull(registry.FileContainingSymbol("somepackage.Nonexistent")); + } + } +} diff --git a/src/csharp/Grpc.Reflection.Tests/packages.config b/src/csharp/Grpc.Reflection.Tests/packages.config new file mode 100644 index 0000000000..0fed4dbd41 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/packages.config @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> + <package id="NUnit" version="3.2.0" targetFramework="net45" /> + <package id="NUnitLite" version="3.2.0" targetFramework="net45" /> + <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" /> +</packages>
\ No newline at end of file diff --git a/src/csharp/Grpc.Reflection.Tests/project.json b/src/csharp/Grpc.Reflection.Tests/project.json new file mode 100644 index 0000000000..61d3b7e47b --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/project.json @@ -0,0 +1,65 @@ +{ + "buildOptions": { + "emitEntryPoint": true + }, + "configurations": { + "Debug": { + "buildOptions": { + "define": [ "SIGNED" ], + "keyFile": "../keys/Grpc.snk", + "xmlDoc": true, + "compile": { + "includeFiles": [ "../Grpc.Core/Version.cs" ] + }, + "copyToOutput": { + "mappings": { + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + } + } + } + }, + "Release": { + "buildOptions": { + "define": [ "SIGNED" ], + "keyFile": "../keys/Grpc.snk", + "xmlDoc": true, + "compile": { + "includeFiles": [ "../Grpc.Core/Version.cs" ] + }, + "copyToOutput": { + "mappings": { + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + } + } + } + } + }, + + "dependencies": { + "Grpc.Reflection": { + "target": "project" + }, + "NUnit": "3.2.0", + "NUnitLite": "3.2.0-*" + }, + "frameworks": { + "net45": { }, + "netcoreapp1.0": { + "imports": [ + "portable-net45" + ], + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + } + } + } + } +} diff --git a/src/csharp/Grpc.Reflection/.gitignore b/src/csharp/Grpc.Reflection/.gitignore new file mode 100644 index 0000000000..1746e3269e --- /dev/null +++ b/src/csharp/Grpc.Reflection/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj new file mode 100644 index 0000000000..ea65998ce3 --- /dev/null +++ b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Grpc.Reflection</RootNamespace> + <AssemblyName>Grpc.Reflection</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <DocumentationFile>bin\$(Configuration)\Grpc.Reflection.Xml</DocumentationFile> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\ReleaseSigned</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <SignAssembly>True</SignAssembly> + <AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + <Reference Include="Google.Protobuf"> + <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> + </Reference> + <Reference Include="System.Interactive.Async"> + <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Grpc.Core\Version.cs"> + <Link>Version.cs</Link> + </Compile> + <Compile Include="SymbolRegistry.cs" /> + <Compile Include="ReflectionServiceImpl.cs" /> + <Compile Include="Reflection.cs" /> + <Compile Include="ReflectionGrpc.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="Grpc.Reflection.project.json" /> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj"> + <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project> + <Name>Grpc.Core</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Reflection/Grpc.Reflection.project.json b/src/csharp/Grpc.Reflection/Grpc.Reflection.project.json new file mode 100644 index 0000000000..c2f5bcb163 --- /dev/null +++ b/src/csharp/Grpc.Reflection/Grpc.Reflection.project.json @@ -0,0 +1,8 @@ +{ + "frameworks": { + "net45": { } + }, + "runtimes": { + "win": { } + } +} diff --git a/src/csharp/Grpc.Reflection/Grpc.Reflection.xproj b/src/csharp/Grpc.Reflection/Grpc.Reflection.xproj new file mode 100644 index 0000000000..833d98b121 --- /dev/null +++ b/src/csharp/Grpc.Reflection/Grpc.Reflection.xproj @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + </PropertyGroup> + <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" /> + <PropertyGroup Label="Globals"> + <ProjectGuid>2b372155-80ba-4cf9-82d6-4b938e8ec3a0</ProjectGuid> + <RootNamespace>Grpc.Reflection</RootNamespace> + <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath> + <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> + </PropertyGroup> + <PropertyGroup> + <SchemaVersion>2.0</SchemaVersion> + </PropertyGroup> + <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3104ecdd54 --- /dev/null +++ b/src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs @@ -0,0 +1,44 @@ +#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.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Reflection")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Reflection/Reflection.cs b/src/csharp/Grpc.Reflection/Reflection.cs new file mode 100644 index 0000000000..06c5d08030 --- /dev/null +++ b/src/csharp/Grpc.Reflection/Reflection.cs @@ -0,0 +1,1556 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: grpc/reflection/v1alpha/reflection.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Reflection.V1Alpha { + + /// <summary>Holder for reflection information generated from grpc/reflection/v1alpha/reflection.proto</summary> + public static partial class ReflectionReflection { + + #region Descriptor + /// <summary>File descriptor for grpc/reflection/v1alpha/reflection.proto</summary> + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ReflectionReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CihncnBjL3JlZmxlY3Rpb24vdjFhbHBoYS9yZWZsZWN0aW9uLnByb3RvEhdn", + "cnBjLnJlZmxlY3Rpb24udjFhbHBoYSKKAgoXU2VydmVyUmVmbGVjdGlvblJl", + "cXVlc3QSDAoEaG9zdBgBIAEoCRIaChBmaWxlX2J5X2ZpbGVuYW1lGAMgASgJ", + "SAASIAoWZmlsZV9jb250YWluaW5nX3N5bWJvbBgEIAEoCUgAEk4KGWZpbGVf", + "Y29udGFpbmluZ19leHRlbnNpb24YBSABKAsyKS5ncnBjLnJlZmxlY3Rpb24u", + "djFhbHBoYS5FeHRlbnNpb25SZXF1ZXN0SAASJwodYWxsX2V4dGVuc2lvbl9u", + "dW1iZXJzX29mX3R5cGUYBiABKAlIABIXCg1saXN0X3NlcnZpY2VzGAcgASgJ", + "SABCEQoPbWVzc2FnZV9yZXF1ZXN0IkUKEEV4dGVuc2lvblJlcXVlc3QSFwoP", + "Y29udGFpbmluZ190eXBlGAEgASgJEhgKEGV4dGVuc2lvbl9udW1iZXIYAiAB", + "KAUi0QMKGFNlcnZlclJlZmxlY3Rpb25SZXNwb25zZRISCgp2YWxpZF9ob3N0", + "GAEgASgJEkoKEG9yaWdpbmFsX3JlcXVlc3QYAiABKAsyMC5ncnBjLnJlZmxl", + "Y3Rpb24udjFhbHBoYS5TZXJ2ZXJSZWZsZWN0aW9uUmVxdWVzdBJTChhmaWxl", + "X2Rlc2NyaXB0b3JfcmVzcG9uc2UYBCABKAsyLy5ncnBjLnJlZmxlY3Rpb24u", + "djFhbHBoYS5GaWxlRGVzY3JpcHRvclJlc3BvbnNlSAASWgoeYWxsX2V4dGVu", + "c2lvbl9udW1iZXJzX3Jlc3BvbnNlGAUgASgLMjAuZ3JwYy5yZWZsZWN0aW9u", + "LnYxYWxwaGEuRXh0ZW5zaW9uTnVtYmVyUmVzcG9uc2VIABJOChZsaXN0X3Nl", + "cnZpY2VzX3Jlc3BvbnNlGAYgASgLMiwuZ3JwYy5yZWZsZWN0aW9uLnYxYWxw", + "aGEuTGlzdFNlcnZpY2VSZXNwb25zZUgAEkAKDmVycm9yX3Jlc3BvbnNlGAcg", + "ASgLMiYuZ3JwYy5yZWZsZWN0aW9uLnYxYWxwaGEuRXJyb3JSZXNwb25zZUgA", + "QhIKEG1lc3NhZ2VfcmVzcG9uc2UiNwoWRmlsZURlc2NyaXB0b3JSZXNwb25z", + "ZRIdChVmaWxlX2Rlc2NyaXB0b3JfcHJvdG8YASADKAwiSwoXRXh0ZW5zaW9u", + "TnVtYmVyUmVzcG9uc2USFgoOYmFzZV90eXBlX25hbWUYASABKAkSGAoQZXh0", + "ZW5zaW9uX251bWJlchgCIAMoBSJQChNMaXN0U2VydmljZVJlc3BvbnNlEjkK", + "B3NlcnZpY2UYASADKAsyKC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2", + "aWNlUmVzcG9uc2UiHwoPU2VydmljZVJlc3BvbnNlEgwKBG5hbWUYASABKAki", + "OgoNRXJyb3JSZXNwb25zZRISCgplcnJvcl9jb2RlGAEgASgFEhUKDWVycm9y", + "X21lc3NhZ2UYAiABKAkykwEKEFNlcnZlclJlZmxlY3Rpb24SfwoUU2VydmVy", + "UmVmbGVjdGlvbkluZm8SMC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2", + "ZXJSZWZsZWN0aW9uUmVxdWVzdBoxLmdycGMucmVmbGVjdGlvbi52MWFscGhh", + "LlNlcnZlclJlZmxlY3Rpb25SZXNwb25zZSgBMAFiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionRequest), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser, new[]{ "Host", "FileByFilename", "FileContainingSymbol", "FileContainingExtension", "AllExtensionNumbersOfType", "ListServices" }, new[]{ "MessageRequest" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionRequest), global::Grpc.Reflection.V1Alpha.ExtensionRequest.Parser, new[]{ "ContainingType", "ExtensionNumber" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionResponse), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser, new[]{ "ValidHost", "OriginalRequest", "FileDescriptorResponse", "AllExtensionNumbersResponse", "ListServicesResponse", "ErrorResponse" }, new[]{ "MessageResponse" }, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.FileDescriptorResponse), global::Grpc.Reflection.V1Alpha.FileDescriptorResponse.Parser, new[]{ "FileDescriptorProto" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse), global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse.Parser, new[]{ "BaseTypeName", "ExtensionNumber" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ListServiceResponse), global::Grpc.Reflection.V1Alpha.ListServiceResponse.Parser, new[]{ "Service" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServiceResponse), global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser, new[]{ "Name" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ErrorResponse), global::Grpc.Reflection.V1Alpha.ErrorResponse.Parser, new[]{ "ErrorCode", "ErrorMessage" }, null, null, null) + })); + } + #endregion + + } + #region Messages + /// <summary> + /// The message sent by the client when calling ServerReflectionInfo method. + /// </summary> + public sealed partial class ServerReflectionRequest : pb::IMessage<ServerReflectionRequest> { + private static readonly pb::MessageParser<ServerReflectionRequest> _parser = new pb::MessageParser<ServerReflectionRequest>(() => new ServerReflectionRequest()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<ServerReflectionRequest> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServerReflectionRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServerReflectionRequest(ServerReflectionRequest other) : this() { + host_ = other.host_; + switch (other.MessageRequestCase) { + case MessageRequestOneofCase.FileByFilename: + FileByFilename = other.FileByFilename; + break; + case MessageRequestOneofCase.FileContainingSymbol: + FileContainingSymbol = other.FileContainingSymbol; + break; + case MessageRequestOneofCase.FileContainingExtension: + FileContainingExtension = other.FileContainingExtension.Clone(); + break; + case MessageRequestOneofCase.AllExtensionNumbersOfType: + AllExtensionNumbersOfType = other.AllExtensionNumbersOfType; + break; + case MessageRequestOneofCase.ListServices: + ListServices = other.ListServices; + break; + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServerReflectionRequest Clone() { + return new ServerReflectionRequest(this); + } + + /// <summary>Field number for the "host" field.</summary> + public const int HostFieldNumber = 1; + private string host_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Host { + get { return host_; } + set { + host_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// <summary>Field number for the "file_by_filename" field.</summary> + public const int FileByFilenameFieldNumber = 3; + /// <summary> + /// Find a proto file by the file name. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FileByFilename { + get { return messageRequestCase_ == MessageRequestOneofCase.FileByFilename ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.FileByFilename; + } + } + + /// <summary>Field number for the "file_containing_symbol" field.</summary> + public const int FileContainingSymbolFieldNumber = 4; + /// <summary> + /// Find the proto file that declares the given fully-qualified symbol name. + /// This field should be a fully-qualified symbol name + /// (e.g. <package>.<service>[.<method>] or <package>.<type>). + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string FileContainingSymbol { + get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.FileContainingSymbol; + } + } + + /// <summary>Field number for the "file_containing_extension" field.</summary> + public const int FileContainingExtensionFieldNumber = 5; + /// <summary> + /// Find the proto file which defines an extension extending the given + /// message type with the given field number. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Grpc.Reflection.V1Alpha.ExtensionRequest FileContainingExtension { + get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension ? (global::Grpc.Reflection.V1Alpha.ExtensionRequest) messageRequest_ : null; } + set { + messageRequest_ = value; + messageRequestCase_ = value == null ? MessageRequestOneofCase.None : MessageRequestOneofCase.FileContainingExtension; + } + } + + /// <summary>Field number for the "all_extension_numbers_of_type" field.</summary> + public const int AllExtensionNumbersOfTypeFieldNumber = 6; + /// <summary> + /// Finds the tag numbers used by all known extensions of the given message + /// type, and appends them to ExtensionNumberResponse in an undefined order. + /// Its corresponding method is best-effort: it's not guaranteed that the + /// reflection service will implement this method, and it's not guaranteed + /// that this method will provide all extensions. Returns + /// StatusCode::UNIMPLEMENTED if it's not implemented. + /// This field should be a fully-qualified type name. The format is + /// <package>.<type> + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string AllExtensionNumbersOfType { + get { return messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.AllExtensionNumbersOfType; + } + } + + /// <summary>Field number for the "list_services" field.</summary> + public const int ListServicesFieldNumber = 7; + /// <summary> + /// List the full names of registered services. The content will not be + /// checked. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ListServices { + get { return messageRequestCase_ == MessageRequestOneofCase.ListServices ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.ListServices; + } + } + + private object messageRequest_; + /// <summary>Enum of possible cases for the "message_request" oneof.</summary> + public enum MessageRequestOneofCase { + None = 0, + FileByFilename = 3, + FileContainingSymbol = 4, + FileContainingExtension = 5, + AllExtensionNumbersOfType = 6, + ListServices = 7, + } + private MessageRequestOneofCase messageRequestCase_ = MessageRequestOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageRequestOneofCase MessageRequestCase { + get { return messageRequestCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMessageRequest() { + messageRequestCase_ = MessageRequestOneofCase.None; + messageRequest_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ServerReflectionRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ServerReflectionRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Host != other.Host) return false; + if (FileByFilename != other.FileByFilename) return false; + if (FileContainingSymbol != other.FileContainingSymbol) return false; + if (!object.Equals(FileContainingExtension, other.FileContainingExtension)) return false; + if (AllExtensionNumbersOfType != other.AllExtensionNumbersOfType) return false; + if (ListServices != other.ListServices) return false; + if (MessageRequestCase != other.MessageRequestCase) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Host.Length != 0) hash ^= Host.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) hash ^= FileByFilename.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) hash ^= FileContainingSymbol.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) hash ^= FileContainingExtension.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) hash ^= AllExtensionNumbersOfType.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.ListServices) hash ^= ListServices.GetHashCode(); + hash ^= (int) messageRequestCase_; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Host.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Host); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) { + output.WriteRawTag(26); + output.WriteString(FileByFilename); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) { + output.WriteRawTag(34); + output.WriteString(FileContainingSymbol); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + output.WriteRawTag(42); + output.WriteMessage(FileContainingExtension); + } + if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) { + output.WriteRawTag(50); + output.WriteString(AllExtensionNumbersOfType); + } + if (messageRequestCase_ == MessageRequestOneofCase.ListServices) { + output.WriteRawTag(58); + output.WriteString(ListServices); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Host.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Host); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FileByFilename); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FileContainingSymbol); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileContainingExtension); + } + if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(AllExtensionNumbersOfType); + } + if (messageRequestCase_ == MessageRequestOneofCase.ListServices) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ListServices); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ServerReflectionRequest other) { + if (other == null) { + return; + } + if (other.Host.Length != 0) { + Host = other.Host; + } + switch (other.MessageRequestCase) { + case MessageRequestOneofCase.FileByFilename: + FileByFilename = other.FileByFilename; + break; + case MessageRequestOneofCase.FileContainingSymbol: + FileContainingSymbol = other.FileContainingSymbol; + break; + case MessageRequestOneofCase.FileContainingExtension: + FileContainingExtension = other.FileContainingExtension; + break; + case MessageRequestOneofCase.AllExtensionNumbersOfType: + AllExtensionNumbersOfType = other.AllExtensionNumbersOfType; + break; + case MessageRequestOneofCase.ListServices: + ListServices = other.ListServices; + break; + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Host = input.ReadString(); + break; + } + case 26: { + FileByFilename = input.ReadString(); + break; + } + case 34: { + FileContainingSymbol = input.ReadString(); + break; + } + case 42: { + global::Grpc.Reflection.V1Alpha.ExtensionRequest subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionRequest(); + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + subBuilder.MergeFrom(FileContainingExtension); + } + input.ReadMessage(subBuilder); + FileContainingExtension = subBuilder; + break; + } + case 50: { + AllExtensionNumbersOfType = input.ReadString(); + break; + } + case 58: { + ListServices = input.ReadString(); + break; + } + } + } + } + + } + + /// <summary> + /// The type name and extension number sent by the client when requesting + /// file_containing_extension. + /// </summary> + public sealed partial class ExtensionRequest : pb::IMessage<ExtensionRequest> { + private static readonly pb::MessageParser<ExtensionRequest> _parser = new pb::MessageParser<ExtensionRequest>(() => new ExtensionRequest()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<ExtensionRequest> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ExtensionRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ExtensionRequest(ExtensionRequest other) : this() { + containingType_ = other.containingType_; + extensionNumber_ = other.extensionNumber_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ExtensionRequest Clone() { + return new ExtensionRequest(this); + } + + /// <summary>Field number for the "containing_type" field.</summary> + public const int ContainingTypeFieldNumber = 1; + private string containingType_ = ""; + /// <summary> + /// Fully-qualified type name. The format should be <package>.<type> + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ContainingType { + get { return containingType_; } + set { + containingType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// <summary>Field number for the "extension_number" field.</summary> + public const int ExtensionNumberFieldNumber = 2; + private int extensionNumber_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int ExtensionNumber { + get { return extensionNumber_; } + set { + extensionNumber_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ExtensionRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ExtensionRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ContainingType != other.ContainingType) return false; + if (ExtensionNumber != other.ExtensionNumber) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (ContainingType.Length != 0) hash ^= ContainingType.GetHashCode(); + if (ExtensionNumber != 0) hash ^= ExtensionNumber.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (ContainingType.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ContainingType); + } + if (ExtensionNumber != 0) { + output.WriteRawTag(16); + output.WriteInt32(ExtensionNumber); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (ContainingType.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ContainingType); + } + if (ExtensionNumber != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ExtensionNumber); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ExtensionRequest other) { + if (other == null) { + return; + } + if (other.ContainingType.Length != 0) { + ContainingType = other.ContainingType; + } + if (other.ExtensionNumber != 0) { + ExtensionNumber = other.ExtensionNumber; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + ContainingType = input.ReadString(); + break; + } + case 16: { + ExtensionNumber = input.ReadInt32(); + break; + } + } + } + } + + } + + /// <summary> + /// The message sent by the server to answer ServerReflectionInfo method. + /// </summary> + public sealed partial class ServerReflectionResponse : pb::IMessage<ServerReflectionResponse> { + private static readonly pb::MessageParser<ServerReflectionResponse> _parser = new pb::MessageParser<ServerReflectionResponse>(() => new ServerReflectionResponse()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<ServerReflectionResponse> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServerReflectionResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServerReflectionResponse(ServerReflectionResponse other) : this() { + validHost_ = other.validHost_; + OriginalRequest = other.originalRequest_ != null ? other.OriginalRequest.Clone() : null; + switch (other.MessageResponseCase) { + case MessageResponseOneofCase.FileDescriptorResponse: + FileDescriptorResponse = other.FileDescriptorResponse.Clone(); + break; + case MessageResponseOneofCase.AllExtensionNumbersResponse: + AllExtensionNumbersResponse = other.AllExtensionNumbersResponse.Clone(); + break; + case MessageResponseOneofCase.ListServicesResponse: + ListServicesResponse = other.ListServicesResponse.Clone(); + break; + case MessageResponseOneofCase.ErrorResponse: + ErrorResponse = other.ErrorResponse.Clone(); + break; + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServerReflectionResponse Clone() { + return new ServerReflectionResponse(this); + } + + /// <summary>Field number for the "valid_host" field.</summary> + public const int ValidHostFieldNumber = 1; + private string validHost_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ValidHost { + get { return validHost_; } + set { + validHost_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// <summary>Field number for the "original_request" field.</summary> + public const int OriginalRequestFieldNumber = 2; + private global::Grpc.Reflection.V1Alpha.ServerReflectionRequest originalRequest_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Grpc.Reflection.V1Alpha.ServerReflectionRequest OriginalRequest { + get { return originalRequest_; } + set { + originalRequest_ = value; + } + } + + /// <summary>Field number for the "file_descriptor_response" field.</summary> + public const int FileDescriptorResponseFieldNumber = 4; + /// <summary> + /// This message is used to answer file_by_filename, file_containing_symbol, + /// file_containing_extension requests with transitive dependencies. As + /// the repeated label is not allowed in oneof fields, we use a + /// FileDescriptorResponse message to encapsulate the repeated fields. + /// The reflection service is allowed to avoid sending FileDescriptorProtos + /// that were previously sent in response to earlier requests in the stream. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Grpc.Reflection.V1Alpha.FileDescriptorResponse FileDescriptorResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse ? (global::Grpc.Reflection.V1Alpha.FileDescriptorResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.FileDescriptorResponse; + } + } + + /// <summary>Field number for the "all_extension_numbers_response" field.</summary> + public const int AllExtensionNumbersResponseFieldNumber = 5; + /// <summary> + /// This message is used to answer all_extension_numbers_of_type requst. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse AllExtensionNumbersResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse ? (global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.AllExtensionNumbersResponse; + } + } + + /// <summary>Field number for the "list_services_response" field.</summary> + public const int ListServicesResponseFieldNumber = 6; + /// <summary> + /// This message is used to answer list_services request. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Grpc.Reflection.V1Alpha.ListServiceResponse ListServicesResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse ? (global::Grpc.Reflection.V1Alpha.ListServiceResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ListServicesResponse; + } + } + + /// <summary>Field number for the "error_response" field.</summary> + public const int ErrorResponseFieldNumber = 7; + /// <summary> + /// This message is used when an error occurs. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Grpc.Reflection.V1Alpha.ErrorResponse ErrorResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.ErrorResponse ? (global::Grpc.Reflection.V1Alpha.ErrorResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ErrorResponse; + } + } + + private object messageResponse_; + /// <summary>Enum of possible cases for the "message_response" oneof.</summary> + public enum MessageResponseOneofCase { + None = 0, + FileDescriptorResponse = 4, + AllExtensionNumbersResponse = 5, + ListServicesResponse = 6, + ErrorResponse = 7, + } + private MessageResponseOneofCase messageResponseCase_ = MessageResponseOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MessageResponseOneofCase MessageResponseCase { + get { return messageResponseCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearMessageResponse() { + messageResponseCase_ = MessageResponseOneofCase.None; + messageResponse_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ServerReflectionResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ServerReflectionResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ValidHost != other.ValidHost) return false; + if (!object.Equals(OriginalRequest, other.OriginalRequest)) return false; + if (!object.Equals(FileDescriptorResponse, other.FileDescriptorResponse)) return false; + if (!object.Equals(AllExtensionNumbersResponse, other.AllExtensionNumbersResponse)) return false; + if (!object.Equals(ListServicesResponse, other.ListServicesResponse)) return false; + if (!object.Equals(ErrorResponse, other.ErrorResponse)) return false; + if (MessageResponseCase != other.MessageResponseCase) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (ValidHost.Length != 0) hash ^= ValidHost.GetHashCode(); + if (originalRequest_ != null) hash ^= OriginalRequest.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) hash ^= FileDescriptorResponse.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) hash ^= AllExtensionNumbersResponse.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) hash ^= ListServicesResponse.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) hash ^= ErrorResponse.GetHashCode(); + hash ^= (int) messageResponseCase_; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (ValidHost.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ValidHost); + } + if (originalRequest_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OriginalRequest); + } + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + output.WriteRawTag(34); + output.WriteMessage(FileDescriptorResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + output.WriteRawTag(42); + output.WriteMessage(AllExtensionNumbersResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + output.WriteRawTag(50); + output.WriteMessage(ListServicesResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + output.WriteRawTag(58); + output.WriteMessage(ErrorResponse); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (ValidHost.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ValidHost); + } + if (originalRequest_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OriginalRequest); + } + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileDescriptorResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(AllExtensionNumbersResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListServicesResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ErrorResponse); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ServerReflectionResponse other) { + if (other == null) { + return; + } + if (other.ValidHost.Length != 0) { + ValidHost = other.ValidHost; + } + if (other.originalRequest_ != null) { + if (originalRequest_ == null) { + originalRequest_ = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest(); + } + OriginalRequest.MergeFrom(other.OriginalRequest); + } + switch (other.MessageResponseCase) { + case MessageResponseOneofCase.FileDescriptorResponse: + FileDescriptorResponse = other.FileDescriptorResponse; + break; + case MessageResponseOneofCase.AllExtensionNumbersResponse: + AllExtensionNumbersResponse = other.AllExtensionNumbersResponse; + break; + case MessageResponseOneofCase.ListServicesResponse: + ListServicesResponse = other.ListServicesResponse; + break; + case MessageResponseOneofCase.ErrorResponse: + ErrorResponse = other.ErrorResponse; + break; + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + ValidHost = input.ReadString(); + break; + } + case 18: { + if (originalRequest_ == null) { + originalRequest_ = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest(); + } + input.ReadMessage(originalRequest_); + break; + } + case 34: { + global::Grpc.Reflection.V1Alpha.FileDescriptorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.FileDescriptorResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + subBuilder.MergeFrom(FileDescriptorResponse); + } + input.ReadMessage(subBuilder); + FileDescriptorResponse = subBuilder; + break; + } + case 42: { + global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + subBuilder.MergeFrom(AllExtensionNumbersResponse); + } + input.ReadMessage(subBuilder); + AllExtensionNumbersResponse = subBuilder; + break; + } + case 50: { + global::Grpc.Reflection.V1Alpha.ListServiceResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ListServiceResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + subBuilder.MergeFrom(ListServicesResponse); + } + input.ReadMessage(subBuilder); + ListServicesResponse = subBuilder; + break; + } + case 58: { + global::Grpc.Reflection.V1Alpha.ErrorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ErrorResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + subBuilder.MergeFrom(ErrorResponse); + } + input.ReadMessage(subBuilder); + ErrorResponse = subBuilder; + break; + } + } + } + } + + } + + /// <summary> + /// Serialized FileDescriptorProto messages sent by the server answering + /// a file_by_filename, file_containing_symbol, or file_containing_extension + /// request. + /// </summary> + public sealed partial class FileDescriptorResponse : pb::IMessage<FileDescriptorResponse> { + private static readonly pb::MessageParser<FileDescriptorResponse> _parser = new pb::MessageParser<FileDescriptorResponse>(() => new FileDescriptorResponse()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<FileDescriptorResponse> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FileDescriptorResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FileDescriptorResponse(FileDescriptorResponse other) : this() { + fileDescriptorProto_ = other.fileDescriptorProto_.Clone(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public FileDescriptorResponse Clone() { + return new FileDescriptorResponse(this); + } + + /// <summary>Field number for the "file_descriptor_proto" field.</summary> + public const int FileDescriptorProtoFieldNumber = 1; + private static readonly pb::FieldCodec<pb::ByteString> _repeated_fileDescriptorProto_codec + = pb::FieldCodec.ForBytes(10); + private readonly pbc::RepeatedField<pb::ByteString> fileDescriptorProto_ = new pbc::RepeatedField<pb::ByteString>(); + /// <summary> + /// Serialized FileDescriptorProto messages. We avoid taking a dependency on + /// descriptor.proto, which uses proto2 only features, by making them opaque + /// bytes instead. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField<pb::ByteString> FileDescriptorProto { + get { return fileDescriptorProto_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as FileDescriptorResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(FileDescriptorResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!fileDescriptorProto_.Equals(other.fileDescriptorProto_)) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= fileDescriptorProto_.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + fileDescriptorProto_.WriteTo(output, _repeated_fileDescriptorProto_codec); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += fileDescriptorProto_.CalculateSize(_repeated_fileDescriptorProto_codec); + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(FileDescriptorResponse other) { + if (other == null) { + return; + } + fileDescriptorProto_.Add(other.fileDescriptorProto_); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + fileDescriptorProto_.AddEntriesFrom(input, _repeated_fileDescriptorProto_codec); + break; + } + } + } + } + + } + + /// <summary> + /// A list of extension numbers sent by the server answering + /// all_extension_numbers_of_type request. + /// </summary> + public sealed partial class ExtensionNumberResponse : pb::IMessage<ExtensionNumberResponse> { + private static readonly pb::MessageParser<ExtensionNumberResponse> _parser = new pb::MessageParser<ExtensionNumberResponse>(() => new ExtensionNumberResponse()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<ExtensionNumberResponse> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ExtensionNumberResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ExtensionNumberResponse(ExtensionNumberResponse other) : this() { + baseTypeName_ = other.baseTypeName_; + extensionNumber_ = other.extensionNumber_.Clone(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ExtensionNumberResponse Clone() { + return new ExtensionNumberResponse(this); + } + + /// <summary>Field number for the "base_type_name" field.</summary> + public const int BaseTypeNameFieldNumber = 1; + private string baseTypeName_ = ""; + /// <summary> + /// Full name of the base type, including the package name. The format + /// is <package>.<type> + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string BaseTypeName { + get { return baseTypeName_; } + set { + baseTypeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// <summary>Field number for the "extension_number" field.</summary> + public const int ExtensionNumberFieldNumber = 2; + private static readonly pb::FieldCodec<int> _repeated_extensionNumber_codec + = pb::FieldCodec.ForInt32(18); + private readonly pbc::RepeatedField<int> extensionNumber_ = new pbc::RepeatedField<int>(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField<int> ExtensionNumber { + get { return extensionNumber_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ExtensionNumberResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ExtensionNumberResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (BaseTypeName != other.BaseTypeName) return false; + if(!extensionNumber_.Equals(other.extensionNumber_)) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (BaseTypeName.Length != 0) hash ^= BaseTypeName.GetHashCode(); + hash ^= extensionNumber_.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (BaseTypeName.Length != 0) { + output.WriteRawTag(10); + output.WriteString(BaseTypeName); + } + extensionNumber_.WriteTo(output, _repeated_extensionNumber_codec); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (BaseTypeName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(BaseTypeName); + } + size += extensionNumber_.CalculateSize(_repeated_extensionNumber_codec); + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ExtensionNumberResponse other) { + if (other == null) { + return; + } + if (other.BaseTypeName.Length != 0) { + BaseTypeName = other.BaseTypeName; + } + extensionNumber_.Add(other.extensionNumber_); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + BaseTypeName = input.ReadString(); + break; + } + case 18: + case 16: { + extensionNumber_.AddEntriesFrom(input, _repeated_extensionNumber_codec); + break; + } + } + } + } + + } + + /// <summary> + /// A list of ServiceResponse sent by the server answering list_services request. + /// </summary> + public sealed partial class ListServiceResponse : pb::IMessage<ListServiceResponse> { + private static readonly pb::MessageParser<ListServiceResponse> _parser = new pb::MessageParser<ListServiceResponse>(() => new ListServiceResponse()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<ListServiceResponse> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ListServiceResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ListServiceResponse(ListServiceResponse other) : this() { + service_ = other.service_.Clone(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ListServiceResponse Clone() { + return new ListServiceResponse(this); + } + + /// <summary>Field number for the "service" field.</summary> + public const int ServiceFieldNumber = 1; + private static readonly pb::FieldCodec<global::Grpc.Reflection.V1Alpha.ServiceResponse> _repeated_service_codec + = pb::FieldCodec.ForMessage(10, global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser); + private readonly pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse> service_ = new pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse>(); + /// <summary> + /// The information of each service may be expanded in the future, so we use + /// ServiceResponse message to encapsulate it. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse> Service { + get { return service_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ListServiceResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ListServiceResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!service_.Equals(other.service_)) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + hash ^= service_.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + service_.WriteTo(output, _repeated_service_codec); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + size += service_.CalculateSize(_repeated_service_codec); + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ListServiceResponse other) { + if (other == null) { + return; + } + service_.Add(other.service_); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + service_.AddEntriesFrom(input, _repeated_service_codec); + break; + } + } + } + } + + } + + /// <summary> + /// The information of a single service used by ListServiceResponse to answer + /// list_services request. + /// </summary> + public sealed partial class ServiceResponse : pb::IMessage<ServiceResponse> { + private static readonly pb::MessageParser<ServiceResponse> _parser = new pb::MessageParser<ServiceResponse>(() => new ServiceResponse()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<ServiceResponse> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServiceResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServiceResponse(ServiceResponse other) : this() { + name_ = other.name_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ServiceResponse Clone() { + return new ServiceResponse(this); + } + + /// <summary>Field number for the "name" field.</summary> + public const int NameFieldNumber = 1; + private string name_ = ""; + /// <summary> + /// Full name of a registered service, including its package name. The format + /// is <package>.<service> + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ServiceResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ServiceResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ServiceResponse other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + } + + } + + /// <summary> + /// The error code and error message sent by the server when an error occurs. + /// </summary> + public sealed partial class ErrorResponse : pb::IMessage<ErrorResponse> { + private static readonly pb::MessageParser<ErrorResponse> _parser = new pb::MessageParser<ErrorResponse>(() => new ErrorResponse()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser<ErrorResponse> Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ErrorResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ErrorResponse(ErrorResponse other) : this() { + errorCode_ = other.errorCode_; + errorMessage_ = other.errorMessage_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ErrorResponse Clone() { + return new ErrorResponse(this); + } + + /// <summary>Field number for the "error_code" field.</summary> + public const int ErrorCodeFieldNumber = 1; + private int errorCode_; + /// <summary> + /// This field uses the error codes defined in grpc::StatusCode. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int ErrorCode { + get { return errorCode_; } + set { + errorCode_ = value; + } + } + + /// <summary>Field number for the "error_message" field.</summary> + public const int ErrorMessageFieldNumber = 2; + private string errorMessage_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ErrorMessage { + get { return errorMessage_; } + set { + errorMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ErrorResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ErrorResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ErrorCode != other.ErrorCode) return false; + if (ErrorMessage != other.ErrorMessage) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (ErrorCode != 0) hash ^= ErrorCode.GetHashCode(); + if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (ErrorCode != 0) { + output.WriteRawTag(8); + output.WriteInt32(ErrorCode); + } + if (ErrorMessage.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ErrorMessage); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (ErrorCode != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ErrorCode); + } + if (ErrorMessage.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ErrorResponse other) { + if (other == null) { + return; + } + if (other.ErrorCode != 0) { + ErrorCode = other.ErrorCode; + } + if (other.ErrorMessage.Length != 0) { + ErrorMessage = other.ErrorMessage; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + ErrorCode = input.ReadInt32(); + break; + } + case 18: { + ErrorMessage = input.ReadString(); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs new file mode 100644 index 0000000000..1b6f96ce7c --- /dev/null +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -0,0 +1,132 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: grpc/reflection/v1alpha/reflection.proto +// Original file comments: +// 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. +// +// Service exported by server reflection +// +#region Designer generated code + +using System; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; + +namespace Grpc.Reflection.V1Alpha { + public static partial class ServerReflection + { + static readonly string __ServiceName = "grpc.reflection.v1alpha.ServerReflection"; + + static readonly Marshaller<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest> __Marshaller_ServerReflectionRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> __Marshaller_ServerReflectionResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser.ParseFrom); + + static readonly Method<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> __Method_ServerReflectionInfo = new Method<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse>( + MethodType.DuplexStreaming, + __ServiceName, + "ServerReflectionInfo", + __Marshaller_ServerReflectionRequest, + __Marshaller_ServerReflectionResponse); + + /// <summary>Service descriptor</summary> + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.Services[0]; } + } + + /// <summary>Base class for server-side implementations of ServerReflection</summary> + public abstract partial class ServerReflectionBase + { + /// <summary> + /// The reflection service is structured as a bidirectional stream, ensuring + /// all related requests go to a single server. + /// </summary> + public virtual global::System.Threading.Tasks.Task ServerReflectionInfo(IAsyncStreamReader<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest> requestStream, IServerStreamWriter<global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + + /// <summary>Client for ServerReflection</summary> + public partial class ServerReflectionClient : ClientBase<ServerReflectionClient> + { + /// <summary>Creates a new client for ServerReflection</summary> + /// <param name="channel">The channel to use to make remote calls.</param> + public ServerReflectionClient(Channel channel) : base(channel) + { + } + /// <summary>Creates a new client for ServerReflection that uses a custom <c>CallInvoker</c>.</summary> + /// <param name="callInvoker">The callInvoker to use to make remote calls.</param> + public ServerReflectionClient(CallInvoker callInvoker) : base(callInvoker) + { + } + /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected ServerReflectionClient() : base() + { + } + /// <summary>Protected constructor to allow creation of configured clients.</summary> + /// <param name="configuration">The client configuration.</param> + protected ServerReflectionClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// <summary> + /// The reflection service is structured as a bidirectional stream, ensuring + /// all related requests go to a single server. + /// </summary> + public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return ServerReflectionInfo(new CallOptions(headers, deadline, cancellationToken)); + } + /// <summary> + /// The reflection service is structured as a bidirectional stream, ensuring + /// all related requests go to a single server. + /// </summary> + public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_ServerReflectionInfo, null, options); + } + /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary> + protected override ServerReflectionClient NewInstance(ClientBaseConfiguration configuration) + { + return new ServerReflectionClient(configuration); + } + } + + /// <summary>Creates service definition that can be registered with a server</summary> + public static ServerServiceDefinition BindService(ServerReflectionBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build(); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs b/src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs new file mode 100644 index 0000000000..105c4c963b --- /dev/null +++ b/src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs @@ -0,0 +1,173 @@ +#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.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Reflection.V1Alpha; +using Google.Protobuf.Reflection; + +namespace Grpc.Reflection +{ + /// <summary> + /// Implementation of server reflection service. + /// </summary> + public class ReflectionServiceImpl : Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionBase + { + readonly List<string> services; + readonly SymbolRegistry symbolRegistry; + + /// <summary> + /// Creates a new instance of <c>ReflectionServiceIml</c>. + /// </summary> + public ReflectionServiceImpl(IEnumerable<string> services, SymbolRegistry symbolRegistry) + { + this.services = new List<string>(services); + this.symbolRegistry = symbolRegistry; + } + + /// <summary> + /// Creates a new instance of <c>ReflectionServiceIml</c>. + /// </summary> + public ReflectionServiceImpl(IEnumerable<ServiceDescriptor> serviceDescriptors) + { + this.services = new List<string>(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.FullName)); + this.symbolRegistry = SymbolRegistry.FromFiles(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.File)); + } + + /// <summary> + /// Creates a new instance of <c>ReflectionServiceIml</c>. + /// </summary> + public ReflectionServiceImpl(params ServiceDescriptor[] serviceDescriptors) : this((IEnumerable<ServiceDescriptor>) serviceDescriptors) + { + } + + public override async Task ServerReflectionInfo(IAsyncStreamReader<ServerReflectionRequest> requestStream, IServerStreamWriter<ServerReflectionResponse> responseStream, ServerCallContext context) + { + while (await requestStream.MoveNext()) + { + var response = ProcessRequest(requestStream.Current); + await responseStream.WriteAsync(response); + } + } + + ServerReflectionResponse ProcessRequest(ServerReflectionRequest request) + { + switch (request.MessageRequestCase) + { + case ServerReflectionRequest.MessageRequestOneofCase.FileByFilename: + return FileByFilename(request.FileByFilename); + case ServerReflectionRequest.MessageRequestOneofCase.FileContainingSymbol: + return FileContainingSymbol(request.FileContainingSymbol); + case ServerReflectionRequest.MessageRequestOneofCase.ListServices: + return ListServices(); + case ServerReflectionRequest.MessageRequestOneofCase.AllExtensionNumbersOfType: + case ServerReflectionRequest.MessageRequestOneofCase.FileContainingExtension: + default: + return CreateErrorResponse(StatusCode.Unimplemented, "Request type not supported by C# reflection service."); + } + } + + ServerReflectionResponse FileByFilename(string filename) + { + FileDescriptor file = symbolRegistry.FileByName(filename); + if (file == null) + { + return CreateErrorResponse(StatusCode.NotFound, "File not found."); + } + + var transitiveDependencies = new HashSet<FileDescriptor>(); + CollectTransitiveDependencies(file, transitiveDependencies); + + return new ServerReflectionResponse + { + FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } } + }; + } + + ServerReflectionResponse FileContainingSymbol(string symbol) + { + FileDescriptor file = symbolRegistry.FileContainingSymbol(symbol); + if (file == null) + { + return CreateErrorResponse(StatusCode.NotFound, "Symbol not found."); + } + + var transitiveDependencies = new HashSet<FileDescriptor>(); + CollectTransitiveDependencies(file, transitiveDependencies); + + return new ServerReflectionResponse + { + FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } } + }; + } + + ServerReflectionResponse ListServices() + { + var serviceResponses = new ListServiceResponse(); + foreach (string serviceName in services) + { + serviceResponses.Service.Add(new ServiceResponse { Name = serviceName }); + } + + return new ServerReflectionResponse + { + ListServicesResponse = serviceResponses + }; + } + + ServerReflectionResponse CreateErrorResponse(StatusCode status, string message) + { + return new ServerReflectionResponse + { + ErrorResponse = new ErrorResponse { ErrorCode = (int) status, ErrorMessage = message } + }; + } + + void CollectTransitiveDependencies(FileDescriptor descriptor, HashSet<FileDescriptor> pool) + { + pool.Add(descriptor); + foreach (var dependency in descriptor.Dependencies) + { + if (pool.Add(dependency)) + { + // descriptors cannot have circular dependencies + CollectTransitiveDependencies(dependency, pool); + } + } + } + } +} diff --git a/src/csharp/Grpc.Reflection/Settings.StyleCop b/src/csharp/Grpc.Reflection/Settings.StyleCop new file mode 100644 index 0000000000..2942add962 --- /dev/null +++ b/src/csharp/Grpc.Reflection/Settings.StyleCop @@ -0,0 +1,10 @@ +<StyleCopSettings Version="105"> + <SourceFileList> + <SourceFile>Health.cs</SourceFile> + <Settings> + <GlobalSettings> + <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty> + </GlobalSettings> + </Settings> + </SourceFileList> +</StyleCopSettings> diff --git a/src/csharp/Grpc.Reflection/SymbolRegistry.cs b/src/csharp/Grpc.Reflection/SymbolRegistry.cs new file mode 100644 index 0000000000..b7104ab2f9 --- /dev/null +++ b/src/csharp/Grpc.Reflection/SymbolRegistry.cs @@ -0,0 +1,160 @@ +#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.Collections.Generic; +using Grpc.Core.Utils; +using Google.Protobuf.Reflection; + +namespace Grpc.Reflection +{ + /// <summary>Registry of protobuf symbols</summary> + public class SymbolRegistry + { + private readonly Dictionary<string, FileDescriptor> filesByName; + private readonly Dictionary<string, FileDescriptor> filesBySymbol; + + private SymbolRegistry(Dictionary<string, FileDescriptor> filesByName, Dictionary<string, FileDescriptor> filesBySymbol) + { + this.filesByName = new Dictionary<string, FileDescriptor>(filesByName); + this.filesBySymbol = new Dictionary<string, FileDescriptor>(filesBySymbol); + } + + /// <summary> + /// Creates a symbol registry from the specified set of file descriptors. + /// </summary> + /// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param> + /// <returns>A symbol registry for the given files.</returns> + public static SymbolRegistry FromFiles(IEnumerable<FileDescriptor> fileDescriptors) + { + GrpcPreconditions.CheckNotNull(fileDescriptors); + var builder = new Builder(); + foreach (var file in fileDescriptors) + { + builder.AddFile(file); + } + return builder.Build(); + } + + /// <summary> + /// Gets file descriptor for given file name (including package path). Returns <c>null</c> if not found. + /// </summary> + public FileDescriptor FileByName(string filename) + { + FileDescriptor file; + filesByName.TryGetValue(filename, out file); + return file; + } + + /// <summary> + /// Gets file descriptor that contains definition of given symbol full name (including package path). Returns <c>null</c> if not found. + /// </summary> + public FileDescriptor FileContainingSymbol(string symbol) + { + FileDescriptor file; + filesBySymbol.TryGetValue(symbol, out file); + return file; + } + + /// <summary> + /// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. + /// </summary> + private class Builder + { + private readonly Dictionary<string, FileDescriptor> filesByName; + private readonly Dictionary<string, FileDescriptor> filesBySymbol; + + + internal Builder() + { + filesByName = new Dictionary<string, FileDescriptor>(); + filesBySymbol = new Dictionary<string, FileDescriptor>(); + } + + internal void AddFile(FileDescriptor fileDescriptor) + { + if (filesByName.ContainsKey(fileDescriptor.Name)) + { + return; + } + filesByName.Add(fileDescriptor.Name, fileDescriptor); + + foreach (var dependency in fileDescriptor.Dependencies) + { + AddFile(dependency); + } + foreach (var enumeration in fileDescriptor.EnumTypes) + { + AddEnum(enumeration); + } + foreach (var message in fileDescriptor.MessageTypes) + { + AddMessage(message); + } + foreach (var service in fileDescriptor.Services) + { + AddService(service); + } + } + + private void AddEnum(EnumDescriptor enumDescriptor) + { + filesBySymbol[enumDescriptor.FullName] = enumDescriptor.File; + } + + private void AddMessage(MessageDescriptor messageDescriptor) + { + foreach (var nestedEnum in messageDescriptor.EnumTypes) + { + AddEnum(nestedEnum); + } + foreach (var nestedType in messageDescriptor.NestedTypes) + { + AddMessage(nestedType); + } + filesBySymbol[messageDescriptor.FullName] = messageDescriptor.File; + } + + private void AddService(ServiceDescriptor serviceDescriptor) + { + foreach (var method in serviceDescriptor.Methods) + { + filesBySymbol[method.FullName] = method.File; + } + filesBySymbol[serviceDescriptor.FullName] = serviceDescriptor.File; + } + + internal SymbolRegistry Build() + { + return new SymbolRegistry(filesByName, filesBySymbol); + } + } + } +} diff --git a/src/csharp/Grpc.Reflection/packages.config b/src/csharp/Grpc.Reflection/packages.config new file mode 100644 index 0000000000..5ab40b7a8c --- /dev/null +++ b/src/csharp/Grpc.Reflection/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> + <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" /> +</packages>
\ No newline at end of file diff --git a/src/csharp/Grpc.Reflection/project.json b/src/csharp/Grpc.Reflection/project.json new file mode 100644 index 0000000000..2fe617cc7a --- /dev/null +++ b/src/csharp/Grpc.Reflection/project.json @@ -0,0 +1,40 @@ +{ + "version": "1.1.0-dev", + "title": "gRPC C# Reflection", + "authors": [ "Google Inc." ], + "copyright": "Copyright 2016, Google Inc.", + "packOptions": { + "summary": "Implementation of gRPC reflection service", + "description": "Provides information about services running on a gRPC C# server.", + "owners": [ "grpc-packages" ], + "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE", + "projectUrl": "https://github.com/grpc/grpc", + "requireLicenseAcceptance": false, + "tags": [ "gRPC reflection" ] + }, + "buildOptions": { + "define": [ "SIGNED" ], + "keyFile": "../keys/Grpc.snk", + "xmlDoc": true, + "compile": { + "includeFiles": [ "../Grpc.Core/Version.cs" ] + } + }, + "dependencies": { + "Grpc.Core": "1.1.0-dev", + "Google.Protobuf": "3.0.0" + }, + "frameworks": { + "net45": { + "frameworkAssemblies": { + "System.Runtime": "", + "System.IO": "" + } + }, + "netstandard1.5": { + "dependencies": { + "NETStandard.Library": "1.6.0" + } + } + } +} diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln index 9be36c0caa..2e6a8fd435 100644 --- a/src/csharp/Grpc.sln +++ b/src/csharp/Grpc.sln @@ -36,6 +36,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Qps EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.csproj", "{ADEBA147-80AE-4710-82E9-5B7F93690266}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.csproj", "{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{B88F91D6-436D-4C78-8B99-47800FA8DE03}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -55,6 +59,12 @@ Global {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+ {4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -103,6 +113,12 @@ Global {B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.Build.0 = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+ {B88F91D6-436D-4C78-8B99-47800FA8DE03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B88F91D6-436D-4C78-8B99-47800FA8DE03}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B88F91D6-436D-4C78-8B99-47800FA8DE03}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B88F91D6-436D-4C78-8B99-47800FA8DE03}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B88F91D6-436D-4C78-8B99-47800FA8DE03}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+ {B88F91D6-436D-4C78-8B99-47800FA8DE03}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat deleted file mode 100644 index c0036df13f..0000000000 --- a/src/csharp/build_packages.bat +++ /dev/null @@ -1,91 +0,0 @@ -@rem Copyright 2016, Google Inc. -@rem All rights reserved. -@rem -@rem Redistribution and use in source and binary forms, with or without -@rem modification, are permitted provided that the following conditions are -@rem met: -@rem -@rem * Redistributions of source code must retain the above copyright -@rem notice, this list of conditions and the following disclaimer. -@rem * Redistributions in binary form must reproduce the above -@rem copyright notice, this list of conditions and the following disclaimer -@rem in the documentation and/or other materials provided with the -@rem distribution. -@rem * Neither the name of Google Inc. nor the names of its -@rem contributors may be used to endorse or promote products derived from -@rem this software without specific prior written permission. -@rem -@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -@rem Builds gRPC NuGet packages - -@rem This way of building nuget packages is now obsolete. C# nuget packages -@rem with CoreCLR support are now being built using the dotnet cli -@rem in build_packages_dotnetcli.sh - -@rem Current package versions -set VERSION=1.1.0-dev -set PROTOBUF_VERSION=3.0.0 - -@rem Adjust the location of nuget.exe -set NUGET=C:\nuget\nuget.exe - -@rem Collect the artifacts built by the previous build step if running on Jenkins -@rem TODO(jtattermusch): is there a better way to do this? -xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* nativelibs\windows_x86\ -xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* nativelibs\windows_x64\ -xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* nativelibs\linux_x86\ -xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* nativelibs\linux_x64\ -xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x86\ -xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x64\ - -@rem Collect protoc artifacts built by the previous build step -xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86\ -xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x64\ -xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x86\ -xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x64\ -xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x86\ -xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x64\ - -@rem Fetch all dependencies -%NUGET% restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error - -setlocal - -@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86 - -@rem We won't use the native libraries from this step, but without this Grpc.sln will fail. -msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error - -msbuild Grpc.sln /p:Configuration=ReleaseSigned || goto :error - -endlocal - -%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error -%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error -%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error -%NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error -%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error - -@rem copy resulting nuget packages to artifacts directory -xcopy /Y /I *.nupkg ..\..\artifacts\ - -@rem create a zipfile with the artifacts as well -powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('..\..\artifacts', 'csharp_nugets_obsolete.zip');" -xcopy /Y /I csharp_nugets_obsolete.zip ..\..\artifacts\ - -goto :EOF - -:error -echo Failed! -exit /b %errorlevel% diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index b0e358fdff..9e8c045a1f 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -28,7 +28,7 @@ @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Current package versions -set VERSION=1.0.1 +set VERSION=1.1.0-dev set PROTOBUF_VERSION=3.0.0 @rem Adjust the location of nuget.exe @@ -61,9 +61,10 @@ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* pr %DOTNET% pack --configuration Release Grpc.Core\project.json --output ..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.Auth\project.json --output ..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.HealthCheck\project.json --output ..\..\artifacts || goto :error +%DOTNET% pack --configuration Release Grpc.Reflection\project.json --output ..\..\artifacts || goto :error -%NUGET% pack Grpc.nuspec -Version "1.0.1" -OutputDirectory ..\..\artifacts || goto :error -%NUGET% pack Grpc.Tools.nuspec -Version "1.0.1" -OutputDirectory ..\..\artifacts +%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error +%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts @rem copy resulting nuget packages to artifacts directory xcopy /Y /I *.nupkg ..\..\artifacts\ || goto :error diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index 3c127f320b..52cf2f9ddc 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -63,6 +63,7 @@ dotnet restore . dotnet pack --configuration Release Grpc.Core/project.json --output ../../artifacts dotnet pack --configuration Release Grpc.Auth/project.json --output ../../artifacts dotnet pack --configuration Release Grpc.HealthCheck/project.json --output ../../artifacts +dotnet pack --configuration Release Grpc.Reflection/project.json --output ../../artifacts nuget pack Grpc.nuspec -Version "1.1.0-dev" -OutputDirectory ../../artifacts nuget pack Grpc.Tools.nuspec -Version "1.1.0-dev" -OutputDirectory ../../artifacts diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 37d04eb100..946f5872c0 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -521,8 +521,8 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) { GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(grpc_call *call, grpcsharp_batch_context *ctx, - const char *send_buffer, size_t send_buffer_len, - grpc_metadata_array *initial_metadata, uint32_t write_flags) { + const char *send_buffer, size_t send_buffer_len, uint32_t write_flags, + grpc_metadata_array *initial_metadata, uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[6]; memset(ops, 0, sizeof(ops)); @@ -532,7 +532,7 @@ grpcsharp_call_start_unary(grpc_call *call, grpcsharp_batch_context *ctx, ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; - ops[0].flags = 0; + ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_SEND_MESSAGE; @@ -575,7 +575,8 @@ grpcsharp_call_start_unary(grpc_call *call, grpcsharp_batch_context *ctx, GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(grpc_call *call, grpcsharp_batch_context *ctx, - grpc_metadata_array *initial_metadata) { + grpc_metadata_array *initial_metadata, + uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[4]; memset(ops, 0, sizeof(ops)); @@ -585,7 +586,7 @@ grpcsharp_call_start_client_streaming(grpc_call *call, ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; - ops[0].flags = 0; + ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_RECV_INITIAL_METADATA; @@ -617,7 +618,8 @@ grpcsharp_call_start_client_streaming(grpc_call *call, GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer, - size_t send_buffer_len, grpc_metadata_array *initial_metadata, uint32_t write_flags) { + size_t send_buffer_len, uint32_t write_flags, + grpc_metadata_array *initial_metadata, uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[4]; memset(ops, 0, sizeof(ops)); @@ -627,7 +629,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; - ops[0].flags = 0; + ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_SEND_MESSAGE; @@ -660,7 +662,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(grpc_call *call, grpcsharp_batch_context *ctx, - grpc_metadata_array *initial_metadata) { + grpc_metadata_array *initial_metadata, + uint32_t initial_metadata_flags) { /* TODO: don't use magic number */ grpc_op ops[2]; memset(ops, 0, sizeof(ops)); @@ -670,7 +673,7 @@ grpcsharp_call_start_duplex_streaming(grpc_call *call, ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; ops[0].data.send_initial_metadata.metadata = ctx->send_initial_metadata.metadata; - ops[0].flags = 0; + ops[0].flags = initial_metadata_flags; ops[0].reserved = NULL; ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT; diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh index 79488e02a5..ea5d678cba 100755 --- a/src/csharp/generate_proto_csharp.sh +++ b/src/csharp/generate_proto_csharp.sh @@ -36,13 +36,20 @@ PROTOC=bins/opt/protobuf/protoc PLUGIN=protoc-gen-grpc=bins/opt/grpc_csharp_plugin EXAMPLES_DIR=src/csharp/Grpc.Examples HEALTHCHECK_DIR=src/csharp/Grpc.HealthCheck +REFLECTION_DIR=src/csharp/Grpc.Reflection TESTING_DIR=src/csharp/Grpc.IntegrationTesting $PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \ - -I src/proto/math src/proto/math/math.proto + -I src/proto src/proto/math/math.proto $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \ - -I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto + -I src/proto src/proto/grpc/health/v1/health.proto + +$PROTOC --plugin=$PLUGIN --csharp_out=$REFLECTION_DIR --grpc_out=$REFLECTION_DIR \ + -I src/proto src/proto/grpc/reflection/v1alpha/reflection.proto +# TODO(jtattermusch): following .proto files are a bit broken and import paths +# don't match the package names. Setting -I to the correct value src/proto +# breaks the code generation. $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \ -I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto diff --git a/src/csharp/tests.json b/src/csharp/tests.json index 7e7aee1093..4ce6769eee 100644 --- a/src/csharp/tests.json +++ b/src/csharp/tests.json @@ -48,5 +48,9 @@ "Grpc.IntegrationTesting.MetadataCredentialsTest", "Grpc.IntegrationTesting.RunnerClientServerTest", "Grpc.IntegrationTesting.SslCredentialsTest" + ], + "Grpc.Reflection.Tests": [ + "Grpc.Reflection.Tests.ReflectionClientServerTest", + "Grpc.Reflection.Tests.SymbolRegistryTest" ] }
\ No newline at end of file diff --git a/src/node/performance/worker_service_impl.js b/src/node/performance/worker_service_impl.js index 3f317f6429..38888a7219 100644 --- a/src/node/performance/worker_service_impl.js +++ b/src/node/performance/worker_service_impl.js @@ -55,9 +55,8 @@ module.exports = function WorkerServiceImpl(benchmark_impl, server) { } this.quitWorker = function quitWorker(call, callback) { - server.tryShutdown(function() { - callback(null, {}); - }); + callback(null, {}); + server.tryShutdown(function() {}); }; this.runClient = function runClient(call) { diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 627b6aa86d..38fcae0299 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -112,7 +112,7 @@ } - (void)dealloc { - gpr_free(_op.data.send_message); + grpc_byte_buffer_destroy(_op.data.send_message); } @end diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m index 4a92cc8e0d..4ba7badd86 100644 --- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m +++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m @@ -316,7 +316,8 @@ static char *roots_filename; } - (void)testInvokeLargeRequest { - [self testIndividualCase:"invoke_large_request"]; + // NOT SUPPORTED (frame size) + // [self testIndividualCase:"invoke_large_request"]; } - (void)testLargeMetadata { @@ -329,7 +330,8 @@ static char *roots_filename; } - (void)testMaxMessageLength { - [self testIndividualCase:"max_message_length"]; + // NOT SUPPORTED (close_error) + // [self testIndividualCase:"max_message_length"]; } - (void)testNegativeDeadline { diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 77640525d5..0b72a75f3d 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -43,6 +43,8 @@ #import <RxLibrary/GRXWriteable.h> #import <RxLibrary/GRXWriter+Immediate.h> +#define TEST_TIMEOUT 16 + static NSString * const kHostAddress = @"localhost:5050"; static NSString * const kPackage = @"grpc.testing"; static NSString * const kService = @"TestService"; @@ -137,7 +139,7 @@ static GRPCProtoMethod *kUnaryCallMethod; [call startWithWriteable:responsesWriteable]; - [self waitForExpectationsWithTimeout:4 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testEmptyRPC { @@ -159,7 +161,7 @@ static GRPCProtoMethod *kUnaryCallMethod; [call startWithWriteable:responsesWriteable]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testSimpleProtoRPC { @@ -191,7 +193,7 @@ static GRPCProtoMethod *kUnaryCallMethod; [call startWithWriteable:responsesWriteable]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testMetadata { @@ -225,7 +227,7 @@ static GRPCProtoMethod *kUnaryCallMethod; [call startWithWriteable:responsesWriteable]; - [self waitForExpectationsWithTimeout:4 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testResponseMetadataKVO { @@ -256,7 +258,7 @@ static GRPCProtoMethod *kUnaryCallMethod; [call startWithWriteable:responsesWriteable]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testUserAgentPrefix { @@ -287,7 +289,7 @@ static GRPCProtoMethod *kUnaryCallMethod; [call startWithWriteable:responsesWriteable]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } // TODO(makarandd): Move to a different file that contains only unit tests @@ -347,7 +349,7 @@ static GRPCProtoMethod *kUnaryCallMethod; [call startWithWriteable:responsesWriteable]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @end diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 9804734d6a..c3935ce1e0 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -46,6 +46,8 @@ #import <RxLibrary/GRXBufferedPipe.h> #import <RxLibrary/GRXWriter+Immediate.h> +#define TEST_TIMEOUT 32 + // Convenience constructors for the generated proto messages: @interface RMTStreamingOutputCallRequest (Constructors) @@ -124,7 +126,7 @@ [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:4 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testLargeUnaryRPC { @@ -147,7 +149,7 @@ [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:16 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)test4MBResponsesAreAccepted { @@ -164,7 +166,7 @@ [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:16 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testResponsesOverMaxSizeFailWithActionableMessage { @@ -185,7 +187,7 @@ [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:16 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testResponsesOver4MBAreAcceptedIfOptedIn { @@ -205,7 +207,7 @@ [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:16 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testClientStreamingRPC { @@ -238,7 +240,7 @@ [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testServerStreamingRPC { @@ -275,7 +277,7 @@ } }]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testPingPongRPC { @@ -319,7 +321,7 @@ [expectation fulfill]; } }]; - [self waitForExpectationsWithTimeout:4 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } #ifndef GRPC_COMPILE_WITH_CRONET @@ -335,7 +337,7 @@ XCTAssert(done, @"Unexpected response: %@", response); [expectation fulfill]; }]; - [self waitForExpectationsWithTimeout:2 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } #endif @@ -361,7 +363,7 @@ [call cancel]; XCTAssertEqual(call.state, GRXWriterStateFinished); - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testCancelAfterFirstResponseRPC { @@ -396,7 +398,7 @@ } }]; [call start]; - [self waitForExpectationsWithTimeout:8 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } - (void)testRPCAfterClosingOpenConnections { @@ -420,7 +422,7 @@ }]; }]; - [self waitForExpectationsWithTimeout:4 handler:nil]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @end diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 17478fab12..5785b976f2 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -84,9 +84,9 @@ post_install do |installer| end # CocoaPods creates duplicated library targets of gRPC-Core when the test targets include - # non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core.' + # non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core' # and require the same error suppresion. - if target.name == 'gRPC-Core' or target.name.start_with?('gRPC-Core.') + if target.name.start_with?('gRPC-Core') target.build_configurations.each do |config| # TODO(zyc): Remove this setting after the issue is resolved # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php index 4b35b1a28c..fa33d38911 100644 --- a/src/php/tests/unit_tests/ChannelTest.php +++ b/src/php/tests/unit_tests/ChannelTest.php @@ -99,7 +99,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase $this->channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $time = new Grpc\Timeval(1000); - $state = $this->channel->watchConnectivityState(123, $time); + $state = $this->channel->watchConnectivityState(1, $time); $this->assertTrue($state); unset($time); } diff --git a/src/php/tests/unit_tests/ServerTest.php b/src/php/tests/unit_tests/ServerTest.php index f2346ab113..5f40202f18 100644 --- a/src/php/tests/unit_tests/ServerTest.php +++ b/src/php/tests/unit_tests/ServerTest.php @@ -67,9 +67,9 @@ class ServerTest extends PHPUnit_Framework_TestCase public function testRequestCall() { $this->server = new Grpc\Server(); - $port = $this->server->addHttp2Port('0.0.0.0:8888'); + $port = $this->server->addHttp2Port('0.0.0.0:0'); $this->server->start(); - $channel = new Grpc\Channel('localhost:8888', + $channel = new Grpc\Channel('localhost:' . $port, ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $deadline = Grpc\Timeval::infFuture(); diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 4e4062bafc..cfad7de42f 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -849,6 +849,26 @@ class GenericRpcHandler(six.with_metaclass(abc.ABCMeta)): raise NotImplementedError() +class ServiceRpcHandler(six.with_metaclass(abc.ABCMeta, GenericRpcHandler)): + """An implementation of RPC methods belonging to a service. + + A service handles RPC methods with structured names of the form + '/Service.Name/Service.MethodX', where 'Service.Name' is the value + returned by service_name(), and 'Service.MethodX' is the service method + name. A service can have multiple service methods names, but only a single + service name. + """ + + @abc.abstractmethod + def service_name(self): + """Returns this services name. + + Returns: + The service name. + """ + raise NotImplementedError() + + ############################# Server Interface ############################### @@ -905,6 +925,21 @@ class Server(six.with_metaclass(abc.ABCMeta)): raise NotImplementedError() @abc.abstractmethod + def add_shutdown_handler(self, shutdown_handler): + """Adds a handler to be called on server shutdown. + + Shutdown handlers are run on server stop() or in the event that a running + server is destroyed unexpectedly. The handlers are run in series before + the stop grace period. + + Args: + shutdown_handler: A function taking a single arg, a time in seconds + within which the handler should complete. None indicates the handler can + run for any duration. + """ + raise NotImplementedError() + + @abc.abstractmethod def start(self): """Starts this Server's service of RPCs. @@ -914,7 +949,7 @@ class Server(six.with_metaclass(abc.ABCMeta)): raise NotImplementedError() @abc.abstractmethod - def stop(self, grace): + def stop(self, grace, shutdown_handler_grace=None): """Stops this Server's service of RPCs. All calls to this method immediately stop service of new RPCs. When existing @@ -937,6 +972,8 @@ class Server(six.with_metaclass(abc.ABCMeta)): aborted by this Server's stopping. If None, all RPCs will be aborted immediately and this method will block until this Server is completely stopped. + shutdown_handler_grace: A duration of time in seconds or None. This + value is passed to all shutdown handlers. Returns: A threading.Event that will be set when this Server has completely @@ -1231,7 +1268,8 @@ def secure_channel(target, credentials, options=None): credentials._credentials) -def server(thread_pool, handlers=None, options=None): +def server(thread_pool, handlers=None, options=None, exit_grace=None, + exit_shutdown_handler_grace=None): """Creates a Server with which RPCs can be serviced. Args: @@ -1244,13 +1282,19 @@ def server(thread_pool, handlers=None, options=None): returned Server is started. options: A sequence of string-value pairs according to which to configure the created server. + exit_grace: The grace period to use when terminating + running servers at interpreter exit. None indicates unspecified. + exit_shutdown_handler_grace: The shutdown handler grace to use when + terminating running servers at interpreter exit. None indicates + unspecified. Returns: A Server with which RPCs can be serviced. """ from grpc import _server return _server.Server(thread_pool, () if handlers is None else handlers, - () if options is None else options) + () if options is None else options, exit_grace, + exit_shutdown_handler_grace) ################################### __all__ ################################# @@ -1280,6 +1324,7 @@ __all__ = ( 'RpcMethodHandler', 'HandlerCallDetails', 'GenericRpcHandler', + 'ServiceRpcHandler', 'Server', 'unary_unary_rpc_method_handler', 'unary_stream_rpc_method_handler', diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index 5223712dfa..d83a2e6ded 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -60,7 +60,8 @@ _CANCELLED = 'cancelled' _EMPTY_FLAGS = 0 _EMPTY_METADATA = cygrpc.Metadata(()) -_UNEXPECTED_EXIT_SERVER_GRACE = 1.0 +_DEFAULT_EXIT_GRACE = 1.0 +_DEFAULT_EXIT_SHUTDOWN_HANDLER_GRACE = 5.0 def _serialized_request(request_event): @@ -595,14 +596,18 @@ class _ServerStage(enum.Enum): class _ServerState(object): - def __init__(self, completion_queue, server, generic_handlers, thread_pool): + def __init__(self, completion_queue, server, generic_handlers, thread_pool, + exit_grace, exit_shutdown_handler_grace): self.lock = threading.Lock() self.completion_queue = completion_queue self.server = server self.generic_handlers = list(generic_handlers) self.thread_pool = thread_pool + self.exit_grace = exit_grace + self.exit_shutdown_handler_grace = exit_shutdown_handler_grace self.stage = _ServerStage.STOPPED self.shutdown_events = None + self.shutdown_handlers = [] # TODO(https://github.com/grpc/grpc/issues/6597): eliminate these fields. self.rpc_states = set() @@ -672,41 +677,45 @@ def _serve(state): return -def _stop(state, grace): - with state.lock: - if state.stage is _ServerStage.STOPPED: - shutdown_event = threading.Event() - shutdown_event.set() - return shutdown_event - else: - if state.stage is _ServerStage.STARTED: - state.server.shutdown(state.completion_queue, _SHUTDOWN_TAG) +def _stop(state, grace, shutdown_handler_grace): + shutdown_event = threading.Event() + + def cancel_all_calls_after_grace(): + with state.lock: + if state.stage is _ServerStage.STOPPED: + shutdown_event.set() + return + elif state.stage is _ServerStage.STARTED: + do_shutdown = True state.stage = _ServerStage.GRACE state.shutdown_events = [] - state.due.add(_SHUTDOWN_TAG) - shutdown_event = threading.Event() + else: + do_shutdown = False state.shutdown_events.append(shutdown_event) - if grace is None: + + if do_shutdown: + # Run Shutdown Handlers without the lock + for handler in state.shutdown_handlers: + handler(shutdown_handler_grace) + with state.lock: + state.server.shutdown(state.completion_queue, _SHUTDOWN_TAG) + state.stage = _ServerStage.GRACE + state.due.add(_SHUTDOWN_TAG) + + if not shutdown_event.wait(timeout=grace): + with state.lock: state.server.cancel_all_calls() # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. for rpc_state in state.rpc_states: with rpc_state.condition: rpc_state.client = _CANCELLED rpc_state.condition.notify_all() - else: - def cancel_all_calls_after_grace(): - shutdown_event.wait(timeout=grace) - with state.lock: - state.server.cancel_all_calls() - # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. - for rpc_state in state.rpc_states: - with rpc_state.condition: - rpc_state.client = _CANCELLED - rpc_state.condition.notify_all() - thread = threading.Thread(target=cancel_all_calls_after_grace) - thread.start() - return shutdown_event - shutdown_event.wait() + + if grace is None: + cancel_all_calls_after_grace() + else: + threading.Thread(target=cancel_all_calls_after_grace).start() + return shutdown_event @@ -716,12 +725,12 @@ def _start(state): raise ValueError('Cannot start already-started server!') state.server.start() state.stage = _ServerStage.STARTED - _request_call(state) + _request_call(state) def cleanup_server(timeout): if timeout is None: - _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait() + _stop(state, state.exit_grace, state.exit_shutdown_handler_grace).wait() else: - _stop(state, timeout).wait() + _stop(state, timeout, 0).wait() thread = _common.CleanupThread( cleanup_server, target=_serve, args=(state,)) @@ -729,12 +738,16 @@ def _start(state): class Server(grpc.Server): - def __init__(self, thread_pool, generic_handlers, options): + def __init__(self, thread_pool, generic_handlers, options, exit_grace, + exit_shutdown_handler_grace): completion_queue = cygrpc.CompletionQueue() server = cygrpc.Server(_common.channel_args(options)) server.register_completion_queue(completion_queue) self._state = _ServerState( - completion_queue, server, generic_handlers, thread_pool) + completion_queue, server, generic_handlers, thread_pool, + _DEFAULT_EXIT_GRACE if exit_grace is None else exit_grace, + _DEFAULT_EXIT_SHUTDOWN_HANDLER_GRACE if exit_shutdown_handler_grace + is None else exit_shutdown_handler_grace) def add_generic_rpc_handlers(self, generic_rpc_handlers): _add_generic_handlers(self._state, generic_rpc_handlers) @@ -745,11 +758,14 @@ class Server(grpc.Server): def add_secure_port(self, address, server_credentials): return _add_secure_port(self._state, _common.encode(address), server_credentials) + def add_shutdown_handler(self, handler): + self._state.shutdown_handlers.append(handler) + def start(self): _start(self._state) - def stop(self, grace): - return _stop(self._state, grace) + def stop(self, grace, shutdown_handler_grace=None): + return _stop(self._state, grace, shutdown_handler_grace) def __del__(self): - _stop(self._state, None) + _stop(self._state, None, None) diff --git a/src/python/grpcio/grpc/_utilities.py b/src/python/grpcio/grpc/_utilities.py index 4850967fbc..a375896e6e 100644 --- a/src/python/grpcio/grpc/_utilities.py +++ b/src/python/grpcio/grpc/_utilities.py @@ -53,13 +53,17 @@ class RpcMethodHandler( pass -class DictionaryGenericHandler(grpc.GenericRpcHandler): +class DictionaryGenericHandler(grpc.ServiceRpcHandler): def __init__(self, service, method_handlers): + self._name = service self._method_handlers = { _common.fully_qualified_method(service, method): method_handler for method, method_handler in six.iteritems(method_handlers)} + def service_name(self): + return self._name + def service(self, handler_call_details): return self._method_handlers.get(handler_call_details.method) diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index bfd706a78b..d43f93b94f 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -226,9 +226,9 @@ CORE_SOURCE_FILES = [ 'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/transport/client_auth_filter.c', - 'src/core/lib/security/transport/handshake.c', 'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/security_connector.c', + 'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/server_auth_filter.c', 'src/core/lib/security/transport/tsi_error.c', 'src/core/lib/security/util/b64.c', @@ -237,6 +237,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/tsi/fake_transport_security.c', 'src/core/lib/tsi/ssl_transport_security.c', 'src/core/lib/tsi/transport_security.c', + 'src/core/ext/transport/chttp2/server/chttp2_server.c', 'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c', 'src/core/ext/client_channel/channel_connectivity.c', 'src/core/ext/client_channel/client_channel.c', @@ -256,6 +257,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/client_channel/subchannel.c', 'src/core/ext/client_channel/subchannel_index.c', 'src/core/ext/client_channel/uri_parser.c', + 'src/core/ext/transport/chttp2/client/chttp2_connector.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py index 089366a8c7..64fd97256e 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py @@ -167,7 +167,7 @@ class SameSeparateTest(unittest.TestCase, SeparateTestMixin): '', '--proto_path={}'.format(self.proto_directory), '--python_out={}'.format(self.python_out_directory), - '--grpc_python_out={}'.format(self.grpc_python_out_directory), + '--grpc_python_out=grpc_2_0:{}'.format(self.grpc_python_out_directory), same_proto_file, ]) if protoc_result != 0: @@ -241,7 +241,7 @@ class SplitCommonTest(unittest.TestCase, CommonTestMixin): '', '--proto_path={}'.format(self.proto_directory), '--python_out={}'.format(self.python_out_directory), - '--grpc_python_out={}'.format(self.python_out_directory), + '--grpc_python_out={}'.format(self.grpc_python_out_directory), services_proto_file, messages_proto_file, ]) @@ -285,7 +285,7 @@ class SplitSeparateTest(unittest.TestCase, SeparateTestMixin): '', '--proto_path={}'.format(self.proto_directory), '--python_out={}'.format(self.python_out_directory), - '--grpc_python_out={}'.format(self.grpc_python_out_directory), + '--grpc_python_out=grpc_2_0:{}'.format(self.grpc_python_out_directory), services_proto_file, messages_proto_file, ]) diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json index dd4a0257f5..04a2e44178 100644 --- a/src/python/grpcio_tests/tests/tests.json +++ b/src/python/grpcio_tests/tests/tests.json @@ -27,6 +27,7 @@ "unit._cython.cygrpc_test.TypeSmokeTest", "unit._empty_message_test.EmptyMessageTest", "unit._exit_test.ExitTest", + "unit._exit_test.ShutdownHandlerTest", "unit._metadata_code_details_test.MetadataCodeDetailsTest", "unit._metadata_test.MetadataTest", "unit._rpc_test.RPCTest", diff --git a/src/python/grpcio_tests/tests/unit/_api_test.py b/src/python/grpcio_tests/tests/unit/_api_test.py index 2fe89499f5..51dc425420 100644 --- a/src/python/grpcio_tests/tests/unit/_api_test.py +++ b/src/python/grpcio_tests/tests/unit/_api_test.py @@ -65,6 +65,7 @@ class AllTest(unittest.TestCase): 'RpcMethodHandler', 'HandlerCallDetails', 'GenericRpcHandler', + 'ServiceRpcHandler', 'Server', 'unary_unary_rpc_method_handler', 'unary_stream_rpc_method_handler', diff --git a/src/python/grpcio_tests/tests/unit/_exit_test.py b/src/python/grpcio_tests/tests/unit/_exit_test.py index 5a4a32887c..342f5fcc10 100644 --- a/src/python/grpcio_tests/tests/unit/_exit_test.py +++ b/src/python/grpcio_tests/tests/unit/_exit_test.py @@ -43,6 +43,8 @@ import threading import time import unittest +import grpc +from grpc.framework.foundation import logging_pool from tests.unit import _exit_scenarios SCENARIO_FILE = os.path.abspath(os.path.join( @@ -52,7 +54,7 @@ BASE_COMMAND = [INTERPRETER, SCENARIO_FILE] BASE_SIGTERM_COMMAND = BASE_COMMAND + ['--wait_for_interrupt'] INIT_TIME = 1.0 - +SHUTDOWN_GRACE = 5.0 processes = [] process_lock = threading.Lock() @@ -182,5 +184,24 @@ class ExitTest(unittest.TestCase): interrupt_and_wait(process) +class _ShutDownHandler(object): + + def __init__(self): + self.seen_handler_grace = None + + def shutdown_handler(self, handler_grace): + self.seen_handler_grace = handler_grace + + +class ShutdownHandlerTest(unittest.TestCase): + + def test_shutdown_handler(self): + server = grpc.server(logging_pool.pool(1)) + handler = _ShutDownHandler() + server.add_shutdown_handler(handler.shutdown_handler) + server.start() + server.stop(0, shutdown_handler_grace=SHUTDOWN_GRACE).wait() + self.assertEqual(SHUTDOWN_GRACE, handler.seen_handler_grace) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/templates/src/csharp/Grpc.Reflection.Tests/project.json.template b/templates/src/csharp/Grpc.Reflection.Tests/project.json.template new file mode 100644 index 0000000000..2869609138 --- /dev/null +++ b/templates/src/csharp/Grpc.Reflection.Tests/project.json.template @@ -0,0 +1,26 @@ +%YAML 1.2 +--- | + { + <%include file="../build_options.include" args="executable=True"/> + "dependencies": { + "Grpc.Reflection": { + "target": "project" + }, + "NUnit": "3.2.0", + "NUnitLite": "3.2.0-*" + }, + "frameworks": { + "net45": { }, + "netcoreapp1.0": { + "imports": [ + "portable-net45" + ], + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + } + } + } + } + } diff --git a/templates/src/csharp/Grpc.Reflection/project.json.template b/templates/src/csharp/Grpc.Reflection/project.json.template new file mode 100644 index 0000000000..8a33e1ccc9 --- /dev/null +++ b/templates/src/csharp/Grpc.Reflection/project.json.template @@ -0,0 +1,42 @@ +%YAML 1.2 +--- | + { + "version": "${settings.csharp_version}", + "title": "gRPC C# Reflection", + "authors": [ "Google Inc." ], + "copyright": "Copyright 2016, Google Inc.", + "packOptions": { + "summary": "Implementation of gRPC reflection service", + "description": "Provides information about services running on a gRPC C# server.", + "owners": [ "grpc-packages" ], + "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE", + "projectUrl": "https://github.com/grpc/grpc", + "requireLicenseAcceptance": false, + "tags": [ "gRPC reflection" ] + }, + "buildOptions": { + "define": [ "SIGNED" ], + "keyFile": "../keys/Grpc.snk", + "xmlDoc": true, + "compile": { + "includeFiles": [ "../Grpc.Core/Version.cs" ] + } + }, + "dependencies": { + "Grpc.Core": "${settings.csharp_version}", + "Google.Protobuf": "3.0.0" + }, + "frameworks": { + "net45": { + "frameworkAssemblies": { + "System.Runtime": "", + "System.IO": "" + } + }, + "netstandard1.5": { + "dependencies": { + "NETStandard.Library": "1.6.0" + } + } + } + } diff --git a/templates/src/csharp/build_packages.bat.template b/templates/src/csharp/build_packages_dotnetcli.bat.template index 87c4b5ae27..562b7704ab 100644..100755 --- a/templates/src/csharp/build_packages.bat.template +++ b/templates/src/csharp/build_packages_dotnetcli.bat.template @@ -29,18 +29,17 @@ @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - @rem Builds gRPC NuGet packages - - @rem This way of building nuget packages is now obsolete. C# nuget packages - @rem with CoreCLR support are now being built using the dotnet cli - @rem in build_packages_dotnetcli.sh - @rem Current package versions set VERSION=${settings.csharp_version} set PROTOBUF_VERSION=3.0.0 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe + set DOTNET=C:\dotnet\dotnet.exe + + set -ex + + mkdir -p ..\..\artifacts${"\\"} @rem Collect the artifacts built by the previous build step if running on Jenkins @rem TODO(jtattermusch): is there a better way to do this? @@ -59,32 +58,22 @@ xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x86${"\\"} xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x64${"\\"} - @rem Fetch all dependencies - %%NUGET% restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error - - setlocal - - @call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86 - - @rem We won't use the native libraries from this step, but without this Grpc.sln will fail. - msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error - - msbuild Grpc.sln /p:Configuration=ReleaseSigned || goto :error + %%DOTNET% restore . || goto :error - endlocal + %%DOTNET% pack --configuration Release Grpc.Core\project.json --output ..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.Auth\project.json --output ..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.HealthCheck\project.json --output ..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.Reflection\project.json --output ..\..\artifacts || goto :error - %%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error - %%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error - %%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error - %%NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error - %%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error + %%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error + %%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts @rem copy resulting nuget packages to artifacts directory - xcopy /Y /I *.nupkg ..\..\artifacts${"\\"} + xcopy /Y /I *.nupkg ..\..\artifacts\ || goto :error @rem create a zipfile with the artifacts as well - powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('..\..\artifacts', 'csharp_nugets_obsolete.zip');" - xcopy /Y /I csharp_nugets_obsolete.zip ..\..\artifacts${"\\"} + powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('..\..\artifacts', 'csharp_nugets_windows_dotnetcli.zip');" + xcopy /Y /I csharp_nugets_windows_dotnetcli.zip ..\..\artifacts\ || goto :error goto :EOF diff --git a/templates/src/csharp/build_packages_dotnetcli.sh.template b/templates/src/csharp/build_packages_dotnetcli.sh.template index 99b049a5a1..91c6fb6928 100755 --- a/templates/src/csharp/build_packages_dotnetcli.sh.template +++ b/templates/src/csharp/build_packages_dotnetcli.sh.template @@ -65,6 +65,7 @@ dotnet pack --configuration Release Grpc.Core/project.json --output ../../artifacts dotnet pack --configuration Release Grpc.Auth/project.json --output ../../artifacts dotnet pack --configuration Release Grpc.HealthCheck/project.json --output ../../artifacts + dotnet pack --configuration Release Grpc.Reflection/project.json --output ../../artifacts nuget pack Grpc.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts nuget pack Grpc.Tools.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template index 12309b64d1..0168353933 100644 --- a/templates/tools/dockerfile/test/sanity/Dockerfile.template +++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template @@ -48,9 +48,12 @@ #====================================== # More sanity test dependencies (bazel) RUN apt-get install -y openjdk-8-jdk - # TOOD(jtattermusch): pin the bazel version - RUN git clone https://github.com/bazelbuild/bazel.git /bazel - RUN cd /bazel && ./compile.sh + # Check out Bazel version 0.4.1 since this version allows running + # ./compile.sh without a local protoc dependency + # TODO(mattkwong): install dependencies to support latest Bazel version if newer + # version is needed + RUN git clone https://github.com/bazelbuild/bazel.git /bazel && \ + cd /bazel && git checkout tags/0.4.1 && ./compile.sh RUN ln -s /bazel/output/bazel /bin/ #=================== diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c index 95595d7c51..6e4058fc21 100644 --- a/test/core/client_channel/lb_policies_test.c +++ b/test/core/client_channel/lb_policies_test.c @@ -64,9 +64,11 @@ typedef struct servers_fixture { } servers_fixture; typedef struct request_sequences { - size_t n; - int *connections; - int *connectivity_states; + size_t n; /* number of iterations */ + int *connections; /* indexed by the interation number, value is the index of + the server it connected to or -1 if none */ + int *connectivity_states; /* indexed by the interation number, value is the + client connectivity state */ } request_sequences; typedef void (*verifier_fn)(const servers_fixture *, grpc_channel *, @@ -481,7 +483,7 @@ void run_spec(const test_spec *spec) { gpr_asprintf(&client_hostport, "ipv4:%s", servers_hostports_str); arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff"; + arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; arg_array[0].value.integer = RETRY_TIMEOUT; arg_array[1].type = GRPC_ARG_STRING; arg_array[1].key = GRPC_ARG_LB_POLICY_NAME; @@ -519,7 +521,7 @@ static grpc_channel *create_client(const servers_fixture *f) { gpr_asprintf(&client_hostport, "ipv4:%s", servers_hostports_str); arg_array[0].type = GRPC_ARG_INTEGER; - arg_array[0].key = "grpc.testing.fixed_reconnect_backoff"; + arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; arg_array[0].value.integer = RETRY_TIMEOUT; arg_array[1].type = GRPC_ARG_STRING; arg_array[1].key = GRPC_ARG_LB_POLICY_NAME; @@ -780,15 +782,17 @@ static void verify_total_carnage_round_robin(const servers_fixture *f, } } - /* no server is ever available. The persistent state is TRANSIENT_FAILURE */ + /* no server is ever available. The persistent state is TRANSIENT_FAILURE. May + * also be CONNECTING if, under load, this check took too long to run and some + * subchannel already transitioned to retrying. */ for (size_t i = 0; i < sequences->n; i++) { const grpc_connectivity_state actual = sequences->connectivity_states[i]; - const grpc_connectivity_state expected = GRPC_CHANNEL_TRANSIENT_FAILURE; - if (actual != expected) { + if (actual != GRPC_CHANNEL_TRANSIENT_FAILURE && + actual != GRPC_CHANNEL_CONNECTING) { gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " - "at iteration #%d", - grpc_connectivity_state_name(expected), + "CONNECTIVITY STATUS SEQUENCE FAILURE: expected " + "GRPC_CHANNEL_TRANSIENT_FAILURE or GRPC_CHANNEL_CONNECTING, got " + "'%s' at iteration #%d", grpc_connectivity_state_name(actual), (int)i); abort(); } @@ -825,8 +829,7 @@ static void verify_partial_carnage_round_robin( } /* We can assert that the first client channel state should be READY, when all - * servers were available; and that the last one should be TRANSIENT_FAILURE, - * after all servers are gone. */ + * servers were available */ grpc_connectivity_state actual = sequences->connectivity_states[0]; grpc_connectivity_state expected = GRPC_CHANNEL_READY; if (actual != expected) { @@ -838,17 +841,21 @@ static void verify_partial_carnage_round_robin( abort(); } + /* ... and that the last one should be TRANSIENT_FAILURE, after all servers + * are gone. May also be CONNECTING if, under load, this check took too long + * to run and the subchannel already transitioned to retrying. */ actual = sequences->connectivity_states[num_iters - 1]; - expected = GRPC_CHANNEL_TRANSIENT_FAILURE; - if (actual != expected) { - gpr_log(GPR_ERROR, - "CONNECTIVITY STATUS SEQUENCE FAILURE: expected '%s', got '%s' " - "at iteration #%d", - grpc_connectivity_state_name(expected), - grpc_connectivity_state_name(actual), (int)num_iters - 1); - abort(); + for (i = 0; i < sequences->n; i++) { + if (actual != GRPC_CHANNEL_TRANSIENT_FAILURE && + actual != GRPC_CHANNEL_CONNECTING) { + gpr_log(GPR_ERROR, + "CONNECTIVITY STATUS SEQUENCE FAILURE: expected " + "GRPC_CHANNEL_TRANSIENT_FAILURE or GRPC_CHANNEL_CONNECTING, got " + "'%s' at iteration #%d", + grpc_connectivity_state_name(actual), (int)i); + abort(); + } } - gpr_free(expected_connection_sequence); } @@ -873,68 +880,21 @@ static void verify_rebirth_round_robin(const servers_fixture *f, grpc_channel *client, const request_sequences *sequences, const size_t num_iters) { - int *expected_connection_sequence; - size_t i, j, unique_seq_last_idx, unique_seq_first_idx; - const size_t expected_seq_length = f->num_servers; - int *seen_elements; - dump_array("actual_connection_sequence", sequences->connections, num_iters); - /* verify conn. seq. expectation */ - /* get the first unique run of length "num_servers". */ - expected_connection_sequence = gpr_malloc(sizeof(int) * expected_seq_length); - seen_elements = gpr_malloc(sizeof(int) * expected_seq_length); - - unique_seq_last_idx = ~(size_t)0; - - memset(seen_elements, 0, sizeof(int) * expected_seq_length); - for (i = 0; i < num_iters; i++) { - if (sequences->connections[i] < 0 || - seen_elements[sequences->connections[i]] != 0) { - /* if anything breaks the uniqueness of the run, back to square zero */ - memset(seen_elements, 0, sizeof(int) * expected_seq_length); - continue; - } - seen_elements[sequences->connections[i]] = 1; - for (j = 0; j < expected_seq_length; j++) { - if (seen_elements[j] == 0) break; - } - if (j == expected_seq_length) { /* seen all the elements */ - unique_seq_last_idx = i; - break; - } - } - /* make sure we found a valid run */ - dump_array("seen_elements", seen_elements, expected_seq_length); - for (j = 0; j < expected_seq_length; j++) { - GPR_ASSERT(seen_elements[j] != 0); - } - - GPR_ASSERT(unique_seq_last_idx != ~(size_t)0); - - unique_seq_first_idx = (unique_seq_last_idx - expected_seq_length + 1); - memcpy(expected_connection_sequence, - sequences->connections + unique_seq_first_idx, - sizeof(int) * expected_seq_length); - /* first iteration succeeds */ GPR_ASSERT(sequences->connections[0] != -1); /* then we fail for a while... */ GPR_ASSERT(sequences->connections[1] == -1); - /* ... but should be up at "unique_seq_first_idx" */ - GPR_ASSERT(sequences->connections[unique_seq_first_idx] != -1); - - for (j = 0, i = unique_seq_first_idx; i < num_iters; i++) { - const int actual = sequences->connections[i]; - const int expected = - expected_connection_sequence[j++ % expected_seq_length]; - if (actual != expected) { - print_failed_expectations(expected_connection_sequence, - sequences->connections, expected_seq_length, - num_iters); - abort(); + /* ... but should be up eventually */ + size_t first_iter_back_up = ~0ul; + for (size_t i = 2; i < sequences->n; ++i) { + if (sequences->connections[i] != -1) { + first_iter_back_up = i; + break; } } + GPR_ASSERT(first_iter_back_up != ~0ul); /* We can assert that the first client channel state should be READY, when all * servers were available; same thing for the last one. In the middle @@ -962,7 +922,7 @@ static void verify_rebirth_round_robin(const servers_fixture *f, } bool found_failure_status = false; - for (i = 1; i < sequences->n - 1; i++) { + for (size_t i = 1; i < sequences->n - 1; i++) { if (sequences->connectivity_states[i] == GRPC_CHANNEL_TRANSIENT_FAILURE) { found_failure_status = true; break; @@ -974,14 +934,11 @@ static void verify_rebirth_round_robin(const servers_fixture *f, "CONNECTIVITY STATUS SEQUENCE FAILURE: " "GRPC_CHANNEL_TRANSIENT_FAILURE status not found. Got the following " "instead:"); - for (i = 0; i < num_iters; i++) { + for (size_t i = 0; i < num_iters; i++) { gpr_log(GPR_ERROR, "[%d]: %s", (int)i, grpc_connectivity_state_name(sequences->connectivity_states[i])); } } - - gpr_free(expected_connection_sequence); - gpr_free(seen_elements); } int main(int argc, char **argv) { diff --git a/test/core/client_channel/set_initial_connect_string_test.c b/test/core/client_channel/set_initial_connect_string_test.c index b16a3ebf45..11e57439d5 100644 --- a/test/core/client_channel/set_initial_connect_string_test.c +++ b/test/core/client_channel/set_initial_connect_string_test.c @@ -92,6 +92,7 @@ static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor) { + gpr_free(acceptor); test_tcp_server *server = arg; grpc_closure_init(&on_read, handle_read, NULL); grpc_slice_buffer_init(&state.incoming_buffer); diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c index 1c4a17fda8..30468558e8 100644 --- a/test/core/end2end/bad_server_response_test.c +++ b/test/core/end2end/bad_server_response_test.c @@ -145,6 +145,7 @@ static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor) { + gpr_free(acceptor); test_tcp_server *server = arg; grpc_closure_init(&on_read, handle_read, NULL); grpc_closure_init(&on_write, done_write, NULL); diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index 663489082f..76dd645b93 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -119,6 +119,8 @@ extern void resource_quota_server(grpc_end2end_test_config config); extern void resource_quota_server_pre_init(void); extern void server_finishes_request(grpc_end2end_test_config config); extern void server_finishes_request_pre_init(void); +extern void short_deadlines(grpc_end2end_test_config config); +extern void short_deadlines_pre_init(void); extern void shutdown_finishes_calls(grpc_end2end_test_config config); extern void shutdown_finishes_calls_pre_init(void); extern void shutdown_finishes_tags(grpc_end2end_test_config config); @@ -177,6 +179,7 @@ void grpc_end2end_tests_pre_init(void) { request_with_payload_pre_init(); resource_quota_server_pre_init(); server_finishes_request_pre_init(); + short_deadlines_pre_init(); shutdown_finishes_calls_pre_init(); shutdown_finishes_tags_pre_init(); simple_cacheable_request_pre_init(); @@ -232,6 +235,7 @@ void grpc_end2end_tests(int argc, char **argv, request_with_payload(config); resource_quota_server(config); server_finishes_request(config); + short_deadlines(config); shutdown_finishes_calls(config); shutdown_finishes_tags(config); simple_cacheable_request(config); @@ -396,6 +400,10 @@ void grpc_end2end_tests(int argc, char **argv, server_finishes_request(config); continue; } + if (0 == strcmp("short_deadlines", argv[i])) { + short_deadlines(config); + continue; + } if (0 == strcmp("shutdown_finishes_calls", argv[i])) { shutdown_finishes_calls(config); continue; diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index 25c7c62fde..754fbfc6fa 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -121,6 +121,8 @@ extern void resource_quota_server(grpc_end2end_test_config config); extern void resource_quota_server_pre_init(void); extern void server_finishes_request(grpc_end2end_test_config config); extern void server_finishes_request_pre_init(void); +extern void short_deadlines(grpc_end2end_test_config config); +extern void short_deadlines_pre_init(void); extern void shutdown_finishes_calls(grpc_end2end_test_config config); extern void shutdown_finishes_calls_pre_init(void); extern void shutdown_finishes_tags(grpc_end2end_test_config config); @@ -180,6 +182,7 @@ void grpc_end2end_tests_pre_init(void) { request_with_payload_pre_init(); resource_quota_server_pre_init(); server_finishes_request_pre_init(); + short_deadlines_pre_init(); shutdown_finishes_calls_pre_init(); shutdown_finishes_tags_pre_init(); simple_cacheable_request_pre_init(); @@ -236,6 +239,7 @@ void grpc_end2end_tests(int argc, char **argv, request_with_payload(config); resource_quota_server(config); server_finishes_request(config); + short_deadlines(config); shutdown_finishes_calls(config); shutdown_finishes_tags(config); simple_cacheable_request(config); @@ -404,6 +408,10 @@ void grpc_end2end_tests(int argc, char **argv, server_finishes_request(config); continue; } + if (0 == strcmp("short_deadlines", argv[i])) { + short_deadlines(config); + continue; + } if (0 == strcmp("shutdown_finishes_calls", argv[i])) { shutdown_finishes_calls(config); continue; diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy.c index 57fc4a38f8..80865fc7a6 100644 --- a/test/core/end2end/fixtures/http_proxy.c +++ b/test/core/end2end/fixtures/http_proxy.c @@ -367,6 +367,7 @@ static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, grpc_endpoint* endpoint, grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor) { + gpr_free(acceptor); grpc_end2end_http_proxy* proxy = arg; // Instantiate proxy_connection. proxy_connection* conn = gpr_malloc(sizeof(*conn)); diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 201a92a1fd..655236ca5d 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -122,6 +122,7 @@ END2END_TESTS = { 'max_concurrent_streams': default_test_options._replace(proxyable=False), 'max_message_length': default_test_options, 'negative_deadline': default_test_options, + 'short_deadlines': default_test_options, 'network_status_change': default_test_options, 'no_logging': default_test_options._replace(traceable=False), 'no_op': default_test_options, diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c index a8c7b2be5a..cd68b390bb 100644 --- a/test/core/end2end/goaway_server_test.c +++ b/test/core/end2end/goaway_server_test.c @@ -126,8 +126,16 @@ int main(int argc, char **argv) { char *addr; + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; + /* create a channel that picks first amongst the servers */ - grpc_channel *chan = grpc_insecure_channel_create("test", NULL, NULL); + grpc_channel *chan = grpc_insecure_channel_create("test", &client_args, NULL); /* and an initial call to them */ grpc_call *call1 = grpc_channel_create_call( chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "127.0.0.1", diff --git a/test/core/end2end/tests/connectivity.c b/test/core/end2end/tests/connectivity.c index 260297ebd4..42475c7331 100644 --- a/test/core/end2end/tests/connectivity.c +++ b/test/core/end2end/tests/connectivity.c @@ -68,7 +68,15 @@ static void test_connectivity(grpc_end2end_test_config config) { gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; - config.init_client(&f, NULL); + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; + + config.init_client(&f, &client_args); ce.channel = f.client; ce.cq = f.cq; diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c index db2e5c83de..4a88c5f2a8 100644 --- a/test/core/end2end/tests/payload.c +++ b/test/core/end2end/tests/payload.c @@ -126,7 +126,7 @@ static void request_response_with_payload(grpc_end2end_test_config config, grpc_raw_byte_buffer_create(&request_payload_slice, 1); grpc_byte_buffer *response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - gpr_timespec deadline = five_seconds_time(); + gpr_timespec deadline = n_seconds_time(60); cq_verifier *cqv = cq_verifier_create(f.cq); grpc_op ops[6]; grpc_op *op; diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c index 7ec33e97a3..c919faea89 100644 --- a/test/core/end2end/tests/resource_quota_server.c +++ b/test/core/end2end/tests/resource_quota_server.c @@ -234,7 +234,7 @@ void resource_quota_server(grpc_end2end_test_config config) { while (pending_client_calls + pending_server_recv_calls + pending_server_end_calls > 0) { - grpc_event ev = grpc_completion_queue_next(f.cq, n_seconds_time(10), NULL); + grpc_event ev = grpc_completion_queue_next(f.cq, n_seconds_time(60), NULL); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); int ev_tag = (int)(intptr_t)ev.tag; diff --git a/test/core/end2end/tests/short_deadlines.c b/test/core/end2end/tests/short_deadlines.c new file mode 100644 index 0000000000..9602a34f91 --- /dev/null +++ b/test/core/end2end/tests/short_deadlines.c @@ -0,0 +1,203 @@ +/* + * + * 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 "test/core/end2end/end2end_tests.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/byte_buffer.h> +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); +} + +static void simple_request_body_with_deadline(grpc_end2end_test_config config, + grpc_end2end_test_fixture f, + size_t num_ops, int deadline_ms) { + grpc_call *c; + const gpr_timespec deadline = + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(deadline_ms, GPR_TIMESPAN)); + + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_status_code status; + grpc_call_error error; + char *details = NULL; + size_t details_capacity = 0; + + gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops, %d ms deadline", num_ops, + deadline_ms); + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", + get_host_override_string("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + GPR_ASSERT(num_ops <= (size_t)(op - ops)); + error = grpc_call_start_batch(c, ops, num_ops, tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* because there's no logic here to move along the server side of the call, + * client calls are always going to timeout */ + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + if (status != GRPC_STATUS_DEADLINE_EXCEEDED) { + gpr_log(GPR_ERROR, + "Expected GRPC_STATUS_DEADLINE_EXCEEDED (code %d), got code %d", + GRPC_STATUS_DEADLINE_EXCEEDED, status); + abort(); + } + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + + grpc_call_destroy(c); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_short_deadline_request(grpc_end2end_test_config config, + size_t num_ops, + int deadline_ms) { + grpc_end2end_test_fixture f; + + f = begin_test(config, "test_invoke_short_deadline_request", NULL, NULL); + simple_request_body_with_deadline(config, f, num_ops, deadline_ms); + end_test(&f); + config.tear_down_data(&f); +} + +void short_deadlines(grpc_end2end_test_config config) { + size_t i; + for (i = 1; i <= 4; i++) { + test_invoke_short_deadline_request(config, i, 0); + test_invoke_short_deadline_request(config, i, 1); + test_invoke_short_deadline_request(config, i, 5); + test_invoke_short_deadline_request(config, i, 10); + test_invoke_short_deadline_request(config, i, 15); + test_invoke_short_deadline_request(config, i, 30); + } +} + +void short_deadlines_pre_init(void) {} diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c index ec40c8f22d..414a03d98b 100644 --- a/test/core/end2end/tests/simple_delayed_request.c +++ b/test/core/end2end/tests/simple_delayed_request.c @@ -200,21 +200,36 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, static void test_simple_delayed_request_short(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; gpr_log(GPR_INFO, "%s/%s", "test_simple_delayed_request_short", config.name); f = config.create_fixture(NULL, NULL); - simple_delayed_request_body(config, &f, NULL, NULL, 100000); + + simple_delayed_request_body(config, &f, &client_args, NULL, 100000); end_test(&f); config.tear_down_data(&f); } static void test_simple_delayed_request_long(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; + grpc_channel_args client_args; + grpc_arg arg_array[1]; + arg_array[0].type = GRPC_ARG_INTEGER; + arg_array[0].key = "grpc.testing.fixed_reconnect_backoff_ms"; + arg_array[0].value.integer = 1000; + client_args.args = arg_array; + client_args.num_args = 1; gpr_log(GPR_INFO, "%s/%s", "test_simple_delayed_request_long", config.name); f = config.create_fixture(NULL, NULL); /* This timeout should be longer than a single retry */ - simple_delayed_request_body(config, &f, NULL, NULL, 1500000); + simple_delayed_request_body(config, &f, &client_args, NULL, 1500000); end_test(&f); config.tear_down_data(&f); } diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c index 1b8a39c1be..9a7810e227 100644 --- a/test/core/iomgr/tcp_server_posix_test.c +++ b/test/core/iomgr/tcp_server_posix_test.c @@ -126,6 +126,7 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, on_connect_result temp_result; on_connect_result_set(&temp_result, acceptor); + gpr_free(acceptor); gpr_mu_lock(g_mu); g_result = temp_result; diff --git a/test/core/security/ssl_server_fuzzer.c b/test/core/security/ssl_server_fuzzer.c index 04969765f5..8673225fef 100644 --- a/test/core/security/ssl_server_fuzzer.c +++ b/test/core/security/ssl_server_fuzzer.c @@ -58,17 +58,14 @@ struct handshake_state { bool done_callback_called; }; -static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, - grpc_security_status status, - grpc_endpoint *secure_endpoint, - grpc_auth_context *auth_context) { - struct handshake_state *state = (struct handshake_state *)statep; +static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_handshaker_args *args = arg; + struct handshake_state *state = args->user_data; GPR_ASSERT(state->done_callback_called == false); state->done_callback_called = true; // The fuzzer should not pass the handshake. - GPR_ASSERT(status != GRPC_SECURITY_OK); - GPR_ASSERT(secure_endpoint == NULL); - GPR_ASSERT(auth_context == NULL); + GPR_ASSERT(error != GRPC_ERROR_NONE); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { @@ -108,15 +105,16 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { grpc_security_status status = grpc_server_credentials_create_security_connector(creds, &sc); GPR_ASSERT(status == GRPC_SECURITY_OK); - sc->channel_args = NULL; gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(1, GPR_TIMESPAN)); struct handshake_state state; state.done_callback_called = false; - grpc_server_security_connector_do_handshake(&exec_ctx, sc, NULL, - mock_endpoint, NULL, deadline, - on_secure_handshake_done, &state); + grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create(); + grpc_server_security_connector_add_handshakers(&exec_ctx, sc, handshake_mgr); + grpc_handshake_manager_do_handshake( + &exec_ctx, handshake_mgr, mock_endpoint, NULL /* channel_args */, + deadline, NULL /* acceptor */, on_handshake_done, &state); grpc_exec_ctx_flush(&exec_ctx); // If the given string happens to be part of the correct client hello, the @@ -129,6 +127,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { GPR_ASSERT(state.done_callback_called); + grpc_handshake_manager_destroy(&exec_ctx, handshake_mgr); GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "test"); grpc_server_credentials_release(creds); grpc_slice_unref(cert_slice); diff --git a/test/core/support/backoff_test.c b/test/core/support/backoff_test.c index 13cba7d750..ad6e5a98f2 100644 --- a/test/core/support/backoff_test.c +++ b/test/core/support/backoff_test.c @@ -39,61 +39,110 @@ static void test_constant_backoff(void) { gpr_backoff backoff; - gpr_backoff_init(&backoff, 1.0, 0.0, 1000, 1000); + gpr_backoff_init(&backoff, 200 /* initial timeout */, 1.0 /* multiplier */, + 0.0 /* jitter */, 100 /* min timeout */, + 1000 /* max timeout */); gpr_timespec now = gpr_time_0(GPR_TIMESPAN); gpr_timespec next = gpr_backoff_begin(&backoff, now); - GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 1000); + GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 200); for (int i = 0; i < 10000; i++) { next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 1000); + GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 200); now = next; } } -static void test_no_jitter_backoff(void) { +static void test_min_connect(void) { gpr_backoff backoff; - gpr_backoff_init(&backoff, 2.0, 0.0, 1, 513); + gpr_backoff_init(&backoff, 100 /* initial timeout */, 1.0 /* multiplier */, + 0.0 /* jitter */, 200 /* min timeout */, + 1000 /* max timeout */); gpr_timespec now = gpr_time_0(GPR_TIMESPAN); gpr_timespec next = gpr_backoff_begin(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1, GPR_TIMESPAN), next) == 0); - now = next; - next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(3, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 200); +} + +static void test_no_jitter_backoff(void) { + gpr_backoff backoff; + gpr_backoff_init(&backoff, 2 /* initial timeout */, 2.0 /* multiplier */, + 0.0 /* jitter */, 1 /* min timeout */, + 513 /* max timeout */); + // x_1 = 2 + // x_n = 2**i + x_{i-1} ( = 2**(n+1) - 2 ) + gpr_timespec now = gpr_time_0(GPR_TIMESPAN); + gpr_timespec next = gpr_backoff_begin(&backoff, now); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(7, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(6, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(15, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(14, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(31, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(30, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(63, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(62, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(127, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(126, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(255, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(254, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(511, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(510, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1023, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1022, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1536, GPR_TIMESPAN), next) == 0); + // Hit the maximum timeout. From this point onwards, retries will increase + // only by max timeout. + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1535, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2049, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2048, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); - GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2562, GPR_TIMESPAN), next) == 0); + GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2561, GPR_TIMESPAN), next) == 0); +} + +static void test_jitter_backoff(void) { + const int64_t initial_timeout = 500; + const double jitter = 0.1; + gpr_backoff backoff; + gpr_backoff_init(&backoff, initial_timeout, 1.0 /* multiplier */, jitter, + 100 /* min timeout */, 1000 /* max timeout */); + + backoff.rng_state = 0; // force consistent PRNG + + gpr_timespec now = gpr_time_0(GPR_TIMESPAN); + gpr_timespec next = gpr_backoff_begin(&backoff, now); + GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 500); + + int64_t expected_next_lower_bound = + (int64_t)((double)initial_timeout * (1 - jitter)); + int64_t expected_next_upper_bound = + (int64_t)((double)initial_timeout * (1 + jitter)); + + for (int i = 0; i < 10000; i++) { + next = gpr_backoff_step(&backoff, now); + + // next-now must be within (jitter*100)% of the previous timeout. + const int64_t timeout_millis = gpr_time_to_millis(gpr_time_sub(next, now)); + GPR_ASSERT(timeout_millis >= expected_next_lower_bound); + GPR_ASSERT(timeout_millis <= expected_next_upper_bound); + + expected_next_lower_bound = + (int64_t)((double)timeout_millis * (1 - jitter)); + expected_next_upper_bound = + (int64_t)((double)timeout_millis * (1 + jitter)); + now = next; + } } int main(int argc, char **argv) { @@ -101,7 +150,9 @@ int main(int argc, char **argv) { gpr_time_init(); test_constant_backoff(); + test_min_connect(); test_no_jitter_backoff(); + test_jitter_backoff(); return 0; } diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c index f9f4675454..93a4794222 100644 --- a/test/core/surface/concurrent_connectivity_test.c +++ b/test/core/surface/concurrent_connectivity_test.c @@ -105,8 +105,8 @@ void server_thread(void *vargs) { static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor) { + gpr_free(acceptor); struct server_thread_args *args = (struct server_thread_args *)vargs; - (void)acceptor; grpc_endpoint_shutdown(exec_ctx, tcp); grpc_endpoint_destroy(exec_ctx, tcp); GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL)); diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index d4cfa25d44..df6b733493 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -42,6 +42,7 @@ #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/gpr_slice.h> #include <grpc/impl/codegen/gpr_types.h> #include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/port_platform.h> diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c index 6310b6f00b..6c178abdad 100644 --- a/test/core/surface/server_chttp2_test.c +++ b/test/core/surface/server_chttp2_test.c @@ -44,8 +44,11 @@ #include "test/core/util/test_config.h" void test_unparsable_target(void) { - int port = grpc_server_add_insecure_http2_port(NULL, "["); + grpc_channel_args args = {0, NULL}; + grpc_server *server = grpc_server_create(&args, NULL); + int port = grpc_server_add_insecure_http2_port(server, "["); GPR_ASSERT(port == 0); + grpc_server_destroy(server); } void test_add_same_port_twice() { diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c index 6509cc5b68..7bf83a74a1 100644 --- a/test/core/util/reconnect_server.c +++ b/test/core/util/reconnect_server.c @@ -73,6 +73,7 @@ static void pretty_print_backoffs(reconnect_server *server) { static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor) { + gpr_free(acceptor); char *peer; char *last_colon; reconnect_server *server = (reconnect_server *)arg; diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc index 8cee1403dc..b1f9216055 100644 --- a/test/cpp/end2end/server_crash_test.cc +++ b/test/cpp/end2end/server_crash_test.cc @@ -138,7 +138,7 @@ TEST_F(CrashTest, ResponseStream) { auto server = CreateServerAndClient("response"); gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(5, GPR_TIMESPAN))); + gpr_time_from_seconds(60, GPR_TIMESPAN))); KillClient(); server->Shutdown(); GPR_ASSERT(HadOneResponseStream()); @@ -148,7 +148,7 @@ TEST_F(CrashTest, BidiStream) { auto server = CreateServerAndClient("bidi"); gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(5, GPR_TIMESPAN))); + gpr_time_from_seconds(60, GPR_TIMESPAN))); KillClient(); server->Shutdown(); GPR_ASSERT(HadOneBidiStream()); diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc index 57a53ca11e..fcdcaba6a2 100644 --- a/test/cpp/grpclb/grpclb_test.cc +++ b/test/cpp/grpclb/grpclb_test.cc @@ -523,9 +523,8 @@ static void perform_request(client_fixture *cf) { CQ_EXPECT_COMPLETION(cqv, tag(2), 1); cq_verify(cqv); + gpr_log(GPR_INFO, "Client after sending msg %d / 4", i + 1); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, PAYLOAD)); - GPR_ASSERT(grpc_channel_check_connectivity_state( - cf->client, 0 /* try to connect */) == GRPC_CHANNEL_READY); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(response_payload_recv); @@ -546,16 +545,17 @@ static void perform_request(client_fixture *cf) { cq_verify(cqv); peer = grpc_call_get_peer(c); gpr_log(GPR_INFO, "Client DONE WITH SERVER %s ", peer); - gpr_free(peer); grpc_call_destroy(c); - cq_verify_empty_timeout(cqv, 1); + cq_verify_empty_timeout(cqv, 1 /* seconds */); cq_verifier_destroy(cqv); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); gpr_free(details); + gpr_log(GPR_INFO, "Client call (peer %s) DESTROYED.", peer); + gpr_free(peer); } static void setup_client(const char *server_hostport, client_fixture *cf) { @@ -699,39 +699,42 @@ static test_fixture test_update(int lb_server_update_delay_ms) { TEST(GrpclbTest, Updates) { grpc::test_fixture tf_result; - // Clients take a bit over one second to complete a call (the last part of the + // Clients take at least one second to complete a call (the last part of the // call sleeps for 1 second while verifying the client's completion queue is - // empty). Therefore: + // empty), more if the system is under load. Therefore: // // If the LB server waits 800ms before sending an update, it will arrive - // before the first client request is done, skipping the second server from - // batch 1 altogether: the 2nd client request will go to the 1st server of - // batch 2 (ie, the third one out of the four total servers). + // before the first client request finishes, skipping the second server from + // batch 1. All subsequent picks will come from the second half of the + // backends, those coming in the LB update. tf_result = grpc::test_update(800); GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1); GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 0); - GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced == 2); - GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 1); + GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced + + tf_result.lb_backends[3].num_calls_serviced > + 0); + int num_serviced_calls = 0; + for (int i = 0; i < 4; i++) { + num_serviced_calls += tf_result.lb_backends[i].num_calls_serviced; + } + GPR_ASSERT(num_serviced_calls == 4); - // If the LB server waits 1500ms, the update arrives after having picked the - // 2nd server from batch 1 but before the next pick for the first server of - // batch 2. All server are used. - tf_result = grpc::test_update(1500); - GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced == 1); - GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1); - GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced == 1); - GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 1); - - // If the LB server waits > 2000ms, the update arrives after the first two - // request are done and the third pick is performed, which returns, in RR - // fashion, the 1st server of the 1st update. Therefore, the second server of - // batch 1 is hit at least one, whereas the first server of batch 2 is never - // hit. + // If the LB server waits 2500ms, the update arrives after two calls and three + // picks. The third pick will be the 1st server of the 1st update (RR policy + // going around). The fourth and final pick will come from the second LB + // update. In any case, the total number of serviced calls must again be equal + // to four across all the backends. tf_result = grpc::test_update(2500); GPR_ASSERT(tf_result.lb_backends[0].num_calls_serviced >= 1); - GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced > 0); - GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced > 0); - GPR_ASSERT(tf_result.lb_backends[3].num_calls_serviced == 0); + GPR_ASSERT(tf_result.lb_backends[1].num_calls_serviced == 1); + GPR_ASSERT(tf_result.lb_backends[2].num_calls_serviced + + tf_result.lb_backends[3].num_calls_serviced > + 0); + num_serviced_calls = 0; + for (int i = 0; i < 4; i++) { + num_serviced_calls += tf_result.lb_backends[i].num_calls_serviced; + } + GPR_ASSERT(num_serviced_calls == 4); } TEST(GrpclbTest, InvalidAddressInServerlist) {} diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc index 8b50ae8c05..67456ce18b 100644 --- a/test/cpp/interop/interop_server.cc +++ b/test/cpp/interop/interop_server.cc @@ -344,7 +344,7 @@ void grpc::testing::interop::RunServer( } std::unique_ptr<Server> server(builder.BuildAndStart()); gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str()); - while (!g_got_sigint) { + while (!gpr_atm_no_barrier_load(&g_got_sigint)) { sleep(5); } } diff --git a/test/cpp/interop/interop_server_bootstrap.cc b/test/cpp/interop/interop_server_bootstrap.cc index 424f7ca7f0..99518c6943 100644 --- a/test/cpp/interop/interop_server_bootstrap.cc +++ b/test/cpp/interop/interop_server_bootstrap.cc @@ -37,10 +37,10 @@ #include "test/cpp/interop/server_helper.h" #include "test/cpp/util/test_config.h" -bool grpc::testing::interop::g_got_sigint = false; +gpr_atm grpc::testing::interop::g_got_sigint; static void sigint_handler(int x) { - grpc::testing::interop::g_got_sigint = true; + gpr_atm_no_barrier_store(&grpc::testing::interop::g_got_sigint, true); } int main(int argc, char** argv) { diff --git a/test/cpp/interop/interop_test.cc b/test/cpp/interop/interop_test.cc index c066598d36..d4004740a4 100644 --- a/test/cpp/interop/interop_test.cc +++ b/test/cpp/interop/interop_test.cc @@ -126,7 +126,7 @@ int main(int argc, char** argv) { return 1; } /* wait a little */ - sleep(2); + sleep(10); /* start the clients */ ret = test_client(root, "127.0.0.1", port); if (ret != 0) return ret; diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h index fc4ea8b3e8..99539adee5 100644 --- a/test/cpp/interop/server_helper.h +++ b/test/cpp/interop/server_helper.h @@ -36,9 +36,11 @@ #include <memory> +#include <grpc/compression.h> +#include <grpc/impl/codegen/atm.h> + #include <grpc++/security/server_credentials.h> #include <grpc++/server_context.h> -#include <grpc/compression.h> namespace grpc { namespace testing { @@ -62,7 +64,7 @@ class InteropServerContextInspector { namespace interop { -extern bool g_got_sigint; +extern gpr_atm g_got_sigint; void RunServer(std::shared_ptr<ServerCredentials> creds); } // namespace interop diff --git a/test/cpp/microbenchmarks/bm_fullstack.cc b/test/cpp/microbenchmarks/bm_fullstack.cc index 559e66cdd7..6c0bf80488 100644 --- a/test/cpp/microbenchmarks/bm_fullstack.cc +++ b/test/cpp/microbenchmarks/bm_fullstack.cc @@ -59,7 +59,7 @@ extern "C" { } #include "src/cpp/client/create_channel_internal.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" -#include "third_party/google_benchmark/include/benchmark/benchmark.h" +#include "third_party/benchmark/include/benchmark/benchmark.h" namespace grpc { namespace testing { @@ -128,7 +128,16 @@ class TCP : public FullstackFixture { class UDS : public FullstackFixture { public: - UDS(Service* service) : FullstackFixture(service, "unix:bm_fullstack") {} + UDS(Service* service) : FullstackFixture(service, MakeAddress()) {} + + private: + static grpc::string MakeAddress() { + int port = grpc_pick_unused_port_or_die(); // just for a unique id - not a + // real port + std::stringstream addr; + addr << "unix:/tmp/bm_fullstack." << port; + return addr.str(); + } }; class EndpointPairFixture { @@ -223,7 +232,7 @@ class InProcessCHTTP2 : public EndpointPairFixture { * CONTEXT MUTATORS */ -static const int kPregenerateKeyCount = 10000000; +static const int kPregenerateKeyCount = 100000; template <class F> auto MakeVector(size_t length, F f) -> std::vector<decltype(f())> { diff --git a/test/cpp/microbenchmarks/noop-benchmark.cc b/test/cpp/microbenchmarks/noop-benchmark.cc index 6b06c69c6e..99fa6d5f6e 100644 --- a/test/cpp/microbenchmarks/noop-benchmark.cc +++ b/test/cpp/microbenchmarks/noop-benchmark.cc @@ -31,10 +31,10 @@ * */ -/* This benchmark exists to ensure that the google_benchmark integration is +/* This benchmark exists to ensure that the benchmark integration is * working */ -#include "third_party/google_benchmark/include/benchmark/benchmark.h" +#include "third_party/benchmark/include/benchmark/benchmark.h" static void BM_NoOp(benchmark::State& state) { while (state.KeepRunning()) { diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index ea0b38e8ad..22b2cd080d 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -101,7 +101,7 @@ static std::unordered_map<string, std::deque<int>> get_hosts_and_cores( static deque<string> get_workers(const string& name) { char* env = gpr_getenv(name.c_str()); - if (!env) return deque<string>(); + if (!env || strlen(env) == 0) return deque<string>(); deque<string> out; char* p = env; diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py index 4aa58d2737..188d6196e5 100755 --- a/test/cpp/qps/gen_build_yaml.py +++ b/test/cpp/qps/gen_build_yaml.py @@ -91,7 +91,7 @@ print yaml.dump({ 'boringssl': True, 'defaults': 'boringssl', 'cpu_cost': guess_cpu(scenario_json, False), - 'exclude_configs': ['tsan'], + 'exclude_configs': ['tsan', 'asan'], 'timeout_seconds': 6*60 } for scenario_json in scenario_config.CXXLanguage().scenarios() @@ -99,7 +99,7 @@ print yaml.dump({ ] + [ { 'name': 'json_run_localhost', - 'shortname': 'json_run_localhost:%s' % scenario_json['name'], + 'shortname': 'json_run_localhost:%s_low_thread_count' % scenario_json['name'], 'args': ['--scenarios_json', _scenario_json_string(scenario_json, True)], 'ci_platforms': ['linux'], 'platforms': ['linux'], @@ -108,7 +108,7 @@ print yaml.dump({ 'boringssl': True, 'defaults': 'boringssl', 'cpu_cost': guess_cpu(scenario_json, True), - 'exclude_configs': sorted(c for c in configs_from_yaml if c != 'tsan'), + 'exclude_configs': sorted(c for c in configs_from_yaml if c not in ('tsan', 'asan')), 'timeout_seconds': 6*60 } for scenario_json in scenario_config.CXXLanguage().scenarios() diff --git a/test/cpp/qps/json_run_localhost.cc b/test/cpp/qps/json_run_localhost.cc index 74e40fbf1a..b7b2553f12 100644 --- a/test/cpp/qps/json_run_localhost.cc +++ b/test/cpp/qps/json_run_localhost.cc @@ -31,7 +31,11 @@ * */ +#include <signal.h> +#include <string.h> + #include <memory> +#include <mutex> #include <sstream> #include <string> @@ -43,6 +47,11 @@ using grpc::SubProcess; +constexpr auto kNumWorkers = 2; + +static SubProcess* g_driver; +static SubProcess* g_workers[kNumWorkers]; + template <class T> std::string as_string(const T& val) { std::ostringstream out; @@ -50,9 +59,38 @@ std::string as_string(const T& val) { return out.str(); } +static void sighandler(int sig) { + const int errno_saved = errno; + if (g_driver != NULL) g_driver->Interrupt(); + for (int i = 0; i < kNumWorkers; ++i) { + if (g_workers[i]) g_workers[i]->Interrupt(); + } + errno = errno_saved; +} + +static void register_sighandler() { + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = sighandler; + + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); +} + +static void LogStatus(int status, const char* label) { + if (WIFEXITED(status)) { + gpr_log(GPR_INFO, "%s: subprocess exited with status %d", label, + WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + gpr_log(GPR_INFO, "%s: subprocess terminated with signal %d", label, + WTERMSIG(status)); + } else { + gpr_log(GPR_INFO, "%s: unknown subprocess status: %d", label, status); + } +} + int main(int argc, char** argv) { - typedef std::unique_ptr<SubProcess> SubProcessPtr; - std::vector<SubProcessPtr> jobs; + register_sighandler(); std::string my_bin = argv[0]; std::string bin_dir = my_bin.substr(0, my_bin.rfind('/')); @@ -60,11 +98,11 @@ int main(int argc, char** argv) { std::ostringstream env; bool first = true; - for (int i = 0; i < 2; i++) { - auto port = grpc_pick_unused_port_or_die(); + for (int i = 0; i < kNumWorkers; i++) { + const auto port = grpc_pick_unused_port_or_die(); std::vector<std::string> args = {bin_dir + "/qps_worker", "-driver_port", as_string(port)}; - jobs.emplace_back(new SubProcess(args)); + g_workers[i] = new SubProcess(args); if (!first) env << ","; env << "localhost:" << port; first = false; @@ -75,12 +113,27 @@ int main(int argc, char** argv) { for (int i = 1; i < argc; i++) { args.push_back(argv[i]); } - GPR_ASSERT(SubProcess(args).Join() == 0); - for (auto it = jobs.begin(); it != jobs.end(); ++it) { - (*it)->Interrupt(); + g_driver = new SubProcess(args); + const int driver_join_status = g_driver->Join(); + if (driver_join_status != 0) { + LogStatus(driver_join_status, "driver"); } - for (auto it = jobs.begin(); it != jobs.end(); ++it) { - (*it)->Join(); + for (int i = 0; i < kNumWorkers; ++i) { + if (g_workers[i]) g_workers[i]->Interrupt(); } + + for (int i = 0; i < kNumWorkers; ++i) { + if (g_workers[i]) { + const int worker_status = g_workers[i]->Join(); + if (worker_status != 0) { + LogStatus(worker_status, "worker"); + } + } + } + + delete g_driver; + g_driver = NULL; + for (int i = 0; i < kNumWorkers; ++i) delete g_workers[i]; + GPR_ASSERT(driver_join_status == 0); } diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc index 03c33abe9f..a3da5682dc 100644 --- a/test/cpp/util/grpc_tool.cc +++ b/test/cpp/util/grpc_tool.cc @@ -414,6 +414,7 @@ bool GrpcTool::CallMethod(int argc, const char** argv, grpc::string request_text; grpc::string server_address(argv[0]); grpc::string method_name(argv[1]); + grpc::string formatted_method_name; std::unique_ptr<grpc::testing::ProtoFileParser> parser; grpc::string serialized_request_proto; @@ -450,7 +451,9 @@ bool GrpcTool::CallMethod(int argc, const char** argv, if (FLAGS_binary_input) { serialized_request_proto = request_text; + formatted_method_name = method_name; } else { + formatted_method_name = parser->GetFormattedMethodName(method_name); serialized_request_proto = parser->GetSerializedProtoFromMethod( method_name, request_text, true /* is_request */); if (parser->HasError()) { @@ -466,9 +469,9 @@ bool GrpcTool::CallMethod(int argc, const char** argv, ParseMetadataFlag(&client_metadata); PrintMetadata(client_metadata, "Sending client initial metadata:"); grpc::Status status = grpc::testing::CliCall::Call( - channel, parser->GetFormatedMethodName(method_name), - serialized_request_proto, &serialized_response_proto, client_metadata, - &server_initial_metadata, &server_trailing_metadata); + channel, formatted_method_name, serialized_request_proto, + &serialized_response_proto, client_metadata, &server_initial_metadata, + &server_trailing_metadata); PrintMetadata(server_initial_metadata, "Received initial metadata from server:"); PrintMetadata(server_trailing_metadata, diff --git a/test/cpp/util/proto_file_parser.cc b/test/cpp/util/proto_file_parser.cc index 3e524227e5..bc8a6083f4 100644 --- a/test/cpp/util/proto_file_parser.cc +++ b/test/cpp/util/proto_file_parser.cc @@ -172,19 +172,19 @@ grpc::string ProtoFileParser::GetFullMethodName(const grpc::string& method) { return method_descriptor->full_name(); } -grpc::string ProtoFileParser::GetFormatedMethodName( +grpc::string ProtoFileParser::GetFormattedMethodName( const grpc::string& method) { has_error_ = false; - grpc::string formated_method_name = GetFullMethodName(method); + grpc::string formatted_method_name = GetFullMethodName(method); if (has_error_) { return ""; } - size_t last_dot = formated_method_name.find_last_of('.'); + size_t last_dot = formatted_method_name.find_last_of('.'); if (last_dot != grpc::string::npos) { - formated_method_name[last_dot] = '/'; + formatted_method_name[last_dot] = '/'; } - formated_method_name.insert(formated_method_name.begin(), '/'); - return formated_method_name; + formatted_method_name.insert(formatted_method_name.begin(), '/'); + return formatted_method_name; } grpc::string ProtoFileParser::GetMessageTypeFromMethod( diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h index eda3991e72..c1070a37b5 100644 --- a/test/cpp/util/proto_file_parser.h +++ b/test/cpp/util/proto_file_parser.h @@ -64,9 +64,9 @@ class ProtoFileParser { // descriptor database queries. grpc::string GetFullMethodName(const grpc::string& method); - // Formated method name is in the form of /Service/Method, it's good to be + // Formatted method name is in the form of /Service/Method, it's good to be // used as the argument of Stub::Call() - grpc::string GetFormatedMethodName(const grpc::string& method); + grpc::string GetFormattedMethodName(const grpc::string& method); grpc::string GetSerializedProtoFromMethod( const grpc::string& method, const grpc::string& text_format_proto, diff --git a/third_party/google_benchmark b/third_party/benchmark -Subproject 44c25c892a6229b20db7cd9dc05584ea865896d +Subproject 44c25c892a6229b20db7cd9dc05584ea865896d diff --git a/tools/README.md b/tools/README.md index d142d4aee2..d051846c33 100644 --- a/tools/README.md +++ b/tools/README.md @@ -11,6 +11,8 @@ gce: Scripts to help setup testing infrastructure on GCE. gcp: Helper scripts for interacting with various services on GCP (like Google container engine, BigQuery etc) +internal_ci: Support for running tests on an internal CI platform. + jenkins: Support for running tests on Jenkins. run_tests: Scripts to run gRPC tests in parallel. diff --git a/tools/buildgen/generate_build_additions.sh b/tools/buildgen/generate_build_additions.sh index 1ea47042f4..53c30c7609 100644 --- a/tools/buildgen/generate_build_additions.sh +++ b/tools/buildgen/generate_build_additions.sh @@ -30,7 +30,7 @@ gen_build_yaml_dirs=" \ src/boringssl \ - src/google_benchmark \ + src/benchmark \ src/proto \ src/zlib \ test/core/bad_client \ diff --git a/tools/dockerfile/push_testing_images.sh b/tools/dockerfile/push_testing_images.sh new file mode 100755 index 0000000000..f1ee8d59dd --- /dev/null +++ b/tools/dockerfile/push_testing_images.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# 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. +# +# Builds selected testing docker images and pushes them to dockerhub. +# Useful for testing environments where it's impractical (or impossible) +# to rely on docker images being cached locally after they've been built +# for the first time (which might be costly especially for some images). +# NOTE: gRPC docker images intended to be used by end users are NOT +# pushed using this script (they're built automatically by dockerhub). +# This script is only for "internal" images we use when testing gRPC. + +set -ex + +cd $(dirname $0)/../.. +git_root=$(pwd) +cd - + +DOCKERHUB_ORGANIZATION=grpctesting + +for DOCKERFILE_DIR in tools/dockerfile/test/fuzzer +do + # Generate image name based on Dockerfile checksum. That works well as long + # as can count on dockerfiles being written in a way that changing the logical + # contents of the docker image always changes the SHA (e.g. using "ADD file" + # cmd in the dockerfile in not ok as contents of the added file will not be + # reflected in the SHA). + DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) + + # skip the image if it already exists in the repo + curl --silent -f -lSL https://registry.hub.docker.com/v2/repositories/${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}/tags/latest > /dev/null \ + && continue + + docker build -t ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME} ${DOCKERFILE_DIR} + + # "docker login" needs to be run in advance + docker push ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME} +done diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index f4b4831a64..6b19ac845b 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -93,9 +93,11 @@ RUN pip install simplejson mako #====================================== # More sanity test dependencies (bazel) RUN apt-get install -y openjdk-8-jdk -# TOOD(jtattermusch): pin the bazel version -RUN git clone https://github.com/bazelbuild/bazel.git /bazel -RUN cd /bazel && ./compile.sh +# Check out Bazel version 0.4.1 since this version allows running +# ./compile.sh without a local protoc dependency +# TODO(mattkwong): install dependencies to support latest Bazel version if newer +# version is needed +RUN git clone https://github.com/bazelbuild/bazel.git /bazel && cd /bazel && git checkout tags/0.4.1 && ./compile.sh RUN ln -s /bazel/output/bazel /bin/ #=================== diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index ff3a0e381d..9e3fc62ebc 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -840,6 +840,7 @@ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 04e8f4e7f2..074ba504fa 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -840,6 +840,7 @@ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 1e748ba4a8..b83e710a2b 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -779,6 +779,7 @@ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -818,6 +819,7 @@ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index a629bdc542..533999b765 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -779,6 +779,7 @@ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -919,9 +920,9 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.h \ src/core/lib/security/credentials/plugin/plugin_credentials.h \ src/core/lib/security/credentials/ssl/ssl_credentials.h \ src/core/lib/security/transport/auth_filters.h \ -src/core/lib/security/transport/handshake.h \ src/core/lib/security/transport/secure_endpoint.h \ src/core/lib/security/transport/security_connector.h \ +src/core/lib/security/transport/security_handshaker.h \ src/core/lib/security/transport/tsi_error.h \ src/core/lib/security/util/b64.h \ src/core/lib/security/util/json_util.h \ @@ -930,6 +931,7 @@ src/core/lib/tsi/ssl_transport_security.h \ src/core/lib/tsi/ssl_types.h \ src/core/lib/tsi/transport_security.h \ src/core/lib/tsi/transport_security_interface.h \ +src/core/ext/transport/chttp2/server/chttp2_server.h \ src/core/ext/client_channel/client_channel.h \ src/core/ext/client_channel/client_channel_factory.h \ src/core/ext/client_channel/connector.h \ @@ -945,6 +947,7 @@ src/core/ext/client_channel/resolver_registry.h \ src/core/ext/client_channel/subchannel.h \ src/core/ext/client_channel/subchannel_index.h \ src/core/ext/client_channel/uri_parser.h \ +src/core/ext/transport/chttp2/client/chttp2_connector.h \ src/core/ext/lb_policy/grpclb/grpclb.h \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \ @@ -1117,9 +1120,9 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.c \ src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/transport/client_auth_filter.c \ -src/core/lib/security/transport/handshake.c \ src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/security_connector.c \ +src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/server_auth_filter.c \ src/core/lib/security/transport/tsi_error.c \ src/core/lib/security/util/b64.c \ @@ -1128,6 +1131,7 @@ src/core/lib/surface/init_secure.c \ src/core/lib/tsi/fake_transport_security.c \ src/core/lib/tsi/ssl_transport_security.c \ src/core/lib/tsi/transport_security.c \ +src/core/ext/transport/chttp2/server/chttp2_server.c \ src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \ src/core/ext/client_channel/channel_connectivity.c \ src/core/ext/client_channel/client_channel.c \ @@ -1147,6 +1151,7 @@ src/core/ext/client_channel/resolver_registry.c \ src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/uri_parser.c \ +src/core/ext/transport/chttp2/client/chttp2_connector.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ @@ -1208,6 +1213,7 @@ 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_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/gce/linux_performance_worker_init.sh b/tools/gce/linux_performance_worker_init.sh index 523749ee81..ab29e015e0 100755 --- a/tools/gce/linux_performance_worker_init.sh +++ b/tools/gce/linux_performance_worker_init.sh @@ -150,3 +150,19 @@ sudo tar -C /usr/local -xzf go$GO_VERSION.$OS-$ARCH.tar.gz # Put go on the PATH, keep the usual installation dir sudo ln -s /usr/local/go/bin/go /usr/bin/go rm go$GO_VERSION.$OS-$ARCH.tar.gz + +# Install perf, to profile benchmarks. (need to get the right linux-tools-<> for kernel version) +sudo apt-get install -y linux-tools-common linux-tools-generic linux-tools-`uname -r` +# see http://unix.stackexchange.com/questions/14227/do-i-need-root-admin-permissions-to-run-userspace-perf-tool-perf-events-ar +echo 0 | sudo tee /proc/sys/kernel/perf_event_paranoid +# see http://stackoverflow.com/questions/21284906/perf-couldnt-record-kernel-reference-relocation-symbol +echo 0 | sudo tee /proc/sys/kernel/kptr_restrict + +# qps workers under perf appear to need a lot of mmap pages under certain scenarios and perf args in +# order to not lose perf events or time out +echo 4096 | sudo tee /proc/sys/kernel/perf_event_mlock_kb + +# Fetch scripts to generate flame graphs from perf data collected +# on benchmarks +git clone -v https://github.com/brendangregg/FlameGraph ~/FlameGraph + diff --git a/tools/internal_ci/README.md b/tools/internal_ci/README.md new file mode 100644 index 0000000000..8bed6ca782 --- /dev/null +++ b/tools/internal_ci/README.md @@ -0,0 +1,6 @@ +#Internal continuous integration + +gRPC's externally facing testing is managed by Jenkins CI (see `tools/jenkins` +directory). Nevertheless, some of the tests are better suited for being run +on internal infrastructure and using an internal CI system. Configuration for +such tests is under this directory. diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.cfg b/tools/internal_ci/linux/grpc_fuzzer_client.cfg new file mode 100644 index 0000000000..b1bce02282 --- /dev/null +++ b/tools/internal_ci/linux/grpc_fuzzer_client.cfg @@ -0,0 +1,40 @@ +#!/bin/bash +# 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. + +# Config file for the internal CI (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_client.sh" +timeout_mins: 1440 # 24 hours is the maximum allowed value +action { + define_artifacts { + regex: "git/grpc/fuzzer_output/**" + } +} diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.sh b/tools/internal_ci/linux/grpc_fuzzer_client.sh new file mode 100755 index 0000000000..f9ff13d303 --- /dev/null +++ b/tools/internal_ci/linux/grpc_fuzzer_client.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# 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. + +set -ex + +# change to grpc repo root +cd $(dirname $0)/../../.. + +git submodule update --init + +# download fuzzer docker image from dockerhub +export DOCKERHUB_ORGANIZATION=grpctesting +# runtime 23 * 60 mins +config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh client_fuzzer diff --git a/tools/internal_ci/linux/grpc_master.cfg b/tools/internal_ci/linux/grpc_master.cfg new file mode 100644 index 0000000000..8ce2ef11a2 --- /dev/null +++ b/tools/internal_ci/linux/grpc_master.cfg @@ -0,0 +1,40 @@ +#!/bin/bash +# 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. + +# Config file for the internal CI (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc/tools/internal_ci/linux/grpc_master.sh" +timeout_mins: 60 +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/tools/internal_ci/linux/grpc_master.sh b/tools/internal_ci/linux/grpc_master.sh new file mode 100755 index 0000000000..ea77d11305 --- /dev/null +++ b/tools/internal_ci/linux/grpc_master.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# 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. + +set -ex + +# change to grpc repo root +cd $(dirname $0)/../../.. + +# TODO(jtattermusch): get rid of the system inspection eventually +nproc || true +lsb_release -dc || true +gcc --version || true +clang --version || true +docker --version || true + +git submodule update --init + +tools/run_tests/run_tests.py -l c -t -x sponge_log.xml || FAILED="true" + +# kill port_server.py to prevent the build from hanging +ps aux | grep port_server\\.py | awk '{print $2}' | xargs kill -9 + +if [ "$FAILED" != "" ] +then + exit 1 +fi diff --git a/tools/jenkins/README.md b/tools/jenkins/README.md index 8e06b68466..02f63f0f4a 100644 --- a/tools/jenkins/README.md +++ b/tools/jenkins/README.md @@ -1 +1,6 @@ +# Jenkins CI scripts + Scripts invoked by Jenkins (our CI platform) to run gRPC test suites. +We run a comprehensive set of tests (unit, integration, interop, +performance, portability..) on each pull request and also periodically on +`master` and release branches. diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh index fb884ad166..7cac394960 100755 --- a/tools/run_tests/build_python.sh +++ b/tools/run_tests/build_python.sh @@ -171,8 +171,7 @@ pip_install_dir() { } $VENV_PYTHON -m pip install --upgrade pip -# TODO(https://github.com/pypa/setuptools/issues/709) get the latest setuptools -$VENV_PYTHON -m pip install setuptools==25.1.1 +$VENV_PYTHON -m pip install setuptools $VENV_PYTHON -m pip install cython pip_install_dir $ROOT $VENV_PYTHON $ROOT/tools/distrib/python/make_grpcio_tools.py diff --git a/tools/run_tests/dockerize/build_and_run_docker.sh b/tools/run_tests/dockerize/build_and_run_docker.sh index 1ef34b2f96..f52f16ebd6 100755 --- a/tools/run_tests/dockerize/build_and_run_docker.sh +++ b/tools/run_tests/dockerize/build_and_run_docker.sh @@ -41,13 +41,20 @@ cd - # DOCKERFILE_DIR - Directory in which Dockerfile file is located. # DOCKER_RUN_SCRIPT - Script to run under docker (relative to grpc repo root) # OUTPUT_DIR - Directory that will be copied from inside docker after finishing. +# DOCKERHUB_ORGANIZATION - If set, pull a prebuilt image from given dockerhub org. # $@ - Extra args to pass to docker run # Use image name based on Dockerfile location checksum DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ ) -# Make sure docker image has been built. Should be instantaneous if so. -docker build -t $DOCKER_IMAGE_NAME $DOCKERFILE_DIR +if [ "$DOCKERHUB_ORGANIZATION" != "" ] +then + DOCKER_IMAGE_NAME=$DOCKERHUB_ORGANIZATION/$DOCKER_IMAGE_NAME + docker pull $DOCKER_IMAGE_NAME +else + # Make sure docker image has been built. Should be instantaneous if so. + docker build -t $DOCKER_IMAGE_NAME $DOCKERFILE_DIR +fi # Choose random name for docker container CONTAINER_NAME="build_and_run_docker_$(uuidgen)" diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py index b84eb3b5d7..1b5d6d66a0 100755 --- a/tools/run_tests/jobset.py +++ b/tools/run_tests/jobset.py @@ -49,12 +49,22 @@ measure_cpu_costs = False _DEFAULT_MAX_JOBS = 16 * multiprocessing.cpu_count() _MAX_RESULT_SIZE = 8192 + +# NOTE: If you change this, please make sure to test reviewing the +# github PR with http://reviewable.io, which is known to add UTF-8 +# characters to the PR description, which leak into the environment here +# and cause failures. +def strip_non_ascii_chars(s): + return ''.join(c for c in s if ord(c) < 128) + + def sanitized_environment(env): sanitized = {} for key, value in env.items(): - sanitized[str(key).encode()] = str(value).encode() + sanitized[strip_non_ascii_chars(key)] = strip_non_ascii_chars(value) return sanitized + def platform_string(): if platform.system() == 'Windows': return 'windows' @@ -129,16 +139,16 @@ def message(tag, msg, explanatory_text=None, do_newline=False): if explanatory_text: print(explanatory_text) print('%s: %s' % (tag, msg)) - return - sys.stdout.write('%s%s%s\x1b[%d;%dm%s\x1b[0m: %s%s' % ( - _BEGINNING_OF_LINE, - _CLEAR_LINE, - '\n%s' % explanatory_text if explanatory_text is not None else '', - _COLORS[_TAG_COLOR[tag]][1], - _COLORS[_TAG_COLOR[tag]][0], - tag, - msg, - '\n' if do_newline or explanatory_text is not None else '')) + else: + sys.stdout.write('%s%s%s\x1b[%d;%dm%s\x1b[0m: %s%s' % ( + _BEGINNING_OF_LINE, + _CLEAR_LINE, + '\n%s' % explanatory_text if explanatory_text is not None else '', + _COLORS[_TAG_COLOR[tag]][1], + _COLORS[_TAG_COLOR[tag]][0], + tag, + msg, + '\n' if do_newline or explanatory_text is not None else '')) sys.stdout.flush() except: pass @@ -396,7 +406,7 @@ class Jobset(object): self.resultset[job.GetSpec().shortname].append(job.result) self._running.remove(job) if dead: return - if (not self._travis): + if not self._travis and platform_string() != 'windows': rstr = '' if self._remaining is None else '%d queued, ' % self._remaining if self._remaining is not None and self._completed > 0: now = time.time() diff --git a/tools/run_tests/package_targets.py b/tools/run_tests/package_targets.py index 2802957ff1..673affeac0 100644 --- a/tools/run_tests/package_targets.py +++ b/tools/run_tests/package_targets.py @@ -71,50 +71,28 @@ def create_jobspec(name, cmdline, environ=None, cwd=None, shell=False, class CSharpPackage: """Builds C# nuget packages.""" - def __init__(self, linux=False, use_dotnet_cli=True): + def __init__(self, linux=False): self.linux = linux - self.use_dotnet_cli = use_dotnet_cli - self.labels = ['package', 'csharp'] - - if use_dotnet_cli: - if linux: - self.name = 'csharp_package_dotnetcli_linux' - self.labels += ['linux'] - else: - self.name = 'csharp_package_dotnetcli_windows' - self.labels += ['windows'] + if linux: + self.name = 'csharp_package_dotnetcli_linux' + self.labels += ['linux'] else: - # official packages built with dotnet cli rather than nuget pack - self.name = 'csharp_package_obsolete' - self.labels += ['obsolete'] - + self.name = 'csharp_package_dotnetcli_windows' + self.labels += ['windows'] def pre_build_jobspecs(self): - # The older, obsolete build uses nuget only instead of dotnet cli - if 'obsolete' in self.labels: - return [create_jobspec('prebuild_%s' % self.name, - ['tools\\run_tests\\pre_build_csharp.bat'], - shell=True, - flake_retries=5, - timeout_retries=2)] - else: - return [] + return [] def build_jobspec(self): - if self.use_dotnet_cli and self.linux: + if self.linux: return create_docker_jobspec( self.name, 'tools/dockerfile/test/csharp_coreclr_x64', 'src/csharp/build_packages_dotnetcli.sh') - elif self.use_dotnet_cli: - return create_jobspec(self.name, - ['build_packages_dotnetcli.bat'], - cwd='src\\csharp', - shell=True) else: return create_jobspec(self.name, - ['build_packages.bat'], + ['build_packages_dotnetcli.bat'], cwd='src\\csharp', shell=True) @@ -194,7 +172,6 @@ def targets(): """Gets list of supported targets""" return [CSharpPackage(), CSharpPackage(linux=True), - CSharpPackage(use_dotnet_cli=False), NodePackage(), RubyPackage(), PythonPackage(), diff --git a/tools/run_tests/performance/process_local_perf_flamegraphs.sh b/tools/run_tests/performance/process_local_perf_flamegraphs.sh new file mode 100755 index 0000000000..d15610f137 --- /dev/null +++ b/tools/run_tests/performance/process_local_perf_flamegraphs.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +mkdir -p $OUTPUT_DIR + +PERF_DATA_FILE=${PERF_BASE_NAME}-perf.data +PERF_SCRIPT_OUTPUT=${PERF_BASE_NAME}-out.perf + +# Generate Flame graphs +echo "running perf script on $PERF_DATA_FILE" +perf script -i $PERF_DATA_FILE > $PERF_SCRIPT_OUTPUT + +~/FlameGraph/stackcollapse-perf.pl $PERF_SCRIPT_OUTPUT | ~/FlameGraph/flamegraph.pl > ${OUTPUT_DIR}/${OUTPUT_FILENAME}.svg diff --git a/tools/run_tests/performance/process_remote_perf_flamegraphs.sh b/tools/run_tests/performance/process_remote_perf_flamegraphs.sh new file mode 100755 index 0000000000..cc075354cc --- /dev/null +++ b/tools/run_tests/performance/process_remote_perf_flamegraphs.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +mkdir -p $OUTPUT_DIR + +PERF_DATA_FILE=${PERF_BASE_NAME}-perf.data +PERF_SCRIPT_OUTPUT=${PERF_BASE_NAME}-out.perf + +# Generate Flame graphs +echo "running perf script on $USER_AT_HOST with perf.data" +ssh $USER_AT_HOST "cd ~/performance_workspace/grpc && perf script -i $PERF_DATA_FILE | gzip > ${PERF_SCRIPT_OUTPUT}.gz" + +scp $USER_AT_HOST:~/performance_workspace/grpc/$PERF_SCRIPT_OUTPUT.gz . + +gzip -d -f $PERF_SCRIPT_OUTPUT.gz + +~/FlameGraph/stackcollapse-perf.pl --kernel $PERF_SCRIPT_OUTPUT | ~/FlameGraph/flamegraph.pl --color=java --hash > ${OUTPUT_DIR}/${OUTPUT_FILENAME}.svg diff --git a/tools/run_tests/report_utils.py b/tools/run_tests/report_utils.py index 90055e3530..5ce2a87cfa 100644 --- a/tools/run_tests/report_utils.py +++ b/tools/run_tests/report_utils.py @@ -122,3 +122,10 @@ def render_interop_html_report( except: print(exceptions.text_error_template().render()) raise + +def render_perf_profiling_results(output_filepath, profile_names): + with open(output_filepath, 'w') as output_file: + output_file.write('<ul>\n') + for name in profile_names: + output_file.write('<li><a href=%s>%s</a></li>\n' % (name, name)) + output_file.write('</ul>\n') diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py index 1d0c98fb69..69ccff85cf 100755 --- a/tools/run_tests/run_performance_tests.py +++ b/tools/run_tests/run_performance_tests.py @@ -49,6 +49,7 @@ import tempfile import time import traceback import uuid +import report_utils _ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..')) @@ -57,15 +58,18 @@ os.chdir(_ROOT) _REMOTE_HOST_USERNAME = 'jenkins' +_PERF_REPORT_OUTPUT_DIR = 'perf_reports' + class QpsWorkerJob: """Encapsulates a qps worker server job.""" - def __init__(self, spec, language, host_and_port): + def __init__(self, spec, language, host_and_port, perf_file_base_name=None): self._spec = spec self.language = language self.host_and_port = host_and_port self._job = None + self.perf_file_base_name = perf_file_base_name def start(self): self._job = jobset.Job(self._spec, newline_on_success=True, travis=True, add_env={}) @@ -80,24 +84,32 @@ class QpsWorkerJob: self._job = None -def create_qpsworker_job(language, shortname=None, - port=10000, remote_host=None): - cmdline = language.worker_cmdline() + ['--driver_port=%s' % port] +def create_qpsworker_job(language, shortname=None, port=10000, remote_host=None, perf_cmd=None): + cmdline = (language.worker_cmdline() + ['--driver_port=%s' % port]) + if remote_host: - user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host) - cmdline = ['ssh', - str(user_at_host), - 'cd ~/performance_workspace/grpc/ && %s' % ' '.join(cmdline)] host_and_port='%s:%s' % (remote_host, port) else: host_and_port='localhost:%s' % port + perf_file_base_name = None + if perf_cmd: + perf_file_base_name = '%s-%s' % (host_and_port, shortname) + # specify -o output file so perf.data gets collected when worker stopped + cmdline = perf_cmd + ['-o', '%s-perf.data' % perf_file_base_name] + cmdline + + if remote_host: + user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host) + ssh_cmd = ['ssh'] + ssh_cmd.extend([str(user_at_host), 'cd ~/performance_workspace/grpc/ && %s' % ' '.join(cmdline)]) + cmdline = ssh_cmd + jobspec = jobset.JobSpec( cmdline=cmdline, shortname=shortname, timeout_seconds=5*60, # workers get restarted after each scenario verbose_success=True) - return QpsWorkerJob(jobspec, language, host_and_port) + return QpsWorkerJob(jobspec, language, host_and_port, perf_file_base_name) def create_scenario_jobspec(scenario_json, workers, remote_host=None, @@ -259,7 +271,7 @@ def build_on_remote_hosts(hosts, languages=scenario_config.LANGUAGES.keys(), bui sys.exit(1) -def create_qpsworkers(languages, worker_hosts): +def create_qpsworkers(languages, worker_hosts, perf_cmd=None): """Creates QPS workers (but does not start them).""" if not worker_hosts: # run two workers locally (for each language) @@ -275,11 +287,32 @@ def create_qpsworkers(languages, worker_hosts): shortname= 'qps_worker_%s_%s' % (language, worker_idx), port=worker[1] + language.worker_port_offset(), - remote_host=worker[0]) + remote_host=worker[0], + perf_cmd=perf_cmd) for language in languages for worker_idx, worker in enumerate(workers)] +def perf_report_processor_job(worker_host, perf_base_name, output_filename): + print('Creating perf report collection job for %s' % worker_host) + cmd = '' + if worker_host != 'localhost': + user_at_host = "%s@%s" % (_REMOTE_HOST_USERNAME, worker_host) + cmd = "USER_AT_HOST=%s OUTPUT_FILENAME=%s OUTPUT_DIR=%s PERF_BASE_NAME=%s\ + tools/run_tests/performance/process_remote_perf_flamegraphs.sh" \ + % (user_at_host, output_filename, _PERF_REPORT_OUTPUT_DIR, perf_base_name) + else: + cmd = "OUTPUT_FILENAME=%s OUTPUT_DIR=%s PERF_BASE_NAME=%s\ + tools/run_tests/performance/process_local_perf_flamegraphs.sh" \ + % (output_filename, _PERF_REPORT_OUTPUT_DIR, perf_base_name) + + return jobset.JobSpec(cmdline=cmd, + timeout_seconds=3*60, + shell=True, + verbose_success=True, + shortname='process perf report') + + Scenario = collections.namedtuple('Scenario', 'jobspec workers name') @@ -372,6 +405,31 @@ def finish_qps_workers(jobs): print('All QPS workers finished.') return num_killed +profile_output_files = [] + +# Collect perf text reports and flamegraphs if perf_cmd was used +# Note the base names of perf text reports are used when creating and processing +# perf data. The scenario name uniqifies the output name in the final +# perf reports directory. +# Alos, the perf profiles need to be fetched and processed after each scenario +# in order to avoid clobbering the output files. +def run_collect_perf_profile_jobs(hosts_and_base_names, scenario_name): + perf_report_jobs = [] + global profile_output_files + for host_and_port in hosts_and_base_names: + perf_base_name = hosts_and_base_names[host_and_port] + output_filename = '%s-%s' % (scenario_name, perf_base_name) + # from the base filename, create .svg output filename + host = host_and_port.split(':')[0] + profile_output_files.append('%s.svg' % output_filename) + perf_report_jobs.append(perf_report_processor_job(host, perf_base_name, output_filename)) + + jobset.message('START', 'Collecting perf reports from qps workers', do_newline=True) + failures, _ = jobset.run(perf_report_jobs, newline_on_success=True, maxjobs=1) + jobset.message('END', 'Collecting perf reports from qps workers', do_newline=True) + return failures + + argp = argparse.ArgumentParser(description='Run performance tests.') argp.add_argument('-l', '--language', choices=['all'] + sorted(scenario_config.LANGUAGES.keys()), @@ -405,6 +463,33 @@ argp.add_argument('--netperf', help='Run netperf benchmark as one of the scenarios.') argp.add_argument('-x', '--xml_report', default='report.xml', type=str, help='Name of XML report file to generate.') +argp.add_argument('--perf_args', + help=('Example usage: "--perf_args=record -F 99 -g". ' + 'Wrap QPS workers in a perf command ' + 'with the arguments to perf specified here. ' + '".svg" flame graph profiles will be ' + 'created for each Qps Worker on each scenario. ' + 'Files will output to "<repo_root>/perf_reports" ' + 'directory. Output files from running the worker ' + 'under perf are saved in the repo root where its ran. ' + 'Note that the perf "-g" flag is necessary for ' + 'flame graphs generation to work (assuming the binary ' + 'being profiled uses frame pointers, check out ' + '"--call-graph dwarf" option using libunwind otherwise.) ' + 'Also note that the entire "--perf_args=<arg(s)>" must ' + 'be wrapped in quotes as in the example usage. ' + 'If the "--perg_args" is unspecified, "perf" will ' + 'not be used at all. ' + 'See http://www.brendangregg.com/perf.html ' + 'for more general perf examples.')) +argp.add_argument('--skip_generate_flamegraphs', + default=False, + action='store_const', + const=True, + help=('Turn flame graph generation off. ' + 'May be useful if "perf_args" arguments do not make sense for ' + 'generating flamegraphs (e.g., "--perf_args=stat ...")')) + args = argp.parse_args() @@ -435,7 +520,13 @@ if not args.remote_driver_host: if not args.dry_run: build_on_remote_hosts(remote_hosts, languages=[str(l) for l in languages], build_local=build_local) -qpsworker_jobs = create_qpsworkers(languages, args.remote_worker_host) +perf_cmd = None +if args.perf_args: + # Expect /usr/bin/perf to be installed here, as is usual + perf_cmd = ['/usr/bin/perf'] + perf_cmd.extend(re.split('\s+', args.perf_args)) + +qpsworker_jobs = create_qpsworkers(languages, args.remote_worker_host, perf_cmd=perf_cmd) # get list of worker addresses for each language. workers_by_lang = dict([(str(language), []) for language in languages]) @@ -457,16 +548,20 @@ if not scenarios: total_scenario_failures = 0 qps_workers_killed = 0 merged_resultset = {} +perf_report_failures = 0 + for scenario in scenarios: if args.dry_run: print(scenario.name) else: + scenario_failures = 0 try: for worker in scenario.workers: worker.start() - scenario_failures, resultset = jobset.run([scenario.jobspec, - create_quit_jobspec(scenario.workers, remote_host=args.remote_driver_host)], - newline_on_success=True, maxjobs=1) + jobs = [scenario.jobspec] + if scenario.workers: + jobs.append(create_quit_jobspec(scenario.workers, remote_host=args.remote_driver_host)) + scenario_failures, resultset = jobset.run(jobs, newline_on_success=True, maxjobs=1) total_scenario_failures += scenario_failures merged_resultset = dict(itertools.chain(merged_resultset.iteritems(), resultset.iteritems())) @@ -474,10 +569,27 @@ for scenario in scenarios: # Consider qps workers that need to be killed as failures qps_workers_killed += finish_qps_workers(scenario.workers) + if perf_cmd and scenario_failures == 0 and not args.skip_generate_flamegraphs: + workers_and_base_names = {} + for worker in scenario.workers: + if not worker.perf_file_base_name: + raise Exception('using perf buf perf report filename is unspecified') + workers_and_base_names[worker.host_and_port] = worker.perf_file_base_name + perf_report_failures += run_collect_perf_profile_jobs(workers_and_base_names, scenario.name) + -report_utils.render_junit_xml_report(merged_resultset, args.xml_report, - suite_name='benchmarks') +# Still write the index.html even if some scenarios failed. +# 'profile_output_files' will only have names for scenarios that passed +if perf_cmd and not args.skip_generate_flamegraphs: + # write the index fil to the output dir, with all profiles from all scenarios/workers + report_utils.render_perf_profiling_results('%s/index.html' % _PERF_REPORT_OUTPUT_DIR, profile_output_files) 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)) + print('%s scenarios failed and %s qps worker jobs killed' % (total_scenario_failures, qps_workers_killed)) + sys.exit(1) + +report_utils.render_junit_xml_report(merged_resultset, args.xml_report, + suite_name='benchmarks') +if perf_report_failures > 0: + print('%s perf profile collection jobs failed' % perf_report_failures) sys.exit(1) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index e503b82f0e..c49ee4a6cc 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -231,6 +231,9 @@ class CLanguage(object): 'GRPC_POLL_STRATEGY': polling_strategy, 'GRPC_VERBOSITY': 'DEBUG'} shortname_ext = '' if polling_strategy=='all' else ' GRPC_POLL_STRATEGY=%s' % polling_strategy + timeout_scaling = 1 + if polling_strategy == 'poll-cv': + timeout_scaling *= 5 if self.config.build_config in target['exclude_configs']: continue if self.args.iomgr_platform in target.get('exclude_iomgrs', []): @@ -269,6 +272,7 @@ class CLanguage(object): out.append(self.config.job_spec(cmdline, shortname='%s --gtest_filter=%s %s' % (binary, test, shortname_ext), cpu_cost=cpu_cost, + timeout_seconds=_DEFAULT_TIMEOUT_SECONDS * timeout_scaling, environ=env)) else: cmdline = [binary] + target['args'] @@ -279,7 +283,7 @@ class CLanguage(object): shortname_ext, cpu_cost=cpu_cost, flaky=target.get('flaky', False), - timeout_seconds=target.get('timeout_seconds', _DEFAULT_TIMEOUT_SECONDS), + timeout_seconds=target.get('timeout_seconds', _DEFAULT_TIMEOUT_SECONDS) * timeout_scaling, environ=env)) elif self.args.regex == '.*' or self.platform == 'windows': print('\nWARNING: binary not found, skipping', binary) @@ -507,7 +511,7 @@ class PythonLanguage(object): config.run, timeout_seconds=5*60, environ=dict(list(environment.items()) + - [('GRPC_PYTHON_TESTRUNNER_FILTER', suite_name)]), + [('GRPC_PYTHON_TESTRUNNER_FILTER', str(suite_name))]), shortname='%s.test.%s' % (config.name, suite_name),) for suite_name in tests_json for config in self.pythons] diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh index 6ec0786c96..be12f968d2 100755 --- a/tools/run_tests/sanity/check_submodules.sh +++ b/tools/run_tests/sanity/check_submodules.sh @@ -43,7 +43,7 @@ git submodule | awk '{ print $1 }' | sort > $submodules cat << EOF | awk '{ print $1 }' | sort > $want_submodules c880e42ba1c8032d4cdde2aba0541d8a9d9fa2e9 third_party/boringssl (version_for_cocoapods_2.0-100-gc880e42) 05b155ff59114735ec8cd089f669c4c3d8f59029 third_party/gflags (v2.1.0-45-g05b155f) - 44c25c892a6229b20db7cd9dc05584ea865896de third_party/google_benchmark (v0.1.0-343-g44c25c8) + 44c25c892a6229b20db7cd9dc05584ea865896de third_party/benchmark (v0.1.0-343-g44c25c8) c99458533a9b4c743ed51537e25989ea55944908 third_party/googletest (release-1.7.0) a428e42072765993ff674fda72863c9f1aa2d268 third_party/protobuf (v3.1.0) 50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8) diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index abdcfe501b..9dd5a1c85f 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -2263,7 +2263,7 @@ }, { "deps": [ - "google_benchmark", + "benchmark", "gpr", "gpr_test_util", "grpc", @@ -2913,7 +2913,7 @@ }, { "deps": [ - "google_benchmark" + "benchmark" ], "headers": [], "is_filegroup": false, @@ -6207,30 +6207,30 @@ { "deps": [], "headers": [ - "third_party/google_benchmark/include/benchmark/benchmark.h", - "third_party/google_benchmark/include/benchmark/benchmark_api.h", - "third_party/google_benchmark/include/benchmark/macros.h", - "third_party/google_benchmark/include/benchmark/reporter.h", - "third_party/google_benchmark/src/arraysize.h", - "third_party/google_benchmark/src/benchmark_api_internal.h", - "third_party/google_benchmark/src/check.h", - "third_party/google_benchmark/src/colorprint.h", - "third_party/google_benchmark/src/commandlineflags.h", - "third_party/google_benchmark/src/complexity.h", - "third_party/google_benchmark/src/cycleclock.h", - "third_party/google_benchmark/src/internal_macros.h", - "third_party/google_benchmark/src/log.h", - "third_party/google_benchmark/src/mutex.h", - "third_party/google_benchmark/src/re.h", - "third_party/google_benchmark/src/sleep.h", - "third_party/google_benchmark/src/stat.h", - "third_party/google_benchmark/src/string_util.h", - "third_party/google_benchmark/src/sysinfo.h", - "third_party/google_benchmark/src/timers.h" - ], - "is_filegroup": false, - "language": "c++", - "name": "google_benchmark", + "third_party/benchmark/include/benchmark/benchmark.h", + "third_party/benchmark/include/benchmark/benchmark_api.h", + "third_party/benchmark/include/benchmark/macros.h", + "third_party/benchmark/include/benchmark/reporter.h", + "third_party/benchmark/src/arraysize.h", + "third_party/benchmark/src/benchmark_api_internal.h", + "third_party/benchmark/src/check.h", + "third_party/benchmark/src/colorprint.h", + "third_party/benchmark/src/commandlineflags.h", + "third_party/benchmark/src/complexity.h", + "third_party/benchmark/src/cycleclock.h", + "third_party/benchmark/src/internal_macros.h", + "third_party/benchmark/src/log.h", + "third_party/benchmark/src/mutex.h", + "third_party/benchmark/src/re.h", + "third_party/benchmark/src/sleep.h", + "third_party/benchmark/src/stat.h", + "third_party/benchmark/src/string_util.h", + "third_party/benchmark/src/sysinfo.h", + "third_party/benchmark/src/timers.h" + ], + "is_filegroup": false, + "language": "c++", + "name": "benchmark", "src": [], "third_party": false, "type": "lib" @@ -6355,6 +6355,7 @@ "test/core/end2end/tests/request_with_payload.c", "test/core/end2end/tests/resource_quota_server.c", "test/core/end2end/tests/server_finishes_request.c", + "test/core/end2end/tests/short_deadlines.c", "test/core/end2end/tests/shutdown_finishes_calls.c", "test/core/end2end/tests/shutdown_finishes_tags.c", "test/core/end2end/tests/simple_cacheable_request.c", @@ -6424,6 +6425,7 @@ "test/core/end2end/tests/request_with_payload.c", "test/core/end2end/tests/resource_quota_server.c", "test/core/end2end/tests/server_finishes_request.c", + "test/core/end2end/tests/short_deadlines.c", "test/core/end2end/tests/shutdown_finishes_calls.c", "test/core/end2end/tests/shutdown_finishes_tags.c", "test/core/end2end/tests/simple_cacheable_request.c", @@ -6631,6 +6633,7 @@ "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -6647,6 +6650,7 @@ "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_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -7219,9 +7223,9 @@ "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", - "src/core/lib/security/transport/handshake.h", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/tsi_error.h", "src/core/lib/security/util/b64.h", "src/core/lib/security/util/json_util.h" @@ -7260,12 +7264,12 @@ "src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/client_auth_filter.c", - "src/core/lib/security/transport/handshake.c", - "src/core/lib/security/transport/handshake.h", "src/core/lib/security/transport/secure_endpoint.c", "src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/security_connector.c", "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/transport/security_handshaker.c", + "src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/server_auth_filter.c", "src/core/lib/security/transport/tsi_error.c", "src/core/lib/security/transport/tsi_error.h", @@ -7432,9 +7436,29 @@ "deps": [ "gpr", "grpc_base", - "grpc_client_channel", "grpc_transport_chttp2" ], + "headers": [ + "src/core/ext/transport/chttp2/client/chttp2_connector.h" + ], + "is_filegroup": true, + "language": "c", + "name": "grpc_transport_chttp2_client_connector", + "src": [ + "src/core/ext/transport/chttp2/client/chttp2_connector.c", + "src/core/ext/transport/chttp2/client/chttp2_connector.h" + ], + "third_party": false, + "type": "filegroup" + }, + { + "deps": [ + "gpr", + "grpc_base", + "grpc_client_channel", + "grpc_transport_chttp2", + "grpc_transport_chttp2_client_connector" + ], "headers": [], "is_filegroup": true, "language": "c", @@ -7452,7 +7476,8 @@ "grpc_base", "grpc_client_channel", "grpc_secure", - "grpc_transport_chttp2" + "grpc_transport_chttp2", + "grpc_transport_chttp2_client_connector" ], "headers": [], "is_filegroup": true, @@ -7470,6 +7495,26 @@ "grpc_base", "grpc_transport_chttp2" ], + "headers": [ + "src/core/ext/transport/chttp2/server/chttp2_server.h" + ], + "is_filegroup": true, + "language": "c", + "name": "grpc_transport_chttp2_server", + "src": [ + "src/core/ext/transport/chttp2/server/chttp2_server.c", + "src/core/ext/transport/chttp2/server/chttp2_server.h" + ], + "third_party": false, + "type": "filegroup" + }, + { + "deps": [ + "gpr", + "grpc_base", + "grpc_transport_chttp2", + "grpc_transport_chttp2_server" + ], "headers": [], "is_filegroup": true, "language": "c", @@ -7486,7 +7531,8 @@ "gpr", "grpc_base", "grpc_secure", - "grpc_transport_chttp2" + "grpc_transport_chttp2", + "grpc_transport_chttp2_server" ], "headers": [], "is_filegroup": true, diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index c4bfd0a9a7..8d1e9b4568 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -5898,6 +5898,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -6981,6 +7004,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -8025,6 +8071,28 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_fakesec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -9006,6 +9074,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -10066,6 +10157,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -10991,6 +11105,25 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_test", + "platforms": [ + "linux" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -11996,6 +12129,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -13116,6 +13272,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -14207,6 +14387,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -15327,6 +15530,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_oauth2_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -16287,6 +16514,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -17319,6 +17570,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -18255,6 +18530,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -19307,6 +19606,32 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -20388,6 +20713,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -21471,6 +21819,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_cert_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -22423,6 +22794,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_ssl_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -23489,6 +23884,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -24549,6 +24967,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -25609,6 +26050,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -26575,6 +27039,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -27612,6 +28099,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -28518,6 +29028,25 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_nosec_test", + "platforms": [ + "linux" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -29500,6 +30029,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -30596,6 +31148,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -31664,6 +32240,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -32592,6 +33191,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -33600,6 +34223,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -34512,6 +35159,30 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -35538,6 +36209,32 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -36571,6 +37268,29 @@ }, { "args": [ + "short_deadlines" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, + { + "args": [ "shutdown_finishes_calls" ], "ci_platforms": [ @@ -36765,7 +37485,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36788,7 +37509,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36811,7 +37533,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36834,7 +37557,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36857,7 +37581,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36880,7 +37605,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36903,7 +37629,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36926,7 +37653,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36949,7 +37677,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36972,7 +37701,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -36995,7 +37725,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37018,7 +37749,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37041,7 +37773,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37064,7 +37797,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37087,7 +37821,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37110,7 +37845,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37133,7 +37869,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37156,7 +37893,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37179,7 +37917,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37202,7 +37941,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37225,7 +37965,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37248,7 +37989,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37271,7 +38013,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37294,7 +38037,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37317,7 +38061,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37340,7 +38085,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37363,7 +38109,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37386,7 +38133,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37409,7 +38157,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37432,7 +38181,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37455,7 +38205,8 @@ "cpu_cost": 1024, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37478,7 +38229,8 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37501,7 +38253,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37524,7 +38277,8 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "tsan" + "tsan", + "asan" ], "flaky": false, "language": "c++", @@ -37547,7 +38301,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37570,7 +38323,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_secure", + "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37585,7 +38338,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37608,7 +38360,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_secure", + "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37623,7 +38375,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37646,7 +38397,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_secure", + "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37661,7 +38412,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37684,7 +38434,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure", + "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37699,7 +38449,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37722,7 +38471,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure", + "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37737,7 +38486,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37760,7 +38508,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_secure", + "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37775,7 +38523,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37798,7 +38545,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_secure", + "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37813,7 +38560,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37836,7 +38582,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_secure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_secure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { @@ -37851,7 +38597,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37874,7 +38619,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_secure", + "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37889,7 +38634,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37912,7 +38656,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_secure", + "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -37927,7 +38671,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37950,7 +38693,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_secure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_secure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { @@ -37965,7 +38708,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -37988,7 +38730,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_secure", + "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -38003,7 +38745,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38026,7 +38767,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_secure", + "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -38041,7 +38782,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38064,7 +38804,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_secure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_secure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { @@ -38079,7 +38819,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38102,7 +38841,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_secure", + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -38117,7 +38856,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38140,7 +38878,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_secure", + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_secure_low_thread_count", "timeout_seconds": 360 }, { @@ -38155,7 +38893,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38178,7 +38915,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_secure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_secure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { @@ -38193,7 +38930,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38216,7 +38952,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_insecure", + "shortname": "json_run_localhost:cpp_generic_async_streaming_ping_pong_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38231,7 +38967,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38254,7 +38989,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_insecure", + "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_unconstrained_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38269,7 +39004,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38292,7 +39026,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_insecure", + "shortname": "json_run_localhost:cpp_generic_async_streaming_qps_one_server_core_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38307,7 +39041,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38330,7 +39063,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure", + "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38345,7 +39078,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38368,7 +39100,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure", + "shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38383,7 +39115,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38406,7 +39137,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_insecure", + "shortname": "json_run_localhost:cpp_protobuf_sync_unary_ping_pong_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38421,7 +39152,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38444,7 +39174,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_insecure", + "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38459,7 +39189,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38482,7 +39211,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_insecure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_sync_unary_qps_unconstrained_insecure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { @@ -38497,7 +39226,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38520,7 +39248,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_insecure", + "shortname": "json_run_localhost:cpp_protobuf_async_unary_ping_pong_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38535,7 +39263,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38558,7 +39285,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_insecure", + "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38573,7 +39300,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38596,7 +39322,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_insecure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_async_unary_qps_unconstrained_insecure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { @@ -38611,7 +39337,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38634,7 +39359,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_insecure", + "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_ping_pong_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38649,7 +39374,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38672,7 +39396,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_insecure", + "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38687,7 +39411,6 @@ "cpu_cost": 64, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38710,7 +39433,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_insecure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_sync_streaming_qps_unconstrained_insecure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { @@ -38725,7 +39448,6 @@ "cpu_cost": 2, "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38748,7 +39470,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_insecure", + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_ping_pong_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38763,7 +39485,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38786,7 +39507,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_insecure", + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_insecure_low_thread_count", "timeout_seconds": 360 }, { @@ -38801,7 +39522,6 @@ "cpu_cost": "capacity", "defaults": "boringssl", "exclude_configs": [ - "asan", "asan-noleaks", "asan-trace-cmp", "basicprof", @@ -38824,7 +39544,7 @@ "platforms": [ "linux" ], - "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_insecure_500kib_resource_quota", + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_qps_unconstrained_insecure_500kib_resource_quota_low_thread_count", "timeout_seconds": 360 }, { diff --git a/vsprojects/vcxproj/google_benchmark/google_benchmark.vcxproj b/vsprojects/vcxproj/benchmark/benchmark.vcxproj index 52774e0802..9f262b3b00 100644 --- a/vsprojects/vcxproj/google_benchmark/google_benchmark.vcxproj +++ b/vsprojects/vcxproj/benchmark/benchmark.vcxproj @@ -19,7 +19,7 @@ </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> - <ProjectGuid>{AAD4AEF3-DF1E-7A6D-EC35-233BD1031BF4}</ProjectGuid> + <ProjectGuid>{07978586-E47C-8709-A63E-895FBF3C3C7D}</ProjectGuid> <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected> <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir> </PropertyGroup> @@ -57,10 +57,10 @@ </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)'=='Debug'"> - <TargetName>google_benchmark</TargetName> + <TargetName>benchmark</TargetName> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)'=='Release'"> - <TargetName>google_benchmark</TargetName> + <TargetName>benchmark</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> @@ -147,53 +147,53 @@ </ItemDefinitionGroup> <ItemGroup> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\benchmark.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\benchmark_api.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\macros.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\reporter.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\arraysize.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\benchmark_api_internal.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\check.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\colorprint.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\commandlineflags.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\complexity.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\cycleclock.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\internal_macros.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\log.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\mutex.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\re.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\sleep.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\stat.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\string_util.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\sysinfo.h" /> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\timers.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\benchmark.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\benchmark_api.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\macros.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\reporter.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\arraysize.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\benchmark_api_internal.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\check.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\colorprint.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\commandlineflags.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\complexity.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\cycleclock.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\internal_macros.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\log.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\mutex.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\re.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\sleep.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\stat.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\string_util.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\sysinfo.h" /> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\timers.h" /> </ItemGroup> <ItemGroup> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\benchmark.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\benchmark.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\benchmark_register.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\benchmark_register.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\colorprint.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\colorprint.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\commandlineflags.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\commandlineflags.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\complexity.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\complexity.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\console_reporter.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\console_reporter.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\csv_reporter.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\csv_reporter.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\json_reporter.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\json_reporter.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\reporter.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\reporter.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\sleep.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\sleep.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\string_util.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\string_util.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\sysinfo.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\sysinfo.cc"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\timers.cc"> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\timers.cc"> </ClCompile> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> diff --git a/vsprojects/vcxproj/benchmark/benchmark.vcxproj.filters b/vsprojects/vcxproj/benchmark/benchmark.vcxproj.filters new file mode 100644 index 0000000000..ccc9ca2cae --- /dev/null +++ b/vsprojects/vcxproj/benchmark/benchmark.vcxproj.filters @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\benchmark.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\benchmark_register.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\colorprint.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\commandlineflags.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\complexity.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\console_reporter.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\csv_reporter.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\json_reporter.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\reporter.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\sleep.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\string_util.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\sysinfo.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\third_party\benchmark\src\timers.cc"> + <Filter>third_party\benchmark\src</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\benchmark.h"> + <Filter>third_party\benchmark\include\benchmark</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\benchmark_api.h"> + <Filter>third_party\benchmark\include\benchmark</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\macros.h"> + <Filter>third_party\benchmark\include\benchmark</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\include\benchmark\reporter.h"> + <Filter>third_party\benchmark\include\benchmark</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\arraysize.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\benchmark_api_internal.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\check.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\colorprint.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\commandlineflags.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\complexity.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\cycleclock.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\internal_macros.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\log.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\mutex.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\re.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\sleep.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\stat.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\string_util.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\sysinfo.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\third_party\benchmark\src\timers.h"> + <Filter>third_party\benchmark\src</Filter> + </ClInclude> + </ItemGroup> + + <ItemGroup> + <Filter Include="third_party"> + <UniqueIdentifier>{7b593518-9fee-107e-6b64-24bdce73f939}</UniqueIdentifier> + </Filter> + <Filter Include="third_party\benchmark"> + <UniqueIdentifier>{f0d35de1-6b41-778d-0ba0-faad514fb0f4}</UniqueIdentifier> + </Filter> + <Filter Include="third_party\benchmark\include"> + <UniqueIdentifier>{cbc02dfa-face-8cc6-0efb-efacc0c3369c}</UniqueIdentifier> + </Filter> + <Filter Include="third_party\benchmark\include\benchmark"> + <UniqueIdentifier>{4f2f03fc-b82d-df33-63ee-bedebeb2c0ee}</UniqueIdentifier> + </Filter> + <Filter Include="third_party\benchmark\src"> + <UniqueIdentifier>{f42a8e0a-5a76-0e6f-d708-f0306858f673}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project> + diff --git a/vsprojects/vcxproj/google_benchmark/google_benchmark.vcxproj.filters b/vsprojects/vcxproj/google_benchmark/google_benchmark.vcxproj.filters deleted file mode 100644 index 9db6ed4657..0000000000 --- a/vsprojects/vcxproj/google_benchmark/google_benchmark.vcxproj.filters +++ /dev/null @@ -1,125 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\benchmark.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\benchmark_register.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\colorprint.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\commandlineflags.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\complexity.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\console_reporter.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\csv_reporter.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\json_reporter.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\reporter.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\sleep.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\string_util.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\sysinfo.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - <ClCompile Include="$(SolutionDir)\..\third_party\google_benchmark\src\timers.cc"> - <Filter>third_party\google_benchmark\src</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\benchmark.h"> - <Filter>third_party\google_benchmark\include\benchmark</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\benchmark_api.h"> - <Filter>third_party\google_benchmark\include\benchmark</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\macros.h"> - <Filter>third_party\google_benchmark\include\benchmark</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\include\benchmark\reporter.h"> - <Filter>third_party\google_benchmark\include\benchmark</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\arraysize.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\benchmark_api_internal.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\check.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\colorprint.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\commandlineflags.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\complexity.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\cycleclock.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\internal_macros.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\log.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\mutex.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\re.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\sleep.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\stat.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\string_util.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\sysinfo.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - <ClInclude Include="$(SolutionDir)\..\third_party\google_benchmark\src\timers.h"> - <Filter>third_party\google_benchmark\src</Filter> - </ClInclude> - </ItemGroup> - - <ItemGroup> - <Filter Include="third_party"> - <UniqueIdentifier>{7458b63d-7ba4-103d-2bed-3e3ad30d8237}</UniqueIdentifier> - </Filter> - <Filter Include="third_party\google_benchmark"> - <UniqueIdentifier>{54a154e8-669b-a7c1-9b6e-bd1aab2f86e3}</UniqueIdentifier> - </Filter> - <Filter Include="third_party\google_benchmark\include"> - <UniqueIdentifier>{f54c3cb1-ec20-a651-6956-78379b51e1a5}</UniqueIdentifier> - </Filter> - <Filter Include="third_party\google_benchmark\include\benchmark"> - <UniqueIdentifier>{0483a457-8050-4565-bc15-09695bf7b822}</UniqueIdentifier> - </Filter> - <Filter Include="third_party\google_benchmark\src"> - <UniqueIdentifier>{c39ff2d1-691e-4614-4d75-4bc20db05e09}</UniqueIdentifier> - </Filter> - </ItemGroup> -</Project> - diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index ce593473c0..c4f9c55308 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -177,6 +177,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index a50a9f4200..77a1ba64d6 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -225,6 +225,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index f281db72b6..14b3453b74 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -338,6 +338,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index f359e4ef31..5360819649 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -354,6 +354,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj index d2305b2e25..6a928e173f 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj @@ -185,6 +185,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters index d1aaba7092..bf8fab03bb 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters @@ -147,6 +147,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index 1511a2cfe4..39b01e6a4e 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -338,6 +338,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index bed77b25a4..9cafa1670a 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -339,6 +339,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 81b43f7a87..40f0f141b5 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -286,6 +286,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> @@ -428,9 +429,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\plugin\plugin_credentials.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\credentials\ssl\ssl_credentials.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\b64.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\util\json_util.h" /> @@ -439,6 +440,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\ssl_types.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security_interface.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.h" /> @@ -454,6 +456,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\load_balancer_api.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" /> @@ -780,12 +783,12 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\client_auth_filter.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\server_auth_filter.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.c"> @@ -802,6 +805,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\secure\secure_channel_create.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\channel_connectivity.c"> @@ -840,6 +845,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2_posix.c"> diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 2f4a659aaa..c0de28563e 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -457,15 +457,15 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\client_auth_filter.c"> <Filter>src\core\lib\security\transport</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.c"> - <Filter>src\core\lib\security\transport</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.c"> <Filter>src\core\lib\security\transport</Filter> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.c"> <Filter>src\core\lib\security\transport</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.c"> + <Filter>src\core\lib\security\transport</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\security\transport\server_auth_filter.c"> <Filter>src\core\lib\security\transport</Filter> </ClCompile> @@ -490,6 +490,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security.c"> <Filter>src\core\lib\tsi</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.c"> + <Filter>src\core\ext\transport\chttp2\server</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\secure\secure_channel_create.c"> <Filter>src\core\ext\transport\chttp2\client\secure</Filter> </ClCompile> @@ -547,6 +550,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.c"> <Filter>src\core\ext\client_channel</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.c"> + <Filter>src\core\ext\transport\chttp2\client</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c"> <Filter>src\core\ext\transport\chttp2\server\insecure</Filter> </ClCompile> @@ -699,6 +705,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> @@ -1121,15 +1130,15 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\auth_filters.h"> <Filter>src\core\lib\security\transport</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\handshake.h"> - <Filter>src\core\lib\security\transport</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\secure_endpoint.h"> <Filter>src\core\lib\security\transport</Filter> </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_connector.h"> <Filter>src\core\lib\security\transport</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\security_handshaker.h"> + <Filter>src\core\lib\security\transport</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\security\transport\tsi_error.h"> <Filter>src\core\lib\security\transport</Filter> </ClInclude> @@ -1154,6 +1163,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\tsi\transport_security_interface.h"> <Filter>src\core\lib\tsi</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h"> + <Filter>src\core\ext\transport\chttp2\server</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel.h"> <Filter>src\core\ext\client_channel</Filter> </ClInclude> @@ -1199,6 +1211,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h"> <Filter>src\core\ext\client_channel</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h"> + <Filter>src\core\ext\transport\chttp2\client</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\grpclb\grpclb.h"> <Filter>src\core\ext\lb_policy\grpclb</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 2acdd32cf3..01b73ce1a2 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -166,6 +166,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 6c918f1254..40ff67671f 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -456,6 +456,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index c96d48db58..49c2d2db30 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -277,6 +277,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> @@ -405,6 +406,8 @@ <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\stream_map.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\varint.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.h" /> @@ -718,10 +721,14 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\channel_connectivity.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel.c"> diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 4b75288b2b..5bca4fb9a5 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -415,12 +415,18 @@ <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.c"> <Filter>src\core\ext\transport\chttp2\alpn</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.c"> + <Filter>src\core\ext\transport\chttp2\server</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create.c"> <Filter>src\core\ext\transport\chttp2\client\insecure</Filter> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c"> <Filter>src\core\ext\transport\chttp2\client\insecure</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.c"> + <Filter>src\core\ext\transport\chttp2\client</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\channel_connectivity.c"> <Filter>src\core\ext\client_channel</Filter> </ClCompile> @@ -615,6 +621,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> @@ -995,6 +1004,12 @@ <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\alpn\alpn.h"> <Filter>src\core\ext\transport\chttp2\alpn</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\chttp2_server.h"> + <Filter>src\core\ext\transport\chttp2\server</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h"> + <Filter>src\core\ext\transport\chttp2\client</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\client_channel.h"> <Filter>src\core\ext\client_channel</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj b/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj index 1ce993e323..3809beb508 100644 --- a/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj +++ b/vsprojects/vcxproj/test/bm_fullstack/bm_fullstack.vcxproj @@ -164,8 +164,8 @@ </ClCompile> </ItemGroup> <ItemGroup> - <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\google_benchmark\google_benchmark.vcxproj"> - <Project>{AAD4AEF3-DF1E-7A6D-EC35-233BD1031BF4}</Project> + <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\benchmark\benchmark.vcxproj"> + <Project>{07978586-E47C-8709-A63E-895FBF3C3C7D}</Project> </ProjectReference> <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj"> <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project> diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj index a2b2a1dfa0..377d86fa5a 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj @@ -198,6 +198,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters index 94b6c2530e..e9ba002e9b 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters @@ -135,6 +135,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj index 1a3c157983..3254ad8d45 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj @@ -198,6 +198,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters index 1f4b60ca4d..6f32f65524 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters @@ -138,6 +138,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj index 4fb8f8f4a1..a79b44afee 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj @@ -231,6 +231,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\server_finishes_request.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\short_deadlines.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\shutdown_finishes_calls.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\shutdown_finishes_tags.c"> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters index ff82a4dd43..ac60d4c789 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters @@ -121,6 +121,9 @@ <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\server_finishes_request.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\short_deadlines.c"> + <Filter>test\core\end2end\tests</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\shutdown_finishes_calls.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj index 0b7d7c2e75..a218fa0310 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj @@ -233,6 +233,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\server_finishes_request.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\short_deadlines.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\shutdown_finishes_calls.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\shutdown_finishes_tags.c"> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters index e641930e64..978893fcd0 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters @@ -124,6 +124,9 @@ <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\server_finishes_request.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\short_deadlines.c"> + <Filter>test\core\end2end\tests</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\shutdown_finishes_calls.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile> diff --git a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj index 1e3cc3ca04..7fad922233 100644 --- a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj +++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj @@ -199,6 +199,7 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" /> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" /> diff --git a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters index 1c308c5881..19cb113341 100644 --- a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters +++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters @@ -129,6 +129,9 @@ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_slice.h"> + <Filter>include\grpc\impl\codegen</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\gpr_types.h"> <Filter>include\grpc\impl\codegen</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/test/noop-benchmark/noop-benchmark.vcxproj b/vsprojects/vcxproj/test/noop-benchmark/noop-benchmark.vcxproj index 99f33b2165..15a82c0ed6 100644 --- a/vsprojects/vcxproj/test/noop-benchmark/noop-benchmark.vcxproj +++ b/vsprojects/vcxproj/test/noop-benchmark/noop-benchmark.vcxproj @@ -164,8 +164,8 @@ </ClCompile> </ItemGroup> <ItemGroup> - <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\google_benchmark\google_benchmark.vcxproj"> - <Project>{AAD4AEF3-DF1E-7A6D-EC35-233BD1031BF4}</Project> + <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\benchmark\benchmark.vcxproj"> + <Project>{07978586-E47C-8709-A63E-895FBF3C3C7D}</Project> </ProjectReference> </ItemGroup> <ItemGroup> |